1 use proptest::{ |
1 use proptest::{ |
2 test_runner::{TestRunner, Reason}, |
|
3 arbitrary::{any, any_with, Arbitrary, StrategyFor}, |
2 arbitrary::{any, any_with, Arbitrary, StrategyFor}, |
4 strategy::{Strategy, BoxedStrategy, Just, Map} |
3 strategy::{BoxedStrategy, Just, Map, Strategy}, |
|
4 test_runner::{Reason, TestRunner}, |
5 }; |
5 }; |
6 |
6 |
7 use crate::server::coretypes::{GameCfg, TeamInfo, HedgehogInfo}; |
7 use crate::server::coretypes::{GameCfg, HedgehogInfo, TeamInfo}; |
8 |
8 |
9 use super::messages::{ |
9 use super::messages::{HWProtocolMessage, HWProtocolMessage::*}; |
10 HWProtocolMessage, HWProtocolMessage::* |
|
11 }; |
|
12 |
10 |
13 // Due to inability to define From between Options |
11 // Due to inability to define From between Options |
14 trait Into2<T>: Sized { fn into2(self) -> T; } |
12 trait Into2<T>: Sized { |
15 impl <T> Into2<T> for T { fn into2(self) -> T { self } } |
13 fn into2(self) -> T; |
|
14 } |
|
15 impl<T> Into2<T> for T { |
|
16 fn into2(self) -> T { |
|
17 self |
|
18 } |
|
19 } |
16 impl Into2<Vec<String>> for Vec<Ascii> { |
20 impl Into2<Vec<String>> for Vec<Ascii> { |
17 fn into2(self) -> Vec<String> { |
21 fn into2(self) -> Vec<String> { |
18 self.into_iter().map(|x| x.0).collect() |
22 self.into_iter().map(|x| x.0).collect() |
19 } |
23 } |
20 } |
24 } |
21 impl Into2<String> for Ascii { fn into2(self) -> String { self.0 } } |
25 impl Into2<String> for Ascii { |
22 impl Into2<Option<String>> for Option<Ascii>{ |
26 fn into2(self) -> String { |
23 fn into2(self) -> Option<String> { self.map(|x| {x.0}) } |
27 self.0 |
|
28 } |
|
29 } |
|
30 impl Into2<Option<String>> for Option<Ascii> { |
|
31 fn into2(self) -> Option<String> { |
|
32 self.map(|x| x.0) |
|
33 } |
24 } |
34 } |
25 |
35 |
26 macro_rules! proto_msg_case { |
36 macro_rules! proto_msg_case { |
27 ($val: ident()) => |
37 ($val: ident()) => { |
28 (Just($val)); |
38 Just($val) |
29 ($val: ident($arg: ty)) => |
39 }; |
30 (any::<$arg>().prop_map(|v| {$val(v.into2())})); |
40 ($val: ident($arg: ty)) => { |
31 ($val: ident($arg1: ty, $arg2: ty)) => |
41 any::<$arg>().prop_map(|v| $val(v.into2())) |
32 (any::<($arg1, $arg2)>().prop_map(|v| {$val(v.0.into2(), v.1.into2())})); |
42 }; |
33 ($val: ident($arg1: ty, $arg2: ty, $arg3: ty)) => |
43 ($val: ident($arg1: ty, $arg2: ty)) => { |
34 (any::<($arg1, $arg2, $arg3)>().prop_map(|v| {$val(v.0.into2(), v.1.into2(), v.2.into2())})); |
44 any::<($arg1, $arg2)>().prop_map(|v| $val(v.0.into2(), v.1.into2())) |
|
45 }; |
|
46 ($val: ident($arg1: ty, $arg2: ty, $arg3: ty)) => { |
|
47 any::<($arg1, $arg2, $arg3)>().prop_map(|v| $val(v.0.into2(), v.1.into2(), v.2.into2())) |
|
48 }; |
35 } |
49 } |
36 |
50 |
37 macro_rules! proto_msg_match { |
51 macro_rules! proto_msg_match { |
38 ($var: expr, def = $default: expr, $($num: expr => $constr: ident $res: tt),*) => ( |
52 ($var: expr, def = $default: expr, $($num: expr => $constr: ident $res: tt),*) => ( |
39 match $var { |
53 match $var { |
73 6 => Ammo(Ascii, Option<Ascii>), |
89 6 => Ammo(Ascii, Option<Ascii>), |
74 7 => Scheme(Ascii, Vec<Ascii>), |
90 7 => Scheme(Ascii, Vec<Ascii>), |
75 8 => Script(Ascii), |
91 8 => Script(Ascii), |
76 9 => Theme(Ascii), |
92 9 => Theme(Ascii), |
77 10 => DrawnMap(Ascii)) |
93 10 => DrawnMap(Ascii)) |
78 }).boxed() |
94 }) |
|
95 .boxed() |
79 } |
96 } |
80 |
97 |
81 type Strategy = BoxedStrategy<GameCfg>; |
98 type Strategy = BoxedStrategy<GameCfg>; |
82 } |
99 } |
83 |
100 |
84 impl Arbitrary for TeamInfo { |
101 impl Arbitrary for TeamInfo { |
85 type Parameters = (); |
102 type Parameters = (); |
86 |
103 |
87 fn arbitrary_with(_args: <Self as Arbitrary>::Parameters) -> <Self as Arbitrary>::Strategy { |
104 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) |
105 ( |
|
106 "[a-z]+", |
|
107 0u8..127u8, |
|
108 "[a-z]+", |
|
109 "[a-z]+", |
|
110 "[a-z]+", |
|
111 "[a-z]+", |
|
112 0u8..127u8, |
|
113 ) |
89 .prop_map(|(name, color, grave, fort, voice_pack, flag, difficulty)| { |
114 .prop_map(|(name, color, grave, fort, voice_pack, flag, difficulty)| { |
90 fn hog(n: u8) -> HedgehogInfo { |
115 fn hog(n: u8) -> HedgehogInfo { |
91 HedgehogInfo { name: format!("hog{}", n), hat: format!("hat{}", n)} |
116 HedgehogInfo { |
|
117 name: format!("hog{}", n), |
|
118 hat: format!("hat{}", n), |
|
119 } |
92 } |
120 } |
93 let hedgehogs = [hog(1), hog(2), hog(3), hog(4), hog(5), hog(6), hog(7), hog(8)]; |
121 let hedgehogs = [ |
|
122 hog(1), |
|
123 hog(2), |
|
124 hog(3), |
|
125 hog(4), |
|
126 hog(5), |
|
127 hog(6), |
|
128 hog(7), |
|
129 hog(8), |
|
130 ]; |
94 TeamInfo { |
131 TeamInfo { |
95 name, color, grave, fort, |
132 name, |
96 voice_pack, flag,difficulty, |
133 color, |
97 hedgehogs, hedgehogs_number: 0 |
134 grave, |
|
135 fort, |
|
136 voice_pack, |
|
137 flag, |
|
138 difficulty, |
|
139 hedgehogs, |
|
140 hedgehogs_number: 0, |
98 } |
141 } |
99 }).boxed() |
142 }) |
|
143 .boxed() |
100 } |
144 } |
101 |
145 |
102 type Strategy = BoxedStrategy<TeamInfo>; |
146 type Strategy = BoxedStrategy<TeamInfo>; |
103 } |
147 } |
104 |
148 |
105 pub fn gen_proto_msg() -> BoxedStrategy<HWProtocolMessage> where { |
149 pub fn gen_proto_msg() -> BoxedStrategy<HWProtocolMessage> where { |
106 let res = (0..58).no_shrink().prop_flat_map(|i| { |
150 let res = (0..58).no_shrink().prop_flat_map(|i| { |
107 proto_msg_match!(i, def = Malformed, |
151 proto_msg_match!(i, def = Malformed, |
108 0 => Ping(), |
152 0 => Ping(), |
109 1 => Pong(), |
153 1 => Pong(), |
110 2 => Quit(Option<Ascii>), |
154 2 => Quit(Option<Ascii>), |
111 //3 => Cmd |
155 //3 => Cmd |
112 4 => Global(Ascii), |
156 4 => Global(Ascii), |
113 5 => Watch(Ascii), |
157 5 => Watch(Ascii), |
114 6 => ToggleServerRegisteredOnly(), |
158 6 => ToggleServerRegisteredOnly(), |
115 7 => SuperPower(), |
159 7 => SuperPower(), |
116 8 => Info(Ascii), |
160 8 => Info(Ascii), |
117 9 => Nick(Ascii), |
161 9 => Nick(Ascii), |
118 10 => Proto(u16), |
162 10 => Proto(u16), |
119 11 => Password(Ascii, Ascii), |
163 11 => Password(Ascii, Ascii), |
120 12 => Checker(u16, Ascii, Ascii), |
164 12 => Checker(u16, Ascii, Ascii), |
121 13 => List(), |
165 13 => List(), |
122 14 => Chat(Ascii), |
166 14 => Chat(Ascii), |
123 15 => CreateRoom(Ascii, Option<Ascii>), |
167 15 => CreateRoom(Ascii, Option<Ascii>), |
124 16 => JoinRoom(Ascii, Option<Ascii>), |
168 16 => JoinRoom(Ascii, Option<Ascii>), |
125 17 => Follow(Ascii), |
169 17 => Follow(Ascii), |
126 18 => Rnd(Vec<Ascii>), |
170 18 => Rnd(Vec<Ascii>), |
127 19 => Kick(Ascii), |
171 19 => Kick(Ascii), |
128 20 => Ban(Ascii, Ascii, u32), |
172 20 => Ban(Ascii, Ascii, u32), |
129 21 => BanIP(Ascii, Ascii, u32), |
173 21 => BanIP(Ascii, Ascii, u32), |
130 22 => BanNick(Ascii, Ascii, u32), |
174 22 => BanNick(Ascii, Ascii, u32), |
131 23 => BanList(), |
175 23 => BanList(), |
132 24 => Unban(Ascii), |
176 24 => Unban(Ascii), |
133 //25 => SetServerVar(ServerVar), |
177 //25 => SetServerVar(ServerVar), |
134 26 => GetServerVar(), |
178 26 => GetServerVar(), |
135 27 => RestartServer(), |
179 27 => RestartServer(), |
136 28 => Stats(), |
180 28 => Stats(), |
137 29 => Part(Option<Ascii>), |
181 29 => Part(Option<Ascii>), |
138 30 => Cfg(GameCfg), |
182 30 => Cfg(GameCfg), |
139 31 => AddTeam(Box<TeamInfo>), |
183 31 => AddTeam(Box<TeamInfo>), |
140 32 => RemoveTeam(Ascii), |
184 32 => RemoveTeam(Ascii), |
141 33 => SetHedgehogsNumber(Ascii, u8), |
185 33 => SetHedgehogsNumber(Ascii, u8), |
142 34 => SetTeamColor(Ascii, u8), |
186 34 => SetTeamColor(Ascii, u8), |
143 35 => ToggleReady(), |
187 35 => ToggleReady(), |
144 36 => StartGame(), |
188 36 => StartGame(), |
145 37 => EngineMessage(Ascii), |
189 37 => EngineMessage(Ascii), |
146 38 => RoundFinished(), |
190 38 => RoundFinished(), |
147 39 => ToggleRestrictJoin(), |
191 39 => ToggleRestrictJoin(), |
148 40 => ToggleRestrictTeams(), |
192 40 => ToggleRestrictTeams(), |
149 41 => ToggleRegisteredOnly(), |
193 41 => ToggleRegisteredOnly(), |
150 42 => RoomName(Ascii), |
194 42 => RoomName(Ascii), |
151 43 => Delegate(Ascii), |
195 43 => Delegate(Ascii), |
152 44 => TeamChat(Ascii), |
196 44 => TeamChat(Ascii), |
153 45 => MaxTeams(u8), |
197 45 => MaxTeams(u8), |
154 46 => Fix(), |
198 46 => Fix(), |
155 47 => Unfix(), |
199 47 => Unfix(), |
156 48 => Greeting(Ascii), |
200 48 => Greeting(Ascii), |
157 //49 => CallVote(Option<(String, Option<String>)>), |
201 //49 => CallVote(Option<(String, Option<String>)>), |
158 50 => Vote(bool), |
202 50 => Vote(bool), |
159 51 => ForceVote(bool), |
203 51 => ForceVote(bool), |
160 52 => Save(Ascii, Ascii), |
204 52 => Save(Ascii, Ascii), |
161 53 => Delete(Ascii), |
205 53 => Delete(Ascii), |
162 54 => SaveRoom(Ascii), |
206 54 => SaveRoom(Ascii), |
163 55 => LoadRoom(Ascii), |
207 55 => LoadRoom(Ascii), |
164 56 => Malformed(), |
208 56 => Malformed(), |
165 57 => Empty() |
209 57 => Empty() |
166 )}); |
210 ) |
|
211 }); |
167 res.boxed() |
212 res.boxed() |
168 } |
213 } |