#![allow(clippy::assertions_on_constants, clippy::eq_op)]
use std::{
process::Stdio,
sync::{Mutex, atomic::AtomicU32},
};
use rustest::{Result, SubFixture, fixture, main, test};
#[test]
fn simple_test() {
assert!(
5 * 6 == 30,
"Rust should be able to do a simple multiplication"
)
}
#[test]
#[xfail]
fn simple_test_failing() {
assert!(
5 * 4 == 30,
"Rust should be able to do a simple multiplication"
)
}
#[test]
fn return_test() -> Result {
Ok(())
}
#[test(xfail)]
fn return_test_failing() -> Result {
Err(std::io::Error::other("Dummy error"))?;
Ok(())
}
#[fixture]
fn ANumber() -> u32 {
5
}
#[test]
fn test_fixture_number(number: ANumber) {
assert_eq!(*number, 5)
}
#[fixture(name = ANewNumber)]
fn setup() -> u32 {
6
}
#[test]
fn test_fixture_new_number(number: ANewNumber) {
assert_eq!(*number, 6)
}
static INC_NUMBER: AtomicU32 = AtomicU32::new(0);
static SEEN: Mutex<Vec<u32>> = Mutex::new(Vec::new());
#[fixture]
fn IncNumber() -> u32 {
INC_NUMBER.fetch_add(1, core::sync::atomic::Ordering::Relaxed)
}
#[test]
fn test_fixture_inc_number_0(number: IncNumber) {
assert!((0..=3).contains(&*number), "{}", *number);
let mut seen = SEEN.lock().unwrap();
assert!(!seen.contains(&*number));
seen.push(*number);
}
#[test]
fn test_fixture_inc_number_1(number: IncNumber) {
assert!((0..=3).contains(&*number), "{}", *number);
let mut seen = SEEN.lock().unwrap();
assert!(!seen.contains(&*number));
seen.push(*number);
}
#[test]
fn test_fixture_inc_number_2(number: IncNumber) {
assert!((0..=3).contains(&*number), "{}", *number);
let mut seen = SEEN.lock().unwrap();
assert!(!seen.contains(&*number));
seen.push(*number);
}
static INC_NUMBER2: AtomicU32 = AtomicU32::new(0);
#[fixture(scope=global)]
fn IncNumber2() -> u32 {
INC_NUMBER2.fetch_add(1, core::sync::atomic::Ordering::Relaxed)
}
#[test]
fn test_fixture_inc_number2_0(number: IncNumber2) {
assert_eq!(*number, 0)
}
#[test]
fn test_fixture_inc_number2_1(number: IncNumber2) {
assert_eq!(*number, 0)
}
#[test]
fn test_fixture_inc_number2_2(number: IncNumber2) {
assert_eq!(*number, 0)
}
#[fixture(scope=global)]
fn IncNumber3(source: IncNumber) -> u32 {
*source
}
static SEEN3: Mutex<Option<u32>> = Mutex::new(None);
#[test]
fn test_fixture_inc_number3_0(number: IncNumber3) {
assert!((0..=3).contains(&*number), "{}", *number);
let mut seen = SEEN3.lock().unwrap();
match *seen {
Some(n) => assert_eq!(n, *number),
None => *seen = Some(*number),
}
}
#[test]
fn test_fixture_inc_number3_1(number: IncNumber3) {
assert!((0..=3).contains(&*number), "{}", *number);
let mut seen = SEEN3.lock().unwrap();
match *seen {
Some(n) => assert_eq!(n, *number),
None => *seen = Some(*number),
}
}
#[test]
fn test_fixture_inc_number3_2(number: IncNumber3) {
assert!((0..=3).contains(&*number), "{}", *number);
let mut seen = SEEN3.lock().unwrap();
match *seen {
Some(n) => assert_eq!(n, *number),
None => *seen = Some(*number),
}
}
struct ProcessChild(pub std::process::Child);
#[fixture(teardown=|v| v.0.kill().unwrap())]
fn RunningProcess() -> std::io::Result<Box<ProcessChild>> {
Ok(Box::new(ProcessChild(
std::process::Command::new("bash")
.stdout(Stdio::piped())
.arg("-c")
.arg("while true; do sleep 1; done")
.spawn()?,
)))
}
#[test]
fn test_with_process(a_process: RunningProcess) -> Result {
println!("Process id: {}", a_process.0.id());
Ok(())
}
static NEW_INC_NUMBER: AtomicU32 = AtomicU32::new(0);
#[fixture]
fn NewIncNumber() -> u32 {
NEW_INC_NUMBER.fetch_add(1, core::sync::atomic::Ordering::Relaxed)
}
#[fixture]
fn Double(source: NewIncNumber) -> u32 {
*source * 2
}
#[test]
fn test_double_unique(a_number: NewIncNumber, its_double: Double) {
assert_ne!(*a_number * 2, *its_double);
}
#[fixture(scope=test)]
fn IncNumberLocal(source: NewIncNumber) -> u32 {
*source
}
#[fixture]
fn DoubleLocal(source: IncNumberLocal) -> u32 {
*source * 2
}
#[test]
fn test_double_local(a_number: IncNumberLocal, its_double: DoubleLocal) {
assert_eq!(*a_number * 2, *its_double);
}
#[fixture]
fn DoubleGeneric<Source>(source: Source) -> u32
where
Source: SubFixture<Type = u32>,
{
*source * 2
}
#[test]
fn test_double_unique_gen(a_number: NewIncNumber, its_double: DoubleGeneric<NewIncNumber>) {
assert_ne!(*a_number * 2, *its_double);
}
#[test]
fn test_double_local_gen(a_number: IncNumberLocal, its_double: DoubleGeneric<IncNumberLocal>) {
assert_eq!(*a_number * 2, *its_double);
}
type MyDoubleFixture = DoubleGeneric<IncNumberLocal>;
#[test]
fn test_double_typedef(a_number: IncNumberLocal, its_double: MyDoubleFixture) {
assert_eq!(*a_number * 2, *its_double);
}
#[fixture(scope=test, params:u32=[1,5])]
fn Parametrized(param: Param) -> u32 {
*param
}
#[test]
fn test_param(a_number: Parametrized) {
assert!([1, 5].contains(&a_number));
}
#[test]
fn test_param_double(a_number: DoubleGeneric<Parametrized>) {
assert!([2, 10].contains(&a_number));
}
#[test(params:u32=[1,5])]
fn test_param2(p: Param) {
assert!([1, 5].contains(&p));
}
#[test(params:(u32, u32)=[
(0, 0),
(1, 1),
(2, 1),
(3, 2),
(4, 3),
(5, 5),
(6, 8),
])]
fn fibonacci_test(Param((input, expected)): Param) {
assert_eq!(expected, fibonacci(input))
}
fn fibonacci(input: u32) -> u32 {
match input {
0 => 0,
1 => 1,
n => fibonacci(n - 2) + fibonacci(n - 1),
}
}
#[main]
fn main() {}