How to simulate socket errors? (sometimes server or client disconnects because of some socket error and it is impossible to reproduce.) I was looking for a tool to do this, but I can't find one. Does anyone know either of a tool or has a code example on how to do this? (C# or C/C++)
Add a wrapper layer to the APIs you're using to access the sockets and have them fail rand() % 100 > x percent of the time.
I had exactly the same problem this summer.
I had a custom Socket
class and wanted to test what would happen if read
or write
threw an exception. I really wanted to mimic the Java mocking frameworks, and I did it like this:
I inherited the Socket
class into a FakeSocket
class, and created something called a SocketExpectation
. Then, in the unit tests, I created fake sockets, set up the expectations and then passed that fake socket to the code I wanted to test.
The FakeSocket
had these methods (stripped of unneeded details):
uint32_t write(buffer, length); // calls check
uint32_t read(buffer, length); // calls check
bool matches();
void expect(expectation);
uint32_t check(CallType, buffer, length) const;
They're all pretty straight forward. check
checks the arguments against the current expectation and if everything is according to plan, proceeds to perform the SocketExpectation
requirement.
The SocketExpectation
has this outline (also stripped):
typedef enum { write, read } CallType;
SocketExpectation(CallType type);
SocketExpectation &with_arguments(void *a1, uint32_t a2); // expects these args
SocketExpectation &will_return(uint32_t value);
SocketExpectation &will_throw(const char * e); // test error handling
bool matches();
I added more methods as I needed them. I would create it like this, then pass the fake socket to the relevant method:
fake_socket = FakeSocket();
fake_socket.expect(SocketExpectation(write).with_arguments(....).will_return(...));
fake_socket.expect(SocketExpectation(read).with_arguments(...).will_throw("something"));
My socket code unit tests are probably better described as integration tests as I drive the code under test to connect to a 'mock' remote peer. Since the remote peer is under the control of the test (it's simply a simple client or server) I can have the test cause the remote peer to disrupt the connection in various ways and then ensure that the code under test reacts as expected. It takes a little work to set up, but once you have all the pieces in place it makes it pretty trivial to test most situations.
So, I guess, my suggestion is that rather than attempting to simulate the situations that you're encountering you should understand them and then reliably generate them.