I am writing some unit tests, and the aim of it is that i have a websocket server running and the unit tests are http clients that connect to said server and ensure that responses correspond to requests.
So the main flow i am looking for is along the lines of :
- Start server
- Run test X
- Stop server
And this is basically repeated for test Y/Z/A/B
The code i have is like this:
#define WEBSOCKET_SERVER_IPV4 "127.0.0.1"
#define WEBSOCKET_SERVER_PORT "3000"
#define WEBSOCKETSECURE_SERVER_IPV4 "127.0.0.1"
#define WEBSOCKETSECURE_SERVER_PORT "3001"
class WebSocketT : public ::testing ::Test{
public:
WebSocketT(){
printf(">>>>>>---START WS SERVER---\n");
ConfigManager *cf = new ConfigManager("/opt/ra/la-d.conf");
pid_t pid = fork();
if (pid == 0){
main_websocket_process(cf);
exit(EXIT_SUCCESS);
}else if (pid > 0){
ws_child = pid;
started = 1;
printf("started child: %i", (int)pid);
}
else {
printf("fork failed");
exit(EXIT_FAILURE);
}
sleep(5);
}
~WebSocketT(){
if (started != 0){
if (kill (ws_child, SIGKILL) != 0){
printf("ERROR kill: %s", strerror(errno));
} else printf("killed");
sleep(3);
}
}
private:
pid_t ws_child;
};
/**
* Test can connect normal
*/
TEST_F(WebSocketT, connect_normal){
// FILE* ecgwsd_fp = popen("/opt/ra/ecgwsd/bin/ecgwsd /opt/ra/ecgwsd/default.conf &", "r"); sleep(3);
Hub h;
bool got_open_message= false;
h.onMessage([&got_open_message](WebSocket<CLIENT> *ws, char *message, size_t length, OpCode opCode){
if (length == 13821){
got_open_message = true;
ASSERT_EQ(strncmp(message, "{\"softw", 7), 0);
}
if (got_open_message == true) ws->close();
fflush(stdout);
});
h.onConnection([](WebSocket<uWS::CLIENT> *ws, HttpRequest req){
//ws->send("{}");
ws->send(ws_json_open.c_str(), ws_json_open.length(), OpCode::TEXT);
});
h.onDisconnection([](WebSocket<uWS::CLIENT> *ws, int code, char *message, size_t length){
//nothign
});
h.onError([](void * u){
printf("ERROR in websocket connection");
FAIL();
});
h.connect("ws://" WEBSOCKET_SERVER_IPV4 ":" WEBSOCKET_SERVER_PORT "/TESTSTS", nullptr );
h.run();
};
/**
* Test can connect secure
*/
TEST_F(WebSocketT, connect_secure){
Hub h;
bool ssl_connected = false;
h.onMessage([](WebSocket<SERVER> *ws, char *message, size_t length, OpCode opCode){
printf("Was a message");
});
h.onConnection([&ssl_connected](WebSocket<uWS::CLIENT> *ws, HttpRequest req){
//ws->send("{}");
ssl_connected = true;
ws->close();
});
h.onDisconnection([&ssl_connected](WebSocket<uWS::CLIENT> *ws, int code, char *message, size_t length){
ASSERT_EQ(ssl_connected, true);
});
h.onError([](void * u){
printf("ERROR in websocket secure connection, %s", (char*) u);
FAIL();
});
h.connect("wss://" WEBSOCKETSECURE_SERVER_IPV4 ":" WEBSOCKETSECURE_SERVER_PORT "/", nullptr );
h.run();
};
So here our test X is: normal/secure
The problem is that when i run this, connect_normal can connect to the server, but connect_secure cant. If i comment out the connect_normal, than connect secure works.
I have also tried fixing this problem by compiling the websocket server as a seperate binary and than running it as "/path/to/binary/websocket_server --port=3242 &" in the continous integration configuration for gitlab. That has the exact same issue.
The only way i can solve this is by creating a seperate binary which can run as a seperate executable by itself, than in the beginning of every test case i run the executable with popen ("/path/to/websocket/server --port=3434 &", "r"); sleep(3);
the sleep is to allow the server some time to start up. This seperate binary runs "main_websocket_process" also, but inside a main function (+ logging + signal handling) - so logically it should do the same thing as above in terms of websocket activities.
Using popen and sleep just seems quite dirty, so is there some way to run this server cleanly for each test case? writing a mock for the server is not practical. Also why does the above code work with a single test case but fail with the next one? should it run the constructor and destructor on each test case?
Aucun commentaire:
Enregistrer un commentaire