From c4fa4dadf9f556976d1b4977b792e5ea0fb8e65c Mon Sep 17 00:00:00 2001 From: Alfie John Date: Thu, 24 Oct 2024 18:58:35 +1100 Subject: [PATCH] Add tests and highlight issues with should_panic (#654) --- Cargo.lock | 19 +- Cargo.toml | 1 + component/src/lib.rs | 132 ++++++++++ src/target_triple.rs | 102 +++++++ src/toolchain_override.rs | 8 +- tests/toolchain.rs | 540 +++++++++++++++++++++++++++++++++++++- 6 files changed, 788 insertions(+), 14 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 4798b105..a6bae7f4 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -507,6 +507,7 @@ dependencies = [ "flate2", "indicatif", "indoc", + "regex", "semver", "serde", "serde_json", @@ -870,14 +871,14 @@ dependencies = [ [[package]] name = "regex" -version = "1.10.4" +version = "1.11.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c117dbdfde9c8308975b6a18d71f3f385c89461f7b3fb054288ecf2a2058ba4c" +checksum = "38200e5ee88914975b69f657f0801b6f6dccafd44fd9326302a4aaeecfacb1d8" dependencies = [ "aho-corasick", "memchr", - "regex-automata 0.4.6", - "regex-syntax 0.8.3", + "regex-automata 0.4.8", + "regex-syntax 0.8.5", ] [[package]] @@ -891,13 +892,13 @@ dependencies = [ [[package]] name = "regex-automata" -version = "0.4.6" +version = "0.4.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "86b83b8b9847f9bf95ef68afb0b8e6cdb80f498442f5179a29fad448fcc1eaea" +checksum = "368758f23274712b504848e9d5a6f010445cc8b87a7cdb4d7cbee666c1288da3" dependencies = [ "aho-corasick", "memchr", - "regex-syntax 0.8.3", + "regex-syntax 0.8.5", ] [[package]] @@ -908,9 +909,9 @@ checksum = "f162c6dd7b008981e4d40210aca20b4bd0f9b60ca9271061b07f78537722f2e1" [[package]] name = "regex-syntax" -version = "0.8.3" +version = "0.8.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "adad44e29e4c806119491a7f06f03de4d1af22c3a680dd47f1e6e179439d1f56" +checksum = "2b15c43186be67a4fd63bee50d0303afffcef381492ebe2c5d87f324e1b8815c" [[package]] name = "ring" diff --git a/Cargo.toml b/Cargo.toml index d397b64e..2ec040a1 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -47,6 +47,7 @@ members = ["component", "ci/build-channel", "ci/compare-versions"] [dev-dependencies] chrono = "0.4.33" +regex = "1.11" strip-ansi-escapes = "0.2.0" [lints.clippy] diff --git a/component/src/lib.rs b/component/src/lib.rs index 8beb0758..8a76211b 100644 --- a/component/src/lib.rs +++ b/component/src/lib.rs @@ -61,6 +61,11 @@ impl Component { && name != FORC) || name == FORC_CLIENT } + + pub fn is_in_same_distribution(forc: &Component, component: &Component) -> bool { + component.repository_name == forc.repository_name + && component.tarball_prefix == forc.tarball_prefix + } } #[derive(Debug)] @@ -253,4 +258,131 @@ mod tests { fn test_collect_plugin_executables() { assert!(Components::collect_plugin_executables().is_ok()); } + + #[test] + fn test_from_name_forc() { + let component = Component::from_name(FORC).unwrap(); + assert_eq!(component.name, FORC, "forc is a publishable component"); + } + + #[test] + fn test_from_name_publishables() { + for publishable in Components::collect_publishables().unwrap() { + let component = Component::from_name(&publishable.name).unwrap(); + assert_eq!( + component.name, publishable.name, + "{} is a publishable component", + publishable.name + ); + } + } + + #[test] + fn test_from_name_plugins() { + for plugin in Components::collect_plugins().unwrap() { + let component = Component::from_name(&plugin.name).unwrap(); + assert_eq!( + component.name, plugin.name, + "{} is a plugin in {}", + plugin.name, component.name + ); + } + } + + // This currently panics because resolving the component from the executable + // is incorrect for some executables + #[test] + #[should_panic] + fn test_from_name_executables() { + for executable in &Components::collect_plugin_executables().unwrap() { + let component = Component::from_name(executable).unwrap(); + assert!( + component.executables.contains(executable), + "{} is an executable in {}", + executable, + component.name + ); + } + } + + #[test] + fn test_is_distributed_by_forc_forc() { + assert!( + Components::is_distributed_by_forc("forc"), + "forc is distributed by forc" + ); + } + + #[test] + fn test_is_distributed_by_forc_publishables() { + for publishable in Components::collect_publishables().unwrap() { + let is_distributed = Components::is_distributed_by_forc(&publishable.name); + + if publishable.name == FORC { + assert!(is_distributed, "forc is distributed by forc"); + } else { + assert!( + !is_distributed, + "{} is not distributed by forc", + publishable.name + ); + } + } + } + + // This currently panics because is_distributed_by_forc() is incorrect for + // some plugins + #[test] + #[should_panic] + fn test_is_distributed_by_forc_plugins() { + let forc = Component::from_name(FORC).unwrap(); + + for plugin in Components::collect_plugins().unwrap() { + let component = Component::from_name(&plugin.name).unwrap(); + let is_distributed = Components::is_distributed_by_forc(&component.name); + + if Component::is_in_same_distribution(&forc, &component) { + assert!(is_distributed, "{} is distributed by forc", plugin.name) + } else { + assert!( + !is_distributed, + "{} is not distributed by forc", + component.name + ) + } + } + } + + // This currently panics because is_distributed_by_forc() is incorrect for + // some executables + #[test] + #[should_panic] + fn test_is_distributed_by_forc_executables() { + let forc = Component::from_name(FORC).unwrap(); + + for executable in Components::collect_plugin_executables().unwrap() { + let components = Components::collect().unwrap(); + let component = components + .component + .values() + .find(|c| c.executables.contains(&executable)) + .unwrap(); + + let is_distributed = Components::is_distributed_by_forc(&component.name); + + if Component::is_in_same_distribution(&forc, component) { + assert!( + is_distributed, + "{:?} is distributed by forc", + component.name + ) + } else { + assert!( + !is_distributed, + "{:?} is not distributed by forc", + component.name + ) + } + } + } } diff --git a/src/target_triple.rs b/src/target_triple.rs index da18f9c5..1e480fec 100644 --- a/src/target_triple.rs +++ b/src/target_triple.rs @@ -90,3 +90,105 @@ impl TargetTriple { } } } + +#[cfg(test)] +mod test_from_component { + use super::*; + use component::{Component, Components}; + use regex::Regex; + + #[test] + fn forc() { + let target_triple = TargetTriple::from_component("forc").unwrap(); + let expected_triple = Regex::new("^(darwin|linux)_(arm64|amd64)$").unwrap(); + assert!( + expected_triple.is_match(&target_triple.0), + "forc has triple '{}'", + &target_triple.0 + ); + } + + #[test] + fn publishables() { + let forc = Component::from_name("forc").unwrap(); + + for publishable in Components::collect_publishables().unwrap() { + let component = Component::from_name(&publishable.name).unwrap(); + let target_triple = TargetTriple::from_component(&component.name).unwrap(); + + let expected_triple_regex = if Component::is_in_same_distribution(&forc, &component) { + "^(darwin|linux)_(arm64|amd64)$" + } else { + "^(aarch64|x86_64)-(apple|unknown)-(darwin|linux-gnu)$" + }; + + let expected_triple = Regex::new(expected_triple_regex).unwrap(); + assert!( + expected_triple.is_match(&target_triple.0), + "{} has triple '{}'", + publishable.name, + &target_triple.0 + ); + } + } + + // This currently panics because calculating the triple is incorrect for + // some plugins + #[test] + #[should_panic] + fn plugins() { + let forc = Component::from_name("forc").unwrap(); + + for plugin in Components::collect_plugins().unwrap() { + let component = Component::from_name(&plugin.name).unwrap(); + let target_triple = TargetTriple::from_component(&component.name).unwrap(); + + let expected_triple_regex = if Component::is_in_same_distribution(&forc, &component) { + "^(darwin|linux)_(arm64|amd64)$" + } else { + "^(aarch64|x86_64)-(apple|unknown)-(darwin|linux-gnu)$" + }; + + let expected_triple = Regex::new(expected_triple_regex).unwrap(); + assert!( + expected_triple.is_match(&target_triple.0), + "{} has triple '{}'", + plugin.name, + &target_triple.0 + ); + } + } + + // This currently panics because calculating the triple is incorrect for + // some executables + #[test] + #[should_panic] + fn executables() { + let forc = Component::from_name("forc").unwrap(); + + for executable in Components::collect_plugin_executables().unwrap() { + let components = Components::collect().unwrap(); + let component = components + .component + .values() + .find(|c| c.executables.contains(&executable)) + .unwrap(); + + let target_triple = TargetTriple::from_component(&component.name).unwrap(); + + let expected_triple_regex = if Component::is_in_same_distribution(&forc, component) { + "^(darwin|linux)_(arm64|amd64)$" + } else { + "^(aarch64|x86_64)-(apple|unknown)-(darwin|linux-gnu)$" + }; + + let expected_triple = Regex::new(expected_triple_regex).unwrap(); + assert!( + expected_triple.is_match(&target_triple.0), + "{} has triple '{}'", + executable, + &target_triple.0 + ); + } + } +} diff --git a/src/toolchain_override.rs b/src/toolchain_override.rs index 3c392b9c..7a5108d4 100644 --- a/src/toolchain_override.rs +++ b/src/toolchain_override.rs @@ -21,27 +21,27 @@ use tracing::{info, warn}; // additional info to OverrideCfg (representation of 'fuel-toolchain.toml'). // In this case, we want the path to the toml file. More info might be // needed in future. -#[derive(Debug, Deserialize, Serialize)] +#[derive(Clone, Debug, Deserialize, Serialize)] pub struct ToolchainOverride { pub cfg: OverrideCfg, pub path: PathBuf, } // Representation of the entire 'fuel-toolchain.toml'. -#[derive(Debug, Deserialize, Serialize)] +#[derive(Clone, Debug, Deserialize, Serialize)] pub struct OverrideCfg { pub toolchain: ToolchainCfg, pub components: Option>, } // Represents the [toolchain] table in 'fuel-toolchain.toml'. -#[derive(Debug, Deserialize)] +#[derive(Clone, Debug, Deserialize)] pub struct ToolchainCfg { #[serde(deserialize_with = "deserialize_channel")] pub channel: Channel, } -#[derive(Debug, Deserialize, Serialize)] +#[derive(Clone, Debug, Deserialize, Serialize)] pub struct Channel { pub name: String, pub date: Option, diff --git a/tests/toolchain.rs b/tests/toolchain.rs index fc9bdc44..70b56fc2 100644 --- a/tests/toolchain.rs +++ b/tests/toolchain.rs @@ -3,8 +3,17 @@ pub mod testcfg; use anyhow::Result; use chrono::{Duration, Utc}; +use component::Component; use expects::expect_files_exist; -use fuelup::{channel, fmt::format_toolchain_with_target, target_triple::TargetTriple}; +use fuelup::{ + channel, + constants::FUEL_TOOLCHAIN_TOML_FILE, + fmt::format_toolchain_with_target, + target_triple::TargetTriple, + toolchain::Toolchain, + toolchain_override::{self, OverrideCfg, ToolchainCfg, ToolchainOverride}, +}; +use std::str::FromStr; use testcfg::{FuelupState, ALL_BINS, CUSTOM_TOOLCHAIN_NAME, DATE}; fn yesterday() -> String { @@ -175,3 +184,532 @@ fn fuelup_toolchain_new_disallowed_with_target() -> Result<()> { })?; Ok(()) } + +#[test] +fn direct_proxy_install_toolchain_in_store_forc() { + // Test steps: + // - trigger direct proxy call + // - install override toolchain + // - delete toolchain but keep it in store + // - trigger another direct proxy call + // - check forc is symlinked from the store + + testcfg::setup(FuelupState::LatestToolchainInstalled, &|cfg| { + let toolchain_override = ToolchainOverride { + cfg: OverrideCfg::new( + ToolchainCfg { + channel: toolchain_override::Channel::from_str(&format!( + "nightly-{}", + yesterday() + )) + .unwrap(), + }, + None, + ), + path: cfg.home.join(FUEL_TOOLCHAIN_TOML_FILE), + }; + + testcfg::setup_override_file(toolchain_override.clone()).unwrap(); + + // trigger direct_proxy install with toolchain override + cfg.forc(&["--version"]); + + // delete toolchain but keep it in store + + let toolchain = Toolchain::new(&format!("nightly-{}", yesterday())).unwrap(); + let toolchain_bin_dir = cfg.toolchain_bin_dir(toolchain.name.as_str()); + let toolchain_dir = &toolchain_bin_dir.parent().unwrap(); + std::fs::remove_dir_all(toolchain_dir).unwrap(); + + // trigger direct_proxy install with toolchain override already in store + cfg.forc(&["--version"]); + + assert!( + toolchain_bin_dir.join("forc").exists(), + "forc executable not found", + ); + }) + .unwrap(); +} + +#[test] +fn direct_proxy_install_toolchain_in_store_publishable() { + // Test steps: + // - trigger direct proxy call + // - install override toolchain + // - delete toolchain but keep it in store + // - trigger another direct proxy call + // - check executables are symlinked from the store + + // As these tests can take a long time, chose `fuel-core` as the non-forc + // publishable component to test + let component = Component::from_name("fuel-core").unwrap(); + + testcfg::setup(FuelupState::LatestToolchainInstalled, &|cfg| { + let toolchain_override = ToolchainOverride { + cfg: OverrideCfg::new( + ToolchainCfg { + channel: toolchain_override::Channel::from_str(&format!( + "nightly-{}", + yesterday() + )) + .unwrap(), + }, + Some( + vec![(component.name.clone(), "0.61.0".parse().unwrap())] + .into_iter() + .collect(), + ), + ), + path: cfg.home.join(FUEL_TOOLCHAIN_TOML_FILE), + }; + + testcfg::setup_override_file(toolchain_override.clone()).unwrap(); + + // trigger direct_proxy install with toolchain override + cfg.exec(&component.name, &["--version"]); + + // delete toolchain but keep it in store + + let toolchain = Toolchain::new(&format!("nightly-{}", yesterday())).unwrap(); + let toolchain_bin_dir = cfg.toolchain_bin_dir(toolchain.name.as_str()); + let toolchain_dir = &toolchain_bin_dir.parent().unwrap(); + std::fs::remove_dir_all(toolchain_dir).unwrap(); + + // trigger direct_proxy install with toolchain override already in store + cfg.exec(&component.name, &["--version"]); + + for executable in component.executables.iter() { + assert!( + toolchain_bin_dir.join(executable).exists(), + "Executable not found: {}", + executable + ); + } + }) + .unwrap(); +} + +// This currently panics because some symlinks are incorrectly created during +// toolchain install +#[test] +#[should_panic] +fn direct_proxy_install_toolchain_in_store_forc_plugin() { + // Test steps: + // - trigger direct proxy call + // - install override toolchain + // - delete toolchain but keep it in store + // - trigger another direct proxy call + // - check executables are symlinked from the store + + // As these tests can take a long time, chose `forc-client` as the forc + // plugin component to test + let component = Component::from_name("forc-client").unwrap(); + + testcfg::setup(FuelupState::LatestToolchainInstalled, &|cfg| { + let toolchain_override = ToolchainOverride { + cfg: OverrideCfg::new( + ToolchainCfg { + channel: toolchain_override::Channel::from_str(&format!( + "nightly-{}", + yesterday() + )) + .unwrap(), + }, + Some( + vec![(component.name.clone(), "0.61.0".parse().unwrap())] + .into_iter() + .collect(), + ), + ), + path: cfg.home.join(FUEL_TOOLCHAIN_TOML_FILE), + }; + + testcfg::setup_override_file(toolchain_override.clone()).unwrap(); + + // trigger direct_proxy install with toolchain override + cfg.exec(component.executables.first().unwrap(), &["--version"]); + + // delete toolchain but keep it in store + + let toolchain = Toolchain::new(&format!("nightly-{}", yesterday())).unwrap(); + let toolchain_bin_dir = cfg.toolchain_bin_dir(toolchain.name.as_str()); + let toolchain_dir = &toolchain_bin_dir.parent().unwrap(); + std::fs::remove_dir_all(toolchain_dir).unwrap(); + + // trigger direct_proxy install with toolchain override already in store + cfg.exec(component.executables.first().unwrap(), &["--version"]); + + for executable in component.executables.iter() { + assert!( + toolchain_bin_dir.join(executable).exists(), + "Executable not found: {}", + executable + ); + } + }) + .unwrap(); +} + +// This currently panics because some symlinks are incorrectly created during +// toolchain install +#[test] +#[should_panic] +fn direct_proxy_install_toolchain_in_store_forc_plugin_external() { + // Test steps: + // - trigger direct proxy call + // - install override toolchain + // - delete toolchain but keep it in store + // - trigger another direct proxy call + // - check executables are symlinked from the store + + // As these tests can take a long time, chose `forc-tx` as the forc plugin + // component not defined it forc's component to test + let component = Component::from_name("forc-tx").unwrap(); + + testcfg::setup(FuelupState::LatestToolchainInstalled, &|cfg| { + let toolchain_override = ToolchainOverride { + cfg: OverrideCfg::new( + ToolchainCfg { + channel: toolchain_override::Channel::from_str(&format!( + "nightly-{}", + yesterday() + )) + .unwrap(), + }, + Some( + vec![(component.name.clone(), "0.61.0".parse().unwrap())] + .into_iter() + .collect(), + ), + ), + path: cfg.home.join(FUEL_TOOLCHAIN_TOML_FILE), + }; + + testcfg::setup_override_file(toolchain_override.clone()).unwrap(); + + // trigger direct_proxy install with toolchain override + cfg.exec(component.executables.first().unwrap(), &["--version"]); + + // delete toolchain but keep it in store + + let toolchain = Toolchain::new(&format!("nightly-{}", yesterday())).unwrap(); + let toolchain_bin_dir = cfg.toolchain_bin_dir(toolchain.name.as_str()); + let toolchain_dir = &toolchain_bin_dir.parent().unwrap(); + std::fs::remove_dir_all(toolchain_dir).unwrap(); + + // trigger direct_proxy install with toolchain override already in store + cfg.exec(component.executables.first().unwrap(), &["--version"]); + + for executable in component.executables.iter() { + assert!( + toolchain_bin_dir.join(executable).exists(), + "Executable not found: {}", + executable + ); + } + }) + .unwrap(); +} + +#[test] +fn direct_proxy_install_toolchain_in_store_not_forc_plugin() { + // Test steps: + // - trigger direct proxy call + // - install override toolchain + // - delete toolchain but keep it in store + // - trigger another direct proxy call + // - check executables are symlinked from the store + + // As these tests can take a long time, chose `forc-wallet` as the non-forc + // plugin component to test + let component = Component::from_name("forc-wallet").unwrap(); + + testcfg::setup(FuelupState::LatestToolchainInstalled, &|cfg| { + let toolchain_override = ToolchainOverride { + cfg: OverrideCfg::new( + ToolchainCfg { + channel: toolchain_override::Channel::from_str(&format!( + "nightly-{}", + yesterday() + )) + .unwrap(), + }, + Some( + vec![(component.name.clone(), "0.61.0".parse().unwrap())] + .into_iter() + .collect(), + ), + ), + path: cfg.home.join(FUEL_TOOLCHAIN_TOML_FILE), + }; + + testcfg::setup_override_file(toolchain_override.clone()).unwrap(); + + // trigger direct_proxy install with toolchain override + cfg.exec(component.executables.first().unwrap(), &["--version"]); + + // delete toolchain but keep it in store + + let toolchain = Toolchain::new(&format!("nightly-{}", yesterday())).unwrap(); + let toolchain_bin_dir = cfg.toolchain_bin_dir(toolchain.name.as_str()); + let toolchain_dir = &toolchain_bin_dir.parent().unwrap(); + std::fs::remove_dir_all(toolchain_dir).unwrap(); + + // trigger direct_proxy install with toolchain override already in store + cfg.exec(component.executables.first().unwrap(), &["--version"]); + + for executable in component.executables.iter() { + assert!( + toolchain_bin_dir.join(executable).exists(), + "Executable not found: {}", + executable + ); + } + }) + .unwrap(); +} + +// This currently panics because some symlinks are incorrectly created during +// toolchain install +#[test] +fn direct_proxy_install_toolchain_not_in_store_forc() { + // Test steps: + // - trigger direct proxy call + // - install override toolchain + // - check executable are symlinked from the store + + testcfg::setup(FuelupState::LatestToolchainInstalled, &|cfg| { + let toolchain_override = ToolchainOverride { + cfg: OverrideCfg::new( + ToolchainCfg { + channel: toolchain_override::Channel::from_str(&format!( + "nightly-{}", + yesterday() + )) + .unwrap(), + }, + None, + ), + path: cfg.home.join(FUEL_TOOLCHAIN_TOML_FILE), + }; + + testcfg::setup_override_file(toolchain_override.clone()).unwrap(); + + // trigger direct_proxy install with toolchain override + cfg.forc(&["--version"]); + + let toolchain = Toolchain::new(&format!("nightly-{}", yesterday())).unwrap(); + let toolchain_bin_dir = cfg.toolchain_bin_dir(toolchain.name.as_str()); + + assert!( + toolchain_bin_dir.join("forc").exists(), + "forc executable not found", + ); + }) + .unwrap(); +} + +// This currently panics because some symlinks are incorrectly created during +// toolchain install +#[test] +fn direct_proxy_install_toolchain_not_in_store_publishable() { + // Test steps: + // - trigger direct proxy call + // - install override toolchain + // - check executables are symlinked from the store + + // As these tests can take a long time, chose `fuel-core` as the non-forc + // publishable component to test + let component = Component::from_name("fuel-core").unwrap(); + + testcfg::setup(FuelupState::LatestToolchainInstalled, &|cfg| { + let toolchain_override = ToolchainOverride { + cfg: OverrideCfg::new( + ToolchainCfg { + channel: toolchain_override::Channel::from_str(&format!( + "nightly-{}", + yesterday() + )) + .unwrap(), + }, + Some( + vec![(component.name.clone(), "0.61.0".parse().unwrap())] + .into_iter() + .collect(), + ), + ), + path: cfg.home.join(FUEL_TOOLCHAIN_TOML_FILE), + }; + + testcfg::setup_override_file(toolchain_override.clone()).unwrap(); + + // trigger direct_proxy install with toolchain override + cfg.exec(&component.name, &["--version"]); + + let toolchain = Toolchain::new(&format!("nightly-{}", yesterday())).unwrap(); + let toolchain_bin_dir = cfg.toolchain_bin_dir(toolchain.name.as_str()); + + for executable in component.executables.iter() { + assert!( + toolchain_bin_dir.join(executable).exists(), + "Executable not found: {}", + executable + ); + } + }) + .unwrap(); +} + +// This currently panics because some symlinks are incorrectly created during +// toolchain install +#[test] +#[should_panic] +fn direct_proxy_install_toolchain_not_in_store_forc_plugin() { + // Test steps: + // - trigger direct proxy call + // - install override toolchain + // - check executables are symlinked from the store + + // As these tests can take a long time, chose `forc-client` as the forc + // plugin component to test + let component = Component::from_name("forc-client").unwrap(); + + testcfg::setup(FuelupState::LatestToolchainInstalled, &|cfg| { + let toolchain_override = ToolchainOverride { + cfg: OverrideCfg::new( + ToolchainCfg { + channel: toolchain_override::Channel::from_str(&format!( + "nightly-{}", + yesterday() + )) + .unwrap(), + }, + Some( + vec![(component.name.clone(), "0.61.0".parse().unwrap())] + .into_iter() + .collect(), + ), + ), + path: cfg.home.join(FUEL_TOOLCHAIN_TOML_FILE), + }; + + testcfg::setup_override_file(toolchain_override.clone()).unwrap(); + + // trigger direct_proxy install with toolchain override + cfg.exec(component.executables.first().unwrap(), &["--version"]); + + let toolchain = Toolchain::new(&format!("nightly-{}", yesterday())).unwrap(); + let toolchain_bin_dir = cfg.toolchain_bin_dir(toolchain.name.as_str()); + + for executable in component.executables.iter() { + assert!( + toolchain_bin_dir.join(executable).exists(), + "Executable not found: {}", + executable + ); + } + }) + .unwrap(); +} + +// This currently panics because some symlinks are incorrectly created during +// toolchain install +#[test] +#[should_panic] +fn direct_proxy_install_toolchain_not_in_store_forc_plugin_external() { + // Test steps: + // - trigger direct proxy call + // - install override toolchain + // - check executables are symlinked from the store + + // As these tests can take a long time, chose `forc-tx` as the forc plugin + // component not defined it forc's component to test + let component = Component::from_name("forc-tx").unwrap(); + + testcfg::setup(FuelupState::LatestToolchainInstalled, &|cfg| { + let toolchain_override = ToolchainOverride { + cfg: OverrideCfg::new( + ToolchainCfg { + channel: toolchain_override::Channel::from_str(&format!( + "nightly-{}", + yesterday() + )) + .unwrap(), + }, + Some( + vec![(component.name.clone(), "0.61.0".parse().unwrap())] + .into_iter() + .collect(), + ), + ), + path: cfg.home.join(FUEL_TOOLCHAIN_TOML_FILE), + }; + + testcfg::setup_override_file(toolchain_override.clone()).unwrap(); + + // trigger direct_proxy install with toolchain override + cfg.exec(component.executables.first().unwrap(), &["--version"]); + + let toolchain = Toolchain::new(&format!("nightly-{}", yesterday())).unwrap(); + let toolchain_bin_dir = cfg.toolchain_bin_dir(toolchain.name.as_str()); + + for executable in component.executables.iter() { + assert!( + toolchain_bin_dir.join(executable).exists(), + "Executable not found: {}", + executable + ); + } + }) + .unwrap(); +} + +#[test] +fn direct_proxy_install_toolchain_not_in_store_not_forc_plugin() { + // Test steps: + // - trigger direct proxy call + // - install override toolchain + // - check executables are symlinked from the store + + // As these tests can take a long time, chose `forc-wallet` as the non-forc + // plugin component to test + let component = Component::from_name("forc-wallet").unwrap(); + + testcfg::setup(FuelupState::LatestToolchainInstalled, &|cfg| { + let toolchain_override = ToolchainOverride { + cfg: OverrideCfg::new( + ToolchainCfg { + channel: toolchain_override::Channel::from_str(&format!( + "nightly-{}", + yesterday() + )) + .unwrap(), + }, + Some( + vec![(component.name.clone(), "0.61.0".parse().unwrap())] + .into_iter() + .collect(), + ), + ), + path: cfg.home.join(FUEL_TOOLCHAIN_TOML_FILE), + }; + + testcfg::setup_override_file(toolchain_override.clone()).unwrap(); + + // trigger direct_proxy install with toolchain override + cfg.exec(component.executables.first().unwrap(), &["--version"]); + + let toolchain = Toolchain::new(&format!("nightly-{}", yesterday())).unwrap(); + let toolchain_bin_dir = cfg.toolchain_bin_dir(toolchain.name.as_str()); + + for executable in component.executables.iter() { + assert!( + toolchain_bin_dir.join(executable).exists(), + "Executable not found: {}", + executable + ); + } + }) + .unwrap(); +} \ No newline at end of file