From 727c17f4163ff44b90be87f71e43ad6924874fe4 Mon Sep 17 00:00:00 2001 From: jordigh Date: Fri, 23 Jun 2023 12:53:34 -0400 Subject: [PATCH] chore(test): convert trace unit test to tap style (#1692) --- test/unit/trace.test.js | 916 +++++++++++++++++++++------------------- 1 file changed, 473 insertions(+), 443 deletions(-) diff --git a/test/unit/trace.test.js b/test/unit/trace.test.js index 7f037cc6c5..9ff93a7486 100644 --- a/test/unit/trace.test.js +++ b/test/unit/trace.test.js @@ -6,15 +6,10 @@ 'use strict' const tap = require('tap') -// TODO: convert to normal tap style. -// Below allows use of mocha DSL with tap runner. -tap.mochaGlobals() const util = require('util') const sinon = require('sinon') -const chai = require('chai') const DESTINATIONS = require('../../lib/config/attribute-filter').DESTINATIONS -const expect = chai.expect const helper = require('../lib/agent_helper') const codec = require('../../lib/util/codec') const codecEncodeAsync = util.promisify(codec.encode) @@ -26,184 +21,67 @@ const Transaction = require('../../lib/transaction') const NEWRELIC_TRACE_HEADER = 'newrelic' -describe('Trace', function () { +tap.test('Trace', (t) => { + t.autoend() let agent = null - beforeEach(function () { + t.beforeEach(() => { agent = helper.loadMockedAgent() }) - afterEach(function () { + t.afterEach(() => { helper.unloadAgent(agent) }) - it('should always be bound to a transaction', function () { + t.test('should always be bound to a transaction', (t) => { // fail - expect(function () { + t.throws(() => { return new Trace() - }).throws(/must be associated with a transaction/) + }, /must be associated with a transaction/) // succeed const transaction = new Transaction(agent) const tt = new Trace(transaction) - expect(tt.transaction).to.be.an.instanceof(Transaction) + t.type(tt.transaction, Transaction) + t.end() }) - it('should have the root of a Segment tree', function () { + t.test('should have the root of a Segment tree', (t) => { const tt = new Trace(new Transaction(agent)) - expect(tt.root).to.be.an.instanceof(Segment) + t.type(tt.root, Segment) + t.end() }) - it('should be the primary interface for adding segments to a trace', function () { + t.test('should be the primary interface for adding segments to a trace', (t) => { const transaction = new Transaction(agent) const trace = transaction.trace - expect(function () { + t.doesNotThrow(() => { trace.add('Custom/Test17/Child1') - }).to.not.throw() - }) - - describe('when serializing synchronously', () => { - let details - - beforeEach(async () => { - details = await makeTrace(agent) - }) - - it('should produce a transaction trace in the expected format', async function () { - const traceJSON = details.trace.generateJSONSync() - const reconstituted = await codecDecodeAsync(traceJSON[4]) - expect(traceJSON, 'full trace JSON').to.deep.equal(details.expectedEncoding) - - expect(reconstituted, 'reconstituted trace segments').to.deep.equal(details.rootNode) - }) - - it('should send response time', function () { - details.transaction.getResponseTimeInMillis = function () { - return 1234 - } - - const json = details.trace.generateJSONSync() - expect(json[1]).to.equal(1234) - }) - - describe('when `simple_compression` is `false`', function () { - it('should compress the segment arrays', async function () { - const json = details.trace.generateJSONSync() - - expect(json[4]).to.match(/^[a-zA-Z0-9\+\/]+={0,2}$/, 'should be base64 encoded') - - const data = await codecDecodeAsync(json[4]) - expect(data).to.deep.equal(details.rootNode) - }) - }) - - describe('when `simple_compression` is `true`', function () { - beforeEach(function () { - agent.config.simple_compression = true - }) - - it('should not compress the segment arrays', function () { - const json = details.trace.generateJSONSync() - expect(json[4]).to.deep.equal(details.rootNode) - }) - }) - - describe('when url_obfuscation is set', function () { - it('should obfuscate the URL', function () { - agent.config.url_obfuscation = { - enabled: true, - regex: { - pattern: '.*', - replacement: '/***' - } - } - - const json = details.trace.generateJSONSync() - expect(json[3]).to.equal('/***') - }) - }) - }) - - describe('when serializing asynchronously', () => { - let details - - beforeEach(async () => { - details = await makeTrace(agent) - }) - - it('should produce a transaction trace in the expected format', async function () { - const traceJSON = await details.trace.generateJSONAsync() - const reconstituted = await codecDecodeAsync(traceJSON[4]) - - expect(traceJSON, 'full trace JSON').to.deep.equal(details.expectedEncoding) - - expect(reconstituted, 'reconstituted trace segments').to.deep.equal(details.rootNode) - }) - - it('should send response time', function () { - details.transaction.getResponseTimeInMillis = function () { - return 1234 - } - - // not using `trace.generateJSONAsync` because - // util.promisify only returns 1st arg in callback - // see: https://github.com/nodejs/node/blob/master/lib/internal/util.js#L332 - return new Promise((resolve, reject) => { - details.trace.generateJSON((err, json, trace) => { - if (err) { - reject(err) - } - - expect(json[1]).to.equal(1234) - expect(trace).to.equal(details.trace) - resolve() - }) - }) - }) - - describe('when `simple_compression` is `false`', function () { - it('should compress the segment arrays', async function () { - const json = await details.trace.generateJSONAsync() - expect(json[4]).to.match(/^[a-zA-Z0-9\+\/]+={0,2}$/, 'should be base64 encoded') - - const data = await codecDecodeAsync(json[4]) - expect(data).to.deep.equal(details.rootNode) - }) - }) - - describe('when `simple_compression` is `true`', function () { - beforeEach(function () { - agent.config.simple_compression = true - }) - - it('should not compress the segment arrays', async function () { - const json = await details.trace.generateJSONAsync() - expect(json[4]).to.deep.equal(details.rootNode) - }) }) + t.end() }) - it('should have DT attributes on transaction end', function (done) { + t.test('should have DT attributes on transaction end', (t) => { agent.config.distributed_tracing.enabled = true agent.config.primary_application_id = 'test' agent.config.account_id = 1 helper.runInTransaction(agent, function (tx) { tx.end() const attributes = tx.trace.intrinsics - expect(attributes.traceId).to.equal(tx.traceId) - expect(attributes.guid).to.equal(tx.id) - expect(attributes.priority).to.equal(tx.priority) - expect(attributes.sampled).to.equal(tx.sampled) - expect(attributes.parentId).to.be.undefined - expect(attributes.parentSpanId).to.be.undefined - expect(tx.sampled).to.equal(true) - expect(tx.priority).to.be.greaterThan(1) - done() + t.equal(attributes.traceId, tx.traceId) + t.equal(attributes.guid, tx.id) + t.equal(attributes.priority, tx.priority) + t.equal(attributes.sampled, tx.sampled) + t.equal(attributes.parentId, undefined) + t.equal(attributes.parentSpanId, undefined) + t.equal(tx.sampled, true) + t.ok(tx.priority > 1) + t.end() }) }) - it('should have DT parent attributes on payload accept', function () { + t.test('should have DT parent attributes on payload accept', (t) => { agent.config.distributed_tracing.enabled = true agent.config.primary_application_id = 'test' agent.config.account_id = 1 @@ -213,21 +91,22 @@ describe('Trace', function () { tx._acceptDistributedTracePayload(payload) tx.end() const attributes = tx.trace.intrinsics - expect(attributes.traceId).to.equal(tx.traceId) - expect(attributes.guid).to.equal(tx.id) - expect(attributes.priority).to.equal(tx.priority) - expect(attributes.sampled).to.equal(tx.sampled) - expect(attributes['parent.type']).to.equal('App') - expect(attributes['parent.app']).to.equal(agent.config.primary_application_id) - expect(attributes['parent.account']).to.equal(agent.config.account_id) - expect(attributes.parentId).to.be.undefined - expect(attributes.parentSpanId).to.be.undefined - expect(tx.sampled).to.equal(true) - expect(tx.priority).to.be.greaterThan(1) + t.equal(attributes.traceId, tx.traceId) + t.equal(attributes.guid, tx.id) + t.equal(attributes.priority, tx.priority) + t.equal(attributes.sampled, tx.sampled) + t.equal(attributes['parent.type'], 'App') + t.equal(attributes['parent.app'], agent.config.primary_application_id) + t.equal(attributes['parent.account'], agent.config.account_id) + t.equal(attributes.parentId, undefined) + t.equal(attributes.parentSpanId, undefined) + t.equal(tx.sampled, true) + t.ok(tx.priority > 1) + t.end() }) }) - it('should generate span events', function () { + t.test('should generate span events', (t) => { agent.config.span_events.enabled = true agent.config.distributed_tracing.enabled = true @@ -247,30 +126,46 @@ describe('Trace', function () { const events = agent.spanEventAggregator.getEvents() const nested = events[0] const testSpan = events[1] - expect(nested).to.have.property('intrinsics') - expect(testSpan).to.have.property('intrinsics') - - expect(nested.intrinsics).to.have.property('parentId', testSpan.intrinsics.guid) - expect(nested.intrinsics).to.have.property('category', 'generic') - expect(nested.intrinsics).to.have.property('priority', transaction.priority) - expect(nested.intrinsics).to.have.property('transactionId', transaction.id) - expect(nested.intrinsics).to.have.property('sampled', transaction.sampled) - expect(nested.intrinsics).to.have.property('name', 'nested') - expect(nested.intrinsics).to.have.property('traceId', transaction.traceId) - expect(nested.intrinsics).to.have.property('timestamp') - - expect(testSpan.intrinsics).to.have.property('parentId', null) - expect(testSpan.intrinsics).to.have.property('nr.entryPoint').and.be.true - expect(testSpan.intrinsics).to.have.property('category', 'generic') - expect(testSpan.intrinsics).to.have.property('priority', transaction.priority) - expect(testSpan.intrinsics).to.have.property('transactionId', transaction.id) - expect(testSpan.intrinsics).to.have.property('sampled', transaction.sampled) - expect(testSpan.intrinsics).to.have.property('name', 'test') - expect(testSpan.intrinsics).to.have.property('traceId', transaction.traceId) - expect(testSpan.intrinsics).to.have.property('timestamp') - }) - - it('should not generate span events on end if span_events is disabled', function () { + t.hasProp(nested, 'intrinsics') + t.hasProp(testSpan, 'intrinsics') + + t.hasProp(nested.intrinsics, 'parentId') + t.equal(nested.intrinsics.parentId, testSpan.intrinsics.guid) + t.hasProp(nested.intrinsics, 'category') + t.equal(nested.intrinsics.category, 'generic') + t.hasProp(nested.intrinsics, 'priority') + t.equal(nested.intrinsics.priority, transaction.priority) + t.hasProp(nested.intrinsics, 'transactionId') + t.equal(nested.intrinsics.transactionId, transaction.id) + t.hasProp(nested.intrinsics, 'sampled') + t.equal(nested.intrinsics.sampled, transaction.sampled) + t.hasProp(nested.intrinsics, 'name') + t.equal(nested.intrinsics.name, 'nested') + t.hasProp(nested.intrinsics, 'traceId') + t.equal(nested.intrinsics.traceId, transaction.traceId) + t.hasProp(nested.intrinsics, 'timestamp') + + t.hasProp(testSpan.intrinsics, 'parentId') + t.equal(testSpan.intrinsics.parentId, null) + t.hasProp(testSpan.intrinsics, 'nr.entryPoint') + t.ok(testSpan.intrinsics['nr.entryPoint']) + t.hasProp(testSpan.intrinsics, 'category') + t.equal(testSpan.intrinsics.category, 'generic') + t.hasProp(testSpan.intrinsics, 'priority') + t.equal(testSpan.intrinsics.priority, transaction.priority) + t.hasProp(testSpan.intrinsics, 'transactionId') + t.equal(testSpan.intrinsics.transactionId, transaction.id) + t.hasProp(testSpan.intrinsics, 'sampled') + t.equal(testSpan.intrinsics.sampled, transaction.sampled) + t.hasProp(testSpan.intrinsics, 'name') + t.equal(testSpan.intrinsics.name, 'test') + t.hasProp(testSpan.intrinsics, 'traceId') + t.equal(testSpan.intrinsics.traceId, transaction.traceId) + t.hasProp(testSpan.intrinsics, 'timestamp') + t.end() + }) + + t.test('should not generate span events on end if span_events is disabled', (t) => { agent.config.span_events.enabled = false agent.config.distributed_tracing.enabled = true @@ -287,10 +182,11 @@ describe('Trace', function () { transaction.end() const events = agent.spanEventAggregator.getEvents() - expect(events.length).to.equal(0) + t.equal(events.length, 0) + t.end() }) - it('should not generate span events on end if distributed_tracing is off', function () { + t.test('should not generate span events on end if distributed_tracing is off', (t) => { agent.config.span_events.enabled = true agent.config.distributed_tracing.enabled = false @@ -307,10 +203,11 @@ describe('Trace', function () { transaction.end() const events = agent.spanEventAggregator.getEvents() - expect(events.length).to.equal(0) + t.equal(events.length, 0) + t.end() }) - it('should not generate span events on end if transaction is not sampled', function () { + t.test('should not generate span events on end if transaction is not sampled', (t) => { agent.config.span_events.enabled = true agent.config.distributed_tracing.enabled = false @@ -330,10 +227,11 @@ describe('Trace', function () { transaction.end() const events = agent.spanEventAggregator.getEvents() - expect(events.length).to.equal(0) + t.equal(events.length, 0) + t.end() }) - it('parent.* attributes should be present on generated spans', function () { + t.test('parent.* attributes should be present on generated spans', (t) => { // Setup DT const encKey = 'gringletoes' agent.config.encoding_key = encKey @@ -371,27 +269,29 @@ describe('Trace', function () { // Test that a child span event has the attributes const attrs = child.attributes.get(DESTINATIONS.SPAN_EVENT) - expect(attrs).deep.equal({ + t.same(attrs, { 'parent.type': 'App', 'parent.app': 222, 'parent.account': 111, 'parent.transportType': 'HTTP', 'parent.transportDuration': 0 }) + t.end() }) - it('should send host display name on transaction when set by user', function () { + t.test('should send host display name on transaction when set by user', (t) => { agent.config.attributes.enabled = true agent.config.process_host.display_name = 'test-value' const trace = new Trace(new Transaction(agent)) - expect(trace.attributes.get(DESTINATIONS.TRANS_TRACE)).deep.equal({ + t.same(trace.attributes.get(DESTINATIONS.TRANS_TRACE), { 'host.displayName': 'test-value' }) + t.end() }) - it('should send host display name attribute on span', function () { + t.test('should send host display name attribute on span', (t) => { agent.config.attributes.enabled = true agent.config.distributed_tracing.enabled = true agent.config.process_host.display_name = 'test-value' @@ -407,292 +307,447 @@ describe('Trace', function () { trace.generateSpanEvents() - expect(child.attributes.get(DESTINATIONS.SPAN_EVENT)).deep.equal({ + t.same(child.attributes.get(DESTINATIONS.SPAN_EVENT), { 'host.displayName': 'test-value' }) + t.end() }) - it('should not send host display name when not set by user', function () { + t.test('should not send host display name when not set by user', (t) => { const trace = new Trace(new Transaction(agent)) - expect(trace.attributes.get(DESTINATIONS.TRANS_TRACE)).deep.equal({}) + t.same(trace.attributes.get(DESTINATIONS.TRANS_TRACE), {}) + t.end() }) +}) - describe('when inserting segments', function () { - let trace = null - let transaction = null +tap.test('when serializing synchronously', (t) => { + t.autoend() + let details - beforeEach(function () { - transaction = new Transaction(agent) - trace = transaction.trace - }) + let agent = null - it('should allow child segments on a trace', function () { - expect(function () { - trace.add('Custom/Test17/Child1') - }).not.throws() - }) + t.beforeEach(async () => { + agent = helper.loadMockedAgent() + details = await makeTrace(t, agent) + }) - it('should return the segment', function () { - let segment - expect(function () { - segment = trace.add('Custom/Test18/Child1') - }).not.throws() - expect(segment).instanceof(Segment) - }) + t.afterEach(() => { + helper.unloadAgent(agent) + }) + + t.test('should produce a transaction trace in the expected format', async (t) => { + const traceJSON = details.trace.generateJSONSync() + const reconstituted = await codecDecodeAsync(traceJSON[4]) + t.same(traceJSON, details.expectedEncoding, 'full trace JSON') + + t.same(reconstituted, details.rootNode, 'reconstituted trace segments') + t.end() + }) + + t.test('should send response time', (t) => { + details.transaction.getResponseTimeInMillis = () => { + return 1234 + } + + const json = details.trace.generateJSONSync() + t.equal(json[1], 1234) + t.end() + }) - it('should call a function associated with the segment', function (done) { - const segment = trace.add('Custom/Test18/Child1', function () { - return done() + t.test('when `simple_compression` is `false`, should compress the segment arrays', async (t) => { + const json = details.trace.generateJSONSync() + + t.match(json[4], /^[a-zA-Z0-9\+\/]+={0,2}$/, 'should be base64 encoded') + + const data = await codecDecodeAsync(json[4]) + t.same(data, details.rootNode) + t.end() + }) + + t.test('when `simple_compression` is `true`, should not compress the segment arrays', (t) => { + agent.config.simple_compression = true + const json = details.trace.generateJSONSync() + t.same(json[4], details.rootNode) + t.end() + }) + + t.test('when url_obfuscation is set, should obfuscate the URL', (t) => { + agent.config.url_obfuscation = { + enabled: true, + regex: { + pattern: '.*', + replacement: '/***' + } + } + + const json = details.trace.generateJSONSync() + t.equal(json[3], '/***') + t.end() + }) +}) + +tap.test('when serializing asynchronously', (t) => { + t.autoend() + + let details + + let agent = null + + t.beforeEach(async () => { + agent = helper.loadMockedAgent() + details = await makeTrace(t, agent) + }) + + t.afterEach(() => { + helper.unloadAgent(agent) + }) + + t.test('should produce a transaction trace in the expected format', async (t) => { + const traceJSON = await details.trace.generateJSONAsync() + const reconstituted = await codecDecodeAsync(traceJSON[4]) + + t.same(traceJSON, details.expectedEncoding, 'full trace JSON') + + t.same(reconstituted, details.rootNode, 'reconstituted trace segments') + t.end() + }) + + t.test('should send response time', (t) => { + details.transaction.getResponseTimeInMillis = () => { + return 1234 + } + + // not using `trace.generateJSONAsync` because + // util.promisify only returns 1st arg in callback + // see: https://github.com/nodejs/node/blob/master/lib/internal/util.js#L332 + return new Promise((resolve, reject) => { + details.trace.generateJSON((err, json, trace) => { + if (err) { + reject(err) + } + + t.equal(json[1], 1234) + t.equal(trace, details.trace) + resolve() }) + }) + t.end() + }) + + t.test('when `simple_compression` is `false`, should compress the segment arrays', async (t) => { + const json = await details.trace.generateJSONAsync() + t.match(json[4], /^[a-zA-Z0-9\+\/]+={0,2}$/, 'should be base64 encoded') + + const data = await codecDecodeAsync(json[4]) + t.same(data, details.rootNode) + t.end() + }) + + t.test( + 'when `simple_compression` is `true`, should not compress the segment arrays', + async (t) => { + agent.config.simple_compression = true + const json = await details.trace.generateJSONAsync() + t.same(json[4], details.rootNode) + t.end() + } + ) +}) + +tap.test('when inserting segments', (t) => { + t.autoend() + let agent + let trace = null + let transaction = null - segment.end() - transaction.end() + t.beforeEach(() => { + agent = helper.loadMockedAgent() + transaction = new Transaction(agent) + trace = transaction.trace + }) + + t.afterEach(() => { + helper.unloadAgent(agent) + }) + + t.test('should allow child segments on a trace', (t) => { + t.doesNotThrow(() => { + trace.add('Custom/Test17/Child1') }) + t.end() + }) - it('should report total time', function () { - trace.setDurationInMillis(40, 0) - const child = trace.add('Custom/Test18/Child1') - child.setDurationInMillis(27, 0) - let seg = child.add('UnitTest') - seg.setDurationInMillis(9, 1) - seg = child.add('UnitTest1') - seg.setDurationInMillis(13, 1) - seg = child.add('UnitTest2') - seg.setDurationInMillis(9, 16) - seg = child.add('UnitTest2') - seg.setDurationInMillis(14, 16) - expect(trace.getTotalTimeDurationInMillis()).equal(48) + t.test('should return the segment', (t) => { + let segment + t.doesNotThrow(() => { + segment = trace.add('Custom/Test18/Child1') }) + t.type(segment, Segment) + t.end() + }) - it('should report total time on branched traces', function () { - trace.setDurationInMillis(40, 0) - const child = trace.add('Custom/Test18/Child1') - child.setDurationInMillis(27, 0) - const seg1 = child.add('UnitTest') - seg1.setDurationInMillis(9, 1) - let seg = child.add('UnitTest1') - seg.setDurationInMillis(13, 1) - seg = seg1.add('UnitTest2') - seg.setDurationInMillis(9, 16) - seg = seg1.add('UnitTest2') - seg.setDurationInMillis(14, 16) - expect(trace.getTotalTimeDurationInMillis()).equal(48) + t.test('should call a function associated with the segment', (t) => { + const segment = trace.add('Custom/Test18/Child1', () => { + t.end() }) - it('should report the expected trees for trees with uncollected segments', () => { - const expectedTrace = [ - 0, - 27, - 'Root', - { nr_exclusive_duration_millis: 3 }, + segment.end() + transaction.end() + }) + + t.test('should report total time', (t) => { + trace.setDurationInMillis(40, 0) + const child = trace.add('Custom/Test18/Child1') + child.setDurationInMillis(27, 0) + let seg = child.add('UnitTest') + seg.setDurationInMillis(9, 1) + seg = child.add('UnitTest1') + seg.setDurationInMillis(13, 1) + seg = child.add('UnitTest2') + seg.setDurationInMillis(9, 16) + seg = child.add('UnitTest2') + seg.setDurationInMillis(14, 16) + t.equal(trace.getTotalTimeDurationInMillis(), 48) + t.end() + }) + + t.test('should report total time on branched traces', (t) => { + trace.setDurationInMillis(40, 0) + const child = trace.add('Custom/Test18/Child1') + child.setDurationInMillis(27, 0) + const seg1 = child.add('UnitTest') + seg1.setDurationInMillis(9, 1) + let seg = child.add('UnitTest1') + seg.setDurationInMillis(13, 1) + seg = seg1.add('UnitTest2') + seg.setDurationInMillis(9, 16) + seg = seg1.add('UnitTest2') + seg.setDurationInMillis(14, 16) + t.equal(trace.getTotalTimeDurationInMillis(), 48) + t.end() + }) + + t.test('should report the expected trees for trees with uncollected segments', (t) => { + const expectedTrace = [ + 0, + 27, + 'Root', + { nr_exclusive_duration_millis: 3 }, + [ [ + 1, + 10, + 'first', + { nr_exclusive_duration_millis: 9 }, + [[16, 25, 'first-first', { nr_exclusive_duration_millis: 9 }, []]] + ], + [ + 1, + 14, + 'second', + { nr_exclusive_duration_millis: 13 }, [ - 1, - 10, - 'first', - { nr_exclusive_duration_millis: 9 }, - [[16, 25, 'first-first', { nr_exclusive_duration_millis: 9 }, []]] - ], - [ - 1, - 14, - 'second', - { nr_exclusive_duration_millis: 13 }, - [ - [16, 25, 'second-first', { nr_exclusive_duration_millis: 9 }, []], - [16, 25, 'second-second', { nr_exclusive_duration_millis: 9 }, []] - ] + [16, 25, 'second-first', { nr_exclusive_duration_millis: 9 }, []], + [16, 25, 'second-second', { nr_exclusive_duration_millis: 9 }, []] ] ] ] + ] - trace.setDurationInMillis(40, 0) - const child = trace.add('Root') - child.setDurationInMillis(27, 0) - const seg1 = child.add('first') - seg1.setDurationInMillis(9, 1) - const seg2 = child.add('second') - seg2.setDurationInMillis(13, 1) - let seg = seg1.add('first-first') - seg.setDurationInMillis(9, 16) - seg = seg1.add('first-second') - seg.setDurationInMillis(14, 16) - seg._collect = false - seg = seg2.add('second-first') - seg.setDurationInMillis(9, 16) - seg = seg2.add('second-second') - seg.setDurationInMillis(9, 16) - - trace.end() - - expect(child.toJSON()).deep.equal(expectedTrace) - }) + trace.setDurationInMillis(40, 0) + const child = trace.add('Root') + child.setDurationInMillis(27, 0) + const seg1 = child.add('first') + seg1.setDurationInMillis(9, 1) + const seg2 = child.add('second') + seg2.setDurationInMillis(13, 1) + let seg = seg1.add('first-first') + seg.setDurationInMillis(9, 16) + seg = seg1.add('first-second') + seg.setDurationInMillis(14, 16) + seg._collect = false + seg = seg2.add('second-first') + seg.setDurationInMillis(9, 16) + seg = seg2.add('second-second') + seg.setDurationInMillis(9, 16) + + trace.end() + + t.same(child.toJSON(), expectedTrace) + t.end() + }) - it('should report the expected trees for branched trees', function () { - const expectedTrace = [ - 0, - 27, - 'Root', - { nr_exclusive_duration_millis: 3 }, + t.test('should report the expected trees for branched trees', (t) => { + const expectedTrace = [ + 0, + 27, + 'Root', + { nr_exclusive_duration_millis: 3 }, + [ [ + 1, + 10, + 'first', + { nr_exclusive_duration_millis: 9 }, [ - 1, - 10, - 'first', - { nr_exclusive_duration_millis: 9 }, - [ - [16, 25, 'first-first', { nr_exclusive_duration_millis: 9 }, []], - [16, 30, 'first-second', { nr_exclusive_duration_millis: 14 }, []] - ] - ], + [16, 25, 'first-first', { nr_exclusive_duration_millis: 9 }, []], + [16, 30, 'first-second', { nr_exclusive_duration_millis: 14 }, []] + ] + ], + [ + 1, + 14, + 'second', + { nr_exclusive_duration_millis: 13 }, [ - 1, - 14, - 'second', - { nr_exclusive_duration_millis: 13 }, - [ - [16, 25, 'second-first', { nr_exclusive_duration_millis: 9 }, []], - [16, 25, 'second-second', { nr_exclusive_duration_millis: 9 }, []] - ] + [16, 25, 'second-first', { nr_exclusive_duration_millis: 9 }, []], + [16, 25, 'second-second', { nr_exclusive_duration_millis: 9 }, []] ] ] ] - trace.setDurationInMillis(40, 0) - const child = trace.add('Root') - child.setDurationInMillis(27, 0) - const seg1 = child.add('first') - seg1.setDurationInMillis(9, 1) - const seg2 = child.add('second') - seg2.setDurationInMillis(13, 1) - let seg = seg1.add('first-first') - seg.setDurationInMillis(9, 16) - seg = seg1.add('first-second') - seg.setDurationInMillis(14, 16) - seg = seg2.add('second-first') - seg.setDurationInMillis(9, 16) - seg = seg2.add('second-second') - seg.setDurationInMillis(9, 16) - - trace.end() - - expect(child.toJSON()).deep.equal(expectedTrace) - }) + ] + trace.setDurationInMillis(40, 0) + const child = trace.add('Root') + child.setDurationInMillis(27, 0) + const seg1 = child.add('first') + seg1.setDurationInMillis(9, 1) + const seg2 = child.add('second') + seg2.setDurationInMillis(13, 1) + let seg = seg1.add('first-first') + seg.setDurationInMillis(9, 16) + seg = seg1.add('first-second') + seg.setDurationInMillis(14, 16) + seg = seg2.add('second-first') + seg.setDurationInMillis(9, 16) + seg = seg2.add('second-second') + seg.setDurationInMillis(9, 16) + + trace.end() + + t.same(child.toJSON(), expectedTrace) + t.end() + }) - it('should measure exclusive time vs total time at each level of the graph', () => { - const child = trace.add('Custom/Test18/Child1') + t.test('should measure exclusive time vs total time at each level of the graph', (t) => { + const child = trace.add('Custom/Test18/Child1') - trace.setDurationInMillis(42) - child.setDurationInMillis(22, 0) + trace.setDurationInMillis(42) + child.setDurationInMillis(22, 0) - expect(trace.getExclusiveDurationInMillis()).equal(20) - }) + t.equal(trace.getExclusiveDurationInMillis(), 20) + t.end() + }) - it('should accurately sum overlapping segments', function () { - trace.setDurationInMillis(42) + t.test('should accurately sum overlapping segments', (t) => { + trace.setDurationInMillis(42) - const now = Date.now() + const now = Date.now() - const child1 = trace.add('Custom/Test19/Child1') - child1.setDurationInMillis(22, now) + const child1 = trace.add('Custom/Test19/Child1') + child1.setDurationInMillis(22, now) - // add another child trace completely encompassed by the first - const child2 = trace.add('Custom/Test19/Child2') - child2.setDurationInMillis(5, now + 5) + // add another child trace completely encompassed by the first + const child2 = trace.add('Custom/Test19/Child2') + child2.setDurationInMillis(5, now + 5) - // add another that starts within the first range but that extends beyond - const child3 = trace.add('Custom/Test19/Child3') - child3.setDurationInMillis(22, now + 11) + // add another that starts within the first range but that extends beyond + const child3 = trace.add('Custom/Test19/Child3') + child3.setDurationInMillis(22, now + 11) - // add a final child that's entirely disjoint - const child4 = trace.add('Custom/Test19/Child4') - child4.setDurationInMillis(4, now + 35) + // add a final child that's entirely disjoint + const child4 = trace.add('Custom/Test19/Child4') + child4.setDurationInMillis(4, now + 35) - expect(trace.getExclusiveDurationInMillis()).equal(5) - }) + t.equal(trace.getExclusiveDurationInMillis(), 5) + t.end() + }) - it('should accurately sum overlapping subtrees', function () { - trace.setDurationInMillis(42) + t.test('should accurately sum overlapping subtrees', (t) => { + trace.setDurationInMillis(42) - const now = Date.now() + const now = Date.now() - // create a long child on its own - const child1 = trace.add('Custom/Test20/Child1') - child1.setDurationInMillis(33, now) + // create a long child on its own + const child1 = trace.add('Custom/Test20/Child1') + child1.setDurationInMillis(33, now) - // add another, short child as a sibling - const child2 = child1.add('Custom/Test20/Child2') - child2.setDurationInMillis(5, now) + // add another, short child as a sibling + const child2 = child1.add('Custom/Test20/Child2') + child2.setDurationInMillis(5, now) - // add two disjoint children of the second segment encompassed by the first segment - const child3 = child2.add('Custom/Test20/Child3') - child3.setDurationInMillis(11, now) + // add two disjoint children of the second segment encompassed by the first segment + const child3 = child2.add('Custom/Test20/Child3') + child3.setDurationInMillis(11, now) - const child4 = child2.add('Custom/Test20/Child3') - child4.setDurationInMillis(11, now + 16) + const child4 = child2.add('Custom/Test20/Child3') + child4.setDurationInMillis(11, now + 16) - expect(trace.getExclusiveDurationInMillis()).equal(9) - expect(child4.getExclusiveDurationInMillis()).equal(11) - expect(child3.getExclusiveDurationInMillis()).equal(11) - expect(child2.getExclusiveDurationInMillis()).equal(0) - expect(child1.getExclusiveDurationInMillis()).equal(11) - }) + t.equal(trace.getExclusiveDurationInMillis(), 9) + t.equal(child4.getExclusiveDurationInMillis(), 11) + t.equal(child3.getExclusiveDurationInMillis(), 11) + t.equal(child2.getExclusiveDurationInMillis(), 0) + t.equal(child1.getExclusiveDurationInMillis(), 11) + t.end() + }) - it('should accurately sum partially overlapping segments', function () { - trace.setDurationInMillis(42) + t.test('should accurately sum partially overlapping segments', (t) => { + trace.setDurationInMillis(42) - const now = Date.now() + const now = Date.now() - const child1 = trace.add('Custom/Test20/Child1') - child1.setDurationInMillis(22, now) + const child1 = trace.add('Custom/Test20/Child1') + child1.setDurationInMillis(22, now) - // add another child trace completely encompassed by the first - const child2 = trace.add('Custom/Test20/Child2') - child2.setDurationInMillis(5, now + 5) + // add another child trace completely encompassed by the first + const child2 = trace.add('Custom/Test20/Child2') + child2.setDurationInMillis(5, now + 5) - /* add another that starts simultaneously with the first range but - * that extends beyond - */ - const child3 = trace.add('Custom/Test20/Child3') - child3.setDurationInMillis(33, now) + /* add another that starts simultaneously with the first range but + * that extends beyond + */ + const child3 = trace.add('Custom/Test20/Child3') + child3.setDurationInMillis(33, now) - expect(trace.getExclusiveDurationInMillis()).equal(9) - }) + t.equal(trace.getExclusiveDurationInMillis(), 9) + t.end() + }) - it('should accurately sum partially overlapping, open-ranged segments', function () { - trace.setDurationInMillis(42) + t.test('should accurately sum partially overlapping, open-ranged segments', (t) => { + trace.setDurationInMillis(42) - const now = Date.now() + const now = Date.now() - const child1 = trace.add('Custom/Test21/Child1') - child1.setDurationInMillis(22, now) + const child1 = trace.add('Custom/Test21/Child1') + child1.setDurationInMillis(22, now) - // add a range that starts at the exact end of the first - const child2 = trace.add('Custom/Test21/Child2') - child2.setDurationInMillis(11, now + 22) + // add a range that starts at the exact end of the first + const child2 = trace.add('Custom/Test21/Child2') + child2.setDurationInMillis(11, now + 22) - expect(trace.getExclusiveDurationInMillis()).equal(9) - }) + t.equal(trace.getExclusiveDurationInMillis(), 9) + t.end() + }) - it('should be limited to 900 children', function () { - // They will be tagged as _collect = false after the limit runs out. - for (let i = 0; i < 950; ++i) { - const segment = trace.add(i.toString(), noop) - if (i < 900) { - expect(segment._collect).equal(true) - } else { - expect(segment._collect).equal(false) - } + t.test('should be limited to 900 children', (t) => { + // They will be tagged as _collect = false after the limit runs out. + for (let i = 0; i < 950; ++i) { + const segment = trace.add(i.toString(), noop) + if (i < 900) { + t.equal(segment._collect, true, `segment ${i} should be collected`) + } else { + t.equal(segment._collect, false, `segment ${i} should not be collected`) } + } - expect(trace.root.children.length).equal(950) - expect(transaction._recorders.length).equal(950) - trace.segmentCount = 0 - trace.root.children = [] - trace.recorders = [] + t.equal(trace.root.children.length, 950) + t.equal(transaction._recorders.length, 950) + trace.segmentCount = 0 + trace.root.children = [] + trace.recorders = [] - function noop() {} - }) + function noop() {} + t.end() }) }) @@ -725,6 +780,7 @@ tap.test('should set URI to null when request.uri attribute is excluded globally }) tap.test('should set URI to null when request.uri attribute is exluded from traces', async (t) => { + t.autoend() const URL = '/test' const agent = helper.loadMockedAgent({ @@ -751,7 +807,6 @@ tap.test('should set URI to null when request.uri attribute is exluded from trac const traceJSON = await trace.generateJSON() const { 3: requestUri } = traceJSON t.notOk(requestUri) - t.end() }) tap.test('should set URI to /Unknown when URL is not known/set on transaction', async (t) => { @@ -805,7 +860,7 @@ tap.test('should obfuscate URI using regex when pattern is set', async (t) => { t.end() }) -async function makeTrace(agent) { +async function makeTrace(t, agent) { const DURATION = 33 const URL = '/test?test=value' agent.config.attributes.enabled = true @@ -825,7 +880,7 @@ async function makeTrace(agent) { // and instead use async/await trace.generateJSONAsync = util.promisify(trace.generateJSON) const start = trace.root.timer.start - expect(start, "root segment's start time").above(0) + t.ok(start > 0, "root segment's start time") trace.setDurationInMillis(DURATION, 0) const web = trace.root.add(URL) @@ -906,31 +961,6 @@ async function makeTrace(agent) { null // syntheticsResourceId ] } - /* - codec.encode(rootNode, function(err, encoded) { - if (err) { - return callback(err) - } - - callback(null, { - transaction, - trace, - rootSegment, - rootNode, - expectedEncoding: [ - 0, - DURATION, - 'WebTransaction/NormalizedUri/*', // scope - '/test', // URI path - encoded, // compressed segment / segment data - transaction.id, // guid - null, // reserved, always NULL - false, // FIXME: RUM2 session persistence, not worrying about it for now - null, // FIXME: xraysessionid - null // syntheticsResourceId - ] - }) - })*/ } tap.test('infinite tracing', (t) => {