paritytech / ink
Showing 4 of 56 files from the diff.
Other files ignored by Codecov

@@ -76,139 +76,3 @@
Loading
76 76
        }
77 77
    };
78 78
}
79 -
80 -
/// A trait to enable running some fuzz tests on a collection.
81 -
pub trait FuzzCollection {
82 -
    type Collection;
83 -
    type Item;
84 -
85 -
    /// Executes a series of operations on `self` in order to make it
86 -
    /// equal to `template`.
87 -
    fn equalize(&mut self, template: &Self::Collection);
88 -
89 -
    /// Takes a value from `self` and puts it into `item`.
90 -
    fn assign(&mut self, item: Self::Item);
91 -
}
92 -
93 -
/// Creates two fuzz tests. Both tests have the same flow:
94 -
///     - Take two instances of the collection, generated by our fuzzer
95 -
///     - Push `instance2` to storage, pull it out and assert that what
96 -
///       is pulled out is what was pushed.
97 -
///     - Do some mutations on the `pulled` object. Here the two tests
98 -
///       behave differently:
99 -
///
100 -
///         * `fuzz_ $id _mutate_some` Mutates some entries of the data
101 -
///           structure based on the content of `instance2`.
102 -
///
103 -
///         * `fuzz_ $id _mutate_all` Mutates the entire data structure,
104 -
///           so that it has the same content as `instance2`.
105 -
///
106 -
///     - Push the mutated `pulled` object into storage again, pull it
107 -
///       out as `pulled2` and assert that both objects are equal.
108 -
///     - Clear the object from storage and assert that storage was
109 -
///       cleared up properly, without any leftovers.
110 -
#[macro_export]
111 -
macro_rules! fuzz_storage {
112 -
    ($id:literal, $collection_type:ty) => {
113 -
        ::paste::paste! {
114 -
            /// Does some basic storage interaction tests whilst mutating
115 -
            /// *some* of the data structure's entries.
116 -
            #[allow(trivial_casts)]
117 -
            #[quickcheck]
118 -
            fn [< fuzz_ $id _mutate_some >] (
119 -
                instance1: $collection_type,
120 -
                mut instance2: $collection_type,
121 -
            ) {
122 -
                ink_env::test::run_test::<ink_env::DefaultEnvironment, _>(|_| {
123 -
                    // we push the generated object into storage
124 -
                    let root_key = ink_primitives::Key::from([0x42; 32]);
125 -
                    let ptr = KeyPtr::from(root_key);
126 -
                    $crate::traits::push_spread_root(&instance1, &root_key.clone());
127 -
128 -
                    // we pull what's in storage and assert that this is what was just pushed
129 -
                    let mut pulled: $collection_type = $crate::traits::pull_spread_root(&root_key.clone());
130 -
                    assert_eq!(instance1, pulled);
131 -
132 -
                    // we iterate over what was pulled and call `assign` for all entries.
133 -
                    // this function may or may not modify elements of `pulled`.
134 -
                    pulled.iter_mut().for_each(|item| {
135 -
                        // this may leave some entries of `pulled` in `State::Preserved`.
136 -
                        // even though the instance which is supposed to be mutated is
137 -
                        // `pulled`, we still need to call this on a mutable `instance2`,
138 -
                        // since e.g. Vec does a `pop()` in assign, so that we don't always
139 -
                        // execute the same operation.
140 -
                        (&mut instance2).assign(item);
141 -
                    });
142 -
143 -
                    // we push the `pulled` object, on which we just executed mutations
144 -
                    // back into storage and asserts it can be pulled out intact again.
145 -
                    $crate::traits::push_spread_root(&pulled, &root_key.clone());
146 -
                    let pulled2: $collection_type = $crate::traits::pull_spread_root(&root_key.clone());
147 -
                    assert_eq!(pulled, pulled2);
148 -
149 -
                    // we clear the objects from storage and assert that everything was
150 -
                    // removed without any leftovers.
151 -
                    SpreadLayout::clear_spread(&pulled2, &mut ptr.clone());
152 -
                    SpreadLayout::clear_spread(&pulled, &mut ptr.clone());
153 -
                    $crate::test_utils::assert_storage_clean();
154 -
155 -
                    Ok(())
156 -
                })
157 -
                    .unwrap()
158 -
            }
159 -
160 -
            /// Does some basic storage interaction tests whilst mutating
161 -
            /// *all* the data structure's entries.
162 -
            #[allow(trivial_casts)]
163 -
            #[quickcheck]
164 -
            fn [< fuzz_ $id _mutate_all >] (
165 -
                instance1: $collection_type,
166 -
                instance2: $collection_type,
167 -
            ) {
168 -
                ink_env::test::run_test::<ink_env::DefaultEnvironment, _>(|_| {
169 -
                    // we push the generated object into storage
170 -
                    let root_key = ink_primitives::Key::from([0x42; 32]);
171 -
                    let ptr = KeyPtr::from(root_key);
172 -
                    $crate::traits::push_spread_root(&instance1, &root_key.clone());
173 -
174 -
                    // we pull what's in storage and assert that this is what was just pushed
175 -
                    let mut pulled: $collection_type = $crate::traits::pull_spread_root(&root_key.clone());
176 -
                    assert_eq!(instance1, pulled);
177 -
178 -
                    // `pulled` is going to be equalized to `
179 -
                    (&mut pulled).equalize(&instance2);
180 -
181 -
                    // we push the `pulled` object, on which we just executed mutations
182 -
                    // back into storage and assert it can be pulled out intact again and
183 -
                    // is equal to `instance2`.
184 -
                    $crate::traits::push_spread_root(&pulled, &root_key.clone());
185 -
                    let pulled2: $collection_type = $crate::traits::pull_spread_root(&root_key.clone());
186 -
                    assert_eq!(pulled, pulled2);
187 -
                    assert_eq!(pulled2, instance2);
188 -
189 -
                    // we clear the objects from storage and assert that everything was
190 -
                    // removed without any leftovers.
191 -
                    SpreadLayout::clear_spread(&pulled2, &mut ptr.clone());
192 -
                    SpreadLayout::clear_spread(&pulled, &mut ptr.clone());
193 -
                    $crate::test_utils::assert_storage_clean();
194 -
195 -
                    Ok(())
196 -
197 -
                })
198 -
                    .unwrap()
199 -
            }
200 -
        }
201 -
    };
202 -
}
203 -
204 -
/// Asserts that the storage is empty, without any leftovers.
205 -
#[cfg(all(test, feature = "ink-fuzz-tests"))]
206 -
pub fn assert_storage_clean() {
207 -
    let contract_id = ink_env::test::callee::<ink_env::DefaultEnvironment>();
208 -
    let used_cells =
209 -
        ink_env::test::count_used_storage_cells::<ink_env::DefaultEnvironment>(
210 -
            &contract_id,
211 -
        )
212 -
        .expect("used cells must be returned");
213 -
    assert_eq!(used_cells, 0);
214 -
}

@@ -37,13 +37,7 @@
Loading
37 37
    LayoutCryptoHasher,
38 38
    StorageLayout,
39 39
};
40 -
pub(crate) use self::optspec::{
41 -
    clear_spread_root_opt,
42 -
    pull_packed_root_opt,
43 -
    pull_spread_root_opt,
44 -
    push_packed_root_opt,
45 -
    push_spread_root_opt,
46 -
};
40 +
pub(crate) use self::optspec::pull_packed_root_opt;
47 41
pub use self::{
48 42
    impls::{
49 43
        forward_allocate_packed,

@@ -18,86 +18,9 @@
Loading
18 18
//! The specializations make use of the storage entry state (occupied or vacant)
19 19
//! in order to store the option's state thus using less storage in total.
20 20
21 -
use super::{
22 -
    KeyPtr,
23 -
    PackedLayout,
24 -
    SpreadLayout,
25 -
};
21 +
use super::PackedLayout;
26 22
use ink_primitives::Key;
27 23
28 -
pub fn pull_spread_root_opt<T>(root_key: &Key) -> Option<T>
29 -
where
30 -
    T: SpreadLayout,
31 -
{
32 -
    // In case the contract storage is occupied we handle
33 -
    // the Option<T> as if it was a T.
34 -
    ink_env::get_contract_storage::<()>(root_key)
35 -
        .ok()
36 -
        .flatten()
37 -
        .map(|_| super::pull_spread_root::<T>(root_key))
38 -
}
39 -
40 -
pub fn push_spread_root_opt<T>(entity: Option<&T>, root_key: &Key)
41 -
where
42 -
    T: SpreadLayout,
43 -
{
44 -
    match entity {
45 -
        Some(value) => {
46 -
            // Handle the Option<T> as if it was a T.
47 -
            //
48 -
            // Sadly this does not not work well with `Option<Option<T>>`.
49 -
            // For this we'd need specialization in Rust or similar.
50 -
            super::push_spread_root(value, root_key)
51 -
        }
52 -
        None => clear_spread_root_opt::<T, _>(root_key, || entity),
53 -
    }
54 -
}
55 -
56 -
pub fn clear_spread_root_opt<'a, T: 'a, F>(root_key: &Key, f: F)
57 -
where
58 -
    T: SpreadLayout,
59 -
    F: FnOnce() -> Option<&'a T>,
60 -
{
61 -
    // We can clean up some storage entity using its `SpreadLayout::clear_spread`
62 -
    // implementation or its defined storage footprint.
63 -
    //
64 -
    // While using its `SpreadLayout::clear_spread` implementation is more precise
65 -
    // and will only clean-up what is necessary it requires an actual instance.
66 -
    // Loading such an instance if it is not already in the memory cache of some
67 -
    // lazy abstraction will incur significant overhead.
68 -
    // Using its defined storage footprint this procedure can eagerly clean-up
69 -
    // the associated contract storage region, however, this might clean-up more
70 -
    // cells than needed.
71 -
    //
72 -
    // There are types that need a so-called "deep" clean-up. An example for this
73 -
    // is `storage::Box<storage::Box<T>>` where the outer storage box definitely
74 -
    // needs to propagate clearing signals onto its inner `storage::Box` in order
75 -
    // to properly clean-up the whole associate contract storage region.
76 -
    // This is when we cannot avoid loading the entity for the clean-up procedure.
77 -
    //
78 -
    // If the entity that shall be cleaned-up does not require deep clean-up we
79 -
    // check if its storage footprint exceeds a certain threshold and only then
80 -
    // we will still load it first in order to not clean-up too many unneeded
81 -
    // storage cells.
82 -
    let footprint = <T as SpreadLayout>::FOOTPRINT;
83 -
    if footprint >= super::FOOTPRINT_CLEANUP_THRESHOLD
84 -
        || <T as SpreadLayout>::REQUIRES_DEEP_CLEAN_UP
85 -
    {
86 -
        // We need to load the entity before we remove its associated contract storage
87 -
        // because it requires a deep clean-up which propagates clearing to its fields,
88 -
        // for example in the case of `T` being a `storage::Box`.
89 -
        if let Some(value) = f() {
90 -
            super::clear_spread_root(value, root_key);
91 -
            return
92 -
        }
93 -
    }
94 -
    // Clean-up eagerly without potentially loading the entity from storage:
95 -
    let mut ptr = KeyPtr::from(*root_key);
96 -
    for _ in 0..footprint {
97 -
        ink_env::clear_contract_storage(ptr.advance_by(1));
98 -
    }
99 -
}
100 -
101 24
pub fn pull_packed_root_opt<T>(root_key: &Key) -> Option<T>
102 25
where
103 26
    T: PackedLayout,
@@ -116,22 +39,3 @@
Loading
116 39
            value
117 40
        })
118 41
}
119 -
120 -
pub fn push_packed_root_opt<T>(entity: Option<&T>, root_key: &Key)
121 -
where
122 -
    T: PackedLayout,
123 -
{
124 -
    match entity {
125 -
        Some(value) => {
126 -
            // Handle the Option<T> as if it was a T.
127 -
            //
128 -
            // Sadly this does not work well with `Option<Option<T>>`.
129 -
            // For this we'd need specialization in Rust or similar.
130 -
            super::push_packed_root(value, root_key);
131 -
        }
132 -
        None => {
133 -
            // Clear the associated storage cell since the entity is `None`.
134 -
            ink_env::clear_contract_storage(root_key);
135 -
        }
136 -
    }
137 -
}

@@ -298,7 +298,7 @@
Loading
298 298
    fn can_clear_entries() {
299 299
        ink_env::test::run_test::<ink_env::DefaultEnvironment, _>(|_| {
300 300
            // We use `Pack` here since it `REQUIRES_DEEP_CLEAN_UP`
301 -
            use crate::Pack;
301 +
            use crate::pack::Pack;
302 302
303 303
            // Given
304 304
            let mut mapping: Mapping<u8, u8> = Mapping::new([0u8; 32].into());
@@ -327,7 +327,7 @@
Loading
327 327
    fn can_clear_unexistent_entries() {
328 328
        ink_env::test::run_test::<ink_env::DefaultEnvironment, _>(|_| {
329 329
            // We use `Pack` here since it `REQUIRES_DEEP_CLEAN_UP`
330 -
            use crate::Pack;
330 +
            use crate::pack::Pack;
331 331
332 332
            // Given
333 333
            let mapping: Mapping<u8, u8> = Mapping::new([0u8; 32].into());
Files Coverage
crates 47.94%
Project Totals (176 files) 47.94%
Sunburst
The inner-most circle is the entire project, moving away from the center are folders then, finally, a single file. The size and color of each slice is representing the number of statements and the coverage, respectively.
Icicle
The top section represents the entire project. Proceeding with folders and finally individual files. The size and color of each slice is representing the number of statements and the coverage, respectively.
Grid
Each block represents a single file in the project. The size and color of each block is represented by the number of statements and the coverage, respectively.
Loading