fuel_chain_config/
config.rs1mod chain;
2mod coin;
3mod contract;
4mod message;
5mod state;
6
7pub use chain::*;
8pub use coin::*;
9pub use contract::*;
10pub use message::*;
11pub use state::*;
12
13#[cfg(test)]
14mod tests {
15 use fuel_core_interfaces::{
16 common::{
17 fuel_asm::Opcode,
18 fuel_vm::prelude::Contract,
19 prelude::{
20 AssetId,
21 Bytes32,
22 },
23 },
24 model::DaBlockHeight,
25 };
26 use rand::{
27 prelude::StdRng,
28 Rng,
29 RngCore,
30 SeedableRng,
31 };
32 use std::{
33 env::temp_dir,
34 fs::write,
35 path::PathBuf,
36 };
37
38 use super::{
39 chain::ChainConfig,
40 coin::CoinConfig,
41 contract::ContractConfig,
42 message::MessageConfig,
43 state::StateConfig,
44 };
45
46 #[test]
47 fn from_str_loads_from_file() {
48 let tmp_file = tmp_path();
50 let disk_config = ChainConfig::local_testnet();
51 let json = serde_json::to_string_pretty(&disk_config).unwrap();
52 write(tmp_file.clone(), json).unwrap();
53
54 let load_config: ChainConfig =
56 tmp_file.to_string_lossy().into_owned().parse().unwrap();
57 assert_eq!(disk_config, load_config);
58 }
59
60 #[test]
61 fn snapshot_local_testnet_config() {
62 let config = ChainConfig::local_testnet();
63 let json = serde_json::to_string_pretty(&config).unwrap();
64 insta::assert_snapshot!(json);
65 }
66
67 #[test]
68 fn can_roundtrip_serialize_local_testnet_config() {
69 let config = ChainConfig::local_testnet();
70 let json = serde_json::to_string(&config).unwrap();
71 let deserialized_config: ChainConfig =
72 serde_json::from_str(json.as_str()).unwrap();
73 assert_eq!(config, deserialized_config);
74 }
75
76 #[test]
77 fn snapshot_configurable_block_height() {
78 let mut rng = StdRng::seed_from_u64(2);
79 let config = ChainConfig {
80 initial_state: Some(StateConfig {
81 height: Some(rng.next_u32().into()),
82 ..Default::default()
83 }),
84 ..ChainConfig::local_testnet()
85 };
86 let json = serde_json::to_string_pretty(&config).unwrap();
87 insta::assert_snapshot!(json);
88 }
89
90 #[test]
91 fn can_roundtrip_serialize_block_height_config() {
92 let mut rng = StdRng::seed_from_u64(2);
93 let config = ChainConfig {
94 initial_state: Some(StateConfig {
95 height: Some(rng.next_u32().into()),
96 ..Default::default()
97 }),
98 ..ChainConfig::local_testnet()
99 };
100 let json = serde_json::to_string(&config).unwrap();
101 let deserialized_config: ChainConfig =
102 serde_json::from_str(json.as_str()).unwrap();
103 assert_eq!(config, deserialized_config);
104 }
105
106 #[test]
107 fn snapshot_simple_contract() {
108 let config = test_config_contract(false, false);
109 let json = serde_json::to_string_pretty(&config).unwrap();
110 insta::assert_snapshot!(json);
111 }
112
113 #[test]
114 fn can_roundtrip_simple_contract() {
115 let config = test_config_contract(false, false);
116 let json = serde_json::to_string(&config).unwrap();
117 let deserialized_config: ChainConfig =
118 serde_json::from_str(json.as_str()).unwrap();
119 assert_eq!(config, deserialized_config);
120 }
121
122 #[test]
123 fn snapshot_contract_with_state() {
124 let config = test_config_contract(true, false);
125 let json = serde_json::to_string_pretty(&config).unwrap();
126 insta::assert_snapshot!(json);
127 }
128
129 #[test]
130 fn can_roundtrip_contract_with_state() {
131 let config = test_config_contract(true, false);
132 let json = serde_json::to_string(&config).unwrap();
133 let deserialized_config: ChainConfig =
134 serde_json::from_str(json.as_str()).unwrap();
135 assert_eq!(config, deserialized_config);
136 }
137
138 #[test]
139 fn snapshot_contract_with_balances() {
140 let config = test_config_contract(false, true);
141 let json = serde_json::to_string_pretty(&config).unwrap();
142 insta::assert_snapshot!(json);
143 }
144
145 #[test]
146 fn can_roundtrip_contract_with_balances() {
147 let config = test_config_contract(false, true);
148 let json = serde_json::to_string(&config).unwrap();
149 let deserialized_config: ChainConfig =
150 serde_json::from_str(json.as_str()).unwrap();
151 assert_eq!(config, deserialized_config);
152 }
153
154 #[test]
155 fn snapshot_simple_coin_state() {
156 let config = test_config_coin_state();
157 let json = serde_json::to_string_pretty(&config).unwrap();
158 insta::assert_snapshot!(json);
159 }
160
161 #[test]
162 fn can_roundtrip_simple_coin_state() {
163 let config = test_config_coin_state();
164 let json = serde_json::to_string(&config).unwrap();
165 let deserialized_config: ChainConfig =
166 serde_json::from_str(json.as_str()).unwrap();
167 assert_eq!(config, deserialized_config);
168 }
169
170 #[test]
171 fn snapshot_simple_message_state() {
172 let config = test_message_config();
173 let json = serde_json::to_string_pretty(&config).unwrap();
174 insta::assert_snapshot!(json);
175 }
176
177 #[test]
178 fn can_roundtrip_simple_message_state() {
179 let config = test_message_config();
180 let json = serde_json::to_string(&config).unwrap();
181 let deserialized_config: ChainConfig =
182 serde_json::from_str(json.as_str()).unwrap();
183 assert_eq!(config, deserialized_config);
184 }
185
186 fn test_config_contract(state: bool, balances: bool) -> ChainConfig {
187 let mut rng = StdRng::seed_from_u64(1);
188 let state = if state {
189 let test_key: Bytes32 = rng.gen();
190 let test_value: Bytes32 = rng.gen();
191 Some(vec![(test_key, test_value)])
192 } else {
193 None
194 };
195 let balances = if balances {
196 let test_asset_id: AssetId = rng.gen();
197 let test_balance: u64 = rng.next_u64();
198 Some(vec![(test_asset_id, test_balance)])
199 } else {
200 None
201 };
202
203 let contract = Contract::from(Opcode::RET(0x10).to_bytes().to_vec());
204
205 ChainConfig {
206 initial_state: Some(StateConfig {
207 contracts: Some(vec![ContractConfig {
208 code: contract.into(),
209 salt: Default::default(),
210 state,
211 balances,
212 }]),
213 ..Default::default()
214 }),
215 ..ChainConfig::local_testnet()
216 }
217 }
218
219 fn test_config_coin_state() -> ChainConfig {
220 let mut rng = StdRng::seed_from_u64(1);
221 let tx_id: Option<Bytes32> = Some(rng.gen());
222 let output_index: Option<u64> = Some(rng.gen());
223 let block_created = Some(rng.next_u32().into());
224 let maturity = Some(rng.next_u32().into());
225 let owner = rng.gen();
226 let amount = rng.gen();
227 let asset_id = rng.gen();
228
229 ChainConfig {
230 initial_state: Some(StateConfig {
231 coins: Some(vec![CoinConfig {
232 tx_id,
233 output_index,
234 block_created,
235 maturity,
236 owner,
237 amount,
238 asset_id,
239 }]),
240 ..Default::default()
241 }),
242 ..ChainConfig::local_testnet()
243 }
244 }
245
246 fn test_message_config() -> ChainConfig {
247 let mut rng = StdRng::seed_from_u64(1);
248
249 ChainConfig {
250 initial_state: Some(StateConfig {
251 messages: Some(vec![MessageConfig {
252 sender: rng.gen(),
253 recipient: rng.gen(),
254 nonce: rng.gen(),
255 amount: rng.gen(),
256 data: vec![rng.gen()],
257 da_height: DaBlockHeight(rng.gen()),
258 }]),
259 ..Default::default()
260 }),
261 ..ChainConfig::local_testnet()
262 }
263 }
264
265 fn tmp_path() -> PathBuf {
266 let mut path = temp_dir();
267 path.push(rand::random::<u16>().to_string());
268 path
269 }
270}