diff --git a/sea_battle_backend/src/bot_client.rs b/sea_battle_backend/src/bot_client.rs index c9e4411..bf62244 100644 --- a/sea_battle_backend/src/bot_client.rs +++ b/sea_battle_backend/src/bot_client.rs @@ -9,7 +9,7 @@ use crate::human_player_ws::{ClientMessage, ServerMessage}; #[derive(Debug, Eq, PartialEq)] pub enum ClientEndResult { Finished, - InvalidLayout, + InvalidBoatsLayout, } pub async fn run_client( @@ -117,7 +117,7 @@ pub async fn run_client( } ServerMessage::RejectedBoatsLayout { errors } => { log::warn!("Rejected boat layout: {:?}", errors); - return Ok(ClientEndResult::InvalidLayout); + return Ok(ClientEndResult::InvalidBoatsLayout); } } } diff --git a/sea_battle_backend/src/data/boats_layout.rs b/sea_battle_backend/src/data/boats_layout.rs index d94030a..a2b20aa 100644 --- a/sea_battle_backend/src/data/boats_layout.rs +++ b/sea_battle_backend/src/data/boats_layout.rs @@ -216,7 +216,8 @@ impl BoatsLayout { true } - pub fn errors(&self, rules: &GameRules) -> Vec<&str> { + /// Check if this boats layout is valid or not + pub fn errors(&self, rules: &GameRules) -> Vec<&'static str> { let mut errors = vec![]; // Check the number of boats @@ -272,12 +273,6 @@ impl BoatsLayout { pub fn number_of_boats(&self) -> usize { self.0.len() } - - /// Check for layout invalid configuration - pub fn layouts_errors(&self, _rules: &GameRules) -> Vec<&'static str> { - //TODO : implement - vec![] - } } #[cfg(test)] diff --git a/sea_battle_backend/src/data/game_rules.rs b/sea_battle_backend/src/data/game_rules.rs index 4edbac9..6f4a118 100644 --- a/sea_battle_backend/src/data/game_rules.rs +++ b/sea_battle_backend/src/data/game_rules.rs @@ -44,6 +44,21 @@ impl GameRules { .collect() } + /// Remove last boat + pub fn pop_boat(&mut self) -> usize { + let list = self.boats_list(); + self.set_boats_list(&list[0..list.len() - 1]); + *list.last().unwrap() + } + + /// Add a boat to the list of boats + pub fn add_boat(&mut self, len: usize) { + let mut list = self.boats_list(); + list.push(len); + self.set_boats_list(&list[0..list.len() - 1]); + } + + /// Check game rules errors pub fn get_errors(&self) -> Vec<&str> { let config = PlayConfiguration::default(); diff --git a/sea_battle_backend/src/game.rs b/sea_battle_backend/src/game.rs index b4015ab..189dfaf 100644 --- a/sea_battle_backend/src/game.rs +++ b/sea_battle_backend/src/game.rs @@ -208,9 +208,9 @@ impl Handler for Game { let player_index = self.player_id_by_uuid(msg.0); - let errors = msg.1.layouts_errors(&self.rules); + let errors = msg.1.errors(&self.rules); if !errors.is_empty() { - log::error!("Got invalid boats layou!"); + log::error!("Got invalid boats layout!"); self.players[player_index].rejected_boats_layout(errors); self.players[player_index].query_boats_layout(&self.rules); return; diff --git a/sea_battle_backend/src/test/client.rs b/sea_battle_backend/src/test/client.rs index 0489914..07273d0 100644 --- a/sea_battle_backend/src/test/client.rs +++ b/sea_battle_backend/src/test/client.rs @@ -95,3 +95,60 @@ async fn full_game_no_touching_boats() { }) .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::FullGameTouchingBoats, + ))); + wait_for_port(TestPort::FullGameTouchingBoats.port()).await; + + let mut rules_modified = rules.clone(); + rules_modified.pop_boat(); + let layout = BoatsLayout::gen_random_for_rules(&rules_modified).unwrap(); + + let res = + bot_client::run_client(&TestPort::FullGameTouchingBoats.as_url(), &rules, layout) + .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::FullGameTouchingBoats, + ))); + wait_for_port(TestPort::FullGameTouchingBoats.port()).await; + + let mut rules_modified = rules.clone(); + let previous = rules_modified.pop_boat(); + rules_modified.add_boat(previous - 1); + let layout = BoatsLayout::gen_random_for_rules(&rules_modified).unwrap(); + + let res = + bot_client::run_client(&TestPort::FullGameTouchingBoats.as_url(), &rules, layout) + .await + .unwrap(); + + assert_eq!(res, ClientEndResult::InvalidBoatsLayout); + }) + .await; +}