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
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
#![cfg_attr(not(feature = "std"), no_std)]
use frame_support::storage::{with_transaction, TransactionOutcome};
use sp_runtime::DispatchError;
use sp_std::result::Result;
#[deprecated(
since = "0.4.1",
note = "iterator module's functionality is now available in substrate's frame-support"
)]
pub mod iterator;
pub mod offchain_worker;
pub mod ordered_set;
#[allow(deprecated)]
pub use iterator::{IterableStorageDoubleMapExtended, IterableStorageMapExtended};
pub use offchain_worker::OffchainErr;
pub use ordered_set::OrderedSet;
pub fn with_transaction_result<R>(f: impl FnOnce() -> Result<R, DispatchError>) -> Result<R, DispatchError> {
with_transaction(|| {
let res = f();
if res.is_ok() {
TransactionOutcome::Commit(res)
} else {
TransactionOutcome::Rollback(res)
}
})
}
#[cfg(test)]
mod tests {
use super::*;
use frame_support::{assert_noop, assert_ok, decl_module, decl_storage};
use sp_io::TestExternalities;
use sp_runtime::{DispatchError, DispatchResult};
pub trait Config: frame_system::Config {}
decl_module! {
pub struct Module<T: Config> for enum Call where origin: T::Origin {}
}
decl_storage! {
trait Store for Module<T: Config> as StorageTransactions {
pub Value: u32;
pub Map: map hasher(twox_64_concat) String => u32;
}
}
#[test]
fn storage_transaction_basic_commit() {
TestExternalities::default().execute_with(|| {
assert_eq!(Value::get(), 0);
assert!(!Map::contains_key("val0"));
assert_ok!(with_transaction_result(|| -> DispatchResult {
Value::set(99);
Map::insert("val0", 99);
assert_eq!(Value::get(), 99);
assert_eq!(Map::get("val0"), 99);
Ok(())
}));
assert_eq!(Value::get(), 99);
assert_eq!(Map::get("val0"), 99);
});
}
#[test]
fn storage_transaction_basic_rollback() {
TestExternalities::default().execute_with(|| {
assert_eq!(Value::get(), 0);
assert_eq!(Map::get("val0"), 0);
assert_noop!(
with_transaction_result(|| -> DispatchResult {
Value::set(99);
Map::insert("val0", 99);
assert_eq!(Value::get(), 99);
assert_eq!(Map::get("val0"), 99);
Err("test".into())
}),
DispatchError::Other("test")
);
assert_eq!(Value::get(), 0);
assert_eq!(Map::get("val0"), 0);
});
}
}