Init
This commit is contained in:
138
tests/forth/harness.rs
Normal file
138
tests/forth/harness.rs
Normal file
@@ -0,0 +1,138 @@
|
||||
use rand::rngs::StdRng;
|
||||
use rand::SeedableRng;
|
||||
use seq::model::forth::{Forth, Rng, StepContext, Value, Variables};
|
||||
use std::collections::HashMap;
|
||||
use std::sync::{Arc, Mutex};
|
||||
|
||||
pub fn default_ctx() -> StepContext {
|
||||
StepContext {
|
||||
step: 0,
|
||||
beat: 0.0,
|
||||
bank: 0,
|
||||
pattern: 0,
|
||||
tempo: 120.0,
|
||||
phase: 0.0,
|
||||
slot: 0,
|
||||
runs: 0,
|
||||
iter: 0,
|
||||
speed: 1.0,
|
||||
fill: false,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn ctx_with(f: impl FnOnce(&mut StepContext)) -> StepContext {
|
||||
let mut ctx = default_ctx();
|
||||
f(&mut ctx);
|
||||
ctx
|
||||
}
|
||||
|
||||
pub fn new_vars() -> Variables {
|
||||
Arc::new(Mutex::new(HashMap::new()))
|
||||
}
|
||||
|
||||
pub fn seeded_rng(seed: u64) -> Rng {
|
||||
Arc::new(Mutex::new(StdRng::seed_from_u64(seed)))
|
||||
}
|
||||
|
||||
pub fn forth() -> Forth {
|
||||
Forth::new(new_vars(), seeded_rng(42))
|
||||
}
|
||||
|
||||
pub fn forth_seeded(seed: u64) -> Forth {
|
||||
Forth::new(new_vars(), seeded_rng(seed))
|
||||
}
|
||||
|
||||
pub fn run(script: &str) -> Forth {
|
||||
let f = forth();
|
||||
f.evaluate(script, &default_ctx()).unwrap();
|
||||
f
|
||||
}
|
||||
|
||||
pub fn run_ctx(script: &str, ctx: &StepContext) -> Forth {
|
||||
let f = forth();
|
||||
f.evaluate(script, ctx).unwrap();
|
||||
f
|
||||
}
|
||||
|
||||
pub fn stack_top(f: &Forth) -> Value {
|
||||
f.stack().pop().expect("stack empty")
|
||||
}
|
||||
|
||||
pub fn stack_int(f: &Forth) -> i64 {
|
||||
match stack_top(f) {
|
||||
Value::Int(i, _) => i,
|
||||
other => panic!("expected Int, got {:?}", other),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn stack_float(f: &Forth) -> f64 {
|
||||
match stack_top(f) {
|
||||
Value::Float(x, _) => x,
|
||||
Value::Int(i, _) => i as f64,
|
||||
other => panic!("expected number, got {:?}", other),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn expect_stack(script: &str, expected: &[Value]) {
|
||||
let f = run(script);
|
||||
let stack = f.stack();
|
||||
assert_eq!(stack, expected, "script: {}", script);
|
||||
}
|
||||
|
||||
pub fn expect_int(script: &str, expected: i64) {
|
||||
expect_stack(script, &[Value::Int(expected, None)]);
|
||||
}
|
||||
|
||||
pub fn expect_float(script: &str, expected: f64) {
|
||||
let f = run(script);
|
||||
let stack = f.stack();
|
||||
assert_eq!(stack.len(), 1, "expected single value on stack");
|
||||
let val = stack_float(&f);
|
||||
assert!(
|
||||
(val - expected).abs() < 1e-9,
|
||||
"expected {}, got {}",
|
||||
expected,
|
||||
val
|
||||
);
|
||||
}
|
||||
|
||||
pub fn expect_floats_close(script: &str, expected: f64, epsilon: f64) {
|
||||
let f = run(script);
|
||||
let val = stack_float(&f);
|
||||
assert!(
|
||||
(val - expected).abs() < epsilon,
|
||||
"expected ~{}, got {}",
|
||||
expected,
|
||||
val
|
||||
);
|
||||
}
|
||||
|
||||
pub fn expect_error(script: &str, expected_substr: &str) {
|
||||
let f = forth();
|
||||
let result = f.evaluate(script, &default_ctx());
|
||||
assert!(result.is_err(), "expected error for '{}'", script);
|
||||
let err = result.unwrap_err();
|
||||
assert!(
|
||||
err.contains(expected_substr),
|
||||
"error '{}' does not contain '{}'",
|
||||
err,
|
||||
expected_substr
|
||||
);
|
||||
}
|
||||
|
||||
pub fn expect_outputs(script: &str, count: usize) -> Vec<String> {
|
||||
let f = forth();
|
||||
let outputs = f.evaluate(script, &default_ctx()).unwrap();
|
||||
assert_eq!(outputs.len(), count, "expected {} outputs", count);
|
||||
outputs
|
||||
}
|
||||
|
||||
pub fn expect_output_contains(script: &str, substr: &str) {
|
||||
let outputs = expect_outputs(script, 1);
|
||||
assert!(
|
||||
outputs[0].contains(substr),
|
||||
"output '{}' does not contain '{}'",
|
||||
outputs[0],
|
||||
substr
|
||||
);
|
||||
}
|
||||
Reference in New Issue
Block a user