frame_support/storage/
storage_noop_guard.rs1#![cfg(any(feature = "std", feature = "runtime-benchmarks", feature = "try-runtime", test))]
20
21#[must_use]
40pub struct StorageNoopGuard<'a> {
41 storage_root: alloc::vec::Vec<u8>,
42 error_message: &'a str,
43}
44
45impl<'a> Default for StorageNoopGuard<'a> {
46 fn default() -> Self {
47 Self {
48 storage_root: sp_io::storage::root(sp_runtime::StateVersion::V1),
49 error_message: "`StorageNoopGuard` detected an attempted storage change.",
50 }
51 }
52}
53
54impl<'a> StorageNoopGuard<'a> {
55 pub fn new() -> Self {
57 Self::default()
58 }
59
60 pub fn from_error_message(error_message: &'a str) -> Self {
62 Self { storage_root: sp_io::storage::root(sp_runtime::StateVersion::V1), error_message }
63 }
64
65 pub fn set_error_message(&mut self, error_message: &'a str) {
67 self.error_message = error_message;
68 }
69}
70
71impl<'a> Drop for StorageNoopGuard<'a> {
72 fn drop(&mut self) {
73 #[cfg(feature = "std")]
75 if std::thread::panicking() {
76 return
77 }
78 assert_eq!(
79 sp_io::storage::root(sp_runtime::StateVersion::V1),
80 self.storage_root,
81 "{}",
82 self.error_message,
83 );
84 }
85}
86
87#[cfg(test)]
88mod tests {
89 use sp_io::TestExternalities;
90
91 use super::*;
92
93 #[test]
94 #[should_panic(expected = "`StorageNoopGuard` detected an attempted storage change.")]
95 fn storage_noop_guard_panics_on_changed() {
96 TestExternalities::default().execute_with(|| {
97 let _guard = StorageNoopGuard::default();
98 frame_support::storage::unhashed::put(b"key", b"value");
99 });
100 }
101
102 #[test]
103 fn storage_noop_guard_works_on_unchanged() {
104 TestExternalities::default().execute_with(|| {
105 let _guard = StorageNoopGuard::default();
106 frame_support::storage::unhashed::put(b"key", b"value");
107 frame_support::storage::unhashed::kill(b"key");
108 });
109 }
110
111 #[test]
112 #[should_panic(expected = "`StorageNoopGuard` detected an attempted storage change.")]
113 fn storage_noop_guard_panics_on_early_drop() {
114 TestExternalities::default().execute_with(|| {
115 let guard = StorageNoopGuard::default();
116 frame_support::storage::unhashed::put(b"key", b"value");
117 std::mem::drop(guard);
118 frame_support::storage::unhashed::kill(b"key");
119 });
120 }
121
122 #[test]
123 fn storage_noop_guard_works_on_changed_forget() {
124 TestExternalities::default().execute_with(|| {
125 let guard = StorageNoopGuard::default();
126 frame_support::storage::unhashed::put(b"key", b"value");
127 std::mem::forget(guard);
128 });
129 }
130
131 #[test]
132 #[should_panic(expected = "Something else")]
133 fn storage_noop_guard_does_not_double_panic() {
134 TestExternalities::default().execute_with(|| {
135 let _guard = StorageNoopGuard::default();
136 frame_support::storage::unhashed::put(b"key", b"value");
137 panic!("Something else");
138 });
139 }
140
141 #[test]
142 #[should_panic(expected = "`StorageNoopGuard` found unexpected storage changes.")]
143 fn storage_noop_guard_panics_created_from_error_message() {
144 TestExternalities::default().execute_with(|| {
145 let _guard = StorageNoopGuard::from_error_message(
146 "`StorageNoopGuard` found unexpected storage changes.",
147 );
148 frame_support::storage::unhashed::put(b"key", b"value");
149 });
150 }
151
152 #[test]
153 #[should_panic(expected = "`StorageNoopGuard` found unexpected storage changes.")]
154 fn storage_noop_guard_panics_with_set_error_message() {
155 TestExternalities::default().execute_with(|| {
156 let mut guard = StorageNoopGuard::default();
157 guard.set_error_message("`StorageNoopGuard` found unexpected storage changes.");
158 frame_support::storage::unhashed::put(b"key", b"value");
159 });
160 }
161
162 #[test]
163 #[should_panic(expected = "`StorageNoopGuard` detected an attempted storage change.")]
164 fn storage_noop_guard_panics_new_alias() {
165 TestExternalities::default().execute_with(|| {
166 let _guard = StorageNoopGuard::new();
167 frame_support::storage::unhashed::put(b"key", b"value");
168 });
169 }
170}