use dynamically generated port number to configure servers in unittest

This commit is contained in:
Benjamin Sergeant 2019-01-28 15:14:49 -08:00
parent 7eaea28970
commit 8983dd97a1
9 changed files with 93 additions and 15 deletions

View File

@ -5,5 +5,5 @@ compiler:
- clang - clang
# - gcc # - gcc
# os: osx # os: osx
script: make test script: python test/run.py

View File

@ -156,7 +156,9 @@ namespace ix
_onCloseCallback = onCloseCallback; _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<std::mutex> lock(_lastSendTimePointMutex); std::lock_guard<std::mutex> lock(_lastSendTimePointMutex);
auto now = std::chrono::steady_clock::now(); auto now = std::chrono::steady_clock::now();
@ -172,7 +174,7 @@ namespace ix
// send for a duration exceeding our heart-beat period, send a // send for a duration exceeding our heart-beat period, send a
// ping to the server. // ping to the server.
if (pollResult == PollResultType_Timeout && if (pollResult == PollResultType_Timeout &&
exceedSendHeartBeatTimeOut()) heartBeatPeriodExceeded())
{ {
std::stringstream ss; std::stringstream ss;
ss << kHeartBeatPingMessage << "::" << _heartBeatPeriod << "s"; ss << kHeartBeatPingMessage << "::" << _heartBeatPeriod << "s";

View File

@ -126,7 +126,7 @@ namespace ix
std::chrono::time_point<std::chrono::steady_clock> _lastSendTimePoint; std::chrono::time_point<std::chrono::steady_clock> _lastSendTimePoint;
// No data was send through the socket for longer that the hearbeat period // No data was send through the socket for longer that the hearbeat period
bool exceedSendHeartBeatTimeOut(); bool heartBeatPeriodExceeded();
void sendOnSocket(); void sendOnSocket();
WebSocketSendInfo sendData(wsheader_type::opcode_type type, WebSocketSendInfo sendData(wsheader_type::opcode_type type,

View File

@ -6,6 +6,7 @@
#include "IXTest.h" #include "IXTest.h"
#include <ixwebsocket/IXWebSocket.h> #include <ixwebsocket/IXWebSocket.h>
#include <ixwebsocket/IXNetSystem.h>
#include <chrono> #include <chrono>
#include <thread> #include <thread>
@ -14,12 +15,14 @@
#include <fstream> #include <fstream>
#include <iostream> #include <iostream>
#include <stdlib.h> #include <stdlib.h>
#include <stack>
namespace ix namespace ix
{ {
std::atomic<size_t> incomingBytes(0); std::atomic<size_t> incomingBytes(0);
std::atomic<size_t> outgoingBytes(0); std::atomic<size_t> outgoingBytes(0);
std::mutex Logger::_mutex; std::mutex Logger::_mutex;
std::stack<int> freePorts;
void setupWebSocketTrafficTrackerCallback() void setupWebSocketTrafficTrackerCallback()
{ {
@ -66,4 +69,52 @@ namespace ix
Logger() << msg; 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;
}
} }

View File

@ -51,4 +51,7 @@ namespace ix
}; };
void log(const std::string& msg); void log(const std::string& msg);
bool computeFreePorts(int count);
int getFreePort();
} }

View File

@ -180,7 +180,7 @@ TEST_CASE("Websocket_heartbeat", "[heartbeat]")
{ {
ix::setupWebSocketTrafficTrackerCallback(); ix::setupWebSocketTrafficTrackerCallback();
int port = 8093; int port = getFreePort();
ix::WebSocketServer server(port); ix::WebSocketServer server(port);
std::atomic<int> serverReceivedPingMessages(0); std::atomic<int> serverReceivedPingMessages(0);
REQUIRE(startServer(server, serverReceivedPingMessages)); REQUIRE(startServer(server, serverReceivedPingMessages));

View File

@ -75,7 +75,7 @@ TEST_CASE("Websocket_server", "[websocket_server]")
{ {
SECTION("Connect to the server, do not send anything. Should timeout and return 400") SECTION("Connect to the server, do not send anything. Should timeout and return 400")
{ {
int port = 8091; int port = getFreePort();
ix::WebSocketServer server(port); ix::WebSocketServer server(port);
REQUIRE(startServer(server)); 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") SECTION("Connect to the server. Send GET request without header. Should return 400")
{ {
int port = 8092; int port = getFreePort();
ix::WebSocketServer server(port); ix::WebSocketServer server(port);
REQUIRE(startServer(server)); REQUIRE(startServer(server));
@ -142,7 +142,7 @@ TEST_CASE("Websocket_server", "[websocket_server]")
SECTION("Connect to the server. Send GET request with correct header") SECTION("Connect to the server. Send GET request with correct header")
{ {
int port = 8093; int port = getFreePort();
ix::WebSocketServer server(port); ix::WebSocketServer server(port);
REQUIRE(startServer(server)); REQUIRE(startServer(server));

View File

@ -4,6 +4,11 @@
* Copyright (c) 2017 Machine Zone. All rights reserved. * 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 <iostream> #include <iostream>
#include <sstream> #include <sstream>
#include <queue> #include <queue>
@ -24,7 +29,8 @@ namespace
{ {
public: public:
WebSocketChat(const std::string& user, WebSocketChat(const std::string& user,
const std::string& session); const std::string& session,
int port);
void subscribe(const std::string& channel); void subscribe(const std::string& channel);
void start(); void start();
@ -40,6 +46,7 @@ namespace
private: private:
std::string _user; std::string _user;
std::string _session; std::string _session;
int _port;
ix::WebSocket _webSocket; ix::WebSocket _webSocket;
@ -47,9 +54,11 @@ namespace
}; };
WebSocketChat::WebSocketChat(const std::string& user, WebSocketChat::WebSocketChat(const std::string& user,
const std::string& session) : const std::string& session,
int port) :
_user(user), _user(user),
_session(session) _session(session),
_port(port)
{ {
; ;
} }
@ -71,7 +80,16 @@ namespace
void WebSocketChat::start() 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); _webSocket.setUrl(url);
std::stringstream ss; std::stringstream ss;
@ -226,8 +244,8 @@ TEST_CASE("Websocket_chat", "[websocket_chat]")
REQUIRE(startServer(server)); REQUIRE(startServer(server));
std::string session = ix::generateSessionId(); std::string session = ix::generateSessionId();
WebSocketChat chatA("jean", session); WebSocketChat chatA("jean", session, port);
WebSocketChat chatB("paul", session); WebSocketChat chatB("paul", session, port);
chatA.start(); chatA.start();
chatB.start(); chatB.start();

View File

@ -34,6 +34,10 @@ if osName == 'Linux':
sanitizerFlags = sanitizersFlags[sanitizer] 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) cmakeCmd = 'cmake -DCMAKE_BUILD_TYPE=Debug {} {} ..'.format(generator, sanitizerFlags)
print(cmakeCmd) print(cmakeCmd)
ret = os.system(cmakeCmd) ret = os.system(cmakeCmd)