35
35
#include " core/io/tcp_server.h"
36
36
#include " tests/test_macros.h"
37
37
38
+ #include < functional>
39
+
38
40
namespace TestTCPServer {
39
41
40
42
const int PORT = 12345 ;
41
43
const IPAddress LOCALHOST (" 127.0.0.1" );
42
44
const uint32_t SLEEP_DURATION = 1000 ;
43
- const uint64_t MAX_WAIT_USEC = 100000 ;
45
+ const uint64_t MAX_WAIT_USEC = 2000000 ;
46
+
47
+ void wait_for_condition (std::function<bool ()> f_test) {
48
+ const uint64_t time = OS::get_singleton ()->get_ticks_usec ();
49
+ while (!f_test () && (OS::get_singleton ()->get_ticks_usec () - time ) < MAX_WAIT_USEC) {
50
+ OS::get_singleton ()->delay_usec (SLEEP_DURATION);
51
+ }
52
+ }
44
53
45
54
Ref<TCPServer> create_server (const IPAddress &p_address, int p_port) {
46
55
Ref<TCPServer> server;
@@ -66,11 +75,9 @@ Ref<StreamPeerTCP> create_client(const IPAddress &p_address, int p_port) {
66
75
}
67
76
68
77
Ref<StreamPeerTCP> accept_connection (Ref<TCPServer> &p_server) {
69
- // Required to get the connection properly established.
70
- const uint64_t time = OS::get_singleton ()->get_ticks_usec ();
71
- while (!p_server->is_connection_available () && (OS::get_singleton ()->get_ticks_usec () - time ) < MAX_WAIT_USEC) {
72
- OS::get_singleton ()->delay_usec (SLEEP_DURATION);
73
- }
78
+ wait_for_condition ([&]() {
79
+ return p_server->is_connection_available ();
80
+ });
74
81
75
82
REQUIRE (p_server->is_connection_available ());
76
83
Ref<StreamPeerTCP> client_from_server = p_server->take_connection ();
@@ -81,16 +88,6 @@ Ref<StreamPeerTCP> accept_connection(Ref<TCPServer> &p_server) {
81
88
return client_from_server;
82
89
}
83
90
84
- Error poll (Ref<StreamPeerTCP> p_client) {
85
- const uint64_t time = OS::get_singleton ()->get_ticks_usec ();
86
- Error err = p_client->poll ();
87
- while (err != Error::OK && (OS::get_singleton ()->get_ticks_usec () - time ) < MAX_WAIT_USEC) {
88
- OS::get_singleton ()->delay_usec (SLEEP_DURATION);
89
- err = p_client->poll ();
90
- }
91
- return err;
92
- }
93
-
94
91
TEST_CASE (" [TCPServer] Instantiation" ) {
95
92
Ref<TCPServer> server;
96
93
server.instantiate ();
@@ -104,7 +101,10 @@ TEST_CASE("[TCPServer] Accept a connection and receive/send data") {
104
101
Ref<StreamPeerTCP> client = create_client (LOCALHOST, PORT);
105
102
Ref<StreamPeerTCP> client_from_server = accept_connection (server);
106
103
107
- REQUIRE_EQ (poll (client), Error::OK);
104
+ wait_for_condition ([&]() {
105
+ return client->poll () != Error::OK || client->get_status () == StreamPeerTCP::STATUS_CONNECTED;
106
+ });
107
+
108
108
CHECK_EQ (client->get_status (), StreamPeerTCP::STATUS_CONNECTED);
109
109
110
110
// Sending data from client to server.
@@ -135,9 +135,25 @@ TEST_CASE("[TCPServer] Handle multiple clients at the same time") {
135
135
clients_from_server.push_back (accept_connection (server));
136
136
}
137
137
138
- // Calling poll() to update client status.
138
+ wait_for_condition ([&]() {
139
+ bool should_exit = true ;
140
+ for (Ref<StreamPeerTCP> &c : clients) {
141
+ if (c->poll () != Error::OK) {
142
+ return true ;
143
+ }
144
+ StreamPeerTCP::Status status = c->get_status ();
145
+ if (status != StreamPeerTCP::STATUS_CONNECTED && status != StreamPeerTCP::STATUS_CONNECTING) {
146
+ return true ;
147
+ }
148
+ if (status != StreamPeerTCP::STATUS_CONNECTED) {
149
+ should_exit = false ;
150
+ }
151
+ }
152
+ return should_exit;
153
+ });
154
+
139
155
for (Ref<StreamPeerTCP> &c : clients) {
140
- REQUIRE_EQ (poll (c ), Error::OK );
156
+ REQUIRE_EQ (c-> get_status ( ), StreamPeerTCP::STATUS_CONNECTED );
141
157
}
142
158
143
159
// Sending data from each client to server.
@@ -158,7 +174,10 @@ TEST_CASE("[TCPServer] When stopped shouldn't accept new connections") {
158
174
Ref<StreamPeerTCP> client = create_client (LOCALHOST, PORT);
159
175
Ref<StreamPeerTCP> client_from_server = accept_connection (server);
160
176
161
- REQUIRE_EQ (poll (client), Error::OK);
177
+ wait_for_condition ([&]() {
178
+ return client->poll () != Error::OK || client->get_status () == StreamPeerTCP::STATUS_CONNECTED;
179
+ });
180
+
162
181
CHECK_EQ (client->get_status (), StreamPeerTCP::STATUS_CONNECTED);
163
182
164
183
// Sending data from client to server.
@@ -170,35 +189,37 @@ TEST_CASE("[TCPServer] When stopped shouldn't accept new connections") {
170
189
server->stop ();
171
190
CHECK_FALSE (server->is_listening ());
172
191
192
+ // Make sure the client times out in less than the wait time.
193
+ int timeout = ProjectSettings::get_singleton ()->get_setting (" network/limits/tcp/connect_timeout_seconds" );
194
+ ProjectSettings::get_singleton ()->set_setting (" network/limits/tcp/connect_timeout_seconds" , 1 );
195
+
173
196
Ref<StreamPeerTCP> new_client = create_client (LOCALHOST, PORT);
174
197
175
- // Required to get the connection properly established.
176
- uint64_t time = OS::get_singleton ()->get_ticks_usec ();
177
- while (!server->is_connection_available () && (OS::get_singleton ()->get_ticks_usec () - time ) < MAX_WAIT_USEC) {
178
- OS::get_singleton ()->delay_usec (SLEEP_DURATION);
179
- }
198
+ // Reset the timeout setting.
199
+ ProjectSettings::get_singleton ()->set_setting (" network/limits/tcp/connect_timeout_seconds" , timeout);
180
200
181
201
CHECK_FALSE (server->is_connection_available ());
182
202
183
- time = OS::get_singleton ()->get_ticks_usec ();
184
- Error err = new_client->poll ();
185
- while (err != Error::OK && err != Error::ERR_CONNECTION_ERROR && (OS::get_singleton ()->get_ticks_usec () - time ) < MAX_WAIT_USEC) {
186
- OS::get_singleton ()->delay_usec (SLEEP_DURATION);
187
- err = new_client->poll ();
188
- }
189
- REQUIRE ((err == Error::OK || err == Error::ERR_CONNECTION_ERROR));
190
- StreamPeerTCP::Status status = new_client->get_status ();
191
- CHECK ((status == StreamPeerTCP::STATUS_CONNECTING || status == StreamPeerTCP::STATUS_ERROR));
203
+ wait_for_condition ([&]() {
204
+ return new_client->poll () != Error::OK || new_client->get_status () == StreamPeerTCP::STATUS_ERROR;
205
+ });
192
206
207
+ CHECK_FALSE (server->is_connection_available ());
208
+
209
+ CHECK_EQ (new_client->get_status (), StreamPeerTCP::STATUS_ERROR);
193
210
new_client->disconnect_from_host ();
211
+ CHECK_EQ (new_client->get_status (), StreamPeerTCP::STATUS_NONE);
194
212
}
195
213
196
214
TEST_CASE (" [TCPServer] Should disconnect client" ) {
197
215
Ref<TCPServer> server = create_server (LOCALHOST, PORT);
198
216
Ref<StreamPeerTCP> client = create_client (LOCALHOST, PORT);
199
217
Ref<StreamPeerTCP> client_from_server = accept_connection (server);
200
218
201
- REQUIRE_EQ (poll (client), Error::OK);
219
+ wait_for_condition ([&]() {
220
+ return client->poll () != Error::OK || client->get_status () == StreamPeerTCP::STATUS_CONNECTED;
221
+ });
222
+
202
223
CHECK_EQ (client->get_status (), StreamPeerTCP::STATUS_CONNECTED);
203
224
204
225
// Sending data from client to server.
@@ -210,12 +231,23 @@ TEST_CASE("[TCPServer] Should disconnect client") {
210
231
server->stop ();
211
232
CHECK_FALSE (server->is_listening ());
212
233
213
- // Reading for a closed connection will print an error.
234
+ // Wait for disconnection
235
+ wait_for_condition ([&]() {
236
+ return client->poll () != Error::OK || client->get_status () == StreamPeerTCP::STATUS_NONE;
237
+ });
238
+
239
+ // Wait for disconnection
240
+ wait_for_condition ([&]() {
241
+ return client_from_server->poll () != Error::OK || client_from_server->get_status () == StreamPeerTCP::STATUS_NONE;
242
+ });
243
+
244
+ CHECK_EQ (client->get_status (), StreamPeerTCP::STATUS_NONE);
245
+ CHECK_EQ (client_from_server->get_status (), StreamPeerTCP::STATUS_NONE);
246
+
214
247
ERR_PRINT_OFF;
215
248
CHECK_EQ (client->get_string (), String ());
249
+ CHECK_EQ (client_from_server->get_string (), String ());
216
250
ERR_PRINT_ON;
217
- REQUIRE_EQ (poll (client), Error::OK);
218
- CHECK_EQ (client->get_status (), StreamPeerTCP::STATUS_NONE);
219
251
}
220
252
221
253
} // namespace TestTCPServer
0 commit comments