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
55
56
57
58
59
60
61
62
63
64
65
//! Basic chain API.

use frame_support::sp_runtime::{
    traits::{One, Saturating},
    BuildStorage,
};
use frame_system::{pallet_prelude::BlockNumberFor, GenesisConfig};
use sp_io::TestExternalities;

use super::Sandbox;
use crate::{DrinkResult, Error, Runtime};

impl<R: Runtime> Sandbox<R> {
    /// Creates a new sandbox.
    ///
    /// Returns an error if the storage could not be initialized.
    ///
    /// The storage is initialized with a genesis block with a single account `R::default_actor()` with
    /// `INITIAL_BALANCE`.
    pub fn new() -> DrinkResult<Self> {
        let mut storage = GenesisConfig::<R::Config>::default()
            .build_storage()
            .map_err(Error::StorageBuilding)?;

        R::initialize_storage(&mut storage).map_err(Error::StorageBuilding)?;

        let mut sandbox = Self {
            externalities: TestExternalities::new(storage),
            _phantom: Default::default(),
        };

        sandbox
            .externalities
            // We start the chain from the 1st block, so that events are collected (they are not
            // recorded for the genesis block...).
            .execute_with(|| {
                R::initialize_block(BlockNumberFor::<R::Config>::one(), Default::default())
            })
            .map_err(Error::BlockInitialize)?;

        Ok(sandbox)
    }
    /// Build a new empty block and return the new height.
    pub fn build_block(&mut self) -> DrinkResult<BlockNumberFor<R::Config>> {
        self.execute_with(|| {
            let mut current_block = frame_system::Pallet::<R::Config>::block_number();
            let block_hash = R::finalize_block(current_block).map_err(Error::BlockFinalize)?;
            current_block.saturating_inc();
            R::initialize_block(current_block, block_hash).map_err(Error::BlockInitialize)?;
            Ok(current_block)
        })
    }
    /// Build `n` empty blocks and return the new height.
    ///
    /// # Arguments
    ///
    /// * `n` - The number of blocks to build.
    pub fn build_blocks(&mut self, n: u32) -> DrinkResult<BlockNumberFor<R::Config>> {
        let mut last_block = None;
        for _ in 0..n {
            last_block = Some(self.build_block()?);
        }
        Ok(last_block.unwrap_or_else(|| self.block_number()))
    }
}