The occasionally failing test
This piece of code is part of a test that runs a scenario, and checks that the appropriate errors are logged. Very occasionally, this test would fail, and it would be nearly impossible to figure out why.
I’ve extracted the offending code from the test, ReadFromWebSocket returns a Task<string>, since that isn’t obvious from the code. Do you see the error?
Think about it, what is this doing?
This is reading from a socket, and there is absolutely no guarantee about the amount of data that will go over the wire in any particular point. Because this test assumes that the entire string will be read in a single call from the socket, if the expected value we are looking is actually going to be returned in two calls, we’ll miss it, and this will never return, leading to sadness and worry everywhere*.
* At least everywhere that care about our tests.
The fix was to remember the previous values and compare to all the data read from the socket, not just the values that were returned in the last call.
Comments
Me think you should have unit tests for your unit tests.
That sounds N^2 to me... Maybe it doesn't matter due to the size of the strings from the socket?
I like this aspect, that such occasionally failing tests forces to think, examine code, learn. And there's a chance that later one can use that knowledge in production code, don't do this kind of difficult bug on production. Better to do such type o bug in tests and fix it on tests, that on production, that's my point. Tests gives developer another - additional perspective on production code.
newt0311, This is a test that is expected to have roughly 1KB of text at the very high end. It is not meaningful difference.
I'm confused because web sockets (unlike plain old TCP sockets) are message-based rather than a bare stream of bytes. I'd therefore have expected a method called
ReadFromWebSocket
to read a whole websocket frame and therefore not to suffer from message fragmentation like this. Had it not mentioned web sockets I'd be less confused.David, WebSocket indeed work this way, but they are still using buffering. You may get partial message from the call, and need to check the "end of message" flag to know when you are done.
In practice, I find it easier to just treat web sockets are regular sockets and not bother with the messages.
Definitely interesting. The assumptions look reasonable at a glance but once explained, the flaw is clear. Interesting reading as always.
Quick, off topic question. What is the purpose of the cast in
```C# var task = Task.Run((Func<Task>)(async () => { await ... }));
Is this just a matter of style or is there a behavioral difference I am not aware of?
Ouch, massive formatting failure in my comment. Sorry about that.
Aluan, IIRC, there is an issue with selecting the right overload here, we want to force it to use the
async Task
and notasync void
.Comment preview