use tokio::task; use crate::args::Args; use crate::consts::MIN_STRIKE_TIMEOUT; use crate::data::{BoatsLayout, GameRules}; use crate::human_player_ws::ServerMessage; use crate::server::start_server; use crate::test::bot_client; use crate::test::bot_client::ClientEndResult; use crate::test::play_utils::check_no_replay_on_hit; use crate::test::TestPort; use crate::utils::network_utils::wait_for_port; #[tokio::test] async fn invalid_port() { let _ = env_logger::builder().is_test(true).try_init(); bot_client::BotClient::new(TestPort::RandomBotClientInvalidPort.as_url()) .run_client() .await .unwrap_err(); } #[tokio::test] async fn invalid_rules() { let _ = env_logger::builder().is_test(true).try_init(); let local_set = task::LocalSet::new(); local_set .run_until(async move { let mut rules = GameRules::random_players_rules(); rules.map_width = 0; task::spawn_local(start_server(Args::for_test( TestPort::RandomBotClientInvalidRules, ))); wait_for_port(TestPort::RandomBotClientInvalidRules.port()).await; bot_client::BotClient::new(TestPort::RandomBotClientInvalidRules.as_url()) .with_rules(rules.clone()) .with_layout( BoatsLayout::gen_random_for_rules(&GameRules::random_players_rules()).unwrap(), ) .run_client() .await .unwrap_err(); }) .await; } #[tokio::test] async fn full_game() { let _ = env_logger::builder().is_test(true).try_init(); let local_set = task::LocalSet::new(); local_set .run_until(async move { task::spawn_local(start_server(Args::for_test(TestPort::RandomBotFullGame))); wait_for_port(TestPort::RandomBotFullGame.port()).await; let res = bot_client::BotClient::new(TestPort::RandomBotFullGame.as_url()) .run_client() .await .unwrap(); assert!(matches!(res, ClientEndResult::Finished { .. })); }) .await; } #[tokio::test] async fn full_game_no_touching_boats() { let _ = env_logger::builder().is_test(true).try_init(); let local_set = task::LocalSet::new(); local_set .run_until(async move { let mut rules = GameRules::random_players_rules(); rules.boats_can_touch = false; task::spawn_local(start_server(Args::for_test( TestPort::RandomBotFullGameNoTouchingBoats, ))); wait_for_port(TestPort::RandomBotFullGameNoTouchingBoats.port()).await; let res = bot_client::BotClient::new(TestPort::RandomBotFullGameNoTouchingBoats.as_url()) .with_rules(rules) .run_client() .await .unwrap(); assert!(matches!(res, ClientEndResult::Finished { .. })); }) .await; } #[tokio::test] async fn invalid_boats_layout_number_of_boats() { let _ = env_logger::builder().is_test(true).try_init(); let local_set = task::LocalSet::new(); local_set .run_until(async move { let mut rules = GameRules::random_players_rules(); rules.boats_can_touch = false; task::spawn_local(start_server(Args::for_test( TestPort::RandomBotInvalidBoatsLayoutNumberOfBoats, ))); wait_for_port(TestPort::RandomBotInvalidBoatsLayoutNumberOfBoats.port()).await; let mut rules_modified = rules.clone(); rules_modified.remove_last_boat(); let layout = BoatsLayout::gen_random_for_rules(&rules_modified).unwrap(); let res = bot_client::BotClient::new( &TestPort::RandomBotInvalidBoatsLayoutNumberOfBoats.as_url(), ) .with_rules(rules) .with_layout(layout) .run_client() .await .unwrap(); assert_eq!(res, ClientEndResult::InvalidBoatsLayout); }) .await; } #[tokio::test] async fn invalid_boats_layout_len_of_a_boat() { let _ = env_logger::builder().is_test(true).try_init(); let local_set = task::LocalSet::new(); local_set .run_until(async move { let mut rules = GameRules::random_players_rules(); rules.boats_can_touch = false; task::spawn_local(start_server(Args::for_test( TestPort::RandomBotInvalidBoatsLayoutLenOfABoat, ))); wait_for_port(TestPort::RandomBotInvalidBoatsLayoutLenOfABoat.port()).await; let mut rules_modified = rules.clone(); let previous = rules_modified.remove_last_boat(); rules_modified.add_boat(previous - 1); let layout = BoatsLayout::gen_random_for_rules(&rules_modified).unwrap(); let res = bot_client::BotClient::new( &TestPort::RandomBotInvalidBoatsLayoutLenOfABoat.as_url(), ) .with_rules(rules) .with_layout(layout) .run_client() .await .unwrap(); assert_eq!(res, ClientEndResult::InvalidBoatsLayout); }) .await; } #[tokio::test] async fn full_game_multiple_rematches() { let _ = env_logger::builder().is_test(true).try_init(); let local_set = task::LocalSet::new(); local_set .run_until(async move { task::spawn_local(start_server(Args::for_test( TestPort::RandomBotFullGameMultipleRematch, ))); wait_for_port(TestPort::RandomBotFullGameMultipleRematch.port()).await; let res = bot_client::BotClient::new(TestPort::RandomBotFullGameMultipleRematch.as_url()) .with_number_plays(5) .run_client() .await .unwrap(); assert!(matches!(res, ClientEndResult::Finished { .. })); }) .await; } #[tokio::test] async fn full_game_no_replay_on_hit() { let _ = env_logger::builder().is_test(true).try_init(); let local_set = task::LocalSet::new(); local_set .run_until(async move { task::spawn_local(start_server(Args::for_test( TestPort::RandomBotNoReplayOnHit, ))); wait_for_port(TestPort::RandomBotNoReplayOnHit.port()).await; let res = bot_client::BotClient::new(TestPort::RandomBotNoReplayOnHit.as_url()) .with_rules(GameRules::random_players_rules().with_player_continue_on_hit(false)) .with_server_msg_callback(check_no_replay_on_hit) .run_client() .await .unwrap(); assert!(matches!(res, ClientEndResult::Finished { .. })); }) .await; } #[tokio::test] async fn check_fire_time_out() { let _ = env_logger::builder().is_test(true).try_init(); let local_set = task::LocalSet::new(); local_set .run_until(async move { task::spawn_local(start_server(Args::for_test(TestPort::RandomCheckTimeout))); wait_for_port(TestPort::RandomCheckTimeout.port()).await; let mut did_skip_one = false; let res = bot_client::BotClient::new(TestPort::RandomCheckTimeout.as_url()) .with_rules( GameRules::random_players_rules().with_strike_timeout(MIN_STRIKE_TIMEOUT), ) .with_server_msg_callback(move |msg| { if matches!(msg, ServerMessage::RequestFire { .. }) && !did_skip_one { *msg = ServerMessage::OpponentReplacedByBot; did_skip_one = true; } }) .run_client() .await .unwrap(); assert!(matches!(res, ClientEndResult::Finished { .. })); }) .await; }