/ compiler / compiler / src / test_compiler.rs
test_compiler.rs
 1  // Copyright (C) 2019-2025 ADnet Contributors
 2  // This file is part of the ADL library.
 3  
 4  // The ADL library is free software: you can redistribute it and/or modify
 5  // it under the terms of the GNU General Public License as published by
 6  // the Free Software Foundation, either version 3 of the License, or
 7  // (at your option) any later version.
 8  
 9  // The ADL library is distributed in the hope that it will be useful,
10  // but WITHOUT ANY WARRANTY; without even the implied warranty of
11  // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12  // GNU General Public License for more details.
13  
14  // You should have received a copy of the GNU General Public License
15  // along with the ADL library. If not, see <https://www.gnu.org/licenses/>.
16  
17  use adl_disassembler::disassemble_from_str;
18  use adl_errors::{AdlError, BufferEmitter, Handler};
19  use adl_span::{Symbol, create_session_if_not_set_then};
20  
21  use snarkvm::{
22      prelude::{Process, TestnetV0},
23      synthesizer::program::ProgramCore,
24  };
25  
26  use indexmap::IndexMap;
27  use itertools::Itertools as _;
28  use serial_test::serial;
29  use std::str::FromStr;
30  
31  fn run_test(test: &str, handler: &Handler) -> Result<String, ()> {
32      // Initialize a `Process`. This should always succeed.
33      let mut process = Process::<TestnetV0>::load().unwrap();
34  
35      let mut import_stubs = IndexMap::new();
36  
37      let mut bytecodes = Vec::<String>::new();
38  
39      // Compile each source file separately.
40      for source in test.split(super::test_utils::PROGRAM_DELIMITER) {
41          let (bytecode, program_name) =
42              handler.extend_if_error(super::test_utils::whole_compile(source, handler, import_stubs.clone()))?;
43  
44          // Parse the bytecode as an Aleo program.
45          // Note that this function checks that the bytecode is well-formed.
46          let alpha_program = handler.extend_if_error(ProgramCore::from_str(&bytecode).map_err(AdlError::Anyhow))?;
47  
48          // Add the program to the process.
49          // Note that this function performs an additional validity check on the bytecode.
50          handler.extend_if_error(process.add_program(&alpha_program).map_err(AdlError::Anyhow))?;
51  
52          // Add the bytecode to the import stubs.
53          let stub = handler
54              .extend_if_error(disassemble_from_str::<TestnetV0>(&program_name, &bytecode).map_err(|err| err.into()))?;
55          import_stubs.insert(Symbol::intern(&program_name), stub);
56  
57          // Only error out if there are errors. Warnings are okay but we still want to print them later.
58          if handler.err_count() != 0 {
59              return Err(());
60          }
61  
62          bytecodes.push(bytecode);
63      }
64  
65      Ok(bytecodes.iter().format(&format!("{}\n", super::test_utils::PROGRAM_DELIMITER)).to_string())
66  }
67  
68  fn runner(source: &str) -> String {
69      let buf = BufferEmitter::new();
70      let handler = Handler::new(buf.clone());
71  
72      create_session_if_not_set_then(|_| match run_test(source, &handler) {
73          Ok(x) => format!("{}{}", buf.extract_warnings(), x),
74          Err(()) => format!("{}{}", buf.extract_errs(), buf.extract_warnings()),
75      })
76  }
77  
78  #[test]
79  #[serial]
80  fn test_compiler() {
81      adl_test_framework::run_tests("compiler", runner);
82  }