1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
//! A sandboxed runtime.

pub mod balance_api;
pub mod contract_api;
pub mod runtime_api;
pub mod system_api;
pub mod timestamp_api;

use std::any::Any;

use sp_externalities::Extension;
use sp_io::TestExternalities;

/// A sandboxed runtime.
pub struct Sandbox<R> {
    externalities: TestExternalities,
    _phantom: std::marker::PhantomData<R>,
}

impl<R> Sandbox<R> {
    /// Execute the given closure with the inner externallities.
    ///
    /// Returns the result of the given closure.
    pub fn execute_with<T>(&mut self, execute: impl FnOnce() -> T) -> T {
        self.externalities.execute_with(execute)
    }

    /// Run an action without modifying the storage.
    ///
    /// # Arguments
    ///
    /// * `action` - The action to run.
    pub fn dry_run<T>(&mut self, action: impl FnOnce(&mut Self) -> T) -> T {
        // Make a backup of the backend.
        let backend_backup = self.externalities.as_backend();

        // Run the action, potentially modifying storage. Ensure, that there are no pending changes
        // that would affect the reverted backend.
        let result = action(self);
        self.externalities
            .commit_all()
            .expect("Failed to commit changes");

        // Restore the backend.
        self.externalities.backend = backend_backup;

        result
    }

    /// Registers an extension.
    pub fn register_extension<E: Any + Extension>(&mut self, ext: E) {
        self.externalities.register_extension(ext);
    }
}