use python_assembler::{
builder::PythonBuilder,
formats::pyc::{writer::PycWriter, PycWriteConfig},
program::{PycHeader, PythonVersion},
};
use std::{fs::File, io::BufWriter, path::Path, process::Command};
#[test]
fn test_build_and_write_pyc() {
let builder = PythonBuilder::new();
let program = builder.print_str("Hello World").build(create_pyc_header());
assert_eq!(program.code_object.source_name, "<string>");
assert_eq!(program.code_object.co_consts.len(), 2);
let output_path = "test_output.pyc";
let file = File::create(output_path).expect("Failed to create output file");
let mut writer = PycWriter::new(BufWriter::new(file), PycWriteConfig::default());
let bytes_written = writer.write(&program).expect("Failed to write pyc file");
println!("Successfully wrote {} bytes to {}", bytes_written, output_path);
assert!(Path::new(output_path).exists(), "Output file should exist");
let output = Command::new("python").arg(output_path).output();
match output {
Ok(result) => {
let stdout = String::from_utf8_lossy(&result.stdout);
let stderr = String::from_utf8_lossy(&result.stderr);
if result.status.success() {
println!("Python execution output: {}", stdout);
assert_eq!(stdout.trim(), "Hello World");
}
else {
println!("Python execution failed: {}", stderr);
panic!("Generated .pyc failed to run: {}", stderr);
}
}
Err(e) => {
println!("Failed to execute python: {}. Skipping execution test.", e);
}
}
if Path::new(output_path).exists() {
std::fs::remove_file(output_path).ok();
}
}
#[test]
fn test_python_builder_functionality() {
let builder = PythonBuilder::new();
let program = builder.print_str("Test Message").build(create_pyc_header());
assert_eq!(program.version, PythonVersion::Python3_12);
assert_eq!(program.code_object.source_name, "<string>");
assert_eq!(program.code_object.first_line, 1);
assert_eq!(program.code_object.last_line, 1);
assert_eq!(program.code_object.co_consts.len(), 2);
match &program.code_object.co_consts[1] {
python_assembler::program::PythonObject::Str(s) => {
assert_eq!(s, "Test Message");
}
_ => panic!("Expected string constant"),
}
}
#[test]
fn test_pyc_writer_basic() {
let builder = PythonBuilder::new();
let program = builder.build(create_pyc_header());
let mut buffer = Vec::new();
let mut writer = PycWriter::new(&mut buffer, PycWriteConfig::default());
let bytes_written = writer.write(&program).expect("Failed to write to buffer");
assert!(bytes_written > 16);
assert_eq!(buffer.len(), bytes_written);
let expected_magic = PythonVersion::Python3_12.as_magic();
assert_eq!(&buffer[0..4], &expected_magic);
}
fn create_pyc_header() -> PycHeader {
let version = PythonVersion::Python3_12;
PycHeader {
magic: version.as_magic(),
flags: 0,
timestamp: std::time::SystemTime::now().duration_since(std::time::UNIX_EPOCH).unwrap_or_default().as_secs() as u32,
size: 0, }
}