From 4e663706f353164b450e76ac67ecf62a1b2e9423 Mon Sep 17 00:00:00 2001 From: Gene Johnston Date: Tue, 22 Feb 2022 14:11:58 -0500 Subject: [PATCH 01/13] Instead of showing command, run background process Signed-off-by: Gene Johnston --- zowex/src/main.rs | 278 +++++++++++++++++++++++++++++++++------------- 1 file changed, 201 insertions(+), 77 deletions(-) diff --git a/zowex/src/main.rs b/zowex/src/main.rs index e82abefa91..a310de2c67 100644 --- a/zowex/src/main.rs +++ b/zowex/src/main.rs @@ -14,24 +14,27 @@ use std::env; use std::io; use std::io::BufReader; use std::io::prelude::*; -use std::net::Shutdown; use std::process::{Command, Stdio}; use std::str; use std::thread; use std::time::Duration; -#[cfg(target_family = "unix")] -use std::os::unix::net::UnixStream; - extern crate atty; use atty::Stream; extern crate base64; use base64::encode; +#[cfg(target_family = "unix")] extern crate home; +#[cfg(target_family = "unix")] use home::home_dir; +#[cfg(target_family = "unix")] +use std::net::Shutdown; +#[cfg(target_family = "unix")] +use std::os::unix::net::UnixStream; + #[cfg(target_family = "windows")] extern crate named_pipe; #[cfg(target_family = "windows")] @@ -61,7 +64,9 @@ const EXIT_CODE_TIMEOUT_CONNECT_TO_RUNNING_DAEMON: i32 = 104; const EXIT_CODE_DAEMON_NOT_RUNNING_AFTER_START: i32 = 105; const EXIT_CODE_DAEMON_FAILED_TO_RUN_CMD: i32 = 106; const EXIT_CODE_FAILED_TO_RUN_NODEJS_CMD: i32 = 107; -const EXIT_CODE_CANT_RUN_DAEMON_CMD: i32 = 108; +const EXIT_CODE_CANT_FIND_CMD_SHELL: i32 = 109; +const EXIT_CODE_UNKNOWN_CMD_SHELL: i32 = 109; + struct DaemonProcInfo { is_running: bool, @@ -92,6 +97,15 @@ struct DaemonResponse { user: Option, } +enum CmdShell { + Bash, // Bourne Again SHell + PowerShellDotNet, // Newer cross-platform .NET Core PowerShell + PowerShellExe, // Legacy Windows executable PowerShell (version 5.x) + WindowsCmd, // Classic Windows CMD shell + Unknown, // A command shell that we do not yet understand + CantFindProcess // Unable to find our parent process in the process list +} + const THREE_SEC_DELAY: u64 = 3; const THREE_MIN_OF_RETRIES: i32 = 60; @@ -118,8 +132,8 @@ fn main() -> io::Result<()> { std::process::exit(EXIT_CODE_SUCCESS); } - // daemon commands that overwrite our executable cannot be run by our executable - exit_when_alt_cmd_needed(&_args); + // Run those only commands which must be run by a background script. + run_delayed_zowe_command_and_exit(&_args); if user_wants_daemon() { // send command to the daemon @@ -161,75 +175,6 @@ fn main() -> io::Result<()> { } } -/** - * Determine if the command to run is a "zowe daemon" command that we cannot - * run from our executable. For such commands, display a zowe NodeJs command - * that can be run instead, and exit the current command. - * - * @param cmd_line_args - * The user-supplied command line arguments to the zowe command. - * Each argument is in its own vector element. - */ -fn exit_when_alt_cmd_needed(cmd_line_args: &[String]) { - // commands other than daemon commands can be run by our exe - if cmd_line_args.len() < 2 { - return; - } - if cmd_line_args[0] != "daemon" { - return; - } - if cmd_line_args[1] != "enable" && cmd_line_args[1] != "disable" { - return; - } - - // we can run any of the help requests for the daemon commands - if cmd_line_args.len() >= 3 { - let third_parm: &str = cmd_line_args[2].as_str(); - match third_parm { - "--help" | "-h" | "--h" | "--help-web" | "--hw" | "--help-examples" => return, - _ => { /* pass on through to next statement */ } - } - } - - // show the NodeJS zowe command that the user can run instead - println!("You cannot run this 'daemon' command while using the Zowe CLI native executable."); - println!("Copy and paste the following command instead:"); - - // - let mut zowe_cmd_to_show = String::new(); - if env::consts::OS == "windows" { - // We use COMSPEC so that the command will work for CMD and PowerShell - match env::var("COMSPEC") { - Ok(comspec_val) => { - if !comspec_val.is_empty() { - if comspec_val.contains(' ') { - zowe_cmd_to_show.push('"'); - zowe_cmd_to_show.push_str(&comspec_val); - zowe_cmd_to_show.push('"'); - } else { - zowe_cmd_to_show.push_str(&comspec_val); - } - zowe_cmd_to_show.push_str(" /C "); - } - }, - Err(_e) => { /* do not add COMSPEC */ }, - } - } - - // add the zowe nodeJS path to our command - let njs_zowe_path = get_nodejs_zowe_path(); - if njs_zowe_path.contains(' ') { - zowe_cmd_to_show.push('"'); - zowe_cmd_to_show.push_str(&njs_zowe_path); - zowe_cmd_to_show.push('"'); - } else { - zowe_cmd_to_show.push_str(&njs_zowe_path); - } - println!("{} {}", zowe_cmd_to_show, arg_vec_to_string(cmd_line_args)); - - std::process::exit(EXIT_CODE_CANT_RUN_DAEMON_CMD); -} - /** * Convert a vector of command line arguments into a single string of arguments. * @param cmd_line_args @@ -302,7 +247,7 @@ fn run_daemon_command(args: &mut Vec) -> io::Result<()> { } println!("The Zowe daemon is in use, retrying ({} of {})", tries, THREE_MIN_OF_RETRIES); - + // pause between attempts to connect thread::sleep(Duration::from_secs(THREE_SEC_DELAY)); tries += 1; @@ -595,6 +540,58 @@ fn get_nodejs_zowe_path() -> String { njs_zowe_path } +/** + * Get the command shell under which we are running. + * + * @returns A tuple consisting of the following: + * First is the type of the command shell + * Second is the name of the process for that command shell + */ +fn get_cmd_shell() -> (CmdShell, String) { + let mut cmd_shell_type: CmdShell = CmdShell::CantFindProcess; + let mut cmd_shell_nm: String = "CantGetName".to_string(); + let my_pid: u32 = std::process::id(); + + // establish the system process list + let mut sys = System::new_all(); + sys.refresh_all(); + + // loop though the process list to find our process ID + for (pid, process) in sys.processes() { + if pid == &(my_pid as usize) { + let my_parent_pid: Option = process.parent(); + + // loop though the process list to find our parent process ID + for (par_pid, par_process) in sys.processes() { + if *par_pid == my_parent_pid.unwrap() { + cmd_shell_nm = par_process.name().to_string(); + + // Set any known command shell name + if cmd_shell_nm.to_lowercase().contains("bash") { + cmd_shell_type = CmdShell::Bash; + + } else if cmd_shell_nm.to_lowercase().contains("pwsh") { + cmd_shell_type = CmdShell::PowerShellDotNet; + + } else if cmd_shell_nm.to_lowercase().contains("powershell") { + cmd_shell_type = CmdShell::PowerShellExe; + + } else if cmd_shell_nm.to_lowercase().contains("cmd") { + cmd_shell_type = CmdShell::WindowsCmd; + + } else { + cmd_shell_type = CmdShell::Unknown; + } + break; // after we find par_pid, stop seaching process list + } + } + break; // after we find my_pid, stop seaching process list + } + } + + (cmd_shell_type, cmd_shell_nm) +} + /** * Is the zowe daemon currently running? * @returns A structure that indicates if the daemon is running, and if so @@ -695,6 +692,133 @@ fn run_nodejs_command(cmd_line_args: &mut Vec) -> Result { Ok(exit_code) } +/** + * Launch a zowe script in the background so that our EXE can exit before + * the script takes action on the EXE. We use ping to cause a delay in the + * script which allows our EXE to terminate before the zowe node.js program + * (which we launch) writes (or deletes) our EXE. + * + * When our EXE exits, the user will get a new prompt immediately, but the + * background output will be displayed after that prompt. + * + * Under PowerShell, our script first displays some newlines to make some + * space on the screen. When the user eventually presses ENTER, the prompt + * will display in the space that we made. If the user presses ENTER enough + * times, the prompts will overwite the output of the background script. + * That is harmless, but it is a little ugly. However, we have no means to + * control this PowerShell behavior. + * + * @param cmd_line_args + * The user-supplied command line arguments to the zowe command. + * + * @returns + * This function returns nothing when it runs no command. + * If it runs a command, it exits with 0 for success, or it exits + * with an error code for failing to launch the NodeJs zowe command. + */ +fn run_delayed_zowe_command_and_exit(cmd_line_args: &[String]) { + // Ony run delayed zowe script for specific commands + if cmd_line_args.len() >= 2 && + cmd_line_args[0] == "daemon" && + (cmd_line_args[1] == "enable" || cmd_line_args[1] == "disable") + { + // determine the command shell under which we are running + let (curr_cmd_shell, cmd_shell_nm) = get_cmd_shell(); + if matches!(curr_cmd_shell, CmdShell::CantFindProcess) { + println!("Unable to find the current command shell in the process list. Terminating."); + std::process::exit(EXIT_CODE_CANT_FIND_CMD_SHELL); + } + if matches!(curr_cmd_shell, CmdShell::Unknown) { + println!("The command shell process named '{}' is unknown to the Zowe CLI. Terminating.", cmd_shell_nm); + std::process::exit(EXIT_CODE_UNKNOWN_CMD_SHELL); + } + + let njs_zowe_path = get_nodejs_zowe_path(); + + // form the command line for the CMD script that we will launch. + let cmd_shell_to_launch: String; + let mut args_for_cmd_script = vec![]; + if env::consts::OS == "windows" { + cmd_shell_to_launch = "CMD".to_string(); + args_for_cmd_script.push("/C"); + args_for_cmd_script.push("echo."); + args_for_cmd_script.push("&&"); + + if matches!(curr_cmd_shell, CmdShell::PowerShellDotNet | CmdShell::PowerShellExe) { + // Powereshell needs extra newlines before the background process output + for next_arg in [ + "echo.", "&&", "echo.", "&&", "echo.", "&&", + "echo.", "&&", "echo.", "&&", "echo.", "&&" + ] { + args_for_cmd_script.push(next_arg); + } + } else if matches!(curr_cmd_shell, CmdShell::Bash) { + // bash on windows needs a newline + for next_arg in [ + "sleep", "1", "&&", "echo.", "&&" + ] { + args_for_cmd_script.push(next_arg); + } + } + } else { + cmd_shell_to_launch = "bash".to_string(); + } + + // display a message, delay, then run zowe script + for next_arg in [ + "echo", "Wait", "to", "see", "the", "results", "below", "...", "&&", + "ping", "127.0.0.1", "-n", "1", ">nul", "&&", &*njs_zowe_path + ] { + args_for_cmd_script.push(next_arg); + } + for next_arg in cmd_line_args { + args_for_cmd_script.push(next_arg); + } + + // add a message after the script is done + args_for_cmd_script.push("&&"); + for next_arg in ["echo", "Now", "press", "ENTER", "to", "see", "your", "command"] { + args_for_cmd_script.push(next_arg); + } + if matches!(curr_cmd_shell, CmdShell::PowerShellDotNet | CmdShell::PowerShellExe) { + for next_arg in [ + "prompt", "in", "the", "open", "space", "above." + ] { + args_for_cmd_script.push(next_arg); + } + } else { + args_for_cmd_script.push("prompt."); + } + + // The following line gives useful debugging info when it is uncommented. + // println!("args_for_cmd_script = {:?}", args_for_cmd_script); + + println!("The '{}' command will run in the background ...", arg_vec_to_string(cmd_line_args)); + let exit_code: i32; + match Command::new(cmd_shell_to_launch) + .args(args_for_cmd_script) + .stdin(Stdio::inherit()) + .stdout(Stdio::inherit()) + .stderr(Stdio::inherit()) + .spawn() + { + Ok(..) => { + exit_code = EXIT_CODE_SUCCESS; + } + Err(error) => { + println!("Failed to run the following command:"); + println!( + " cmd_shell_to_launch = {}\n arguments = {:?}", + njs_zowe_path, cmd_line_args + ); + println!("Due to this error:\n {}", error); + exit_code = EXIT_CODE_FAILED_TO_RUN_NODEJS_CMD; + } + }; + std::process::exit(exit_code); + } // end if this is a command that we must run delayed +} + /** * Start the zowe daemon. * From 5204c5cc7c5fe027b365885c6fb8b8e23740b133 Mon Sep 17 00:00:00 2001 From: Gene Johnston Date: Tue, 22 Feb 2022 16:48:15 -0500 Subject: [PATCH 02/13] Recognize the "sh" command shell. Use a non-success command separator before our final user message after a background script runs. Signed-off-by: Gene Johnston --- zowex/src/main.rs | 34 +++++++++++++++++++++------------- 1 file changed, 21 insertions(+), 13 deletions(-) diff --git a/zowex/src/main.rs b/zowex/src/main.rs index a310de2c67..3028142da7 100644 --- a/zowex/src/main.rs +++ b/zowex/src/main.rs @@ -99,6 +99,7 @@ struct DaemonResponse { enum CmdShell { Bash, // Bourne Again SHell + Sh, // Standard Linux shell PowerShellDotNet, // Newer cross-platform .NET Core PowerShell PowerShellExe, // Legacy Windows executable PowerShell (version 5.x) WindowsCmd, // Classic Windows CMD shell @@ -567,16 +568,19 @@ fn get_cmd_shell() -> (CmdShell, String) { cmd_shell_nm = par_process.name().to_string(); // Set any known command shell name - if cmd_shell_nm.to_lowercase().contains("bash") { + if cmd_shell_nm.to_lowercase().starts_with("bash") { cmd_shell_type = CmdShell::Bash; - } else if cmd_shell_nm.to_lowercase().contains("pwsh") { + } else if cmd_shell_nm.to_lowercase().starts_with("sh") { + cmd_shell_type = CmdShell::Sh; + + } else if cmd_shell_nm.to_lowercase().starts_with("pwsh") { cmd_shell_type = CmdShell::PowerShellDotNet; - } else if cmd_shell_nm.to_lowercase().contains("powershell") { + } else if cmd_shell_nm.to_lowercase().starts_with("powershell") { cmd_shell_type = CmdShell::PowerShellExe; - } else if cmd_shell_nm.to_lowercase().contains("cmd") { + } else if cmd_shell_nm.to_lowercase().starts_with("cmd") { cmd_shell_type = CmdShell::WindowsCmd; } else { @@ -738,36 +742,40 @@ fn run_delayed_zowe_command_and_exit(cmd_line_args: &[String]) { // form the command line for the CMD script that we will launch. let cmd_shell_to_launch: String; let mut args_for_cmd_script = vec![]; + const CMD_WORKED_SEP: &str = "&&"; + let cmd_continue_sep: &str; if env::consts::OS == "windows" { cmd_shell_to_launch = "CMD".to_string(); + cmd_continue_sep = "&"; args_for_cmd_script.push("/C"); args_for_cmd_script.push("echo."); - args_for_cmd_script.push("&&"); + args_for_cmd_script.push(CMD_WORKED_SEP); if matches!(curr_cmd_shell, CmdShell::PowerShellDotNet | CmdShell::PowerShellExe) { // Powereshell needs extra newlines before the background process output for next_arg in [ - "echo.", "&&", "echo.", "&&", "echo.", "&&", - "echo.", "&&", "echo.", "&&", "echo.", "&&" + "echo.", CMD_WORKED_SEP, "echo.", CMD_WORKED_SEP, "echo.", CMD_WORKED_SEP, + "echo.", CMD_WORKED_SEP, "echo.", CMD_WORKED_SEP, "echo.", CMD_WORKED_SEP ] { args_for_cmd_script.push(next_arg); } - } else if matches!(curr_cmd_shell, CmdShell::Bash) { - // bash on windows needs a newline + } else if matches!(curr_cmd_shell, CmdShell::Bash | CmdShell::Sh) { + // Unix shells on windows need a newline for next_arg in [ - "sleep", "1", "&&", "echo.", "&&" + "sleep", "1", CMD_WORKED_SEP, "echo.", CMD_WORKED_SEP ] { args_for_cmd_script.push(next_arg); } } } else { cmd_shell_to_launch = "bash".to_string(); + cmd_continue_sep = ";"; } // display a message, delay, then run zowe script for next_arg in [ - "echo", "Wait", "to", "see", "the", "results", "below", "...", "&&", - "ping", "127.0.0.1", "-n", "1", ">nul", "&&", &*njs_zowe_path + "echo", "Wait", "to", "see", "the", "results", "below", "...", CMD_WORKED_SEP, + "ping", "127.0.0.1", "-n", "1", ">nul", CMD_WORKED_SEP, &*njs_zowe_path ] { args_for_cmd_script.push(next_arg); } @@ -776,7 +784,7 @@ fn run_delayed_zowe_command_and_exit(cmd_line_args: &[String]) { } // add a message after the script is done - args_for_cmd_script.push("&&"); + args_for_cmd_script.push(cmd_continue_sep); for next_arg in ["echo", "Now", "press", "ENTER", "to", "see", "your", "command"] { args_for_cmd_script.push(next_arg); } From f114e414113375ed1978f2a9846e8226c84519a4 Mon Sep 17 00:00:00 2001 From: Gene Johnston Date: Tue, 22 Feb 2022 17:15:00 -0500 Subject: [PATCH 03/13] Test Zowex runs enable & disable in background Signed-off-by: Gene Johnston --- .../cli.zowe.exe.integration.test.ts | 27 +++++++++++-------- 1 file changed, 16 insertions(+), 11 deletions(-) diff --git a/packages/cli/__tests__/daemon/__integration__/cli.zowe.exe.integration.test.ts b/packages/cli/__tests__/daemon/__integration__/cli.zowe.exe.integration.test.ts index 9a77ec253b..f88e735d79 100644 --- a/packages/cli/__tests__/daemon/__integration__/cli.zowe.exe.integration.test.ts +++ b/packages/cli/__tests__/daemon/__integration__/cli.zowe.exe.integration.test.ts @@ -20,9 +20,9 @@ import { TestEnvironment } from "../../../../../__tests__/__src__/environment/Te let testEnvironment: ITestEnvironment; describe("Zowe native executable", () => { - const exeCantRunDaemonMsg1: string = "You cannot run this 'daemon' command while using the Zowe CLI native executable."; - const exeCantRunDaemonMsg2: string = "Copy and paste the following command instead:"; - const EXIT_CODE_CANT_RUN_DAEMON_CMD: number = 108; + const RUN_IN_BACKGROUND_MSG: string = "command will run in the background ..."; + const WAIT_TO_SEE_RESULTS_MSG: string = "Wait to see the results below ..."; + const NOW_PRESS_ENTER_MSG: string = "Now press ENTER to see your command prompt."; let zoweExePath: string; let willRunZoweExe: boolean = true; @@ -67,29 +67,34 @@ describe("Zowe native executable", () => { } }); - it("should refuse to run the enable command", async () => { + it("should run the enable command in the background", async () => { if (willRunZoweExe) { const response = runCliScript( __dirname + "/__scripts__/run_zowe_exe.sh", testEnvironment, [zoweExePath, "daemon", "enable"] ); const stdoutStr = response.stdout.toString(); - expect(stdoutStr).toContain(exeCantRunDaemonMsg1); - expect(stdoutStr).toContain(exeCantRunDaemonMsg2); - expect(response.status).toBe(EXIT_CODE_CANT_RUN_DAEMON_CMD); + expect(stdoutStr).toContain(RUN_IN_BACKGROUND_MSG); + expect(stdoutStr).toContain(WAIT_TO_SEE_RESULTS_MSG); + expect(stdoutStr).toContain("Zowe CLI daemon mode is enabled"); + expect(stdoutStr).toContain("Zowe CLI native executable version ="); + expect(stdoutStr).toContain(NOW_PRESS_ENTER_MSG); + expect(response.status).toBe(0); } }); - it("should refuse to run the disable command", async () => { + it("should run the disable command in the background", async () => { if (willRunZoweExe) { const response = runCliScript( __dirname + "/__scripts__/run_zowe_exe.sh", testEnvironment, [zoweExePath, "daemon", "disable"] ); const stdoutStr = response.stdout.toString(); - expect(stdoutStr).toContain(exeCantRunDaemonMsg1); - expect(stdoutStr).toContain(exeCantRunDaemonMsg2); - expect(response.status).toBe(EXIT_CODE_CANT_RUN_DAEMON_CMD); + expect(stdoutStr).toContain(RUN_IN_BACKGROUND_MSG); + expect(stdoutStr).toContain(WAIT_TO_SEE_RESULTS_MSG); + expect(stdoutStr).toContain("Zowe CLI daemon mode is disabled"); + expect(stdoutStr).toContain(NOW_PRESS_ENTER_MSG); + expect(response.status).toBe(0); } }); }); From 7d897134e1cb8486d03a696a886798270dbc21b2 Mon Sep 17 00:00:00 2001 From: Gene Johnston Date: Fri, 25 Feb 2022 16:52:59 -0500 Subject: [PATCH 04/13] Change background enable/disable to run on Linux. Signed-off-by: Gene Johnston --- zowex/Cargo.lock | 13 ++- zowex/Cargo.toml | 5 +- zowex/src/main.rs | 258 +++++++++++++++++++++++++++++----------------- 3 files changed, 179 insertions(+), 97 deletions(-) diff --git a/zowex/Cargo.lock b/zowex/Cargo.lock index 487ba2615d..232c84a48a 100644 --- a/zowex/Cargo.lock +++ b/zowex/Cargo.lock @@ -302,6 +302,12 @@ dependencies = [ "serde", ] +[[package]] +name = "simple-error" +version = "0.2.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cc47a29ce97772ca5c927f75bac34866b16d64e07f330c3248e2d7226623901b" + [[package]] name = "syn" version = "1.0.81" @@ -315,9 +321,9 @@ dependencies = [ [[package]] name = "sysinfo" -version = "0.22.5" +version = "0.23.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7f1bfab07306a27332451a662ca9c8156e3a9986f82660ba9c8e744fe8455d43" +checksum = "9339fea9ca4725be840dd294b24156ba4fe7aa6b86deac222e99954757ee15e9" dependencies = [ "cfg-if", "core-foundation-sys", @@ -432,7 +438,7 @@ checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f" [[package]] name = "zowe" -version = "0.7.0" +version = "0.8.0" dependencies = [ "atty", "base64", @@ -442,6 +448,7 @@ dependencies = [ "rpassword", "serde", "serde_json", + "simple-error", "sysinfo", "whoami", ] diff --git a/zowex/Cargo.toml b/zowex/Cargo.toml index fe6deabd5d..106ffdfe38 100644 --- a/zowex/Cargo.toml +++ b/zowex/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "zowe" -version = "0.7.0" +version = "0.8.0" authors = ["Zowe Project"] edition = "2018" license = "EPL-2.0" @@ -16,7 +16,8 @@ pathsearch = "0.2.0" rpassword = "5.0.1" serde = { version = "1.0.130", features = ["derive"]} serde_json = "1.0.69" -sysinfo = "0.22.5" +simple-error = "0.2.3" +sysinfo = "0.23.3" whoami = "1.2.1" [target.'cfg(windows)'.dependencies] diff --git a/zowex/src/main.rs b/zowex/src/main.rs index 3028142da7..fd1b04f926 100644 --- a/zowex/src/main.rs +++ b/zowex/src/main.rs @@ -50,11 +50,14 @@ extern crate serde; use serde::{Deserialize, Serialize}; extern crate sysinfo; -use sysinfo::{ProcessExt, System, SystemExt}; +use sysinfo::{PidExt, Pid, ProcessExt, System, SystemExt}; extern crate whoami; use whoami::username; +extern crate simple_error; +use simple_error::SimpleError; + const EXIT_CODE_SUCCESS: i32 = 0; const EXIT_CODE_CANNOT_CONNECT_TO_RUNNING_DAEMON: i32 = 100; const EXIT_CODE_CANNOT_GET_MY_PATH: i32 = 101; @@ -67,7 +70,6 @@ const EXIT_CODE_FAILED_TO_RUN_NODEJS_CMD: i32 = 107; const EXIT_CODE_CANT_FIND_CMD_SHELL: i32 = 109; const EXIT_CODE_UNKNOWN_CMD_SHELL: i32 = 109; - struct DaemonProcInfo { is_running: bool, name: String, @@ -100,11 +102,14 @@ struct DaemonResponse { enum CmdShell { Bash, // Bourne Again SHell Sh, // Standard Linux shell + Korn, // Korn shell + Zshell, // Z shell + Cshell, // C shell + Tenex, // TENEX C shell PowerShellDotNet, // Newer cross-platform .NET Core PowerShell PowerShellExe, // Legacy Windows executable PowerShell (version 5.x) WindowsCmd, // Classic Windows CMD shell - Unknown, // A command shell that we do not yet understand - CantFindProcess // Unable to find our parent process in the process list + Unknown // A command shell that we do not yet understand } const THREE_SEC_DELAY: u64 = 3; @@ -178,8 +183,8 @@ fn main() -> io::Result<()> { /** * Convert a vector of command line arguments into a single string of arguments. - * @param cmd_line_args - * The user-supplied command line arguments to the zowe command. + * @param arg_vec + * The user-supplied command line arguments. * Each argument is in its own vector element. * @returns * A String containing all of the command line arguments. @@ -544,27 +549,39 @@ fn get_nodejs_zowe_path() -> String { /** * Get the command shell under which we are running. * - * @returns A tuple consisting of the following: - * First is the type of the command shell - * Second is the name of the process for that command shell + * @returns A Result, which upon success contains a tuple: + * The first item is the type of the command shell + * The second item is the name of the process for that command shell. + * + * Upon failure the Result contains a SimpleError. */ -fn get_cmd_shell() -> (CmdShell, String) { - let mut cmd_shell_type: CmdShell = CmdShell::CantFindProcess; - let mut cmd_shell_nm: String = "CantGetName".to_string(); - let my_pid: u32 = std::process::id(); +fn get_cmd_shell() -> Result<(CmdShell, String), SimpleError> { + let mut cmd_shell_type: CmdShell = CmdShell::Unknown; + let mut cmd_shell_nm: String = "UnknownCmdShell".to_string(); + let my_pid: Pid = Pid::from_u32(std::process::id()); // establish the system process list let mut sys = System::new_all(); sys.refresh_all(); // loop though the process list to find our process ID - for (pid, process) in sys.processes() { - if pid == &(my_pid as usize) { - let my_parent_pid: Option = process.parent(); + let mut found_my_pid: bool = false; + for (next_pid, process) in sys.processes() { + if next_pid == &my_pid { + found_my_pid = true; + let my_parent_pid: Pid; + match process.parent() { + Some(parent_id) => my_parent_pid = parent_id, + None => { + return Err(SimpleError::new("Got invalid parent process ID from the process list.")); + } + } // loop though the process list to find our parent process ID - for (par_pid, par_process) in sys.processes() { - if *par_pid == my_parent_pid.unwrap() { + let mut found_parent_pid: bool = false; + for (next_par_pid, par_process) in sys.processes() { + if next_par_pid == &my_parent_pid { + found_parent_pid = true; cmd_shell_nm = par_process.name().to_string(); // Set any known command shell name @@ -574,6 +591,18 @@ fn get_cmd_shell() -> (CmdShell, String) { } else if cmd_shell_nm.to_lowercase().starts_with("sh") { cmd_shell_type = CmdShell::Sh; + } else if cmd_shell_nm.to_lowercase().starts_with("ksh") { + cmd_shell_type = CmdShell::Korn; + + } else if cmd_shell_nm.to_lowercase().starts_with("zsh") { + cmd_shell_type = CmdShell::Zshell; + + } else if cmd_shell_nm.to_lowercase().starts_with("csh") { + cmd_shell_type = CmdShell::Cshell; + + } else if cmd_shell_nm.to_lowercase().starts_with("tcsh") { + cmd_shell_type = CmdShell::Tenex; + } else if cmd_shell_nm.to_lowercase().starts_with("pwsh") { cmd_shell_type = CmdShell::PowerShellDotNet; @@ -586,14 +615,28 @@ fn get_cmd_shell() -> (CmdShell, String) { } else { cmd_shell_type = CmdShell::Unknown; } - break; // after we find par_pid, stop seaching process list - } + + // after we find our parent pid, stop seaching process list + break; + + } // end found our parent process ID + } // end iteration of process list to find our parent + + if !found_parent_pid { + return Err(SimpleError::new("Unable to find our parent process in the process list.")); } - break; // after we find my_pid, stop seaching process list - } + + // after we find my_pid, stop seaching process list + break; + + } // end found our own process ID + } // end iteration of process list to find our own process + + if !found_my_pid { + return Err(SimpleError::new("Unable to find our current process in the process list.")); } - (cmd_shell_type, cmd_shell_nm) + Ok((cmd_shell_type, cmd_shell_nm)) } /** @@ -661,19 +704,19 @@ fn user_wants_daemon() -> bool { /** * Run the classic NodeJS zowe command. - * @param cmd_line_args + * @param zowe_cmd_args * The user-supplied command line arguments to the zowe command. * @returns * Our error code when we fail to the NodeJS zowe. * Otherwise, the exit code of the NodeJs zowe command. */ -fn run_nodejs_command(cmd_line_args: &mut Vec) -> Result { +fn run_nodejs_command(zowe_cmd_args: &mut Vec) -> Result { let njs_zowe_path = get_nodejs_zowe_path(); // launch classic NodeJS zowe and wait for it to complete. let exit_code: i32; match Command::new(njs_zowe_path.to_owned()) - .args(cmd_line_args.to_owned()) + .args(zowe_cmd_args.to_owned()) .stdin(Stdio::inherit()) .stdout(Stdio::inherit()) .stderr(Stdio::inherit()) @@ -686,7 +729,7 @@ fn run_nodejs_command(cmd_line_args: &mut Vec) -> Result { println!("Failed to run the following command:"); println!( " Program = {}\n arguments = {:?}", - njs_zowe_path, cmd_line_args + njs_zowe_path, zowe_cmd_args ); println!("Due to this error:\n {}", error); exit_code = EXIT_CODE_FAILED_TO_RUN_NODEJS_CMD; @@ -698,9 +741,8 @@ fn run_nodejs_command(cmd_line_args: &mut Vec) -> Result { /** * Launch a zowe script in the background so that our EXE can exit before - * the script takes action on the EXE. We use ping to cause a delay in the - * script which allows our EXE to terminate before the zowe node.js program - * (which we launch) writes (or deletes) our EXE. + * the zowe node.js program (which we launch) writes (or deletes) our EXE. + * On Windows We use ping to cause a delay since CMD.exe has no 'sleep'. * * When our EXE exits, the user will get a new prompt immediately, but the * background output will be displayed after that prompt. @@ -708,11 +750,11 @@ fn run_nodejs_command(cmd_line_args: &mut Vec) -> Result { * Under PowerShell, our script first displays some newlines to make some * space on the screen. When the user eventually presses ENTER, the prompt * will display in the space that we made. If the user presses ENTER enough - * times, the prompts will overwite the output of the background script. + * times, the prompts will overwrite the output of the background script. * That is harmless, but it is a little ugly. However, we have no means to * control this PowerShell behavior. * - * @param cmd_line_args + * @param zowe_cmd_args * The user-supplied command line arguments to the zowe command. * * @returns @@ -720,91 +762,123 @@ fn run_nodejs_command(cmd_line_args: &mut Vec) -> Result { * If it runs a command, it exits with 0 for success, or it exits * with an error code for failing to launch the NodeJs zowe command. */ -fn run_delayed_zowe_command_and_exit(cmd_line_args: &[String]) { +fn run_delayed_zowe_command_and_exit(zowe_cmd_args: &[String]) { // Ony run delayed zowe script for specific commands - if cmd_line_args.len() >= 2 && - cmd_line_args[0] == "daemon" && - (cmd_line_args[1] == "enable" || cmd_line_args[1] == "disable") + if zowe_cmd_args.len() >= 2 && + zowe_cmd_args[0] == "daemon" && + (zowe_cmd_args[1] == "enable" || zowe_cmd_args[1] == "disable") { // determine the command shell under which we are running - let (curr_cmd_shell, cmd_shell_nm) = get_cmd_shell(); - if matches!(curr_cmd_shell, CmdShell::CantFindProcess) { - println!("Unable to find the current command shell in the process list. Terminating."); - std::process::exit(EXIT_CODE_CANT_FIND_CMD_SHELL); - } + let (curr_cmd_shell, cmd_shell_nm) = match get_cmd_shell() { + Ok((curr_cmd_shell, cmd_shell_nm)) => (curr_cmd_shell, cmd_shell_nm), + Err(error) => { + println!("{} Terminating.", error); + std::process::exit(EXIT_CODE_CANT_FIND_CMD_SHELL); + } + + }; if matches!(curr_cmd_shell, CmdShell::Unknown) { println!("The command shell process named '{}' is unknown to the Zowe CLI. Terminating.", cmd_shell_nm); std::process::exit(EXIT_CODE_UNKNOWN_CMD_SHELL); } - let njs_zowe_path = get_nodejs_zowe_path(); + // variables representing different sections of our background script. + const SCRIPT_WAIT_MSG: &str = "echo Wait to see the results below ... "; + const SCRIPT_PROMPT_MSG_FIXED: &str = "echo Now press ENTER to see your command "; + let cmd_shell_to_launch: &str; + let njs_zowe_path: String = get_nodejs_zowe_path(); + + // combine all of our script commands into an argument vector + let mut script_arg_vec = vec![]; + let mut script_string: String; - // form the command line for the CMD script that we will launch. - let cmd_shell_to_launch: String; - let mut args_for_cmd_script = vec![]; - const CMD_WORKED_SEP: &str = "&&"; - let cmd_continue_sep: &str; + // set cmds script choices that are platform-specific if env::consts::OS == "windows" { - cmd_shell_to_launch = "CMD".to_string(); - cmd_continue_sep = "&"; - args_for_cmd_script.push("/C"); - args_for_cmd_script.push("echo."); - args_for_cmd_script.push(CMD_WORKED_SEP); + cmd_shell_to_launch = "CMD"; + // add any required newlines to create some space + script_arg_vec.push("/C"); + script_arg_vec.push("echo."); + script_arg_vec.push("&&"); if matches!(curr_cmd_shell, CmdShell::PowerShellDotNet | CmdShell::PowerShellExe) { - // Powereshell needs extra newlines before the background process output - for next_arg in [ - "echo.", CMD_WORKED_SEP, "echo.", CMD_WORKED_SEP, "echo.", CMD_WORKED_SEP, - "echo.", CMD_WORKED_SEP, "echo.", CMD_WORKED_SEP, "echo.", CMD_WORKED_SEP - ] { - args_for_cmd_script.push(next_arg); + // PowerShell needs extra newlines before the background process output to create space + for _count in [1,2,3,4,5,6] { + script_arg_vec.push("echo."); + script_arg_vec.push("&&"); } + } else if matches!(curr_cmd_shell, CmdShell::Bash | CmdShell::Sh) { - // Unix shells on windows need a newline - for next_arg in [ - "sleep", "1", CMD_WORKED_SEP, "echo.", CMD_WORKED_SEP - ] { - args_for_cmd_script.push(next_arg); + // Bash shell on windows needs a delay and a newline in its spacing + for next_arg in "sleep 1 && echo. &&".split_whitespace() { + script_arg_vec.push(next_arg); } } - } else { - cmd_shell_to_launch = "bash".to_string(); - cmd_continue_sep = ";"; - } - // display a message, delay, then run zowe script - for next_arg in [ - "echo", "Wait", "to", "see", "the", "results", "below", "...", CMD_WORKED_SEP, - "ping", "127.0.0.1", "-n", "1", ">nul", CMD_WORKED_SEP, &*njs_zowe_path - ] { - args_for_cmd_script.push(next_arg); - } - for next_arg in cmd_line_args { - args_for_cmd_script.push(next_arg); - } + // make script delay so the EXE can exit + for next_arg in SCRIPT_WAIT_MSG.split_whitespace() { + script_arg_vec.push(next_arg); + } + script_arg_vec.push("&&"); - // add a message after the script is done - args_for_cmd_script.push(cmd_continue_sep); - for next_arg in ["echo", "Now", "press", "ENTER", "to", "see", "your", "command"] { - args_for_cmd_script.push(next_arg); - } - if matches!(curr_cmd_shell, CmdShell::PowerShellDotNet | CmdShell::PowerShellExe) { - for next_arg in [ - "prompt", "in", "the", "open", "space", "above." - ] { - args_for_cmd_script.push(next_arg); + // make script delay so the EXE can exit + for next_arg in "ping 127.0.0.1 -n 1 >nul &&".split_whitespace() { + script_arg_vec.push(next_arg); + } + + // run our Zowe command + script_arg_vec.push(&njs_zowe_path); + for next_arg in zowe_cmd_args { + script_arg_vec.push(next_arg); + } + script_arg_vec.push("&"); + + // add a message after the script is done + for next_arg in SCRIPT_PROMPT_MSG_FIXED.split_whitespace() { + script_arg_vec.push(next_arg); } + if matches!(curr_cmd_shell, CmdShell::PowerShellDotNet | CmdShell::PowerShellExe) { + // tell user that prompt will appear in the provided space + for next_arg in "prompt in the space above.".split_whitespace() { + script_arg_vec.push(next_arg); + } + } else { + script_arg_vec.push("prompt."); + } + } else { - args_for_cmd_script.push("prompt."); + // we are on a unix-like system + cmd_shell_to_launch = "bash"; + script_arg_vec.push("-c"); + + // for Bash, the entire script goes into one argument + script_string = "echo \"\" && ".to_string(); + + // make script delay so the EXE can exit + script_string.push_str(SCRIPT_WAIT_MSG); + script_string.push_str(" && sleep 1 && "); + + // run our Zowe command + script_string.push_str(&njs_zowe_path); + for next_arg in zowe_cmd_args { + script_string.push(' '); + script_string.push_str(next_arg); + } + script_string.push_str(" ; "); + + // add a message after the script is done + script_string.push_str(SCRIPT_PROMPT_MSG_FIXED); + script_string.push_str("prompt."); + + script_arg_vec.push(&script_string); } // The following line gives useful debugging info when it is uncommented. - // println!("args_for_cmd_script = {:?}", args_for_cmd_script); + // println!("script_arg_vec = {:?}", script_arg_vec); - println!("The '{}' command will run in the background ...", arg_vec_to_string(cmd_line_args)); + println!("The '{}' command will run in the background ...", arg_vec_to_string(zowe_cmd_args)); let exit_code: i32; match Command::new(cmd_shell_to_launch) - .args(args_for_cmd_script) + .args(script_arg_vec) .stdin(Stdio::inherit()) .stdout(Stdio::inherit()) .stderr(Stdio::inherit()) @@ -817,7 +891,7 @@ fn run_delayed_zowe_command_and_exit(cmd_line_args: &[String]) { println!("Failed to run the following command:"); println!( " cmd_shell_to_launch = {}\n arguments = {:?}", - njs_zowe_path, cmd_line_args + njs_zowe_path, zowe_cmd_args ); println!("Due to this error:\n {}", error); exit_code = EXIT_CODE_FAILED_TO_RUN_NODEJS_CMD; From 77d7bc7bc85d96171d256cee31a04d9ab23b33ed Mon Sep 17 00:00:00 2001 From: Gene Johnston Date: Mon, 28 Feb 2022 13:33:06 -0500 Subject: [PATCH 05/13] Add CHANGELOG entry. Signed-off-by: Gene Johnston --- packages/cli/CHANGELOG.md | 3 +++ 1 file changed, 3 insertions(+) diff --git a/packages/cli/CHANGELOG.md b/packages/cli/CHANGELOG.md index e76cf6756f..a2881b39bf 100644 --- a/packages/cli/CHANGELOG.md +++ b/packages/cli/CHANGELOG.md @@ -2,6 +2,9 @@ All notable changes to the Zowe CLI package will be documented in this file. +## Recent Changes +- Enhancement: the `zowe daemon enable` and `zowe daemon disable` commands run a process in the backgound so that they no longer require a user to copy and paste another command to successfully perform the operation. + ## `7.0.0-next.202202241854` - **LTS Breaking**: Added `stdin` property to `IHandlerParameters` which defaults to `process.stdin` and is overridden with another readable stream in daemon mode. From 62ada30c0907a333943fc98808af953fb30f67e0 Mon Sep 17 00:00:00 2001 From: Gene Johnston Date: Mon, 28 Feb 2022 18:07:44 -0500 Subject: [PATCH 06/13] Tar EXE we built into a prebuilds TGZ for testing. Signed-off-by: Gene Johnston --- .../cli.zowe.exe.integration.test.ts | 34 +++++++++++++++---- 1 file changed, 27 insertions(+), 7 deletions(-) diff --git a/packages/cli/__tests__/daemon/__integration__/cli.zowe.exe.integration.test.ts b/packages/cli/__tests__/daemon/__integration__/cli.zowe.exe.integration.test.ts index f88e735d79..e2d95db8cb 100644 --- a/packages/cli/__tests__/daemon/__integration__/cli.zowe.exe.integration.test.ts +++ b/packages/cli/__tests__/daemon/__integration__/cli.zowe.exe.integration.test.ts @@ -10,6 +10,7 @@ */ import * as nodeJsPath from "path"; +import * as tar from "tar"; import { IO, ProcessUtils, ISystemInfo } from "@zowe/imperative"; @@ -34,25 +35,44 @@ describe("Zowe native executable", () => { skipProperties: true }); - // determine executable file extension for our current OS - let exeExt: string; + // determine executable file name and TGZ path for our current OS + const zoweRootDir: string = nodeJsPath.normalize(__dirname + "/../../../../.."); + const prebuildsDir: string = nodeJsPath.normalize(zoweRootDir + "/packages/cli/prebuilds"); + let zoweExeTgzPath: string; + let zoweExeFileNm: string; const sysInfo: ISystemInfo = ProcessUtils.getBasicSystemInfo(); if (sysInfo.platform == "win32") { - exeExt = ".exe"; + zoweExeFileNm = "zowe.exe"; + zoweExeTgzPath = nodeJsPath.resolve(prebuildsDir, "zowe-windows.tgz"); + } else if (sysInfo.platform == "linux") { + zoweExeFileNm = "zowe"; + zoweExeTgzPath = nodeJsPath.resolve(prebuildsDir, "zowe-linux.tgz"); } else { - exeExt = ""; + zoweExeFileNm = "zowe"; + zoweExeTgzPath = nodeJsPath.resolve(prebuildsDir, "zowe-macos.tgz"); } // Form the path name to our executable. - const zoweExeGrandParentDir: string = nodeJsPath.normalize(__dirname + "/../../../../../zowex/target"); - zoweExePath = nodeJsPath.normalize(zoweExeGrandParentDir + "/release/zowe" + exeExt); + let zoweExeDirPath: string = nodeJsPath.normalize(zoweRootDir + "/zowex/target/release"); + zoweExePath = nodeJsPath.resolve(zoweExeDirPath, zoweExeFileNm); if (!IO.existsSync(zoweExePath)) { - zoweExePath = nodeJsPath.normalize(zoweExeGrandParentDir + "/debug/zowe" + exeExt); + zoweExeDirPath = nodeJsPath.normalize(zoweRootDir + "/zowex/target/debug"); + zoweExePath = nodeJsPath.resolve(zoweExeDirPath, zoweExeFileNm); if (!IO.existsSync(zoweExePath)) { willRunZoweExe = false; zoweExePath = "./NoZoweExeExists"; } } + + // tar our EXE into a TGZ for this platform, so that we can extract it in tests + if (willRunZoweExe) { + tar.create({ + sync: true, + gzip: true, + cwd: zoweExeDirPath, + file: zoweExeTgzPath + }, [zoweExeFileNm]); + } }); it("should display its version number", async () => { From 58977fdf8d6e28eca2a7d1526d7807963287b388 Mon Sep 17 00:00:00 2001 From: Gene Johnston Date: Mon, 28 Feb 2022 18:32:57 -0500 Subject: [PATCH 07/13] Create prebuilds directory when needed. Signed-off-by: Gene Johnston --- .../__integration__/cli.zowe.exe.integration.test.ts | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/packages/cli/__tests__/daemon/__integration__/cli.zowe.exe.integration.test.ts b/packages/cli/__tests__/daemon/__integration__/cli.zowe.exe.integration.test.ts index e2d95db8cb..323d9aa786 100644 --- a/packages/cli/__tests__/daemon/__integration__/cli.zowe.exe.integration.test.ts +++ b/packages/cli/__tests__/daemon/__integration__/cli.zowe.exe.integration.test.ts @@ -64,8 +64,13 @@ describe("Zowe native executable", () => { } } - // tar our EXE into a TGZ for this platform, so that we can extract it in tests if (willRunZoweExe) { + // we may have to create our prebuilds directory + if (!IO.existsSync(prebuildsDir)) { + IO.createDirSync(prebuildsDir); + } + + // tar our EXE into a TGZ for this platform, so that we can extract it in tests tar.create({ sync: true, gzip: true, From d1bfd987fa931784acfe082bbd7396ddaee90077 Mon Sep 17 00:00:00 2001 From: Gene Johnston Date: Tue, 1 Mar 2022 16:06:40 -0500 Subject: [PATCH 08/13] Use form_xxx_cmd_script_arg_vec( ) functions Signed-off-by: Gene Johnston --- zowex/src/main.rs | 295 ++++++++++++++++++++++++++++++++-------------- 1 file changed, 208 insertions(+), 87 deletions(-) diff --git a/zowex/src/main.rs b/zowex/src/main.rs index edaafb8084..5816c61fd2 100644 --- a/zowex/src/main.rs +++ b/zowex/src/main.rs @@ -810,95 +810,18 @@ fn run_delayed_zowe_command_and_exit(zowe_cmd_args: &[String]) { std::process::exit(EXIT_CODE_UNKNOWN_CMD_SHELL); } - // variables representing different sections of our background script. - const SCRIPT_WAIT_MSG: &str = "echo Wait to see the results below ... "; - const SCRIPT_PROMPT_MSG_FIXED: &str = "echo Now press ENTER to see your command "; - let cmd_shell_to_launch: &str; + /* Due to Rust variable lifetime requirements, these variables + * must be declared here and passed into all lower functions. + */ let njs_zowe_path: String = get_nodejs_zowe_path(); + let mut script_string: String = "".to_string(); + let mut script_arg_vec: Vec<&str> = vec![]; - // combine all of our script commands into an argument vector - let mut script_arg_vec = vec![]; - let mut script_string: String; - - // set cmds script choices that are platform-specific - if env::consts::OS == "windows" { - cmd_shell_to_launch = "CMD"; - - // add any required newlines to create some space - script_arg_vec.push("/C"); - script_arg_vec.push("echo."); - script_arg_vec.push("&&"); - if matches!(curr_cmd_shell, CmdShell::PowerShellDotNet | CmdShell::PowerShellExe) { - // PowerShell needs extra newlines before the background process output to create space - for _count in [1,2,3,4,5,6] { - script_arg_vec.push("echo."); - script_arg_vec.push("&&"); - } - - } else if matches!(curr_cmd_shell, CmdShell::Bash | CmdShell::Sh) { - // Bash shell on windows needs a delay and a newline in its spacing - for next_arg in "sleep 1 && echo. &&".split_whitespace() { - script_arg_vec.push(next_arg); - } - } - - // make script delay so the EXE can exit - for next_arg in SCRIPT_WAIT_MSG.split_whitespace() { - script_arg_vec.push(next_arg); - } - script_arg_vec.push("&&"); - - // make script delay so the EXE can exit - for next_arg in "ping 127.0.0.1 -n 1 >nul &&".split_whitespace() { - script_arg_vec.push(next_arg); - } - - // run our Zowe command - script_arg_vec.push(&njs_zowe_path); - for next_arg in zowe_cmd_args { - script_arg_vec.push(next_arg); - } - script_arg_vec.push("&"); - - // add a message after the script is done - for next_arg in SCRIPT_PROMPT_MSG_FIXED.split_whitespace() { - script_arg_vec.push(next_arg); - } - if matches!(curr_cmd_shell, CmdShell::PowerShellDotNet | CmdShell::PowerShellExe) { - // tell user that prompt will appear in the provided space - for next_arg in "prompt in the space above.".split_whitespace() { - script_arg_vec.push(next_arg); - } - } else { - script_arg_vec.push("prompt."); - } - - } else { - // we are on a unix-like system - cmd_shell_to_launch = "bash"; - script_arg_vec.push("-c"); - - // for Bash, the entire script goes into one argument - script_string = "echo \"\" && ".to_string(); - - // make script delay so the EXE can exit - script_string.push_str(SCRIPT_WAIT_MSG); - script_string.push_str(" && sleep 1 && "); - - // run our Zowe command - script_string.push_str(&njs_zowe_path); - for next_arg in zowe_cmd_args { - script_string.push(' '); - script_string.push_str(next_arg); - } - script_string.push_str(" ; "); - - // add a message after the script is done - script_string.push_str(SCRIPT_PROMPT_MSG_FIXED); - script_string.push_str("prompt."); - - script_arg_vec.push(&script_string); - } + // form the command script that we will launch + let cmd_shell_to_launch: String = form_cmd_script_arg_vec( + zowe_cmd_args, &njs_zowe_path, & curr_cmd_shell, + &mut script_string, &mut script_arg_vec + ); // The following line gives useful debugging info when it is uncommented. // println!("script_arg_vec = {:?}", script_arg_vec); @@ -929,6 +852,204 @@ fn run_delayed_zowe_command_and_exit(zowe_cmd_args: &[String]) { } // end if this is a command that we must run delayed } +/** + * Form the argument vector required to launch deamon enable and disable commands. + * + * @param zowe_cmd_args + * The user-supplied command line arguments to the zowe command. + * + * @param njs_zowe_path + * Path to our Node.js zowe command. + * + * @param curr_cmd_shell + * The current command shell under which we are running. + * + * @param script_string + * A string into which we can place all of the command names and parameters. + * + * @param script_arg_vec + * An empty vector into which we place command script arguments. + * + * @returns The command shell program that we will launch in the + * background to run our script. + */ +fn form_cmd_script_arg_vec<'a>( + zowe_cmd_args: &'a [String], + njs_zowe_path: &'a str, + curr_cmd_shell: & CmdShell, + script_string: &'a mut String, + script_arg_vec: &mut Vec<&'a str> +) -> String { + const SCRIPT_WAIT_MSG: &str = "echo Wait to see the results below ... "; + const SCRIPT_PROMPT_MSG_FIXED: &str = "echo Now press ENTER to see your command "; + + if env::consts::OS == "windows" + { + return form_win_cmd_script_arg_vec( + zowe_cmd_args, njs_zowe_path, curr_cmd_shell, + SCRIPT_WAIT_MSG, SCRIPT_PROMPT_MSG_FIXED, + script_arg_vec + ); + } + + form_bash_cmd_script_arg_vec( + zowe_cmd_args, njs_zowe_path, script_string, + SCRIPT_WAIT_MSG, SCRIPT_PROMPT_MSG_FIXED, + script_arg_vec + ) +} + +/** + * Form the argument vector required to launch deamon enable and disable commands + * on Windows. For Windows, each space-separated item on the script's command + * line goes into a separate script_arg_vec element. + * + * @param zowe_cmd_args + * The user-supplied command line arguments to the zowe command. + * + * @param njs_zowe_path + * Path to our Node.js zowe command. + * + * @param curr_cmd_shell + * The current command shell under which we are running. + * + * @param script_wait_msg + * A text message telling the user to wait for our background process. + * + * @param script_prompt_msg_fixed + * The fixed part of text message telling the user to press ENTER to get a prompt. + * + * @param script_arg_vec + * An empty vector into which we place command script arguments. + * + * @returns The command shell program that we will launch in the + * background to run our script. + */ +fn form_win_cmd_script_arg_vec<'a>( + zowe_cmd_args: &'a [String], + njs_zowe_path: &'a str, + curr_cmd_shell: & CmdShell, + script_wait_msg: &'a str, + script_prompt_msg_fixed: &'a str, + script_arg_vec: &mut Vec<&'a str> +) -> String { + // add any required newlines to create some space + script_arg_vec.push("/C"); + script_arg_vec.push("echo."); + script_arg_vec.push("&&"); + + if matches!(curr_cmd_shell, CmdShell::PowerShellDotNet | CmdShell::PowerShellExe) { + // PowerShell needs extra newlines before the background process output to create space + for _count in [1,2,3,4,5,6] { + script_arg_vec.push("echo."); + script_arg_vec.push("&&"); + } + + } else if matches!(curr_cmd_shell, CmdShell::Bash | CmdShell::Sh) { + // Bash shell on windows needs a delay and a newline in its spacing + for next_arg in "sleep 1 && echo. &&".split_whitespace() { + script_arg_vec.push(next_arg); + } + } + + // add our wait message + for next_arg in script_wait_msg.split_whitespace() { + script_arg_vec.push(next_arg); + } + script_arg_vec.push("&&"); + + // make script delay so the EXE can exit + for next_arg in "ping 127.0.0.1 -n 1 >nul &&".split_whitespace() { + script_arg_vec.push(next_arg); + } + + // add our Zowe command to the script + script_arg_vec.push(njs_zowe_path); + for next_arg in zowe_cmd_args { + script_arg_vec.push(next_arg); + } + script_arg_vec.push("&"); + + // add a message after the script is done + for next_arg in script_prompt_msg_fixed.split_whitespace() { + script_arg_vec.push(next_arg); + } + if matches!(curr_cmd_shell, CmdShell::PowerShellDotNet | CmdShell::PowerShellExe) { + // tell user that prompt will appear in the provided space + for next_arg in "prompt in the space above.".split_whitespace() { + script_arg_vec.push(next_arg); + } + } else { + script_arg_vec.push("prompt."); + } + + // return the shell program that we will launch + "CMD".to_string() +} + +/** + * Form the argument vector required to launch deamon enable and disable commands + * on Bash systems (Linux and MacOs). For Bash, all items on the script's command + * line (after the "-c" flag) go into one script_arg_vec argument. + * + * @param zowe_cmd_args + * The user-supplied command line arguments to the zowe command. + * + * @param njs_zowe_path + * Path to our Node.js zowe command. + * + * @param script_string + * A string into which we can place all of the command names and parameters. + * + * @param script_wait_msg + * A text message telling the user to wait for our background process. + * + * @param script_prompt_msg_fixed + * The fixed part of text message telling the user to press ENTER to get a prompt. + * + * @param script_arg_vec + * An empty vector into which we place command script arguments. + * + * @returns The command shell program that we will launch in the + * background to run our script. + */ +fn form_bash_cmd_script_arg_vec<'a>( + zowe_cmd_args: &'a [String], + njs_zowe_path: &'a str, + script_string: &'a mut String, + script_wait_msg: &'a str, + script_prompt_msg_fixed: &'a str, + script_arg_vec: &mut Vec<&'a str> +) -> String { + // -c goes into the first argument + script_arg_vec.push("-c"); + + // all remaining commands and parameters go into a big string. + script_string.push_str("echo \"\" && "); + + // make script delay so the EXE can exit + script_string.push_str(script_wait_msg); + script_string.push_str(" && sleep 1 && "); + + // add our Zowe command + script_string.push_str(njs_zowe_path); + for next_arg in zowe_cmd_args { + script_string.push(' '); + script_string.push_str(next_arg); + } + script_string.push_str(" ; "); + + // add a message after the script is done + script_string.push_str(script_prompt_msg_fixed); + script_string.push_str("prompt."); + + // put our big string into the second script argument + script_arg_vec.push(script_string); + + // return the shell program that we will launch + "bash".to_string() +} + /** * Start the zowe daemon. * From 2db2e4f6d8b054d045ba3b019c786a48c9f95c85 Mon Sep 17 00:00:00 2001 From: Gene Johnston Date: Tue, 1 Mar 2022 18:27:07 -0500 Subject: [PATCH 09/13] Remove prebuilds directory before and after tests Signed-off-by: Gene Johnston --- .../cli.zowe.exe.integration.test.ts | 19 ++++++++++++++----- 1 file changed, 14 insertions(+), 5 deletions(-) diff --git a/packages/cli/__tests__/daemon/__integration__/cli.zowe.exe.integration.test.ts b/packages/cli/__tests__/daemon/__integration__/cli.zowe.exe.integration.test.ts index 323d9aa786..49a1a23548 100644 --- a/packages/cli/__tests__/daemon/__integration__/cli.zowe.exe.integration.test.ts +++ b/packages/cli/__tests__/daemon/__integration__/cli.zowe.exe.integration.test.ts @@ -19,12 +19,15 @@ import { ITestPropertiesSchema } from "../../../../../__tests__/__src__/properti import { TestEnvironment } from "../../../../../__tests__/__src__/environment/TestEnvironment"; let testEnvironment: ITestEnvironment; +let prebuildsDir: string; describe("Zowe native executable", () => { const RUN_IN_BACKGROUND_MSG: string = "command will run in the background ..."; const WAIT_TO_SEE_RESULTS_MSG: string = "Wait to see the results below ..."; const NOW_PRESS_ENTER_MSG: string = "Now press ENTER to see your command prompt."; + const rimrafSync = require("rimraf").sync; + let zoweExePath: string; let willRunZoweExe: boolean = true; @@ -37,7 +40,7 @@ describe("Zowe native executable", () => { // determine executable file name and TGZ path for our current OS const zoweRootDir: string = nodeJsPath.normalize(__dirname + "/../../../../.."); - const prebuildsDir: string = nodeJsPath.normalize(zoweRootDir + "/packages/cli/prebuilds"); + prebuildsDir = nodeJsPath.normalize(zoweRootDir + "/packages/cli/prebuilds"); let zoweExeTgzPath: string; let zoweExeFileNm: string; const sysInfo: ISystemInfo = ProcessUtils.getBasicSystemInfo(); @@ -64,11 +67,12 @@ describe("Zowe native executable", () => { } } + // Remove any existing prebuilds directory + rimrafSync(prebuildsDir); + if (willRunZoweExe) { - // we may have to create our prebuilds directory - if (!IO.existsSync(prebuildsDir)) { - IO.createDirSync(prebuildsDir); - } + // create our prebuilds directory + IO.createDirSync(prebuildsDir); // tar our EXE into a TGZ for this platform, so that we can extract it in tests tar.create({ @@ -80,6 +84,11 @@ describe("Zowe native executable", () => { } }); + afterAll(async () => { + // Remove any existing prebuilds directory + rimrafSync(prebuildsDir); + }); + it("should display its version number", async () => { if (willRunZoweExe) { const response = runCliScript( From d797e70e6eab542e8692f036346e16691103a7b7 Mon Sep 17 00:00:00 2001 From: Gene Johnston Date: Wed, 2 Mar 2022 18:09:29 -0500 Subject: [PATCH 10/13] Serialize daemon EXE, enable, and disable tests. Signed-off-by: Gene Johnston --- .../cli.zowe.daemon.integration.suite.test.ts | 99 +++++++++++++++++++ ...on.test.ts => cli.zowe.exe.integration.ts} | 37 ++----- ...t.ts => cli.daemon.disable.integration.ts} | 7 -- ...st.ts => cli.daemon.enable.integration.ts} | 17 +--- 4 files changed, 107 insertions(+), 53 deletions(-) create mode 100644 packages/cli/__tests__/daemon/__integration__/cli.zowe.daemon.integration.suite.test.ts rename packages/cli/__tests__/daemon/__integration__/{cli.zowe.exe.integration.test.ts => cli.zowe.exe.integration.ts} (76%) rename packages/cli/__tests__/daemon/__integration__/disable/{cli.daemon.disable.integration.test.ts => cli.daemon.disable.integration.ts} (95%) rename packages/cli/__tests__/daemon/__integration__/enable/{cli.daemon.enable.integration.test.ts => cli.daemon.enable.integration.ts} (95%) diff --git a/packages/cli/__tests__/daemon/__integration__/cli.zowe.daemon.integration.suite.test.ts b/packages/cli/__tests__/daemon/__integration__/cli.zowe.daemon.integration.suite.test.ts new file mode 100644 index 0000000000..df9808e0ed --- /dev/null +++ b/packages/cli/__tests__/daemon/__integration__/cli.zowe.daemon.integration.suite.test.ts @@ -0,0 +1,99 @@ +/* +* This program and the accompanying materials are made available under the terms of the +* Eclipse Public License v2.0 which accompanies this distribution, and is available at +* https://www.eclipse.org/legal/epl-v20.html +* +* SPDX-License-Identifier: EPL-2.0 +* +* Copyright Contributors to the Zowe Project. +* +*/ + +/* Our daemon-related tests create a TGZ for our EXE, which should be removed + * after testing. These tests also create and remove an EXE file in our bin + * directory. The file creations and deletions create problems when the tests + * are run in parallel. By placing the daemon tests within this top-level + * describe (thus contining the tests in a single file) the tests are serialized. + */ + +import * as nodeJsPath from "path"; +import * as tar from "tar"; +import { IO, ProcessUtils, ISystemInfo } from "@zowe/imperative"; + +describe("Zowe daemon suite", () => { + const rimrafSync = require("rimraf").sync; + + let prebuildsDir: string; + let zoweExePath: string; + let zoweExeDirPath: string; + let zoweExeTgzPath: string; + let zoweExeFileNm: string; + let willRunZoweExe: boolean = true; + + // establish path names and record whether we are running our EXE or node.js script + beforeAll(async () => { + // determine executable file name and TGZ path for our current OS + const zoweRootDir: string = nodeJsPath.normalize(__dirname + "/../../../../.."); + prebuildsDir = nodeJsPath.normalize(zoweRootDir + "/packages/cli/prebuilds"); + const sysInfo: ISystemInfo = ProcessUtils.getBasicSystemInfo(); + switch (sysInfo.platform) { + case "darwin": { + zoweExeFileNm = "zowe"; + zoweExeTgzPath = nodeJsPath.resolve(prebuildsDir, "zowe-macos.tgz"); + break; + } + case "linux": { + zoweExeFileNm = "zowe"; + zoweExeTgzPath = nodeJsPath.resolve(prebuildsDir, "zowe-linux.tgz"); + break; + } + case "win32": { + zoweExeFileNm = "zowe.exe"; + zoweExeTgzPath = nodeJsPath.resolve(prebuildsDir, "zowe-windows.tgz"); + break; + } + default: { + zoweExeFileNm = "exeForUnknownOs"; + zoweExeTgzPath += "unknownOs.tgz"; + throw "cli.zowe.daemon.integration.suite.test.ts: beforeAll: " + + sysInfo.platform + " is not a known OS."; + } + } + + // Form the path name to our executable. + zoweExeDirPath = nodeJsPath.normalize(zoweRootDir + "/zowex/target/release"); + zoweExePath = nodeJsPath.resolve(zoweExeDirPath, zoweExeFileNm); + if (!IO.existsSync(zoweExePath)) { + zoweExeDirPath = nodeJsPath.normalize(zoweRootDir + "/zowex/target/debug"); + zoweExePath = nodeJsPath.resolve(zoweExeDirPath, zoweExeFileNm); + if (!IO.existsSync(zoweExePath)) { + willRunZoweExe = false; + zoweExePath = "./NoZoweExeExists"; + } + } + + // Remove any existing prebuilds directory + rimrafSync(prebuildsDir); + + // create our prebuilds directory + IO.createDirSync(prebuildsDir); + + // tar our EXE into a TGZ for this platform, so that we can extract it in tests + tar.create({ + sync: true, + gzip: true, + cwd: zoweExeDirPath, + file: zoweExeTgzPath + }, [zoweExeFileNm]); + }); + + afterAll(async () => { + // Remove any existing prebuilds directory + rimrafSync(prebuildsDir); + }); + + // run all of our daemon-related tests + require("./cli.zowe.exe.integration"); + require("./enable/cli.daemon.enable.integration"); + require("./disable/cli.daemon.disable.integration"); +}); diff --git a/packages/cli/__tests__/daemon/__integration__/cli.zowe.exe.integration.test.ts b/packages/cli/__tests__/daemon/__integration__/cli.zowe.exe.integration.ts similarity index 76% rename from packages/cli/__tests__/daemon/__integration__/cli.zowe.exe.integration.test.ts rename to packages/cli/__tests__/daemon/__integration__/cli.zowe.exe.integration.ts index 49a1a23548..6426267cbc 100644 --- a/packages/cli/__tests__/daemon/__integration__/cli.zowe.exe.integration.test.ts +++ b/packages/cli/__tests__/daemon/__integration__/cli.zowe.exe.integration.ts @@ -10,7 +10,6 @@ */ import * as nodeJsPath from "path"; -import * as tar from "tar"; import { IO, ProcessUtils, ISystemInfo } from "@zowe/imperative"; @@ -18,16 +17,14 @@ import { ITestEnvironment, runCliScript } from "@zowe/cli-test-utils"; import { ITestPropertiesSchema } from "../../../../../__tests__/__src__/properties/ITestPropertiesSchema"; import { TestEnvironment } from "../../../../../__tests__/__src__/environment/TestEnvironment"; -let testEnvironment: ITestEnvironment; -let prebuildsDir: string; - describe("Zowe native executable", () => { const RUN_IN_BACKGROUND_MSG: string = "command will run in the background ..."; const WAIT_TO_SEE_RESULTS_MSG: string = "Wait to see the results below ..."; const NOW_PRESS_ENTER_MSG: string = "Now press ENTER to see your command prompt."; - const rimrafSync = require("rimraf").sync; - + let testEnvironment: ITestEnvironment; + let zoweExeFileNm: string; + let zoweExeDirPath: string; let zoweExePath: string; let willRunZoweExe: boolean = true; @@ -38,25 +35,19 @@ describe("Zowe native executable", () => { skipProperties: true }); - // determine executable file name and TGZ path for our current OS + // determine executable file name for our current OS const zoweRootDir: string = nodeJsPath.normalize(__dirname + "/../../../../.."); - prebuildsDir = nodeJsPath.normalize(zoweRootDir + "/packages/cli/prebuilds"); - let zoweExeTgzPath: string; - let zoweExeFileNm: string; const sysInfo: ISystemInfo = ProcessUtils.getBasicSystemInfo(); if (sysInfo.platform == "win32") { zoweExeFileNm = "zowe.exe"; - zoweExeTgzPath = nodeJsPath.resolve(prebuildsDir, "zowe-windows.tgz"); } else if (sysInfo.platform == "linux") { zoweExeFileNm = "zowe"; - zoweExeTgzPath = nodeJsPath.resolve(prebuildsDir, "zowe-linux.tgz"); } else { zoweExeFileNm = "zowe"; - zoweExeTgzPath = nodeJsPath.resolve(prebuildsDir, "zowe-macos.tgz"); } // Form the path name to our executable. - let zoweExeDirPath: string = nodeJsPath.normalize(zoweRootDir + "/zowex/target/release"); + zoweExeDirPath = nodeJsPath.normalize(zoweRootDir + "/zowex/target/release"); zoweExePath = nodeJsPath.resolve(zoweExeDirPath, zoweExeFileNm); if (!IO.existsSync(zoweExePath)) { zoweExeDirPath = nodeJsPath.normalize(zoweRootDir + "/zowex/target/debug"); @@ -66,27 +57,11 @@ describe("Zowe native executable", () => { zoweExePath = "./NoZoweExeExists"; } } - - // Remove any existing prebuilds directory - rimrafSync(prebuildsDir); - - if (willRunZoweExe) { - // create our prebuilds directory - IO.createDirSync(prebuildsDir); - - // tar our EXE into a TGZ for this platform, so that we can extract it in tests - tar.create({ - sync: true, - gzip: true, - cwd: zoweExeDirPath, - file: zoweExeTgzPath - }, [zoweExeFileNm]); - } }); afterAll(async () => { // Remove any existing prebuilds directory - rimrafSync(prebuildsDir); + await TestEnvironment.cleanUp(testEnvironment); }); it("should display its version number", async () => { diff --git a/packages/cli/__tests__/daemon/__integration__/disable/cli.daemon.disable.integration.test.ts b/packages/cli/__tests__/daemon/__integration__/disable/cli.daemon.disable.integration.ts similarity index 95% rename from packages/cli/__tests__/daemon/__integration__/disable/cli.daemon.disable.integration.test.ts rename to packages/cli/__tests__/daemon/__integration__/disable/cli.daemon.disable.integration.ts index bf8ab3a307..c992924037 100644 --- a/packages/cli/__tests__/daemon/__integration__/disable/cli.daemon.disable.integration.test.ts +++ b/packages/cli/__tests__/daemon/__integration__/disable/cli.daemon.disable.integration.ts @@ -25,7 +25,6 @@ let testEnvironment: ITestEnvironment; describe("daemon disable", () => { const rimrafSync = require("rimraf").sync; - const fakeExeContent = "This is not a real executable"; const zoweCmdRegEx = "zowe.*[/|\\\\]cli[/|\\\\]lib[/|\\\\]main.js.* --daemon" + "|" + "[/|\\\\]bin[/|\\\\]zowe.* --daemon"; @@ -44,32 +43,26 @@ describe("daemon disable", () => { const sysInfo: ISystemInfo = ProcessUtils.getBasicSystemInfo(); // form our tgz file name - let tgzFileName = "zowe-"; switch (sysInfo.platform) { case "darwin": { - tgzFileName += "macos.tgz"; exePath = "zowe"; break; } case "linux": { - tgzFileName += "linux.tgz"; exePath = "zowe"; break; } case "win32": { - tgzFileName += "windows.tgz"; exePath = "zowe.exe"; break; } default: { - tgzFileName += "unknownOs.tgz"; exePath = "exeForUnknownOs"; throw "cli.daemon.disable.integration.test.ts: beforeAll: " + sysInfo.platform + " is not a known OS."; } } // form the path to our bin directory, executable, and prebuilds tgz file - const tgzResourcePath = nodeJsPath.resolve(__dirname, "../../__resources__", tgzFileName); pathToBin = nodeJsPath.resolve(testEnvironment.workingDir, "bin"); exePath = nodeJsPath.resolve(pathToBin, exePath); diff --git a/packages/cli/__tests__/daemon/__integration__/enable/cli.daemon.enable.integration.test.ts b/packages/cli/__tests__/daemon/__integration__/enable/cli.daemon.enable.integration.ts similarity index 95% rename from packages/cli/__tests__/daemon/__integration__/enable/cli.daemon.enable.integration.test.ts rename to packages/cli/__tests__/daemon/__integration__/enable/cli.daemon.enable.integration.ts index 75bdceaf72..42348a8cc9 100644 --- a/packages/cli/__tests__/daemon/__integration__/enable/cli.daemon.enable.integration.test.ts +++ b/packages/cli/__tests__/daemon/__integration__/enable/cli.daemon.enable.integration.ts @@ -19,16 +19,14 @@ import { ITestEnvironment, runCliScript } from "@zowe/cli-test-utils"; import { TestEnvironment } from "../../../../../../__tests__/__src__/environment/TestEnvironment"; import { ITestPropertiesSchema } from "../../../../../../__tests__/__src__/properties/ITestPropertiesSchema"; -let testEnvironment: ITestEnvironment; - describe("daemon enable", () => { const rimrafSync = require("rimraf").sync; const fakeExeContent = "This is not a real executable"; const EXIT_CODE_CANT_RUN_DAEMON_CMD: number = 107; + let testEnvironment: ITestEnvironment; let exePath: string; let pathToBin: string; - let preBldDir: string; let preBldTgzPath: string; // is the zowe command that we will run our Node.js script? @@ -45,7 +43,6 @@ describe("daemon enable", () => { return true; }; - beforeAll(async () => { // Create the unique test environment testEnvironment = await TestEnvironment.setUp({ @@ -82,19 +79,10 @@ describe("daemon enable", () => { } // form the path to our bin directory, executable, and prebuilds tgz file - const tgzResourcePath = nodeJsPath.resolve(__dirname, "../../__resources__", tgzFileName); - preBldDir = nodeJsPath.resolve(__dirname, "../../../../prebuilds"); + const preBldDir = nodeJsPath.resolve(__dirname, "../../../../prebuilds"); preBldTgzPath = nodeJsPath.resolve(preBldDir, tgzFileName); pathToBin = nodeJsPath.resolve(testEnvironment.workingDir, "bin"); exePath = nodeJsPath.resolve(pathToBin, exePath); - - // copy a fake tgz file from resources to our prebuilds directory for testing - if (!IO.existsSync(preBldDir)) { - IO.createDirSync(preBldDir); - } - if (!IO.existsSync(preBldTgzPath)) { - fs.copyFileSync(tgzResourcePath, preBldTgzPath); - } }); beforeEach(async () => { @@ -104,7 +92,6 @@ describe("daemon enable", () => { afterAll(async () => { rimrafSync(pathToBin); - rimrafSync(preBldDir); await TestEnvironment.cleanUp(testEnvironment); }); From 90bdb9e33a5d92fd76e17d310f9447b856c615e3 Mon Sep 17 00:00:00 2001 From: Gene Johnston Date: Thu, 3 Mar 2022 11:54:14 -0500 Subject: [PATCH 11/13] Eliminate some redundant cases. Signed-off-by: Gene Johnston --- .../cli.zowe.daemon.integration.suite.test.ts | 2 -- .../daemon/__integration__/cli.zowe.exe.integration.ts | 2 -- .../disable/cli.daemon.disable.integration.ts | 5 +---- 3 files changed, 1 insertion(+), 8 deletions(-) diff --git a/packages/cli/__tests__/daemon/__integration__/cli.zowe.daemon.integration.suite.test.ts b/packages/cli/__tests__/daemon/__integration__/cli.zowe.daemon.integration.suite.test.ts index df9808e0ed..8e2526540e 100644 --- a/packages/cli/__tests__/daemon/__integration__/cli.zowe.daemon.integration.suite.test.ts +++ b/packages/cli/__tests__/daemon/__integration__/cli.zowe.daemon.integration.suite.test.ts @@ -28,7 +28,6 @@ describe("Zowe daemon suite", () => { let zoweExeDirPath: string; let zoweExeTgzPath: string; let zoweExeFileNm: string; - let willRunZoweExe: boolean = true; // establish path names and record whether we are running our EXE or node.js script beforeAll(async () => { @@ -67,7 +66,6 @@ describe("Zowe daemon suite", () => { zoweExeDirPath = nodeJsPath.normalize(zoweRootDir + "/zowex/target/debug"); zoweExePath = nodeJsPath.resolve(zoweExeDirPath, zoweExeFileNm); if (!IO.existsSync(zoweExePath)) { - willRunZoweExe = false; zoweExePath = "./NoZoweExeExists"; } } diff --git a/packages/cli/__tests__/daemon/__integration__/cli.zowe.exe.integration.ts b/packages/cli/__tests__/daemon/__integration__/cli.zowe.exe.integration.ts index 6426267cbc..2b78a766ed 100644 --- a/packages/cli/__tests__/daemon/__integration__/cli.zowe.exe.integration.ts +++ b/packages/cli/__tests__/daemon/__integration__/cli.zowe.exe.integration.ts @@ -40,8 +40,6 @@ describe("Zowe native executable", () => { const sysInfo: ISystemInfo = ProcessUtils.getBasicSystemInfo(); if (sysInfo.platform == "win32") { zoweExeFileNm = "zowe.exe"; - } else if (sysInfo.platform == "linux") { - zoweExeFileNm = "zowe"; } else { zoweExeFileNm = "zowe"; } diff --git a/packages/cli/__tests__/daemon/__integration__/disable/cli.daemon.disable.integration.ts b/packages/cli/__tests__/daemon/__integration__/disable/cli.daemon.disable.integration.ts index c992924037..ca8eb25e38 100644 --- a/packages/cli/__tests__/daemon/__integration__/disable/cli.daemon.disable.integration.ts +++ b/packages/cli/__tests__/daemon/__integration__/disable/cli.daemon.disable.integration.ts @@ -44,10 +44,7 @@ describe("daemon disable", () => { // form our tgz file name switch (sysInfo.platform) { - case "darwin": { - exePath = "zowe"; - break; - } + case "darwin": case "linux": { exePath = "zowe"; break; From 35cc7b458c44bf4d9740a44d983405639e15005f Mon Sep 17 00:00:00 2001 From: Gene Johnston Date: Thu, 3 Mar 2022 16:02:57 -0500 Subject: [PATCH 12/13] Remove hard-coded file name. Signed-off-by: Gene Johnston --- .../__integration__/disable/cli.daemon.disable.integration.ts | 2 +- .../__integration__/enable/cli.daemon.enable.integration.ts | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/packages/cli/__tests__/daemon/__integration__/disable/cli.daemon.disable.integration.ts b/packages/cli/__tests__/daemon/__integration__/disable/cli.daemon.disable.integration.ts index ca8eb25e38..0b7582bded 100644 --- a/packages/cli/__tests__/daemon/__integration__/disable/cli.daemon.disable.integration.ts +++ b/packages/cli/__tests__/daemon/__integration__/disable/cli.daemon.disable.integration.ts @@ -55,7 +55,7 @@ describe("daemon disable", () => { } default: { exePath = "exeForUnknownOs"; - throw "cli.daemon.disable.integration.test.ts: beforeAll: " + sysInfo.platform + " is not a known OS."; + throw __filename + ": beforeAll: " + sysInfo.platform + " is not a known OS."; } } diff --git a/packages/cli/__tests__/daemon/__integration__/enable/cli.daemon.enable.integration.ts b/packages/cli/__tests__/daemon/__integration__/enable/cli.daemon.enable.integration.ts index 42348a8cc9..d424ec82e6 100644 --- a/packages/cli/__tests__/daemon/__integration__/enable/cli.daemon.enable.integration.ts +++ b/packages/cli/__tests__/daemon/__integration__/enable/cli.daemon.enable.integration.ts @@ -74,7 +74,7 @@ describe("daemon enable", () => { default: { tgzFileName += "unknownOs.tgz"; exePath = "exeForUnknownOs"; - throw "cli.daemon.enable.integration.test.ts: beforeAll: " + sysInfo.platform + " is not a known OS."; + throw __filename + ": beforeAll: " + sysInfo.platform + " is not a known OS."; } } From 6a267aecaff36906501a9b44d75bbc5a5313e71a Mon Sep 17 00:00:00 2001 From: Gene Johnston Date: Thu, 3 Mar 2022 16:05:24 -0500 Subject: [PATCH 13/13] Set zoweExeDirPath so tar fails when no EXE exists Declare variables closer to use. Signed-off-by: Gene Johnston --- .../cli.zowe.daemon.integration.suite.test.ts | 13 ++++++------- 1 file changed, 6 insertions(+), 7 deletions(-) diff --git a/packages/cli/__tests__/daemon/__integration__/cli.zowe.daemon.integration.suite.test.ts b/packages/cli/__tests__/daemon/__integration__/cli.zowe.daemon.integration.suite.test.ts index 8e2526540e..9f1447cbc1 100644 --- a/packages/cli/__tests__/daemon/__integration__/cli.zowe.daemon.integration.suite.test.ts +++ b/packages/cli/__tests__/daemon/__integration__/cli.zowe.daemon.integration.suite.test.ts @@ -24,13 +24,12 @@ describe("Zowe daemon suite", () => { const rimrafSync = require("rimraf").sync; let prebuildsDir: string; - let zoweExePath: string; - let zoweExeDirPath: string; - let zoweExeTgzPath: string; - let zoweExeFileNm: string; // establish path names and record whether we are running our EXE or node.js script beforeAll(async () => { + let zoweExeTgzPath: string; + let zoweExeFileNm: string; + // determine executable file name and TGZ path for our current OS const zoweRootDir: string = nodeJsPath.normalize(__dirname + "/../../../../.."); prebuildsDir = nodeJsPath.normalize(zoweRootDir + "/packages/cli/prebuilds"); @@ -60,13 +59,13 @@ describe("Zowe daemon suite", () => { } // Form the path name to our executable. - zoweExeDirPath = nodeJsPath.normalize(zoweRootDir + "/zowex/target/release"); - zoweExePath = nodeJsPath.resolve(zoweExeDirPath, zoweExeFileNm); + let zoweExeDirPath = nodeJsPath.normalize(zoweRootDir + "/zowex/target/release"); + let zoweExePath = nodeJsPath.resolve(zoweExeDirPath, zoweExeFileNm); if (!IO.existsSync(zoweExePath)) { zoweExeDirPath = nodeJsPath.normalize(zoweRootDir + "/zowex/target/debug"); zoweExePath = nodeJsPath.resolve(zoweExeDirPath, zoweExeFileNm); if (!IO.existsSync(zoweExePath)) { - zoweExePath = "./NoZoweExeExists"; + zoweExeDirPath = "./NoZoweExeExists"; } }