Skip to content

Commit 2c4106e

Browse files
committed
Add support for testing full summary
1 parent 592d9cc commit 2c4106e

File tree

5 files changed

+131
-15
lines changed

5 files changed

+131
-15
lines changed

packages/core/src/result-summary.ts

Lines changed: 16 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -333,6 +333,9 @@ class Stats {
333333
class QueryStatistics {
334334
private _stats: Stats
335335
private _systemUpdates: number
336+
private _containsSystemUpdates?: boolean
337+
private _containsUpdates?: boolean
338+
336339
/**
337340
* Structurize the statistics
338341
* @constructor
@@ -350,7 +353,7 @@ class QueryStatistics {
350353
indexesAdded: 0,
351354
indexesRemoved: 0,
352355
constraintsAdded: 0,
353-
constraintsRemoved: 0
356+
constraintsRemoved: 0,
354357
}
355358
this._systemUpdates = 0
356359
Object.keys(statistics).forEach(index => {
@@ -360,6 +363,10 @@ class QueryStatistics {
360363
this._stats[camelCaseIndex] = intValue(statistics[index])
361364
} else if (camelCaseIndex === 'systemUpdates') {
362365
this._systemUpdates = intValue(statistics[index])
366+
} else if (camelCaseIndex === 'containsSystemUpdates') {
367+
this._containsSystemUpdates = statistics[index]
368+
} else if (camelCaseIndex === 'containsUpdates') {
369+
this._containsUpdates = statistics[index]
363370
}
364371
})
365372

@@ -371,11 +378,12 @@ class QueryStatistics {
371378
* @return {boolean}
372379
*/
373380
containsUpdates(): boolean {
374-
return (
375-
Object.keys(this._stats).reduce((last, current) => {
376-
return last + this._stats[current]
377-
}, 0) > 0
378-
)
381+
return this._containsUpdates !== undefined ?
382+
this._containsUpdates : (
383+
Object.keys(this._stats).reduce((last, current) => {
384+
return last + this._stats[current]
385+
}, 0) > 0
386+
)
379387
}
380388

381389
/**
@@ -391,7 +399,8 @@ class QueryStatistics {
391399
* @returns {boolean} - If the system database get updated or not.
392400
*/
393401
containsSystemUpdates(): boolean {
394-
return this._systemUpdates > 0
402+
return this._containsSystemUpdates !== undefined ?
403+
this._containsSystemUpdates : this._systemUpdates > 0
395404
}
396405

397406
/**

packages/testkit-backend/src/cypher-native-binders.js

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,33 @@ export function valueResponse (name, value) {
44
return { name: name, data: { value: value } }
55
}
66

7+
8+
export function objectToCypher (obj) {
9+
return objectMapper(obj, nativeToCypher)
10+
}
11+
12+
export function objectMemberBitIntToNumber (obj, recursive=false) {
13+
return objectMapper(obj, val => {
14+
if(typeof val === 'bigint') {
15+
return Number(val)
16+
} else if (recursive && typeof val === 'object') {
17+
return objectMemberBitIntToNumber(val)
18+
} else if (recursive && typeof val === 'array') {
19+
return val.map(item => objectMemberBitIntToNumber(item, true))
20+
}
21+
return val
22+
})
23+
}
24+
25+
function objectMapper(obj, mapper) {
26+
if (obj === null || obj === undefined) {
27+
return obj
28+
}
29+
return Object.keys(obj).reduce((acc, key) => {
30+
return {...acc, [key]: mapper(obj[key])}
31+
}, {})
32+
}
33+
734
export function nativeToCypher (x) {
835
if (x == null) {
936
return valueResponse('CypherNull', null)

packages/testkit-backend/src/request-handlers.js

Lines changed: 12 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,11 @@
11
import neo4j from './neo4j'
2-
import { cypherToNative, nativeToCypher } from './cypher-native-binders.js'
2+
import {
3+
cypherToNative,
4+
nativeToCypher,
5+
} from './cypher-native-binders.js'
6+
import {
7+
nativeToTestkitSummary,
8+
} from './summary-binder.js'
39
import tls from 'tls'
410

511
const SUPPORTED_TLS = (() => {
@@ -207,16 +213,13 @@ export function ResultPeek (context, data, wire) {
207213
}
208214

209215
export function ResultConsume (context, data, wire) {
216+
217+
210218
const { resultId } = data
211219
const result = context.getResult(resultId)
220+
212221
return result.summary().then(summary => {
213-
wire.writeResponse('Summary', {
214-
...summary,
215-
serverInfo: {
216-
agent: summary.server.agent,
217-
protocolVersion: summary.server.protocolVersion.toFixed(1)
218-
}
219-
})
222+
wire.writeResponse('Summary', nativeToTestkitSummary(summary))
220223
}).catch(e => wire.writeError(e))
221224
}
222225

@@ -376,6 +379,7 @@ export function GetFeatures (_context, _params, wire) {
376379
'Temporary:DriverMaxTxRetryTime',
377380
'Temporary:GetConnectionPoolMetrics',
378381
'Temporary:FastFailingDiscovery',
382+
'Temporary:FullSummary',
379383
'Temporary:ResultKeys',
380384
'Temporary:TransactionClose',
381385
...SUPPORTED_TLS

packages/testkit-backend/src/skipped-tests/common.js

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,14 @@ const skippedTests = [
2727
'Flaky in TeamCity',
2828
ifEndsWith('test_should_fail_when_writing_to_unexpectedly_interrupting_writers_on_run_using_tx_function'),
2929
),
30+
skip(
31+
'Driver does not validate query type values in result summaries',
32+
ifEquals('stub.summary.test_summary.TestSummary.test_invalid_query_type')
33+
),
34+
skip(
35+
'ResultSummary.notifications defaults to empty array instead of return null/undefined',
36+
ifEquals('stub.summary.test_summary.TestSummary.test_no_notifications')
37+
),
3038
skip(
3139
'Partial session iteration is not supported by the js driver',
3240
ifEquals('neo4j.sessionrun.TestSessionRun.test_partial_iteration'),
Lines changed: 68 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,68 @@
1+
import { objectToCypher, objectMemberBitIntToNumber } from './cypher-native-binders.js'
2+
3+
function mapPlan(plan) {
4+
return {
5+
operatorType: plan.operatorType,
6+
args: plan.arguments,
7+
identifiers: plan.identifiers,
8+
children: plan.children ? plan.children.map(mapPlan) : undefined
9+
}
10+
}
11+
12+
function mapCounters(stats) {
13+
return {
14+
...stats._stats,
15+
systemUpdates: stats.systemUpdates(),
16+
containsUpdates: stats.containsUpdates(),
17+
containsSystemUpdates: stats.containsSystemUpdates()
18+
}
19+
}
20+
21+
function mapProfile(profile, child=false) {
22+
const mapChild = (child) => mapProfile(child, true)
23+
const obj = {
24+
args: objectMemberBitIntToNumber(profile.arguments),
25+
dbHits: Number(profile.dbHits),
26+
identifiers: profile.identifiers,
27+
operatorType: profile.operatorType,
28+
rows: Number(profile.rows),
29+
children: profile.children ? profile.children.map(mapChild) : undefined
30+
}
31+
32+
if (child) {
33+
return {
34+
...obj,
35+
pageCacheHitRatio: profile.pageCacheHitRatio !== undefined ? Number(profile.pageCacheHitRatio) : undefined,
36+
pageCacheHits: profile.pageCacheHits !== undefined ? Number(profile.pageCacheHits) : undefined,
37+
pageCacheMisses: profile.pageCacheMisses !== undefined ? Number(profile.pageCacheMisses) : undefined,
38+
time: profile.time !== undefined ? Number(profile.time) : undefined,
39+
}
40+
}
41+
return obj
42+
}
43+
44+
function mapNotification(notification) {
45+
return {
46+
...notification,
47+
position: Object.keys(notification.position).length !== 0 ? notification.position : undefined,
48+
}
49+
}
50+
51+
export function nativeToTestkitSummary (summary) {
52+
return {
53+
...objectMemberBitIntToNumber(summary),
54+
database: summary.database.name,
55+
query: {
56+
text: summary.query.text,
57+
parameters: objectToCypher(summary.query.parameters)
58+
},
59+
serverInfo: {
60+
agent: summary.server.agent,
61+
protocolVersion: summary.server.protocolVersion.toFixed(1)
62+
},
63+
counters: mapCounters(summary.counters),
64+
plan: mapPlan(summary.plan),
65+
profile: mapProfile(summary.profile),
66+
notifications: summary.notifications.map(mapNotification)
67+
}
68+
}

0 commit comments

Comments
 (0)