tiny-soccersim-rust/tests/tssr.rs

368 lines
9.4 KiB
Rust

use std::io::Write;
use tempfile::NamedTempFile;
fn write_tsrc(content: &str) -> NamedTempFile {
let mut f = NamedTempFile::new().unwrap();
f.write_all(content.as_bytes()).unwrap();
f.flush().unwrap();
f
}
fn parse(content: &str) -> Result<tssr::tsrc::TsrcScript, String> {
let f = write_tsrc(content);
tssr::tsrc::parse_tsrc(f.path().to_str().unwrap())
}
#[test]
fn goal_player_not_on_team() {
let r = parse(r#"
string h = "Team A";
string a = "Team B";
players["P1"] = h;
players["P2"] = a;
goal(10, h, "Wrong Player");
match(h, a);
"#);
assert!(r.is_err());
let err = r.unwrap_err();
assert!(err.contains("is not on team"), "got: {}", err);
assert!(err.contains("Wrong Player"), "got: {}", err);
}
#[test]
fn goal_duplicate_same_minute_player() {
let r = parse(r#"
string h = "Team A";
string a = "Team B";
players["P1"] = h;
players["P2"] = a;
goal(10, h, "P1");
goal(10, a, "P1");
match(h, a);
"#);
assert!(r.is_err());
let err = r.unwrap_err();
assert!(err.contains("duplicate goal"), "got: {}", err);
}
#[test]
fn goal_minute_out_of_range() {
let r = parse(r#"
string h = "Team A";
string a = "Team B";
players["P1"] = h;
players["P2"] = a;
goal(95, h, "P1");
match(h, a);
"#);
assert!(r.is_err());
let err = r.unwrap_err();
assert!(err.contains("between 1 and 90"), "got: {}", err);
}
#[test]
fn goal_undefined_team() {
let r = parse(r#"
string h = "Team A";
string a = "Team B";
players["P1"] = h;
players["P2"] = a;
goal(10, "Ghost Team", "P1");
match(h, a);
"#);
assert!(r.is_err());
let err = r.unwrap_err();
assert!(err.contains("not a match team"), "got: {}", err);
}
#[test]
fn goal_undefined_variable() {
let r = parse(r#"
string h = "Team A";
string a = "Team B";
players["P1"] = h;
players["P2"] = a;
goal(10, ghost, "P1");
match(h, a);
"#);
assert!(r.is_err());
let err = r.unwrap_err();
assert!(err.contains("undefined variable"), "got: {}", err);
assert!(err.contains("ghost"), "got: {}", err);
}
#[test]
fn script_valid_full_with_goals() {
let r = parse(r#"
string home = "GNU United";
string away = "BSD Athletic";
players["Richard Stallman"] = home;
players["Brian Fox"] = home;
players["Linus Torvalds"] = home;
players["Theo de Raadt"] = away;
players["Jordan Hubbard"] = away;
players["Ken Thompson"] = away;
goal(12, home, "Richard Stallman");
goal(34, away, "Theo de Raadt");
goal(56, home, "Brian Fox");
goal(78, "BSD Athletic", "Ken Thompson");
goal(89, home, "Linus Torvalds");
match(home, away);
"#);
assert!(r.is_ok(), "got: {:?}", r.err());
let s = r.unwrap();
let goals = s.goals.unwrap();
assert_eq!(goals.len(), 5);
let home_goals: Vec<_> = goals.iter().filter(|g| g.team == "GNU United").collect();
let away_goals: Vec<_> = goals.iter().filter(|g| g.team == "BSD Athletic").collect();
assert_eq!(home_goals.len(), 3);
assert_eq!(away_goals.len(), 2);
assert_eq!(home_goals[0].player, "Richard Stallman");
assert_eq!(home_goals[0].minute, 12);
}
#[test]
fn script_variable_ref_in_players() {
let r = parse(r#"
string h = "Team A";
string a = "Team B";
players["P1"] = h;
players["P2"] = a;
match(h, a);
"#);
assert!(r.is_ok(), "got: {:?}", r.err());
let s = r.unwrap();
assert!(s.roster.contains_key("Team A"));
assert!(s.roster.contains_key("Team B"));
}
#[test]
fn script_mismatch_roster_team_name() {
let r = parse(r#"
string h = "Linux City";
string a = "Libre Pool";
players["P1"] = "Man Page City";
players["P2"] = a;
match(h, a);
"#);
assert!(r.is_err());
let err = r.unwrap_err();
assert!(err.contains("not a match team"), "got: {}", err);
assert!(err.contains("Man Page City"), "got: {}", err);
}
#[test]
fn script_duplicate_player() {
let r = parse(r#"
string h = "Team A";
string a = "Team B";
players["P1"] = h;
players["P1"] = h;
players["P2"] = a;
match(h, a);
"#);
assert!(r.is_err());
let err = r.unwrap_err();
assert!(err.contains("duplicate player"), "got: {}", err);
assert!(err.contains("P1"), "got: {}", err);
}
#[test]
fn script_duplicate_variable() {
let r = parse(r#"
string home = "Team A";
string home = "Team B";
players["P1"] = home;
players["P2"] = home;
match(home, home);
"#);
assert!(r.is_err());
let err = r.unwrap_err();
assert!(err.contains("redefined"), "got: {}", err);
assert!(err.contains("home"), "got: {}", err);
}
#[test]
fn script_no_match_directive() {
let r = parse(r#"
string h = "Team A";
string a = "Team B";
players["P1"] = h;
players["P2"] = a;
"#);
assert!(r.is_err());
let err = r.unwrap_err();
assert!(err.contains("no match() directive found"), "got: {}", err);
}
#[test]
fn script_same_team_in_match() {
let r = parse(r#"
string h = "Team A";
string a = "Team A";
players["P1"] = h;
players["P2"] = a;
match(h, a);
"#);
assert!(r.is_err());
let err = r.unwrap_err();
assert!(err.contains("same team"), "got: {}", err);
assert!(err.contains("Team A"), "got: {}", err);
}
#[test]
fn script_no_players_for_team() {
let r = parse(r#"
string h = "Team A";
string a = "Team B";
players["P1"] = h;
match(h, a);
"#);
assert!(r.is_err());
let err = r.unwrap_err();
assert!(err.contains("no players assigned"), "got: {}", err);
}
#[test]
fn define_default_is_unicode_table() {
let r = parse(r#"
string h = "Team A";
string a = "Team B";
players["P1"] = h;
players["P2"] = a;
match(h, a);
"#);
assert!(r.is_ok(), "got: {:?}", r.err());
assert_eq!(r.unwrap().output_mode, tssr::tsrc::OutputMode::UnicodeTable);
}
#[test]
fn define_json() {
let r = parse(r#"
#define JSON
string h = "Team A";
string a = "Team B";
players["P1"] = h;
players["P2"] = a;
match(h, a);
"#);
assert!(r.is_ok(), "got: {:?}", r.err());
assert_eq!(r.unwrap().output_mode, tssr::tsrc::OutputMode::Json);
}
#[test]
fn define_ascii_table() {
let r = parse(r#"
#define ASCII_TABLE
string h = "Team A";
string a = "Team B";
players["P1"] = h;
players["P2"] = a;
match(h, a);
"#);
assert!(r.is_ok(), "got: {:?}", r.err());
assert_eq!(r.unwrap().output_mode, tssr::tsrc::OutputMode::AsciiTable);
}
#[test]
fn define_unicode_table_explicit() {
let r = parse(r#"
#define UNICODE_TABLE
string h = "Team A";
string a = "Team B";
players["P1"] = h;
players["P2"] = a;
match(h, a);
"#);
assert!(r.is_ok(), "got: {:?}", r.err());
assert_eq!(r.unwrap().output_mode, tssr::tsrc::OutputMode::UnicodeTable);
}
#[test]
fn define_duplicate_error() {
let r = parse(r#"
#define JSON
#define ASCII_TABLE
string h = "Team A";
string a = "Team B";
players["P1"] = h;
players["P2"] = a;
match(h, a);
"#);
assert!(r.is_err());
let err = r.unwrap_err();
assert!(err.contains("duplicate #define"), "got: {}", err);
}
#[test]
fn define_unknown_error() {
let r = parse(r#"
#define FOO_BAR
string h = "Team A";
string a = "Team B";
players["P1"] = h;
players["P2"] = a;
match(h, a);
"#);
assert!(r.is_err());
let err = r.unwrap_err();
assert!(err.contains("unknown #define"), "got: {}", err);
assert!(err.contains("FOO_BAR"), "got: {}", err);
}
#[test]
fn situation_valid_with_goals() {
let r = parse(r#"
#define SITUATION
string h = "Team A";
string a = "Team B";
players["P1"] = h;
players["P2"] = a;
players["P3"] = h;
players["P4"] = a;
goal(10, h, "P1");
goal(45, a, "P2");
match(h, a);
"#);
assert!(r.is_ok(), "got: {:?}", r.err());
let s = r.unwrap();
assert!(s.situation_mode);
assert!(s.goals.is_some());
assert_eq!(s.goals.unwrap().len(), 2);
}
#[test]
fn situation_requires_goals_error() {
let r = parse(r#"
#define SITUATION
string h = "Team A";
string a = "Team B";
players["P1"] = h;
players["P2"] = a;
match(h, a);
"#);
assert!(r.is_err());
let err = r.unwrap_err();
assert!(err.contains("SITUATION"), "got: {}", err);
assert!(err.contains("goal()"), "got: {}", err);
}
#[test]
fn situation_combinable_with_output_mode() {
let r = parse(r#"
#define SITUATION
#define ASCII_TABLE
string h = "Team A";
string a = "Team B";
players["P1"] = h;
players["P2"] = a;
players["P3"] = h;
players["P4"] = a;
goal(10, h, "P1");
match(h, a);
"#);
assert!(r.is_ok(), "got: {:?}", r.err());
let s = r.unwrap();
assert!(s.situation_mode);
assert_eq!(s.output_mode, tssr::tsrc::OutputMode::AsciiTable);
}