API/api.medcify.app/node_modules/continuation-local-storage/test/tracer-scenarios.tap.js
2022-09-26 11:41:44 +05:30

339 lines
9.6 KiB
JavaScript

'use strict';
var EventEmitter = require('events').EventEmitter
, assert = require('assert')
, test = require('tap').test
, cls = require('../context.js')
;
var nextID = 1;
function fresh(name) {
assert.ok(!cls.getNamespace(name), "namespace " + name + " already exists");
return cls.createNamespace(name);
}
function destroy(name) {
return function destroyer(t) {
cls.destroyNamespace(name);
assert.ok(!cls.getNamespace(name), "namespace '" + name + "' should no longer exist");
t.end();
};
}
function runInTransaction(name, fn) {
var namespace = cls.getNamespace(name);
assert(namespace, "namespaces " + name + " doesn't exist");
var context = namespace.createContext();
context.transaction = ++nextID;
process.nextTick(namespace.bind(fn, context));
}
test("asynchronous state propagation", function (t) {
t.plan(24);
t.test("a. async transaction with setTimeout", function (t) {
t.plan(2);
var namespace = fresh('a', this);
function handler() {
t.ok(namespace.get('transaction'), "transaction should be visible");
}
t.notOk(namespace.get('transaction'), "transaction should not yet be visible");
runInTransaction('a', function () { setTimeout(handler, 100); });
});
t.test("a. cleanup", destroy('a'));
t.test("b. async transaction with setInterval", function (t) {
t.plan(4);
var namespace = fresh('b', this)
, count = 0
, handle
;
function handler() {
count += 1;
if (count > 2) clearInterval(handle);
t.ok(namespace.get('transaction'), "transaction should be visible");
}
t.notOk(namespace.get('transaction'), "transaction should not yet be visible");
runInTransaction('b', function () { handle = setInterval(handler, 50); });
});
t.test("b. cleanup", destroy('b'));
t.test("c. async transaction with process.nextTick", function (t) {
t.plan(2);
var namespace = fresh('c', this);
function handler() {
t.ok(namespace.get('transaction'), "transaction should be visible");
}
t.notOk(namespace.get('transaction'), "transaction should not yet be visible");
runInTransaction('c', function () { process.nextTick(handler); });
});
t.test("c. cleanup", destroy('c'));
t.test("d. async transaction with EventEmitter.emit", function (t) {
t.plan(2);
var namespace = fresh('d', this)
, ee = new EventEmitter()
;
function handler() {
t.ok(namespace.get('transaction'), "transaction should be visible");
}
t.notOk(namespace.get('transaction'), "transaction should not yet be visible");
runInTransaction('d', function () {
ee.on('transaction', handler);
ee.emit('transaction');
});
});
t.test("d. cleanup", destroy('d'));
t.test("e. two overlapping async transactions with setTimeout", function (t) {
t.plan(6);
var namespace = fresh('e', this)
, first
, second
;
function handler(id) {
t.ok(namespace.get('transaction'), "transaction should be visible");
t.equal(namespace.get('transaction'), id, "transaction matches");
}
t.notOk(namespace.get('transaction'), "transaction should not yet be visible");
runInTransaction('e', function () {
first = namespace.get('transaction');
setTimeout(handler.bind(null, first), 100);
});
setTimeout(function () {
runInTransaction('e', function () {
second = namespace.get('transaction');
t.notEqual(first, second, "different transaction IDs");
setTimeout(handler.bind(null, second), 100);
});
}, 25);
});
t.test("e. cleanup", destroy('e'));
t.test("f. two overlapping async transactions with setInterval", function (t) {
t.plan(15);
var namespace = fresh('f', this);
function runInterval() {
var count = 0
, handle
, id
;
function handler() {
count += 1;
if (count > 2) clearInterval(handle);
t.ok(namespace.get('transaction'), "transaction should be visible");
t.equal(id, namespace.get('transaction'), "transaction ID should be immutable");
}
function run() {
t.ok(namespace.get('transaction'), "transaction should have been created");
id = namespace.get('transaction');
handle = setInterval(handler, 50);
}
runInTransaction('f', run);
}
t.notOk(namespace.get('transaction'), "transaction should not yet be visible");
runInterval(); runInterval();
});
t.test("f. cleanup", destroy('f'));
t.test("g. two overlapping async transactions with process.nextTick", function (t) {
t.plan(6);
var namespace = fresh('g', this)
, first
, second
;
function handler(id) {
var transaction = namespace.get('transaction');
t.ok(transaction, "transaction should be visible");
t.equal(transaction, id, "transaction matches");
}
t.notOk(namespace.get('transaction'), "transaction should not yet be visible");
runInTransaction('g', function () {
first = namespace.get('transaction');
process.nextTick(handler.bind(null, first));
});
process.nextTick(function () {
runInTransaction('g', function () {
second = namespace.get('transaction');
t.notEqual(first, second, "different transaction IDs");
process.nextTick(handler.bind(null, second));
});
});
});
t.test("g. cleanup", destroy('g'));
t.test("h. two overlapping async runs with EventEmitter.prototype.emit", function (t) {
t.plan(3);
var namespace = fresh('h', this)
, ee = new EventEmitter()
;
function handler() {
t.ok(namespace.get('transaction'), "transaction should be visible");
}
function lifecycle() {
ee.once('transaction', process.nextTick.bind(process, handler));
ee.emit('transaction');
}
t.notOk(namespace.get('transaction'), "transaction should not yet be visible");
runInTransaction('h', lifecycle);
runInTransaction('h', lifecycle);
});
t.test("h. cleanup", destroy('h'));
t.test("i. async transaction with an async sub-call with setTimeout", function (t) {
t.plan(5);
var namespace = fresh('i', this);
function inner(callback) {
setTimeout(function () {
t.ok(namespace.get('transaction'), "transaction should (yep) still be visible");
callback();
}, 50);
}
function outer() {
t.ok(namespace.get('transaction'), "transaction should be visible");
setTimeout(function () {
t.ok(namespace.get('transaction'), "transaction should still be visible");
inner(function () {
t.ok(namespace.get('transaction'), "transaction should even still be visible");
});
}, 50);
}
t.notOk(namespace.get('transaction'), "transaction should not yet be visible");
runInTransaction('i', setTimeout.bind(null, outer, 50));
});
t.test("i. cleanup", destroy('i'));
t.test("j. async transaction with an async sub-call with setInterval", function (t) {
t.plan(5);
var namespace = fresh('j', this)
, outerHandle
, innerHandle
;
function inner(callback) {
innerHandle = setInterval(function () {
clearInterval(innerHandle);
t.ok(namespace.get('transaction'), "transaction should (yep) still be visible");
callback();
}, 50);
}
function outer() {
t.ok(namespace.get('transaction'), "transaction should be visible");
outerHandle = setInterval(function () {
clearInterval(outerHandle);
t.ok(namespace.get('transaction'), "transaction should still be visible");
inner(function () {
t.ok(namespace.get('transaction'), "transaction should even still be visible");
});
}, 50);
}
t.notOk(namespace.get('transaction'), "transaction should not yet be visible");
runInTransaction('j', outer);
});
t.test("j. cleanup", destroy('j'));
t.test("k. async transaction with an async call with process.nextTick", function (t) {
t.plan(5);
var namespace = fresh('k', this);
function inner(callback) {
process.nextTick(function () {
t.ok(namespace.get('transaction'), "transaction should (yep) still be visible");
callback();
});
}
function outer() {
t.ok(namespace.get('transaction'), "transaction should be visible");
process.nextTick(function () {
t.ok(namespace.get('transaction'), "transaction should still be visible");
inner(function () {
t.ok(namespace.get('transaction'), "transaction should even still be visible");
});
});
}
t.notOk(namespace.get('transaction'), "transaction should not yet be visible");
runInTransaction('k', function () { process.nextTick(outer); });
});
t.test("k. cleanup", destroy('k'));
t.test("l. async transaction with an async call with EventEmitter.emit", function (t) {
t.plan(4);
var namespace = fresh('l', this)
, outer = new EventEmitter()
, inner = new EventEmitter()
;
inner.on('pong', function (callback) {
t.ok(namespace.get('transaction'), "transaction should still be visible");
callback();
});
function outerCallback() {
t.ok(namespace.get('transaction'), "transaction should even still be visible");
}
outer.on('ping', function () {
t.ok(namespace.get('transaction'), "transaction should be visible");
inner.emit('pong', outerCallback);
});
t.notOk(namespace.get('transaction'), "transaction should not yet be visible");
runInTransaction('l', outer.emit.bind(outer, 'ping'));
});
t.test("l. cleanup", destroy('l'));
});