use alloc::string::{String, ToString as _};
use core::time::Duration;
use shakmaty::fen::Fen;
use crate::{
ParseUciMessageError, ProtectionState, UciInfo, UciInfoCurrLine, UciInfoScore, UciMessage,
UciOptionConfig, UciSearchControl, UciTimeControl,
};
#[test]
fn test_display_uci() {
let msg = UciMessage::Uci;
assert_eq!(msg.to_string(), "uci");
}
#[test]
fn test_display_uciok() {
let msg = UciMessage::UciOk;
assert_eq!(msg.to_string(), "uciok");
}
#[test]
fn test_display_readyok() {
let msg = UciMessage::ReadyOk;
assert_eq!(msg.to_string(), "readyok");
}
#[test]
fn test_display_register_later() {
let msg = UciMessage::register_later();
assert_eq!(msg.to_string(), "register later");
}
#[test]
fn test_display_register_name_code() {
let msg = UciMessage::register_code("foo", "bar");
assert_eq!(msg.to_string(), "register name foo code bar");
}
#[test]
fn test_display_position_startpos() {
let msg = UciMessage::Position {
startpos: true,
fen: None,
moves: vec![],
};
assert_eq!(msg.to_string(), "position startpos")
}
#[test]
fn test_display_position_statpos_moves() {
let msg = UciMessage::Position {
startpos: true,
fen: None,
moves: vec!["e2e4".parse().unwrap(), "e7e5".parse().unwrap()],
};
assert_eq!(msg.to_string(), "position startpos moves e2e4 e7e5")
}
#[test]
fn test_display_position_fen() {
let msg = UciMessage::Position {
startpos: false,
fen: Some(
"r1bqkbnr/ppp2Qpp/2np4/4p3/2B1P3/8/PPPP1PPP/RNB1K1NR b KQkq - 0 4"
.parse()
.unwrap(),
),
moves: vec![],
};
assert_eq!(
msg.to_string(),
"position fen r1bqkbnr/ppp2Qpp/2np4/4p3/2B1P3/8/PPPP1PPP/RNB1K1NR b KQkq - 0 4"
)
}
#[test]
fn test_display_position_fen_moves() {
let msg = UciMessage::Position {
startpos: false,
fen: Some(
"rnbqkbnr/pppppppp/8/8/8/8/PPPPPPPP/RNBQKBNR w KQkq - 0 1"
.parse()
.unwrap(),
),
moves: vec!["e2e4".parse().unwrap(), "e7e5".parse().unwrap()],
};
assert_eq!(
msg.to_string(),
"position fen rnbqkbnr/pppppppp/8/8/8/8/PPPPPPPP/RNBQKBNR w KQkq - 0 1 moves e2e4 e7e5"
)
}
#[test]
fn test_display_go() {
let msg = UciMessage::go();
assert_eq!(msg.to_string(), "go");
}
#[test]
fn test_display_go_infinite() {
let msg = UciMessage::go_infinite();
assert_eq!(msg.to_string(), "go infinite");
}
#[test]
fn test_display_go_ponder() {
let msg = UciMessage::go_ponder();
assert_eq!(msg.to_string(), "go ponder");
}
#[test]
fn test_display_go_movetime() {
let msg = UciMessage::go_movetime(Duration::from_millis(10000));
assert_eq!(msg.to_string(), "go movetime 10000");
}
#[test]
fn test_display_go_depth() {
let msg = UciMessage::Go {
time_control: None,
search_control: Some(UciSearchControl {
depth: Some(30),
..Default::default()
}),
};
assert_eq!(msg.to_string(), "go depth 30");
}
#[test]
fn test_display_go_full_example() {
let msg = UciMessage::Go {
time_control: Some(UciTimeControl::MoveTime(Duration::from_millis(10000))),
search_control: Some(UciSearchControl {
depth: Some(6),
nodes: Some(55000000),
mate: Some(100),
search_moves: vec!["a1h8".parse().unwrap()],
}),
};
assert_eq!(
msg.to_string(),
"go movetime 10000 depth 6 nodes 55000000 mate 100 searchmoves a1h8"
);
}
#[test]
fn test_display_id_name() {
let msg = UciMessage::Id {
name: Some(String::from("Shakmaty")),
author: None,
};
assert_eq!(msg.to_string(), "id name Shakmaty");
}
#[test]
fn test_display_id_author() {
let msg = UciMessage::Id {
name: None,
author: Some(String::from("Matija Kejžar")),
};
assert_eq!(msg.to_string(), "id author Matija Kejžar");
}
#[test]
fn test_display_bestmove() {
let msg = UciMessage::BestMove {
best_move: "a1a7".parse().unwrap(),
ponder: None,
};
assert_eq!(msg.to_string(), "bestmove a1a7");
}
#[test]
fn test_display_bestmove_with_options() {
let msg = UciMessage::BestMove {
best_move: "b4a5".parse().unwrap(),
ponder: Some("b4d6".parse().unwrap()),
};
assert_eq!(msg.to_string(), "bestmove b4a5 ponder b4d6");
}
#[test]
fn test_display_copyprotection() {
let msg = UciMessage::CopyProtection(ProtectionState::Checking);
assert_eq!(msg.to_string(), "copyprotection checking");
}
#[test]
fn test_display_registration() {
let msg = UciMessage::Registration(ProtectionState::Ok);
assert_eq!(msg.to_string(), "registration ok");
}
#[test]
fn test_display_check_option() {
let msg = UciMessage::Option(UciOptionConfig::Check {
name: String::from("Nullmove"),
default: Some(false),
});
assert_eq!(
msg.to_string(),
"option name Nullmove type check default false"
);
}
#[test]
fn test_display_spin_option() {
let msg = UciMessage::Option(UciOptionConfig::Spin {
name: String::from("Selectivity"),
default: Some(2),
min: Some(0),
max: Some(4),
});
assert_eq!(
msg.to_string(),
"option name Selectivity type spin default 2 min 0 max 4"
);
}
#[test]
fn test_display_combo_option() {
let msg = UciMessage::Option(UciOptionConfig::Combo {
name: String::from("Style"),
default: Some(String::from("Normal")),
var: vec![
String::from("Solid"),
String::from("Normal"),
String::from("Risky"),
],
});
assert_eq!(
msg.to_string(),
"option name Style type combo default Normal var Solid var Normal var Risky"
);
}
#[test]
fn test_display_string_option() {
let msg = UciMessage::Option(UciOptionConfig::String {
name: String::from("Nalimov Path"),
default: Some(String::from("c:\\")),
});
assert_eq!(
msg.to_string(),
"option name Nalimov Path type string default c:\\"
);
}
#[test]
fn test_display_button_option() {
let msg = UciMessage::Option(UciOptionConfig::Button {
name: String::from("Clear Hash"),
});
assert_eq!(msg.to_string(), "option name Clear Hash type button");
}
#[test]
fn test_display_info_depth() {
let msg = UciMessage::Info(UciInfo {
depth: Some(24),
..Default::default()
});
assert_eq!(msg.to_string(), "info depth 24");
}
#[test]
fn test_display_info_seldepth() {
let msg = UciMessage::Info(UciInfo {
depth: Some(22),
sel_depth: Some(17),
..Default::default()
});
assert_eq!(msg.to_string(), "info depth 22 seldepth 17");
}
#[test]
fn test_display_info_pv() {
let msg = UciMessage::Info(UciInfo {
depth: Some(2),
score: Some(UciInfoScore::from_centipawns(214)),
time: Some(Duration::from_millis(1242)),
nodes: Some(2124),
nps: Some(34928),
pv: vec![
"e2e4".parse().unwrap(),
"e7e5".parse().unwrap(),
"g1f3".parse().unwrap(),
],
..Default::default()
});
assert_eq!(
msg.to_string(),
"info depth 2 time 1242 nodes 2124 pv e2e4 e7e5 g1f3 score cp 214 nps 34928"
);
}
#[test]
fn test_display_info_multipv() {
let msg = UciMessage::Info(UciInfo {
depth: Some(5),
sel_depth: Some(5),
multi_pv: Some(1),
score: Some(UciInfoScore::from_centipawns(-5)),
nodes: Some(1540),
nps: Some(54),
tb_hits: Some(0),
time: Some(Duration::from_millis(28098)),
pv: vec![
"a8b6".parse().unwrap(),
"e3b6".parse().unwrap(),
"b1b6".parse().unwrap(),
"a5a7".parse().unwrap(),
"e2e3".parse().unwrap(),
],
..Default::default()
});
assert_eq!(
msg.to_string(),
"info depth 5 seldepth 5 time 28098 nodes 1540 pv a8b6 e3b6 b1b6 a5a7 e2e3 multipv 1 score cp -5 nps 54 tbhits 0"
);
}
#[test]
fn test_display_info_score() {
let msg = UciMessage::Info(UciInfo {
score: Some(UciInfoScore {
cp: Some(817),
upper_bound: true,
..Default::default()
}),
..Default::default()
});
assert_eq!(msg.to_string(), "info score cp 817 upperbound");
}
#[test]
fn test_display_info_score_mate_in_three() {
let msg = UciMessage::Info(UciInfo {
score: Some(UciInfoScore {
mate: Some(-3),
..Default::default()
}),
..Default::default()
});
assert_eq!(msg.to_string(), "info score mate -3");
}
#[test]
fn test_display_info_currmove() {
let msg = UciMessage::Info(UciInfo {
curr_move: Some("a5c3".parse().unwrap()),
..Default::default()
});
assert_eq!(msg.to_string(), "info currmove a5c3");
}
#[test]
fn test_display_info_currmovenumber() {
let msg = UciMessage::Info(UciInfo {
curr_move: Some("a2f2".parse().unwrap()),
curr_move_num: Some(2),
..Default::default()
});
assert_eq!(msg.to_string(), "info currmove a2f2 currmovenumber 2");
}
#[test]
fn test_display_info_hashfull() {
let msg = UciMessage::Info(UciInfo {
hash_full: Some(455),
..Default::default()
});
assert_eq!(msg.to_string(), "info hashfull 455");
}
#[test]
fn test_display_info_nps() {
let msg = UciMessage::Info(UciInfo {
nps: Some(5098),
..Default::default()
});
assert_eq!(msg.to_string(), "info nps 5098");
}
#[test]
fn test_display_info_tbhits_sbhits() {
let msg = UciMessage::Info(UciInfo {
tb_hits: Some(987),
sb_hits: Some(409),
..Default::default()
});
assert_eq!(msg.to_string(), "info tbhits 987 sbhits 409");
}
#[test]
fn test_display_info_cpuload() {
let msg = UciMessage::Info(UciInfo {
cpu_load: Some(823),
..Default::default()
});
assert_eq!(msg.to_string(), "info cpuload 823");
}
#[test]
fn test_display_info_string() {
let msg = UciMessage::Info(UciInfo {
string: Some(String::from("Invalid move: d6e1 - violates chess rules")),
..Default::default()
});
assert_eq!(
msg.to_string(),
"info string Invalid move: d6e1 - violates chess rules"
);
}
#[test]
fn test_display_info_refutation() {
let msg = UciMessage::Info(UciInfo {
refutation: vec!["d1h5".parse().unwrap(), "g6h5".parse().unwrap()],
..Default::default()
});
assert_eq!(msg.to_string(), "info refutation d1h5 g6h5");
}
#[test]
fn test_display_info_currline() {
let msg = UciMessage::Info(UciInfo {
curr_line: vec![UciInfoCurrLine {
cpu_nr: Some(1),
moves: vec!["d1h5".parse().unwrap(), "g6h5".parse().unwrap()],
}],
..Default::default()
});
assert_eq!(msg.to_string(), "info currline cpunr 1 d1h5 g6h5");
}
#[test]
fn test_display_serialize_none_setoption() {
let msg = UciMessage::SetOption {
name: String::from("Some option"),
value: None,
};
assert_eq!(msg.to_string(), "setoption name Some option value <empty>")
}
#[test]
fn test_display_serialize_empty_setoption() {
let msg = UciMessage::SetOption {
name: String::from("ABC"),
value: Some(String::from("")),
};
assert_eq!(msg.to_string(), "setoption name ABC value <empty>")
}
#[test]
fn test_parse_uci() {
let msg: Result<UciMessage, ParseUciMessageError> = "uci\r\n".parse();
assert_eq!(msg, Ok(UciMessage::Uci));
}
#[test]
fn test_parse_debug_on() {
let msg: Result<UciMessage, ParseUciMessageError> = "debug on\r\n".parse();
assert_eq!(msg, Ok(UciMessage::Debug(true)));
}
#[test]
fn test_parse_debug_off() {
let msg: Result<UciMessage, ParseUciMessageError> = "debug off\n".parse();
assert_eq!(msg, Ok(UciMessage::Debug(false)));
}
#[test]
fn test_parse_debugon() {
"debugon\r\n"
.parse::<UciMessage>()
.expect_err("Should not parse 'debugon'");
}
#[test]
fn test_parse_debug_wrong_param() {
"debug abc\r\n"
.parse::<UciMessage>()
.expect_err("Should not parse 'debug abc'");
}
#[test]
fn test_parse_debug_cutoff() {
"debug ontario\r\n"
.parse::<UciMessage>()
.expect_err("Should not parse");
}
#[test]
fn test_parse_isready() {
let msg: Result<UciMessage, ParseUciMessageError> = " \tisready \r\n".parse();
assert_eq!(msg, Ok(UciMessage::IsReady));
}
#[test]
fn test_parse_set_option_bool() {
let msg: Result<UciMessage, ParseUciMessageError> =
"setoption name Nullmove value true\n".parse();
let expected = UciMessage::SetOption {
name: String::from("Nullmove"),
value: Some(String::from("true")),
};
assert_eq!(msg, Ok(expected));
}
#[test]
fn test_parse_set_option_int() {
let msg: Result<UciMessage, ParseUciMessageError> =
"setoption name Selectivity is awesome value 3\n".parse();
let expected = UciMessage::SetOption {
name: String::from("Selectivity is awesome"),
value: Some(String::from("3")),
};
assert_eq!(msg, Ok(expected));
}
#[test]
fn test_parse_set_option_button() {
let msg: Result<UciMessage, ParseUciMessageError> = "setoption name Clear Hash\r\n".parse();
let expected = UciMessage::SetOption {
name: String::from("Clear Hash"),
value: None,
};
assert_eq!(msg, Ok(expected));
}
#[test]
fn test_parse_set_option_str() {
let msg: Result<UciMessage, ParseUciMessageError> =
"setoption name NalimovPath value c:\\chess\\tb\\4;c:\\chess\\tb\\5\n".parse();
let expected = UciMessage::SetOption {
name: String::from("NalimovPath"),
value: Some(String::from("c:\\chess\\tb\\4;c:\\chess\\tb\\5")),
};
assert_eq!(msg, Ok(expected))
}
#[test]
fn test_parse_register_later() {
let msg: Result<UciMessage, ParseUciMessageError> = "REGISTER lateR\r\n".parse();
assert_eq!(msg, Ok(UciMessage::register_later()));
}
#[test]
fn test_parse_register_name_code() {
let msg: Result<UciMessage, ParseUciMessageError> =
"register name Matija Kejžar code 4359874324\n".parse();
let expected = UciMessage::register_code("Matija Kejžar", "4359874324");
assert_eq!(msg, Ok(expected));
}
#[test]
fn test_parse_register_invalid() {
"register name Matija Kejžar\n"
.parse::<UciMessage>()
.expect_err("Parse error expected.");
}
#[test]
fn test_parse_register_invalid2() {
"register code XX-344-00LP name Matija Kejžar\n"
.parse::<UciMessage>()
.expect_err("Parse error expected.");
}
#[test]
fn test_parse_ucinewgame() {
let msg: Result<UciMessage, ParseUciMessageError> = " ucinewGAME \r\n".parse();
assert_eq!(msg, Ok(UciMessage::UciNewGame));
}
#[test]
fn test_parse_stop() {
let msg: Result<UciMessage, ParseUciMessageError> = "stop\r\n".parse();
assert_eq!(msg, Ok(UciMessage::Stop));
}
#[test]
fn test_parse_stop_really_stop() {
"stopper\r\n"
.parse::<UciMessage>()
.expect_err("Parse error expected for 'stopper'.");
}
#[test]
fn test_parse_quit() {
let msg: Result<UciMessage, ParseUciMessageError> = "QUIT\r\n".parse();
assert_eq!(msg, Ok(UciMessage::Quit));
}
#[test]
fn test_parse_ponderhit() {
let msg: Result<UciMessage, ParseUciMessageError> = "PonderHit \r\n".parse();
assert_eq!(msg, Ok(UciMessage::PonderHit));
}
#[test]
fn test_parse_position_startpos() {
let msg: Result<UciMessage, ParseUciMessageError> =
"position startpos moves e2e4 e7e5\r\n".parse();
let expected = UciMessage::Position {
startpos: true,
fen: None,
moves: vec!["e2e4".parse().unwrap(), "e7e5".parse().unwrap()],
};
assert_eq!(msg, Ok(expected));
}
#[test]
fn test_parse_position_startpos_as_fen() {
let msg: Result<UciMessage, ParseUciMessageError> =
"position fen rnbqkbnr/pppppppp/8/8/8/8/PPPPPPPP/RNBQKBNR w KQkq - 0 1 moves d2d4\r\n"
.parse();
let expected = UciMessage::Position {
startpos: false,
fen: Some(
Fen::from_ascii(b"rnbqkbnr/pppppppp/8/8/8/8/PPPPPPPP/RNBQKBNR w KQkq - 0 1").unwrap(),
),
moves: vec!["d2d4".parse().unwrap()],
};
assert_eq!(msg, Ok(expected));
}
#[test]
fn test_parse_position_endgame() {
let msg: Result<UciMessage, ParseUciMessageError> =
"position fen 2k5/6PR/8/8/2b4P/8/6K1/8 w - - 0 53 moves g7g8q c4g8\r\n".parse();
let expected = UciMessage::Position {
startpos: false,
fen: Some(Fen::from_ascii(b"2k5/6PR/8/8/2b4P/8/6K1/8 w - - 0 53").unwrap()),
moves: vec!["g7g8q".parse().unwrap(), "c4g8".parse().unwrap()],
};
assert_eq!(msg, Ok(expected));
}
#[test]
fn test_parse_position_incorrect_fen() {
"position fen 2k50/6PR/8/8/2b4P/8/6K1/8 w - - 0 53 moves g7g8q c4g8\r\n"
.parse::<UciMessage>()
.expect_err("Parse should fail.");
}
#[test]
fn test_parse_position_startpos_no_moves() {
let msg: Result<UciMessage, ParseUciMessageError> = "position startpos\r\n".parse();
let expected = UciMessage::Position {
startpos: true,
fen: None,
moves: vec![],
};
assert_eq!(msg, Ok(expected));
}
#[test]
fn test_parse_position_fen_no_moves() {
let msg: Result<UciMessage, ParseUciMessageError> =
"position fen 2k5/6PR/8/8/2b4P/8/6K1/8 w - - 0 53\r\n".parse();
let expected = UciMessage::Position {
startpos: false,
fen: Some(Fen::from_ascii(b"2k5/6PR/8/8/2b4P/8/6K1/8 w - - 0 53").unwrap()),
moves: vec![],
};
assert_eq!(msg, Ok(expected));
}
#[test]
fn test_parse_go() {
let msg: Result<UciMessage, ParseUciMessageError> = "go".parse();
assert_eq!(msg, Ok(UciMessage::go()));
}
#[test]
fn test_parse_go_ponder() {
let msg: Result<UciMessage, ParseUciMessageError> = "go ponder\n".parse();
assert_eq!(msg, Ok(UciMessage::go_ponder()));
}
#[test]
fn test_parse_go_infinite() {
let msg: Result<UciMessage, ParseUciMessageError> = "go infinite\n".parse();
assert_eq!(msg, Ok(UciMessage::go_infinite()));
}
#[test]
fn test_parse_go_movetime() {
let msg: Result<UciMessage, ParseUciMessageError> = "go movetime 55055\n".parse();
assert_eq!(
msg,
Ok(UciMessage::go_movetime(Duration::from_millis(55055)))
);
}
#[test]
fn test_parse_go_timeleft() {
let msg: Result<UciMessage, ParseUciMessageError> =
"go wtime 903000 btime 770908 winc 15000 movestogo 17 binc 10000\n".parse();
let expected = UciMessage::Go {
search_control: None,
time_control: Some(UciTimeControl::TimeLeft {
white_time: Some(Duration::from_millis(903000)),
black_time: Some(Duration::from_millis(770908)),
white_increment: Some(Duration::from_millis(15000)),
black_increment: Some(Duration::from_millis(10000)),
moves_to_go: Some(17),
}),
};
assert_eq!(msg, Ok(expected));
}
#[test]
fn test_parse_search_control_depth() {
let msg: Result<UciMessage, ParseUciMessageError> = "go ponder depth 6\n".parse();
let expected = UciMessage::Go {
time_control: Some(UciTimeControl::Ponder),
search_control: Some(UciSearchControl::depth(6)),
};
assert_eq!(msg, Ok(expected));
}
#[test]
fn test_parse_search_control_mate() {
let msg: Result<UciMessage, ParseUciMessageError> = "go mate 12\n".parse();
let expected = UciMessage::Go {
time_control: None,
search_control: Some(UciSearchControl::mate(12)),
};
assert_eq!(msg, Ok(expected));
}
#[test]
fn test_parse_nodes_searchmoves() {
let msg: Result<UciMessage, ParseUciMessageError> =
"go nodes 79093455456 searchmoves e2e4 d2d4 g2g1n\n".parse();
let expected = UciMessage::Go {
time_control: None,
search_control: Some(UciSearchControl {
depth: None,
nodes: Some(79093455456),
mate: None,
search_moves: vec![
"e2e4".parse().unwrap(),
"d2d4".parse().unwrap(),
"g2g1n".parse().unwrap(),
],
}),
};
assert_eq!(msg, Ok(expected));
}
#[test]
fn test_parse_go_full_example() {
let msg: Result<UciMessage, ParseUciMessageError> =
"go movetime 10000 searchmoves a1h8 depth 6 nodes 55000000\n".parse();
let expected = UciMessage::Go {
time_control: Some(UciTimeControl::MoveTime(Duration::from_millis(10000))),
search_control: Some(UciSearchControl {
depth: Some(6),
nodes: Some(55000000),
mate: None,
search_moves: vec!["a1h8".parse().unwrap()],
}),
};
assert_eq!(msg, Ok(expected));
}
#[test]
fn test_parse_id_name() {
let msg: Result<UciMessage, ParseUciMessageError> = "id name Vampirc 1.0\n".parse();
let expected = UciMessage::Id {
name: Some(String::from("Vampirc 1.0")),
author: None,
};
assert_eq!(msg, Ok(expected));
}
#[test]
fn test_parse_id_author() {
let msg: Result<UciMessage, ParseUciMessageError> = "id author Matija Kejžar\n".parse();
let expected = UciMessage::Id {
author: Some(String::from("Matija Kejžar")),
name: None,
};
assert_eq!(msg, Ok(expected));
}
#[test]
fn test_parse_uciok() {
let msg: Result<UciMessage, ParseUciMessageError> = "uciok \r\n".parse();
assert_eq!(msg, Ok(UciMessage::UciOk));
}
#[test]
fn test_parse_readyok() {
let msg: Result<UciMessage, ParseUciMessageError> = "readyok\n".parse();
assert_eq!(msg, Ok(UciMessage::ReadyOk));
}
#[test]
fn test_parse_bestmove() {
let msg: Result<UciMessage, ParseUciMessageError> = "bestmove g1f3\n".parse();
let expected = UciMessage::BestMove {
best_move: "g1f3".parse().unwrap(),
ponder: None,
};
assert_eq!(msg, Ok(expected));
}
#[test]
fn test_parse_bestmove_with_ponder() {
let msg: Result<UciMessage, ParseUciMessageError> = "bestmove g1f3 ponder d8f6\n".parse();
let expected = UciMessage::BestMove {
best_move: "g1f3".parse().unwrap(),
ponder: Some("d8f6".parse().unwrap()),
};
assert_eq!(msg, Ok(expected));
}
#[test]
fn test_parse_copyprotection_checking() {
let msg: Result<UciMessage, ParseUciMessageError> = "copyprotection checking".parse();
assert_eq!(
msg,
Ok(UciMessage::CopyProtection(ProtectionState::Checking))
);
}
#[test]
fn test_parse_copyprotection_ok() {
let msg: Result<UciMessage, ParseUciMessageError> = "copyprotection ok".parse();
assert_eq!(msg, Ok(UciMessage::CopyProtection(ProtectionState::Ok)));
}
#[test]
fn test_parse_copyprotection_error() {
let msg: Result<UciMessage, ParseUciMessageError> = "copyprotection error".parse();
assert_eq!(msg, Ok(UciMessage::CopyProtection(ProtectionState::Error)));
}
#[test]
fn test_parse_registration_checking() {
let msg: Result<UciMessage, ParseUciMessageError> = "registration checking".parse();
assert_eq!(msg, Ok(UciMessage::Registration(ProtectionState::Checking)));
}
#[test]
fn test_parse_registration_ok() {
let msg: Result<UciMessage, ParseUciMessageError> = "registration ok".parse();
assert_eq!(msg, Ok(UciMessage::Registration(ProtectionState::Ok)));
}
#[test]
fn test_parse_registration_error() {
let msg: Result<UciMessage, ParseUciMessageError> = "registration error".parse();
assert_eq!(msg, Ok(UciMessage::Registration(ProtectionState::Error)));
}
#[test]
fn test_parse_option_check() {
let msg: Result<UciMessage, ParseUciMessageError> =
"option name Nullmove type check default true\n".parse();
let expected = UciMessage::Option(UciOptionConfig::Check {
name: String::from("Nullmove"),
default: Some(true),
});
assert_eq!(msg, Ok(expected));
}
#[test]
fn test_parse_option_check_no_default() {
let msg: Result<UciMessage, ParseUciMessageError> =
"option name A long option name type check \n".parse();
let expected = UciMessage::Option(UciOptionConfig::Check {
name: String::from("A long option name"),
default: None,
});
assert_eq!(msg, Ok(expected));
}
#[test]
fn test_parse_option_spin() {
let msg: Result<UciMessage, ParseUciMessageError> =
"option name Selectivity type spin default 2 min 0 max 4\n\n".parse();
let expected = UciMessage::Option(UciOptionConfig::Spin {
name: String::from("Selectivity"),
default: Some(2),
min: Some(0),
max: Some(4),
});
assert_eq!(msg, Ok(expected));
}
#[test]
fn test_parse_option_spin_no_default() {
let msg: Result<UciMessage, ParseUciMessageError> =
"option name A spin option without a default type spin min -5676 max -33\n".parse();
let expected = UciMessage::Option(UciOptionConfig::Spin {
name: String::from("A spin option without a default"),
default: None,
min: Some(-5676),
max: Some(-33),
});
assert_eq!(msg, Ok(expected));
}
#[test]
fn test_parse_option_spin_just_min() {
let msg: Result<UciMessage, ParseUciMessageError> =
"option name JUST MIN type spin min -40964656\n".parse();
let expected = UciMessage::Option(UciOptionConfig::Spin {
name: String::from("JUST MIN"),
default: None,
min: Some(-40964656),
max: None,
});
assert_eq!(msg, Ok(expected));
}
#[test]
fn test_parse_option_spin_just_max() {
let msg: Result<UciMessage, ParseUciMessageError> =
"option name just_max type spin max 56565464509\n".parse();
let expected = UciMessage::Option(UciOptionConfig::Spin {
name: String::from("just_max"),
default: None,
max: Some(56565464509),
min: None,
});
assert_eq!(msg, Ok(expected));
}
#[test]
fn test_parse_option_spin_just_default_and_max() {
let msg: Result<UciMessage, ParseUciMessageError> =
"option name def max type spin default -5 max 55\n".parse();
let expected = UciMessage::Option(UciOptionConfig::Spin {
name: String::from("def max"),
default: Some(-5),
max: Some(55),
min: None,
});
assert_eq!(msg, Ok(expected));
}
#[test]
fn test_parse_option_combo() {
let msg: Result<UciMessage, ParseUciMessageError> =
"option name Style type combo default Normal var Solid var Normal var Risky\n".parse();
let expected = UciMessage::Option(UciOptionConfig::Combo {
name: String::from("Style"),
default: Some(String::from("Normal")),
var: vec![
String::from("Solid"),
String::from("Normal"),
String::from("Risky"),
],
});
assert_eq!(msg, Ok(expected));
}
#[test]
fn test_parse_option_combo_no_default() {
let msg: Result<UciMessage, ParseUciMessageError> =
"option name Some ccccc-combo type combo var A B C var D E F var 1 2 3\n".parse();
let expected = UciMessage::Option(UciOptionConfig::Combo {
name: String::from("Some ccccc-combo"),
default: None,
var: vec![
String::from("A B C"),
String::from("D E F"),
String::from("1 2 3"),
],
});
assert_eq!(msg, Ok(expected));
}
#[test]
fn test_parse_option_button() {
let msg: Result<UciMessage, ParseUciMessageError> =
"option name Clear Hash type button\n".parse();
let expected = UciMessage::Option(UciOptionConfig::Button {
name: String::from("Clear Hash"),
});
assert_eq!(msg, Ok(expected));
}
#[test]
fn test_parse_option_button_ignore_default() {
let msg: Result<UciMessage, ParseUciMessageError> =
"option name CH type button default Ignore min 5 max 6 var A var B\n".parse();
let expected = UciMessage::Option(UciOptionConfig::Button {
name: String::from("CH"),
});
assert_eq!(msg, Ok(expected));
}
#[test]
fn test_parse_option_string() {
let msg: Result<UciMessage, ParseUciMessageError> =
"option name Nalimov Path type string default c:\\\n".parse();
let expected = UciMessage::Option(UciOptionConfig::String {
name: String::from("Nalimov Path"),
default: Some(String::from("c:\\")),
});
assert_eq!(msg, Ok(expected));
}
#[test]
fn test_parse_option_string_no_default() {
let msg: Result<UciMessage, ParseUciMessageError> = "option name NP type string\r\n".parse();
let expected = UciMessage::Option(UciOptionConfig::String {
name: String::from("NP"),
default: None,
});
assert_eq!(msg, Ok(expected));
}
#[test]
fn test_parse_option_string_default_is_empty() {
let msg: Result<UciMessage, ParseUciMessageError> =
"option name Nalimov Path type string default <empty>\n".parse();
let expected = UciMessage::Option(UciOptionConfig::String {
name: String::from("Nalimov Path"),
default: Some(String::from("")),
});
assert_eq!(msg, Ok(expected));
}
#[test]
fn test_parse_option_string_empty_default() {
let msg: Result<UciMessage, ParseUciMessageError> =
"option name Debug Log File type string default".parse();
let expected = UciMessage::Option(UciOptionConfig::String {
name: "Debug Log File".to_string(),
default: Some("".to_string()),
});
assert_eq!(msg, Ok(expected));
}
#[test]
fn test_parse_info_depth() {
let msg: Result<UciMessage, ParseUciMessageError> = "info depth 23\n".parse();
let expected = UciMessage::Info(UciInfo {
depth: Some(23),
..Default::default()
});
assert_eq!(msg, Ok(expected));
}
#[test]
fn test_parse_info_seldepth() {
let msg: Result<UciMessage, ParseUciMessageError> = "info seldepth 9\n".parse();
let expected = UciMessage::Info(UciInfo {
sel_depth: Some(9),
..Default::default()
});
assert_eq!(msg, Ok(expected));
}
#[test]
fn test_parse_info_time() {
let msg: Result<UciMessage, ParseUciMessageError> = "info time 9002\n".parse();
let expected = UciMessage::Info(UciInfo {
time: Some(Duration::from_millis(9002)),
..Default::default()
});
assert_eq!(msg, Ok(expected));
}
#[test]
fn test_parse_info_nodes() {
let msg: Result<UciMessage, ParseUciMessageError> = "info nodes 56435234425\n".parse();
let expected = UciMessage::Info(UciInfo {
nodes: Some(56435234425),
..Default::default()
});
assert_eq!(msg, Ok(expected));
}
#[test]
fn test_parse_info_currmovenumber() {
let msg: Result<UciMessage, ParseUciMessageError> = "info currmovenumber 102\n".parse();
let expected = UciMessage::Info(UciInfo {
curr_move_num: Some(102),
..Default::default()
});
assert_eq!(msg, Ok(expected));
}
#[test]
fn test_parse_info_hashfull() {
let msg: Result<UciMessage, ParseUciMessageError> = "info hashfull 673\n".parse();
let expected = UciMessage::Info(UciInfo {
hash_full: Some(673),
..Default::default()
});
assert_eq!(msg, Ok(expected));
}
#[test]
fn test_parse_info_nps() {
let msg: Result<UciMessage, ParseUciMessageError> = "info nps 12003\n".parse();
let expected = UciMessage::Info(UciInfo {
nps: Some(12003),
..Default::default()
});
assert_eq!(msg, Ok(expected));
}
#[test]
fn test_parse_info_tbhits() {
let msg: Result<UciMessage, ParseUciMessageError> = "info tbhits 5305\n".parse();
let expected = UciMessage::Info(UciInfo {
tb_hits: Some(5305),
..Default::default()
});
assert_eq!(msg, Ok(expected));
}
#[test]
fn test_parse_info_sbhits() {
let msg: Result<UciMessage, ParseUciMessageError> = "info sbhits 0\n".parse();
let expected = UciMessage::Info(UciInfo {
sb_hits: Some(0),
..Default::default()
});
assert_eq!(msg, Ok(expected));
}
#[test]
fn test_parse_info_cpuload() {
let msg: Result<UciMessage, ParseUciMessageError> = "info cpuload 773\n".parse();
let expected = UciMessage::Info(UciInfo {
cpu_load: Some(773),
..Default::default()
});
assert_eq!(msg, Ok(expected));
}
#[test]
fn test_parse_info_multipv() {
let msg: Result<UciMessage, ParseUciMessageError> = "info multipv 2\n".parse();
let expected = UciMessage::Info(UciInfo {
multi_pv: Some(2),
..Default::default()
});
assert_eq!(msg, Ok(expected));
}
#[test]
fn test_parse_info_string() {
let msg: Result<UciMessage, ParseUciMessageError> =
"info string I am the Walrus! Cuckoo cachoo.\n".parse();
let expected = UciMessage::Info(UciInfo {
string: Some(String::from("I am the Walrus! Cuckoo cachoo.")),
..Default::default()
});
assert_eq!(msg, Ok(expected));
}
#[test]
fn test_parse_info_currmove() {
let msg: Result<UciMessage, ParseUciMessageError> = "info currmove a7a8q\n".parse();
let expected = UciMessage::Info(UciInfo {
curr_move: Some("a7a8q".parse().unwrap()),
..Default::default()
});
assert_eq!(msg, Ok(expected));
}
#[test]
fn test_parse_info_pv() {
let msg: Result<UciMessage, ParseUciMessageError> = "info pv e2e4 e7e5 g1f3\n".parse();
let expected = UciMessage::Info(UciInfo {
pv: vec![
"e2e4".parse().unwrap(),
"e7e5".parse().unwrap(),
"g1f3".parse().unwrap(),
],
..Default::default()
});
assert_eq!(msg, Ok(expected));
}
#[test]
fn test_parse_info_refutation() {
let msg: Result<UciMessage, ParseUciMessageError> = "info refutation d1h5 g6h5\n".parse();
let expected = UciMessage::Info(UciInfo {
refutation: vec!["d1h5".parse().unwrap(), "g6h5".parse().unwrap()],
..Default::default()
});
assert_eq!(msg, Ok(expected));
}
#[test]
fn test_parse_info_currline_no_cpu_nr() {
let msg: Result<UciMessage, ParseUciMessageError> = "info currline d1h5 g6h5\n".parse();
let expected = UciMessage::Info(UciInfo {
curr_line: vec![UciInfoCurrLine {
cpu_nr: None,
moves: vec!["d1h5".parse().unwrap(), "g6h5".parse().unwrap()],
}],
..Default::default()
});
assert_eq!(msg, Ok(expected));
}
#[test]
fn test_parse_info_currline_with_cpu_nr() {
let msg: Result<UciMessage, ParseUciMessageError> = "info currline 1 d1h5 g6h5\n".parse();
let expected = UciMessage::Info(UciInfo {
curr_line: vec![UciInfoCurrLine {
cpu_nr: Some(1),
moves: vec!["d1h5".parse().unwrap(), "g6h5".parse().unwrap()],
}],
..Default::default()
});
assert_eq!(msg, Ok(expected));
}
#[test]
fn test_parse_info_currline_multi_cpu_nr() {
let msg: Result<UciMessage, ParseUciMessageError> =
"info currline 1 d1h5 g6h5 currline 2 e2e4 currline 3 d2d4 d7d5\n".parse();
let expected = UciMessage::Info(UciInfo {
curr_line: vec![
UciInfoCurrLine {
cpu_nr: Some(1),
moves: vec!["d1h5".parse().unwrap(), "g6h5".parse().unwrap()],
},
UciInfoCurrLine {
cpu_nr: Some(2),
moves: vec!["e2e4".parse().unwrap()],
},
UciInfoCurrLine {
cpu_nr: Some(3),
moves: vec!["d2d4".parse().unwrap(), "d7d5".parse().unwrap()],
},
],
..Default::default()
});
assert_eq!(msg, Ok(expected));
}
#[test]
fn test_parse_info_score_cp() {
let msg: Result<UciMessage, ParseUciMessageError> = "info score cp 20\n".parse();
let expected = UciMessage::Info(UciInfo {
score: Some(UciInfoScore {
cp: Some(20),
..Default::default()
}),
..Default::default()
});
assert_eq!(msg, Ok(expected));
}
#[test]
fn test_parse_info_score_mate() {
let msg: Result<UciMessage, ParseUciMessageError> = "info score mate -3\n".parse();
let expected = UciMessage::Info(UciInfo {
score: Some(UciInfoScore {
mate: Some(-3),
..Default::default()
}),
..Default::default()
});
assert_eq!(msg, Ok(expected));
}
#[test]
fn test_parse_info_score_cp_lowerbound() {
let msg: Result<UciMessage, ParseUciMessageError> = "info score cp -75 lowerbound\n".parse();
let expected = UciMessage::Info(UciInfo {
score: Some(UciInfoScore {
cp: Some(-75),
mate: None,
lower_bound: true,
upper_bound: false,
}),
..Default::default()
});
assert_eq!(msg, Ok(expected));
}
#[test]
fn test_parse_info_score_cp_upperbound() {
let msg: Result<UciMessage, ParseUciMessageError> = "info score cp 404 upperbound\n".parse();
let expected = UciMessage::Info(UciInfo {
score: Some(UciInfoScore {
cp: Some(404),
mate: None,
upper_bound: true,
lower_bound: false,
}),
..Default::default()
});
assert_eq!(msg, Ok(expected));
}
#[test]
fn test_parse_info_multi1() {
let msg: Result<UciMessage, ParseUciMessageError> =
"info score cp 13 depth 1 nodes 13 time 15 pv f1b5\n".parse();
let expected = UciMessage::Info(UciInfo {
score: Some(UciInfoScore {
cp: Some(13),
..Default::default()
}),
depth: Some(1),
nodes: Some(13),
time: Some(Duration::from_millis(15)),
pv: vec!["f1b5".parse().unwrap()],
..Default::default()
});
assert_eq!(msg, Ok(expected));
}
#[test]
fn test_parse_info_multi2() {
let msg: Result<UciMessage, ParseUciMessageError> = "info depth 2 seldepth 2\n".parse();
let expected = UciMessage::Info(UciInfo {
depth: Some(2),
sel_depth: Some(2),
..Default::default()
});
assert_eq!(msg, Ok(expected));
}
#[test]
fn test_parse_info_multi3() {
let msg: Result<UciMessage, ParseUciMessageError> =
"info score cp 20 depth 3 nodes 423 time 15 pv f1c4 g8f6 b1c3 \n".parse();
let expected = UciMessage::Info(UciInfo {
score: Some(UciInfoScore {
cp: Some(20),
..Default::default()
}),
depth: Some(3),
nodes: Some(423),
time: Some(Duration::from_millis(15)),
pv: vec![
"f1c4".parse().unwrap(),
"g8f6".parse().unwrap(),
"b1c3".parse().unwrap(),
],
..Default::default()
});
assert_eq!(msg, Ok(expected));
}
#[test]
fn test_parse_empty() {
"".parse::<UciMessage>().expect_err("should not parse");
}
#[test]
fn test_parse_nl() {
"\n".parse::<UciMessage>().expect_err("should not parse");
}