From 4fe25a880fd36a2d858f81b756c6fff2a0dc88dc Mon Sep 17 00:00:00 2001 From: David Baird Date: Thu, 13 Nov 2014 08:43:07 -0500 Subject: [PATCH] Add test code used to diagnose bug #37. --- Makefile | 5 +- test/Makefile | 11 +++ test/easywsclient.t.cpp | 167 ++++++++++++++++++++++++++++++++++++++++ test/testServer.js | 48 ++++++++++++ 4 files changed, 230 insertions(+), 1 deletion(-) create mode 100644 test/Makefile create mode 100644 test/easywsclient.t.cpp create mode 100644 test/testServer.js diff --git a/Makefile b/Makefile index b02c686..7bca648 100644 --- a/Makefile +++ b/Makefile @@ -1,9 +1,12 @@ CXXFLAGS = -std=gnu++0x -Wall LDLIBS = -lstdc++ -.PHONY: all clean +.PHONY: all clean test all: example-client example-client-cpp11 clean: -rm example-client example-client-cpp11 *.o + cd test; $(MAKE) clean +test: + cd test; $(MAKE) test testserver: node_modules node example-server.js node_modules: diff --git a/test/Makefile b/test/Makefile new file mode 100644 index 0000000..82796ee --- /dev/null +++ b/test/Makefile @@ -0,0 +1,11 @@ +CXXFLAGS = -std=gnu++1y -Wall -I.. +LDLIBS = -lstdc++ +.PHONY: all clean +test: easywsclient.t + node testServer.js & sleep 1 && ./easywsclient.t +clean: + -rm easywsclient.t *.o +vpath %.cpp ../ +vpath %.hpp ../ +easywsclient.t: easywsclient.t.o easywsclient.o +easywsclient.o: easywsclient.cpp easywsclient.hpp diff --git a/test/easywsclient.t.cpp b/test/easywsclient.t.cpp new file mode 100644 index 0000000..df1cadf --- /dev/null +++ b/test/easywsclient.t.cpp @@ -0,0 +1,167 @@ +#include "easywsclient.hpp" +#ifdef _WIN32 +#pragma comment( lib, "ws2_32" ) +#include +#endif +#include +#include +#include +#include +#include +#include +#include +#include + +using easywsclient::WebSocket; + +template +std::string toString(const T& t, size_t maxLen=32) +{ + std::stringstream ss; + ss << t; + std::string s = ss.str(); + if (s.length() > maxLen) { + return s.substr(0, maxLen-3) + "..."; + } + else { + return s; + } +} + +#define ASSERT_EQ(a, b) \ + if ((a) != (b)) { \ + std::cout << "Failed: " #a " == " #b "\n" \ + << "Expected: " << toString(b) << "\n" \ + << " Actual: " << toString(a) << "\n"; \ + throw std::runtime_error("test assertion failed"); \ + } + +namespace { + +#ifdef _WIN32 +class WSAInit +{ + public: + WSAInit() + { + INT rc; + WSADATA wsaData; + rc = WSAStartup(MAKEWORD(2, 2), &wsaData); + if (rc) { + throw std::runtime_error("WSAStartup failed"); + } + } + ~WSAInit() + { + WSACleanup(); + } +}; +#endif + +class KillServer +{ + public: + KillServer() : d_ws(WebSocket::from_url("ws://localhost:8123/killServer")) + { + assert(d_ws); + } + ~KillServer() + { + d_ws->send("exit"); // sending any message instructs the server to die + d_ws->poll(); + d_ws->poll(); + } + private: + std::unique_ptr d_ws; +}; + +std::string makeString(size_t length) +{ + std::vector v; + v.reserve(length + 1); + for (size_t i = 0; i < length; ++i) { + v.push_back('0' + (i % 10)); + } + v.push_back(0); + return &v[0]; +} + +} + +void test() +{ +#ifdef _WIN32 + WSAInit wsaInit; +#endif + KillServer killServer; + + std::unique_ptr ws(WebSocket::from_url("ws://localhost:8123/echoWithSize")); + assert(ws); + + ws->send("four"); + std::string message; + while (ws->getReadyState() != WebSocket::CLOSED) { + bool gotMessage = false; + ws->poll(); + ws->dispatch([gotMessageOut=&gotMessage, messageOut=&message, ws=ws.get()](const std::string& message) { + *gotMessageOut = true; + *messageOut = message; + }); + if (gotMessage) { + break; + } + } + ASSERT_EQ("4\nfour", message); + + std::vector > v; + v.emplace_back( "0", makeString(0)); + v.emplace_back( "1", makeString(1)); + v.emplace_back( "123", makeString(123)); + v.emplace_back( "124", makeString(124)); + v.emplace_back( "125", makeString(125)); + v.emplace_back( "126", makeString(126)); + v.emplace_back( "127", makeString(127)); + v.emplace_back( "128", makeString(128)); + v.emplace_back("10000", makeString(10000)); + v.emplace_back("32767", makeString(32767)); + v.emplace_back("65500", makeString(65500)); + v.emplace_back("65529", makeString(65529)); + v.emplace_back("65530", makeString(65530)); + v.emplace_back("65531", makeString(65531)); + v.emplace_back("65532", makeString(65532)); + v.emplace_back("65533", makeString(65533)); + v.emplace_back("65534", makeString(65534)); + v.emplace_back("65535", makeString(65535)); + v.emplace_back("65536", makeString(65536)); + v.emplace_back("65537", makeString(65537)); + + for (auto i = v.begin(); i != v.end(); ++i) { + ws->send(i->second); + std::string message; + while (ws->getReadyState() != WebSocket::CLOSED) { + bool gotMessage = false; + ws->poll(); + ws->dispatch([gotMessageOut=&gotMessage, messageOut=&message, ws=ws.get()](const std::string& message) { + *gotMessageOut = true; + *messageOut = message; + }); + if (gotMessage) { + break; + } + } + ASSERT_EQ(i->first + "\n" + i->second, message); + } + + ws->close(); +} + +int main() +{ + try { + test(); + } + catch (...) { + throw; + } + return 0; +} diff --git a/test/testServer.js b/test/testServer.js new file mode 100644 index 0000000..3653edb --- /dev/null +++ b/test/testServer.js @@ -0,0 +1,48 @@ +/* + Prerequisites: + + 1. Install node.js and npm + 2. npm install ws + + See also, + + http://einaros.github.com/ws/ + + To run, + + node example-server.js +*/ + +"use strict"; // http://ejohn.org/blog/ecmascript-5-strict-mode-json-and-more/ +var WebSocketServer = require('ws').Server; +var http = require('http'); +var app = http.createServer(); +var server; // assigned by app.listen() below + +var wssEchoWithSize = new WebSocketServer({server: app, path: '/echoWithSize'}); +wssEchoWithSize.on('connection', function(ws) { + ws.on('message', function(data, flags) { + if (flags.binary) { return; } + ws.send(data.length + '\n' + data); + }); + ws.on('close', function() { + }); + ws.on('error', function(e) { + }); +}); + +var wssKillServer = new WebSocketServer({server: app, path: '/killServer'}); +wssKillServer.on('connection', function(ws) { + ws.on('message', function(data, flags) { + if (flags.binary) { return; } + server.close(); + }); + ws.on('close', function() { + }); + ws.on('error', function(e) { + }); +}); + +var PORT = parseInt(process.env.PORT || '8123'); +server = app.listen(PORT); +console.log('Listening on port ' + PORT + '...');