diff options
Diffstat (limited to 'framework/src/onos/web/gui/src/test/_karma/mockserver.js')
-rw-r--r-- | framework/src/onos/web/gui/src/test/_karma/mockserver.js | 361 |
1 files changed, 361 insertions, 0 deletions
diff --git a/framework/src/onos/web/gui/src/test/_karma/mockserver.js b/framework/src/onos/web/gui/src/test/_karma/mockserver.js new file mode 100644 index 00000000..23b468b0 --- /dev/null +++ b/framework/src/onos/web/gui/src/test/_karma/mockserver.js @@ -0,0 +1,361 @@ +#!/usr/bin/env node + +// === Mock Web Socket Server - for testing the topology view + +var fs = require('fs'), + readline = require('readline'), + http = require('http'), + WebSocketServer = require('websocket').server, + port = 8123, + scenarioRoot = 'ev/', + verbose = false, // show received messages from client + extraVerbose = false; // show ALL received messages from client + +var lastcmd, // last command executed + lastargs, // arguments to last command + connection, // ws connection + origin, // origin of connection + scid, // scenario ID + scdata, // scenario data + scdone, // shows when scenario is over + eventsById, // map of event file names + maxEvno, // highest loaded event number + autoLast, // last event number for auto-advance + evno, // next event number + evdata; // event data + + +process.argv.forEach(function (val) { + switch (val) { + case '-v': verbose = true; break; + case '-v!': extraVerbose = true; break; + } +}); + +var scFiles = fs.readdirSync(scenarioRoot); +console.log(); +console.log('Mock Server v1.0'); +if (verbose || extraVerbose) { + console.log('Verbose=' + verbose, 'ExtraVerbose=' + extraVerbose); +} +console.log('================'); +listScenarios(); + +var rl = readline.createInterface(process.stdin, process.stdout); +rl.setPrompt('ws> '); + + +var server = http.createServer(function(request, response) { + console.log((new Date()) + ' Received request for ' + request.url); + response.writeHead(404); + response.end(); +}); + +server.listen(port, function() { + console.log((new Date()) + ' Server is listening on port ' + port); +}); + +server.on('listening', function () { + console.log('OK, server is running'); + console.log('(? for help)'); +}); + +var wsServer = new WebSocketServer({ + httpServer: server, + // You should not use autoAcceptConnections for production + // applications, as it defeats all standard cross-origin protection + // facilities built into the protocol and the browser. You should + // *always* verify the connection's origin and decide whether or not + // to accept it. + autoAcceptConnections: false +}); + +function originIsAllowed(origin) { + // put logic here to detect whether the specified origin is allowed. + return true; +} + +// displays the message if our arguments say we should +function displayMsg(msg) { + var ev = JSON.parse(msg); + switch (ev.event) { + case 'topoHeartbeat': return extraVerbose; + default: return true; + } +} + +wsServer.on('request', function(request) { + console.log(); // newline after prompt + console.log("Origin: ", request.origin); + + if (!originIsAllowed(request.origin)) { + // Make sure we only accept requests from an allowed origin + request.reject(); + console.log((new Date()) + ' Connection from origin ' + request.origin + ' rejected.'); + return; + } + + origin = request.origin; + connection = request.accept(null, origin); + + + console.log((new Date()) + ' Connection accepted.'); + rl.prompt(); + + connection.on('message', function(message) { + if (verbose || extraVerbose) { + if (message.type === 'utf8') { + if (displayMsg(message.utf8Data)) { + console.log(); // newline after prompt + console.log('Received Message: ' + message.utf8Data); + } + //connection.sendUTF(message.utf8Data); + rl.prompt(); + } + else if (message.type === 'binary') { + console.log('Received Binary Message of ' + message.binaryData.length + ' bytes'); + //connection.sendBytes(message.binaryData); + } + } + }); + connection.on('close', function(reasonCode, description) { + console.log((new Date()) + ' Peer ' + connection.remoteAddress + ' disconnected.'); + connection = null; + origin = null; + }); +}); + + +setTimeout(doCli, 10); // allow async processes to write to stdout first + +function doCli() { + rl.prompt(); + rl.on('line', function (line) { + var words = line.trim().split(' '), + cmd = words.shift(), + str = words.join(' '); + + if (!cmd) { + // repeat last command + cmd = lastcmd; + str = lastargs; + } + + switch(cmd) { + case 'l': listScenarios(); break; + case 'c': connStatus(); break; + case 'm': customMessage(str); break; + case 's': setScenario(str); break; + case 'a': autoAdvance(); break; + case 'n': nextEvent(); break; + case 'r': restartScenario(); break; + case 'q': quit(); break; + case '?': showHelp(); break; + default: console.log('Say what?! (? for help)'); break; + } + lastcmd = cmd; + lastargs = str; + rl.prompt(); + + }).on('close', function () { + quit(); + }); +} + +var helptext = '\n' + + 'l - list scenarios\n' + + 'c - show connection status\n' + + 'm {text} - send custom message to client\n' + + 's {id} - load scenario {id}\n' + + 's - show scenario status\n' + + 'a - auto-send events\n' + + 'n - send next event\n' + + 'r - restart the scenario\n' + + 'q - exit the server\n' + + '? - display this help text\n'; + +function showHelp() { + console.log(helptext); +} + +function listScenarios() { + console.log('Scenarios ...'); + console.log(scFiles.join(', ')); + console.log(); +} + +function connStatus() { + if (connection) { + console.log('Connection from ' + origin + ' established.'); + } else { + console.log('No connection.'); + } +} + +function quit() { + console.log('Quitting...'); + process.exit(0); +} + +function customMessage(m) { + if (connection) { + console.log('Sending message: ' + m); + connection.sendUTF(m); + } else { + console.warn('No current connection.'); + } +} + +function showScenarioStatus() { + var msg; + if (!scid) { + console.log('No scenario loaded.'); + } else { + msg = 'Scenario: "' + scid + '", ' + + (scdone ? 'DONE' : 'next event: ' + evno); + console.log(msg); + } +} + +function scenarioPath(evno) { + var file = evno ? ('/' + eventsById[evno].fname) : '/scenario.json'; + return scenarioRoot + scid + file; +} + + +function initScenario(verb) { + console.log(); // get past prompt + console.log(verb + ' scenario "' + scid + '"'); + console.log(scdata.title); + scdata.description.forEach(function (d) { + console.log(' ' + d); + }); + autoLast = (scdata.params && scdata.params.lastAuto) || 0; + if (autoLast) { + console.log('[auto-advance: ' + autoLast + ']'); + } + evno = 1; + scdone = false; + readEventFilenames(); +} + +function readEventFilenames() { + var files = fs.readdirSync(scenarioRoot + scid), + eventCount = 0, + match, id, tag; + + maxEvno = 0; + + eventsById = {}; + files.forEach(function (f) { + match = /^ev_(\d+)_(.*)\.json$/.exec(f); + if (match) { + eventCount++; + id = match[1]; + tag = match[2]; + eventsById[id] = { + fname: f, + num: id, + tag: tag + }; + if (Number(id) > Number(maxEvno)) { + maxEvno = id; + } + } + + }); + console.log('[' + eventCount + ' events loaded, (max=' + maxEvno + ')]'); +} + +function setScenario(id) { + if (!id) { + return showScenarioStatus(); + } + + evdata = null; + scid = id; + fs.readFile(scenarioPath(), 'utf8', function (err, data) { + if (err) { + console.warn('No scenario named "' + id + '"', err); + scid = null; + } else { + scdata = JSON.parse(data); + initScenario('Loading'); + } + rl.prompt(); + }); +} + +function restartScenario() { + if (!scid) { + console.log('No scenario loaded.'); + } else { + initScenario('Restarting'); + } + rl.prompt(); +} + +function eventAvailable() { + if (!scid) { + console.log('No scenario loaded.'); + rl.prompt(); + return false; + } + + if (!connection) { + console.log('No current connection.'); + rl.prompt(); + return false; + } + + if (Number(evno) > Number(maxEvno)) { + scdone = true; + console.log('Scenario DONE.'); + return false; + } + return true; +} + +function autoAdvance() { + if (evno > autoLast) { + console.log('[auto done]'); + return; + } + + // need to recurse with a callback, since each event send relies + // on an async load of event data... + function callback() { + if (eventAvailable() && evno <= autoLast) { + _nextEvent(callback); + } + } + + callback(); +} + +function nextEvent() { + if (eventAvailable()) { + _nextEvent(); + } +} + +function _nextEvent(callback) { + var path = scenarioPath(evno); + + fs.readFile(path, 'utf8', function (err, data) { + if (err) { + console.error('Oops error: ' + err); + } else { + evdata = JSON.parse(data); + console.log(); // get past prompt + console.log('Sending event #' + evno + ' [' + evdata.event + + '] from ' + eventsById[evno].fname); + connection.sendUTF(data); + evno++; + if (callback) { + callback(); + } + } + rl.prompt(); + }); +} |