Skip to content

Commit ad47e45

Browse files
committed
Merge pull request #36 from neo4j/1.0-tck
1.0 tck - ResultSummary API and Equality
2 parents 3c88364 + e507f76 commit ad47e45

File tree

6 files changed

+265
-17
lines changed

6 files changed

+265
-17
lines changed

gulpfile.js

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -204,8 +204,8 @@ gulp.task('download-tck', function() {
204204
gulp.task('run-tck', ['download-tck', 'nodejs'], function() {
205205
return gulp.src(featureHome + "/*").pipe(cucumber({
206206
'steps': 'test/v1/tck/steps/*.js',
207-
'format': 'summary',
208-
'tags' : ['~@in_dev', '~@db']
207+
'format': 'pretty',
208+
'tags' : ['~@in_dev', '~@db', '~@equality']
209209
}));
210210
});
211211

src/v1/internal/ch-node.js

Lines changed: 2 additions & 2 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
import net from 'net';
2121
import tls from 'tls';
2222
import fs from 'fs';
@@ -210,7 +210,7 @@ class NodeChannel {
210210
this.onerror(err);
211211
}
212212
}
213-
213+
214214
/**
215215
* Write the passed in buffer to connection
216216
* @param {NodeBuffer} buffer - Buffer to write

test/v1/tck/steps/environment.js

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,10 @@ module.exports = function () {
1919
callback();
2020
});
2121

22+
this.Before("@equality_test", function( scenario ) {
23+
this.savedValues = {}
24+
});
25+
2226
this.After(function (scenario, callback) {
2327
if (!scenario.isSuccessful()) {
2428
failedScenarios.push(scenario)

test/v1/tck/steps/matchacceptencesteps.js

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -3,15 +3,15 @@ var util = require("./util")
33

44
module.exports = function () {
55

6-
this.Given(/^init:(.*)$/, function (statement) {
6+
this.Given(/^init: (.*)$/, function (statement) {
77
return this.session.run(statement);
88
});
99

10-
this.When(/^running:(.*)$/, function (statement) {
10+
this.When(/^running: (.*)$/, function (statement) {
1111
this.rc = this.session.run(statement);
1212
});
1313

14-
this.When(/^running parametrized:(.*)$/, function (statement, table) {
14+
this.When(/^running parametrized: (.*)$/, function (statement, table) {
1515
var param = util.literalTableToTestObject(table.hashes())[0];
1616
this.rc = this.session.run(statement, param);
1717
});

test/v1/tck/steps/resultapisteps.js

Lines changed: 219 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,219 @@
1+
var neo4j = require("../../../../lib/v1");
2+
var resultSummary = require("../../../../lib/v1/result-summary");
3+
var util = require("./util")
4+
5+
module.exports = function () {
6+
7+
this.When(/^the `Statement Result` is consumed a `Result Summary` is returned$/, function (callback) {
8+
self = this;
9+
this.rc.then(function(res) {
10+
self.summary = res.summary;
11+
callback();
12+
}).catch(function(err) {callback(new Error("Rejected Promise: " + err))});
13+
});
14+
15+
this.Then(/^the `Statement Result` is closed$/, function () {
16+
//No result cursor in JavaScript Driver
17+
});
18+
19+
this.When(/^I request a `Statement` from the `Result Summary`$/, function () {
20+
this.statement = this.summary.statement
21+
});
22+
23+
this.Then(/^requesting the `Statement` as text should give: (.*)$/, function (statementText) {
24+
if (this.statement.text != statementText) {
25+
throw Error("'" + this.statement.text + "' does not match expected text: '" + statementText + "'")
26+
}
27+
});
28+
29+
this.Then(/^requesting the `Statement` parameter should give: (.*)$/, function (statementParam) {
30+
var param = util.literalValueToTestValue(statementParam);
31+
if (typeof this.statement.parameters === 'undefined') {
32+
this.statement.parameters = {}
33+
}
34+
if (!util.compareValues(this.statement.parameters, param)) {
35+
throw Error("Params does not match! Got: " + this.statement.parameters + " Expected: " + param);
36+
}
37+
});
38+
39+
this.Then(/^requesting `Counters` from `Result Summary` should give$/, function (table) {
40+
var updateStatistics = this.summary.updateStatistics
41+
for ( var i = 0 ; i < table.hashes().length; i++) {
42+
var statistic = table.hashes()[i].counter;
43+
var expected = util.literalValueToTestValueNormalIntegers(table.hashes()[i].result);
44+
var given = getStatistic(statistic, updateStatistics)
45+
if (!util.compareValues(given, expected)) {
46+
throw Error("Statistics for: " + statistic + " does not match. Expected: '" + expected + "' Given: '" + given + "'");
47+
}
48+
}
49+
});
50+
51+
this.Then(/^requesting the `Statement Type` should give (.*)$/, function (type) {
52+
var type = getStatementTypeFromString(type);
53+
if (this.summary.statementType != type)
54+
{
55+
throw Error("statementType does not match. Expected: '" + type + "' Given: '" + this.summary.statementType + "'");
56+
}
57+
});
58+
59+
this.Then(/^the `Result Summary` has a `Plan`$/, function () {
60+
if(! this.summary.hasPlan()) {
61+
throw Error("Expected summary to have a `plan`. It did not...");
62+
}
63+
});
64+
65+
this.Then(/^the `Result Summary` does not have a `Plan`$/, function () {
66+
if(this.summary.hasPlan()) {
67+
throw Error("Expected summary to NOT have a `plan`. It did not...");
68+
}
69+
});
70+
71+
this.Then(/^the `Result Summary` has a `Profile`$/, function () {
72+
if(! this.summary.hasProfile()) {
73+
throw Error("Expected summary to have a `profile plan`. It did not...");
74+
}
75+
});
76+
77+
this.Then(/^the `Result Summary` does not have a `Profile`$/, function () {
78+
if( this.summary.hasProfile()) {
79+
throw Error("Expected summary to NOT have a `profile plan`. It did...");
80+
}
81+
});
82+
83+
this.Then(/^requesting the `Plan` it contains$/, function (table) {
84+
checkPlanExact(table, this.summary.plan)
85+
});
86+
87+
this.Then(/^the `Plan` also contains method calls for:$/, function (table) {
88+
checkPlan(table, this.summary.plan)
89+
});
90+
91+
this.Then(/^requesting the `Profile` it contains:$/, function (table) {
92+
checkPlanExact(table, this.summary.profile)
93+
});
94+
95+
this.Then(/^the `Profile` also contains method calls for:$/, function (table) {
96+
checkPlan(table, this.summary.profile)
97+
});
98+
99+
this.Then(/^the `Result Summary` `Notifications` is empty$/, function () {
100+
if (! this.summary.notifications.length == 0) {
101+
throw Error("Expected no notifications. Got: " + this.summary.notifications.length)
102+
}
103+
});
104+
105+
this.Then(/^the `Result Summary` `Notifications` has one notification with$/, function (table) {
106+
107+
var expected = {};
108+
if (this.summary.notifications.length > 1) {
109+
throw Error("Expected only one notification. Got: " + this.summary.notifications.length)
110+
}
111+
var givenNotification = this.summary.notifications[0];
112+
var given = {}
113+
for ( var i = 0 ; i < table.hashes().length; i++) {
114+
var key = table.hashes()[i]['key']
115+
expected[key] = util.literalValueToTestValueNormalIntegers(table.hashes()[i]['value']);
116+
given[key] = givenNotification[key]
117+
}
118+
if (Object.keys(givenNotification).length !== Object.keys(given).length) {
119+
throw Error("Keys do not match with expected. Got: " + Object.keys(givenNotification) + " Expected: " + Object.keys(given))
120+
}
121+
if (!util.compareValues(expected, given)) {
122+
throw Error("Summary notifications does not match. Expected: '" + util.printable(expected) + "' Given: '" + util.printable(givenNotification) + "'");
123+
}
124+
});
125+
126+
function checkPlanExact(table, plan)
127+
{
128+
for ( var i = 0 ; i < table.hashes().length; i++) {
129+
var dataKey = getPlanParam(table.hashes()[i]["plan method"])
130+
var given = plan[dataKey];
131+
if (given === undefined || given === null || given === NaN) {
132+
throw Error("Plans `" + dataKey + "` has no content! Got: " + given);
133+
}
134+
}
135+
}
136+
137+
function checkPlan(table, plan)
138+
{
139+
for ( var i = 0 ; i < table.hashes().length; i++) {
140+
var dataKey = getPlanParam(table.hashes()[i]["plan method"])
141+
var given = plan[dataKey];
142+
if (given === undefined || given === null || given === NaN) {
143+
throw Error("Plans `" + dataKey + "` has no content! Got: " + given);
144+
}
145+
}
146+
}
147+
148+
function getPlanParam(key) {
149+
if (key == 'operator type') {
150+
return 'operatorType'
151+
}
152+
if (key == 'db hits') {
153+
return 'dbHits'
154+
}
155+
if (key == 'records') {
156+
return 'rows'
157+
}
158+
else {
159+
return key
160+
}
161+
}
162+
163+
function getStatementTypeFromString(type) {
164+
if (type == 'read write') {
165+
return resultSummary.statementType.READ_WRITE;
166+
}
167+
if (type == 'read only') {
168+
return resultSummary.statementType.READ_ONLY;
169+
}
170+
if (type == 'write only') {
171+
return resultSummary.statementType.WRITE_ONLY;
172+
}
173+
if (type == 'schema write') {
174+
return resultSummary.statementType.SCHEMA_WRITE;
175+
}
176+
throw Error("No statement type mapping of: " + type)
177+
}
178+
179+
function getStatistic(statementString, updateStatistics) {
180+
if (statementString == 'nodes created') {
181+
return updateStatistics.nodesCreated();
182+
}
183+
if (statementString == 'nodes deleted') {
184+
return updateStatistics.nodesDeleted();
185+
}
186+
if (statementString == 'relationships created') {
187+
return updateStatistics.relationshipsCreated();
188+
}
189+
if (statementString == 'relationships deleted') {
190+
return updateStatistics.relationshipsDeleted();
191+
}
192+
if (statementString == 'properties set') {
193+
return updateStatistics.propertiesSet();
194+
}
195+
if (statementString == 'labels added') {
196+
return updateStatistics.labelsAdded();
197+
}
198+
if (statementString == 'labels removed') {
199+
return updateStatistics.labelsRemoved();
200+
}
201+
if (statementString == 'indexes added') {
202+
return updateStatistics.indexesAdded();
203+
}
204+
if (statementString == 'indexes removed') {
205+
return updateStatistics.indexesRemoved();
206+
}
207+
if (statementString == 'constraints added') {
208+
return updateStatistics.constraintsAdded();
209+
}
210+
if (statementString == 'constraints removed') {
211+
return updateStatistics.constraintsRemoved();
212+
}
213+
if (statementString == 'contains updates') {
214+
return updateStatistics.containsUpdates();
215+
}
216+
throw Error("No statistics mapping of: " + statementString)
217+
}
218+
219+
}

test/v1/tck/steps/util.js

Lines changed: 35 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@ PATH = 'path';
1111

1212
module.exports = {
1313
literalTableToTestObject: literalTableToTestObject,
14+
literalValueToTestValueNormalIntegers : literalValueToTestValueNormalIntegers,
1415
literalValueToTestValue: literalValueToTestValue,
1516
compareValues: compareValues,
1617
sizeOfObject: sizeOfObject,
@@ -35,12 +36,20 @@ function literalLineToObjects(resultRow) {
3536
return resultObject;
3637
}
3738

39+
function literalValueToTestValueNormalIntegers(values) {
40+
return literalValueToTestObject(values, false)
41+
}
42+
3843
function literalValueToTestValue(values) {
44+
return literalValueToTestObject(values, true)
45+
}
46+
47+
function literalValueToTestObject(values, bigInt) {
3948
if (isLiteralArray(values)) {
4049
values = getLiteralArray(values);
4150
}
4251
if (isLiteralMap(values)) {
43-
return getProperties(values);
52+
return parseMap(values, bigInt);
4453
}
4554
if (values instanceof Array) {
4655
var res = [];
@@ -49,12 +58,12 @@ function literalValueToTestValue(values) {
4958
}
5059
}
5160
else {
52-
var res = convertValue(values);
61+
var res = convertValue(values, bigInt);
5362
}
5463
return res;
5564
}
5665

57-
function convertValue(value) {
66+
function convertValue(value, bigInt) {
5867
if (value === NULL) {
5968
return null;
6069
}
@@ -74,7 +83,13 @@ function convertValue(value) {
7483
return createPath(value);
7584
}
7685
if (value.match( "^(-?[0-9]+)$")) {
77-
return neo4j.int(value)
86+
if (bigInt)
87+
{
88+
return neo4j.int(value)
89+
}
90+
else {
91+
return parseInt(value)
92+
}
7893
}
7994
return parseFloat(value);
8095
}
@@ -159,19 +174,29 @@ function parseNodesAndRelationshipsFromPath(val) {
159174
return nodesAndRels;
160175
}
161176

177+
function parseMap(val, bigInt) {
178+
if (bigInt)
179+
{
180+
return properties = JSON.parse(val, function(k, v) {
181+
if (Number.isInteger(v)) {
182+
return neo4j.int(v);
183+
}
184+
return v;
185+
});
186+
}
187+
else {
188+
return properties = JSON.parse(val);
189+
}
190+
}
191+
162192
function getProperties(val) {
163193
var startIndex = val.indexOf("{");
164194
var endIndex = val.indexOf("}");
165195
if (!(startIndex >= 0 && endIndex >= 0)) {
166196
return {};
167197
}
168198
val = val.substring(startIndex, endIndex + 1);
169-
return properties = JSON.parse(val, function(k, v) {
170-
if (Number.isInteger(v)) {
171-
return neo4j.int(v);
172-
}
173-
return v;
174-
});
199+
return parseMap(val, true)
175200
}
176201

177202
function printable(array) {

0 commit comments

Comments
 (0)