rust/hedgewars-server/src/protocol/test.rs
changeset 14415 06672690d71b
parent 13805 0463a4221327
child 14457 98ef2913ec73
equal deleted inserted replaced
14414:6843c4551cde 14415:06672690d71b
       
     1 use proptest::{
       
     2     test_runner::{TestRunner, Reason},
       
     3     arbitrary::{any, any_with, Arbitrary, StrategyFor},
       
     4     strategy::{Strategy, BoxedStrategy, Just, Map}
       
     5 };
       
     6 
       
     7 use crate::server::coretypes::{GameCfg, TeamInfo, HedgehogInfo};
       
     8 
       
     9 use super::messages::{
       
    10     HWProtocolMessage, HWProtocolMessage::*
       
    11 };
       
    12 
       
    13 // Due to inability to define From between Options
       
    14 trait Into2<T>: Sized { fn into2(self) -> T; }
       
    15 impl <T> Into2<T> for T { fn into2(self) -> T { self } }
       
    16 impl Into2<Vec<String>> for Vec<Ascii> {
       
    17     fn into2(self) -> Vec<String> {
       
    18         self.into_iter().map(|x| x.0).collect()
       
    19     }
       
    20 }
       
    21 impl Into2<String> for Ascii { fn into2(self) -> String { self.0 } }
       
    22 impl Into2<Option<String>> for Option<Ascii>{
       
    23     fn into2(self) -> Option<String> { self.map(|x| {x.0}) }
       
    24 }
       
    25 
       
    26 macro_rules! proto_msg_case {
       
    27     ($val: ident()) =>
       
    28         (Just($val));
       
    29     ($val: ident($arg: ty)) =>
       
    30         (any::<$arg>().prop_map(|v| {$val(v.into2())}));
       
    31     ($val: ident($arg1: ty, $arg2: ty)) =>
       
    32         (any::<($arg1, $arg2)>().prop_map(|v| {$val(v.0.into2(), v.1.into2())}));
       
    33     ($val: ident($arg1: ty, $arg2: ty, $arg3: ty)) =>
       
    34         (any::<($arg1, $arg2, $arg3)>().prop_map(|v| {$val(v.0.into2(), v.1.into2(), v.2.into2())}));
       
    35 }
       
    36 
       
    37 macro_rules! proto_msg_match {
       
    38     ($var: expr, def = $default: expr, $($num: expr => $constr: ident $res: tt),*) => (
       
    39         match $var {
       
    40             $($num => (proto_msg_case!($constr $res)).boxed()),*,
       
    41             _ => Just($default).boxed()
       
    42         }
       
    43     )
       
    44 }
       
    45 
       
    46 /// Wrapper type for generating non-empty strings
       
    47 #[derive(Debug)]
       
    48 struct Ascii(String);
       
    49 
       
    50 impl Arbitrary for Ascii {
       
    51     type Parameters = <String as Arbitrary>::Parameters;
       
    52 
       
    53     fn arbitrary_with(_args: Self::Parameters) -> Self::Strategy {
       
    54         "[a-zA-Z0-9]+".prop_map(Ascii).boxed()
       
    55     }
       
    56 
       
    57     type Strategy = BoxedStrategy<Ascii>;
       
    58 }
       
    59 
       
    60 impl Arbitrary for GameCfg {
       
    61     type Parameters = ();
       
    62 
       
    63     fn arbitrary_with(_args: <Self as Arbitrary>::Parameters) -> <Self as Arbitrary>::Strategy {
       
    64         use crate::server::coretypes::GameCfg::*;
       
    65         (0..10).no_shrink().prop_flat_map(|i| {
       
    66             proto_msg_match!(i, def = FeatureSize(0),
       
    67             0 => FeatureSize(u32),
       
    68             1 => MapType(Ascii),
       
    69             2 => MapGenerator(u32),
       
    70             3 => MazeSize(u32),
       
    71             4 => Seed(Ascii),
       
    72             5 => Template(u32),
       
    73             6 => Ammo(Ascii, Option<Ascii>),
       
    74             7 => Scheme(Ascii, Vec<Ascii>),
       
    75             8 => Script(Ascii),
       
    76             9 => Theme(Ascii),
       
    77             10 => DrawnMap(Ascii))
       
    78         }).boxed()
       
    79     }
       
    80 
       
    81     type Strategy = BoxedStrategy<GameCfg>;
       
    82 }
       
    83 
       
    84 impl Arbitrary for TeamInfo {
       
    85     type Parameters = ();
       
    86 
       
    87     fn arbitrary_with(_args: <Self as Arbitrary>::Parameters) -> <Self as Arbitrary>::Strategy {
       
    88         ("[a-z]+", 0u8..127u8, "[a-z]+", "[a-z]+", "[a-z]+", "[a-z]+",  0u8..127u8)
       
    89             .prop_map(|(name, color, grave, fort, voice_pack, flag, difficulty)| {
       
    90                 fn hog(n: u8) -> HedgehogInfo {
       
    91                     HedgehogInfo { name: format!("hog{}", n), hat: format!("hat{}", n)}
       
    92                 }
       
    93                 let hedgehogs = [hog(1), hog(2), hog(3), hog(4), hog(5), hog(6), hog(7), hog(8)];
       
    94                 TeamInfo {
       
    95                     name, color, grave, fort,
       
    96                     voice_pack, flag,difficulty,
       
    97                     hedgehogs, hedgehogs_number: 0
       
    98                 }
       
    99             }).boxed()
       
   100     }
       
   101 
       
   102     type Strategy = BoxedStrategy<TeamInfo>;
       
   103 }
       
   104 
       
   105 pub fn gen_proto_msg() -> BoxedStrategy<HWProtocolMessage> where {
       
   106     let res = (0..58).no_shrink().prop_flat_map(|i| {
       
   107         proto_msg_match!(i, def = Malformed,
       
   108         0 => Ping(),
       
   109         1 => Pong(),
       
   110         2 => Quit(Option<Ascii>),
       
   111         //3 => Cmd
       
   112         4 => Global(Ascii),
       
   113         5 => Watch(Ascii),
       
   114         6 => ToggleServerRegisteredOnly(),
       
   115         7 => SuperPower(),
       
   116         8 => Info(Ascii),
       
   117         9 => Nick(Ascii),
       
   118         10 => Proto(u16),
       
   119         11 => Password(Ascii, Ascii),
       
   120         12 => Checker(u16, Ascii, Ascii),
       
   121         13 => List(),
       
   122         14 => Chat(Ascii),
       
   123         15 => CreateRoom(Ascii, Option<Ascii>),
       
   124         16 => JoinRoom(Ascii, Option<Ascii>),
       
   125         17 => Follow(Ascii),
       
   126         18 => Rnd(Vec<Ascii>),
       
   127         19 => Kick(Ascii),
       
   128         20 => Ban(Ascii, Ascii, u32),
       
   129         21 => BanIP(Ascii, Ascii, u32),
       
   130         22 => BanNick(Ascii, Ascii, u32),
       
   131         23 => BanList(),
       
   132         24 => Unban(Ascii),
       
   133         //25 => SetServerVar(ServerVar),
       
   134         26 => GetServerVar(),
       
   135         27 => RestartServer(),
       
   136         28 => Stats(),
       
   137         29 => Part(Option<Ascii>),
       
   138         30 => Cfg(GameCfg),
       
   139         31 => AddTeam(Box<TeamInfo>),
       
   140         32 => RemoveTeam(Ascii),
       
   141         33 => SetHedgehogsNumber(Ascii, u8),
       
   142         34 => SetTeamColor(Ascii, u8),
       
   143         35 => ToggleReady(),
       
   144         36 => StartGame(),
       
   145         37 => EngineMessage(Ascii),
       
   146         38 => RoundFinished(),
       
   147         39 => ToggleRestrictJoin(),
       
   148         40 => ToggleRestrictTeams(),
       
   149         41 => ToggleRegisteredOnly(),
       
   150         42 => RoomName(Ascii),
       
   151         43 => Delegate(Ascii),
       
   152         44 => TeamChat(Ascii),
       
   153         45 => MaxTeams(u8),
       
   154         46 => Fix(),
       
   155         47 => Unfix(),
       
   156         48 => Greeting(Ascii),
       
   157         //49 => CallVote(Option<(String, Option<String>)>),
       
   158         50 => Vote(bool),
       
   159         51 => ForceVote(bool),
       
   160         52 => Save(Ascii, Ascii),
       
   161         53 => Delete(Ascii),
       
   162         54 => SaveRoom(Ascii),
       
   163         55 => LoadRoom(Ascii),
       
   164         56 => Malformed(),
       
   165         57 => Empty()
       
   166     )});
       
   167     res.boxed()
       
   168 }