Files

97 lines
4.1 KiB
Rust
Raw Permalink Normal View History

2026-05-04 22:45:55 -07:00
use roto_codegen::google::protobuf::compiler::plugin::CodeGeneratorRequest;
use roto_codegen::google::protobuf::descriptor::FileDescriptorSet;
2026-05-03 13:06:11 -07:00
use std::fs;
use std::process::Command;
#[test]
fn test_generated_code_builds() {
// 1. Generate Rust code from data/request.bin
let request_path = "data/request.bin";
let data = fs::read(request_path).expect("Failed to read request.bin");
2026-05-04 22:45:55 -07:00
let request = CodeGeneratorRequest::new(&data).expect("Failed to parse CodeGeneratorRequest");
2026-05-03 13:06:11 -07:00
// Mimic the logic from protoc-gen-roto to build a FileDescriptorSet
let mut set_buf = Vec::new();
for file_res in request.proto_file() {
let (file_data, _) = file_res.expect("Failed to iterate proto_file");
// Tag 1, Length-delimited: (1 << 3) | 2 = 10
set_buf.push(10);
// Write length as varint
let len = file_data.len() as u64;
let mut len_buf = [0u8; 10];
2026-05-04 22:45:55 -07:00
let len_size =
roto_runtime::write_varint(len, &mut len_buf).expect("Failed to write varint length");
2026-05-03 13:06:11 -07:00
set_buf.extend_from_slice(&len_buf[..len_size]);
// Write data
set_buf.extend_from_slice(file_data);
}
2026-05-04 22:45:55 -07:00
let set = FileDescriptorSet::new(&set_buf).expect("Failed to create FileDescriptorSet");
2026-05-03 13:06:11 -07:00
2026-05-04 22:45:55 -07:00
let generated_files = roto_codegen::generator::generate_rust_code(&set, None, false);
assert!(
!generated_files.is_empty(),
"Generated code should not be empty"
);
2026-05-03 13:06:11 -07:00
// 2. Setup a temporary Cargo project to verify the code builds
2026-05-15 10:49:56 -07:00
let codegen_root = std::path::PathBuf::from(env!("CARGO_MANIFEST_DIR"));
let project_root = codegen_root.parent().expect("Failed to get project root");
let temp_project_dir = std::path::PathBuf::from("/tmp/roto_test_gen_project");
2026-05-03 13:06:11 -07:00
// Clean up previous runs
if temp_project_dir.exists() {
fs::remove_dir_all(&temp_project_dir).expect("Failed to clean up temp project directory");
}
// Create new library project
let status = Command::new("cargo")
2026-05-15 10:49:56 -07:00
.args(["new", "--lib", temp_project_dir.to_str().expect("Invalid path")])
2026-05-03 13:06:11 -07:00
.status()
.expect("Failed to run cargo new");
assert!(status.success(), "cargo new failed");
// 3. Configure the project to depend on the current roto crate
let cargo_toml_path = temp_project_dir.join("Cargo.toml");
2026-05-04 22:45:55 -07:00
let cargo_toml_content =
fs::read_to_string(&cargo_toml_path).expect("Failed to read Cargo.toml");
2026-05-03 13:06:11 -07:00
let updated_cargo_toml = format!(
2026-05-15 10:49:56 -07:00
"{}\n\nroto-codegen = {{ path = \"{}\" }}\nroto-runtime = {{ path = \"{}\" }}\nroto-tonic = {{ path = \"{}\" }}\nbytes = \"1.7\"\ntonic = \"0.12\"\ntokio-stream = \"0.1\"\ntower = \"0.4\"\nfutures-util = \"0.3\"\nhttp-body-util = \"0.1\"\nhttp-body = \"1.0\"\n\n[workspace]\n",
cargo_toml_content,
codegen_root.to_string_lossy(),
project_root.join("runtime").to_string_lossy(),
project_root.join("roto-tonic").to_string_lossy()
2026-05-03 13:06:11 -07:00
);
fs::write(cargo_toml_path, updated_cargo_toml).expect("Failed to write Cargo.toml");
// 4. Write the generated code to src/lib.rs
// The generated code uses `use crate::{...}`, but it's now in a separate crate.
2026-05-16 19:45:46 -07:00
// Replace `crate` with `roto_tonic` to reference the types in the dependency.
let mut all_code = String::new();
for (_, content) in generated_files {
2026-05-16 19:45:46 -07:00
let replaced = content.replace("use crate::{BufferPool, StatusBody};", "use roto_tonic::{BufferPool, StatusBody};");
all_code.push_str(&replaced);
all_code.push_str("\n");
}
2026-05-03 13:06:11 -07:00
let lib_path = temp_project_dir.join("src/lib.rs");
2026-05-07 17:59:39 -07:00
fs::write(lib_path, all_code).expect("Failed to write generated code to src/lib.rs");
2026-05-03 13:06:11 -07:00
// 5. Attempt to build the project
2026-05-15 10:49:56 -07:00
let build_output = Command::new("cargo")
.args(["build"])
2026-05-03 13:06:11 -07:00
.current_dir(&temp_project_dir)
2026-05-15 10:49:56 -07:00
.output()
2026-05-03 13:06:11 -07:00
.expect("Failed to run cargo build");
2026-05-15 10:49:56 -07:00
if !build_output.status.success() {
eprintln!("Cargo build failed output:\n{}", String::from_utf8_lossy(&build_output.stderr));
}
2026-05-04 22:45:55 -07:00
assert!(
2026-05-15 10:49:56 -07:00
build_output.status.success(),
2026-05-04 22:45:55 -07:00
"The generated Rust code failed to build in a standalone project!"
);
2026-05-03 13:06:11 -07:00
}