#![cfg(feature = "testing")]
use std::env;
use std::fs;
use tempfile::TempDir;
fn create_e2e_workspace() -> TempDir {
let temp_dir = tempfile::tempdir().expect("Failed to create temp workspace");
let workspace_root = temp_dir.path();
let root_cargo_toml = r#"
[workspace]
members = ["token-program", "governance-program", "shared-lib"]
resolver = "2"
[workspace.dependencies]
solana-program = "~1.18.0"
"#;
fs::write(workspace_root.join("Cargo.toml"), root_cargo_toml)
.expect("Failed to write root Cargo.toml");
let token_dir = workspace_root.join("token-program");
fs::create_dir_all(token_dir.join("src")).expect("Failed to create token-program dir");
let token_cargo_toml = r#"
[package]
name = "token-program"
version = "0.1.0"
edition = "2021"
[lib]
crate-type = ["cdylib"]
[dependencies]
solana-program = { workspace = true }
"#;
fs::write(token_dir.join("Cargo.toml"), token_cargo_toml)
.expect("Failed to write token-program Cargo.toml");
let token_lib_rs = r#"
use solana_program::{
account_info::AccountInfo,
entrypoint,
entrypoint::ProgramResult,
msg,
pubkey::Pubkey,
};
entrypoint!(process_instruction);
pub fn process_instruction(
_program_id: &Pubkey,
_accounts: &[AccountInfo],
_instruction_data: &[u8],
) -> ProgramResult {
msg!("Token program executed!");
Ok(())
}
"#;
fs::write(token_dir.join("src/lib.rs"), token_lib_rs)
.expect("Failed to write token-program lib.rs");
let governance_dir = workspace_root.join("governance-program");
fs::create_dir_all(governance_dir.join("src"))
.expect("Failed to create governance-program dir");
let governance_cargo_toml = r#"
[package]
name = "governance-program"
version = "0.1.0"
edition = "2021"
[lib]
crate-type = ["cdylib"]
[dependencies]
solana-program = { workspace = true }
"#;
fs::write(governance_dir.join("Cargo.toml"), governance_cargo_toml)
.expect("Failed to write governance-program Cargo.toml");
let governance_lib_rs = r#"
use solana_program::{
account_info::AccountInfo,
entrypoint,
entrypoint::ProgramResult,
msg,
pubkey::Pubkey,
};
entrypoint!(process_instruction);
pub fn process_instruction(
_program_id: &Pubkey,
_accounts: &[AccountInfo],
_instruction_data: &[u8],
) -> ProgramResult {
msg!("Governance program executed!");
Ok(())
}
"#;
fs::write(governance_dir.join("src/lib.rs"), governance_lib_rs)
.expect("Failed to write governance-program lib.rs");
let shared_dir = workspace_root.join("shared-lib");
fs::create_dir_all(shared_dir.join("src")).expect("Failed to create shared-lib dir");
let shared_cargo_toml = r#"
[package]
name = "shared-lib"
version = "0.1.0"
edition = "2021"
[lib]
crate-type = ["lib"]
[dependencies]
solana-program = { workspace = true }
"#;
fs::write(shared_dir.join("Cargo.toml"), shared_cargo_toml)
.expect("Failed to write shared-lib Cargo.toml");
let shared_lib_rs = r#"
pub fn shared_function() -> u32 {
42
}
"#;
fs::write(shared_dir.join("src/lib.rs"), shared_lib_rs)
.expect("Failed to write shared-lib lib.rs");
temp_dir
}
fn create_elf_crate_in_workspace(workspace_root: &std::path::Path, elf_magic_config: Option<&str>) {
let current_dir = env::current_dir().expect("Failed to get current directory");
let elf_magic_path = current_dir.display();
let elf_dir = workspace_root.join("my-elves");
fs::create_dir_all(elf_dir.join("src")).expect("Failed to create elf crate dir");
let mut root_cargo = fs::read_to_string(workspace_root.join("Cargo.toml"))
.expect("Failed to read root Cargo.toml");
let mut cargo_toml: toml::Value =
toml::from_str(&root_cargo).expect("Failed to parse root Cargo.toml");
if let Some(workspace) = cargo_toml.get_mut("workspace") {
if let Some(members) = workspace.get_mut("members") {
if let Some(members_array) = members.as_array_mut() {
let my_elves_value = toml::Value::String("my-elves".to_string());
if !members_array.contains(&my_elves_value) {
members_array.push(my_elves_value);
}
}
}
}
root_cargo = toml::to_string(&cargo_toml).expect("Failed to serialize updated Cargo.toml");
fs::write(workspace_root.join("Cargo.toml"), root_cargo)
.expect("Failed to update root Cargo.toml");
let mut elf_cargo_toml = format!(
r#"
[package]
name = "my-elves"
version = "0.1.0"
edition = "2021"
[build-dependencies]
elf-magic = {{ path = "{}" }}
"#,
elf_magic_path
);
if let Some(config) = elf_magic_config {
elf_cargo_toml.push('\n');
elf_cargo_toml.push_str(config);
}
fs::write(elf_dir.join("Cargo.toml"), elf_cargo_toml)
.expect("Failed to write elf crate Cargo.toml");
let build_rs = r#"
fn main() {
elf_magic::generate().expect("elf-magic generation failed");
}
"#;
fs::write(elf_dir.join("build.rs"), build_rs).expect("Failed to write build.rs");
let lib_rs = r#"
// This will be overwritten by elf-magic
"#;
fs::write(elf_dir.join("src/lib.rs"), lib_rs).expect("Failed to write initial lib.rs");
}
#[test]
fn test_e2e_full_pipeline() {
let workspace = create_e2e_workspace();
create_elf_crate_in_workspace(workspace.path(), None);
let elf_manifest_dir = workspace
.path()
.join("my-elves")
.to_string_lossy()
.to_string();
let result = elf_magic::generate_with_manifest_dir(&elf_manifest_dir);
assert!(
result.is_ok(),
"elf-magic generation should succeed: {:?}",
result.err()
);
let generation_result = result.unwrap();
println!("Found {} programs:", generation_result.programs.len());
for program in &generation_result.programs {
println!(" - {} at {}", program.name, program.path.display());
}
assert_eq!(generation_result.programs.len(), 2);
let program_names: Vec<&String> = generation_result.programs.iter().map(|p| &p.name).collect();
assert!(program_names.contains(&&"governance_program".to_string()));
assert!(program_names.contains(&&"token_program".to_string()));
let lib_path = workspace.path().join("my-elves/src/lib.rs");
assert!(lib_path.exists(), "Generated lib.rs should exist");
let lib_content = fs::read_to_string(&lib_path).expect("Failed to read generated lib.rs");
assert!(
lib_content.contains("GOVERNANCE_PROGRAM_ELF"),
"Should contain governance program constant"
);
assert!(
lib_content.contains("TOKEN_PROGRAM_ELF"),
"Should contain token program constant"
);
assert!(
lib_content.contains("pub fn elves()"),
"Should contain elves function"
);
assert!(
lib_content.contains("auto-generated by elf-magic"),
"Should contain generation comment"
);
for program in &generation_result.programs {
let env_var = program.env_var_name();
assert!(
lib_content.contains(&env_var),
"Should reference env var {}",
env_var
);
}
}
#[test]
fn test_e2e_with_filtering() {
let workspace = create_e2e_workspace();
let elf_magic_config = r#"
[package.metadata.elf-magic]
include = ["**/*"]
exclude = ["governance-program"]
"#;
create_elf_crate_in_workspace(workspace.path(), Some(elf_magic_config));
let elf_manifest_dir = workspace
.path()
.join("my-elves")
.to_string_lossy()
.to_string();
let result = elf_magic::generate_with_manifest_dir(&elf_manifest_dir);
assert!(
result.is_ok(),
"elf-magic generation should succeed: {:?}",
result.err()
);
let generation_result = result.unwrap();
assert_eq!(generation_result.programs.len(), 1);
assert_eq!(generation_result.programs[0].name, "token_program");
let lib_path = workspace.path().join("my-elves/src/lib.rs");
let lib_content = fs::read_to_string(&lib_path).expect("Failed to read generated lib.rs");
assert!(
lib_content.contains("TOKEN_PROGRAM_ELF"),
"Should contain token program constant"
);
assert!(
!lib_content.contains("GOVERNANCE_PROGRAM_ELF"),
"Should NOT contain governance program constant"
);
}
#[test]
fn test_e2e_empty_workspace() {
let temp_dir = tempfile::tempdir().expect("Failed to create temp workspace");
let workspace_root = temp_dir.path();
let root_cargo_toml = r#"
[workspace]
members = ["regular-lib"]
resolver = "2"
"#;
fs::write(workspace_root.join("Cargo.toml"), root_cargo_toml)
.expect("Failed to write root Cargo.toml");
let lib_dir = workspace_root.join("regular-lib");
fs::create_dir_all(lib_dir.join("src")).expect("Failed to create regular-lib dir");
let lib_cargo_toml = r#"
[package]
name = "regular-lib"
version = "0.1.0"
edition = "2021"
[lib]
crate-type = ["lib"]
"#;
fs::write(lib_dir.join("Cargo.toml"), lib_cargo_toml)
.expect("Failed to write regular-lib Cargo.toml");
fs::write(lib_dir.join("src/lib.rs"), "pub fn hello() {}")
.expect("Failed to write regular-lib lib.rs");
create_elf_crate_in_workspace(workspace_root, None);
let elf_manifest_dir = workspace_root
.join("my-elves")
.to_string_lossy()
.to_string();
let result = elf_magic::generate_with_manifest_dir(&elf_manifest_dir);
assert!(
result.is_ok(),
"elf-magic generation should succeed even with no programs"
);
let generation_result = result.unwrap();
assert_eq!(generation_result.programs.len(), 0);
let lib_path = workspace_root.join("my-elves/src/lib.rs");
let lib_content = fs::read_to_string(&lib_path).expect("Failed to read generated lib.rs");
assert!(
lib_content.contains("pub fn elves()"),
"Should contain elves function"
);
assert!(
lib_content.contains("vec![]"),
"Should contain empty vector"
);
assert!(
lib_content.contains("auto-generated by elf-magic"),
"Should contain generation comment"
);
assert!(
!lib_content.contains("_ELF"),
"Should not contain any ELF constants"
);
}
#[test]
fn test_e2e_invalid_workspace() {
let temp_dir = tempfile::tempdir().expect("Failed to create temp dir");
let temp_manifest_dir = temp_dir.path().to_string_lossy().to_string();
let result = elf_magic::generate_with_manifest_dir(&temp_manifest_dir);
assert!(
result.is_err(),
"elf-magic should fail gracefully on invalid workspace"
);
let error = result.unwrap_err();
let error_msg = error.to_string();
assert!(
error_msg.contains("Cargo.toml")
|| error_msg.contains("workspace")
|| error_msg.contains("metadata"),
"Error should mention workspace/cargo issues: {}",
error_msg
);
}