var WebSocket = require('ws'); var events = require('events'); if (typeof String.prototype.startsWith != 'function') { String.prototype.startsWith = function (str){ return this.indexOf(str) === 0; }; } describe('LoadTest', function () { // 30s timeout this.timeout(30000); // set the slow time to 5ms knowing each test takes more than that, // so the run time is always printed this.slow(5); var testsRan = 0, testsToRun = 500; tileSize = 256, tileSizeTwips = 3840, host = 'wss://localhost:9980'; var _parseServerCmd = function (msg) { var tokens = msg.split(/[ \n]+/); var command = {}; for (var i = 0; i < tokens.length; i++) { if (tokens[i].substring(0, 9) === 'tileposx=') { command.x = parseInt(tokens[i].substring(9)); } else if (tokens[i].substring(0, 9) === 'tileposy=') { command.y = parseInt(tokens[i].substring(9)); } else if (tokens[i].substring(0, 10) === 'tilewidth=') { command.tileWidth = parseInt(tokens[i].substring(10)); } else if (tokens[i].substring(0, 11) === 'tileheight=') { command.tileHeight = parseInt(tokens[i].substring(11)); } else if (tokens[i].substring(0, 6) === 'width=') { command.width = parseInt(tokens[i].substring(6)); } else if (tokens[i].substring(0, 7) === 'height=') { command.height = parseInt(tokens[i].substring(7)); } else if (tokens[i].substring(0, 5) === 'part=') { command.part = parseInt(tokens[i].substring(5)); } else if (tokens[i].substring(0, 6) === 'parts=') { command.parts = parseInt(tokens[i].substring(6)); } else if (tokens[i].substring(0, 8) === 'current=') { command.currentPart = parseInt(tokens[i].substring(8)); } } return command; }; function shuffle(o){ for(var j, x, i = o.length; i; j = Math.floor(Math.random() * i), x = o[--i], o[i] = o[j], o[j] = x); return o; } docPath = 'file://' + __dirname + '/data/load_test/'; var docs = []; for (var i = 1; i <= 125; i++) { docs.push('eval' + i + '.odt'); docs.push('eval' + i + '.odp'); docs.push('eval' + i + '.ods'); docs.push('eval' + i + '.odg'); } docs = shuffle(docs); docs.forEach(function (testDoc) { if (testsRan >= testsToRun) { return; } testsRan += 1; describe('Document #' + testsRan + ' (' + testDoc + ')', function () { var ws; var requestedTiles = 0; var docWidthTwips, docHeightTwips, midY, endY; var eventEmitter = new events.EventEmitter(); var onMessage = function (evt) { var bytes, index, textMsg; if (typeof (evt.data) === 'string') { textMsg = evt.data; } else if (typeof (evt.data) === 'object') { bytes = new Uint8Array(evt.data); index = 0; // search for the first newline which marks the end of the message while (index < bytes.length && bytes[index] !== 10) { index++; } textMsg = String.fromCharCode.apply(null, bytes.subarray(0, index)); } if (textMsg.startsWith('status:')) { command = _parseServerCmd(textMsg); docWidthTwips = command.width; docHeightTwips = command.height; endY = Math.floor(docHeightTwips / tileSizeTwips); midY = Math.floor(endY / 2); eventEmitter.emit('status'); } else if (textMsg.startsWith('tile:')) { requestedTiles -= 1; if (requestedTiles <= 0) { eventEmitter.emit('alltilesloaded'); } } else if (textMsg.startsWith('error:')) { console.log(textMsg); throw new Error(textMsg); } }; var requestTiles = function (x, y) { requestedTiles += 1; ws.send('tile ' + 'part=0 ' + 'width=' + tileSize + ' ' + 'height=' + tileSize + ' ' + 'tileposx=' + x * tileSizeTwips + ' ' + 'tileposy=' + y * tileSizeTwips + ' ' + 'tilewidth=' + tileSizeTwips + ' ' + 'tileheight=' + tileSizeTwips); }; var isValidTile = function (x, y) { return x >= 0 && y >= 0 && (x * tileSizeTwips < docWidthTwips) && (y * tileSizeTwips < docHeightTwips); }; after(function (done) { ws.onmessage = function () {}; ws.close(); done(); }); it('Connect to the server', function (done) { eventEmitter.once('status', done); ws = new WebSocket(host); ws.onmessage = onMessage; ws.onerror = function (e) {console.log(e)}; ws.binaryType = 'arraybuffer'; ws.onopen = function () { ws.send('load url=' + docPath + testDoc); ws.send('status'); }; }); it('Load the document', function (done) { eventEmitter.once('alltilesloaded', done); for (var i = 0; i < 3; i++) { for (j = 0; j < 5; j++) { if (isValidTile(j, i)) { requestTiles(j, i); } } } }); it('Scroll to the middle', function (done) { eventEmitter.once('alltilesloaded', done); for (var i = midY; i < midY + 3; i++) { for (j = 0; j < 5; j++) { if (isValidTile(j, i)) { requestTiles(j, i); } } } }); it('Scroll to the end', function (done) { eventEmitter.once('alltilesloaded', done); for (var i = endY; i > endY - 3; i--) { for (j = 0; j < 5; j++) { if (isValidTile(j, i)) { requestTiles(j, i); } } } }); }); }); });