Mercurial > irccd
comparison tests/src/plugins/tictactoe/main.cpp @ 632:e5d0f4289e04
Plugin tictactoe: brand new plugin, closes #393 @6h
author | David Demelier <markand@malikania.fr> |
---|---|
date | Tue, 13 Mar 2018 13:51:17 +0100 |
parents | |
children | c07819d1d306 |
comparison
equal
deleted
inserted
replaced
631:1fa9e5222e87 | 632:e5d0f4289e04 |
---|---|
1 /* | |
2 * main.cpp -- test plugin plugin | |
3 * | |
4 * Copyright (c) 2013-2018 David Demelier <markand@malikania.fr> | |
5 * | |
6 * Permission to use, copy, modify, and/or distribute this software for any | |
7 * purpose with or without fee is hereby granted, provided that the above | |
8 * copyright notice and this permission notice appear in all copies. | |
9 * | |
10 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES | |
11 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF | |
12 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR | |
13 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES | |
14 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN | |
15 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF | |
16 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. | |
17 */ | |
18 | |
19 #define BOOST_TEST_MODULE "Plugin tictactoe" | |
20 #include <boost/test/unit_test.hpp> | |
21 | |
22 #include <irccd/string_util.hpp> | |
23 | |
24 #include <irccd/daemon/irccd.hpp> | |
25 #include <irccd/daemon/server.hpp> | |
26 #include <irccd/daemon/service/plugin_service.hpp> | |
27 | |
28 #include <irccd/test/plugin_test.hpp> | |
29 | |
30 namespace irccd { | |
31 | |
32 class test_fixture : public plugin_test { | |
33 public: | |
34 test_fixture() | |
35 : plugin_test(PLUGIN_NAME, PLUGIN_PATH) | |
36 { | |
37 plugin_->set_formats({ | |
38 { "draw", "draw=#{channel}:#{command}:#{nickname}:#{plugin}:#{server}" }, | |
39 { "invalid", "invalid=#{channel}:#{command}:#{nickname}:#{origin}:#{plugin}:#{server}" }, | |
40 { "running", "running=#{channel}:#{command}:#{nickname}:#{origin}:#{plugin}:#{server}" }, | |
41 { "turn", "turn=#{channel}:#{command}:#{nickname}:#{plugin}:#{server}" }, | |
42 { "used", "used=#{channel}:#{command}:#{nickname}:#{origin}:#{plugin}:#{server}" }, | |
43 { "win", "win=#{channel}:#{command}:#{nickname}:#{plugin}:#{server}" } | |
44 }); | |
45 } | |
46 | |
47 auto next_players() const | |
48 { | |
49 if (server_->cqueue().size() == 0) | |
50 throw std::runtime_error("no message"); | |
51 | |
52 const auto cmd = server_->cqueue().back(); | |
53 const auto list = string_util::split(cmd["message"].get<std::string>(), ":"); | |
54 | |
55 BOOST_TEST(list.size() == 5U); | |
56 BOOST_TEST(list[0] == "turn=#tictactoe"); | |
57 BOOST_TEST(list[1] == "!tictactoe"); | |
58 BOOST_TEST(list[3] == "tictactoe"); | |
59 BOOST_TEST(list[4] == "test"); | |
60 | |
61 return list[2] == "a" ? std::make_pair("a", "b") : std::make_pair("b", "a"); | |
62 } | |
63 | |
64 auto start() | |
65 { | |
66 plugin_->on_command(irccd_, {server_, "a!a@localhost", "#tictactoe", "b"}); | |
67 plugin_->on_names(irccd_, {server_, "#tictactoe", {"a", "b"}}); | |
68 | |
69 return next_players(); | |
70 } | |
71 | |
72 /** | |
73 * Helper to place several tokens on the board and automatically toggling | |
74 * players. | |
75 * | |
76 * This will start the game from "a" with target opponent "b". | |
77 * | |
78 */ | |
79 void run(const std::initializer_list<std::string>& points) | |
80 { | |
81 auto players = start(); | |
82 | |
83 for (const auto& p : points) { | |
84 server_->cqueue().clear(); | |
85 plugin_->on_message(irccd_, {server_, players.first, "#tictactoe", p}); | |
86 players = next_players(); | |
87 } | |
88 } | |
89 }; | |
90 | |
91 BOOST_FIXTURE_TEST_SUITE(test_fixture_suite, test_fixture) | |
92 | |
93 BOOST_AUTO_TEST_CASE(win) | |
94 { | |
95 run({"a 1", "b 1", "a 2", "b 2"}); | |
96 | |
97 const auto players = next_players(); | |
98 | |
99 plugin_->on_message(irccd_, {server_, players.first, "#tictactoe", "a 3"}); | |
100 | |
101 const auto cmd = server_->cqueue().back(); | |
102 | |
103 BOOST_TEST(cmd.is_object()); | |
104 BOOST_TEST(cmd["command"].get<std::string>() == "message"); | |
105 BOOST_TEST(cmd["target"].get<std::string>() == "#tictactoe"); | |
106 | |
107 const auto parts = string_util::split(cmd["message"].get<std::string>(), ":"); | |
108 | |
109 BOOST_TEST(parts.size() == 5U); | |
110 BOOST_TEST(parts[0] == "win=#tictactoe"); | |
111 BOOST_TEST(parts[1] == "!tictactoe"); | |
112 BOOST_TEST(parts[2] == players.first); | |
113 BOOST_TEST(parts[3] == "tictactoe"); | |
114 BOOST_TEST(parts[4] == "test"); | |
115 } | |
116 | |
117 BOOST_AUTO_TEST_CASE(draw) | |
118 { | |
119 /* | |
120 * a b c | |
121 * 1 o x o | |
122 * 2 o x x | |
123 * 3 x o x | |
124 */ | |
125 run({ "b 2", "c 1", "c 3", "b 3", "c 2", "a 2", "a 3", "a 1" }); | |
126 | |
127 const auto players = next_players(); | |
128 | |
129 plugin_->on_message(irccd_, {server_, players.first, "#tictactoe", "b 1"}); | |
130 | |
131 const auto cmd = server_->cqueue().back(); | |
132 | |
133 BOOST_TEST(cmd.is_object()); | |
134 BOOST_TEST(cmd["command"].get<std::string>() == "message"); | |
135 BOOST_TEST(cmd["target"].get<std::string>() == "#tictactoe"); | |
136 | |
137 const auto parts = string_util::split(cmd["message"].get<std::string>(), ":"); | |
138 | |
139 BOOST_TEST(parts.size() == 5U); | |
140 BOOST_TEST(parts[0] == "draw=#tictactoe"); | |
141 BOOST_TEST(parts[1] == "!tictactoe"); | |
142 BOOST_TEST(parts[2] == players.first); | |
143 BOOST_TEST(parts[3] == "tictactoe"); | |
144 BOOST_TEST(parts[4] == "test"); | |
145 } | |
146 | |
147 BOOST_AUTO_TEST_CASE(used) | |
148 { | |
149 auto players = start(); | |
150 | |
151 plugin_->on_message(irccd_, {server_, players.first, "#tictactoe", "a 1"}); | |
152 plugin_->on_message(irccd_, {server_, players.second, "#tictactoe", "a 1"}); | |
153 | |
154 const auto cmd = server_->cqueue().back(); | |
155 | |
156 BOOST_TEST(cmd.is_object()); | |
157 BOOST_TEST(cmd["command"].get<std::string>() == "message"); | |
158 BOOST_TEST(cmd["target"].get<std::string>() == "#tictactoe"); | |
159 | |
160 const auto parts = string_util::split(cmd["message"].get<std::string>(), ":"); | |
161 | |
162 BOOST_TEST(parts[0] == "used=#tictactoe"); | |
163 BOOST_TEST(parts[1] == "!tictactoe"); | |
164 BOOST_TEST(parts[2] == players.second); | |
165 BOOST_TEST(parts[3] == players.second); | |
166 BOOST_TEST(parts[4] == "tictactoe"); | |
167 BOOST_TEST(parts[5] == "test"); | |
168 } | |
169 | |
170 BOOST_AUTO_TEST_CASE(invalid) | |
171 { | |
172 nlohmann::json cmd; | |
173 | |
174 // empty name (no names) | |
175 plugin_->on_command(irccd_, {server_, "jean", "#tictactoe", ""}); | |
176 cmd = server_->cqueue().back(); | |
177 | |
178 BOOST_TEST(cmd["command"].get<std::string>() == "message"); | |
179 BOOST_TEST(cmd["target"].get<std::string>() == "#tictactoe"); | |
180 BOOST_TEST(cmd["message"].get<std::string>() == "invalid=#tictactoe:!tictactoe:jean:jean:tictactoe:test"); | |
181 | |
182 // bot name (no names) | |
183 plugin_->on_command(irccd_, {server_, "jean", "#tictactoe", "irccd"}); | |
184 cmd = server_->cqueue().back(); | |
185 | |
186 BOOST_TEST(cmd["command"].get<std::string>() == "message"); | |
187 BOOST_TEST(cmd["target"].get<std::string>() == "#tictactoe"); | |
188 BOOST_TEST(cmd["message"].get<std::string>() == "invalid=#tictactoe:!tictactoe:jean:jean:tictactoe:test"); | |
189 | |
190 // target is origin (no names) | |
191 plugin_->on_command(irccd_, {server_, server_->nickname(), "#tictactoe", server_->nickname()}); | |
192 cmd = server_->cqueue().back(); | |
193 | |
194 BOOST_TEST(cmd["command"].get<std::string>() == "message"); | |
195 BOOST_TEST(cmd["target"].get<std::string>() == "#tictactoe"); | |
196 BOOST_TEST(cmd["message"].get<std::string>() == "invalid=#tictactoe:!tictactoe:irccd:irccd:tictactoe:test"); | |
197 | |
198 // not existing (names) | |
199 plugin_->on_command(irccd_, {server_, server_->nickname(), "#tictactoe", server_->nickname()}); | |
200 plugin_->on_names(irccd_, {server_, "#tictactoe", {"a", "b", "c"}}); | |
201 cmd = server_->cqueue().back(); | |
202 | |
203 BOOST_TEST(cmd["command"].get<std::string>() == "message"); | |
204 BOOST_TEST(cmd["target"].get<std::string>() == "#tictactoe"); | |
205 BOOST_TEST(cmd["message"].get<std::string>() == "invalid=#tictactoe:!tictactoe:irccd:irccd:tictactoe:test"); | |
206 } | |
207 | |
208 BOOST_AUTO_TEST_CASE(random) | |
209 { | |
210 /* | |
211 * Ensure that the first player is not always the originator, start the game | |
212 * for at most 1'000'000 times to avoid forever loop. | |
213 */ | |
214 unsigned count = 0; | |
215 bool a = false; | |
216 bool b = false; | |
217 | |
218 // Last player turn is the winner. | |
219 while (!a && !b && count++ < 1000000U) { | |
220 run({"a 1", "b 1", "a 2", "b 2"}); | |
221 | |
222 const auto players = next_players(); | |
223 | |
224 if (players.first == std::string("a")) | |
225 a = true; | |
226 else | |
227 b = true; | |
228 | |
229 plugin_->on_message(irccd_, {server_, players.first, "#tictactoe", "a 3"}); | |
230 } | |
231 } | |
232 | |
233 BOOST_AUTO_TEST_CASE(kick) | |
234 { | |
235 auto players = start(); | |
236 | |
237 server_->cqueue().clear(); | |
238 plugin_->on_kick(irccd_, {server_, "kefka", "#tictactoe", players.first, ""}); | |
239 plugin_->on_message(irccd_, {server_, players.first, "#tictactoe", "a 1"}); | |
240 | |
241 BOOST_TEST(server_->cqueue().empty()); | |
242 } | |
243 | |
244 BOOST_AUTO_TEST_CASE(part) | |
245 { | |
246 auto players = start(); | |
247 | |
248 server_->cqueue().clear(); | |
249 plugin_->on_part(irccd_, {server_, players.first, "#tictactoe", ""}); | |
250 plugin_->on_message(irccd_, {server_, players.first, "#tictactoe", "a 1"}); | |
251 | |
252 BOOST_TEST(server_->cqueue().empty()); | |
253 } | |
254 | |
255 BOOST_AUTO_TEST_SUITE_END() | |
256 | |
257 } // !irccd |