Skip to content

Commit

Permalink
Beginnings of a test to track down the "Trying to read beyond buffer …
Browse files Browse the repository at this point in the history
…length" error. Can only really guess what is triggering it given the sketchy details but the test case tries to replicate what is described in the VoltDB#18 issue.

Also contains some experimental promise based wrappers around the call back style fns in VoltClient... plus an eslint config.
  • Loading branch information
mattyouill committed Sep 19, 2017
1 parent 293b6c2 commit 84fca91
Show file tree
Hide file tree
Showing 3 changed files with 302 additions and 32 deletions.
28 changes: 28 additions & 0 deletions .eslintrc.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
{
"env": {
"es6": true,
"node": true
},
"extends": "eslint:recommended",
"parserOptions": {
"sourceType": "module"
},
"rules": {
"indent": [
"error",
2
],
"linebreak-style": [
"error",
"unix"
],
"quotes": [
"error",
"double"
],
"semi": [
"error",
"always"
]
}
}
70 changes: 38 additions & 32 deletions package.json
Original file line number Diff line number Diff line change
@@ -1,34 +1,40 @@
{
"name": "voltjs",
"version": "2.0.0",
"description": "VoltDB binary driver",
"keywords": [
"voltdb",
"client",
"driver",
"binary driver"
],
"bugs": {
"url": "https://github.com/VoltDB/voltdb-client-nodejs/issues",
"email": "[email protected]"
},
"license": "MIT",
"author": "VoltDB",
"engines": {
"node": ">= 6.11.0"
},
"repository": {
"type": "git",
"url": "https://github.com/VoltDB/voltdb-client-nodejs.git"
},
"dependencies": {
"bignumber": "^1.1.0",
"ctype": "^0.5.0",
"cli": "^1.0.0",
"debug": "^3.0.1",
"supports-color": "^4.4.0"
},
"devDependencies": {
"nodeunit": "^0.11.0"
}
"name": "voltjs",
"version": "2.0.0",
"description": "VoltDB binary driver",
"keywords": [
"voltdb",
"client",
"driver",
"binary driver"
],
"bugs": {
"url": "https://github.com/VoltDB/voltdb-client-nodejs/issues",
"email": "[email protected]"
},
"license": "MIT",
"author": "VoltDB",
"engines": {
"node": ">= 6.11.0"
},
"repository": {
"type": "git",
"url": "https://github.com/VoltDB/voltdb-client-nodejs.git"
},
"dependencies": {
"bignumber": "^1.1.0",
"ctype": "^0.5.0",
"cli": "^1.0.0",
"debug": "^3.0.1",
"supports-color": "^4.4.0"
},
"devDependencies": {
"eslint": "^4.7.1",
"eslint-config-standard": "^10.2.1",
"eslint-plugin-import": "^2.7.0",
"eslint-plugin-node": "^5.1.1",
"eslint-plugin-promise": "^3.5.0",
"eslint-plugin-standard": "^3.0.1",
"nodeunit": "^0.11.0"
}
}
236 changes: 236 additions & 0 deletions test/cases/bufferTest.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,236 @@
!(function (global) { // eslint-disable-line no-unused-vars

"use strict";

const VoltClient = require("../../lib/client");
const VoltConfiguration = require("../../lib/configuration");
const VoltConstants = require("../../lib/voltconstants");
const VoltProcedure = require("../../lib/query");


require("nodeunit");
const debug = require("debug")("voltdb-client-nodejs:BufferTest");

/**
* A "good" client config that points to a volt instance on localhost
*/
function configs() {

const configs = [];

const config = new VoltConfiguration();
config.host = "localhost";

configs.push(config);

return configs;
}

/**
* Promise style function for connecting to a Volt instance
*/
function connect(client){

const p = new Promise(function(resolve, reject) {
client.connect(function(code, event, results) {
if(code === VoltConstants.STATUS_CODES.SUCCESS){
resolve({errorCode: code, eventCode: event, results: results});
}
else{
debug("Connect Failure | Code: %o, Event: %o", code, event);
reject({errorCode: code, eventCode: event, results: results});
}
});
});

return p;
}

/**
* Promise style function for calling a procedure. An alternative to the old
* callback style functions that returns both a write and a read promise.
*/
function query(query, client){

var writeResolve = null;
var writeReject = null;

const writePromise = new Promise(function(resolve, reject){
writeResolve = resolve;
writeReject = reject;
});

const readPromise = new Promise(function(resolve, reject){

client.callProcedure(query, function read(code, event, results) {
// debug("AdHocQuery Complete | errorCode: %o, eventCode: %o, results:
// %O", code, event, results);
if(code === VoltConstants.STATUS_CODES.SUCCESS){
// The results code is 1 for SUCCESS so can't use voltconstants
if(results.status === PROC_STATUS_CODE_SUCCESS){
resolve({errorCode: code, eventCode: event, results: results});
}
else{
debug("AdHocQuery Failure | Read Error. errorCode: %o, eventCode: %o, results: %O", statusCodeToString(code), event, results);
reject({errorCode: code, eventCode: event, results: results});
}
}
else{
debug("AdHocQuery Failure | Read Error. errorCode: %o, eventCode: %o, results: %O", statusCodeToString(code), event, results);
reject({errorCode: code, eventCode: event, results: results});
}

}, function write(code, event, results) {
if(code === VoltConstants.STATUS_CODES.SUCCESS){
writeResolve({errorCode: code, eventCode: event, results: results});
}
else{
debug("AdHocQuery Failure | Write Error. errorCode: %o, eventCode: %o, results: %O", statusCodeToString(code), event, results);
writeReject({errorCode: code, eventCode: event, results: results});
}
});
});

return { writePromise: writePromise, readPromise: readPromise };
}

/**
* Sugar for running an adhoc query
*/
function adHocQuery(queryString, client){

debug("Query | query: %o", queryString);

const p = new VoltProcedure("@AdHoc", [ "string" ]);

const q = p.getQuery();
q.setParameters([queryString]);

return query(q, client);
}

/**
*
*/
function statusCodeToString(code){
return code === null ? VoltConstants.STATUS_CODE_STRINGS[PROC_STATUS_CODE_SUCCESS] : VoltConstants.STATUS_CODE_STRINGS[code];
}

/**
* Utility method for volt queries that return a write and a read promise.
* Useful for when you want to fire off a bunch of writes and then wait on the
* read at the end. Executes the query and collects the read promises in the
* given array. Returns both the write and read promise.
*/
function queryCollect(queryString, readPromises, client){
const p = adHocQuery(queryString, client);
readPromises.push(p.readPromise);
return p;
}

/**
*
*/
const PROC_STATUS_CODE_SUCCESS = 1;

// Exports
module.exports = {
setUp : function(callback){
callback();
},
tearDown : function(callback){
callback();
},
readTest : function(test){

debug("readTest");

const client = new VoltClient(configs());

debug("Connecting");

connect(client)
.then(function(value){
test.ok(value.errorCode === VoltConstants.STATUS_CODES.SUCCESS);
return Promise.resolve(null);
})
.then(function(){
return adHocQuery("DROP TABLE PLAYERS IF EXISTS;", client).readPromise;
})
.then(function(){
return adHocQuery("CREATE TABLE PLAYERS (" +
"playerID integer NOT NULL, " +
"teamid varchar(100) NOT NULL " +
");", client).readPromise;
})
.then(function(){
return adHocQuery("DROP TABLE TEAM_PLAYERS IF EXISTS;", client).readPromise;
})
.then(function(){
return adHocQuery("CREATE TABLE TEAM_PLAYERS (" +
"id integer NOT NULL, " +
"uid varchar(100) NOT NULL, " +
"name varchar(100) NOT NULL, " +
"avatar varbinary(12000) NOT NULL" +
");", client).readPromise;
})
.then(function(){

const readPromises = [];

return Promise.resolve()
.then(function() { return queryCollect("INSERT INTO PLAYERS VALUES (0, 'TeamA');", readPromises, client).writePromise; })
.then(function() { return queryCollect("INSERT INTO PLAYERS VALUES (1, 'TeamA');", readPromises, client).writePromise; })
.then(function() { return queryCollect("INSERT INTO PLAYERS VALUES (2, 'TeamA');", readPromises, client).writePromise; })
.then(function() { return queryCollect("INSERT INTO PLAYERS VALUES (3, 'TeamA');", readPromises, client).writePromise; })
.then(function() { return queryCollect("INSERT INTO PLAYERS VALUES (4, 'TeamA');", readPromises, client).writePromise; })
.then(function() { return queryCollect("INSERT INTO PLAYERS VALUES (5, 'TeamB');", readPromises, client).writePromise; })
.then(function() { return queryCollect("INSERT INTO PLAYERS VALUES (6, 'TeamB');", readPromises, client).writePromise; })
.then(function() { return queryCollect("INSERT INTO PLAYERS VALUES (7, 'TeamB');", readPromises, client).writePromise; })
.then(function() { return queryCollect("INSERT INTO PLAYERS VALUES (8, 'TeamB');", readPromises, client).writePromise; })
.then(function() { return queryCollect("INSERT INTO PLAYERS VALUES (9, 'TeamB');", readPromises, client).writePromise; })
.then(function() { return Promise.all(readPromises); });

})
.then(function(){

const readPromises = [];

return Promise.resolve()
.then(function() { return queryCollect("INSERT INTO TEAM_PLAYERS VALUES (0, 'GameA', 'TeamA', 'ABCDEF');", readPromises, client).writePromise; })
.then(function() { return queryCollect("INSERT INTO TEAM_PLAYERS VALUES (1, 'GameB', 'TeamA', 'ABCDEF');", readPromises, client).writePromise; })
.then(function() { return queryCollect("INSERT INTO TEAM_PLAYERS VALUES (2, 'GameC', 'TeamA', 'ABCDEF');", readPromises, client).writePromise; })
.then(function() { return queryCollect("INSERT INTO TEAM_PLAYERS VALUES (3, 'GameD', 'TeamA', 'ABCDEF');", readPromises, client).writePromise; })
.then(function() { return queryCollect("INSERT INTO TEAM_PLAYERS VALUES (4, 'GameE', 'TeamA', 'ABCDEF');", readPromises, client).writePromise; })
.then(function() { return queryCollect("INSERT INTO TEAM_PLAYERS VALUES (5, 'GameA', 'TeamB', 'ABCDEF');", readPromises, client).writePromise; })
.then(function() { return queryCollect("INSERT INTO TEAM_PLAYERS VALUES (6, 'GameB', 'TeamB', 'ABCDEF');", readPromises, client).writePromise; })
.then(function() { return queryCollect("INSERT INTO TEAM_PLAYERS VALUES (7, 'GameC', 'TeamB', 'ABCDEF');", readPromises, client).writePromise; })
.then(function() { return queryCollect("INSERT INTO TEAM_PLAYERS VALUES (8, 'GameD', 'TeamB', 'ABCDEF');", readPromises, client).writePromise; })
.then(function() { return queryCollect("INSERT INTO TEAM_PLAYERS VALUES (9, 'GameE', 'TeamB', 'ABCDEF');", readPromises, client).writePromise; })
.then(function() { return Promise.all(readPromises); });

})
.then(function(){
return adHocQuery("select A.*, " +
"B.name as name, " +
"B.avatar as avatar " +
"from PLAYERS as A left join TEAM_PLAYERS as B on A.playerID=B.id " +
"where uID='GameA' and A.teamID='TeamA';", client).readPromise;
})
.then(function(value){
debug("Result Count: %O", value.results.table.length);
debug("Results: %O", value.results.table[0][0]);
client.exit();
test.done();
return Promise.resolve(null);
})
.catch(function(value){
debug("Test Failed | Results: %O", value);
client.exit();
test.ok(false, "Test failed, see previous messages");
test.done();
});
}
};

}(this));

0 comments on commit 84fca91

Please sign in to comment.