/* Any copyright is dedicated to the Public Domain. * https://creativecommons.org/publicdomain/zero/1.0/ */ use editres_cli::{inject, list}; use std::io::{stderr, Write}; use std::sync::Once; use std::vec; use std::{ env, path::PathBuf, process::{Command, Output}, }; use tempfile::TempPath; fn build_testbin_once() { static BUILD_ONCE: Once = Once::new(); BUILD_ONCE.call_once(|| { let build_status = Command::new(env::var("CARGO").unwrap()) .args(["build", "--release", "-p", "testbin", "--all-targets"]) .env("CARGO_TARGET_DIR", env!("CARGO_TARGET_TMPDIR")) .status() .unwrap(); assert!(build_status.success()); }); } fn testbin_command(name: &str) -> Command { build_testbin_once(); let mut path = format!("{}/release/{}", env!("CARGO_TARGET_TMPDIR"), name); if cfg!(windows) { path.push_str(".exe"); } Command::new(path) } fn temp_path() -> PathBuf { let mut path = PathBuf::from(env!("CARGO_TARGET_TMPDIR")); path.push(fastrand::u128(..).to_string()); path } fn get_printed_resources(output: &Output) -> Vec> { if !output.status.success() { stderr().lock().write_all(&output.stderr).unwrap(); panic!("Failed to get printed resources. Exit status: {:?}", output.status); } assert_eq!(output.status.success(), true); bincode::deserialize(&output.stdout).unwrap() } #[test] fn test_basic() { let mut single_command = testbin_command("single"); let output = single_command.output().unwrap(); assert_eq!(get_printed_resources(&output), &[None]); let resources = list(single_command.get_program()).unwrap(); assert_eq!(&resources, &[("my_res".to_string(), false)]); let mut injected_path = temp_path(); inject( single_command.get_program(), "my_res", b"res_content", &mut injected_path, ) .unwrap(); let resources = list(&injected_path).unwrap(); assert_eq!(&resources, &[("my_res".to_string(), true)]); let _path_guard = TempPath::from_path(&injected_path); let output = Command::new(injected_path).output().unwrap(); assert_eq!( get_printed_resources(&output), &[Some(b"res_content".as_slice())] ); } #[test] fn test_zero_size_resource() { let single_command = testbin_command("single"); let mut injected_path = temp_path(); inject( single_command.get_program(), "my_res", b"", &mut injected_path, ) .unwrap(); let _path_guard = TempPath::from_path(&injected_path); let output = Command::new(injected_path).output().unwrap(); assert_eq!(get_printed_resources(&output), &[Some(b"".as_slice())]); } #[test] fn test_multiple_resources() { let mut double_command = testbin_command("double"); let output = double_command.output().unwrap(); assert_eq!(get_printed_resources(&output), &[None, None]); let resources = list(double_command.get_program()).unwrap(); assert_eq!( &resources, &[ ("my_res1".to_string(), false), ("my_res2".to_string(), false) ] ); let mut injected_path = temp_path(); inject( double_command.get_program(), "my_res2", b"res2_content", &mut injected_path, ) .unwrap(); let _path_guard: TempPath = TempPath::from_path(&injected_path); assert_eq!( &list(&injected_path).unwrap(), &[ ("my_res1".to_string(), false), ("my_res2".to_string(), true) ] ); assert_eq!( get_printed_resources(&Command::new(&injected_path).output().unwrap()), &[None, Some(b"res2_content".as_slice())] ); let mut injected_path2 = temp_path(); inject( injected_path, "my_res1", b"res1_content", &mut injected_path2, ) .unwrap(); let _path_guard2: TempPath = TempPath::from_path(&injected_path2); assert_eq!( &list(&injected_path2).unwrap(), &[("my_res1".to_string(), true), ("my_res2".to_string(), true)] ); assert_eq!( get_printed_resources(&Command::new(&injected_path2).output().unwrap()), &[ Some(b"res1_content".as_slice()), Some(b"res2_content".as_slice()) ] ); } #[test] fn test_resource_existed() { let single_command = testbin_command("single"); let mut injected_path = temp_path(); inject( single_command.get_program(), "my_res", b"res_content", &mut injected_path, ) .unwrap(); let _path_guard: TempPath = TempPath::from_path(&injected_path); let mut injected_path2 = temp_path(); let inject_result = inject(injected_path, "my_res", b"res_content", &mut injected_path2); let _path_guard2: TempPath = TempPath::from_path(&injected_path2); assert!(inject_result .err() .unwrap() .to_string() .contains("already exists")) } #[test] fn test_duplicated_resource_declarations() { let mut dup_command = testbin_command("dup"); let output = dup_command.output().unwrap(); assert_eq!(get_printed_resources(&output), &[None, None]); let resources = list(dup_command.get_program()).unwrap(); assert_eq!(&resources, &[("my_res".to_string(), false)]); let mut injected_path = temp_path(); inject( dup_command.get_program(), "my_res", b"res_content", &mut injected_path, ) .unwrap(); let resources = list(&injected_path).unwrap(); assert_eq!(&resources, &[("my_res".to_string(), true)]); let _path_guard = TempPath::from_path(&injected_path); let output = Command::new(injected_path).output().unwrap(); assert_eq!( get_printed_resources(&output), &[ Some(b"res_content".as_slice()), Some(b"res_content".as_slice()) ] ); } #[test] #[cfg_attr(target_pointer_width = "32", ignore)] fn test_large_resource() { let large_resource = vec![0u8; 1 * 1024 * 1024 * 1024]; let single_command = testbin_command("single"); let mut injected_path = temp_path(); inject( single_command.get_program(), "my_res", &large_resource, &mut injected_path, ) .unwrap(); let _path_guard = TempPath::from_path(&injected_path); let resources = list(&injected_path).unwrap(); assert_eq!(&resources, &[("my_res".to_string(), true)]); let output = Command::new(injected_path).output().unwrap(); assert_eq!( get_printed_resources(&output), &[Some(large_resource.as_slice())] ); }