Skip to content

Commit 192c6ff

Browse files
committed
TCK tests
1 parent 2f23645 commit 192c6ff

File tree

3 files changed

+335
-4
lines changed

3 files changed

+335
-4
lines changed

gulpfile.js

Lines changed: 23 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@
1616
* See the License for the specific language governing permissions and
1717
* limitations under the License.
1818
*/
19-
19+
2020
var browserify = require('browserify');
2121
var source = require('vinyl-source-stream');
2222
var buffer = require('vinyl-buffer');
@@ -42,6 +42,7 @@ var runSequence = require('run-sequence');
4242
var path = require('path');
4343
var childProcess = require("child_process");
4444
var minimist = require('minimist');
45+
var cucumber = require('gulp-cucumber');
4546

4647
gulp.task('default', ["test"]);
4748

@@ -89,10 +90,10 @@ gulp.task('build-browser-test', function(){
8990
cb();
9091
}))
9192
.pipe( through.obj( function( testFiles, enc, cb) {
92-
browserify({
93+
browserify({
9394
entries: testFiles,
9495
cache: {},
95-
debug: true
96+
debug: true
9697
}).transform(babelify.configure({
9798
ignore: /external/
9899
}))
@@ -186,6 +187,25 @@ gulp.task('download-neo4j', function() {
186187
}
187188
});
188189

190+
var featureFiles = 'https://s3-eu-west-1.amazonaws.com/remoting.neotechnology.com/driver-compliance/tck.tar.gz';
191+
var featureHome = './build/tck';
192+
193+
gulp.task('download-tck', function() {
194+
if( !fs.existsSync(featureHome) ) {
195+
// Need to download
196+
return download(featureFiles)
197+
.pipe(decompress({strip: 1}))
198+
.pipe(gulp.dest(featureHome));
199+
}
200+
});
201+
202+
gulp.task('run-tck', ['download-tck', 'nodejs'], function() {
203+
return gulp.src(featureHome + "/*").pipe(cucumber({
204+
'steps': 'test/v1/tck/steps/*.js',
205+
'format': 'pretty'
206+
}));
207+
});
208+
189209
var runPowershell = function( cmd ) {
190210
var spawn = childProcess.spawn, child;
191211
child = spawn("powershell.exe",[

package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,7 @@
2626
"gulp-babel": "^5.2.1",
2727
"gulp-batch": "^1.0.5",
2828
"gulp-concat": "^2.6.0",
29-
"gulp-cucumber": "^0.0.12",
29+
"gulp-cucumber": "0.0.14",
3030
"gulp-decompress": "^1.2.0",
3131
"gulp-download": "^0.0.1",
3232
"gulp-if": "^1.2.5",

test/v1/tck/steps/steps.js

Lines changed: 311 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,311 @@
1+
var neo4j = require("../../../../lib/v1");
2+
3+
module.exports = function () {
4+
5+
this.Before(function( scenario ) {
6+
this.driver = neo4j.driver("bolt://localhost");
7+
this.session = this.driver.session();
8+
});
9+
10+
this.Given(/^A running database$/, function () {
11+
return this.session.run("RETURN 1 AS one");
12+
});
13+
14+
this.Given(/^a String of size (\d+)$/, function (size) {
15+
this.expectedValue = stringOfSize(size);
16+
});
17+
18+
this.Given(/^a List of size (\d+) and type (.*)$/, function (size, type) {
19+
var list = [];
20+
for(var i = 0; i < size; i++ ) {
21+
if (type === 'String') {
22+
list.push(stringOfSize(3));
23+
}
24+
if (type === 'Integer') {
25+
list.push(randomInt());
26+
}
27+
if (type === 'Boolean') {
28+
list.push(randomBool());
29+
}
30+
if (type === 'Float') {
31+
list.push(randomFloat());
32+
}
33+
if (type === 'Null') {
34+
list.push(null);
35+
}
36+
}
37+
this.expectedValue = list;
38+
});
39+
40+
this.Given(/^a Map of size (\d+) and type (.*)$/, function (size, type) {
41+
var map = {};
42+
for(var i = 0; i < size; i++ ) {
43+
if (type === 'String') {
44+
map["a" + tempSizeOfObject(this.M)] = stringOfSize(3);
45+
}
46+
if (type === 'Integer') {
47+
map["a" + tempSizeOfObject(this.M)] = randomInt();
48+
}
49+
if (type === 'Boolean') {
50+
map["a" + tempSizeOfObject(this.M)] = randomBool();
51+
}
52+
if (type === 'Float') {
53+
map["a" + tempSizeOfObject(this.M)] = randomFloat();
54+
}
55+
if (type === 'Null') {
56+
map["a" + tempSizeOfObject(this.M)] = null;
57+
}
58+
}
59+
this.expectedValue = map;
60+
});
61+
62+
this.Given(/^a list value (.*) of type (.*)$/, function (input, boltType) {
63+
this.expectedValue = getListFromString(boltType, input);
64+
});
65+
66+
this.Given(/^a value (.*) of type (.*)$/, function (input, boltType) {
67+
this.expectedValue = toParameter(boltType, input)
68+
});
69+
70+
this.Given(/^an empty list L$/, function () {
71+
this.L = [];
72+
});
73+
74+
this.Given(/^an empty map M$/, function () {
75+
this.M = {};
76+
});
77+
78+
this.Given(/^adding a table of values to the list L$/, function (table) {
79+
var rows = table.rows();
80+
for (var i = 0, len = rows.length; i < len; i++) {
81+
this.L.push(toParameter(rows[i][0], rows[i][1]));
82+
}
83+
});
84+
85+
this.Given(/^adding a table of lists to the list L$/, function (table) {
86+
var rows = table.rows();
87+
for (var i = 0, len = rows.length; i < len; i++) {
88+
this.L.push(getListFromString(rows[i][0], rows[i][1]));
89+
}
90+
});
91+
92+
this.Given(/^adding map M to list L$/, function () {
93+
this.L.push(this.M);
94+
});
95+
96+
this.Given(/^adding a table of values to the map M$/, function (table) {
97+
var rows = table.rows();
98+
for (var i = 0, len = rows.length; i < len; i++) {
99+
this.M["a" + tempSizeOfObject(this.M)] = toParameter(rows[i][0], rows[i][1]);
100+
}
101+
});
102+
103+
this.When(/^adding a table of lists to the map M$/, function (table) {
104+
var rows = table.rows();
105+
for (var i = 0, len = rows.length; i < len; i++) {
106+
this.M["a" + tempSizeOfObject(this.M)] = getListFromString(rows[i][0], rows[i][1]);
107+
}
108+
});
109+
110+
this.When(/^adding a copy of map M to map M$/, function () {
111+
var copyt_of_map = Object.assign({}, this.M);
112+
this.M["a" + tempSizeOfObject(this.M)] = copyt_of_map;
113+
});
114+
115+
this.When(/^the driver asks the server to echo this value back$/, function () {
116+
echoExpectedValue(this);
117+
});
118+
119+
this.When(/^the driver asks the server to echo this list back$/, function () {
120+
this.expectedValue = this.L;
121+
echoExpectedValue(this);
122+
});
123+
124+
this.When(/^the driver asks the server to echo this map back$/, function () {
125+
this.expectedValue = this.M;
126+
echoExpectedValue(this);
127+
});
128+
129+
this.Then(/^the result returned from the server should be a single record with a single value$/, function (callback) {
130+
var self = this;
131+
this.setWithParam.then( function(res) {
132+
if(res.records.length != 1 || tempSizeOfObject(res.records[0]) != 1) {
133+
callback(new Error("Expected the parameterized statement to return a single row, single field record. Got: " + res));
134+
} else {
135+
self.paramResult = res.records[0]['x'];
136+
}
137+
}, function(err) {callback(new Error("Rejected Promise: " + err))});
138+
this.setWithLiteral.then( function(res) {
139+
if(res.records.length != 1 || tempSizeOfObject(res.records[0]) != 1) {
140+
callback(new Error("Expected the literal statement to return a single row, single field record. Got: " + res));
141+
} else {
142+
self.literalResult = res.records[0]['x'];
143+
callback();
144+
}
145+
}, function(err) {callback(new Error("Rejected Promise: " + err))});
146+
});
147+
148+
149+
this.Then(/^the value given in the result should be the same as what was sent$/, function () {
150+
if (!compareValues(this.paramResult, this.expectedValue)) {
151+
throw new Error("Expected the parameterized statement to return same as what was sent. Got: " + this.paramResult + " Expected: " + this.expectedValue);
152+
}
153+
if(!compareValues(this.literalResult,this.expectedValue)) {
154+
throw new Error("Expected the literal statement to return same as what was sent. Got: " + this.literalResult + " Expected: " + this.expectedValue);
155+
}
156+
});
157+
158+
this.After(function () {
159+
this.driver.close()
160+
});
161+
162+
//Should not be used in final!!!!
163+
function tempSizeOfObject(obj) {
164+
var size = 0, key;
165+
for (key in obj) {
166+
if (obj.hasOwnProperty(key)) size++;
167+
}
168+
return size;
169+
}
170+
171+
function stringOfSize(size) {
172+
var chars = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789";
173+
return Array(size).join().split(',').map(function() { return chars.charAt(Math.floor(Math.random() * chars.length)); }).join('');
174+
}
175+
176+
function randomBool()
177+
{
178+
return Math.random() >= 0.5
179+
}
180+
181+
function randomInt()
182+
{
183+
return neo4j.int(Math.floor(Math.random() * (2147483647 + 2147483648 + 1)) - 2147483648);
184+
}
185+
186+
function randomFloat()
187+
{
188+
return Math.random()
189+
}
190+
191+
function toParameter(type, value) {
192+
193+
if (type === 'String') {
194+
return value.toString();
195+
}
196+
if (type === 'Integer') {
197+
return neo4j.int(value);
198+
}
199+
if (type === 'Boolean') {
200+
return Boolean(value);
201+
}
202+
if (type === 'Float') {
203+
return parseFloat(value);
204+
}
205+
if (type === 'Null') {
206+
return null;
207+
}
208+
else {
209+
throw new Error("Cannot conversion of type:" + type + " has not been implemented" );
210+
}
211+
}
212+
213+
function jsToCypherLiteral(jsVal) {
214+
if( typeof jsVal === "string" || jsVal instanceof String ) {
215+
return '"' + jsVal + '"';
216+
}
217+
else if( neo4j.isInt(jsVal) ) {
218+
return jsVal.toString();
219+
}
220+
else if( typeof jsVal === "boolean") {
221+
return jsVal.toString();
222+
}
223+
//number is float
224+
else if( typeof jsVal === "number") {
225+
var f = jsVal.toString();
226+
if (!(f.indexOf("e") != -1 || f.indexOf("E") != -1)) {
227+
if (f.indexOf(".") == -1) {
228+
return jsVal.toFixed(1).toString();
229+
}
230+
}
231+
return f.replace("+", "");
232+
}
233+
else if( jsVal === undefined || jsVal === null) {
234+
return 'Null'
235+
}
236+
else if( typeof jsVal === "object" && jsVal instanceof Array ) {
237+
var list = "["
238+
for(var i = 0; i < jsVal.length; i++ ) {
239+
list += jsToCypherLiteral(jsVal[i]);
240+
if ( i < jsVal.length -1) {
241+
list += ",";
242+
}
243+
}
244+
return list += "]";
245+
}
246+
else if( typeof jsVal === "object" && jsVal instanceof Object ) {
247+
var map = "{"
248+
for(var key in jsVal) {
249+
var new_key = key;
250+
map += new_key + ":" + jsToCypherLiteral(jsVal[key]);
251+
map += ",";
252+
}
253+
map = map.slice(0,-1);
254+
return map += "}";
255+
}
256+
else {
257+
throw new Error("Cannot convert " + jsVal);
258+
}
259+
}
260+
261+
function compareValues(one, other) {
262+
if (neo4j.isInt(one)) {
263+
if (one.equals(other)) {
264+
return true;
265+
}
266+
}
267+
else if (typeof one === "object" && one instanceof Array){
268+
if (one === other) return true;
269+
if (tempSizeOfObject(one) != tempSizeOfObject(other)) return false;
270+
for (var i = 0; i < one.length; ++i) {
271+
if (!compareValues(one[i], other[i])) {
272+
console.log("Miss-match at index: [" + i + "] Values should be same but was : [" + one[i] +"] and : [" + other[i] + "]");
273+
return false;
274+
}
275+
}
276+
return true;
277+
}
278+
else if (typeof one === "object" && one instanceof Object){
279+
if (one === other) return true;
280+
if (one.length != other.length) return false;
281+
for (var key in one) {
282+
if (typeof other[key] == "undefined") return false;
283+
if (!compareValues(one[key], other[key])) {
284+
console.log("Miss-match at key: [" + key + "] Values should be same but was : [" + one[key] +"] and : [" + other[key] + "]");
285+
return false;
286+
}
287+
}
288+
return true;
289+
}
290+
else if (one === other) {
291+
return true;
292+
}
293+
return false;
294+
}
295+
296+
function getListFromString(type, input) {
297+
var str = input.replace("[", "");
298+
str = str.replace("]","");
299+
str = str.split(",");
300+
var list = [];
301+
for(var i = 0; i < str.length; i++ ) {
302+
list.push(toParameter(type,str[i]));
303+
}
304+
return list;
305+
}
306+
307+
function echoExpectedValue(self) {
308+
self.setWithParam = self.session.run("RETURN {x} as x", {x:self.expectedValue});
309+
self.setWithLiteral = self.session.run("RETURN "+jsToCypherLiteral(self.expectedValue)+" as x");
310+
}
311+
};

0 commit comments

Comments
 (0)