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