test_process_execute.rs
1 // Copyright (c) 2019-2025 Alpha-Delta Network Inc. 2 // This file is part of the deltavm library. 3 4 // Licensed under the Apache License, Version 2.0 (the "License"); 5 // you may not use this file except in compliance with the License. 6 // You may obtain a copy of the License at: 7 8 // http://www.apache.org/licenses/LICENSE-2.0 9 10 // Unless required by applicable law or agreed to in writing, software 11 // distributed under the License is distributed on an "AS IS" BASIS, 12 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 // See the License for the specific language governing permissions and 14 // limitations under the License. 15 16 mod utilities; 17 18 use deltavm_console::{ 19 account::PrivateKey, 20 network::prelude::*, 21 program::{Identifier, Literal, ProgramID, Value}, 22 types::Boolean, 23 }; 24 use deltavm_synthesizer_process::Process; 25 use utilities::*; 26 27 use rayon::prelude::*; 28 use std::panic::AssertUnwindSafe; 29 30 #[test] 31 fn test_process_execute() { 32 // Load the tests. 33 let tests = load_tests::<_, ProgramTest>("./tests/process/execute", "./expectations/process/execute"); 34 // Initialize a process. 35 let process = Process::<CurrentNetwork>::load().unwrap(); 36 37 // Run each test and compare it against its corresponding expectation. 38 tests.par_iter().for_each(|test| { 39 // Run the test. 40 let output = run_test(process.clone(), test); 41 // Check against the expected output. 42 let res = test.check(&output); 43 if let Err(err) = &res { 44 println!("Error running test {:?}: {}", test.path(), err); 45 } 46 res.unwrap(); 47 // Save the output when valid. 48 test.save(&output).unwrap(); 49 }); 50 } 51 52 // A helper function to run the test and extract the outputs as YAML, to be compared against the expectation. 53 fn run_test(process: Process<CurrentNetwork>, test: &ProgramTest) -> serde_yaml::Mapping { 54 // Initialize the output. 55 let mut output = serde_yaml::Mapping::new(); 56 output.insert( 57 serde_yaml::Value::String("errors".to_string()), 58 serde_yaml::Value::Sequence(serde_yaml::Sequence::new()), 59 ); 60 61 // Add the programs into the process. 62 let mut process = process.clone(); 63 for program in test.programs() { 64 if let Err(err) = process.add_program(program) { 65 output 66 .get_mut(serde_yaml::Value::String("errors".to_string())) 67 .unwrap() 68 .as_sequence_mut() 69 .unwrap() 70 .push(serde_yaml::Value::String(err.to_string())); 71 output.insert( 72 serde_yaml::Value::String("outputs".to_string()), 73 serde_yaml::Value::Sequence(serde_yaml::Sequence::new()), 74 ); 75 return output; 76 } 77 } 78 79 // Initialize the RNG. 80 let rng = &mut match test.randomness() { 81 None => TestRng::default(), 82 Some(randomness) => TestRng::fixed(randomness), 83 }; 84 85 output.insert( 86 serde_yaml::Value::String("outputs".to_string()), 87 serde_yaml::Value::Sequence( 88 test.cases() 89 .iter() 90 .map(|value| { 91 // Extract the function name, inputs, and optional private key. 92 let value = value.as_mapping().expect("expected mapping for test case"); 93 let program_id = ProgramID::<CurrentNetwork>::from_str( 94 value 95 .get("program") 96 .expect("expected program name for test case") 97 .as_str() 98 .expect("expected string for program name"), 99 ) 100 .expect("unable to parse program name"); 101 let function_name = Identifier::<CurrentNetwork>::from_str( 102 value 103 .get("function") 104 .expect("expected function name for test case") 105 .as_str() 106 .expect("expected string for function name"), 107 ) 108 .expect("unable to parse function name"); 109 let inputs = value 110 .get("inputs") 111 .expect("expected inputs for test case") 112 .as_sequence() 113 .expect("expected sequence for inputs") 114 .iter() 115 .map(|input| match &input { 116 serde_yaml::Value::Bool(bool) => { 117 Value::<CurrentNetwork>::from(Literal::Boolean(Boolean::new(*bool))) 118 } 119 _ => Value::<CurrentNetwork>::from_str(input.as_str().expect("expected string for input")) 120 .expect("unable to parse input"), 121 }) 122 .collect_vec(); 123 let private_key = match value.get("private_key") { 124 Some(private_key) => PrivateKey::<CurrentNetwork>::from_str( 125 private_key.as_str().expect("expected string for private key"), 126 ) 127 .expect("unable to parse private key"), 128 None => PrivateKey::new(rng).unwrap(), 129 }; 130 131 let mut run_test = || -> serde_yaml::Value { 132 // Authorize the execution. 133 let authorization = match process.authorize::<CurrentAlpha, _>( 134 &private_key, 135 program_id, 136 function_name, 137 inputs.iter(), 138 rng, 139 ) { 140 Ok(authorization) => authorization, 141 Err(err) => return serde_yaml::Value::String(err.to_string()), 142 }; 143 // Execute the authorization and extract the output as YAML. 144 std::panic::catch_unwind(AssertUnwindSafe(|| { 145 match process.execute::<CurrentAlpha, _>(authorization, rng) { 146 Ok((response, _)) => serde_yaml::Value::Sequence( 147 response 148 .outputs() 149 .iter() 150 .cloned() 151 .map(|output| serde_yaml::Value::String(output.to_string())) 152 .collect_vec(), 153 ), 154 Err(err) => serde_yaml::Value::String(err.to_string()), 155 } 156 })) 157 .unwrap_or(serde_yaml::Value::String( 158 "Compiler panicked when calling `Process::execute`".to_string(), 159 )) 160 }; 161 run_test() 162 }) 163 .collect::<serde_yaml::Sequence>(), 164 ), 165 ); 166 167 output 168 }