-
-
Notifications
You must be signed in to change notification settings - Fork 21.2k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Add unit tests for TCPServer #97262
base: master
Are you sure you want to change the base?
Add unit tests for TCPServer #97262
Conversation
1618d75
to
03f913b
Compare
03f913b
to
0e9c698
Compare
tests/core/io/test_tcp_server.h
Outdated
// Required to get the connection properly established. | ||
OS::get_singleton()->delay_usec(500000); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It's always recommended to poll
while waiting
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Could you please elaborate a little bit more?
A couple of lines below I'm calling client->poll()
, so maybe I'm not fully getting how should I use poll
.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@pafuent Great work and thanks for working on this! Not Fabio, and he may correct me, but:
Polling is what allows the connection (or underlying socket) to execute and do actual work. They don't run by themselves in parallel in threads or anything, they literally only do work when polled.
The server polls its socket when calling server->is_connection_available()
(see here; I think we should actually point this one out more directly in TCPServer docs, looking at it), the client as you point out with client->poll()
.
This means that it is good practice to poll as regularly as possible, because the longer the time between polls:
- the higher the chance networking buffers may fill up/overrun and you lose packets/get errors
- the higher the chance you process messages too late (if you were to poll, say, every five seconds, you may end up processing information from 4 seconds ago that is by now outdated and no longer relevant, you don't really need the player's movement update from 4 seconds ago)
- the longer the connection appears to "hang" for the other side, as they won't get a packet response until you poll
- as per the above, this also introduces problems in transit, especially for TCP (which is not "fire and forget" like UDP), because both your node, the remote node and any node in between could decide your connection is dead because there has been no traffic, so why not kill the connection to free up resources? I.e., timeouts/connection terminations may happen, usually only with very high poll times, of course :)
Of course, all this is a bit more theoretical and "best practice" than 100% applicable to a test case like this. Instead of waiting arbitrarily for half a second, you could replace that with a loop that sleeps, say, 1000usecs, and then polls both client and server each time until you get your desired result (StreamPeerTCP::STATUS_CONNECTED
), an error, or you run longer then expected and time out/fail the test.
Currently, this doesn't poll the connections for half a second, which means both ends don't process any network traffic for that time, which can be an eternity in networking. So, not really a good practice, although it works in this case because everything is local anyway and there is not much traffic.
Or, stated in another way: this test currently likely breaks if networking timeouts are set below 0.5 seconds (Which, granted, is pretty theoretical, but a local connection also should work faster than that) or we send more data and buffers are too small.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks for the amazing explanation!!!
In my case I needed to add that sleep because when I called poll
or other method that does that internally I was getting a wrong return code or value. IIRC that was happening on Windows, but not on Mac or Linux.
Besides of that, if you think that it's worth it for the tests, I can try to change them to poll on a for loop with a smaller sleep time.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
In my case I needed to add that sleep because when I called
poll
or other method that does that internally I was getting a wrong return code or value.
Indeed, the problem here is that you keep blocking for a long time and only poll once, while you should only block for brief periods of time and regularly poll (i.e. multiple times), or you risk of having the same error on other OS configurations.
1d6a9e6
to
edb7ee8
Compare
edb7ee8
to
22cb110
Compare
Friendly remainder |
22cb110
to
0352e6e
Compare
0352e6e
to
e9cba19
Compare
I updated the test to only block for brief periods of time and regularly poll. Can I get the tests reviewed again? |
This PR aims to help "fix" godotengine#43440
e9cba19
to
dffab3d
Compare
This PR aims to help "fix" #43440