mirror of
https://github.com/AleoHQ/leo.git
synced 2024-09-11 15:05:33 +03:00
Add support for multi-file compile tests
This commit is contained in:
parent
8456096ac8
commit
f4af8a77d2
1
Cargo.lock
generated
1
Cargo.lock
generated
@ -1459,6 +1459,7 @@ dependencies = [
|
||||
name = "leo-compiler"
|
||||
version = "1.10.0"
|
||||
dependencies = [
|
||||
"disassembler",
|
||||
"dotenvy",
|
||||
"indexmap 1.9.3",
|
||||
"leo-ast",
|
||||
|
@ -45,6 +45,9 @@ version = "0.10"
|
||||
version = "1.9"
|
||||
features = []
|
||||
|
||||
[dev-dependencies.disassembler]
|
||||
path = "../../utils/disassembler"
|
||||
|
||||
[dev-dependencies.leo-test-framework]
|
||||
path = "../../tests/test-framework"
|
||||
|
||||
@ -76,4 +79,4 @@ version = "3.10"
|
||||
|
||||
[features]
|
||||
default = [ ]
|
||||
ci_skip = [ "leo-ast/ci_skip" ]
|
||||
ci_skip = [ "leo-ast/ci_skip" ]
|
||||
|
@ -27,16 +27,20 @@ use utilities::{
|
||||
BufferEmitter,
|
||||
};
|
||||
|
||||
use disassembler::disassemble_from_str;
|
||||
use leo_compiler::{CompilerOptions, OutputOptions};
|
||||
use leo_errors::{emitter::Handler, LeoError};
|
||||
use leo_span::symbol::create_session_if_not_set_then;
|
||||
use leo_test_framework::{
|
||||
runner::{Namespace, ParseType, Runner},
|
||||
Test,
|
||||
PROGRAM_DELIMITER,
|
||||
};
|
||||
|
||||
use snarkvm::console::prelude::*;
|
||||
|
||||
use indexmap::IndexMap;
|
||||
use leo_span::Symbol;
|
||||
use serde::{Deserialize, Serialize};
|
||||
use serde_yaml::Value;
|
||||
use std::{fs, path::Path, rc::Rc};
|
||||
@ -101,48 +105,68 @@ fn run_test(test: Test, handler: &Handler, buf: &BufferEmitter) -> Result<Value,
|
||||
},
|
||||
};
|
||||
|
||||
// Parse the program.
|
||||
let mut parsed =
|
||||
handler.extend_if_error(parse_program(handler, &test.content, cwd.clone(), Some(compiler_options)))?;
|
||||
// Split the test content into individual program strings based on the program delimiter.
|
||||
let program_strings = test.content.split(PROGRAM_DELIMITER).collect::<Vec<&str>>();
|
||||
|
||||
// Compile the program to bytecode.
|
||||
let program_name = format!("{}.{}", parsed.program_name, parsed.network);
|
||||
let bytecode = handler.extend_if_error(compile_and_process(&mut parsed))?;
|
||||
// Initialize storage for the stubs.
|
||||
let mut import_stubs = IndexMap::new();
|
||||
|
||||
// Set up the build directory.
|
||||
// Note that this function checks that the bytecode is well-formed.
|
||||
let package = setup_build_directory(&program_name, &bytecode, handler)?;
|
||||
// Compile each program string separately.
|
||||
for program_string in program_strings {
|
||||
// Parse the program.
|
||||
let mut parsed = handler.extend_if_error(parse_program(
|
||||
handler,
|
||||
program_string,
|
||||
cwd.clone(),
|
||||
Some(compiler_options.clone()),
|
||||
import_stubs.clone(),
|
||||
))?;
|
||||
|
||||
// Get the program process and check all instructions.
|
||||
handler.extend_if_error(package.get_process().map_err(LeoError::Anyhow))?;
|
||||
// Compile the program to bytecode.
|
||||
let program_name = parsed.program_name.to_string();
|
||||
let full_program_name = format!("{program_name}.{}", parsed.network);
|
||||
let bytecode = handler.extend_if_error(compile_and_process(&mut parsed))?;
|
||||
|
||||
// Hash the ast files.
|
||||
let (initial_ast, unrolled_ast, ssa_ast, flattened_ast, destructured_ast, inlined_ast, dce_ast) = hash_asts();
|
||||
// Add the bytecode to the import stubs.
|
||||
let stub = handler.extend_if_error(disassemble_from_str(&bytecode).map_err(|err| err.into()))?;
|
||||
import_stubs.insert(Symbol::intern(&program_name), stub);
|
||||
|
||||
// Hash the symbol tables.
|
||||
let (initial_symbol_table, type_checked_symbol_table, unrolled_symbol_table) = hash_symbol_tables();
|
||||
// Set up the build directory.
|
||||
// Note that this function checks that the bytecode is well-formed.
|
||||
let package = setup_build_directory(&full_program_name, &bytecode, handler)?;
|
||||
|
||||
// Clean up the output directory.
|
||||
if fs::read_dir("/tmp/output").is_ok() {
|
||||
fs::remove_dir_all(Path::new("/tmp/output")).expect("Error failed to clean up output dir.");
|
||||
// Get the program process and check all instructions.
|
||||
handler.extend_if_error(package.get_process().map_err(LeoError::Anyhow))?;
|
||||
|
||||
// Hash the ast files.
|
||||
let (initial_ast, unrolled_ast, ssa_ast, flattened_ast, destructured_ast, inlined_ast, dce_ast) =
|
||||
hash_asts();
|
||||
|
||||
// Hash the symbol tables.
|
||||
let (initial_symbol_table, type_checked_symbol_table, unrolled_symbol_table) = hash_symbol_tables();
|
||||
|
||||
// Clean up the output directory.
|
||||
if fs::read_dir("/tmp/output").is_ok() {
|
||||
fs::remove_dir_all(Path::new("/tmp/output")).expect("Error failed to clean up output dir.");
|
||||
}
|
||||
|
||||
let final_output = CompileOutput {
|
||||
initial_symbol_table,
|
||||
type_checked_symbol_table,
|
||||
unrolled_symbol_table,
|
||||
initial_ast,
|
||||
unrolled_ast,
|
||||
ssa_ast,
|
||||
flattened_ast,
|
||||
destructured_ast,
|
||||
inlined_ast,
|
||||
dce_ast,
|
||||
bytecode: hash_content(&bytecode),
|
||||
warnings: buf.1.take().to_string(),
|
||||
};
|
||||
|
||||
outputs.push(final_output);
|
||||
}
|
||||
|
||||
let final_output = CompileOutput {
|
||||
initial_symbol_table,
|
||||
type_checked_symbol_table,
|
||||
unrolled_symbol_table,
|
||||
initial_ast,
|
||||
unrolled_ast,
|
||||
ssa_ast,
|
||||
flattened_ast,
|
||||
destructured_ast,
|
||||
inlined_ast,
|
||||
dce_ast,
|
||||
bytecode: hash_content(&bytecode),
|
||||
warnings: buf.1.take().to_string(),
|
||||
};
|
||||
|
||||
outputs.push(final_output);
|
||||
}
|
||||
Ok(serde_yaml::to_value(outputs).expect("serialization failed"))
|
||||
}
|
||||
|
@ -116,8 +116,13 @@ fn run_test(test: Test, handler: &Handler, err_buf: &BufferEmitter) -> Result<Va
|
||||
};
|
||||
|
||||
// Parse the program.
|
||||
let mut parsed =
|
||||
handler.extend_if_error(parse_program(handler, &test.content, cwd.clone(), Some(compiler_options)))?;
|
||||
let mut parsed = handler.extend_if_error(parse_program(
|
||||
handler,
|
||||
&test.content,
|
||||
cwd.clone(),
|
||||
Some(compiler_options),
|
||||
Default::default(),
|
||||
))?;
|
||||
|
||||
// Compile the program to bytecode.
|
||||
let program_name = format!("{}.{}", parsed.program_name, parsed.network);
|
||||
|
@ -30,7 +30,8 @@ use leo_test_framework::{test::TestConfig, Test};
|
||||
use snarkvm::prelude::*;
|
||||
|
||||
use indexmap::IndexMap;
|
||||
use leo_ast::ProgramVisitor;
|
||||
use leo_ast::{ProgramVisitor, Stub};
|
||||
use leo_span::Symbol;
|
||||
use snarkvm::{file::Manifest, package::Package};
|
||||
use std::{
|
||||
cell::RefCell,
|
||||
@ -139,6 +140,7 @@ pub fn new_compiler(
|
||||
handler: &Handler,
|
||||
main_file_path: PathBuf,
|
||||
compiler_options: Option<CompilerOptions>,
|
||||
import_stubs: IndexMap<Symbol, Stub>,
|
||||
) -> Compiler<'_> {
|
||||
let output_dir = PathBuf::from("/tmp/output/");
|
||||
fs::create_dir_all(output_dir.clone()).unwrap();
|
||||
@ -150,7 +152,7 @@ pub fn new_compiler(
|
||||
main_file_path,
|
||||
output_dir,
|
||||
compiler_options,
|
||||
IndexMap::new(),
|
||||
import_stubs,
|
||||
)
|
||||
}
|
||||
|
||||
@ -159,8 +161,10 @@ pub fn parse_program<'a>(
|
||||
program_string: &str,
|
||||
cwd: Option<PathBuf>,
|
||||
compiler_options: Option<CompilerOptions>,
|
||||
import_stubs: IndexMap<Symbol, Stub>,
|
||||
) -> Result<Compiler<'a>, LeoError> {
|
||||
let mut compiler = new_compiler(handler, cwd.clone().unwrap_or_else(|| "compiler-test".into()), compiler_options);
|
||||
let mut compiler =
|
||||
new_compiler(handler, cwd.clone().unwrap_or_else(|| "compiler-test".into()), compiler_options, import_stubs);
|
||||
let name = cwd.map_or_else(|| FileName::Custom("compiler-test".into()), FileName::Real);
|
||||
compiler.parse_program_from_string(program_string, name)?;
|
||||
|
||||
|
@ -56,6 +56,7 @@ version = "1.10"
|
||||
[dev-dependencies.leo-compiler]
|
||||
path = "../../compiler/compiler"
|
||||
|
||||
|
||||
[dev-dependencies.leo-span]
|
||||
path = "../../compiler/span"
|
||||
|
||||
|
@ -25,6 +25,8 @@ use std::{
|
||||
|
||||
use crate::{error::*, fetch::find_tests, output::TestExpectation, test::*};
|
||||
|
||||
pub const PROGRAM_DELIMITER: &str = "// --- Next Program --- //";
|
||||
|
||||
#[derive(Debug, PartialEq, Eq, Clone, Copy)]
|
||||
pub enum ParseType {
|
||||
Line,
|
||||
|
@ -71,8 +71,8 @@ pub fn disassemble<N: Network, Instruction: InstructionTrait<N>, Command: Comman
|
||||
}
|
||||
}
|
||||
|
||||
pub fn disassemble_from_str(program: String) -> Result<Stub, UtilError> {
|
||||
match Program::<CurrentNetwork>::from_str(&program) {
|
||||
pub fn disassemble_from_str(program: &str) -> Result<Stub, UtilError> {
|
||||
match Program::<CurrentNetwork>::from_str(program) {
|
||||
Ok(p) => Ok(disassemble(p)),
|
||||
Err(_) => Err(UtilError::snarkvm_parsing_error(Default::default())),
|
||||
}
|
||||
@ -109,7 +109,7 @@ mod tests {
|
||||
create_session_if_not_set_then(|_| {
|
||||
let program_from_file =
|
||||
fs::read_to_string("../tmp/.aleo/registry/testnet3/zk_bitwise_stack_v0_0_2.aleo").unwrap();
|
||||
let _program = disassemble_from_str(program_from_file).unwrap();
|
||||
let _program = disassemble_from_str(&program_from_file).unwrap();
|
||||
});
|
||||
}
|
||||
}
|
||||
|
@ -304,7 +304,7 @@ impl Retriever {
|
||||
})?;
|
||||
|
||||
// Cache the disassembled stub
|
||||
let stub: Stub = disassemble_from_str(content)?;
|
||||
let stub: Stub = disassemble_from_str(&content)?;
|
||||
if cur_context.add_stub(stub.clone()) {
|
||||
Err(UtilError::duplicate_dependency_name_error(stub.stub_id.name.name, Default::default()))?;
|
||||
}
|
||||
@ -484,7 +484,7 @@ fn retrieve_from_network(
|
||||
})?;
|
||||
|
||||
// Disassemble into Stub
|
||||
let stub: Stub = disassemble_from_str(file_str)?;
|
||||
let stub: Stub = disassemble_from_str(&file_str)?;
|
||||
|
||||
// Create entry for leo.lock
|
||||
Ok((
|
||||
|
Loading…
Reference in New Issue
Block a user