Initial commit

Initial commit.
This commit is contained in:
kntran1
2026-03-23 14:40:39 -05:00
parent e84b2b4166
commit 4e2a5258a5
872 changed files with 165227 additions and 0 deletions

2
bootloader/mcuboot/ptest/.gitignore vendored Normal file
View File

@@ -0,0 +1,2 @@
target
.*.swp

556
bootloader/mcuboot/ptest/Cargo.lock generated Normal file
View File

@@ -0,0 +1,556 @@
# This file is automatically @generated by Cargo.
# It is not intended for manual editing.
version = 3
[[package]]
name = "addr2line"
version = "0.17.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b9ecd88a8c8378ca913a680cd98f0f13ac67383d35993f86c90a70e3f137816b"
dependencies = [
"gimli",
]
[[package]]
name = "adler"
version = "1.0.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f26201604c87b1e01bd3d98f8d5d9a8fcbb815e8cedb41ffccbeb4bf593a35fe"
[[package]]
name = "aho-corasick"
version = "0.7.18"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1e37cfd5e7657ada45f742d6e99ca5788580b5c529dc78faf11ece6dc702656f"
dependencies = [
"memchr",
]
[[package]]
name = "atty"
version = "0.2.14"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d9b39be18770d11421cdb1b9947a45dd3f37e93092cbf377614828a319d5fee8"
dependencies = [
"hermit-abi 0.1.19",
"libc",
"winapi",
]
[[package]]
name = "autocfg"
version = "1.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d468802bab17cbc0cc575e9b053f41e72aa36bfa6b7f55e3529ffa43161b97fa"
[[package]]
name = "backtrace"
version = "0.3.65"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "11a17d453482a265fd5f8479f2a3f405566e6ca627837aaddb85af8b1ab8ef61"
dependencies = [
"addr2line",
"cc",
"cfg-if",
"libc",
"miniz_oxide",
"object",
"rustc-demangle",
]
[[package]]
name = "bitflags"
version = "2.5.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "cf4b9d6a944f767f8e5e0db018570623c85f3d925ac718db4e06d0187adb21c1"
[[package]]
name = "cc"
version = "1.0.73"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "2fff2a6927b3bb87f9595d67196a70493f627687a71d87a0d692242c33f58c11"
[[package]]
name = "cfg-if"
version = "1.0.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd"
[[package]]
name = "chrono"
version = "0.4.19"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "670ad68c9088c2a963aaa298cb369688cf3f9465ce5e2d4ca10e6e0098a1ce73"
dependencies = [
"libc",
"num-integer",
"num-traits",
"time",
"winapi",
]
[[package]]
name = "clap"
version = "4.1.11"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "42dfd32784433290c51d92c438bb72ea5063797fc3cc9a21a8c4346bebbb2098"
dependencies = [
"bitflags",
"clap_derive",
"clap_lex",
"is-terminal",
"once_cell",
"strsim",
"termcolor",
]
[[package]]
name = "clap_derive"
version = "4.1.9"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "fddf67631444a3a3e3e5ac51c36a5e01335302de677bd78759eaa90ab1f46644"
dependencies = [
"heck",
"proc-macro-error",
"proc-macro2",
"quote",
"syn",
]
[[package]]
name = "clap_lex"
version = "0.3.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "033f6b7a4acb1f358c742aaca805c939ee73b4c6209ae4318ec7aca81c42e646"
dependencies = [
"os_str_bytes",
]
[[package]]
name = "env_logger"
version = "0.9.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "0b2cf0344971ee6c64c31be0d530793fba457d322dfec2810c453d0ef228f9c3"
dependencies = [
"atty",
"humantime",
"log",
"regex",
"termcolor",
]
[[package]]
name = "failure"
version = "0.1.8"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d32e9bd16cc02eae7db7ef620b392808b89f6a5e16bb3497d159c6b92a0f4f86"
dependencies = [
"backtrace",
"failure_derive",
]
[[package]]
name = "failure_derive"
version = "0.1.8"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "aa4da3c766cd7a0db8242e326e9e4e081edd567072893ed320008189715366a4"
dependencies = [
"proc-macro2",
"quote",
"syn",
"synstructure",
]
[[package]]
name = "gimli"
version = "0.26.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "78cc372d058dcf6d5ecd98510e7fbc9e5aec4d21de70f65fea8fecebcd881bd4"
[[package]]
name = "heck"
version = "0.4.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "95505c38b4572b2d910cecb0281560f54b440a19336cbbcb27bf6ce6adc6f5a8"
[[package]]
name = "hermit-abi"
version = "0.1.19"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "62b467343b94ba476dcb2500d242dadbb39557df889310ac77c5d99100aaac33"
dependencies = [
"libc",
]
[[package]]
name = "hermit-abi"
version = "0.3.9"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d231dfb89cfffdbc30e7fc41579ed6066ad03abda9e567ccafae602b97ec5024"
[[package]]
name = "humantime"
version = "2.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9a3a5bfb195931eeb336b2a7b4d761daec841b97f947d34394601737a7bba5e4"
[[package]]
name = "is-terminal"
version = "0.4.12"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f23ff5ef2b80d608d61efee834934d862cd92461afc0560dedf493e4c033738b"
dependencies = [
"hermit-abi 0.3.9",
"libc",
"windows-sys",
]
[[package]]
name = "libc"
version = "0.2.126"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "349d5a591cd28b49e1d1037471617a32ddcda5731b99419008085f72d5a53836"
[[package]]
name = "linked-hash-map"
version = "0.5.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7fb9b38af92608140b86b693604b9ffcc5824240a484d1ecd4795bacb2fe88f3"
[[package]]
name = "log"
version = "0.4.17"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "abb12e687cfb44aa40f41fc3978ef76448f9b6038cad6aef4259d3c095a2382e"
dependencies = [
"cfg-if",
]
[[package]]
name = "memchr"
version = "2.5.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "2dffe52ecf27772e601905b7522cb4ef790d2cc203488bbd0e2fe85fcb74566d"
[[package]]
name = "miniz_oxide"
version = "0.5.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "6f5c75688da582b8ffc1f1799e9db273f32133c49e048f614d22ec3256773ccc"
dependencies = [
"adler",
]
[[package]]
name = "num-integer"
version = "0.1.45"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "225d3389fb3509a24c93f5c29eb6bde2586b98d9f016636dff58d7c6f7569cd9"
dependencies = [
"autocfg",
"num-traits",
]
[[package]]
name = "num-traits"
version = "0.2.15"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "578ede34cf02f8924ab9447f50c28075b4d3e5b269972345e7e0372b38c6cdcd"
dependencies = [
"autocfg",
]
[[package]]
name = "num_cpus"
version = "1.13.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "19e64526ebdee182341572e50e9ad03965aa510cd94427a4549448f285e957a1"
dependencies = [
"hermit-abi 0.1.19",
"libc",
]
[[package]]
name = "object"
version = "0.28.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e42c982f2d955fac81dd7e1d0e1426a7d702acd9c98d19ab01083a6a0328c424"
dependencies = [
"memchr",
]
[[package]]
name = "once_cell"
version = "1.19.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "3fdb12b2476b595f9358c5161aa467c2438859caa136dec86c26fdd2efe17b92"
[[package]]
name = "os_str_bytes"
version = "6.6.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e2355d85b9a3786f481747ced0e0ff2ba35213a1f9bd406ed906554d7af805a1"
[[package]]
name = "proc-macro-error"
version = "1.0.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "da25490ff9892aab3fcf7c36f08cfb902dd3e71ca0f9f9517bea02a73a5ce38c"
dependencies = [
"proc-macro-error-attr",
"proc-macro2",
"quote",
"syn",
"version_check",
]
[[package]]
name = "proc-macro-error-attr"
version = "1.0.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a1be40180e52ecc98ad80b184934baf3d0d29f979574e439af5a55274b35f869"
dependencies = [
"proc-macro2",
"quote",
"version_check",
]
[[package]]
name = "proc-macro2"
version = "1.0.79"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e835ff2298f5721608eb1a980ecaee1aef2c132bf95ecc026a11b7bf3c01c02e"
dependencies = [
"unicode-ident",
]
[[package]]
name = "ptest"
version = "0.1.0"
dependencies = [
"chrono",
"clap",
"env_logger",
"failure",
"log",
"num_cpus",
"std-semaphore",
"yaml-rust",
]
[[package]]
name = "quote"
version = "1.0.20"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "3bcdf212e9776fbcb2d23ab029360416bb1706b1aea2d1a5ba002727cbcab804"
dependencies = [
"proc-macro2",
]
[[package]]
name = "regex"
version = "1.5.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d83f127d94bdbcda4c8cc2e50f6f84f4b611f69c902699ca385a39c3a75f9ff1"
dependencies = [
"aho-corasick",
"memchr",
"regex-syntax",
]
[[package]]
name = "regex-syntax"
version = "0.6.26"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "49b3de9ec5dc0a3417da371aab17d729997c15010e7fd24ff707773a33bddb64"
[[package]]
name = "rustc-demangle"
version = "0.1.21"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7ef03e0a2b150c7a90d01faf6254c9c48a41e95fb2a8c2ac1c6f0d2b9aefc342"
[[package]]
name = "std-semaphore"
version = "0.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "33ae9eec00137a8eed469fb4148acd9fc6ac8c3f9b110f52cd34698c8b5bfa0e"
[[package]]
name = "strsim"
version = "0.10.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "73473c0e59e6d5812c5dfe2a064a6444949f089e20eec9a2e5506596494e4623"
[[package]]
name = "syn"
version = "1.0.98"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c50aef8a904de4c23c788f104b7dddc7d6f79c647c7c8ce4cc8f73eb0ca773dd"
dependencies = [
"proc-macro2",
"quote",
"unicode-ident",
]
[[package]]
name = "synstructure"
version = "0.12.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f36bdaa60a83aca3921b5259d5400cbf5e90fc51931376a9bd4a0eb79aa7210f"
dependencies = [
"proc-macro2",
"quote",
"syn",
"unicode-xid",
]
[[package]]
name = "termcolor"
version = "1.1.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "bab24d30b911b2376f3a13cc2cd443142f0c81dda04c118693e35b3835757755"
dependencies = [
"winapi-util",
]
[[package]]
name = "time"
version = "0.1.44"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "6db9e6914ab8b1ae1c260a4ae7a49b6c5611b40328a735b21862567685e73255"
dependencies = [
"libc",
"wasi",
"winapi",
]
[[package]]
name = "unicode-ident"
version = "1.0.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5bd2fe26506023ed7b5e1e315add59d6f584c621d037f9368fea9cfb988f368c"
[[package]]
name = "unicode-xid"
version = "0.2.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "957e51f3646910546462e67d5f7599b9e4fb8acdd304b087a6494730f9eebf04"
[[package]]
name = "version_check"
version = "0.9.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "49874b5167b65d7193b8aba1567f5c7d93d001cafc34600cee003eda787e483f"
[[package]]
name = "wasi"
version = "0.10.0+wasi-snapshot-preview1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1a143597ca7c7793eff794def352d41792a93c481eb1042423ff7ff72ba2c31f"
[[package]]
name = "winapi"
version = "0.3.9"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5c839a674fcd7a98952e593242ea400abe93992746761e38641405d28b00f419"
dependencies = [
"winapi-i686-pc-windows-gnu",
"winapi-x86_64-pc-windows-gnu",
]
[[package]]
name = "winapi-i686-pc-windows-gnu"
version = "0.4.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6"
[[package]]
name = "winapi-util"
version = "0.1.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "70ec6ce85bb158151cae5e5c87f95a8e97d2c0c4b001223f33a334e3ce5de178"
dependencies = [
"winapi",
]
[[package]]
name = "winapi-x86_64-pc-windows-gnu"
version = "0.4.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f"
[[package]]
name = "windows-sys"
version = "0.52.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "282be5f36a8ce781fad8c8ae18fa3f9beff57ec1b52cb3de0789201425d9a33d"
dependencies = [
"windows-targets",
]
[[package]]
name = "windows-targets"
version = "0.52.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7dd37b7e5ab9018759f893a1952c9420d060016fc19a472b4bb20d1bdd694d1b"
dependencies = [
"windows_aarch64_gnullvm",
"windows_aarch64_msvc",
"windows_i686_gnu",
"windows_i686_msvc",
"windows_x86_64_gnu",
"windows_x86_64_gnullvm",
"windows_x86_64_msvc",
]
[[package]]
name = "windows_aarch64_gnullvm"
version = "0.52.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "bcf46cf4c365c6f2d1cc93ce535f2c8b244591df96ceee75d8e83deb70a9cac9"
[[package]]
name = "windows_aarch64_msvc"
version = "0.52.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "da9f259dd3bcf6990b55bffd094c4f7235817ba4ceebde8e6d11cd0c5633b675"
[[package]]
name = "windows_i686_gnu"
version = "0.52.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b474d8268f99e0995f25b9f095bc7434632601028cf86590aea5c8a5cb7801d3"
[[package]]
name = "windows_i686_msvc"
version = "0.52.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1515e9a29e5bed743cb4415a9ecf5dfca648ce85ee42e15873c3cd8610ff8e02"
[[package]]
name = "windows_x86_64_gnu"
version = "0.52.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5eee091590e89cc02ad514ffe3ead9eb6b660aedca2183455434b93546371a03"
[[package]]
name = "windows_x86_64_gnullvm"
version = "0.52.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "77ca79f2451b49fa9e2af39f0747fe999fcda4f5e241b2898624dca97a1f2177"
[[package]]
name = "windows_x86_64_msvc"
version = "0.52.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "32b752e52a2da0ddfbdbcc6fceadfeede4c939ed16d13e648833a61dfb611ed8"
[[package]]
name = "yaml-rust"
version = "0.4.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "56c1936c4cc7a1c9ab21a1ebb602eb942ba868cbd44a99cb7cdc5892335e1c85"
dependencies = [
"linked-hash-map",
]

View File

@@ -0,0 +1,18 @@
[package]
name = "ptest"
version = "0.1.0"
authors = ["david.brown"]
edition = "2018"
[dependencies]
chrono = "0.4"
env_logger = "0.9.0"
failure = "0.1.8"
log = "0.4.17"
num_cpus = "1.13.1"
std-semaphore = "0.1"
yaml-rust = "0.4"
[dependencies.clap]
version = "4.0"
features = ["derive"]

View File

@@ -0,0 +1,374 @@
//! Parallel testing.
//!
//! mcuboot simulator is strictly single threaded, as there is a lock around running the C startup
//! code, because it contains numerous global variables.
//!
//! To help speed up testing, the Workflow configuration defines all of the configurations that can
//! be run in parallel. Fortunately, cargo works well this way, and these can be run by simply
//! using subprocess for each particular thread.
//!
//! For now, we assume all of the features are listed under
//! jobs->environment->strategy->matric->features
use chrono::Local;
use clap::{Parser, Subcommand};
use log::{debug, error, warn};
use std::{
collections::HashSet,
env,
fs::{self, OpenOptions},
io::{ErrorKind, stdout, Write},
process::Command,
result,
sync::{
Arc,
Mutex,
},
thread,
time::Duration,
};
use std_semaphore::Semaphore;
use yaml_rust::{
Yaml,
YamlLoader,
};
type Result<T> = result::Result<T, failure::Error>;
fn main() -> Result<()> {
env_logger::init();
let args = Cli::parse();
let workflow_text = fs::read_to_string(&args.workflow)?;
let workflow = YamlLoader::load_from_str(&workflow_text)?;
let ncpus = num_cpus::get();
let limiter = Arc::new(Semaphore::new(ncpus as isize));
let matrix = Matrix::from_yaml(&workflow);
let matrix = if args.test.len() == 0 { matrix } else {
matrix.only(&args.test)
};
match args.command {
Commands::List => {
matrix.show();
return Ok(());
}
Commands::Run => (),
}
let mut children = vec![];
let state = State::new(matrix.envs.len());
let st2 = state.clone();
let _status = thread::spawn(move || {
loop {
thread::sleep(Duration::new(15, 0));
st2.lock().unwrap().status();
}
});
for env in matrix.envs {
let state = state.clone();
let limiter = limiter.clone();
let child = thread::spawn(move || {
let _run = limiter.access();
state.lock().unwrap().start(&env);
let out = env.run();
state.lock().unwrap().done(&env, out);
});
children.push(child);
}
for child in children {
child.join().unwrap();
}
println!();
Ok(())
}
/// The main Cli.
#[derive(Debug, Parser)]
#[command(name = "ptest")]
#[command(about = "Run MCUboot CI tests stand alone")]
struct Cli {
/// The workflow file to use.
#[arg(short, long, default_value = "../.github/workflows/sim.yaml")]
workflow: String,
/// The tests to run (defaults to all)
#[arg(short, long)]
test: Vec<usize>,
#[command(subcommand)]
command: Commands,
}
#[derive(Debug, Subcommand)]
enum Commands {
/// Runs the tests.
Run,
/// List available tests.
List,
}
/// State, for printing status.
struct State {
running: HashSet<String>,
done: HashSet<String>,
total: usize,
}
/// Result of a test run.
struct TestResult {
/// Was this run successful.
success: bool,
/// The captured output.
output: Vec<u8>,
}
impl State {
fn new(total: usize) -> Arc<Mutex<State>> {
Arc::new(Mutex::new(State {
running: HashSet::new(),
done: HashSet::new(),
total,
}))
}
fn start(&mut self, fs: &FeatureSet) {
let key = fs.textual();
if self.running.contains(&key) || self.done.contains(&key) {
warn!("Duplicate: {:?}", key);
}
debug!("Starting: {} ({} running)", key, self.running.len() + 1);
self.running.insert(key);
self.status();
}
fn done(&mut self, fs: &FeatureSet, output: Result<TestResult>) {
let key = fs.textual();
self.running.remove(&key);
self.done.insert(key.clone());
match output {
Ok(output) => {
if !output.success || log_all() {
// Write the output into a file.
let mut count = 1;
let (mut fd, logname) = loop {
let base = if output.success { "success" } else { "failure" };
let name = format!("./{}-{:04}.log", base, count);
count += 1;
match OpenOptions::new()
.create_new(true)
.write(true)
.open(&name)
{
Ok(file) => break (file, name),
Err(ref err) if err.kind() == ErrorKind::AlreadyExists => continue,
Err(err) => {
error!("Unable to write log file to current directory: {:?}", err);
return;
}
}
};
fd.write_all(&output.output).unwrap();
if !output.success {
error!("Failure {} log:{:?} ({} running)", key, logname,
self.running.len());
}
}
}
Err(err) => {
error!("Unable to run test {:?} ({:?}", key, err);
}
}
self.status();
}
fn status(&self) {
let running = self.running.len();
let done = self.done.len();
print!(" {} running ({}/{}/{} done)\r", running, done, running + done, self.total);
stdout().flush().unwrap();
}
}
/// The extracted configurations from the workflow config
#[derive(Debug)]
struct Matrix {
envs: Vec<FeatureSet>,
}
#[derive(Debug, Eq, Hash, PartialEq)]
struct FeatureSet {
// The environment variable to set.
env: String,
// The successive values to set it to.
values: Vec<String>,
}
impl Matrix {
fn from_yaml(yaml: &[Yaml]) -> Matrix {
let mut envs = vec![];
let mut all_tests = HashSet::new();
for y in yaml {
let m = match lookup_matrix(y) {
Some (m) => m,
None => continue,
};
for elt in m {
let elt = match elt.as_str() {
None => {
warn!("Unexpected yaml: {:?}", elt);
continue;
}
Some(e) => e,
};
let fset = FeatureSet::decode(elt);
if false {
// Respect the groupings in the `.workflow.yml` file.
envs.push(fset);
} else {
// Break each test up so we can run more in
// parallel.
let env = fset.env.clone();
for val in fset.values {
if !all_tests.contains(&val) {
all_tests.insert(val.clone());
envs.push(FeatureSet {
env: env.clone(),
values: vec![val],
});
} else {
warn!("Duplicate: {:?}: {:?}", env, val);
}
}
}
}
}
Matrix {
envs,
}
}
/// Print out all of the feature sets.
fn show(&self) {
for (i, feature) in self.envs.iter().enumerate() {
println!("{:3}. {}", i + 1, feature.simple_textual());
}
}
/// Replace this matrix with one that only has the chosen tests in it. Note
/// that the original order is preserved, not that given in `pick`.
fn only(self, pick: &[usize]) -> Self {
let pick: HashSet<usize> = pick.iter().cloned().collect();
let envs: Vec<_> = self
.envs
.into_iter()
.enumerate()
.filter(|(ind, _)| pick.contains(&(ind + 1)))
.map(|(_, item)| item)
.collect();
Matrix { envs }
}
}
impl FeatureSet {
fn decode(text: &str) -> FeatureSet {
// The github workflow is just a space separated set of values.
let values: Vec<_> = text
.split(',')
.map(|s| s.to_string())
.collect();
FeatureSet {
env: "MULTI_FEATURES".to_string(),
values,
}
}
/// Run a test for this given feature set. Output is captured and will be returned if there is
/// an error. Each will be run successively, and the first failure will be returned.
/// Otherwise, it returns None, which means everything worked.
fn run(&self) -> Result<TestResult> {
let mut output = vec![];
let mut success = true;
for v in &self.values {
let cmdout = Command::new("bash")
.arg("./ci/sim_run.sh")
.current_dir("..")
.env(&self.env, v)
.output()?;
// Grab the output for logging, etc.
writeln!(&mut output, "Test {} {}",
if cmdout.status.success() { "success" } else { "FAILURE" },
self.textual())?;
writeln!(&mut output, "time: {}", Local::now().to_rfc3339())?;
writeln!(&mut output, "----------------------------------------")?;
writeln!(&mut output, "stdout:")?;
output.extend(&cmdout.stdout);
writeln!(&mut output, "----------------------------------------")?;
writeln!(&mut output, "stderr:")?;
output.extend(&cmdout.stderr);
if !cmdout.status.success() {
success = false;
}
}
Ok(TestResult { success, output })
}
/// Convert this feature set into a textual representation
fn textual(&self) -> String {
use std::fmt::Write;
let mut buf = String::new();
write!(&mut buf, "{}:", self.env).unwrap();
for v in &self.values {
write!(&mut buf, " {}", v).unwrap();
}
buf
}
/// Generate a simpler textual representation, without showing the environment.
fn simple_textual(&self) -> String {
use std::fmt::Write;
let mut buf = String::new();
for v in &self.values {
write!(&mut buf, " {}", v).unwrap();
}
buf
}
}
fn lookup_matrix(y: &Yaml) -> Option<&Vec<Yaml>> {
let jobs = Yaml::String("jobs".to_string());
let environment = Yaml::String("environment".to_string());
let strategy = Yaml::String("strategy".to_string());
let matrix = Yaml::String("matrix".to_string());
let features = Yaml::String("features".to_string());
y
.as_hash()?.get(&jobs)?
.as_hash()?.get(&environment)?
.as_hash()?.get(&strategy)?
.as_hash()?.get(&matrix)?
.as_hash()?.get(&features)?
.as_vec()
}
/// Query if we should be logging all tests and not only failures.
fn log_all() -> bool {
env::var("PTEST_LOG_ALL").is_ok()
}