diff --git a/.travis.yml b/.travis.yml index 4dfb451e..62bcde55 100644 --- a/.travis.yml +++ b/.travis.yml @@ -5,5 +5,5 @@ compiler: - clang # - gcc - # os: osx -script: make test +# os: osx +script: python test/run.py diff --git a/ixwebsocket/IXWebSocketTransport.cpp b/ixwebsocket/IXWebSocketTransport.cpp index 15b155f8..bbdee50d 100644 --- a/ixwebsocket/IXWebSocketTransport.cpp +++ b/ixwebsocket/IXWebSocketTransport.cpp @@ -156,7 +156,9 @@ namespace ix _onCloseCallback = onCloseCallback; } - bool WebSocketTransport::exceedSendHeartBeatTimeOut() + // Only consider send time points for that computation. + // The receive time points is taken into account in Socket::poll (second parameter). + bool WebSocketTransport::heartBeatPeriodExceeded() { std::lock_guard lock(_lastSendTimePointMutex); auto now = std::chrono::steady_clock::now(); @@ -172,7 +174,7 @@ namespace ix // send for a duration exceeding our heart-beat period, send a // ping to the server. if (pollResult == PollResultType_Timeout && - exceedSendHeartBeatTimeOut()) + heartBeatPeriodExceeded()) { std::stringstream ss; ss << kHeartBeatPingMessage << "::" << _heartBeatPeriod << "s"; diff --git a/ixwebsocket/IXWebSocketTransport.h b/ixwebsocket/IXWebSocketTransport.h index 90585c78..86fba38a 100644 --- a/ixwebsocket/IXWebSocketTransport.h +++ b/ixwebsocket/IXWebSocketTransport.h @@ -126,7 +126,7 @@ namespace ix std::chrono::time_point _lastSendTimePoint; // No data was send through the socket for longer that the hearbeat period - bool exceedSendHeartBeatTimeOut(); + bool heartBeatPeriodExceeded(); void sendOnSocket(); WebSocketSendInfo sendData(wsheader_type::opcode_type type, diff --git a/test/IXTest.cpp b/test/IXTest.cpp index dddaaeda..7a9c1096 100644 --- a/test/IXTest.cpp +++ b/test/IXTest.cpp @@ -6,6 +6,7 @@ #include "IXTest.h" #include +#include #include #include @@ -14,12 +15,14 @@ #include #include #include +#include namespace ix { std::atomic incomingBytes(0); std::atomic outgoingBytes(0); std::mutex Logger::_mutex; + std::stack freePorts; void setupWebSocketTrafficTrackerCallback() { @@ -66,4 +69,52 @@ namespace ix Logger() << msg; } + int getFreePort() + { + int defaultPort = 8090; + + int sockfd; + if ((sockfd = socket(AF_INET, SOCK_STREAM, 0)) < 0) + { + log("Cannot compute a free port. socket error."); + return defaultPort; + } + + int enable = 1; + if (setsockopt(sockfd, SOL_SOCKET, SO_REUSEADDR, + (char*) &enable, sizeof(enable)) < 0) + { + log("Cannot compute a free port. setsockopt error."); + return defaultPort; + } + + // Bind to port 0. This is the standard way to get a free port. + struct sockaddr_in server; // server address information + server.sin_family = AF_INET; + server.sin_port = htons(0); + server.sin_addr.s_addr = inet_addr("127.0.0.1"); + + if (bind(sockfd, (struct sockaddr *)&server, sizeof(server)) < 0) + { + log("Cannot compute a free port. bind error."); + + ::close(sockfd); + return defaultPort; + } + + struct sockaddr_in sa; // server address information + unsigned int len; + if (getsockname(sockfd, (struct sockaddr *) &sa, &len) < 0) + { + log("Cannot compute a free port. getsockname error."); + + ::close(sockfd); + return defaultPort; + } + + int port = ntohs(sa.sin_port); + ::close(sockfd); + + return port; + } } diff --git a/test/IXTest.h b/test/IXTest.h index 12022bfe..89bb57cf 100644 --- a/test/IXTest.h +++ b/test/IXTest.h @@ -51,4 +51,7 @@ namespace ix }; void log(const std::string& msg); + + bool computeFreePorts(int count); + int getFreePort(); } diff --git a/test/IXWebSocketHeartBeatTest.cpp b/test/IXWebSocketHeartBeatTest.cpp index cc1d5510..67301065 100644 --- a/test/IXWebSocketHeartBeatTest.cpp +++ b/test/IXWebSocketHeartBeatTest.cpp @@ -180,7 +180,7 @@ TEST_CASE("Websocket_heartbeat", "[heartbeat]") { ix::setupWebSocketTrafficTrackerCallback(); - int port = 8093; + int port = getFreePort(); ix::WebSocketServer server(port); std::atomic serverReceivedPingMessages(0); REQUIRE(startServer(server, serverReceivedPingMessages)); diff --git a/test/IXWebSocketServerTest.cpp b/test/IXWebSocketServerTest.cpp index ea425b5d..7a3c1607 100644 --- a/test/IXWebSocketServerTest.cpp +++ b/test/IXWebSocketServerTest.cpp @@ -75,7 +75,7 @@ TEST_CASE("Websocket_server", "[websocket_server]") { SECTION("Connect to the server, do not send anything. Should timeout and return 400") { - int port = 8091; + int port = getFreePort(); ix::WebSocketServer server(port); REQUIRE(startServer(server)); @@ -107,7 +107,7 @@ TEST_CASE("Websocket_server", "[websocket_server]") SECTION("Connect to the server. Send GET request without header. Should return 400") { - int port = 8092; + int port = getFreePort(); ix::WebSocketServer server(port); REQUIRE(startServer(server)); @@ -142,7 +142,7 @@ TEST_CASE("Websocket_server", "[websocket_server]") SECTION("Connect to the server. Send GET request with correct header") { - int port = 8093; + int port = getFreePort(); ix::WebSocketServer server(port); REQUIRE(startServer(server)); diff --git a/test/cmd_websocket_chat.cpp b/test/cmd_websocket_chat.cpp index b3a49f45..5a91cde2 100644 --- a/test/cmd_websocket_chat.cpp +++ b/test/cmd_websocket_chat.cpp @@ -4,6 +4,11 @@ * Copyright (c) 2017 Machine Zone. All rights reserved. */ +// +// Simple chat program that talks to the node.js server at +// websocket_chat_server/broacast-server.js +// + #include #include #include @@ -24,7 +29,8 @@ namespace { public: WebSocketChat(const std::string& user, - const std::string& session); + const std::string& session, + int port); void subscribe(const std::string& channel); void start(); @@ -40,6 +46,7 @@ namespace private: std::string _user; std::string _session; + int _port; ix::WebSocket _webSocket; @@ -47,9 +54,11 @@ namespace }; WebSocketChat::WebSocketChat(const std::string& user, - const std::string& session) : + const std::string& session, + int port) : _user(user), - _session(session) + _session(session), + _port(port) { ; } @@ -71,7 +80,16 @@ namespace void WebSocketChat::start() { - std::string url("ws://localhost:8090/"); + std::string url; + { + std::stringstream ss; + ss << "ws://localhost:" + << _port + << "/"; + + url = ss.str(); + } + _webSocket.setUrl(url); std::stringstream ss; @@ -226,8 +244,8 @@ TEST_CASE("Websocket_chat", "[websocket_chat]") REQUIRE(startServer(server)); std::string session = ix::generateSessionId(); - WebSocketChat chatA("jean", session); - WebSocketChat chatB("paul", session); + WebSocketChat chatA("jean", session, port); + WebSocketChat chatB("paul", session, port); chatA.start(); chatB.start(); diff --git a/test/run.py b/test/run.py index 49586b1f..d4a3e214 100644 --- a/test/run.py +++ b/test/run.py @@ -34,6 +34,10 @@ if osName == 'Linux': sanitizerFlags = sanitizersFlags[sanitizer] +# if osName == 'Windows': +# os.environ['CC'] = 'clang-cl' +# os.environ['CXX'] = 'clang-cl' + cmakeCmd = 'cmake -DCMAKE_BUILD_TYPE=Debug {} {} ..'.format(generator, sanitizerFlags) print(cmakeCmd) ret = os.system(cmakeCmd)