use super::harness::{expect_int, expect_stack}; use cagire::forth::Value; fn ints(vals: &[i64]) -> Vec { vals.iter().map(|&v| Value::Int(v, None)).collect() } #[test] fn interval_keeps_root() { // Interval dups the root, then adds - so both values remain expect_stack("c4 M3", &ints(&[60, 64])); expect_stack("c4 P5", &ints(&[60, 67])); } #[test] fn interval_stacking_builds_chord() { // C major: root + M3 + m3 (stacked) expect_stack("c4 M3 m3", &ints(&[60, 64, 67])); // C minor: root + m3 + M3 expect_stack("c4 m3 M3", &ints(&[60, 63, 67])); } #[test] fn interval_tritone() { // "tritone" word is taken by the scale, use aug4 or dim5 for interval expect_stack("c4 aug4", &ints(&[60, 66])); expect_stack("c4 dim5", &ints(&[60, 66])); } #[test] fn interval_all_simple() { expect_stack("c4 P1", &ints(&[60, 60])); // unison expect_stack("c4 m2", &ints(&[60, 61])); expect_stack("c4 M2", &ints(&[60, 62])); expect_stack("c4 m3", &ints(&[60, 63])); expect_stack("c4 M3", &ints(&[60, 64])); expect_stack("c4 P4", &ints(&[60, 65])); expect_stack("c4 P5", &ints(&[60, 67])); expect_stack("c4 m6", &ints(&[60, 68])); expect_stack("c4 M6", &ints(&[60, 69])); expect_stack("c4 m7", &ints(&[60, 70])); expect_stack("c4 M7", &ints(&[60, 71])); expect_stack("c4 P8", &ints(&[60, 72])); } #[test] fn interval_compound() { expect_stack("c4 m9", &ints(&[60, 73])); expect_stack("c4 M9", &ints(&[60, 74])); expect_stack("c4 P15", &ints(&[60, 84])); } #[test] fn interval_from_any_note() { expect_stack("a4 m3", &ints(&[69, 72])); // A4 + m3 = C5 expect_stack("e4 P5", &ints(&[64, 71])); // E4 + P5 = B4 } #[test] fn interval_dominant_seventh() { // C7: C E G Bb = root + M3 + m3 + m3 expect_stack("c4 M3 m3 m3", &ints(&[60, 64, 67, 70])); } #[test] fn interval_major_seventh() { // Cmaj7: C E G B = root + M3 + m3 + M3 expect_stack("c4 M3 m3 M3", &ints(&[60, 64, 67, 71])); } #[test] fn interval_with_nip() { // If you only want the new note, nip drops the one below top expect_int("c4 M3 nip", 64); }