2021-12-03 21:13:19 +00:00
|
|
|
use mps_interpreter::lang::MpsLanguageError;
|
2021-12-12 19:59:43 +00:00
|
|
|
use mps_interpreter::tokens::{MpsToken, MpsTokenizer, ParseError};
|
|
|
|
use mps_interpreter::*;
|
|
|
|
use std::collections::VecDeque;
|
|
|
|
use std::io::Cursor;
|
2021-12-03 21:13:19 +00:00
|
|
|
|
|
|
|
#[test]
|
|
|
|
fn parse_line() -> Result<(), ParseError> {
|
|
|
|
let cursor = Cursor::new("sql(`SELECT * FROM songs;`)");
|
|
|
|
let correct_tokens: Vec<MpsToken> = vec![
|
2021-12-29 17:12:58 +00:00
|
|
|
MpsToken::Name("sql".into()),
|
2021-12-03 21:13:19 +00:00
|
|
|
MpsToken::OpenBracket,
|
|
|
|
MpsToken::Literal("SELECT * FROM songs;".into()),
|
|
|
|
MpsToken::CloseBracket,
|
|
|
|
];
|
|
|
|
|
|
|
|
let mut tokenizer = MpsTokenizer::new(cursor);
|
|
|
|
let mut buf = VecDeque::<MpsToken>::new();
|
|
|
|
tokenizer.read_line(&mut buf)?; // operation being tested
|
|
|
|
|
|
|
|
// debug output
|
|
|
|
println!("Token buffer:");
|
|
|
|
for i in 0..buf.len() {
|
|
|
|
println!(" Token #{}: {}", i, &buf[i]);
|
|
|
|
}
|
|
|
|
|
|
|
|
// validity tests
|
|
|
|
assert_eq!(buf.len(), correct_tokens.len());
|
|
|
|
for i in 0..buf.len() {
|
2022-01-01 00:56:46 +00:00
|
|
|
assert_eq!(
|
|
|
|
buf[i], correct_tokens[i],
|
|
|
|
"Tokens at position {} do not match ()",
|
|
|
|
i
|
|
|
|
);
|
2021-12-03 21:13:19 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
tokenizer.read_line(&mut buf)?; // this should immediately return
|
|
|
|
Ok(())
|
|
|
|
}
|
|
|
|
|
2021-12-29 17:12:58 +00:00
|
|
|
#[inline(always)]
|
2022-01-01 00:56:46 +00:00
|
|
|
fn execute_single_line(
|
|
|
|
line: &str,
|
|
|
|
should_be_emtpy: bool,
|
|
|
|
should_complete: bool,
|
|
|
|
) -> Result<(), Box<dyn MpsLanguageError>> {
|
2021-12-29 17:12:58 +00:00
|
|
|
println!("--- Executing MPS code: '{}' ---", line);
|
2021-12-12 19:59:43 +00:00
|
|
|
let cursor = Cursor::new(line);
|
2021-12-03 21:13:19 +00:00
|
|
|
|
|
|
|
let tokenizer = MpsTokenizer::new(cursor);
|
|
|
|
let interpreter = MpsInterpretor::with_standard_vocab(tokenizer);
|
|
|
|
|
|
|
|
let mut count = 0;
|
|
|
|
for result in interpreter {
|
|
|
|
if let Ok(item) = result {
|
2021-12-12 19:59:43 +00:00
|
|
|
count += 1;
|
|
|
|
if count > 100 {
|
2021-12-29 17:12:58 +00:00
|
|
|
if should_complete {
|
2021-12-30 00:46:53 +00:00
|
|
|
continue; // skip println, but still check for errors
|
2021-12-29 17:12:58 +00:00
|
|
|
} else {
|
|
|
|
println!("Got 100 items, stopping to avoid infinite loop");
|
|
|
|
break;
|
|
|
|
}
|
2021-12-12 19:59:43 +00:00
|
|
|
} // no need to spam the rest of the songs
|
2022-01-21 00:52:03 +00:00
|
|
|
println!("Got song `{}` (file: `{}`)",
|
|
|
|
item.field("title").expect("Expected field `title` to exist").clone().to_str().expect("Expected field `title` to be String"),
|
|
|
|
item.field("filename").expect("Expected field `filename` to exist").clone().to_str().expect("Expected field `filename` to be String")
|
|
|
|
);
|
2021-12-03 21:13:19 +00:00
|
|
|
} else {
|
2021-12-29 17:12:58 +00:00
|
|
|
println!("!!! Got error while iterating (executing) !!!");
|
2022-01-01 00:56:46 +00:00
|
|
|
eprintln!("{}", result.as_ref().err().unwrap());
|
2021-12-03 21:13:19 +00:00
|
|
|
result?;
|
|
|
|
}
|
|
|
|
}
|
2021-12-12 19:59:43 +00:00
|
|
|
if should_be_emtpy {
|
2022-01-01 00:56:46 +00:00
|
|
|
assert_eq!(
|
|
|
|
count, 0,
|
|
|
|
"{} music items found while iterating over line which should be None",
|
|
|
|
count
|
|
|
|
);
|
2021-12-12 19:59:43 +00:00
|
|
|
} else {
|
2022-01-01 00:56:46 +00:00
|
|
|
println!(
|
|
|
|
"Got {} items, execution complete (no songs were harmed in the making of this test)",
|
|
|
|
count
|
|
|
|
);
|
|
|
|
assert_ne!(
|
|
|
|
count, 0,
|
|
|
|
"0 music items found while iterating over line which should have Some results"
|
|
|
|
); // assumption: database is populated
|
2021-12-12 19:59:43 +00:00
|
|
|
}
|
2021-12-03 21:13:19 +00:00
|
|
|
Ok(())
|
|
|
|
}
|
2021-12-12 19:59:43 +00:00
|
|
|
|
|
|
|
#[test]
|
|
|
|
fn execute_sql_line() -> Result<(), Box<dyn MpsLanguageError>> {
|
2021-12-29 17:12:58 +00:00
|
|
|
execute_single_line("sql(`SELECT * FROM songs ORDER BY artist;`)", false, true)
|
2021-12-12 19:59:43 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
#[test]
|
|
|
|
fn execute_simple_sql_line() -> Result<(), Box<dyn MpsLanguageError>> {
|
2021-12-29 17:12:58 +00:00
|
|
|
execute_single_line("song(`lov`)", false, true)
|
2021-12-12 19:59:43 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
#[test]
|
|
|
|
fn execute_comment_line() -> Result<(), Box<dyn MpsLanguageError>> {
|
2021-12-29 17:12:58 +00:00
|
|
|
execute_single_line("// this is a comment", true, true)?;
|
|
|
|
execute_single_line("# this is a special comment", true, true)
|
|
|
|
}
|
|
|
|
|
|
|
|
#[test]
|
|
|
|
fn execute_repeat_line() -> Result<(), Box<dyn MpsLanguageError>> {
|
2022-01-12 01:45:48 +00:00
|
|
|
execute_single_line("repeat(files(`~/Music/MusicFlac/Bruno Mars/24K Magic/`))", false, false)?;
|
|
|
|
execute_single_line("repeat(files(`~/Music/MusicFlac/Bruno Mars/24K Magic/`), 4)", false, true)?;
|
|
|
|
execute_single_line("repeat(files(`~/Music/MusicFlac/Bruno Mars/24K Magic/`), 0)", true, true)
|
2021-12-29 17:12:58 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
#[test]
|
|
|
|
fn execute_sql_init_line() -> Result<(), Box<dyn MpsLanguageError>> {
|
2022-01-01 00:56:46 +00:00
|
|
|
execute_single_line(
|
|
|
|
"sql_init(generate = false, folder = `/home/ngnius/Music`)",
|
|
|
|
true,
|
|
|
|
true,
|
|
|
|
)
|
2021-12-29 17:12:58 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
#[test]
|
|
|
|
fn execute_assign_line() -> Result<(), Box<dyn MpsLanguageError>> {
|
2022-01-01 00:56:46 +00:00
|
|
|
execute_single_line(
|
|
|
|
"let some_var = repeat(song(`Christmas in L.A.`))",
|
|
|
|
true,
|
|
|
|
true,
|
|
|
|
)?;
|
2021-12-29 17:12:58 +00:00
|
|
|
execute_single_line("let some_var2 = 1234", true, true)
|
|
|
|
}
|
|
|
|
|
|
|
|
#[test]
|
|
|
|
fn execute_emptyfilter_line() -> Result<(), Box<dyn MpsLanguageError>> {
|
2022-01-18 14:14:05 +00:00
|
|
|
execute_single_line("files(`~/Music/MusicFlac/Bruno Mars/24K Magic/`).().().()", false, true)
|
2021-12-29 17:12:58 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
#[test]
|
|
|
|
fn execute_fieldfilter_line() -> Result<(), Box<dyn MpsLanguageError>> {
|
2022-01-11 15:22:05 +00:00
|
|
|
execute_single_line(
|
|
|
|
"files(`~/Music/MusicFlac/Bruno Mars/24K Magic/`).(year >= 2000)",
|
|
|
|
false,
|
|
|
|
true,
|
2022-01-12 01:45:48 +00:00
|
|
|
)?;
|
|
|
|
execute_single_line(
|
|
|
|
"files(`~/Music/MusicFlac/Bruno Mars/24K Magic/`).(year <= 2020)",
|
|
|
|
false,
|
|
|
|
true,
|
|
|
|
)?;
|
|
|
|
execute_single_line(
|
|
|
|
"files(`~/Music/MusicFlac/Bruno Mars/24K Magic/`).(year == 2016)",
|
|
|
|
false,
|
|
|
|
true,
|
|
|
|
)?;
|
|
|
|
execute_single_line(
|
|
|
|
"files(`~/Music/MusicFlac/Bruno Mars/24K Magic/`).(year != 2048)",
|
|
|
|
false,
|
|
|
|
true,
|
2022-01-11 15:22:05 +00:00
|
|
|
)
|
2021-12-12 19:59:43 +00:00
|
|
|
}
|
2022-01-01 00:56:46 +00:00
|
|
|
|
2022-01-12 14:59:30 +00:00
|
|
|
#[test]
|
|
|
|
fn execute_fieldfiltermaybe_line() -> Result<(), Box<dyn MpsLanguageError>> {
|
|
|
|
execute_single_line(
|
|
|
|
"files(`~/Music/MusicFlac/Bruno Mars/24K Magic/`).(year? >= 2000)",
|
|
|
|
false,
|
|
|
|
true,
|
|
|
|
)?;
|
|
|
|
execute_single_line(
|
|
|
|
"files(`~/Music/MusicFlac/Bruno Mars/24K Magic/`).(year? <= 2020)",
|
|
|
|
false,
|
|
|
|
true,
|
|
|
|
)?;
|
|
|
|
execute_single_line(
|
|
|
|
"files(`~/Music/MusicFlac/Bruno Mars/24K Magic/`).(year! == 2016)",
|
|
|
|
false,
|
|
|
|
true,
|
|
|
|
)?;
|
|
|
|
execute_single_line(
|
|
|
|
"files(`~/Music/MusicFlac/Bruno Mars/24K Magic/`).(year! != `test`)",
|
|
|
|
false,
|
|
|
|
true,
|
|
|
|
)
|
|
|
|
}
|
|
|
|
|
2022-01-01 00:56:46 +00:00
|
|
|
#[test]
|
|
|
|
fn execute_files_line() -> Result<(), Box<dyn MpsLanguageError>> {
|
|
|
|
execute_single_line(
|
2022-01-11 15:22:05 +00:00
|
|
|
r"files(folder=`~/Music/MusicFlac/Bruno Mars/24K Magic/`, re=``, recursive=false)",
|
2022-01-01 00:56:46 +00:00
|
|
|
false,
|
|
|
|
true,
|
2022-01-11 15:22:05 +00:00
|
|
|
)?;
|
|
|
|
execute_single_line(
|
|
|
|
r"files(`~/Music/MusicFlac/Bruno Mars/24K Magic/`)",
|
|
|
|
false,
|
|
|
|
true,
|
|
|
|
)?;
|
|
|
|
execute_single_line(r"files()", false, true)
|
2022-01-01 00:56:46 +00:00
|
|
|
}
|
2022-01-12 16:06:32 +00:00
|
|
|
|
|
|
|
#[test]
|
|
|
|
fn execute_indexfilter_line() -> Result<(), Box<dyn MpsLanguageError>> {
|
|
|
|
execute_single_line(
|
|
|
|
"files(`~/Music/MusicFlac/Bruno Mars/24K Magic/`).(2)",
|
|
|
|
false,
|
|
|
|
true,
|
|
|
|
)?;
|
|
|
|
execute_single_line(
|
|
|
|
"files(`~/Music/MusicFlac/Bruno Mars/24K Magic/`).(0)",
|
|
|
|
false,
|
|
|
|
true,
|
|
|
|
)?;
|
2022-01-17 21:58:37 +00:00
|
|
|
execute_single_line(
|
|
|
|
"files(`~/Music/MusicFlac/Bruno Mars/24K Magic/`).(!0)",
|
|
|
|
false,
|
|
|
|
true,
|
|
|
|
)?;
|
2022-01-12 16:06:32 +00:00
|
|
|
execute_single_line(
|
|
|
|
"files(`~/Music/MusicFlac/Bruno Mars/24K Magic/`).(200)",
|
|
|
|
true,
|
|
|
|
true,
|
|
|
|
)
|
|
|
|
}
|
2022-01-12 21:23:56 +00:00
|
|
|
|
|
|
|
#[test]
|
|
|
|
fn execute_rangefilter_line() -> Result<(), Box<dyn MpsLanguageError>> {
|
|
|
|
execute_single_line(
|
|
|
|
"files(`~/Music/MusicFlac/Bruno Mars/24K Magic/`).(..)",
|
|
|
|
false,
|
|
|
|
true,
|
|
|
|
)?;
|
|
|
|
execute_single_line(
|
|
|
|
"files(`~/Music/MusicFlac/Bruno Mars/24K Magic/`).(0..=4)",
|
|
|
|
false,
|
|
|
|
true,
|
|
|
|
)?;
|
|
|
|
execute_single_line(
|
|
|
|
"files(`~/Music/MusicFlac/Bruno Mars/24K Magic/`).(..=4)",
|
|
|
|
false,
|
|
|
|
true,
|
|
|
|
)?;
|
|
|
|
execute_single_line(
|
|
|
|
"files(`~/Music/MusicFlac/Bruno Mars/24K Magic/`).(0..5)",
|
|
|
|
false,
|
|
|
|
true,
|
|
|
|
)
|
|
|
|
}
|
2022-01-17 02:00:00 +00:00
|
|
|
|
|
|
|
#[test]
|
|
|
|
fn execute_orfilter_line() -> Result<(), Box<dyn MpsLanguageError>> {
|
|
|
|
execute_single_line(
|
|
|
|
"files(`~/Music/MusicFlac/Bruno Mars/24K Magic/`).(4 || 5)",
|
|
|
|
false,
|
|
|
|
true,
|
|
|
|
)?;
|
|
|
|
execute_single_line(
|
|
|
|
"files(`~/Music/MusicFlac/Bruno Mars/24K Magic/`).(year != 2020 || 5)",
|
|
|
|
false,
|
|
|
|
true,
|
2022-01-17 21:58:37 +00:00
|
|
|
)?;
|
|
|
|
execute_single_line(
|
|
|
|
"files(`~/Music/MusicFlac/Bruno Mars/24K Magic/`).(year != 2020 || 5 || 4 || 12)",
|
|
|
|
false,
|
|
|
|
true,
|
2022-01-17 02:00:00 +00:00
|
|
|
)
|
|
|
|
}
|
2022-01-18 14:14:05 +00:00
|
|
|
|
|
|
|
#[test]
|
|
|
|
fn execute_replacefilter_line() -> Result<(), Box<dyn MpsLanguageError>> {
|
|
|
|
execute_single_line(
|
|
|
|
"files(`~/Music/MusicFlac/Bruno Mars/24K Magic/`).(if 4: files(`~/Music/MusicFlac/Bruno Mars/24K Magic/`).(5))",
|
|
|
|
false,
|
|
|
|
true,
|
|
|
|
)?;
|
|
|
|
execute_single_line(
|
|
|
|
"files(`~/Music/MusicFlac/Bruno Mars/24K Magic/`).(if 4: files(`~/Music/MusicFlac/Bruno Mars/24K Magic/`).(5) else item.())",
|
|
|
|
false,
|
|
|
|
true,
|
|
|
|
)?;
|
|
|
|
execute_single_line(
|
|
|
|
"files(`~/Music/MusicFlac/Bruno Mars/24K Magic/`).(if 4: item.() else files(`~/Music/MusicFlac/Bruno Mars/24K Magic/`).(0 || 1).(if 200: files() else repeat(item.(), 2)))",
|
|
|
|
false,
|
|
|
|
true,
|
|
|
|
)
|
|
|
|
}
|
2022-01-23 01:44:53 +00:00
|
|
|
|
|
|
|
#[test]
|
|
|
|
fn execute_emptysort_line() -> Result<(), Box<dyn MpsLanguageError>> {
|
|
|
|
execute_single_line(
|
|
|
|
"files(`~/Music/MusicFlac/Bruno Mars/24K Magic/`).sort()",
|
|
|
|
false,
|
|
|
|
true,
|
|
|
|
)?;
|
|
|
|
execute_single_line(
|
|
|
|
"files(`~/Music/MusicFlac/Bruno Mars/24K Magic/`)~()",
|
|
|
|
false,
|
|
|
|
true,
|
|
|
|
)
|
|
|
|
}
|