Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Upstream changes from "Windows ARM in test framework"-investigation #7316

Merged
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion test/test-manager/docs/config.md
Original file line number Diff line number Diff line change
Expand Up @@ -57,7 +57,7 @@ A configuration containing one Debian 12 VM and one Windows 11 VM
"image_path": "$VM_IMAGES/windows11.qcow2",
"os_type": "windows",
"package_type": null,
"architecture": null,
"architecture": "x64",
"provisioner": "noop",
"ssh_user": null,
"ssh_password": null,
Expand Down
14 changes: 7 additions & 7 deletions test/test-manager/src/config.rs
Original file line number Diff line number Diff line change
Expand Up @@ -154,8 +154,8 @@ pub struct VmConfig {
pub package_type: Option<PackageType>,

/// CPU architecture
#[arg(long, required_if_eq("os_type", "linux"))]
pub architecture: Option<Architecture>,
#[arg(long)]
pub architecture: Architecture,

/// Tool to use for provisioning
#[arg(long, default_value = "noop")]
Expand Down Expand Up @@ -203,8 +203,8 @@ impl VmConfig {
pub fn get_default_runner_dir(&self) -> PathBuf {
let target_dir = self.get_target_dir();
let subdir = match self.architecture {
None | Some(Architecture::X64) => self.get_x64_runner_subdir(),
Some(Architecture::Aarch64) => self.get_aarch64_runner_subdir(),
Architecture::X64 => self.get_x64_runner_subdir(),
Architecture::Aarch64 => self.get_aarch64_runner_subdir(),
};

target_dir.join(subdir)
Expand Down Expand Up @@ -282,10 +282,10 @@ pub enum Architecture {
}

impl Architecture {
pub fn get_identifiers(&self) -> &[&'static str] {
pub fn get_identifiers(self) -> Vec<&'static str> {
match self {
Architecture::X64 => &["x86_64", "amd64"],
Architecture::Aarch64 => &["arm64", "aarch64"],
Architecture::X64 => vec!["x86_64", "amd64"],
Architecture::Aarch64 => vec!["arm64", "aarch64"],
}
}
}
Expand Down
30 changes: 16 additions & 14 deletions test/test-manager/src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ use std::{net::SocketAddr, path::PathBuf};

use anyhow::{Context, Result};
use clap::{builder::PossibleValuesParser, Parser};
use package::TargetInfo;
use tests::{config::TEST_CONFIG, get_filtered_tests};
use vm::provision;

Expand Down Expand Up @@ -270,22 +271,10 @@ async fn main() -> Result<()> {
log::debug!("Mullvad host: {mullvad_host}");

let vm_config = vm::get_vm_config(&config, &vm).context("Cannot get VM config")?;

let summary_logger = match test_report {
Some(path) => Some(
summary::SummaryLogger::new(
&vm,
test_rpc::meta::Os::from(vm_config.os_type),
&path,
)
.await
.context("Failed to create summary logger")?,
),
None => None,
};
let runner_target = TargetInfo::try_from(vm_config)?;

let manifest = package::get_app_manifest(
vm_config,
runner_target,
app_package,
app_package_to_upgrade_from,
gui_package,
Expand Down Expand Up @@ -337,6 +326,19 @@ async fn main() -> Result<()> {

let skip_wait = vm_config.provisioner != config::Provisioner::Noop;

let summary_logger = match test_report {
Some(path) => Some(
summary::SummaryLogger::new(
&vm,
test_rpc::meta::Os::from(vm_config.os_type),
&path,
)
.await
.context("Failed to create summary logger")?,
),
None => None,
};

let result = run_tests::run(&*instance, tests, skip_wait, !verbose, summary_logger)
.await
.context("Tests failed");
Expand Down
103 changes: 78 additions & 25 deletions test/test-manager/src/package.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
use crate::config::{Architecture, OsType, PackageType, VmConfig};
use anyhow::{Context, Result};
use anyhow::{bail, Context, Result};
use itertools::Itertools;
use regex::Regex;
use std::{
Expand All @@ -14,24 +14,38 @@ pub struct Manifest {
pub gui_package_path: Option<PathBuf>,
}

/// Basic metadata about the test runner target platform such as OS, architecture and package
/// manager.
#[derive(Debug, Clone, Copy)]
pub enum TargetInfo {
Windows {
arch: Architecture,
},
Macos {
arch: Architecture,
},
Linux {
arch: Architecture,
package_type: PackageType,
},
}

/// Obtain app packages and their filenames
/// If it's a path, use the path.
/// If it corresponds to a file in packages/, use that package.
/// TODO: If it's a git tag or rev, download it.
pub fn get_app_manifest(
config: &VmConfig,
runner_target: TargetInfo,
app_package: String,
app_package_to_upgrade_from: Option<String>,
gui_package: Option<String>,
package_dir: Option<PathBuf>,
) -> Result<Manifest> {
let package_type = (config.os_type, config.package_type, config.architecture);

let app_package_path = find_app(&app_package, false, package_type, package_dir.as_ref())?;
let app_package_path = find_app(&app_package, false, runner_target, package_dir.as_ref())?;
log::info!("App package: {}", app_package_path.display());

let app_package_to_upgrade_from_path = app_package_to_upgrade_from
.map(|app| find_app(&app, false, package_type, package_dir.as_ref()))
.map(|app| find_app(&app, false, runner_target, package_dir.as_ref()))
.transpose()?;
log::info!("App package to upgrade from: {app_package_to_upgrade_from_path:?}");

Expand All @@ -52,7 +66,7 @@ pub fn get_app_manifest(
None => &app_version,
},
true,
package_type,
runner_target,
Some(&ui_e2e_package_dir),
);

Expand Down Expand Up @@ -86,7 +100,7 @@ pub fn get_version_from_path(app_package_path: &Path) -> Result<String, anyhow::
fn find_app(
app: &str,
e2e_bin: bool,
package_type: (OsType, Option<PackageType>, Option<Architecture>),
runner_target: TargetInfo,
package_dir: Option<&PathBuf>,
) -> Result<PathBuf> {
// If it's a path, use that path
Expand All @@ -112,18 +126,18 @@ fn find_app(
e2e_bin ||
path
.extension()
.map(|m_ext| m_ext.eq_ignore_ascii_case(get_ext(package_type)))
.map(|m_ext| m_ext.eq_ignore_ascii_case(runner_target.get_ext()))
.unwrap_or(false)
}) // Filter out irrelevant platforms
.map(|path| {
let u8_path = path.as_os_str().to_string_lossy().to_ascii_lowercase();
(path, u8_path)
})
.filter(|(_path, u8_path)| !(e2e_bin ^ u8_path.contains("app-e2e-tests"))) // Skip non-UI-e2e binaries or vice versa
.filter(|(_path, u8_path)| !e2e_bin || u8_path.contains(get_os_name(package_type))) // Filter out irrelevant platforms
.filter(|(_path, u8_path)| !e2e_bin || u8_path.contains(runner_target.get_os_name())) // Filter out irrelevant platforms
.filter(|(_path, u8_path)| {
let linux = e2e_bin || package_type.0 == OsType::Linux;
let matching_ident = package_type.2.map(|arch| arch.get_identifiers().iter().any(|id| u8_path.contains(id))).unwrap_or(true);
let linux = e2e_bin || runner_target.is_linux();
let matching_ident = runner_target.get_identifiers().any(|id| u8_path.contains(id));
// Skip for non-Linux, because there's only one package
!linux || matching_ident
}) // Skip file if it doesn't match the architecture
Expand All @@ -143,22 +157,61 @@ fn find_app(
})
}

fn get_ext(package_type: (OsType, Option<PackageType>, Option<Architecture>)) -> &'static str {
match package_type.0 {
OsType::Windows => "exe",
OsType::Macos => "pkg",
OsType::Linux => match package_type.1.expect("must specify package type") {
PackageType::Deb => "deb",
PackageType::Rpm => "rpm",
},
impl TargetInfo {
const fn is_linux(self) -> bool {
matches!(self, TargetInfo::Linux { .. })
}

const fn get_ext(self) -> &'static str {
match self {
TargetInfo::Windows { .. } => "exe",
TargetInfo::Macos { .. } => "pkg",
TargetInfo::Linux { package_type, .. } => match package_type {
PackageType::Deb => "deb",
PackageType::Rpm => "rpm",
},
}
}

const fn get_os_name(self) -> &'static str {
match self {
TargetInfo::Windows { .. } => "windows",
TargetInfo::Macos { .. } => "apple",
TargetInfo::Linux { .. } => "linux",
}
}

fn get_identifiers(self) -> impl Iterator<Item = &'static str> {
match self {
TargetInfo::Windows { arch }
| TargetInfo::Macos { arch }
| TargetInfo::Linux { arch, .. } => arch.get_identifiers().into_iter(),
}
}
}

fn get_os_name(package_type: (OsType, Option<PackageType>, Option<Architecture>)) -> &'static str {
match package_type.0 {
OsType::Windows => "windows",
OsType::Macos => "apple",
OsType::Linux => "linux",
impl TryFrom<&VmConfig> for TargetInfo {
type Error = anyhow::Error;

fn try_from(config: &VmConfig) -> std::result::Result<Self, Self::Error> {
let target_info = match config.os_type {
OsType::Windows => TargetInfo::Windows {
arch: config.architecture,
},
OsType::Macos => TargetInfo::Macos {
arch: config.architecture,
},
OsType::Linux => {
let Some(package_type) = config.package_type else {
bail!("Linux VM configuration did not specify any package type (Deb|Rpm)!");
};
TargetInfo::Linux {
arch: config.architecture,
package_type,
}
}
};
Ok(target_info)
}
}

Expand Down
Loading
Loading