use std::path::Path;
use std::process::Command;
use crate::helpers::{fixture, scratch};
const CASES: [(&str, &str, &str); 17] = [
("arranged", "@master([0, 1s])", "@master"),
("bar-grid", "@master([0, 1s])", "@master"),
("basic", "@master([0, 1s])", "@master"),
("basic", "@loop-1b([0, 0.5s])", "@loop-1b"),
("cost", "@bowl([0, 0.1s])", "@bowl"),
("no-tempo", "@master([0, 1s])", "@master"),
("reverb", "@master([0, 0.5s])", "@fx/reverb"),
("stereo", "@master([0, 0.06s])", "@pan"),
("stereo", "@pingpong([0, 0.6s])", "@pingpong"),
("two-entries", "@master([0, 1s])", "@master"),
("two-entries", "@bench-2s([0, 1s])", "@bench-2s"),
(
"closure-1a4989c6",
"@sva1a4989c6fb22b2969fa478e6ee47b16aee6a20df52c484d241618c6b112876bb([0, 1s])",
"@sva4065c0245b85ba8686d4da12124b41e3d0ea09ebb3000a229f931ee6194a9558(f0=D2)",
),
(
"closure-1e362f88",
"@sva1e362f88072bf4bb3c0edb42fda6269ffc00ee12c4f3f4e07bbde0269c103ded([0, 1s])",
"@sva5f25539e1ff16edd2ae8228c54964a2afe65f15881c456fdcaf0a4d36ec52082(f0=A1, release=0.8, vel=1)",
),
(
"closure-1f15ca3d",
"@sva1f15ca3db2096f385f391721c5c0fff2210e4c6b3ed996ef063529631ac3bda6([0, 1s])",
"@svad163ed7735e112fc74e76ed73b689901236c80717584dcc13d14fb72cd3f0e4e(seed=1)",
),
(
"closure-db781e56",
"@svadb781e56ae75d7bb4802f257ff1b7c509b9cce9dcd53f4cad13450110d3a4a8f([0, 0.5s])",
"@sva8062dfa9b6df789c110d873e7fe5164b6ab95b0c7517ca5dcb7afce047d0f9bc(f0=261.6255653006, release=3.0833333333, vel=0.7087)",
),
(
"closure-db781e56",
"@sva046a5fc7c03eb08d8ac01e517b4ce72a7765d820d9966e676c197a21b3b39045([0, 0.1s], tc=0.08)",
"@sva046a5fc7c03eb08d8ac01e517b4ce72a7765d820d9966e676c197a21b3b39045",
),
(
"closure-f5a155b1",
"@svaf5a155b1d5f640ea99aa441093bdb8c793a166a697f1f1eb8c032160feb4cd81([0, 0.5s])",
"@sva3828c5b584260ff15968d7fd155d5d8856184bd78099c66fca8b2b39f671b8b5(f0=A2, release=2, vel=0.35)",
),
];
const READINGS: [&str; 15] = [
"lines",
"spectrum",
"envelope",
"derivative",
"ledger",
"pitch",
"formants",
"stereo",
"bands",
"crest",
"loudness",
"onsets",
"alias",
"bindings",
"arguments",
];
const PINNED: &str = r#"
0 stdout 247a8ad492f8b3d7
0 wav 665924a7a274d695
0 store:3620e0612b5d84925fa1bd15f1b7716e 6e7a3b8c4323869b
0 lines refused "read.lines_need_unwindowed_lines"
0 spectrum refused "read.lines_need_unwindowed_lines"
0 envelope refused "cast.left_algebra"
0 derivative 35f9147e138d1ec8
0 ledger 301ba8530bb8a641
0 pitch refused "read.lines_need_unwindowed_lines"
0 formants 69ac51091d002826
0 stereo refused "type.width_mismatch"
0 bands 5ddbbb246c27967f
0 crest 9da293a2a033e041
0 loudness 6beb066a8865bf77
0 onsets 04c47d79948cdf22
0 alias e318d641144719e7
0 bindings b2361ce7b3484da7
0 arguments 2629850681a29371
1 stdout 247a8ad492f8b3d7
1 wav 26291e77cc78e829
1 store:90af903a105917870539e1943a4b72c7 dd23718686b0019d
1 lines refused "read.lines_need_unwindowed_lines"
1 spectrum refused "read.lines_need_unwindowed_lines"
1 envelope refused "cast.left_algebra"
1 derivative 8423ad0fc11dacf4
1 ledger 40b6413cf9c33fc0
1 pitch refused "read.lines_need_unwindowed_lines"
1 formants 4558f476fdf28802
1 stereo refused "type.width_mismatch"
1 bands 652286a71d7ba909
1 crest 6589fb8644e10ca3
1 loudness 8b44aa2ca17316b1
1 onsets d73ec35b4563fc20
1 alias 485523f8cabe0972
1 bindings b2361ce7b3484da7
1 arguments 2629850681a29371
2 stdout 247a8ad492f8b3d7
2 wav 968e2e9858e90ed9
2 store:29c7e17ebaef85e9ff784832c3108192 dbaee90c4cd14203
2 lines refused "read.no_spectral_sum"
2 spectrum refused "read.no_spectral_sum"
2 envelope refused "read.no_spectral_sum"
2 derivative refused "read.no_spectral_sum"
2 ledger d5403c5358edc0e2
2 pitch refused "read.no_spectral_sum"
2 formants c3364258e02d81e6
2 stereo refused "type.width_mismatch"
2 bands f7a5e849debf50b2
2 crest fbd77b10d5dde3ac
2 loudness b53fa58b1c3cfcf7
2 onsets f516024a0a08d9d9
2 alias cbbc144627936787
2 bindings b2361ce7b3484da7
2 arguments 626f051e3a2fc700
3 stdout ab995f31111d716c
3 wav 64318e943f03cc25
3 store:273d32d1fbc24d73b322a79899449566 d655ced2289ed136
3 lines 1b91625484873716
3 spectrum 72763f1617db3c1e
3 envelope 5ff2738827a015bc
3 derivative 2d6f0bddc0248089
3 ledger 5c22057f215775d1
3 pitch 31eb906bd2504ddd
3 formants 82cfccabbf2a95e5
3 stereo refused "type.width_mismatch"
3 bands 3d2781a6afdfb4c8
3 crest e0f4c5aaa9c7c270
3 loudness 1efebe0b0fefa1a0
3 onsets ebcb0cf6f04264e8
3 alias 506c180529a7011d
3 bindings de379a53261f899f
3 arguments 963d7e681d3a7159
4 stdout 53ef6500c0c74fac
4 wav d8d646db74dc9cb2
4 store:7d17584ff33a1d5714e10c35ba698e01 487a1b3fda336215
4 lines 856b8c259fc6ee26
4 spectrum 5875cbec9753bd9a
4 envelope cdefdc3ad777a6cc
4 derivative 1335b1af4f591c60
4 ledger c053925e93af266d
4 pitch 12415b8ef26ea22e
4 formants 5b0b91afdc94a81c
4 stereo refused "type.width_mismatch"
4 bands eaa2cac9886e0d17
4 crest 4b17dbafe5a25887
4 loudness f43469c2b46c18fa
4 onsets 541b1fa4f6b9b8cd
4 alias 8d924afebae5f453
4 bindings a066a34dcc83fcfb
4 arguments 9eaefeccb255ec5d
5 stdout 247a8ad492f8b3d7
5 wav 177aed0c28183ef5
5 store:52690610e792cbd9ec87410effce6ac0 c5488abce5d848a7
5 lines 4745742b132f215a
5 spectrum cfc00a7586fe2dc2
5 envelope 3cab08eac882effb
5 derivative fc27dc342d808d4a
5 ledger e4349ebf63d76218
5 pitch 6c4088af788a0ba4
5 formants 7a25e231d6e83128
5 stereo refused "type.width_mismatch"
5 bands 41f346248f013bb4
5 crest 7e413e4086bc977c
5 loudness 2e51b000ed8e618a
5 onsets 92bbe62371efe02b
5 alias 3ded1f4b860a2c36
5 bindings b2361ce7b3484da7
5 arguments 2629850681a29371
6 stdout b7be809aeee4a986
6 wav 72bce77b8424e0c6
6 store:0aa625a325ad009e42736fb0b55da15e c5942df6f6705a52
6 store:11c136c343d5887a356999a4fc86e8f7 0cd034c8419e36e9
6 store:14f6414df6fcdd24e3ba1efa6b601e02 9b49ca9f4338685b
6 store:2a812a178319a3d66188660d033eee56 dddb4966aa54c1e2
6 store:2b1dfb572460ba3c3e8a08891ad3feda c455643137e1666c
6 store:2cc1e056c0cd5c6013c986cb46ea8680 45eea96b7c077254
6 store:57a6b91a9d6ee92c9f220a471c761060 070c72473fe22f3e
6 store:6e22a9b54e73a673f2f7252c439f5d3c 0b91058235937250
6 store:6f9bcd032cb9677f874eba226b581950 be30a3f2d69e0a1f
6 store:d18c8f806552ff35a1cabe95f566fe2e 74803c93aea52c1f
6 store:d4b554f1adbd1e2708edf6cef39dd919 200d07b6e91dfa95
6 store:dfbe3e234fa8c68c2717f78df327e90f 6187182b7dda3f2e
6 store:e41ecc22b1d8d907ef9ba75bd804e1e7 1dbdd6ed6f7b9789
6 store:e51a27e86bcbd36a2c884364cb358a1e b13e933cd4588103
6 lines refused "type.samples_in_closed_form"
6 spectrum c143451080b1b42f
6 envelope 510b9276d5e7c870
6 derivative 4e77b328e32c4c32
6 ledger e296c7b26fd92e2f
6 pitch d8acbfd122ead830
6 formants 4a5877c3e5e367d9
6 stereo refused "type.width_mismatch"
6 bands 5f534aa9aa3bbcd7
6 crest 0ee986c4ebc6919e
6 loudness 0a34d0ed19f5e82e
6 onsets 89cc588bb24828d4
6 alias refused "engine.alias_needs_a_closed_form"
6 bindings 61d25ef94a8f6635
6 arguments f96cc4a110318b3d
7 stdout edd1ad4d03ca1433
7 wav 3372a403bff9f10a
7 store:48cc333eda6f48499d525bb87ae7a03c 413a510a27a5c41f
7 lines refused "read.lines_need_unwindowed_lines"
7 spectrum refused "read.lines_need_unwindowed_lines"
7 envelope refused "cast.left_algebra"
7 derivative 17cd66f01d871437
7 ledger 3eced3ce79e67005
7 pitch refused "read.lines_need_unwindowed_lines"
7 formants c0281bb4e0ac6319
7 stereo ed61419626773d93
7 bands 63f7a635e479975b
7 crest 11bd7455ec37430f
7 loudness 7d6440ef7def4aca
7 onsets 365b79ff87273315
7 alias 23748d016eb6d4d0
7 bindings e78c34f33117e96f
7 arguments bcbf8809de18a142
8 stdout ab6aa7bed370fd04
8 wav 083e3fdfa6fd2b2d
8 store:0435c2987fec5f6fa5f7bc60ed42587e 31fc1d6de3a78d9f
8 lines refused "type.samples_in_closed_form"
8 spectrum 1df6ea56e09c379f
8 envelope 0c5253e952c2fa8d
8 derivative 2ca6691cd11a21e4
8 ledger d7d7417544077963
8 pitch 6f9dd96865b68639
8 formants 0e95b6ea73de97c9
8 stereo 6494bdf51a307118
8 bands a77c7f445be310ef
8 crest 5acbf9ff63a1ae21
8 loudness a3a819dc1ebce653
8 onsets 48063a15f2fa7dae
8 alias refused "engine.alias_needs_a_closed_form"
8 bindings 79396b2f23896766
8 arguments a5fe2d9cfe6ecec2
9 stdout 247a8ad492f8b3d7
9 wav 3a9ca1a53a5fa42a
9 store:3180ee7f5ba55875b73514cbc66c3107 ee52b899077cfc7b
9 lines refused "read.lines_need_unwindowed_lines"
9 spectrum refused "read.lines_need_unwindowed_lines"
9 envelope refused "cast.left_algebra"
9 derivative d50dd96bf045c44e
9 ledger 01194d6093d32b20
9 pitch refused "read.lines_need_unwindowed_lines"
9 formants 4a1893055be9d546
9 stereo refused "type.width_mismatch"
9 bands 21d75879d5a36084
9 crest 17fd2a6d80a8ce3a
9 loudness 834f5d4cfb83c638
9 onsets 6bc6790ece226d7e
9 alias b26cecc4edcab851
9 bindings b2361ce7b3484da7
9 arguments 2629850681a29371
10 stdout 099b2f66421d30cb
10 wav a9866247325c001f
10 store:6655845ef1b852c2dfba6667b7a17cb7 b0709c7476956377
10 lines refused "read.lines_need_unwindowed_lines"
10 spectrum refused "read.lines_need_unwindowed_lines"
10 envelope refused "cast.left_algebra"
10 derivative b672d107adb53ae4
10 ledger d85440a165c53e75
10 pitch refused "read.lines_need_unwindowed_lines"
10 formants a89662a64fb8a4dd
10 stereo refused "type.width_mismatch"
10 bands 198cf5dfb1458000
10 crest bafbab9959c18d6e
10 loudness 34aa5712017ee81c
10 onsets a7c09136915371ba
10 alias e5e1283668112a07
10 bindings 5d16a4e7b16c54d3
10 arguments 13a9d91a5de370e5
11 stdout d79a956da40777a2
11 wav c187b7408a55ebf7
11 store:05527852d844ba60e2f03bfc763cbeda a988306ede2eb6b7
11 store:b6774780ba26bd24289ee5a5a363539e 7509bfcfccb25771
11 store:fef920a29d25f7e69ab776f1c1aa2df8 5a1a23698fff0512
11 lines refused "type.samples_in_closed_form"
11 spectrum f25da52885882adf
11 envelope 7c67a5d377431f4e
11 derivative 63a11563fea7dad7
11 ledger 85f91208b93bf675
11 pitch e2518db792f886da
11 formants ab893e9880a0ad66
11 stereo refused "type.width_mismatch"
11 bands 8f984c522da9befa
11 crest d2139cfcaf0fd8ba
11 loudness b45d9c8f9dc07543
11 onsets 86bbaf66d84dc5dc
11 alias refused "engine.alias_needs_a_closed_form"
11 bindings 6187812054881a9c
11 arguments 00523829ab775155
12 stdout 2125d7cc6a62b570
12 wav 3fc9f322aaf6fc5f
12 store:05fd9b34f0c3d96a4508e7fe93cef407 99763ac1b4f08b05
12 store:eefd7456adda71f95410a477bc38064f 25998e4cba244b7c
12 lines refused "type.samples_in_closed_form"
12 spectrum 8ca9ad07eee19d5b
12 envelope 1b9d192b3e91dcb6
12 derivative 680aa7a6c864fac2
12 ledger 9521693f05bf90e3
12 pitch 9993abf09efb1ccd
12 formants f63e3f59fb8ff19a
12 stereo refused "type.width_mismatch"
12 bands 8d953bbc6e7a6774
12 crest 93883cb32f667560
12 loudness bdf143d2e6060672
12 onsets 9886546931789888
12 alias refused "engine.alias_needs_a_closed_form"
12 bindings 2246221dde6bf19e
12 arguments 31ac7203e7c98531
13 stdout 35b22cc894edba26
13 wav 256b6dfecab93743
13 store:7766d37a0cdcc294553055f59415b4ee ecce9080780fff1a
13 store:b636f740c7f5c69c7d133075cf6253c3 2fdd7da48324e1b7
13 lines refused "type.samples_in_closed_form"
13 spectrum 3abc3201aa4a2410
13 envelope c7477734fba002a5
13 derivative ffa59bb931676ae3
13 ledger 1a738c8d556a802e
13 pitch 186e31c478850407
13 formants e82d2ddad859d9c3
13 stereo refused "type.width_mismatch"
13 bands ff24830f55ca7d97
13 crest 9bad027881a738b0
13 loudness e00776a8141b9681
13 onsets 806949e0f3195792
13 alias refused "engine.alias_needs_a_closed_form"
13 bindings 4d733f3c0aabb4f4
13 arguments c4f0bea827f62da3
14 stdout cfe7231299dd5013
14 wav 0c1d8e0ad4b6a019
14 store:254945568a381e7c3e5471da1d74728f ffdf9d3456bc9823
14 store:9799ab7ba6f836a107fd71777f42e6f0 651bf83dd5fdb31f
14 store:979e8f53e59fb8d66035a41b9132d6a7 e5655bc3498b0d57
14 store:f9f5071eb92a34c3a0ca9fe84c15c685 50d78de808a824d3
14 lines refused "type.samples_in_closed_form"
14 spectrum 5efa6c48ce11d24c
14 envelope 88f602a703affc7c
14 derivative 2b9e8c981a270e7f
14 ledger 3ce3405aef9719b3
14 pitch 8322f2f2f4852b5a
14 formants 07b076a9b2773249
14 stereo refused "type.width_mismatch"
14 bands e59cf9c09fde48fd
14 crest 946716d90df65745
14 loudness d3a463c6f70e21ea
14 onsets 0f9d34d3f16cfca4
14 alias refused "engine.alias_needs_a_closed_form"
14 bindings 93b2bd559b5e577e
14 arguments 7309f5cc8a34fe8a
15 stdout c1ee5cc59d6fb404
15 wav 82773cac15ff1cca
15 store:b5146c74a37c137f36a90b33af43d7d6 8acfacd50445baef
15 lines refused "read.lines_need_unwindowed_lines"
15 spectrum refused "read.lines_need_unwindowed_lines"
15 envelope refused "cast.left_algebra"
15 derivative 9e12de6ee9602f21
15 ledger f3afb30b0c4c2fb5
15 pitch refused "read.lines_need_unwindowed_lines"
15 formants 53fe55520cbb1aba
15 stereo refused "type.width_mismatch"
15 bands 783c04ff4dc38ba4
15 crest 25f0c999bb9f0512
15 loudness 46d79f3bbbb5df11
15 onsets 289cbea3f525c18b
15 alias 4f6598282adf4aff
15 bindings f758b54150146934
15 arguments 6fe5313a42a03884
16 stdout 81e5860d85938ad0
16 wav 9007d5d55c305e67
16 store:26ad75243b2f79c4c406c6f5bf4ec486 c418462b254b42d5
16 store:3c3e02ce6997bbbc519549daeed604f4 4ba0d4a350140222
16 store:721873409668da2d147b4a20e9a0d6e3 2a704778eabb22b0
16 store:7d2a34d66251dbf649d696726b2f90f8 85083b1a5bdc5bf4
16 store:7febd1dbb83c13997bf57fbce8e72f50 0d28f9abd7177441
16 lines refused "type.samples_in_closed_form"
16 spectrum 1d4445163666b88a
16 envelope eedb58d4e0ba84e8
16 derivative 6ea3e8568de26a88
16 ledger e9282e1791e85be2
16 pitch b22880e861c79361
16 formants 6f05c52bc183f345
16 stereo refused "type.width_mismatch"
16 bands a3d90ca6090450f6
16 crest 45a7abc702e4a819
16 loudness b7addddc1aff3995
16 onsets 3e5d66c88c2bf481
16 alias refused "engine.alias_needs_a_closed_form"
16 bindings 76ea2f9c67cc302d
16 arguments ef9f32c3d73615ee
"#;
fn fnv(bytes: &[u8]) -> u64 {
bytes.iter().fold(0xcbf2_9ce4_8422_2325, |h, b| {
(h ^ u64::from(*b)).wrapping_mul(0x0100_0000_01b3)
})
}
fn before_meta(printed: &str) -> &str {
&printed[..printed.find("\"meta\"").expect("an envelope")]
}
fn render(dir: &Path, target: &str, store: &Path, representation: &str) -> (bool, String) {
let ran = Command::new(env!("CARGO_BIN_EXE_sva-cli"))
.current_dir(dir)
.args([
"render",
target,
"--representation",
representation,
"--cache",
])
.arg(store)
.output()
.expect("the binary runs");
let printed = String::from_utf8_lossy(&ran.stdout);
(ran.status.success(), before_meta(&printed).to_string())
}
fn codes(printed: &str) -> &str {
let opening = "\"codes\": { \"items\": [";
let from = printed.find(opening).expect("a refusal's codes") + opening.len();
let listed = &printed[from..];
&listed[..listed.find(']').expect("a closed array")]
}
fn stored(store: &Path) -> Vec<(String, String)> {
let mut keys: Vec<String> = std::fs::read_dir(store)
.expect("a store")
.flatten()
.map(|e| e.file_name().to_string_lossy().into_owned())
.filter(|name| name.len() == 32 && name.bytes().all(|b| b.is_ascii_hexdigit()))
.collect();
keys.sort();
keys.into_iter()
.map(|key| {
let bytes = std::fs::read(store.join(&key)).expect("a stored value");
(format!("store:{key}"), format!("{:016x}", fnv(&bytes)))
})
.collect()
}
fn pinned(case: usize, dir: &Path, target: &str, instance: &str) -> Vec<(String, String)> {
let out = scratch(&format!("pinned-{case}"));
let wav = out.join("out.wav");
let store = out.join("store");
let (answered, stdout) = render(dir, target, &store, &format!("samples={}", wav.display()));
let samples = std::fs::read(&wav).unwrap_or_default();
let mut held = vec![
(
"stdout".to_string(),
format!(
"{:016x}",
fnv(stdout
.replace(&wav.display().to_string(), "<wav>")
.as_bytes())
),
),
("wav".to_string(), format!("{:016x}", fnv(&samples))),
];
held.extend(stored(&store));
for name in READINGS {
let call = match name {
"bindings" => format!("bindings(node={instance})"),
other => other.to_string(),
};
let (read, printed) = render(dir, target, &store, &call);
let value = match read {
true => format!("{:016x}", fnv(printed.as_bytes())),
false => format!("refused {}", codes(&printed)),
};
held.push((name.to_string(), value));
}
let _ = std::fs::remove_dir_all(&out);
assert!(answered, "{target}: {stdout}");
held
}
#[cfg(all(target_os = "linux", target_arch = "x86_64"))]
#[test]
fn renders_stores_and_readings_answer_what_they_answered() {
let mut table = String::new();
for (case, (name, target, instance)) in CASES.iter().enumerate() {
for (item, value) in pinned(case, &fixture(name), target, instance) {
table.push_str(&format!("{case} {item} {value}\n"));
}
}
let moved: Vec<&str> = table
.lines()
.filter(|line| !PINNED.trim().lines().any(|p| p == *line))
.collect();
assert!(
moved.is_empty() && table.lines().count() == PINNED.trim().lines().count(),
"moved:\n{}\nwhole table:\n{table}",
moved.join("\n")
);
}