|
1 use proptest::{ |
|
2 test_runner::{TestRunner, Reason}, |
|
3 arbitrary::{any, any_with, Arbitrary, StrategyFor}, |
|
4 strategy::{Strategy, BoxedStrategy, Just, Filter, ValueTree}, |
|
5 string::RegexGeneratorValueTree |
|
6 }; |
|
7 |
|
8 use super::messages::{ |
|
9 HWProtocolMessage, HWProtocolMessage::* |
|
10 }; |
|
11 |
|
12 // Due to inability to define From between Options |
|
13 trait Into2<T>: Sized { fn into2(self) -> T; } |
|
14 impl <T> Into2<T> for T { fn into2(self) -> T { self } } |
|
15 impl Into2<String> for Ascii { fn into2(self) -> String { self.0 } } |
|
16 impl Into2<Option<String>> for Option<Ascii>{ |
|
17 fn into2(self) -> Option<String> { self.map(|x| {x.0}) } |
|
18 } |
|
19 |
|
20 macro_rules! proto_msg_case { |
|
21 ($val: ident()) => |
|
22 (Just($val)); |
|
23 ($val: ident($arg: ty)) => |
|
24 (any::<$arg>().prop_map(|v| {$val(v.into2())})); |
|
25 ($val: ident($arg1: ty, $arg2: ty)) => |
|
26 (any::<($arg1, $arg2)>().prop_map(|v| {$val(v.0.into2(), v.1.into2())})); |
|
27 ($val: ident($arg1: ty, $arg2: ty, $arg3: ty)) => |
|
28 (any::<($arg1, $arg2, $arg3)>().prop_map(|v| {$val(v.0.into2(), v.1.into2(), v.2.into2())})); |
|
29 } |
|
30 |
|
31 macro_rules! proto_msg_match { |
|
32 ($var: expr, def = $default: ident, $($num: expr => $constr: ident $res: tt),*) => ( |
|
33 match $var { |
|
34 $($num => (proto_msg_case!($constr $res)).boxed()),*, |
|
35 _ => Just($default).boxed() |
|
36 } |
|
37 ) |
|
38 } |
|
39 |
|
40 #[derive(Debug)] |
|
41 struct Ascii(String); |
|
42 |
|
43 struct AsciiValueTree(RegexGeneratorValueTree<String>); |
|
44 |
|
45 impl ValueTree for AsciiValueTree { |
|
46 type Value = Ascii; |
|
47 |
|
48 fn current(&self) -> Self::Value { Ascii(self.0.current()) } |
|
49 fn simplify(&mut self) -> bool { self.0.simplify() } |
|
50 fn complicate(&mut self) -> bool { self.0.complicate() } |
|
51 } |
|
52 |
|
53 impl Arbitrary for Ascii { |
|
54 type Parameters = <String as Arbitrary>::Parameters; |
|
55 |
|
56 fn arbitrary_with(args: Self::Parameters) -> Self::Strategy { |
|
57 any_with::<String>(args) |
|
58 .prop_filter("not ascii", |s| { |
|
59 s.len() > 0 && s.is_ascii() && |
|
60 s.find(|c| { |
|
61 ['\0', '\n', '\x20'].contains(&c) |
|
62 }).is_none()}) |
|
63 .prop_map(Ascii) |
|
64 .boxed() |
|
65 } |
|
66 |
|
67 type Strategy = BoxedStrategy<Ascii>; |
|
68 type ValueTree = Box<ValueTree<Value = Ascii>>; |
|
69 } |
|
70 |
|
71 pub fn gen_proto_msg() -> BoxedStrategy<HWProtocolMessage> where { |
|
72 let res = (0..58).no_shrink().prop_flat_map(|i| { |
|
73 proto_msg_match!(i, def = Malformed, |
|
74 0 => Ping(), |
|
75 1 => Pong(), |
|
76 2 => Quit(Option<Ascii>), |
|
77 //3 => Cmd |
|
78 4 => Global(Ascii), |
|
79 5 => Watch(Ascii), |
|
80 6 => ToggleServerRegisteredOnly(), |
|
81 7 => SuperPower(), |
|
82 8 => Info(Ascii), |
|
83 9 => Nick(Ascii), |
|
84 10 => Proto(u32), |
|
85 11 => Password(Ascii, Ascii), |
|
86 12 => Checker(u32, Ascii, Ascii), |
|
87 13 => List(), |
|
88 14 => Chat(Ascii), |
|
89 15 => CreateRoom(Ascii, Option<Ascii>), |
|
90 16 => JoinRoom(Ascii, Option<Ascii>), |
|
91 17 => Follow(Ascii), |
|
92 //18 => Rnd(Vec<String>), |
|
93 19 => Kick(Ascii), |
|
94 20 => Ban(Ascii, Ascii, u32), |
|
95 21 => BanIP(Ascii, Ascii, u32), |
|
96 22 => BanNick(Ascii, Ascii, u32), |
|
97 23 => BanList(), |
|
98 24 => Unban(Ascii), |
|
99 //25 => SetServerVar(ServerVar), |
|
100 26 => GetServerVar(), |
|
101 27 => RestartServer(), |
|
102 28 => Stats(), |
|
103 29 => Part(Option<Ascii>), |
|
104 //30 => Cfg(GameCfg), |
|
105 //31 => AddTeam(TeamInfo), |
|
106 32 => RemoveTeam(Ascii), |
|
107 //33 => SetHedgehogsNumber(String, u8), |
|
108 //34 => SetTeamColor(String, u8), |
|
109 35 => ToggleReady(), |
|
110 36 => StartGame(), |
|
111 37 => EngineMessage(Ascii), |
|
112 38 => RoundFinished(), |
|
113 39 => ToggleRestrictJoin(), |
|
114 40 => ToggleRestrictTeams(), |
|
115 41 => ToggleRegisteredOnly(), |
|
116 42 => RoomName(Ascii), |
|
117 43 => Delegate(Ascii), |
|
118 44 => TeamChat(Ascii), |
|
119 45 => MaxTeams(u8), |
|
120 46 => Fix(), |
|
121 47 => Unfix(), |
|
122 48 => Greeting(Ascii), |
|
123 //49 => CallVote(Option<(String, Option<String>)>), |
|
124 50 => Vote(String), |
|
125 51 => ForceVote(Ascii), |
|
126 //52 => Save(String, String), |
|
127 53 => Delete(Ascii), |
|
128 54 => SaveRoom(Ascii), |
|
129 55 => LoadRoom(Ascii), |
|
130 56 => Malformed(), |
|
131 57 => Empty() |
|
132 )}); |
|
133 res.boxed() |
|
134 } |