diff options
author | Thorsten Lorenz <thlorenz@gmx.de> | 2016-11-22 13:13:44 -0300 |
---|---|---|
committer | Anna Henningsen <anna@addaleax.net> | 2017-05-10 22:22:33 +0200 |
commit | e3e56f1d71fd496c8a25d6b4b50e51d4a682d184 (patch) | |
tree | 764b9470be5afecee9027acccbbf84e6e590bac9 /test/async-hooks/verify-graph.js | |
parent | 4a7233c1788334c171d2280026333242df7d37af (diff) | |
download | android-node-v8-e3e56f1d71fd496c8a25d6b4b50e51d4a682d184.tar.gz android-node-v8-e3e56f1d71fd496c8a25d6b4b50e51d4a682d184.tar.bz2 android-node-v8-e3e56f1d71fd496c8a25d6b4b50e51d4a682d184.zip |
test: adding tests for initHooks API
Async wrap providers tested:
- crypto.randomBytes
- crypto.pbkdf2
- fs event wrap
- fsreqwrap access
- fsreqwrap readFile
- getaddrinforeq wrap
- getnameinforeq wrap
- pipe connect wrap
- query wrap
- pipewrap
- processwrap
- shutdown wrap
- tcpwrap
- udpwrap
- send wrap
- detailed signal wrap
- statwatcher
- timerwrap via setTimeout
- timerwrap via setInterval
- for Immediate
- http parser request
- http parser response
- connection via ssl server
- tls wrap
- write wrap
- ttywrap via readstream
- ttywrap via wriream
- zctx via zlib binding deflate
Embedder API:
- async-event tests
- one test looks at the happy paths
- another ensures that in cases of events emitted in an order that
doesn't make sense, the order is enforced by async hooks throwing a
meaningful error
- embedder enforcement tests are split up since async hook stack
corruption now the process
- therefore we launch a child and check for error output of the offending code
Additional tests:
- tests that show that we can enable/disable hooks inside their lifetime
events
- tests that verify the graph of resources triggering the creation of
other resources
Test Helpers:
- init-hooks:
- returns one collector instance
- when created an async hook is created and the lifetime events are
registered to call the appropriate collector functions
- the collector also exposes `enable` and `disable` functions which call
through to the async hook
- hook checks:
- checks invocations of life time hooks against the actual invocations
that were collected
- in some cases like `destroy` a min/max range of invocations can be
supplied since in these cases the exact number is non-deterministic
- verify graph:
- verifies the triggerIds of specific async resources are as expected,
i.e. the creation of resources was triggered by the resource we expect
- includes a printGraph function to generate easily readable test
input for verify graph
- both functions prune TickObjects to create less brittle and easier
to understand tests
PR-URL: https://github.com/nodejs/node/pull/12892
Ref: https://github.com/nodejs/node/pull/11883
Ref: https://github.com/nodejs/node/pull/8531
Reviewed-By: Andreas Madsen <amwebdk@gmail.com>
Reviewed-By: Anna Henningsen <anna@addaleax.net>
Reviewed-By: Sam Roberts <vieuxtech@gmail.com>
Reviewed-By: Matteo Collina <matteo.collina@gmail.com>
Reviewed-By: Refael Ackermann <refack@gmail.com>
Reviewed-By: James M Snell <jasnell@gmail.com>
Reviewed-By: Jeremiah Senkpiel <fishrock123@rocketmail.com>
Diffstat (limited to 'test/async-hooks/verify-graph.js')
-rw-r--r-- | test/async-hooks/verify-graph.js | 114 |
1 files changed, 114 insertions, 0 deletions
diff --git a/test/async-hooks/verify-graph.js b/test/async-hooks/verify-graph.js new file mode 100644 index 0000000000..e87dd5596c --- /dev/null +++ b/test/async-hooks/verify-graph.js @@ -0,0 +1,114 @@ +'use strict'; + +const assert = require('assert'); +require('../common'); + +function findInGraph(graph, type, n) { + let found = 0; + for (let i = 0; i < graph.length; i++) { + const node = graph[i]; + if (node.type === type) found++; + if (found === n) return node; + } +} + +function pruneTickObjects(activities) { + // remove one TickObject on each pass until none is left anymore + // not super efficient, but simplest especially to handle + // multiple TickObjects in a row + let foundTickObject = true; + + while (foundTickObject) { + foundTickObject = false; + let tickObjectIdx = -1; + for (let i = 0; i < activities.length; i++) { + if (activities[i].type !== 'TickObject') continue; + tickObjectIdx = i; + break; + } + + if (tickObjectIdx >= 0) { + foundTickObject = true; + + // point all triggerIds that point to the tickObject + // to its triggerId and findally remove it from the activities + const tickObject = activities[tickObjectIdx]; + const newTriggerId = tickObject.triggerId; + const oldTriggerId = tickObject.uid; + activities.forEach(function repointTriggerId(x) { + if (x.triggerId === oldTriggerId) x.triggerId = newTriggerId; + }); + activities.splice(tickObjectIdx, 1); + } + } + return activities; +} + +module.exports = function verifyGraph(hooks, graph) { + pruneTickObjects(hooks); + + // map actual ids to standin ids defined in the graph + const idtouid = {}; + const uidtoid = {}; + const typeSeen = {}; + const errors = []; + + const activities = pruneTickObjects(hooks.activities); + activities.forEach(processActivity); + + function processActivity(x) { + if (!typeSeen[x.type]) typeSeen[x.type] = 0; + typeSeen[x.type]++; + + const node = findInGraph(graph, x.type, typeSeen[x.type]); + if (node == null) return; + + idtouid[node.id] = x.uid; + uidtoid[x.uid] = node.id; + if (node.triggerId == null) return; + + const tid = idtouid[node.triggerId]; + if (x.triggerId === tid) return; + + errors.push({ + id: node.id, + expectedTid: node.triggerId, + actualTid: uidtoid[x.triggerId] + }); + } + + if (errors.length) { + errors.forEach((x) => + console.error( + `'${x.id}' expected to be triggered by '${x.expectedTid}', ` + + `but was triggered by '${x.actualTid}' instead.` + ) + ); + } + assert.strictEqual(errors.length, 0, 'Found errors while verifying graph.'); +}; + +// +// Helper to generate the input to the verifyGraph tests +// +function inspect(obj, depth) { + console.error(require('util').inspect(obj, false, depth || 5, true)); +} + +module.exports.printGraph = function printGraph(hooks) { + const ids = {}; + const uidtoid = {}; + const activities = pruneTickObjects(hooks.activities); + const graph = []; + activities.forEach(procesNode); + + function procesNode(x) { + const key = x.type.replace(/WRAP/, '').toLowerCase(); + if (!ids[key]) ids[key] = 1; + const id = key + ':' + ids[key]++; + uidtoid[x.uid] = id; + const triggerId = uidtoid[x.triggerId] || null; + graph.push({ type: x.type, id, triggerId }); + } + inspect(graph); +}; |