From 7de6dec1c6fe816dd483abcf6ba68f31afaf2d2b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Boni=20Garc=C3=ADa?= Date: Wed, 1 Feb 2023 14:40:42 +0100 Subject: [PATCH] [rust] Selenium Manager processes PATH (#11597) * [rust] Selenium Manager processes PATH * [rust] Fix CLI test (when driver is not in the cache but in the PATH) --- rust/src/chrome.rs | 11 +++--- rust/src/edge.rs | 11 +++--- rust/src/files.rs | 12 +++++-- rust/src/firefox.rs | 11 +++--- rust/src/lib.rs | 75 ++++++++++++++++++++++++++++++++++++++++- rust/tests/cli_tests.rs | 2 +- 6 files changed, 97 insertions(+), 25 deletions(-) diff --git a/rust/src/chrome.rs b/rust/src/chrome.rs index db3d7971dff4c..1e6fb90b1cbd1 100644 --- a/rust/src/chrome.rs +++ b/rust/src/chrome.rs @@ -139,14 +139,11 @@ impl SeleniumManager for ChromeManager { } else { commands = vec![self.format_one_arg(WMIC_COMMAND, browser_path)]; } - let (shell, flag, args) = if WINDOWS.is(self.get_os()) { - ("cmd", "/C", commands) + let (shell, flag) = self.get_shell_command(); + let args = if WINDOWS.is(self.get_os()) { + commands } else { - ( - "sh", - "-c", - vec![self.format_one_arg(DASH_DASH_VERSION, browser_path)], - ) + vec![self.format_one_arg(DASH_DASH_VERSION, browser_path)] }; self.detect_browser_version(shell, flag, args) } diff --git a/rust/src/edge.rs b/rust/src/edge.rs index 25a9022f80887..987d1e4258a45 100644 --- a/rust/src/edge.rs +++ b/rust/src/edge.rs @@ -139,14 +139,11 @@ impl SeleniumManager for EdgeManager { } else { commands = vec![self.format_one_arg(WMIC_COMMAND, browser_path)]; } - let (shell, flag, args) = if WINDOWS.is(self.get_os()) { - ("cmd", "/C", commands) + let (shell, flag) = self.get_shell_command(); + let args = if WINDOWS.is(self.get_os()) { + commands } else { - ( - "sh", - "-c", - vec![self.format_one_arg(DASH_DASH_VERSION, browser_path)], - ) + vec![self.format_one_arg(DASH_DASH_VERSION, browser_path)] }; self.detect_browser_version(shell, flag, args) } diff --git a/rust/src/files.rs b/rust/src/files.rs index b25b75470a25b..9ed447f202fe1 100644 --- a/rust/src/files.rs +++ b/rust/src/files.rs @@ -183,6 +183,14 @@ pub fn parse_version(version_text: String) -> Result> { if version_text.to_ascii_lowercase().contains("error") { return Err(PARSE_ERROR.into()); } - let re = Regex::new(r"[^\d^.]").unwrap(); - Ok(re.replace_all(&version_text, "").to_string()) + let mut parsed_version = "".to_string(); + let re_numbers_dots = Regex::new(r"[^\d^.]")?; + let re_versions = Regex::new(r"(?:(\d+)\.)?(?:(\d+)\.)?(?:(\d+)\.\d+)")?; + for token in version_text.split(' ') { + parsed_version = re_numbers_dots.replace_all(token, "").to_string(); + if re_versions.is_match(parsed_version.as_str()) { + break; + } + } + Ok(parsed_version) } diff --git a/rust/src/firefox.rs b/rust/src/firefox.rs index 11d38a1d53da5..29e7ce424376a 100644 --- a/rust/src/firefox.rs +++ b/rust/src/firefox.rs @@ -129,14 +129,11 @@ impl SeleniumManager for FirefoxManager { } else { commands = vec![self.format_one_arg(WMIC_COMMAND, browser_path)]; } - let (shell, flag, args) = if WINDOWS.is(self.get_os()) { - ("cmd", "/C", commands) + let (shell, flag) = self.get_shell_command(); + let args = if WINDOWS.is(self.get_os()) { + commands } else { - ( - "sh", - "-c", - vec![self.format_one_arg(DASH_VERSION, browser_path)], - ) + vec![self.format_one_arg(DASH_VERSION, browser_path)] }; self.detect_browser_version(shell, flag, args) } diff --git a/rust/src/lib.rs b/rust/src/lib.rs index de3db9c653ab2..f5a6b13daf017 100644 --- a/rust/src/lib.rs +++ b/rust/src/lib.rs @@ -22,6 +22,7 @@ use crate::firefox::FirefoxManager; use crate::iexplorer::IExplorerManager; use std::fs; +use crate::config::OS::WINDOWS; use crate::config::{str_to_os, ManagerConfig}; use reqwest::{Client, ClientBuilder, Proxy}; use std::collections::HashMap; @@ -62,6 +63,8 @@ pub const ENV_PROGRAM_FILES: &str = "PROGRAMFILES"; pub const ENV_PROGRAM_FILES_X86: &str = "PROGRAMFILES(X86)"; pub const ENV_LOCALAPPDATA: &str = "LOCALAPPDATA"; pub const FALLBACK_RETRIES: u32 = 5; +pub const WHERE_COMMAND: &str = "where {}"; +pub const WHICH_COMMAND: &str = "which {}"; pub trait SeleniumManager { // ---------------------------------------------------------- @@ -217,6 +220,45 @@ pub trait SeleniumManager { Ok(driver_version) } + fn find_driver_in_path(&self) -> (Option, Option) { + let (shell, flag) = self.get_shell_command(); + match self.run_shell_command( + shell, + flag, + self.format_one_arg(DASH_DASH_VERSION, self.get_driver_name()), + ) { + Ok(output) => { + let parsed_version = parse_version(output).unwrap_or_default(); + if !parsed_version.is_empty() { + let which_command = if WINDOWS.is(self.get_os()) { + WHERE_COMMAND + } else { + WHICH_COMMAND + }; + let driver_path = match self.run_shell_command( + shell, + flag, + self.format_one_arg(which_command, self.get_driver_name()), + ) { + Ok(path) => Some(path), + Err(_) => None, + }; + return (Some(parsed_version), driver_path); + } + (None, None) + } + Err(_) => (None, None), + } + } + + fn get_shell_command(&self) -> (&str, &str) { + if WINDOWS.is(self.get_os()) { + ("cmd", "/C") + } else { + ("sh", "-c") + } + } + fn is_browser_version_unstable(&self) -> bool { let browser_version = self.get_browser_version(); browser_version.eq_ignore_ascii_case(BETA) @@ -231,6 +273,27 @@ pub trait SeleniumManager { self.set_driver_version(driver_version); } + let (in_path_driver_version, in_path_driver_path) = self.find_driver_in_path(); + if let (Some(found_driver_version), Some(found_driver_path)) = + (in_path_driver_version, in_path_driver_path) + { + if found_driver_version.eq(self.get_driver_version()) { + self.get_logger().debug(format!( + "Found {} {} in PATH: {}", + self.get_driver_name(), + found_driver_version, + found_driver_path + )); + return Ok(PathBuf::from(found_driver_path)); + } else { + self.get_logger().warn(format!( + "Incompatible release of {} (version {}) detected in PATH: {}", + self.get_driver_name(), + found_driver_version, + found_driver_path + )); + } + } let driver_path = self.get_driver_path_in_cache(); if driver_path.exists() { self.get_logger().debug(format!( @@ -255,7 +318,10 @@ pub trait SeleniumManager { let output = Command::new(command).args([flag, args.as_str()]).output()?; self.get_logger().debug(format!("{:?}", output)); - Ok(String::from_utf8_lossy(&output.stdout).to_string()) + Ok( + strip_trailing_newline(String::from_utf8_lossy(&output.stdout).to_string().as_str()) + .to_string(), + ) } fn get_major_version(&self, full_version: &str) -> Result> { @@ -454,3 +520,10 @@ pub fn http_client_builder() -> ClientBuilder { .danger_accept_invalid_certs(true) .use_rustls_tls() } + +fn strip_trailing_newline(input: &str) -> &str { + input + .strip_suffix("\r\n") + .or_else(|| input.strip_suffix('\n')) + .unwrap_or(input) +} diff --git a/rust/tests/cli_tests.rs b/rust/tests/cli_tests.rs index 8c02e0967f555..e08c34dcd7994 100644 --- a/rust/tests/cli_tests.rs +++ b/rust/tests/cli_tests.rs @@ -55,7 +55,7 @@ fn ok_test( println!("{}", output); assert!(output.contains(&driver_name)); - if !browser_version.is_empty() { + if !browser_version.is_empty() && output.contains("cache") { assert!(output.contains(&driver_version)); } }