6 Commits

Author SHA1 Message Date
2a7e6f4092 Version bump to v0.4.1
All checks were successful
ci/woodpecker/push/woodpecker Pipeline was successful
ci/woodpecker/tag/woodpecker Pipeline was successful
2025-01-16 17:31:24 -05:00
baf8630832 Added benchmarks for CPU and memory
All checks were successful
ci/woodpecker/push/woodpecker Pipeline was successful
2025-01-16 17:31:01 -05:00
000a33cfe4 Updating version of Rust used to build
All checks were successful
ci/woodpecker/push/woodpecker Pipeline was successful
2025-01-16 17:21:02 -05:00
a6f6994c2b Added runtime req for iperf3
Some checks failed
ci/woodpecker/push/woodpecker Pipeline failed
2024-01-28 19:59:31 -05:00
a4e0f27ddb Version bump to v0.4.0
All checks were successful
ci/woodpecker/push/woodpecker Pipeline was successful
ci/woodpecker/tag/woodpecker Pipeline was successful
2022-09-05 13:06:02 -04:00
f9de9ef93c Renamed the 'ping' test to the 'latency' test to more accurately reflect the test; Added the '-i' flag to the jitter and latency tests to set the ping interval timing
All checks were successful
ci/woodpecker/push/woodpecker Pipeline was successful
2022-09-05 13:05:32 -04:00
8 changed files with 136 additions and 38 deletions

View File

@ -1,11 +1,11 @@
pipeline: pipeline:
test_build: test_build:
image: rust:1.62 image: rust:1.75
commands: commands:
- "cargo build" - "cargo build"
build_release: build_release:
image: rust:1.62 image: rust:1.75
commands: commands:
- "cargo install cargo-deb cargo-generate-rpm" - "cargo install cargo-deb cargo-generate-rpm"
- "cargo build --release" - "cargo build --release"

View File

@ -1,7 +1,7 @@
[package] [package]
name = "hardware-tests" name = "hardware-tests"
description = "Bit Goblin PC hardware test suite." description = "Bit Goblin PC hardware test suite."
version = "0.3.3" version = "0.4.1"
edition = "2021" edition = "2021"
readme = "README.md" readme = "README.md"
license = "BSD 2-Clause" license = "BSD 2-Clause"

View File

@ -13,7 +13,8 @@ Currently there is no installation method other than downloading the provided re
Simply run the tool with `./bgbench` and you'll be presented with the available subcommands. Simply run the tool with `./bgbench` and you'll be presented with the available subcommands.
### Runtime requirements: ### Runtime requirements:
* disk - requires `fio`. * `disk` - requires `fio`.
* `network bandwidth` - requires `iperf3`
## Building ## Building

19
src/benchmarks/cpu.rs Normal file
View File

@ -0,0 +1,19 @@
use std::process::Command;
// test system memory with sysbench
pub fn sysbench(threads: &u8, maxprime: &u32) {
// run the fio command
let output = Command::new("sysbench")
.arg("cpu")
.arg(format!("--threads={}", threads))
.arg(format!("--cpu-max-prime={}", maxprime))
.arg("run")
.output()
.expect("Failed to execute command");
// check that the command succeeded
assert!(output.status.success());
// print the test's output
println!("{}", String::from_utf8_lossy(&output.stdout));
}

21
src/benchmarks/memory.rs Normal file
View File

@ -0,0 +1,21 @@
use std::process::Command;
// test system memory with sysbench
pub fn sysbench(accessmode: &str, operation: &str, blocksize: &str, totalsize: &str) {
// run the fio command
let output = Command::new("sysbench")
.arg("memory")
.arg(format!("--memory-access-mode={}", accessmode))
.arg(format!("--memory-oper={}", operation))
.arg(format!("--memory-block-size={}", blocksize))
.arg(format!("--memory-total-size={}", totalsize))
.arg("run")
.output()
.expect("Failed to execute command");
// check that the command succeeded
assert!(output.status.success());
// print the test's output
println!("{}", String::from_utf8_lossy(&output.stdout));
}

View File

@ -1,3 +1,5 @@
pub mod cpu;
pub mod disk; pub mod disk;
pub mod games; pub mod games;
pub mod memory;
pub mod network; pub mod network;

View File

@ -3,19 +3,25 @@ use std::process;
use crate::text; use crate::text;
// ping a host // ping a host
pub fn ping_host(address: &str, count: &u16) { pub fn latency_test(address: &str, count: &u16, interval: &u16) {
println!("Pinging host {}, {} times.", address, count); println!("Pinging host {}, {} times.", address, count);
// if we're on Windows we need to use the -n flag for ping counts
let mut count_arg = "-c"; let mut count_arg = "-c";
if cfg!(windows) { if cfg!(windows) {
count_arg = "-n"; count_arg = "-n";
} }
// convert the ping interval to seconds
let interval_secs = *interval as f64 / 1000 as f64;
// run the ping command // run the ping command
let output = process::Command::new("ping") let output = process::Command::new("ping")
.arg(address) .arg(address)
.arg(count_arg) .arg(count_arg)
.arg(format!("{}", count)) .arg(format!("{}", count))
.arg("-i")
.arg(format!("{}", interval_secs))
.output() .output()
.expect("Failed to execute command"); .expect("Failed to execute command");
@ -31,19 +37,25 @@ pub fn ping_host(address: &str, count: &u16) {
} }
// network jitter test // network jitter test
pub fn jitter_test(address: &str, count: &u16) { pub fn jitter_test(address: &str, count: &u16, interval: &u16) {
println!("Pinging host {}, {} times to determine network jitter.", address, count); println!("Pinging host {}, {} times to determine network jitter.", address, count);
// if we're on Windows we need to use the -n flag for ping counts
let mut count_arg = "-c"; let mut count_arg = "-c";
if cfg!(windows) { if cfg!(windows) {
count_arg = "-n"; count_arg = "-n";
} }
// convert the ping interval to seconds
let interval_secs = *interval as f64 / 1000 as f64;
// run the ping command // run the ping command
let output = process::Command::new("ping") let output = process::Command::new("ping")
.arg(address) .arg(address)
.arg(count_arg) .arg(count_arg)
.arg(format!("{}", count)) .arg(format!("{}", count))
.arg("-i")
.arg(format!("{}", interval_secs))
.output() .output()
.expect("Failed to execute command"); .expect("Failed to execute command");

View File

@ -11,8 +11,8 @@ struct Cli {
#[clap(subcommand)] #[clap(subcommand)]
command: Commands, command: Commands,
#[clap(short = 'i', long, default_value_t = 1, help = "Number of times to run test. Default = 1", global = true)] #[clap(short = 'l', long, default_value_t = 1, help = "Number of times to run test. Default = 1", global = true)]
iterations: u8, loopcount: u8,
} }
#[derive(Subcommand)] #[derive(Subcommand)]
@ -20,6 +20,9 @@ enum Commands {
// CPU benchmarks subcommand // CPU benchmarks subcommand
#[clap(name = "cpu", about = "CPU benchmarks and stress tests.")] #[clap(name = "cpu", about = "CPU benchmarks and stress tests.")]
Cpu(Cpu), Cpu(Cpu),
// memory benchmarks subcommand
#[clap(name = "memory", about = "Memory benchmarks and stress tests.")]
Mem(Mem),
// disk benchmarks subcommand // disk benchmarks subcommand
#[clap(name = "disk", about = "Hard drive and SSD benchmarks.")] #[clap(name = "disk", about = "Hard drive and SSD benchmarks.")]
Disk(Disk), Disk(Disk),
@ -47,6 +50,37 @@ enum CpuCommands {
#[clap(short = 't', long, default_value_t = 0, help = "Number of threads to use; defaults to CPU's max thread count. Defaults to 0 (automatic)")] #[clap(short = 't', long, default_value_t = 0, help = "Number of threads to use; defaults to CPU's max thread count. Defaults to 0 (automatic)")]
threads: usize, threads: usize,
}, },
// CPU benchmark test subcommand
#[clap(name = "benchmark", about = "Benchmark the CPU")]
Benchmark {
#[clap(short = 'm', long, default_value_t = 4)]
threads: u8,
#[clap(short = 'o', long, default_value_t = 10000)]
maxprime: u32,
},
}
#[derive(Args)]
struct Mem {
#[clap(subcommand)]
mem_commands: MemCommands,
}
#[derive(Subcommand)]
enum MemCommands {
// Memory benchmark test subcommand
#[clap(name = "benchmark", about = "Benchmark the system memory")]
Benchmark {
#[clap(short = 'm', long, default_value_t = String::from("seq"))]
accessmode: String,
#[clap(short = 'o', long, default_value_t = String::from("write"))]
operation: String,
#[clap(short = 'b', long, default_value_t = String::from("1K"))]
blocksize: String,
#[clap(short = 's', long, default_value_t = String::from("100G"))]
totalsize: String,
},
} }
#[derive(Args)] #[derive(Args)]
@ -123,13 +157,11 @@ struct Net {
#[derive(Subcommand)] #[derive(Subcommand)]
enum NetCommands { enum NetCommands {
// ping subcommand // bandwidth test subcommand
#[clap(name = "ping", about = "Ping a host to determine network latency.")] #[clap(name = "bandwidth", about = "Uses iperf to test network bandwidth.")]
Ping { Bandwidth {
#[clap(short = 'a', long, default_value_t = String::from("8.8.8.8"))] #[clap(short = 'a', long, required = true)]
address: String, host: String,
#[clap(short = 'c', long, default_value_t = 30)]
count: u16,
}, },
// jitter subcommand // jitter subcommand
@ -137,15 +169,21 @@ enum NetCommands {
Jitter { Jitter {
#[clap(short = 'a', long, default_value_t = String::from("8.8.8.8"))] #[clap(short = 'a', long, default_value_t = String::from("8.8.8.8"))]
address: String, address: String,
#[clap(short = 'c', long, default_value_t = 30)] #[clap(short = 'c', long, default_value_t = 100)]
count: u16, count: u16,
#[clap(short = 'i', long, default_value_t = 1000)]
interval: u16,
}, },
// bandwidth test subcommand // latency subcommand
#[clap(name = "bandwidth", about = "Uses iperf to test network bandwidth.")] #[clap(name = "latency", about = "Ping a host to determine network latency.")]
Bandwidth { Latency {
#[clap(short = 'a', long, required = true)] #[clap(short = 'a', long, default_value_t = String::from("8.8.8.8"))]
host: String, address: String,
#[clap(short = 'c', long, default_value_t = 100)]
count: u16,
#[clap(short = 'i', long, default_value_t = 1000)]
interval: u16,
}, },
} }
@ -156,29 +194,34 @@ fn main() {
match &cli.command { match &cli.command {
Commands::Cpu(args) => match &args.cpu_commands { Commands::Cpu(args) => match &args.cpu_commands {
CpuCommands::StressTest { runtime, threads } => stress::cpu::cpu_stress_math(*runtime, *threads), CpuCommands::StressTest { runtime, threads } => stress::cpu::cpu_stress_math(*runtime, *threads),
CpuCommands::Benchmark { threads, maxprime } => benchmarks::cpu::sysbench(threads, maxprime),
},
Commands::Mem(args) => match &args.mem_commands {
MemCommands::Benchmark { accessmode, operation, blocksize, totalsize } => benchmarks::memory::sysbench(accessmode, operation, blocksize, totalsize),
}, },
Commands::Disk(args) => match &args.disk_commands { Commands::Disk(args) => match &args.disk_commands {
DiskCommands::ReadSeqTest { tempfile, size } => { DiskCommands::ReadSeqTest { tempfile, size } => {
for i in 0..cli.iterations { for i in 0..cli.loopcount {
println!("Test run number {}.", i + 1); println!("Test run number {}.", i + 1);
benchmarks::disk::disk_read_seq_test(tempfile, size); benchmarks::disk::disk_read_seq_test(tempfile, size);
} }
}, },
DiskCommands::ReadRandTest { tempfile, size } => { DiskCommands::ReadRandTest { tempfile, size } => {
for i in 0..cli.iterations { for i in 0..cli.loopcount {
println!("Test run number {}.", i + 1); println!("Test run number {}.", i + 1);
benchmarks::disk::disk_read_rand_test(tempfile, size); benchmarks::disk::disk_read_rand_test(tempfile, size);
} }
}, },
DiskCommands::WriteSeqTest { tempfile, size } => { DiskCommands::WriteSeqTest { tempfile, size } => {
for i in 0..cli.iterations { for i in 0..cli.loopcount {
println!("Test run number {}.", i + 1); println!("Test run number {}.", i + 1);
benchmarks::disk::disk_write_seq_test(tempfile, size); benchmarks::disk::disk_write_seq_test(tempfile, size);
} }
}, },
DiskCommands::WriteRandTest { tempfile, size } => { DiskCommands::WriteRandTest { tempfile, size } => {
for i in 0..cli.iterations { for i in 0..cli.loopcount {
println!("Test run number {}.", i + 1); println!("Test run number {}.", i + 1);
benchmarks::disk::disk_write_rand_test(tempfile, size); benchmarks::disk::disk_write_rand_test(tempfile, size);
} }
@ -192,24 +235,24 @@ fn main() {
}, },
Commands::Net(args) => match &args.net_commands { Commands::Net(args) => match &args.net_commands {
NetCommands::Ping { address, count } => {
for i in 0..cli.iterations {
println!("Test run number {}.", i + 1);
benchmarks::network::ping_host(address, count);
}
},
NetCommands::Jitter { address, count } => {
for i in 0..cli.iterations {
println!("Test run number {}.", i + 1);
benchmarks::network::jitter_test(address, count);
}
},
NetCommands::Bandwidth { host } => { NetCommands::Bandwidth { host } => {
for i in 0..cli.iterations { for i in 0..cli.loopcount {
println!("Test run number {}.", i + 1); println!("Test run number {}.", i + 1);
benchmarks::network::bandwidth_test(host); benchmarks::network::bandwidth_test(host);
} }
}, },
NetCommands::Jitter { address, count, interval } => {
for i in 0..cli.loopcount {
println!("Test run number {}.", i + 1);
benchmarks::network::jitter_test(address, count, interval);
}
},
NetCommands::Latency { address, count, interval } => {
for i in 0..cli.loopcount {
println!("Test run number {}.", i + 1);
benchmarks::network::latency_test(address, count, interval);
}
},
}, },
} }
} }