use tokio::task; use crate::args::Args; use crate::data::{BotType, CurrentGameStatus, GameRules}; use crate::human_player_ws::ServerMessage; use crate::server::start_server; use crate::test::bot_client::ClientEndResult; use crate::test::network_utils::wait_for_port; use crate::test::{bot_client, TestPort}; #[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::IntermediateBotFullGame, ))); wait_for_port(TestPort::IntermediateBotFullGame.port()).await; let mut curr_status = CurrentGameStatus::default(); let res = bot_client::BotClient::new(TestPort::IntermediateBotFullGame.as_url()) .with_rules(GameRules::random_players_rules().with_bot_type(BotType::Smart)) .with_server_msg_callback(move |msg| match msg { ServerMessage::OpponentMustFire { status } => { curr_status = status.clone(); } ServerMessage::OpponentFireResult { pos, .. } => { let pending_sunk_loc = curr_status.your_map.get_successful_but_un_sunk_locations(); if !pending_sunk_loc.is_empty() { log::debug!("Check if fire was smart..."); assert!(pending_sunk_loc.iter().any(|l| pos.dist_with(l) <= 1)) } } _ => {} }) .run_client() .await .unwrap(); assert!(matches!(res, ClientEndResult::Finished { .. })); }) .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::IntermediateBotFullGame, ))); wait_for_port(TestPort::IntermediateBotFullGame.port()).await; let mut curr_status = CurrentGameStatus::default(); let res = bot_client::BotClient::new(TestPort::IntermediateBotFullGame.as_url()) .with_rules(GameRules::random_players_rules().with_bot_type(BotType::Smart)) .with_server_msg_callback(move |msg| match msg { ServerMessage::OpponentMustFire { status } => { curr_status = status.clone(); } ServerMessage::OpponentFireResult { pos, .. } => { let pending_sunk_loc = curr_status.your_map.get_successful_but_un_sunk_locations(); if !pending_sunk_loc.is_empty() { log::debug!("Check if fire was smart..."); assert!(pending_sunk_loc.iter().any(|l| pos.dist_with(l) <= 1)) } } _ => {} }) .with_number_plays(20) .run_client() .await .unwrap(); if let ClientEndResult::Finished { number_defeats, .. } = res { assert!( number_defeats > 15, "number of defeats = {} which is < 15", number_defeats ) } else { assert_eq!(0, 1, "Client did not finish correctly"); } }) .await; }