changeset 1537:6daad5c31f52

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
author Jiri Vanek <jvanek@redhat.com>
date Mon, 14 Jan 2019 13:02:58 +0100
parents f358ea7a6377
children 67eb4fc36fa0
files ChangeLog rust-launcher/src/main.rs rust-launcher/src/utils.rs
diffstat 3 files changed, 193 insertions(+), 29 deletions(-) [+]
line wrap: on
line diff
--- 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 <jvanek@redhat.com>
+
+	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 <jvanek@redhat.com>
 
 	Added detection of JDK from PATH
--- 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<String> = 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<String>, os: &os_access::Os) -> Vec<String> {
     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(&current_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(&current_name);
     bin_location.push_str(&dirs_paths_helper::path_to_string(&current_bin));
 
-    let a = env::args();
-    let s = a.skip(1);
-    let c: std::vec::Vec<String> = 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<std::string::String>, target: &mut Vec<std::string::String>) {
+    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<std::string::String>, target: &mut Vec<std::string::String>, 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<std::string::String> = vec![];
+        let mut result: Vec<std::string::String> = Vec::new();
+        let ex: Vec<std::string::String> = 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<std::string::String> = vec![];
+        let mut result: Vec<std::string::String> = Vec::new();
+        let ex: Vec<std::string::String> = Vec::new();
+        super::include_dashJs_values(&switches, &mut result, &tu::TestLogger::create_new());
+        assert_eq!(ex, result);
+    }
 }
 
 
--- 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<std::path::PathBuf> {
-    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<OsString>, libsearch: hardcoded_paths::ItwLibSearch, os: &os_access::Os) -> Option<std::path::PathBuf> {
     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<std::path::PathBuf> {
-    env::var_os("PATH").and_then(|paths| {
+
+fn get_jdk_from_given_path_testable(system_path: Option<OsString>, os: &os_access::Os) -> Option<std::path::PathBuf> {
+    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<Vec<String>>,
@@ -185,7 +252,7 @@
         fn get_classpath_separator(&self) -> char { ':' }
 
         fn get_exec_suffixes(&self) -> &'static [&'static str] {
-            panic!("not implemented");
+            &[""]
         }
     }