The Battle for Wesnoth  1.13.4+dev
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Modules Pages
test_network_worker.cpp
Go to the documentation of this file.
1 /*
2  Copyright (C) 2008 - 2016 by Pauli Nieminen <[email protected]>
3  Part of the Battle for Wesnoth Project http://www.wesnoth.org/
4 
5  This program is free software; you can redistribute it and/or modify
6  it under the terms of the GNU General Public License as published by
7  the Free Software Foundation; either version 2 of the License, or
8  (at your option) any later version.
9  This program is distributed in the hope that it will be useful,
10  but WITHOUT ANY WARRANTY.
11 
12  See the COPYING file for more details.
13 */
14 
15 #define GETTEXT_DOMAIN "wesnoth-test"
16 
17 #include <boost/test/unit_test.hpp>
18 
19 
21 #include "utils/predicate.hpp"
22 
23 #include "network_worker.hpp"
24 #include "thread.hpp"
25 #include "filesystem.hpp"
26 
27 #include "config.hpp"
28 #include "game_config.hpp"
29 
30 /**
31  * Test networking to prevent bugs there.
32  * Try to create all kind of unlikely error conditions
33  * Some test should lock management_mutex from worker to settup stress test
34  * It is like that this will need some threading also :(
35  */
36 
37 BOOST_AUTO_TEST_SUITE( test_network )
38 
39 const int TEST_PORT = 15010;
40 const int MIN_THREADS = 1;
41 const int MAX_THREADS = 5;
42 const std::string LOCALHOST = "localhost";
43 
44 
45 network::manager* wes_manager;
46 network::server_manager* wes_server;
47 
50 
53 
54 
55 BOOST_AUTO_TEST_CASE( test_connect )
56 {
57  int connections = network::nconnections();
58 
59  BOOST_WARN_MESSAGE(connections == 0, "There is open "<< connections <<" connections before test!");
60  BOOST_CHECK_MESSAGE(wes_manager = new network::manager(MIN_THREADS,MAX_THREADS), "network::manager failed to initialize");
61 
62  BOOST_CHECK_MESSAGE(wes_server = new network::server_manager(TEST_PORT,network::server_manager::MUST_CREATE_SERVER),
63  "network::server_manager failed to initialize");
64  BOOST_REQUIRE_MESSAGE(wes_server->is_running(), "Can't start server!");
65 
66  client_client1 = network::connect(LOCALHOST, TEST_PORT);
67 
68  BOOST_CHECK_MESSAGE(client_client1 > 0, "Can't connect to server");
69 
70  server_client1 = network::accept_connection();
71 
72  BOOST_CHECK_MESSAGE(server_client1 > 0, "Can't accept connection");
73 
74 
75 }
76 
77 template<class T>
78 static network::connection receive(T& cfg, int max_tries = 100)
79 {
80  network::connection receive_con;
81  while ((receive_con = network::receive_data(cfg)) == network::null_connection)
82  {
83  // loop untill data is received
84  SDL_Delay(50);
85  if (--max_tries <= 0)
86  {
87  BOOST_WARN_MESSAGE(max_tries > 0,"receiving data took too long. Preventing for ever loop");
88  break;
89  }
90  }
91  return receive_con;
92 }
93 
94 BOOST_AUTO_TEST_CASE( test_send_client )
95 {
96  config cfg_send;
97  config& child = cfg_send.add_child("test_client_send");
98 
99  child["test"] = "yes!";
100  cfg_send["test_running"] = true;
102 
103  network::connection receive_from;
104  config received;
105 
106  receive_from = receive(received);
107 
108  BOOST_CHECK_MESSAGE( receive_from == server_client1, "Received data is not from test client 1" );
109 
110  BOOST_CHECK_EQUAL(cfg_send, received);
111 
112 }
113 
114 static void try_send_random_seed ( const std::string seed_str, const unsigned int random_calls)
115 {
116  config cfg_send;
117  config& child = cfg_send.add_child("command");
118 
119  child["random_seed"] = seed_str;
120  child["random_calls"] = random_calls;
121 
123 
124  network::connection receive_from;
125  config received;
126 
127  receive_from = receive(received);
128 
129  BOOST_CHECK_MESSAGE( receive_from == server_client1, "Received data is not from test client 1" );
130 
131  BOOST_CHECK_EQUAL(cfg_send, received);
132 
133  config rec_command = received.child("command");
134 
135  std::string rec_seed_str = rec_command["random_seed"].str();
136  unsigned int rec_calls = rec_command["random_calls"];
137 
138  BOOST_CHECK_EQUAL(seed_str, rec_seed_str);
139  BOOST_CHECK_EQUAL(random_calls, rec_calls);
140 }
141 
142 BOOST_AUTO_TEST_CASE( test_send_random_seed )
143 {
144  try_send_random_seed("0000badd",0);
145  try_send_random_seed("00001234",1);
146  try_send_random_seed("deadbeef",2);
147  try_send_random_seed("12345678",3);
148  try_send_random_seed("00009999",4);
149  try_send_random_seed("ffffaaaa",5);
150  try_send_random_seed("11110000",6);
151  try_send_random_seed("10101010",7);
152  try_send_random_seed("aaaa0000",8);
153 }
154 
156 {
157 public:
158  connect_aborter() : start_(SDL_GetTicks())
159  {}
160  ACTION process();
161 
162 private:
163  size_t start_;
164 };
165 
167 {
168  // Abort connection after 5 ms
169  if(SDL_GetTicks() - start_ >= 5) {
170  return ABORT;
171  } else {
172  return WAIT;
173  }
174 }
175 
176 #if 0
177 BOOST_AUTO_TEST_CASE( test_sdl_thread_wait_crash )
178 {
179 
180  delete wes_server;
181  wes_server = 0;
182  delete wes_manager;
183  wes_manager = 0;
184  BOOST_CHECK_MESSAGE(wes_manager == 0, "network::manager nono zero after delete");
185 
186  BOOST_CHECK_MESSAGE(wes_manager = new network::manager(MIN_THREADS,MAX_THREADS), "network::manager failed to initialize");
188  BOOST_CHECK_MESSAGE(client_client1 > 0, "Can't connect to server");
189  delete wes_manager;
190  wes_manager = 0;
191  BOOST_CHECK_MESSAGE(wes_manager = new network::manager(MIN_THREADS,MAX_THREADS), "network::manager failed to initialize");
192 
193  connect_aborter aborter;
194  BOOST_CHECK_MESSAGE((client_client1 = network::connect("server.wesnoth.org", 15000, aborter)) == 0, "Connection create but not shoul");
195  delete wes_manager;
196 
197  BOOST_CHECK_MESSAGE(wes_manager = new network::manager(MIN_THREADS,MAX_THREADS), "network::manager failed to initialize");
199  BOOST_CHECK_MESSAGE((client_client1 = network::connect(LOCALHOST, TEST_PORT, aborter)) == 0, "Connection create but not shoul");
200  delete wes_manager;
201 
204  BOOST_CHECK_MESSAGE(client_client1 > 0, "Can't connect to server");
205  delete wes_server;
206  delete wes_manager;
209 }
210 #endif
211 
212 // Use 1kb, 500kb and 10Mb files for testing
214  sendfile_param(size_t size, bool system) : size_(size), system_(system) {}
215  size_t size_;
216  bool system_;
217 };
218 
220  sendfile_param(5*1024*1024,true),
221  sendfile_param(1*1024,false),
222  sendfile_param(5*1024*1024,false)};
223 
225 {
226  char buffer[1024];
227  const int buffer_size = sizeof(buffer)/sizeof(buffer[0]);
228  int *begin = reinterpret_cast<int*>(&buffer[0]);
229  int *end = begin + sizeof(buffer)/sizeof(int);
230  std::string filename = "sendfile.tmp";
232  std::generate(begin,end,std::rand);
233  while( size > 0
234  && !file->bad())
235  {
236  file->write(buffer, buffer_size);
237  size -= buffer_size;
238  }
239  return filename;
240 }
241 
242 static void delete_random_sendfile(const std::string& file)
243 {
245 }
246 
247 template<class T>
251  public:
252  auto_resetter(const T& new_value, T& value_to_change) : value_to_change_(value_to_change), old_val_(value_to_change)
253  {
254  value_to_change_ = new_value;
255  }
257  {
258  value_to_change_ = old_val_;
259  }
260 };
261 
262 WESNOTH_PARAMETERIZED_TEST_CASE( test_multi_sendfile, sendfile_param, sendfile_sizes, size )
263 {
268 
269  network::connection cl_client1, se_client1;
270  network::connection cl_client2, se_client2;
271  network::connection cl_client3, se_client3;
272 
273  BOOST_CHECK_MESSAGE((cl_client1 = network::connect(LOCALHOST, TEST_PORT)) > 0, "Can't connect to server!");
274  BOOST_CHECK_MESSAGE((se_client1 = network::accept_connection()) > 0, "Coulnd't accept new connection");
275  BOOST_CHECK_MESSAGE((cl_client2 = network::connect(LOCALHOST, TEST_PORT)) > 0, "Can't connect to server!");
276  BOOST_CHECK_MESSAGE((se_client2 = network::accept_connection()) > 0, "Coulnd't accept new connection");
277  BOOST_CHECK_MESSAGE((cl_client3 = network::connect(LOCALHOST, TEST_PORT)) > 0, "Can't connect to server!");
278  BOOST_CHECK_MESSAGE((se_client3 = network::accept_connection()) > 0, "Coulnd't accept new connection");
279 
280  network::send_file(file, cl_client1);
281  network::send_file(file, cl_client2);
282  network::send_file(file, cl_client3);
283 
284  std::vector<char> data;
285 
286  BOOST_CHECK_PREDICATE(test_utils::one_of<network::connection> , (receive(data,500))(3)(se_client1)(se_client2)(se_client3));
287  BOOST_CHECK_EQUAL(data.size(), static_cast<size_t>(filesystem::file_size(file)));
288  BOOST_CHECK_PREDICATE(test_utils::one_of<network::connection> , (receive(data,500))(3)(se_client1)(se_client2)(se_client3));
289  BOOST_CHECK_EQUAL(data.size(), static_cast<size_t>(filesystem::file_size(file)));
290  BOOST_CHECK_PREDICATE(test_utils::one_of<network::connection> , (receive(data,500))(3)(se_client1)(se_client2)(se_client3));
291 
292  BOOST_CHECK_EQUAL(data.size(), static_cast<size_t>(filesystem::file_size(file)));
293 
294  network::disconnect(cl_client1);
295  network::disconnect(cl_client2);
296  network::disconnect(cl_client3);
297 
298  BOOST_CHECK_THROW(receive(data),network::error);
299  BOOST_CHECK_THROW(receive(data),network::error);
300  BOOST_CHECK_THROW(receive(data),network::error);
301 
303 }
304 
305 #if 0
306 BOOST_AUTO_TEST_CASE( test_multiple_connections )
307 {
308 }
309 
310 BOOST_AUTO_TEST_CASE( test_cancel_transfer )
311 {
312 }
313 
314 BOOST_AUTO_TEST_CASE( test_detect_errors )
315 {
316 }
317 
318 BOOST_AUTO_TEST_CASE( test_broken_data )
319 {
320 }
321 
322 BOOST_AUTO_TEST_CASE( test_config_with_macros )
323 {
324 }
325 
326 BOOST_AUTO_TEST_CASE( test_disconnect )
327 {
330 }
331 #endif
332 BOOST_AUTO_TEST_CASE( test_shutdown )
333 {
334  delete wes_server;
335  BOOST_CHECK_MESSAGE(true,"Not true");
336  delete wes_manager;
337 }
338 
339 BOOST_AUTO_TEST_SUITE_END()
340 /* vim: set ts=4 sw=4: */
void set_raw_data_only()
Definition: network.cpp:280
High level network layer for config object transport.
Definition: network.cpp:212
static void delete_random_sendfile(const std::string &file)
network::connection client_client2
auto_resetter(const T &new_value, T &value_to_change)
const int MIN_THREADS
bool delete_file(const std::string &filename)
connection receive_data(config &cfg, connection connection_num, unsigned int timeout, bandwidth_in_ptr *bandwidth_in)
Definition: network.cpp:702
network::manager * wes_manager
STL namespace.
BOOST_AUTO_TEST_SUITE(test_map_location)
GLint GLenum GLsizei GLint GLsizei const GLvoid * data
Definition: glew.h:1347
Definitions for the interface to Wesnoth Markup Language (WML).
network::connection client_client1
void send_file(const std::string &filename, connection connection_num, const std::string &packet_type)
Definition: network.cpp:1071
static std::string create_random_sendfile(size_t size)
GLsizei const char ** path
Definition: glew.h:4654
GLuint GLuint end
Definition: glew.h:1221
static network::connection receive(T &cfg, int max_tries=100)
std::ostream * ostream_file(std::string const &fname, bool create_directory=true)
config & add_child(const std::string &key)
Definition: config.cpp:743
std::string path
sendfile_param sendfile_sizes[]
const int TEST_PORT
Test networking to prevent bugs there.
static void try_send_random_seed(const std::string seed_str, const unsigned int random_calls)
GLuint buffer
Definition: glew.h:1648
size_t send_data(const config &cfg, connection connection_num, const std::string &packet_type)
Function to send data down a given connection, or broadcast to all peers if connection_num is 0...
Definition: network.cpp:1098
Will throw exception on failure.
Definition: network.hpp:84
BOOST_AUTO_TEST_CASE(test_connect)
sendfile_param(size_t size, bool system)
network::connection server_client2
A server manager causes listening on a given port to occur for the duration of its lifetime...
Definition: network.hpp:81
connection accept_connection()
Function to accept a connection from a remote host.
Definition: network.cpp:582
Declarations for File-IO.
const std::string LOCALHOST
bool disconnect(connection s)
Function to disconnect from a certain host, or close all connections if connection_num is 0...
Definition: network.cpp:646
int file_size(const std::string &fname)
Returns the size of a file, or -1 if the file doesn't exist.
GLsizeiptr size
Definition: glew.h:1649
size_t nconnections()
The number of peers we are connected to.
Definition: network.cpp:350
connection connect(const std::string &host, int port)
Function to attempt to connect to a remote host.
Definition: network.cpp:498
config & child(const std::string &key, int n=0)
Returns the nth child with the given key, or a reference to an invalid config if there is none...
Definition: config.cpp:658
WESNOTH_PARAMETERIZED_TEST_CASE(test_multi_sendfile, sendfile_param, sendfile_sizes, size)
int connection
Definition: network.hpp:74
void set_use_system_sendfile(bool use)
const int MAX_THREADS
A config object defines a single node in a WML file, with access to child nodes.
Definition: config.hpp:83
network::connection server_client1
GLsizei const GLcharARB ** string
Definition: glew.h:4503
network::server_manager * wes_server
connection const null_connection
Definition: network.hpp:75