# HG changeset patch # User Jiri Vanek # Date 1547467378 -3600 # Node ID 6daad5c31f52f6d3b81a8126666e1ad4b4d5a4c0 # Parent f358ea7a637724d5d30ca0eb86f01897cd18f97e Refactored arranging of arguments and finding jre on path to be testable * rust-launcher/src/main.rs: introduced compose_arguments, include_not_dashJs, include_dashJs_values; used, tested * rust-launcher/src/utils.rs: introduced get_jdk_from_path_conditionally_testable and get_jdk_from_given_path_testable; used, tested diff -r f358ea7a6377 -r 6daad5c31f52 ChangeLog --- a/ChangeLog Mon Jan 14 10:24:14 2019 +0100 +++ b/ChangeLog Mon Jan 14 13:02:58 2019 +0100 @@ -1,3 +1,12 @@ +2019-01-14 Jiri Vanek + + Refactored arranging of arguments and finding jre on path to be testable + * rust-launcher/src/main.rs: introduced compose_arguments, include_not_dashJs, + include_dashJs_values; used, tested + * rust-launcher/src/utils.rs: introduced get_jdk_from_path_conditionally_testable and + get_jdk_from_given_path_testable; used, tested + + 2019-01-14 Jiri Vanek Added detection of JDK from PATH diff -r f358ea7a6377 -r 6daad5c31f52 rust-launcher/src/main.rs --- a/rust-launcher/src/main.rs Mon Jan 14 10:24:14 2019 +0100 +++ b/rust-launcher/src/main.rs Mon Jan 14 13:02:58 2019 +0100 @@ -36,12 +36,23 @@ write!(&mut info2, "selected jre: {}", java_dir.display()).expect("unwrap failed"); os.info(&info2); + let a = env::args(); + let s = a.skip(1); + let c: std::vec::Vec = s.collect(); + + let mut child = os.spawn_java_process(&java_dir, &compose_arguments(&java_dir, &c, &os)); + let ecode = child.wait().expect("failed to wait on child"); + let code = ecode.code().expect("code should be always here"); + std::process::exit(code) +} + +fn compose_arguments(java_dir: &std::path::PathBuf, original_args: &std::vec::Vec, os: &os_access::Os) -> Vec { let hard_bootcp = hardcoded_paths::get_bootcp(); - let bootcp = jars_helper::get_bootclasspath(&java_dir, &os); - let cp = jars_helper::get_classpath(&java_dir, &os); + let bootcp = jars_helper::get_bootclasspath(&java_dir, os); + let cp = jars_helper::get_classpath(&java_dir, os); let current_name = dirs_paths_helper::current_program_name(); let current_bin = dirs_paths_helper::current_program(); - info2 = String::new(); + let mut info2 = String::new(); write!(&mut info2, "itw-rust-debug: exemplar boot classpath: {}", hard_bootcp).expect("unwrap failed"); os.log(&info2); info2 = String::new(); @@ -63,28 +74,16 @@ write!(&mut info2, "itw-rust-debug: current bin: {}", &dirs_paths_helper::path_to_string(¤t_bin)).expect("unwrap failed"); os.log(&info2); - let splash = jars_helper::resolve_splash(&os); + let splash = jars_helper::resolve_splash(os); let mut bin_name = String::from("-Dicedtea-web.bin.name="); let mut bin_location = String::from("-Dicedtea-web.bin.location="); //no metter what ITW_LIBS are saying, imho using current pgm is always correct comapred to hardcoded values bin_name.push_str(¤t_name); bin_location.push_str(&dirs_paths_helper::path_to_string(¤t_bin)); - let a = env::args(); - let s = a.skip(1); - let c: std::vec::Vec = s.collect(); + let mut all_args = std::vec::Vec::new(); - let mut all_args = std::vec::Vec::new(); - for f in c.iter() { - if f.to_string().starts_with("-J") { - let s = String::from(f.to_string().get(2..).expect("-J should be substring-able by 2")); - if s.is_empty() { - os.info("Warning, empty -J switch") - } else { - all_args.push(s); - } - } - } + include_dashJs_values(&original_args, &mut all_args, os); all_args.push(bootcp); all_args.push(String::from("-classpath")); @@ -93,16 +92,105 @@ all_args.push(bin_location); all_args.push(hardcoded_paths::get_main().to_string()); - for f in c.iter() { + include_not_dashJs(&original_args, &mut all_args); + + all_args +} + +#[allow(non_snake_case)] +fn include_not_dashJs(srcs: &Vec, target: &mut Vec) { + for f in srcs.iter() { if !f.to_string().starts_with("-J") { - all_args.push(f.to_string()); + target.push(f.to_string()); + } + } +} + +#[allow(non_snake_case)] +fn include_dashJs_values(srcs: &Vec, target: &mut Vec, os: &os_access::Os) { + for f in srcs.iter() { + if f.to_string().starts_with("-J") { + let s = String::from(f.to_string().get(2..).expect("-J should be substring-able by 2")); + if s.is_empty() { + os.info("Warning, empty -J switch") + } else { + target.push(s); + } } } +} - let mut child = os.spawn_java_process(&java_dir, &all_args); - let ecode = child.wait().expect("failed to wait on child"); - let code = ecode.code().expect("code should be always here"); - std::process::exit(code) +#[cfg(test)] +pub mod tests_main { + use utils::tests_utils as tu; + + + #[test] + fn compose_arguments_test() { + // this test just ensures -Js are first, and all others are last, and something get betwen them + let switches = vec![ + String::from("-a"), + String::from("-J-b")]; + let result = super::compose_arguments(&std::path::PathBuf::from("/some/jre"),&switches, &tu::TestLogger::create_new()); + assert_eq!(result.len()>3, true); + assert_eq!(result.get(0).expect("first item should exists"), &String::from("-b")); + assert_eq!(result.get(result.len()-1).expect("last item should exists"), &String::from("-a")); + + } + + #[test] + #[allow(non_snake_case)] + fn include_not_dashJs_test() { + let switches = vec![ + String::from("-J-a"), + String::from("-b"), + String::from("--Jc"), + String::from("d")]; + let mut result = Vec::new(); + super::include_not_dashJs(&switches, &mut result); + let ex = vec![ + String::from("-b"), + String::from("--Jc"), + String::from("d")]; + assert_eq!(ex, result); + } + + #[test] + #[allow(non_snake_case)] + fn include_not_dashJs_test_empty() { + let switches: Vec = vec![]; + let mut result: Vec = Vec::new(); + let ex: Vec = Vec::new(); + super::include_not_dashJs(&switches, &mut result); + assert_eq!(ex, result); + } + + + #[test] + #[allow(non_snake_case)] + fn include_dashJs_valuess_test() { + let switches = vec![ + String::from("-J-a"), + String::from("-b"), + String::from("--Jc"), + String::from("-Jd")]; + let mut result = Vec::new(); + super::include_dashJs_values(&switches, &mut result, &tu::TestLogger::create_new()); + let ex = vec![ + String::from("-a"), + String::from("d")]; + assert_eq!(ex, result); + } + + #[test] + #[allow(non_snake_case)] + fn include_dashJs_values_test_empty() { + let switches: Vec = vec![]; + let mut result: Vec = Vec::new(); + let ex: Vec = Vec::new(); + super::include_dashJs_values(&switches, &mut result, &tu::TestLogger::create_new()); + assert_eq!(ex, result); + } } diff -r f358ea7a6377 -r 6daad5c31f52 rust-launcher/src/utils.rs --- a/rust-launcher/src/utils.rs Mon Jan 14 10:24:14 2019 +0100 +++ b/rust-launcher/src/utils.rs Mon Jan 14 13:02:58 2019 +0100 @@ -1,4 +1,5 @@ use std; +use std::ffi::OsString; use env; use dirs_paths_helper; use os_access; @@ -51,7 +52,10 @@ } fn get_jdk_from_path_conditionally(os: &os_access::Os) -> Option { - let libsearch = hardcoded_paths::get_libsearch(os); + get_jdk_from_path_conditionally_testable(env::var_os("PATH"), hardcoded_paths::get_libsearch(os), os) +} + +fn get_jdk_from_path_conditionally_testable(system_path: Option, libsearch: hardcoded_paths::ItwLibSearch, os: &os_access::Os) -> Option { if libsearch == hardcoded_paths::ItwLibSearch::DISTRIBUTION { os.log("itw-rust-debug: skipping jdk from path, your build is distribution"); None @@ -59,12 +63,13 @@ if libsearch == hardcoded_paths::ItwLibSearch::BOTH { os.info("your build is done as BOTH distribution and bundled, jdk from PATH may be not what you want!"); } - get_jdk_from_path(os) + get_jdk_from_given_path_testable(system_path, os) } } -fn get_jdk_from_path(os: &os_access::Os) -> Option { - env::var_os("PATH").and_then(|paths| { + +fn get_jdk_from_given_path_testable(system_path: Option, os: &os_access::Os) -> Option { + system_path.and_then(|paths| { env::split_paths(&paths).filter_map(|dir| { for suffix in os.get_exec_suffixes() { let mut bin_name = String::new(); @@ -128,6 +133,68 @@ use os_access; use std::cell::RefCell; use dirs_paths_helper; + use hardcoded_paths; + use std::ffi::OsString as fo; + + #[test] + fn try_none_jre_from_path() { + assert_eq!(super::get_jdk_from_path_conditionally_testable(None, hardcoded_paths::ItwLibSearch::DISTRIBUTION, &TestLogger::create_new()), + None); + assert_eq!(super::get_jdk_from_path_conditionally_testable(None, hardcoded_paths::ItwLibSearch::BUNDLED, &TestLogger::create_new()), + None); + assert_eq!(super::get_jdk_from_path_conditionally_testable(None, hardcoded_paths::ItwLibSearch::BOTH, &TestLogger::create_new()), + None); + assert_eq!(super::get_jdk_from_path_conditionally_testable(Some(fo::from("/some/bad/path")), hardcoded_paths::ItwLibSearch::DISTRIBUTION, &TestLogger::create_new()), + None); + assert_eq!(super::get_jdk_from_path_conditionally_testable(Some(fo::from("/some/bad/path")), hardcoded_paths::ItwLibSearch::BUNDLED, &TestLogger::create_new()), + None); + assert_eq!(super::get_jdk_from_path_conditionally_testable(Some(fo::from("/some/bad/path")), hardcoded_paths::ItwLibSearch::BOTH, &TestLogger::create_new()), + None); + } + + #[test] + fn try_jre_exists_on_path() { + let top_dir = fake_jre(true); + let mut master_dir = top_dir.clone(); + master_dir.push("bin"); + let v1 = super::get_jdk_from_path_conditionally_testable(Some(fo::from(master_dir.clone())), hardcoded_paths::ItwLibSearch::DISTRIBUTION, &TestLogger::create_new()); + let v2 = super::get_jdk_from_path_conditionally_testable(Some(fo::from(master_dir.clone())), hardcoded_paths::ItwLibSearch::BUNDLED, &TestLogger::create_new()); + let v3 = super::get_jdk_from_path_conditionally_testable(Some(fo::from(master_dir.clone())), hardcoded_paths::ItwLibSearch::BOTH, &TestLogger::create_new()); + debuggable_remove_dir(&master_dir); + assert_eq!(None, v1); + assert_eq!(Some(top_dir.clone()), v2); + assert_eq!(Some(top_dir.clone()), v3); + } + + #[test] + fn try_jre_dir_on_path_exists_but_no_java() { + let master_dir = fake_jre(false); + let v1 = super::get_jdk_from_path_conditionally_testable(Some(fo::from(master_dir.clone())), hardcoded_paths::ItwLibSearch::DISTRIBUTION, &TestLogger::create_new()); + let v2 = super::get_jdk_from_path_conditionally_testable(Some(fo::from(master_dir.clone())), hardcoded_paths::ItwLibSearch::BUNDLED, &TestLogger::create_new()); + let v3 = super::get_jdk_from_path_conditionally_testable(Some(fo::from(master_dir.clone())), hardcoded_paths::ItwLibSearch::BOTH, &TestLogger::create_new()); + debuggable_remove_dir(&master_dir); + assert_eq!(None, v1); + assert_eq!(None, v2); + assert_eq!(None, v3); + } + + #[test] + fn try_jre_dir_java_on_path_but_no_bin() { + let mut fake_jre = create_tmp_file(); + debuggable_remove_file(&fake_jre); + let master_dir = fake_jre.clone(); + std::fs::create_dir(&fake_jre).expect("dir creation failed"); + fake_jre.push("java"); + File::create(&fake_jre).expect("File created"); + let v1 = super::get_jdk_from_path_conditionally_testable(Some(fo::from(master_dir.clone())), hardcoded_paths::ItwLibSearch::DISTRIBUTION, &TestLogger::create_new()); + let v2 = super::get_jdk_from_path_conditionally_testable(Some(fo::from(master_dir.clone())), hardcoded_paths::ItwLibSearch::BUNDLED, &TestLogger::create_new()); + let v3 = super::get_jdk_from_path_conditionally_testable(Some(fo::from(master_dir.clone())), hardcoded_paths::ItwLibSearch::BOTH, &TestLogger::create_new()); + debuggable_remove_dir(&master_dir); + assert_eq!(None, v1); + let parent = std::path::PathBuf::from(master_dir.parent().expect("just created")); + assert_eq!(Some(parent.clone()), v2); + assert_eq!(Some(parent.clone()), v3); + } pub struct TestLogger { vec: RefCell>, @@ -185,7 +252,7 @@ fn get_classpath_separator(&self) -> char { ':' } fn get_exec_suffixes(&self) -> &'static [&'static str] { - panic!("not implemented"); + &[""] } }