From e0dc01571087c3d53434d2d21d77206592137b66 Mon Sep 17 00:00:00 2001 From: Bob Evans Date: Tue, 1 Oct 2024 12:37:42 -0400 Subject: [PATCH] test: Migrated `aws-sdk-v2` and `aws-sdk-v3` tests to `node:test` (#2620) --- test/lib/custom-assertions.js | 39 +- test/unit/analytics_events.test.js | 10 +- test/unit/attributes.test.js | 3 +- test/unit/collector/facts.test.js | 23 +- test/unit/environment.test.js | 12 +- test/unit/errors/error-collector.test.js | 33 +- .../errors/error-event-aggregator.test.js | 5 +- test/unit/errors/error-group.test.js | 23 +- .../errors/error-trace-aggregator.test.js | 6 +- test/unit/errors/server-config.test.js | 36 +- test/unit/harvester.test.js | 3 +- test/unit/high-security.test.js | 11 +- test/unit/index.test.js | 55 ++- test/unit/instrumentation-tracker.test.js | 5 +- test/unit/metrics-mapper.test.js | 16 +- test/unit/parse-proc-cpuinfo.test.js | 6 +- test/unit/parse-proc-meminfo.test.js | 7 +- test/unit/parsed-statement.test.js | 4 +- test/unit/priority-queue.test.js | 26 +- test/unit/protocols.test.js | 11 +- test/unit/serverless/api-gateway-v2.test.js | 5 +- test/unit/transaction.test.js | 11 +- .../aws-sdk-v2/amazon-dax-client.tap.js | 63 ++-- test/versioned/aws-sdk-v2/aws-sdk.tap.js | 65 ++-- test/versioned/aws-sdk-v2/dynamodb.tap.js | 92 +++-- .../versioned/aws-sdk-v2/http-services.tap.js | 98 +++-- .../instrumentation-supported.tap.js | 33 +- .../instrumentation-unsupported.tap.js | 35 +- test/versioned/aws-sdk-v2/s3.tap.js | 100 +++--- test/versioned/aws-sdk-v2/sns.tap.js | 77 ++-- test/versioned/aws-sdk-v2/sqs.tap.js | 177 ++++----- test/versioned/aws-sdk-v3/api-gateway.tap.js | 33 +- .../bedrock-chat-completions.tap.js | 339 ++++++++---------- .../aws-sdk-v3/bedrock-embeddings.tap.js | 128 +++---- .../aws-sdk-v3/bedrock-negative-tests.tap.js | 86 ++--- .../aws-sdk-v3/client-dynamodb.tap.js | 261 +++++++------- test/versioned/aws-sdk-v3/common.js | 79 ++-- test/versioned/aws-sdk-v3/elasticache.tap.js | 33 +- test/versioned/aws-sdk-v3/elb.tap.js | 32 +- test/versioned/aws-sdk-v3/lambda.tap.js | 32 +- test/versioned/aws-sdk-v3/lib-dynamodb.tap.js | 163 +++------ test/versioned/aws-sdk-v3/rds.tap.js | 32 +- test/versioned/aws-sdk-v3/redshift.tap.js | 32 +- test/versioned/aws-sdk-v3/rekognition.tap.js | 32 +- test/versioned/aws-sdk-v3/s3.tap.js | 40 +-- test/versioned/aws-sdk-v3/ses.tap.js | 30 +- test/versioned/aws-sdk-v3/sns.tap.js | 199 +++++----- test/versioned/aws-sdk-v3/sqs.tap.js | 85 ++--- 48 files changed, 1225 insertions(+), 1501 deletions(-) diff --git a/test/lib/custom-assertions.js b/test/lib/custom-assertions.js index 5f594400e2..3fa0ddbddf 100644 --- a/test/lib/custom-assertions.js +++ b/test/lib/custom-assertions.js @@ -6,6 +6,10 @@ 'use strict' const assert = require('node:assert') const { isSimpleObject } = require('../../lib/util/objects') +const typeMappings = { + String: 'string', + Number: 'number' +} function assertExactClmAttrs(segmentStub, expectedAttrs) { const attrs = segmentStub.addAttribute.args @@ -204,37 +208,24 @@ function assertSegments(parent, expected, options) { */ function match(actual, expected) { if (typeof actual === 'string' && typeof expected === 'string') { - const patterns = expected - .trim() - .split(/\r?\n/) - .map((s) => s.trim()) - - let lastIndex = -1 - for (const pattern of patterns) { - const index = actual.indexOf(pattern) - if (index === -1 || index < lastIndex) { - return false - } - lastIndex = index - } - return true + assert.ok(actual.indexOf(expected) > -1) + return } for (const key in expected) { if (key in actual) { - if (typeof expected[key] === 'object' && expected[key] !== null) { - /* c8 ignore next 3 */ - if (!match(actual[key], expected[key])) { - return false - } - } else if (actual[key] !== expected[key]) { - return false + if (typeof expected[key] === 'function') { + const type = expected[key] + assert.ok(typeof actual[key] === typeMappings[type.name]) + } else if (expected[key] instanceof RegExp) { + assert.ok(expected[key].test(actual[key])) + } else if (typeof expected[key] === 'object' && expected[key] !== null) { + match(actual[key], expected[key]) + } else { + assert.equal(actual[key], expected[key]) } - } else { - return false } } - return true } /** diff --git a/test/unit/analytics_events.test.js b/test/unit/analytics_events.test.js index 66a0b792cc..3be4c6f95d 100644 --- a/test/unit/analytics_events.test.js +++ b/test/unit/analytics_events.test.js @@ -8,7 +8,6 @@ const test = require('node:test') const assert = require('node:assert') -const { match } = require('../lib/custom-assertions') const Transaction = require('../../lib/transaction') const helper = require('../lib/agent_helper') @@ -63,12 +62,9 @@ test('when host name is specified by user', async (t) => { const events = getTransactionEvents(agent) const firstEvent = events[first] - assert.equal( - match(firstEvent[agentAttrs], { - 'host.displayName': 'test-value' - }), - true - ) + assert.deepEqual(firstEvent[agentAttrs], { + 'host.displayName': 'test-value' + }) }) }) diff --git a/test/unit/attributes.test.js b/test/unit/attributes.test.js index 506c0e5d57..bb6abd15dd 100644 --- a/test/unit/attributes.test.js +++ b/test/unit/attributes.test.js @@ -8,7 +8,6 @@ const test = require('node:test') const assert = require('node:assert') -const { match } = require('../lib/custom-assertions') const helper = require('../lib/agent_helper') const { Attributes } = require('../../lib/attributes') const AttributeFilter = require('../../lib/config/attribute-filter') @@ -204,6 +203,6 @@ test('#reset', async (t) => { inst.reset() - assert.equal(match(inst.attributes, {}), true) + assert.deepEqual(inst.attributes, {}) }) }) diff --git a/test/unit/collector/facts.test.js b/test/unit/collector/facts.test.js index 6fff7fb7d3..a4ffb2dd66 100644 --- a/test/unit/collector/facts.test.js +++ b/test/unit/collector/facts.test.js @@ -12,7 +12,6 @@ const fs = require('node:fs') const net = require('node:net') const helper = require('../../lib/agent_helper') -const { match } = require('../../lib/custom-assertions') const sysInfo = require('../../../lib/system-info') const utilTests = require('../../lib/cross_agent_tests/utilization/utilization_json') const bootIdTests = require('../../lib/cross_agent_tests/utilization/boot_id') @@ -174,7 +173,7 @@ test('fun facts about apps that New Relic is interested in including', async (t) } ] ] - assert.equal(match(t.nr.logs.debug, expectedLogs), true, 'New Relic metadata logged properly') + assert.deepEqual(t.nr.logs.debug, expectedLogs, 'New Relic metadata logged properly') end() }) }) @@ -182,7 +181,7 @@ test('fun facts about apps that New Relic is interested in including', async (t) await t.test('empty `metadata` object if no metadata env vars found', (t, end) => { const { agent, facts } = t.nr facts(agent, (result) => { - assert.equal(match(result.metadata, {}), true) + assert.deepEqual(result.metadata, {}) end() }) }) @@ -190,7 +189,7 @@ test('fun facts about apps that New Relic is interested in including', async (t) await t.test('only returns expected facts', (t, end) => { const { agent, facts } = t.nr facts(agent, (result) => { - assert.equal(match(Object.keys(result).sort(), EXPECTED_FACTS.sort()), true) + assert.deepEqual(Object.keys(result).sort(), EXPECTED_FACTS.sort()) end() }) }) @@ -208,7 +207,7 @@ test('fun facts about apps that New Relic is interested in including', async (t) { label_type: 'a', label_value: 'b' }, { label_type: '€'.repeat(255), label_value: '𝌆'.repeat(255) } ] - assert.equal(match(result.labels, expected), true) + assert.deepEqual(result.labels, expected) end() }) }) @@ -223,7 +222,7 @@ test('fun facts about apps that New Relic is interested in including', async (t) { label_type: 'a', label_value: 'b' }, { label_type: '€'.repeat(255), label_value: '𝌆'.repeat(255) } ] - assert.equal(match(result.labels, expected), true) + assert.deepEqual(result.labels, expected) end() }) }) @@ -252,7 +251,7 @@ test('fun facts about apps that New Relic is interested in including', async (t) } facts(agent, (result) => { - assert.equal(match(result.event_harvest_config, expectedHarvestConfig), true) + assert.deepEqual(result.event_harvest_config, expectedHarvestConfig) end() }) } @@ -441,7 +440,7 @@ test('utilization facts', async (t) => { } t.nr.facts(agent, (result) => { - assert.equal(match(result.utilization, expected), true) + assert.deepEqual(result.utilization, expected) end() }) @@ -684,15 +683,15 @@ test('display_host facts', async (t) => { agent.config.process_host.display_name = 'test-value2' facts(agent, (result2) => { - assert.equal(match(result2.display_host, displayHost1), true) - assert.equal(match(result2.host, host1), true) + assert.deepEqual(result2.display_host, displayHost1) + assert.deepEqual(result2.host, host1) agent.config.clearHostnameCache() agent.config.clearDisplayHostCache() facts(agent, (result3) => { - assert.equal(match(result3.display_host, 'test-value2'), true) - assert.equal(match(result3.host, os.hostname()), true) + assert.deepEqual(result3.display_host, 'test-value2') + assert.deepEqual(result3.host, os.hostname()) end() }) diff --git a/test/unit/environment.test.js b/test/unit/environment.test.js index c75db60576..79d35a30ef 100644 --- a/test/unit/environment.test.js +++ b/test/unit/environment.test.js @@ -15,7 +15,6 @@ const { spawn } = require('node:child_process') // environment when testing. delete process.env.NODE_ENV -const { match } = require('../lib/custom-assertions') const { isSupportedVersion } = require('../lib/agent_helper') const environment = require('../../lib/environment') @@ -217,13 +216,10 @@ test('should get correct version for dependencies', async () => { return map }, {}) - assert.equal( - match(versions, { - 'invalid-json': '', - 'valid-json': '1.2.3' - }), - true - ) + assert.deepEqual(versions, { + 'invalid-json': '', + 'valid-json': '1.2.3' + }) }) // TODO: remove this test when we drop support for node 18 diff --git a/test/unit/errors/error-collector.test.js b/test/unit/errors/error-collector.test.js index d6d87e984a..7ca9deda95 100644 --- a/test/unit/errors/error-collector.test.js +++ b/test/unit/errors/error-collector.test.js @@ -8,7 +8,6 @@ const test = require('node:test') const assert = require('node:assert') -const { match } = require('../../lib/custom-assertions') const helper = require('../../lib/agent_helper') const Exception = require('../../../lib/errors').Exception const ErrorCollector = require('../../../lib/errors/error-collector') @@ -118,12 +117,12 @@ test('Errors', async (t) => { const errorTraces = getErrorTraces(errors) let params = errorTraces[0][PARAMS] - assert.equal(match(params.agentAttributes, { 'request.parameters.a': 'A' }), true) + assert.deepEqual(params.agentAttributes, { 'request.parameters.a': 'A' }) // Error events const errorEvents = getErrorEvents(errors) params = errorEvents[0][2] - assert.equal(match(params, { 'request.parameters.a': 'A' }), true) + assert.deepEqual(params, { 'request.parameters.a': 'A' }) }) await t.test('record custom parameters', (t) => { @@ -134,11 +133,11 @@ test('Errors', async (t) => { const errorTraces = getErrorTraces(errors) let params = errorTraces[0][PARAMS] - assert.equal(match(params.userAttributes, { a: 'A' }), true) + assert.deepEqual(params.userAttributes, { a: 'A' }) const errorEvents = getErrorEvents(errors) params = errorEvents[0][1] - assert.equal(match(params, { a: 'A' }), true) + assert.deepEqual(params, { a: 'A' }) }) await t.test('merge custom parameters', (t) => { @@ -149,11 +148,11 @@ test('Errors', async (t) => { const errorTraces = getErrorTraces(errors) let params = errorTraces[0][PARAMS] - assert.equal(match(params.userAttributes, { a: 'A', b: 'B' }), true) + assert.deepEqual(params.userAttributes, { a: 'A', b: 'B' }) const errorEvents = getErrorEvents(errors) params = errorEvents[0][1] - assert.equal(match(params, { a: 'A', b: 'B' }), true) + assert.deepEqual(params, { a: 'A', b: 'B' }) }) await t.test('overrides existing custom attributes with new custom attributes', (t) => { @@ -164,11 +163,11 @@ test('Errors', async (t) => { const errorTraces = getErrorTraces(errors) let params = errorTraces[0][PARAMS] - assert.equal(match(params.userAttributes, { a: 'AA' }), true) + assert.deepEqual(params.userAttributes, { a: 'AA' }) const errorEvents = getErrorEvents(errors) params = errorEvents[0][1] - assert.equal(match(params, { a: 'AA' }), true) + assert.deepEqual(params, { a: 'AA' }) }) await t.test('does not add custom attributes in high security mode', (t) => { @@ -179,11 +178,11 @@ test('Errors', async (t) => { const errorTraces = getErrorTraces(errors) let params = errorTraces[0][PARAMS] - assert.equal(match(params.userAttributes, {}), true) + assert.deepEqual(params.userAttributes, {}) const errorEvents = getErrorEvents(errors) params = errorEvents[0][1] - assert.equal(match(params, {}), true) + assert.deepEqual(params, {}) }) await t.test('redacts the error message in high security mode', (t) => { @@ -388,7 +387,7 @@ test('Errors', async (t) => { const errorTraces = getErrorTraces(errors) const params = errorTraces[0][PARAMS] - assert.equal(match(params.agentAttributes, { 'host.displayName': 'test-value' }), true) + assert.deepEqual(params.agentAttributes, { 'host.displayName': 'test-value' }) }) await t.test('should not be in agent attributes if not set by user', (t) => { @@ -399,7 +398,7 @@ test('Errors', async (t) => { const errorTraces = getErrorTraces(errors) const params = errorTraces[0][PARAMS] - assert.equal(match(params.agentAttributes, {}), true) + assert.deepEqual(params.agentAttributes, {}) }) }) @@ -923,7 +922,7 @@ test('Errors', async (t) => { const errorTraces = getErrorTraces(errors) const errorJSON = errorTraces[0] const params = errorJSON[4] - assert.equal(match(params.agentAttributes, { test_param: 'a value' }), true) + assert.deepEqual(params.agentAttributes, { test_param: 'a value' }) }) await t.test('with a thrown TypeError object and no transaction', async (t) => { @@ -2281,7 +2280,7 @@ test('_processErrors', async (t) => { const errorType = 'user' const result = errorCollector._getIterableProperty(tx, errorType) - assert.equal(match(result, []), true) + assert.deepEqual(result, []) }) await t.test('if type is transactionException, return an array of objects', (t) => { @@ -2289,7 +2288,7 @@ test('_processErrors', async (t) => { const errorType = 'transactionException' const result = errorCollector._getIterableProperty(tx, errorType) - assert.equal(match(result, []), true) + assert.deepEqual(result, []) }) await t.test( @@ -2301,7 +2300,7 @@ test('_processErrors', async (t) => { const expectedErrors = 0 const result = errorCollector._processErrors(tx, collectedErrors, expectedErrors, errorType) - assert.equal(match(result, [collectedErrors, expectedErrors]), true) + assert.deepEqual(result, [collectedErrors, expectedErrors]) } ) }) diff --git a/test/unit/errors/error-event-aggregator.test.js b/test/unit/errors/error-event-aggregator.test.js index 1239dfed1a..77c9bff429 100644 --- a/test/unit/errors/error-event-aggregator.test.js +++ b/test/unit/errors/error-event-aggregator.test.js @@ -10,7 +10,6 @@ const assert = require('node:assert') const ErrorEventAggregator = require('../../../lib/errors/error-event-aggregator') const Metrics = require('../../../lib/metrics') -const { match } = require('../../lib/custom-assertions') const RUN_ID = 1337 const LIMIT = 5 @@ -61,8 +60,8 @@ test('Error Event Aggregator', async (t) => { const [runId, eventMetrics, errorEventData] = payload assert.equal(runId, RUN_ID) - assert.equal(match(eventMetrics, expectedMetrics), true) - assert.equal(match(errorEventData, [rawErrorEvent]), true) + assert.deepEqual(eventMetrics, expectedMetrics) + assert.deepEqual(errorEventData, [rawErrorEvent]) }) await t.test('toPayload() should return nothing with no error event data', (t) => { diff --git a/test/unit/errors/error-group.test.js b/test/unit/errors/error-group.test.js index 2ae8b32fce..bde1eee864 100644 --- a/test/unit/errors/error-group.test.js +++ b/test/unit/errors/error-group.test.js @@ -7,8 +7,6 @@ const test = require('node:test') const assert = require('node:assert') -const { match } = require('../../lib/custom-assertions') - const helper = require('../../lib/agent_helper') const Transaction = require('../../../lib/transaction') @@ -33,11 +31,10 @@ test('Error Group functionality', async (t) => { const errorTraces = getErrorTraces(agent.errors) const errorEvents = getErrorEvents(agent.errors) - assert.equal( - match(errorTraces[0][4].agentAttributes, { 'error.group.name': 'error-group-test-1' }), - true - ) - assert.equal(match(errorEvents[0][2], { 'error.group.name': 'error-group-test-1' }), true) + assert.deepEqual(errorTraces[0][4].agentAttributes, { + 'error.group.name': 'error-group-test-1' + }) + assert.deepEqual(errorEvents[0][2], { 'error.group.name': 'error-group-test-1' }) function myCallback() { return 'error-group-test-1' @@ -55,8 +52,8 @@ test('Error Group functionality', async (t) => { const errorTraces = getErrorTraces(agent.errors) const errorEvents = getErrorEvents(agent.errors) - assert.equal(match(errorTraces[0][4].agentAttributes, {}), true) - assert.equal(match(errorEvents[0][2], {}), true) + assert.deepEqual(errorTraces[0][4].agentAttributes, {}) + assert.deepEqual(errorEvents[0][2], {}) function myCallback() { throw Error('boom') @@ -76,8 +73,8 @@ test('Error Group functionality', async (t) => { const errorTraces = getErrorTraces(agent.errors) const errorEvents = getErrorEvents(agent.errors) - assert.equal(match(errorTraces[0][4].agentAttributes, {}), true) - assert.equal(match(errorEvents[0][2], {}), true) + assert.deepEqual(errorTraces[0][4].agentAttributes, {}) + assert.deepEqual(errorEvents[0][2], {}) function myCallback() { return '' @@ -98,8 +95,8 @@ test('Error Group functionality', async (t) => { const errorTraces = getErrorTraces(agent.errors) const errorEvents = getErrorEvents(agent.errors) - assert.equal(match(errorTraces[0][4].agentAttributes, {}), true) - assert.equal(match(errorEvents[0][2], {}), true) + assert.deepEqual(errorTraces[0][4].agentAttributes, {}) + assert.deepEqual(errorEvents[0][2], {}) function myCallback() { return { 'error.group.name': 'blah' } diff --git a/test/unit/errors/error-trace-aggregator.test.js b/test/unit/errors/error-trace-aggregator.test.js index a22e830907..f1bfa3baf7 100644 --- a/test/unit/errors/error-trace-aggregator.test.js +++ b/test/unit/errors/error-trace-aggregator.test.js @@ -7,8 +7,6 @@ const test = require('node:test') const assert = require('node:assert') -const { match } = require('../../lib/custom-assertions') - const ErrorTraceAggregator = require('../../../lib/errors/error-trace-aggregator') const RUN_ID = 1337 @@ -74,7 +72,7 @@ test('Error Trace Aggregator', async (t) => { assert.equal(runId, RUN_ID, 'run ID should match') const expectedTraceData = [rawErrorTrace] - assert.equal(match(errorTraceData, expectedTraceData), true, 'errorTraceData should match') + assert.deepEqual(errorTraceData, expectedTraceData, 'errorTraceData should match') }) await t.test('toPayload() should return json format of data', (t, end) => { @@ -89,7 +87,7 @@ test('Error Trace Aggregator', async (t) => { assert.equal(runId, RUN_ID, 'run ID should match') const expectedTraceData = [rawErrorTrace] - assert.equal(match(errorTraceData, expectedTraceData), true, 'errorTraceData should match') + assert.deepEqual(errorTraceData, expectedTraceData, 'errorTraceData should match') end() }) }) diff --git a/test/unit/errors/server-config.test.js b/test/unit/errors/server-config.test.js index 4b8fcbde29..1a2b098329 100644 --- a/test/unit/errors/server-config.test.js +++ b/test/unit/errors/server-config.test.js @@ -9,8 +9,6 @@ const test = require('node:test') const assert = require('node:assert') const helper = require('../../lib/agent_helper') -const { match } = require('../../lib/custom-assertions') - test('Merging Server Config Values', async (t) => { t.beforeEach((ctx) => { ctx.nr = {} @@ -28,7 +26,7 @@ test('Merging Server Config Values', async (t) => { const params = { 'error_collector.ignore_status_codes': ['501-505'] } agent.config._fromServer(params, 'error_collector.ignore_status_codes') const expected = [404, 501, 502, 503, 504, 505] - assert.equal(match(agent.config.error_collector.ignore_status_codes, expected), true) + assert.deepEqual(agent.config.error_collector.ignore_status_codes, expected) end() }) }) @@ -40,7 +38,7 @@ test('Merging Server Config Values', async (t) => { const params = { 'error_collector.expected_status_codes': ['501-505'] } agent.config._fromServer(params, 'error_collector.expected_status_codes') const expected = [404, 501, 502, 503, 504, 505] - assert.equal(match(agent.config.error_collector.expected_status_codes, expected), true) + assert.deepEqual(agent.config.error_collector.expected_status_codes, expected) end() }) }) @@ -52,7 +50,7 @@ test('Merging Server Config Values', async (t) => { const params = { 'error_collector.expected_classes': ['Bar'] } agent.config._fromServer(params, 'error_collector.expected_classes') const expected = ['Foo', 'Bar'] - assert.equal(match(agent.config.error_collector.expected_classes, expected), true) + assert.deepEqual(agent.config.error_collector.expected_classes, expected) end() }) }) @@ -64,7 +62,7 @@ test('Merging Server Config Values', async (t) => { const params = { 'error_collector.ignore_classes': ['Bar'] } agent.config._fromServer(params, 'error_collector.ignore_classes') const expected = ['Foo', 'Bar'] - assert.equal(match(agent.config.error_collector.ignore_classes, expected), true) + assert.deepEqual(agent.config.error_collector.ignore_classes, expected) end() }) }) @@ -78,7 +76,7 @@ test('Merging Server Config Values', async (t) => { const nonsense = { 'error_collector.ignore_classes': [{ this: 'isNotAClass' }] } agent.config._fromServer(nonsense, 'error_collector.ignore_classes') const expected = ['Foo', 'Bar'] - assert.equal(match(agent.config.error_collector.ignore_classes, expected), true) + assert.deepEqual(agent.config.error_collector.ignore_classes, expected) end() }) }) @@ -90,7 +88,7 @@ test('Merging Server Config Values', async (t) => { const params = { 'error_collector.expected_messages': { Zip: ['zap'] } } agent.config._fromServer(params, 'error_collector.expected_messages') const expected = { Foo: ['bar'], Zip: ['zap'] } - assert.equal(match(agent.config.error_collector.expected_messages, expected), true) + assert.deepEqual(agent.config.error_collector.expected_messages, expected) end() }) }) @@ -102,7 +100,7 @@ test('Merging Server Config Values', async (t) => { const params = { 'error_collector.ignore_messages': { Zip: ['zap'] } } agent.config._fromServer(params, 'error_collector.ignore_messages') const expected = { Foo: ['bar'], Zip: ['zap'] } - assert.equal(match(agent.config.error_collector.ignore_messages, expected), true) + assert.deepEqual(agent.config.error_collector.ignore_messages, expected) end() }) }) @@ -114,7 +112,7 @@ test('Merging Server Config Values', async (t) => { const params = { 'error_collector.ignore_messages': { Foo: ['zap'] } } agent.config._fromServer(params, 'error_collector.ignore_messages') const expected = { Foo: ['bar', 'zap'] } - assert.equal(match(agent.config.error_collector.ignore_messages, expected), true) + assert.deepEqual(agent.config.error_collector.ignore_messages, expected) end() }) }) @@ -127,7 +125,7 @@ test('Merging Server Config Values', async (t) => { const params = { 'error_collector.ignore_messages': { Foo: ['zap'] } } agent.config._fromServer(params, 'error_collector.ignore_messages') const expected = { Foo: ['zap'] } // expect this to replace - assert.equal(match(agent.config.error_collector.ignore_messages, expected), true) + assert.deepEqual(agent.config.error_collector.ignore_messages, expected) end() }) }) @@ -140,7 +138,7 @@ test('Merging Server Config Values', async (t) => { const params = { 'error_collector.ignore_messages': { Foo: ['zap'] } } agent.config._fromServer(params, 'error_collector.ignore_messages') const expected = { Foo: ['zap'] } // expect this to replace - assert.equal(match(agent.config.error_collector.ignore_messages, expected), true) + assert.deepEqual(agent.config.error_collector.ignore_messages, expected) end() }) }) @@ -163,7 +161,7 @@ test('Merging Server Config Values', async (t) => { agent.config.error_collector.ignore_messages = expected const params = { 'error_collector.ignore_messages': value } agent.config._fromServer(params, 'error_collector.ignore_messages') - assert.equal(match(agent.config.error_collector.ignore_messages, expected), true) + assert.deepEqual(agent.config.error_collector.ignore_messages, expected) }) end() }) @@ -187,7 +185,7 @@ test('Merging Server Config Values', async (t) => { agent.config.error_collector.expect_messages = expected const params = { 'error_collector.expect_messages': value } agent.config._fromServer(params, 'error_collector.expect_messages') - assert.equal(match(agent.config.error_collector.expect_messages, expected), true) + assert.deepEqual(agent.config.error_collector.expect_messages, expected) }) end() }) @@ -211,7 +209,7 @@ test('Merging Server Config Values', async (t) => { agent.config.error_collector.ignore_classes = expected const params = { 'error_collector.ignore_classes': value } agent.config._fromServer(params, 'error_collector.ignore_classes') - assert.equal(match(agent.config.error_collector.ignore_classes, expected), true) + assert.deepEqual(agent.config.error_collector.ignore_classes, expected) }) end() }) @@ -235,7 +233,7 @@ test('Merging Server Config Values', async (t) => { agent.config.error_collector.expect_classes = expected const params = { 'error_collector.expect_classes': value } agent.config._fromServer(params, 'error_collector.expect_classes') - assert.equal(match(agent.config.error_collector.expect_classes, expected), true) + assert.deepEqual(agent.config.error_collector.expect_classes, expected) }) end() }) @@ -260,7 +258,7 @@ test('Merging Server Config Values', async (t) => { agent.config.error_collector.ignore_status_codes = toSet const params = { 'error_collector.ignore_status_codes': value } agent.config._fromServer(params, 'error_collector.ignore_status_codes') - assert.equal(match(agent.config.error_collector.ignore_status_codes, expected), true) + assert.deepEqual(agent.config.error_collector.ignore_status_codes, expected) }) end() }) @@ -285,7 +283,7 @@ test('Merging Server Config Values', async (t) => { agent.config.error_collector.expected_status_codes = toSet const params = { 'error_collector.expected_status_codes': value } agent.config._fromServer(params, 'error_collector.expected_status_codes') - assert.equal(match(agent.config.error_collector.expected_status_codes, expected), true) + assert.deepEqual(agent.config.error_collector.expected_status_codes, expected) }) end() }) @@ -299,7 +297,7 @@ test('Merging Server Config Values', async (t) => { const params = { 'error_collector.ignore_messages': { Foo: ['bar'] } } agent.config._fromServer(params, 'error_collector.ignore_messages') const expected = { Foo: ['zap', 'bar'] } // expect this to replace - assert.equal(match(agent.config.error_collector.ignore_messages, expected), true) + assert.deepEqual(agent.config.error_collector.ignore_messages, expected) end() }) }) diff --git a/test/unit/harvester.test.js b/test/unit/harvester.test.js index abcea8d261..1eb6ff4b48 100644 --- a/test/unit/harvester.test.js +++ b/test/unit/harvester.test.js @@ -10,7 +10,6 @@ const assert = require('node:assert') const { EventEmitter } = require('node:events') const sinon = require('sinon') -const { match } = require('../lib/custom-assertions') const promiseResolvers = require('../lib/promise-resolvers') const Harvester = require('../../lib/harvester') @@ -91,7 +90,7 @@ test('should reconfigure all aggregators', (t) => { harvester.update(config) assert.equal(aggregators[0].reconfigure.callCount, 1, 'should stop enabled aggregator') assert.equal(aggregators[1].reconfigure.callCount, 1, 'should stop disabled aggregator') - assert.equal(match(aggregators[0].reconfigure.args[0], [config]), true) + assert.deepEqual(aggregators[0].reconfigure.args[0], [config]) }) test('resolve when all data is sent', async (t) => { diff --git a/test/unit/high-security.test.js b/test/unit/high-security.test.js index 2cd30c71d0..a9b246e924 100644 --- a/test/unit/high-security.test.js +++ b/test/unit/high-security.test.js @@ -8,7 +8,6 @@ const test = require('node:test') const assert = require('node:assert') -const { match } = require('../lib/custom-assertions') const helper = require('../lib/agent_helper') const facts = require('../../lib/collector/facts') const API = require('../../api') @@ -42,7 +41,7 @@ function check(key, before, after) { setPath(fromFile, key, before) const config = new Config(fromFile) - return assert.equal(match(getPath(config, key), after), true) + assert.deepEqual(getPath(config, key), after) } function checkServer(config, key, expected, server) { @@ -50,11 +49,11 @@ function checkServer(config, key, expected, server) { const fromServer = { high_security: true } fromServer[key] = server - assert.equal(match(getPath(config, key), expected), true) - assert.equal(match(fromServer[key], server), true) + assert.equal(getPath(config, key), expected) + assert.equal(fromServer[key], server) config.onConnect(fromServer) - return assert.equal(match(getPath(config, key), expected), true) + assert.equal(getPath(config, key), expected) } test('config to be sent during connect', async (t) => { @@ -255,7 +254,7 @@ test('coerces other settings', async (t) => { config.attributes.include = ['some val'] config._applyHighSecurity() assert.equal(config.ssl, true) - assert.equal(match(config.attributes.include, []), true) + assert.deepEqual(config.attributes.include, []) }) }) }) diff --git a/test/unit/index.test.js b/test/unit/index.test.js index ec5f1031c3..ca3a4c3199 100644 --- a/test/unit/index.test.js +++ b/test/unit/index.test.js @@ -10,8 +10,6 @@ const assert = require('node:assert') const sinon = require('sinon') -const { match } = require('../lib/custom-assertions') - const proxyquire = require('proxyquire').noCallThru() const createLoggerMock = require('./mocks/logger') const createMockAgent = require('./mocks/agent') @@ -72,13 +70,10 @@ test('loader metrics', async (t) => { assert.equal(metricCall.args.length, 1) assert.equal(metricCall.args[0][0], 'Supportability/Features/CJS/Require') - assert.equal( - match( - t.nr.loggerMock.debug.args[4][1], - /node -r some-cool-lib.*index\.test\.js/, - 'should log how the agent is called' - ), - true + assert.match( + t.nr.loggerMock.debug.args[4][1], + /node -r some-cool-lib.*index\.test\.js/, + 'should log how the agent is called' ) }) @@ -115,13 +110,10 @@ test('loader metrics', async (t) => { assert.equal(metricCall.args.length, 2) assert.equal(metricCall.args[0][0], 'Supportability/Features/ESM/Loader') assert.equal(metricCall.args[1][0], 'Supportability/Features/CJS/Preload') - assert.equal( - match( - t.nr.loggerMock.debug.args[4][1], - /node --loader newrelic\/esm-loader.mjs -r newrelic.*index\.test\.js/, - 'should log how the agent is called' - ), - true + assert.match( + t.nr.loggerMock.debug.args[4][1], + /node --loader newrelic\/esm-loader.mjs -r newrelic.*index\.test\.js/, + 'should log how the agent is called' ) } ) @@ -254,20 +246,17 @@ test('index tests', async (t) => { await t.test('should set api on require.cache.__NR_cache', (t) => { const api = loadIndex(t) - assert.equal(match(require.cache.__NR_cache, api), true) + assert.deepEqual(require.cache.__NR_cache, api) }) await t.test('should load k2 agent if config.security.agent.enabled', (t) => { t.nr.mockConfig.security.agent.enabled = true const api = loadIndex(t) assert.equal(t.nr.k2Stub.start.callCount, 1, 'should register security agent') - assert.equal( - match( - t.nr.k2Stub.start.args[0][0], - api, - 'should call start on security agent with proper args' - ), - true + assert.deepEqual( + t.nr.k2Stub.start.args[0][0], + api, + 'should call start on security agent with proper args' ) }) @@ -284,9 +273,9 @@ test('index tests', async (t) => { t.nr.processVersionStub.satisfies.onCall(0).returns(false) loadIndex(t) assert.equal(t.nr.loggerMock.error.callCount, 1, 'should log an error') - assert.equal( - match(t.nr.loggerMock.error.args[0][0], /New Relic for Node.js requires a version of Node/), - true + assert.match( + t.nr.loggerMock.error.args[0][0].message, + /New Relic for Node.js requires a version of Node/ ) }) @@ -296,9 +285,9 @@ test('index tests', async (t) => { t.nr.configMock.getOrCreateInstance.returns(null) loadIndex(t) assert.equal(t.nr.loggerMock.warn.callCount, 1, 'should log an error') - assert.equal( - match(t.nr.loggerMock.warn.args[0][0], /New Relic for Node\.js.*has not been tested on Node/), - true + assert.match( + t.nr.loggerMock.warn.args[0][0], + /New Relic for Node\.js.*has not been tested on Node/ ) }) @@ -339,9 +328,9 @@ test('index tests', async (t) => { t.nr.mockConfig.applications.returns([]) loadIndex(t) assert.equal(t.nr.loggerMock.error.callCount, 1, 'should log an error') - assert.equal( - match(t.nr.loggerMock.error.args[0][0], /New Relic requires that you name this application!/), - true + assert.match( + t.nr.loggerMock.error.args[0][0].message, + /New Relic requires that you name this application!/ ) }) diff --git a/test/unit/instrumentation-tracker.test.js b/test/unit/instrumentation-tracker.test.js index 12c2dc0db3..096eaec704 100644 --- a/test/unit/instrumentation-tracker.test.js +++ b/test/unit/instrumentation-tracker.test.js @@ -7,9 +7,6 @@ const test = require('node:test') const assert = require('node:assert') - -const { match } = require('../lib/custom-assertions') - const InstrumentationTracker = require('../../lib/instrumentation-tracker') const InstrumentationDescriptor = require('../../lib/instrumentation-descriptor') @@ -42,7 +39,7 @@ test('can get a tracked item by instrumentation', async () => { tracker.track('foo', inst) const item = tracker.getTrackedItem('foo', inst) assert.equal(item.instrumentation, inst) - assert.equal(match(item.meta, { instrumented: false, didError: undefined }), true) + assert.deepEqual(item.meta, { instrumented: false, didError: undefined }) }) test('sets hook failure correctly', async () => { diff --git a/test/unit/metrics-mapper.test.js b/test/unit/metrics-mapper.test.js index 7f1b81c127..f371933e08 100644 --- a/test/unit/metrics-mapper.test.js +++ b/test/unit/metrics-mapper.test.js @@ -8,8 +8,6 @@ const test = require('node:test') const assert = require('node:assert') -const { match } = require('../lib/custom-assertions') - const MetricMapper = require('../../lib/metrics/mapper.js') test("shouldn't throw if passed null", () => { @@ -66,11 +64,8 @@ test('when loading mappings at creation', async (t) => { await t.test('should turn non-mapped metrics into specs', (t) => { const { mapper } = t.nr - assert.equal(match(mapper.map('Test/Metric1'), { name: 'Test/Metric1' }), true) - assert.equal( - match(mapper.map('Test/Metric2', 'TEST'), { name: 'Test/Metric2', scope: 'TEST' }), - true - ) + assert.deepEqual(mapper.map('Test/Metric1'), { name: 'Test/Metric1' }) + assert.deepEqual(mapper.map('Test/Metric2', 'TEST'), { name: 'Test/Metric2', scope: 'TEST' }) }) }) @@ -96,10 +91,7 @@ test('when adding mappings after creation', async (t) => { await t.test('should turn non-mapped metrics into specs', (t) => { const { mapper } = t.nr - assert.equal(match(mapper.map('Test/Metric1'), { name: 'Test/Metric1' }), true) - assert.equal( - match(mapper.map('Test/Metric2', 'TEST'), { name: 'Test/Metric2', scope: 'TEST' }), - true - ) + assert.deepEqual(mapper.map('Test/Metric1'), { name: 'Test/Metric1' }) + assert.deepEqual(mapper.map('Test/Metric2', 'TEST'), { name: 'Test/Metric2', scope: 'TEST' }) }) }) diff --git a/test/unit/parse-proc-cpuinfo.test.js b/test/unit/parse-proc-cpuinfo.test.js index 6826a4975e..4e8f115dc0 100644 --- a/test/unit/parse-proc-cpuinfo.test.js +++ b/test/unit/parse-proc-cpuinfo.test.js @@ -8,8 +8,6 @@ const test = require('node:test') const assert = require('node:assert') -const { match } = require('../lib/custom-assertions') - const parseCpuInfo = require('../../lib/parse-proc-cpuinfo') // Most functionality is covered in-depth via cross-agent tests in @@ -24,7 +22,7 @@ test('Should return object with null processor stats when data is null', () => { const result = parseCpuInfo(null) - assert.equal(match(result, expectedStats), true) + assert.deepEqual(result, expectedStats) }) test('Should return object with null processor stats when data is undefined', () => { @@ -36,5 +34,5 @@ test('Should return object with null processor stats when data is undefined', () const result = parseCpuInfo(undefined) - assert.equal(match(result, expectedStats), true) + assert.deepEqual(result, expectedStats) }) diff --git a/test/unit/parse-proc-meminfo.test.js b/test/unit/parse-proc-meminfo.test.js index 8172fc3b05..ab58d032c2 100644 --- a/test/unit/parse-proc-meminfo.test.js +++ b/test/unit/parse-proc-meminfo.test.js @@ -7,9 +7,6 @@ const test = require('node:test') const assert = require('node:assert') - -const { match } = require('../lib/custom-assertions') - const parseMemInfo = require('../../lib/parse-proc-meminfo') // Most functionality is covered in-depth via cross-agent tests in @@ -17,10 +14,10 @@ const parseMemInfo = require('../../lib/parse-proc-meminfo') test('Should return `null` when data is null', () => { const result = parseMemInfo(null) - assert.equal(match(result, null), true) + assert.equal(result, null) }) test('Should return `null` when data is undefined', () => { const result = parseMemInfo(undefined) - assert.equal(match(result, undefined), true) + assert.equal(result, undefined) }) diff --git a/test/unit/parsed-statement.test.js b/test/unit/parsed-statement.test.js index 9a86be8d5c..33b9569699 100644 --- a/test/unit/parsed-statement.test.js +++ b/test/unit/parsed-statement.test.js @@ -15,7 +15,7 @@ const Transaction = require('../../lib/transaction') const ParsedStatement = require('../../lib/db/parsed-statement') function checkMetric(metrics, name, scope) { - assert.equal(match(metrics.getMetric(name, scope), { total: 0.333 }), true) + match(metrics.getMetric(name, scope), { total: 0.333 }) } test('recording database metrics', async (t) => { @@ -449,7 +449,7 @@ test('recording slow queries', async (t) => { await t.test('should not capture queries', (t) => { const { agent } = t.nr - assert.equal(match(agent.queries.samples.size, 0), true) + assert.equal(agent.queries.samples.size, 0) }) }) }) diff --git a/test/unit/priority-queue.test.js b/test/unit/priority-queue.test.js index ed99e679c6..5e76d6816b 100644 --- a/test/unit/priority-queue.test.js +++ b/test/unit/priority-queue.test.js @@ -8,8 +8,6 @@ const test = require('node:test') const assert = require('node:assert') -const { match } = require('../lib/custom-assertions') - const PriorityQueue = require('../../lib/priority-queue') test('#add', async (t) => { @@ -21,10 +19,7 @@ test('#add', async (t) => { queue.add('right child', 5) queue.add('left child', 8) - assert.equal( - match(queue.toArray(), ['parent', 'left child', 'right child', 'left grandchild']), - true - ) + assert.deepEqual(queue.toArray(), ['parent', 'left child', 'right child', 'left grandchild']) }) await t.test('replaces lowest priority item if limit is met', () => { @@ -35,17 +30,16 @@ test('#add', async (t) => { queue.add('right child', 5) queue.add('left child', 8) - assert.equal( - match(queue.toArray(), ['parent', 'left child', 'right child', 'left grandchild']), - true - ) + assert.deepEqual(queue.toArray(), ['parent', 'left child', 'right child', 'left grandchild']) queue.add('new parent', 2) - assert.equal( - match(queue.toArray(), ['new parent', 'right child', 'left grandchild', 'left child']), - true - ) + assert.deepEqual(queue.toArray(), [ + 'new parent', + 'right child', + 'left grandchild', + 'left child' + ]) }) await t.test('does not insert events in the case the limit is 0', () => { @@ -84,9 +78,9 @@ test('#setLimit', async (t) => { } assert.equal(queue.length, 6) - assert.equal(match(queue.toArray(), [0, 5, 4, 3, 2, 1]), true) + assert.deepEqual(queue.toArray(), [0, 5, 4, 3, 2, 1]) queue.setLimit(5) - assert.equal(match(queue.toArray(), [1, 2, 3, 4, 5]), true) + assert.deepEqual(queue.toArray(), [1, 2, 3, 4, 5]) assert.equal(queue.length, 5) }) }) diff --git a/test/unit/protocols.test.js b/test/unit/protocols.test.js index 20fb737920..ec9dc43986 100644 --- a/test/unit/protocols.test.js +++ b/test/unit/protocols.test.js @@ -38,13 +38,10 @@ test('errors', async (t) => { const payload = agent.errors.traceAggregator._toPayloadSync() RemoteMethod.prototype.serialize(payload, (err, errors) => { assert.equal(err, null) - assert.equal( - match( - errors, - '[1,[[0,"Unknown","test","Error",{"userAttributes":{},"agentAttributes":{},' + - '"intrinsics":{"error.expected":false},"stack_trace":["test stack"]},null]]]' - ), - true + match( + errors, + '[1,[[0,"Unknown","test","Error",{"userAttributes":{},"agentAttributes":{},' + + '"intrinsics":{"error.expected":false},"stack_trace":["test stack"]},null]]]' ) end() }) diff --git a/test/unit/serverless/api-gateway-v2.test.js b/test/unit/serverless/api-gateway-v2.test.js index d171b91759..c800334a0e 100644 --- a/test/unit/serverless/api-gateway-v2.test.js +++ b/test/unit/serverless/api-gateway-v2.test.js @@ -10,7 +10,6 @@ const assert = require('node:assert') const os = require('node:os') const { tspl } = require('@matteo.collina/tspl') -const { match } = require('../../lib/custom-assertions') const helper = require('../../lib/agent_helper') const AwsLambda = require('../../../lib/serverless/aws-lambda') @@ -138,8 +137,8 @@ test('should add w3c tracecontext to transaction if not present on request heade const headers = {} tx.insertDistributedTraceHeaders(headers) - plan.equal(match(headers.traceparent, /00-[a-f0-9]{32}-[a-f0-9]{16}-\d{2}/), true) - plan.equal(match(headers.tracestate, /33@nr=.+AccountId1-AppId1.+/), true) + plan.match(headers.traceparent, /00-[a-f0-9]{32}-[a-f0-9]{16}-\d{2}/) + plan.match(headers.tracestate, /33@nr=.+AccountId1-AppId1.+/) callback(null, responseBody) }) diff --git a/test/unit/transaction.test.js b/test/unit/transaction.test.js index 781451d24f..fc3290f1b2 100644 --- a/test/unit/transaction.test.js +++ b/test/unit/transaction.test.js @@ -16,7 +16,6 @@ const Transaction = require('../../lib/transaction') const Segment = require('../../lib/transaction/trace/segment') const hashes = require('../../lib/util/hashes') const sinon = require('sinon') -const { match } = require('../lib/custom-assertions') test('Transaction unit tests', async (t) => { t.beforeEach(function (ctx) { @@ -1473,8 +1472,8 @@ test('insertDistributedTraceHeaders', async (t) => { assert.equal(traceparentParts[2].length, 16, 'parentId of length 16') assert.equal(traceparentParts[3], '01', 'flags match') - match(traceparentParts[1], lowercaseHexRegex, 'traceId is lowercase hex') - match(traceparentParts[2], lowercaseHexRegex, 'parentId is lowercase hex') + assert.match(traceparentParts[1], lowercaseHexRegex, 'traceId is lowercase hex') + assert.match(traceparentParts[2], lowercaseHexRegex, 'parentId is lowercase hex') }) await t.test('should generate new parentId when spans_events disabled', (t) => { @@ -1494,7 +1493,7 @@ test('insertDistributedTraceHeaders', async (t) => { assert.equal(traceparentParts[2].length, 16, 'parentId has length 16') - match(traceparentParts[2], lowercaseHexRegex, 'parentId is lowercase hex') + assert.match(traceparentParts[2], lowercaseHexRegex, 'parentId is lowercase hex') }) await t.test('should set traceparent sample part to 01 for sampled transaction', (t) => { @@ -1870,7 +1869,7 @@ test('when being named with finalizeNameFromUri', async (t) => { const attrs = txn.trace.attributes.get(AttributeFilter.DESTINATIONS.TRANS_TRACE) - match(attrs, { + assert.deepEqual(attrs, { 'request.parameters.foo': 'biz', 'request.parameters.bar': 'bang' }) @@ -1953,7 +1952,7 @@ test('requestd', async (t) => { const segment = contextManager.getContext() - match(segment.attributes.get(AttributeFilter.DESTINATIONS.SPAN_EVENT), { + assert.deepEqual(segment.attributes.get(AttributeFilter.DESTINATIONS.SPAN_EVENT), { 'request.parameters.foo': 'biz', 'request.parameters.bar': 'bang' }) diff --git a/test/versioned/aws-sdk-v2/amazon-dax-client.tap.js b/test/versioned/aws-sdk-v2/amazon-dax-client.tap.js index e9b1d95db3..6070538c7f 100644 --- a/test/versioned/aws-sdk-v2/amazon-dax-client.tap.js +++ b/test/versioned/aws-sdk-v2/amazon-dax-client.tap.js @@ -4,11 +4,12 @@ */ 'use strict' - -const tap = require('tap') +const assert = require('node:assert') +const test = require('node:test') const common = require('../aws-sdk-v3/common') const helper = require('../../lib/agent_helper') const { FAKE_CREDENTIALS } = require('../../lib/aws-server-stubs') +const { match } = require('../../lib/custom-assertions') // This will not resolve / allow web requests. Even with real ones, requests // have to execute within the same VPC as the DAX configuration. When adding DAX support, @@ -18,11 +19,10 @@ const DAX_ENDPOINTS = [ 'this.is.not.real2.amazonaws.com:8111' ] -tap.test('amazon-dax-client', (t) => { - t.autoend() - - t.beforeEach(() => { - t.context.agent = helper.instrumentMockedAgent() +test('amazon-dax-client', async (t) => { + t.beforeEach((ctx) => { + ctx.nr = {} + ctx.nr.agent = helper.instrumentMockedAgent() const AWS = require('aws-sdk') const AmazonDaxClient = require('amazon-dax-client') @@ -31,59 +31,54 @@ tap.test('amazon-dax-client', (t) => { endpoints: DAX_ENDPOINTS, maxRetries: 0 // fail fast }) - t.context.docClient = new AWS.DynamoDB.DocumentClient({ service: daxClient }) + ctx.nr.docClient = new AWS.DynamoDB.DocumentClient({ service: daxClient }) }) - t.afterEach((t) => { - helper.unloadAgent(t.context.agent) + t.afterEach((ctx) => { + helper.unloadAgent(ctx.nr.agent) }) - t.test('should not crash when using DAX', (t) => { - const { agent, docClient } = t.context + await t.test('should not crash when using DAX', (t, end) => { + const { agent, docClient } = t.nr helper.runInTransaction(agent, () => { // We don't need a successful case to repro const getParam = getDocItemParams('TableDoesNotExist', 'ArtistDoesNotExist') docClient.get(getParam, (err) => { - t.ok(err) - t.end() + assert.ok(err) + end() }) }) }) - t.test('should capture instance data as unknown using DAX', (t) => { - const { agent, docClient } = t.context + await t.test('should capture instance data as unknown using DAX', (t, end) => { + const { agent, docClient } = t.nr helper.runInTransaction(agent, (transaction) => { // We don't need a successful case to repro const getParam = getDocItemParams('TableDoesNotExist', 'ArtistDoesNotExist') docClient.get(getParam, (err) => { - t.ok(err) + assert.ok(err) const root = transaction.trace.root // Won't have the attributes cause not making web request... - const segments = common.getMatchingSegments(t, root, common.DATASTORE_PATTERN) + const segments = common.getMatchingSegments(root, common.DATASTORE_PATTERN) - t.equal(segments.length, 1) + assert.equal(segments.length, 1) - const externalSegments = common.checkAWSAttributes(t, root, common.EXTERN_PATTERN) - t.equal(externalSegments.length, 0, 'should not have any External segments') + const externalSegments = common.checkAWSAttributes(root, common.EXTERN_PATTERN) + assert.equal(externalSegments.length, 0, 'should not have any External segments') const segment = segments[0] - t.equal(segment.name, 'Datastore/operation/DynamoDB/getItem') + assert.equal(segment.name, 'Datastore/operation/DynamoDB/getItem') const attrs = segment.attributes.get(common.SEGMENT_DESTINATION) - t.match( - attrs, - { - host: 'unknown', - port_path_or_id: 'unknown', - collection: 'TableDoesNotExist', - product: 'DynamoDB' - }, - 'should have expected attributes' - ) - - t.end() + match(attrs, { + host: 'unknown', + port_path_or_id: 'unknown', + collection: 'TableDoesNotExist', + product: 'DynamoDB' + }), + end() }) }) }) diff --git a/test/versioned/aws-sdk-v2/aws-sdk.tap.js b/test/versioned/aws-sdk-v2/aws-sdk.tap.js index d942436d9c..517c63bf7f 100644 --- a/test/versioned/aws-sdk-v2/aws-sdk.tap.js +++ b/test/versioned/aws-sdk-v2/aws-sdk.tap.js @@ -4,45 +4,43 @@ */ 'use strict' - +const assert = require('node:assert') const sinon = require('sinon') -const tap = require('tap') +const test = require('node:test') const helper = require('../../lib/agent_helper') const symbols = require('../../../lib/symbols') - const { createEmptyResponseServer, FAKE_CREDENTIALS } = require('../../lib/aws-server-stubs') -tap.test('aws-sdk', (t) => { - t.autoend() - - t.beforeEach(async (t) => { +test('aws-sdk', async (t) => { + t.beforeEach(async (ctx) => { + ctx.nr = {} const server = createEmptyResponseServer() await new Promise((resolve) => { server.listen(0, resolve) }) - t.context.server = server + ctx.nr.server = server - t.context.agent = helper.instrumentMockedAgent() + ctx.nr.agent = helper.instrumentMockedAgent() const AWS = require('aws-sdk') AWS.config.update({ region: 'us-east-1' }) - t.context.AWS = AWS + ctx.nr.AWS = AWS - t.context.endpoint = `http://localhost:${server.address().port}` + ctx.nr.endpoint = `http://localhost:${server.address().port}` }) - t.afterEach((t) => { - t.context.server.close() - helper.unloadAgent(t.context.agent) + t.afterEach((ctx) => { + ctx.nr.server.close() + helper.unloadAgent(ctx.nr.agent) }) - t.test('should mark requests to be dt-disabled', (t) => { - const { AWS, endpoint } = t.context + await t.test('should mark requests to be dt-disabled', (t, end) => { + const { AWS, endpoint } = t.nr // http because we've changed endpoint to be http const http = require('http') sinon.spy(http, 'request') - t.teardown(() => { + t.after(() => { // `afterEach` runs before `tearDown`, so the sinon spy may have already // been removed. if (http.request.restore) { @@ -60,58 +58,51 @@ tap.test('aws-sdk', (t) => { params: { Bucket: 'bucket' } }) s3.listObjects({ Delimiter: '/' }, (err) => { - t.error(err) + assert.ok(!err) - if (t.ok(http.request.calledOnce, 'should call http.request')) { + if (assert.ok(http.request.calledOnce, 'should call http.request')) { const args = http.request.getCall(0).args const headers = args[0].headers - t.equal(headers[symbols.disableDT], true) + assert.equal(headers[symbols.disableDT], true) } - t.end() + end() }) }) - t.test('should maintain transaction state in promises', (t) => { - const { AWS, endpoint, agent } = t.context + await t.test('should maintain transaction state in promises', async (t) => { + const { AWS, endpoint, agent } = t.nr const service = new AWS.SES({ credentials: FAKE_CREDENTIALS, endpoint }) - helper.runInTransaction(agent, (tx) => { - service + const req1 = helper.runInTransaction(agent, (tx) => { + return service .cloneReceiptRuleSet({ OriginalRuleSetName: 'RuleSetToClone', RuleSetName: 'RuleSetToCreate' }) .promise() .then(() => { - t.equal(tx.id, agent.getTransaction().id) + assert.equal(tx.id, agent.getTransaction().id) tx.end() - ender() }) }) // Run two concurrent promises to check for conflation - helper.runInTransaction(agent, (tx) => { - service + const req2 = helper.runInTransaction(agent, (tx) => { + return service .cloneReceiptRuleSet({ OriginalRuleSetName: 'RuleSetToClone', RuleSetName: 'RuleSetToCreate' }) .promise() .then(() => { - t.equal(tx.id, agent.getTransaction().id) + assert.equal(tx.id, agent.getTransaction().id) tx.end() - ender() }) }) - let count = 0 - function ender() { - if (++count === 2) { - t.end() - } - } + await Promise.all([req1, req2]) }) }) diff --git a/test/versioned/aws-sdk-v2/dynamodb.tap.js b/test/versioned/aws-sdk-v2/dynamodb.tap.js index 88cf85078d..1a27862846 100644 --- a/test/versioned/aws-sdk-v2/dynamodb.tap.js +++ b/test/versioned/aws-sdk-v2/dynamodb.tap.js @@ -4,25 +4,26 @@ */ 'use strict' - -const tap = require('tap') +const assert = require('node:assert') +const test = require('node:test') const helper = require('../../lib/agent_helper') const common = require('../aws-sdk-v3/common') const { createEmptyResponseServer, FAKE_CREDENTIALS } = require('../../lib/aws-server-stubs') +const { match } = require('../../lib/custom-assertions') +const promiseResolvers = require('../../lib/promise-resolvers') -tap.test('DynamoDB', (t) => { - t.autoend() - - t.beforeEach(async (t) => { +test('DynamoDB', async (t) => { + t.beforeEach(async (ctx) => { + ctx.nr = {} const server = createEmptyResponseServer() await new Promise((resolve) => { server.listen(0, resolve) }) - t.context.server = server + ctx.nr.server = server - t.context.agent = helper.instrumentMockedAgent() + ctx.nr.agent = helper.instrumentMockedAgent() const AWS = require('aws-sdk') @@ -39,24 +40,21 @@ tap.test('DynamoDB', (t) => { }) const tableName = `delete-aws-sdk-test-table-${Math.floor(Math.random() * 100000)}` - t.context.tests = createTests(ddb, docClient, tableName) + ctx.nr.tests = createTests(ddb, docClient, tableName) }) - t.afterEach((t) => { - t.context.server.close() - helper.unloadAgent(t.context.agent) + t.afterEach((ctx) => { + ctx.nr.server.close() + helper.unloadAgent(ctx.nr.agent) }) - t.test('commands with callback', (t) => { - const { tests, agent } = t.context + await t.test('commands with callback', (t, end) => { + const { tests, agent } = t.nr helper.runInTransaction(agent, async (tx) => { for (const test of tests) { - t.comment(`Testing ${test.method}`) - await new Promise((resolve) => { test.api[test.method](test.params, (err) => { - t.error(err) - + assert.ok(!err) return setImmediate(resolve) }) }) @@ -64,71 +62,65 @@ tap.test('DynamoDB', (t) => { tx.end() - const args = [t, tests, tx] + const args = [end, tests, tx] setImmediate(finish, ...args) }) }) - t.test('commands with promises', (t) => { - const { tests, agent } = t.context + await t.test('commands with promises', async (t) => { + const { tests, agent } = t.nr + const { promise, resolve } = promiseResolvers() helper.runInTransaction(agent, async function (tx) { // Execute commands in order // Await works because this is in a for-loop / no callback api - for (let i = 0; i < tests.length; i++) { - const cfg = tests[i] - - t.comment(`Testing ${cfg.method}`) - + for (const test of tests) { try { - await cfg.api[cfg.method](cfg.params).promise() + await test.api[test.method](test.params).promise() } catch (err) { - t.error(err) + assert.ok(!err) } } tx.end() - const args = [t, tests, tx] + const args = [resolve, tests, tx] setImmediate(finish, ...args) }) + await promise }) }) -function finish(t, tests, tx) { +function finish(end, tests, tx) { const root = tx.trace.root - const segments = common.checkAWSAttributes(t, root, common.DATASTORE_PATTERN) + const segments = common.checkAWSAttributes(root, common.DATASTORE_PATTERN) - t.equal(segments.length, tests.length, `should have ${tests.length} aws datastore segments`) + assert.equal(segments.length, tests.length, `should have ${tests.length} aws datastore segments`) - const externalSegments = common.checkAWSAttributes(t, root, common.EXTERN_PATTERN) - t.equal(externalSegments.length, 0, 'should not have any External segments') + const externalSegments = common.checkAWSAttributes(root, common.EXTERN_PATTERN) + assert.equal(externalSegments.length, 0, 'should not have any External segments') segments.forEach((segment, i) => { const operation = tests[i].operation - t.equal( + assert.equal( segment.name, `Datastore/operation/DynamoDB/${operation}`, 'should have operation in segment name' ) const attrs = segment.attributes.get(common.SEGMENT_DESTINATION) attrs.port_path_or_id = parseInt(attrs.port_path_or_id, 10) - t.match( - attrs, - { - 'host': String, - 'port_path_or_id': Number, - 'product': 'DynamoDB', - 'collection': String, - 'aws.operation': operation, - 'aws.requestId': String, - 'aws.region': 'us-east-1', - 'aws.service': 'DynamoDB' - }, - 'should have expected attributes' - ) + match(attrs, { + 'host': String, + 'port_path_or_id': Number, + 'product': 'DynamoDB', + 'collection': String, + 'aws.operation': operation, + 'aws.requestId': String, + 'aws.region': 'us-east-1', + 'aws.service': 'DynamoDB' + }) }) - t.end() + end() } function createTests(ddb, docClient, tableName) { diff --git a/test/versioned/aws-sdk-v2/http-services.tap.js b/test/versioned/aws-sdk-v2/http-services.tap.js index 679e6b11b1..ecf9e525df 100644 --- a/test/versioned/aws-sdk-v2/http-services.tap.js +++ b/test/versioned/aws-sdk-v2/http-services.tap.js @@ -4,39 +4,39 @@ */ 'use strict' - -const tap = require('tap') +const assert = require('node:assert') +const test = require('node:test') const helper = require('../../lib/agent_helper') const common = require('../aws-sdk-v3/common') const { createEmptyResponseServer, FAKE_CREDENTIALS } = require('../../lib/aws-server-stubs') +const { match } = require('../../lib/custom-assertions') -tap.test('AWS HTTP Services', (t) => { - t.autoend() - - t.beforeEach(async (t) => { +test('AWS HTTP Services', async (t) => { + t.beforeEach(async (ctx) => { + ctx.nr = {} const server = createEmptyResponseServer() await new Promise((resolve) => { server.listen(0, resolve) }) - t.context.server = server + ctx.nr.server = server - t.context.agent = helper.instrumentMockedAgent() + ctx.nr.agent = helper.instrumentMockedAgent() const AWS = require('aws-sdk') AWS.config.update({ region: 'us-east-1' }) - t.context.endpoint = `http://localhost:${server.address().port}` - t.context.AWS = AWS + ctx.nr.endpoint = `http://localhost:${server.address().port}` + ctx.nr.AWS = AWS }) - t.afterEach((t) => { - t.context.server.close() - helper.unloadAgent(t.context.agent) + t.afterEach((ctx) => { + ctx.nr.server.close() + helper.unloadAgent(ctx.nr.agent) }) - t.test('APIGateway', (t) => { - const { agent, endpoint, AWS } = t.context + await t.test('APIGateway', (t, end) => { + const { agent, endpoint, AWS } = t.nr helper.runInTransaction(agent, (tx) => { const service = new AWS.APIGateway({ credentials: FAKE_CREDENTIALS, @@ -59,14 +59,14 @@ tap.test('AWS HTTP Services', (t) => { }, () => { tx.end() - setImmediate(finish, t, 'API Gateway', 'createApiKey', tx) + setImmediate(finish, end, 'API Gateway', 'createApiKey', tx) } ) }) }) - t.test('ELB', (t) => { - const { agent, endpoint, AWS } = t.context + await t.test('ELB', (t, end) => { + const { agent, endpoint, AWS } = t.nr helper.runInTransaction(agent, (tx) => { const service = new AWS.ELB({ credentials: FAKE_CREDENTIALS, @@ -88,14 +88,14 @@ tap.test('AWS HTTP Services', (t) => { }, () => { tx.end() - setImmediate(finish, t, 'Elastic Load Balancing', 'addTags', tx) + setImmediate(finish, end, 'Elastic Load Balancing', 'addTags', tx) } ) }) }) - t.test('ElastiCache', (t) => { - const { agent, endpoint, AWS } = t.context + await t.test('ElastiCache', (t, end) => { + const { agent, endpoint, AWS } = t.nr helper.runInTransaction(agent, (tx) => { const service = new AWS.ElastiCache({ credentials: FAKE_CREDENTIALS, @@ -114,14 +114,14 @@ tap.test('AWS HTTP Services', (t) => { }, () => { tx.end() - setImmediate(finish, t, 'ElastiCache', 'addTagsToResource', tx) + setImmediate(finish, end, 'ElastiCache', 'addTagsToResource', tx) } ) }) }) - t.test('Lambda', (t) => { - const { agent, endpoint, AWS } = t.context + await t.test('Lambda', (t, end) => { + const { agent, endpoint, AWS } = t.nr helper.runInTransaction(agent, (tx) => { const service = new AWS.Lambda({ credentials: FAKE_CREDENTIALS, @@ -139,14 +139,14 @@ tap.test('AWS HTTP Services', (t) => { }, () => { tx.end() - setImmediate(finish, t, 'Lambda', 'addLayerVersionPermission', tx) + setImmediate(finish, end, 'Lambda', 'addLayerVersionPermission', tx) } ) }) }) - t.test('RDS', (t) => { - const { agent, endpoint, AWS } = t.context + await t.test('RDS', (t, end) => { + const { agent, endpoint, AWS } = t.nr helper.runInTransaction(agent, (tx) => { const service = new AWS.RDS({ credentials: FAKE_CREDENTIALS, @@ -159,14 +159,14 @@ tap.test('AWS HTTP Services', (t) => { }, () => { tx.end() - setImmediate(finish, t, 'Amazon RDS', 'addRoleToDBCluster', tx) + setImmediate(finish, end, 'Amazon RDS', 'addRoleToDBCluster', tx) } ) }) }) - t.test('Redshift', (t) => { - const { agent, endpoint, AWS } = t.context + await t.test('Redshift', (t, end) => { + const { agent, endpoint, AWS } = t.nr helper.runInTransaction(agent, (tx) => { const service = new AWS.Redshift({ credentials: FAKE_CREDENTIALS, @@ -179,14 +179,14 @@ tap.test('AWS HTTP Services', (t) => { }, () => { tx.end() - setImmediate(finish, t, 'Redshift', 'acceptReservedNodeExchange', tx) + setImmediate(finish, end, 'Redshift', 'acceptReservedNodeExchange', tx) } ) }) }) - t.test('Rekognition', (t) => { - const { agent, endpoint, AWS } = t.context + await t.test('Rekognition', (t, end) => { + const { agent, endpoint, AWS } = t.nr helper.runInTransaction(agent, (tx) => { const service = new AWS.Rekognition({ credentials: FAKE_CREDENTIALS, @@ -210,14 +210,14 @@ tap.test('AWS HTTP Services', (t) => { }, () => { tx.end() - setImmediate(finish, t, 'Rekognition', 'compareFaces', tx) + setImmediate(finish, end, 'Rekognition', 'compareFaces', tx) } ) }) }) - t.test('SES', (t) => { - const { agent, endpoint, AWS } = t.context + await t.test('SES', (t, end) => { + const { agent, endpoint, AWS } = t.nr helper.runInTransaction(agent, (tx) => { const service = new AWS.SES({ credentials: FAKE_CREDENTIALS, @@ -230,28 +230,24 @@ tap.test('AWS HTTP Services', (t) => { }, () => { tx.end() - setImmediate(finish, t, 'Amazon SES', 'cloneReceiptRuleSet', tx) + setImmediate(finish, end, 'Amazon SES', 'cloneReceiptRuleSet', tx) } ) }) }) }) -function finish(t, service, operation, tx) { - const externals = common.checkAWSAttributes(t, tx.trace.root, common.EXTERN_PATTERN) - if (t.equal(externals.length, 1, 'should have an aws external')) { +function finish(end, service, operation, tx) { + const externals = common.checkAWSAttributes(tx.trace.root, common.EXTERN_PATTERN) + if (assert.equal(externals.length, 1, 'should have an aws external')) { const attrs = externals[0].attributes.get(common.SEGMENT_DESTINATION) - t.match( - attrs, - { - 'aws.operation': operation, - 'aws.requestId': String, - 'aws.service': service, - 'aws.region': 'us-east-1' - }, - 'should have expected attributes' - ) + match(attrs, { + 'aws.operation': operation, + 'aws.requestId': String, + 'aws.service': service, + 'aws.region': 'us-east-1' + }) } - t.end() + end() } diff --git a/test/versioned/aws-sdk-v2/instrumentation-supported.tap.js b/test/versioned/aws-sdk-v2/instrumentation-supported.tap.js index 1e4b8aed36..1ea9557dbc 100644 --- a/test/versioned/aws-sdk-v2/instrumentation-supported.tap.js +++ b/test/versioned/aws-sdk-v2/instrumentation-supported.tap.js @@ -4,39 +4,36 @@ */ 'use strict' - -const tap = require('tap') +const assert = require('node:assert') +const test = require('node:test') const helper = require('../../lib/agent_helper') const instrumentationHelper = require('../../../lib/instrumentation/aws-sdk/v2/instrumentation-helper') -tap.test('instrumentation is supported', (t) => { - t.autoend() - - t.beforeEach((t) => { - t.context.agent = helper.instrumentMockedAgent() - t.context.AWS = require('aws-sdk') +test('instrumentation is supported', async (t) => { + t.beforeEach((ctx) => { + ctx.nr = {} + ctx.nr.agent = helper.instrumentMockedAgent() + ctx.nr.AWS = require('aws-sdk') }) - t.afterEach((t) => { - helper.unloadAgent(t.context.agent) + t.afterEach((ctx) => { + helper.unloadAgent(ctx.nr.agent) }) - t.test('AWS should be instrumented', (t) => { - const { AWS } = t.context - t.equal( + await t.test('AWS should be instrumented', (t) => { + const { AWS } = t.nr + assert.equal( AWS.NodeHttpClient.prototype.handleRequest.name, 'wrappedHandleRequest', 'AWS has a wrapped NodeHttpClient' ) - t.end() }) - t.test('instrumentation supported function', (t) => { - const { AWS } = t.context - t.ok( + await t.test('instrumentation supported function', (t) => { + const { AWS } = t.nr + assert.ok( instrumentationHelper.instrumentationSupported(AWS), 'instrumentationSupported returned true' ) - t.end() }) }) diff --git a/test/versioned/aws-sdk-v2/instrumentation-unsupported.tap.js b/test/versioned/aws-sdk-v2/instrumentation-unsupported.tap.js index 1c2db1e73f..eb48b6be36 100644 --- a/test/versioned/aws-sdk-v2/instrumentation-unsupported.tap.js +++ b/test/versioned/aws-sdk-v2/instrumentation-unsupported.tap.js @@ -4,39 +4,36 @@ */ 'use strict' - -const tap = require('tap') +const assert = require('node:assert') +const test = require('node:test') const helper = require('../../lib/agent_helper') const instrumentationHelper = require('../../../lib/instrumentation/aws-sdk/v2/instrumentation-helper') -tap.test('instrumentation is not supported', (t) => { - t.autoend() - - t.beforeEach((t) => { - t.context.agent = helper.instrumentMockedAgent() - t.context.AWS = require('aws-sdk') +test('instrumentation is not supported', async (t) => { + t.beforeEach((ctx) => { + ctx.nr = {} + ctx.nr.agent = helper.instrumentMockedAgent() + ctx.nr.AWS = require('aws-sdk') }) - t.afterEach((t) => { - helper.unloadAgent(t.context.agent) + t.afterEach((ctx) => { + helper.unloadAgent(ctx.nr.agent) }) - t.test('AWS should not be instrumented', (t) => { - const { AWS } = t.context - t.not( + await t.test('AWS should not be instrumented', (t) => { + const { AWS } = t.nr + assert.notEqual( AWS.NodeHttpClient.prototype.handleRequest.name, 'wrappedHandleRequest', 'AWS does not have a wrapped NodeHttpClient' ) - t.end() }) - t.test('instrumentation supported function', (t) => { - const { AWS } = t.context - t.notOk( - instrumentationHelper.instrumentationSupported(AWS), + await t.test('instrumentation supported function', (t) => { + const { AWS } = t.nr + assert.ok( + !instrumentationHelper.instrumentationSupported(AWS), 'instrumentationSupported returned false' ) - t.end() }) }) diff --git a/test/versioned/aws-sdk-v2/s3.tap.js b/test/versioned/aws-sdk-v2/s3.tap.js index 420f3608d6..50a2fe6d84 100644 --- a/test/versioned/aws-sdk-v2/s3.tap.js +++ b/test/versioned/aws-sdk-v2/s3.tap.js @@ -4,27 +4,28 @@ */ 'use strict' - -const tap = require('tap') +const assert = require('node:assert') +const test = require('node:test') const helper = require('../../lib/agent_helper') const common = require('../aws-sdk-v3/common') const { createEmptyResponseServer, FAKE_CREDENTIALS } = require('../../lib/aws-server-stubs') +const { match } = require('../../lib/custom-assertions') +const promiseResolvers = require('../../lib/promise-resolvers') -tap.test('S3 buckets', (t) => { - t.autoend() - - t.beforeEach(async (t) => { +test('S3 buckets', async (t) => { + t.beforeEach(async (ctx) => { + ctx.nr = {} const server = createEmptyResponseServer() await new Promise((resolve) => { server.listen(0, resolve) }) - t.context.server = server + ctx.nr.server = server - t.context.agent = helper.instrumentMockedAgent() + ctx.nr.agent = helper.instrumentMockedAgent() const AWS = require('aws-sdk') - t.context.S3 = new AWS.S3({ + ctx.nr.S3 = new AWS.S3({ credentials: FAKE_CREDENTIALS, endpoint: `http://localhost:${server.address().port}`, // allows using generic endpoint, instead of needing a @@ -34,27 +35,27 @@ tap.test('S3 buckets', (t) => { }) }) - t.afterEach((t) => { - t.context.server.close() - helper.unloadAgent(t.context.agent) + t.afterEach((ctx) => { + ctx.nr.server.close() + helper.unloadAgent(ctx.nr.agent) }) - t.test('commands with callbacks', (t) => { - const { agent, S3 } = t.context + await t.test('commands with callbacks', (t, end) => { + const { agent, S3 } = t.nr const Bucket = 'delete-aws-sdk-test-bucket-' + Math.floor(Math.random() * 100000) helper.runInTransaction(agent, (tx) => { S3.headBucket({ Bucket }, (err) => { - t.error(err) + assert.ok(!err) S3.createBucket({ Bucket }, (err) => { - t.error(err) + assert.ok(!err) S3.deleteBucket({ Bucket }, (err) => { - t.error(err) + assert.ok(!err) tx.end() - const args = [t, tx] + const args = [end, tx] setImmediate(finish, ...args) }) }) @@ -62,60 +63,41 @@ tap.test('S3 buckets', (t) => { }) }) - t.test('commands with promises', (t) => { - const { agent, S3 } = t.context + await t.test('commands with promises', async (t) => { + const { agent, S3 } = t.nr + const { promise, resolve } = promiseResolvers() const Bucket = 'delete-aws-sdk-test-bucket-' + Math.floor(Math.random() * 100000) helper.runInTransaction(agent, async (tx) => { - try { - await S3.headBucket({ Bucket }).promise() - } catch (err) { - t.error(err) - } - - try { - // using pathstyle will result in the params being mutated due to this call, - // which is why the params are manually pasted in each call. - await S3.createBucket({ Bucket }).promise() - } catch (err) { - t.error(err) - } - - try { - await S3.deleteBucket({ Bucket }).promise() - } catch (err) { - t.error(err) - } - + await S3.headBucket({ Bucket }).promise() + await S3.createBucket({ Bucket }).promise() + await S3.deleteBucket({ Bucket }).promise() tx.end() - const args = [t, tx] + const args = [resolve, tx] setImmediate(finish, ...args) }) + await promise }) }) -function finish(t, tx) { - const externals = common.checkAWSAttributes(t, tx.trace.root, common.EXTERN_PATTERN) - t.equal(externals.length, 3, 'should have 3 aws externals') +function finish(end, tx) { + const externals = common.checkAWSAttributes(tx.trace.root, common.EXTERN_PATTERN) + assert.equal(externals.length, 3, 'should have 3 aws externals') const [head, create, del] = externals - checkAttrs(t, head, 'headBucket') - checkAttrs(t, create, 'createBucket') - checkAttrs(t, del, 'deleteBucket') + checkAttrs(head, 'headBucket') + checkAttrs(create, 'createBucket') + checkAttrs(del, 'deleteBucket') - t.end() + end() } -function checkAttrs(t, segment, operation) { +function checkAttrs(segment, operation) { const attrs = segment.attributes.get(common.SEGMENT_DESTINATION) - t.match( - attrs, - { - 'aws.operation': operation, - 'aws.requestId': String, - 'aws.service': 'Amazon S3', - 'aws.region': 'us-east-1' - }, - `should have expected attributes for ${operation}` - ) + match(attrs, { + 'aws.operation': operation, + 'aws.requestId': String, + 'aws.service': 'Amazon S3', + 'aws.region': 'us-east-1' + }) } diff --git a/test/versioned/aws-sdk-v2/sns.tap.js b/test/versioned/aws-sdk-v2/sns.tap.js index 99d37ad834..372cb8e71d 100644 --- a/test/versioned/aws-sdk-v2/sns.tap.js +++ b/test/versioned/aws-sdk-v2/sns.tap.js @@ -4,93 +4,86 @@ */ 'use strict' - -const tap = require('tap') +const assert = require('node:assert') +const test = require('node:test') const helper = require('../../lib/agent_helper') const common = require('../aws-sdk-v3/common') const { createEmptyResponseServer, FAKE_CREDENTIALS } = require('../../lib/aws-server-stubs') +const { match } = require('../../lib/custom-assertions') +const promiseResolvers = require('../../lib/promise-resolvers') const TopicArn = null -tap.test('SNS', (t) => { - t.autoend() - - t.beforeEach(async (t) => { +test('SNS', async (t) => { + t.beforeEach(async (ctx) => { + ctx.nr = {} const server = createEmptyResponseServer() await new Promise((resolve) => { server.listen(0, resolve) }) - t.context.server = server + ctx.nr.server = server - t.context.agent = helper.instrumentMockedAgent() + ctx.nr.agent = helper.instrumentMockedAgent() const AWS = require('aws-sdk') - t.context.sns = new AWS.SNS({ + ctx.nr.sns = new AWS.SNS({ credentials: FAKE_CREDENTIALS, endpoint: `http://localhost:${server.address().port}`, region: 'us-east-1' }) }) - t.afterEach((t) => { - t.context.server.close() - helper.unloadAgent(t.context.agent) + t.afterEach((ctx) => { + ctx.nr.server.close() + helper.unloadAgent(ctx.nr.agent) }) - t.test('publish with callback', (t) => { - const { agent, sns } = t.context + await t.test('publish with callback', (t, end) => { + const { agent, sns } = t.nr helper.runInTransaction(agent, (tx) => { const params = { TopicArn, Message: 'Hello!' } sns.publish(params, (err) => { - t.error(err) + assert.ok(!err) tx.end() - const args = [t, tx] + const args = [end, tx] setImmediate(finish, ...args) }) }) }) - t.test('publish with promise', (t) => { - const { agent, sns } = t.context + await t.test('publish with promise', async (t) => { + const { agent, sns } = t.nr + const { promise, resolve } = promiseResolvers() helper.runInTransaction(agent, async (tx) => { const params = { TopicArn, Message: 'Hello!' } - try { - await sns.publish(params).promise() - } catch (error) { - t.error(error) - } - + await sns.publish(params).promise() tx.end() - const args = [t, tx] + const args = [resolve, tx] setImmediate(finish, ...args) }) + await promise }) }) -function finish(t, tx) { +function finish(end, tx) { const root = tx.trace.root - const messages = common.checkAWSAttributes(t, root, common.SNS_PATTERN) - t.equal(messages.length, 1, 'should have 1 message broker segment') + const messages = common.checkAWSAttributes(root, common.SNS_PATTERN) + assert.equal(messages.length, 1, 'should have 1 message broker segment') - const externalSegments = common.checkAWSAttributes(t, root, common.EXTERN_PATTERN) - t.equal(externalSegments.length, 0, 'should not have any External segments') + const externalSegments = common.checkAWSAttributes(root, common.EXTERN_PATTERN) + assert.equal(externalSegments.length, 0, 'should not have any External segments') const attrs = messages[0].attributes.get(common.SEGMENT_DESTINATION) - t.match( - attrs, - { - 'aws.operation': 'publish', - 'aws.requestId': String, - 'aws.service': 'Amazon SNS', - 'aws.region': 'us-east-1' - }, - 'should have expected attributes for publish' - ) - - t.end() + match(attrs, { + 'aws.operation': 'publish', + 'aws.requestId': String, + 'aws.service': 'Amazon SNS', + 'aws.region': 'us-east-1' + }), + end() } diff --git a/test/versioned/aws-sdk-v2/sqs.tap.js b/test/versioned/aws-sdk-v2/sqs.tap.js index 2326aad760..4b97825b85 100644 --- a/test/versioned/aws-sdk-v2/sqs.tap.js +++ b/test/versioned/aws-sdk-v2/sqs.tap.js @@ -4,59 +4,59 @@ */ 'use strict' - -const tap = require('tap') +const assert = require('node:assert') +const test = require('node:test') const helper = require('../../lib/agent_helper') const common = require('../aws-sdk-v3/common') const { createResponseServer, FAKE_CREDENTIALS } = require('../../lib/aws-server-stubs') +const { match } = require('../../lib/custom-assertions') +const promiseResolvers = require('../../lib/promise-resolvers') const AWS_REGION = 'us-east-1' -tap.test('SQS API', (t) => { - t.autoend() - - let sendMessageRequestId = null - let sendMessageBatchRequestId = null - let receiveMessageRequestId = null - - t.beforeEach(async (t) => { +test('SQS API', async (t) => { + t.beforeEach(async (ctx) => { + ctx.nr = {} const server = createResponseServer() await new Promise((resolve) => { server.listen(0, resolve) }) - t.context.server = server - t.context.agent = helper.instrumentMockedAgent() + ctx.nr.server = server + ctx.nr.agent = helper.instrumentMockedAgent() const AWS = require('aws-sdk') const endpoint = `http://localhost:${server.address().port}` - t.context.sqs = new AWS.SQS({ + ctx.nr.sqs = new AWS.SQS({ credentials: FAKE_CREDENTIALS, endpoint: endpoint, apiVersion: '2012-11-05', region: AWS_REGION }) - t.context.queueName = 'delete-aws-sdk-test-queue-' + Math.floor(Math.random() * 100000) + ctx.nr.queueName = 'delete-aws-sdk-test-queue-' + Math.floor(Math.random() * 100000) }) - t.afterEach((t) => { - t.context.server.close() - helper.unloadAgent(t.context.agent) + t.afterEach((ctx) => { + ctx.nr.server.close() + helper.unloadAgent(ctx.nr.agent) }) - t.test('commands with callback', (t) => { - const { agent, queueName, sqs } = t.context + await t.test('commands with callback', (t, end) => { + const { agent, queueName, sqs } = t.nr const createParams = getCreateParams(queueName) + let sendMessageRequestId + let sendMessageBatchRequestId + let receiveMessageRequestId sqs.createQueue(createParams, function (createErr, createData) { - t.error(createErr) + assert.ok(!createErr) const queueUrl = createData.QueueUrl helper.runInTransaction(agent, (transaction) => { const sendMessageParams = getSendMessageParams(queueUrl) sqs.sendMessage(sendMessageParams, function sendMessageCb(sendErr, sendData) { - t.error(sendErr) - t.ok(sendData.MessageId) + assert.ok(!sendErr) + assert.ok(sendData.MessageId) sendMessageRequestId = this.requestId @@ -64,8 +64,8 @@ tap.test('SQS API', (t) => { sqs.sendMessageBatch( sendMessageBatchParams, function sendBatchCb(sendBatchErr, sendBatchData) { - t.error(sendBatchErr) - t.ok(sendBatchData.Successful) + assert.ok(!sendBatchErr) + assert.ok(sendBatchData.Successful) sendMessageBatchRequestId = this.requestId @@ -73,14 +73,21 @@ tap.test('SQS API', (t) => { sqs.receiveMessage( receiveMessageParams, function receiveMsgCb(receiveErr, receiveData) { - t.error(receiveErr) - t.ok(receiveData.Messages) + assert.ok(!receiveErr) + assert.ok(receiveData.Messages) receiveMessageRequestId = this.requestId transaction.end() - const args = { t, transaction, queueName } + const args = { + end, + transaction, + queueName, + sendMessageRequestId, + sendMessageBatchRequestId, + receiveMessageRequestId + } setImmediate(finish, args) } ) @@ -91,90 +98,94 @@ tap.test('SQS API', (t) => { }) }) - t.test('commands with promises', (t) => { - const { agent, queueName, sqs } = t.context + await t.test('commands with promises', async (t) => { + const { agent, queueName, sqs } = t.nr + const { promise, resolve } = promiseResolvers() const createParams = getCreateParams(queueName) + let sendMessageRequestId + let sendMessageBatchRequestId + let receiveMessageRequestId sqs.createQueue(createParams, function (createErr, createData) { - t.error(createErr) + assert.ok(!createErr) const queueUrl = createData.QueueUrl helper.runInTransaction(agent, async (transaction) => { - try { - const sendMessageParams = getSendMessageParams(queueUrl) - const sendData = await sqs.sendMessage(sendMessageParams).promise() - t.ok(sendData.MessageId) - - sendMessageRequestId = getRequestId(sendData) - } catch (error) { - t.error(error) - } - - try { - const sendMessageBatchParams = getSendMessageBatchParams(queueUrl) - const sendBatchData = await sqs.sendMessageBatch(sendMessageBatchParams).promise() - t.ok(sendBatchData.Successful) - - sendMessageBatchRequestId = getRequestId(sendBatchData) - } catch (error) { - t.error(error) - } + const sendMessageParams = getSendMessageParams(queueUrl) + const sendData = await sqs.sendMessage(sendMessageParams).promise() + assert.ok(sendData.MessageId) - try { - const receiveMessageParams = getReceiveMessageParams(queueUrl) - const receiveData = await sqs.receiveMessage(receiveMessageParams).promise() - t.ok(receiveData.Messages) + sendMessageRequestId = getRequestId(sendData) + const sendMessageBatchParams = getSendMessageBatchParams(queueUrl) + const sendBatchData = await sqs.sendMessageBatch(sendMessageBatchParams).promise() + assert.ok(sendBatchData.Successful) - receiveMessageRequestId = getRequestId(receiveData) - } catch (error) { - t.error(error) - } + sendMessageBatchRequestId = getRequestId(sendBatchData) + const receiveMessageParams = getReceiveMessageParams(queueUrl) + const receiveData = await sqs.receiveMessage(receiveMessageParams).promise() + assert.ok(receiveData.Messages) + receiveMessageRequestId = getRequestId(receiveData) transaction.end() - const args = { t, transaction, queueName } + const args = { + end: resolve, + transaction, + queueName, + sendMessageRequestId, + sendMessageBatchRequestId, + receiveMessageRequestId + } setImmediate(finish, args) }) }) + await promise }) +}) - function finish({ t, transaction, queueName }) { - const expectedSegmentCount = 3 +function finish({ + end, + transaction, + queueName, + sendMessageRequestId, + sendMessageBatchRequestId, + receiveMessageRequestId +}) { + const expectedSegmentCount = 3 - const root = transaction.trace.root - const segments = common.checkAWSAttributes(t, root, common.SQS_PATTERN) + const root = transaction.trace.root + const segments = common.checkAWSAttributes(root, common.SQS_PATTERN) - t.equal( - segments.length, - expectedSegmentCount, - `should have ${expectedSegmentCount} AWS MessageBroker/SQS segments` - ) + assert.equal( + segments.length, + expectedSegmentCount, + `should have ${expectedSegmentCount} AWS MessageBroker/SQS segments` + ) - const externalSegments = common.checkAWSAttributes(t, root, common.EXTERN_PATTERN) - t.equal(externalSegments.length, 0, 'should not have any External segments') + const externalSegments = common.checkAWSAttributes(root, common.EXTERN_PATTERN) + assert.equal(externalSegments.length, 0, 'should not have any External segments') - const [sendMessage, sendMessageBatch, receiveMessage] = segments + const [sendMessage, sendMessageBatch, receiveMessage] = segments - checkName(t, sendMessage.name, 'Produce', queueName) - checkAttributes(t, sendMessage, 'sendMessage', sendMessageRequestId) + checkName(sendMessage.name, 'Produce', queueName) + checkAttributes(sendMessage, 'sendMessage', sendMessageRequestId) - checkName(t, sendMessageBatch.name, 'Produce', queueName) - checkAttributes(t, sendMessageBatch, 'sendMessageBatch', sendMessageBatchRequestId) + checkName(sendMessageBatch.name, 'Produce', queueName) + checkAttributes(sendMessageBatch, 'sendMessageBatch', sendMessageBatchRequestId) - checkName(t, receiveMessage.name, 'Consume', queueName) - checkAttributes(t, receiveMessage, 'receiveMessage', receiveMessageRequestId) + checkName(receiveMessage.name, 'Consume', queueName) + checkAttributes(receiveMessage, 'receiveMessage', receiveMessageRequestId) - t.end() - } -}) + end() +} -function checkName(t, name, action, queueName) { +function checkName(name, action, queueName) { const specificName = `/${action}/Named/${queueName}` - t.match(name, specificName, 'should have correct name') + match(name, specificName) } -function checkAttributes(t, segment, operation, expectedRequestId) { +function checkAttributes(segment, operation, expectedRequestId) { const actualAttributes = segment.attributes.get(common.SEGMENT_DESTINATION) const expectedAttributes = { @@ -184,7 +195,7 @@ function checkAttributes(t, segment, operation, expectedRequestId) { 'aws.region': AWS_REGION } - t.match(actualAttributes, expectedAttributes, `should have expected attributes for ${operation}`) + match(actualAttributes, expectedAttributes) } function getRequestId(data) { diff --git a/test/versioned/aws-sdk-v3/api-gateway.tap.js b/test/versioned/aws-sdk-v3/api-gateway.tap.js index 7910710156..5f00c4672d 100644 --- a/test/versioned/aws-sdk-v3/api-gateway.tap.js +++ b/test/versioned/aws-sdk-v3/api-gateway.tap.js @@ -5,37 +5,37 @@ 'use strict' -const tap = require('tap') +const test = require('node:test') const helper = require('../../lib/agent_helper') -require('./common') +const { afterEach, checkExternals } = require('./common') const { createEmptyResponseServer, FAKE_CREDENTIALS } = require('../../lib/aws-server-stubs') +const promiseResolvers = require('../../lib/promise-resolvers') -tap.test('APIGatewayClient', (t) => { - t.beforeEach(async (t) => { +test('APIGatewayClient', async (t) => { + t.beforeEach(async (ctx) => { + ctx.nr = {} const server = createEmptyResponseServer() await new Promise((resolve) => { server.listen(0, resolve) }) - t.context.server = server - t.context.agent = helper.instrumentMockedAgent() + ctx.nr.server = server + ctx.nr.agent = helper.instrumentMockedAgent() const { APIGatewayClient, ...lib } = require('@aws-sdk/client-api-gateway') - t.context.CreateApiKeyCommand = lib.CreateApiKeyCommand + ctx.nr.CreateApiKeyCommand = lib.CreateApiKeyCommand const endpoint = `http://localhost:${server.address().port}` - t.context.service = new APIGatewayClient({ + ctx.nr.service = new APIGatewayClient({ credentials: FAKE_CREDENTIALS, endpoint, region: 'us-east-1' }) }) - t.afterEach((t) => { - t.context.server.destroy() - helper.unloadAgent(t.context.agent) - }) + t.afterEach(afterEach) - t.test('CreateApiKeyCommand', (t) => { - const { agent, service, CreateApiKeyCommand } = t.context + await t.test('CreateApiKeyCommand', async (t) => { + const { agent, service, CreateApiKeyCommand } = t.nr + const { promise, resolve } = promiseResolvers() helper.runInTransaction(agent, async (tx) => { const cmd = new CreateApiKeyCommand({ customerId: 'STRING_VALUE', @@ -53,12 +53,13 @@ tap.test('APIGatewayClient', (t) => { }) await service.send(cmd) tx.end() - setImmediate(t.checkExternals, { + setImmediate(checkExternals, { + end: resolve, service: 'API Gateway', operations: ['CreateApiKeyCommand'], tx }) }) + await promise }) - t.end() }) diff --git a/test/versioned/aws-sdk-v3/bedrock-chat-completions.tap.js b/test/versioned/aws-sdk-v3/bedrock-chat-completions.tap.js index cda36a41cc..ffc90e570e 100644 --- a/test/versioned/aws-sdk-v3/bedrock-chat-completions.tap.js +++ b/test/versioned/aws-sdk-v3/bedrock-chat-completions.tap.js @@ -4,14 +4,16 @@ */ 'use strict' - -const tap = require('tap') -require('./common') +const assert = require('node:assert') +const test = require('node:test') +const { afterEach, assertChatCompletionMessages, assertChatCompletionSummary } = require('./common') const helper = require('../../lib/agent_helper') -require('../../lib/metrics_helper') const createAiResponseServer = require('../../lib/aws-server-stubs/ai-server') const { FAKE_CREDENTIALS } = require('../../lib/aws-server-stubs') const { DESTINATIONS } = require('../../../lib/config/attribute-filter') +const { assertSegments, match } = require('../../lib/custom-assertions') +const promiseResolvers = require('../../lib/promise-resolvers') +const { tspl } = require('@matteo.collina/tspl') const requests = { ai21: (prompt, modelId) => ({ @@ -54,20 +56,21 @@ const requests = { }) } -tap.beforeEach(async (t) => { - t.context.agent = helper.instrumentMockedAgent({ +test.beforeEach(async (ctx) => { + ctx.nr = {} + ctx.nr.agent = helper.instrumentMockedAgent({ ai_monitoring: { enabled: true } }) const bedrock = require('@aws-sdk/client-bedrock-runtime') - t.context.bedrock = bedrock + ctx.nr.bedrock = bedrock const { server, baseUrl, responses, host, port } = await createAiResponseServer() - t.context.server = server - t.context.baseUrl = baseUrl - t.context.responses = responses - t.context.expectedExternalPath = (modelId, method = 'invoke') => + ctx.nr.server = server + ctx.nr.baseUrl = baseUrl + ctx.nr.responses = responses + ctx.nr.expectedExternalPath = (modelId, method = 'invoke') => `External/${host}:${port}/model/${encodeURIComponent(modelId)}/${method}` const client = new bedrock.BedrockRuntimeClient({ @@ -76,22 +79,10 @@ tap.beforeEach(async (t) => { endpoint: baseUrl, maxAttempts: 1 }) - t.context.client = client + ctx.nr.client = client }) -tap.afterEach(async (t) => { - helper.unloadAgent(t.context.agent) - t.context.server.destroy() - Object.keys(require.cache).forEach((key) => { - if ( - key.includes('@smithy/smithy-client') || - key.includes('@aws-sdk/smithy-client') || - key.includes('@aws-sdk/client-bedrock-runtime') - ) { - delete require.cache[key] - } - }) -}) +test.afterEach(afterEach) ;[ { modelId: 'ai21.j2-ultra-v1', resKey: 'ai21' }, { modelId: 'amazon.titan-text-express-v1', resKey: 'amazon' }, @@ -101,103 +92,95 @@ tap.afterEach(async (t) => { { modelId: 'meta.llama2-13b-chat-v1', resKey: 'llama' }, { modelId: 'meta.llama3-8b-instruct-v1:0', resKey: 'llama' } ].forEach(({ modelId, resKey }) => { - tap.test(`${modelId}: should properly create completion segment`, (t) => { - const { bedrock, client, responses, agent, expectedExternalPath } = t.context + test(`${modelId}: should properly create completion segment`, async (t) => { + const { bedrock, client, responses, agent, expectedExternalPath } = t.nr const prompt = `text ${resKey} ultimate question` const input = requests[resKey](prompt, modelId) const command = new bedrock.InvokeModelCommand(input) const expected = responses[resKey].get(prompt) - helper.runInTransaction(agent, async (tx) => { + await helper.runInTransaction(agent, async (tx) => { const response = await client.send(command) const body = JSON.parse(response.body.transformToString('utf8')) - t.equal(response.$metadata.requestId, expected.headers['x-amzn-requestid']) - t.same(body, expected.body) - t.assertSegments( + assert.equal(response.$metadata.requestId, expected.headers['x-amzn-requestid']) + assert.deepEqual(body, expected.body) + assertSegments( tx.trace.root, ['Llm/completion/Bedrock/InvokeModelCommand', [expectedExternalPath(modelId)]], { exact: false } ) tx.end() - t.end() }) }) - tap.test( - `${modelId}: properly create the LlmChatCompletionMessage(s) and LlmChatCompletionSummary events`, - (t) => { - const { bedrock, client, agent } = t.context - const prompt = `text ${resKey} ultimate question` - const input = requests[resKey](prompt, modelId) - const command = new bedrock.InvokeModelCommand(input) + test(`${modelId}: properly create the LlmChatCompletionMessage(s) and LlmChatCompletionSummary events`, async (t) => { + const { bedrock, client, agent } = t.nr + const prompt = `text ${resKey} ultimate question` + const input = requests[resKey](prompt, modelId) + const command = new bedrock.InvokeModelCommand(input) - const api = helper.getAgentApi() - helper.runInTransaction(agent, async (tx) => { - api.addCustomAttribute('llm.conversation_id', 'convo-id') - await client.send(command) - const events = agent.customEventAggregator.events.toArray() - t.equal(events.length, 3) - const chatSummary = events.filter(([{ type }]) => type === 'LlmChatCompletionSummary')[0] - const chatMsgs = events.filter(([{ type }]) => type === 'LlmChatCompletionMessage') + const api = helper.getAgentApi() + await helper.runInTransaction(agent, async (tx) => { + api.addCustomAttribute('llm.conversation_id', 'convo-id') + await client.send(command) + const events = agent.customEventAggregator.events.toArray() + assert.equal(events.length, 3) + const chatSummary = events.filter(([{ type }]) => type === 'LlmChatCompletionSummary')[0] + const chatMsgs = events.filter(([{ type }]) => type === 'LlmChatCompletionMessage') + + assertChatCompletionMessages({ + modelId, + prompt, + resContent: '42', + tx, + expectedId: modelId.includes('ai21') || modelId.includes('cohere') ? '1234' : null, + chatMsgs + }) - t.llmMessages({ - modelId, - prompt, - resContent: '42', - tx, - expectedId: modelId.includes('ai21') || modelId.includes('cohere') ? '1234' : null, - chatMsgs - }) + assertChatCompletionSummary({ tx, modelId, chatSummary }) - t.llmSummary({ tx, modelId, chatSummary }) + tx.end() + }) + }) - tx.end() - t.end() - }) - } - ) + test(`${modelId}: supports custom attributes on LlmChatCompletionMessage(s) and LlmChatCompletionSummary events`, async (t) => { + const { bedrock, client, agent } = t.nr + const { promise, resolve } = promiseResolvers() + const prompt = `text ${resKey} ultimate question` + const input = requests[resKey](prompt, modelId) + const command = new bedrock.InvokeModelCommand(input) - tap.test( - `${modelId}: supports custom attributes on LlmChatCompletionMessage(s) and LlmChatCompletionSummary events`, - (t) => { - const { bedrock, client, agent } = t.context - const prompt = `text ${resKey} ultimate question` - const input = requests[resKey](prompt, modelId) - const command = new bedrock.InvokeModelCommand(input) + const api = helper.getAgentApi() + helper.runInTransaction(agent, (tx) => { + api.addCustomAttribute('llm.conversation_id', 'convo-id') + api.withLlmCustomAttributes({ 'llm.contextAttribute': 'someValue' }, async () => { + await client.send(command) + const events = agent.customEventAggregator.events.toArray() - const api = helper.getAgentApi() - helper.runInTransaction(agent, async (tx) => { - api.addCustomAttribute('llm.conversation_id', 'convo-id') - api.withLlmCustomAttributes({ 'llm.contextAttribute': 'someValue' }, async () => { - await client.send(command) - const events = agent.customEventAggregator.events.toArray() - - const chatSummary = events.filter(([{ type }]) => type === 'LlmChatCompletionSummary')[0] - const [, message] = chatSummary - t.equal(message['llm.contextAttribute'], 'someValue') - - tx.end() - t.end() - }) + const chatSummary = events.filter(([{ type }]) => type === 'LlmChatCompletionSummary')[0] + const [, message] = chatSummary + assert.equal(message['llm.contextAttribute'], 'someValue') + + tx.end() + resolve() }) - } - ) + }) + await promise + }) - tap.test(`${modelId}: text answer (streamed)`, (t) => { + test(`${modelId}: text answer (streamed)`, async (t) => { if (modelId.includes('ai21')) { - t.skip('model does not support streaming') - t.end() return } - const { bedrock, client, agent } = t.context + const { bedrock, client, agent } = t.nr const prompt = `text ${resKey} ultimate question streamed` const input = requests[resKey](prompt, modelId) const command = new bedrock.InvokeModelWithResponseStreamCommand(input) const api = helper.getAgentApi() - helper.runInTransaction(agent, async (tx) => { + await helper.runInTransaction(agent, async (tx) => { api.addCustomAttribute('llm.conversation_id', 'convo-id') const response = await client.send(command) @@ -209,9 +192,9 @@ tap.afterEach(async (t) => { const events = agent.customEventAggregator.events.toArray() const chatSummary = events.filter(([{ type }]) => type === 'LlmChatCompletionSummary')[0] const chatMsgs = events.filter(([{ type }]) => type === 'LlmChatCompletionMessage') - t.equal(events.length > 2, true) + assert.equal(events.length > 2, true) - t.llmMessages({ + assertChatCompletionMessages({ modelId, prompt, resContent: '42', @@ -220,21 +203,20 @@ tap.afterEach(async (t) => { chatMsgs }) - t.llmSummary({ tx, modelId, chatSummary, numMsgs: events.length - 1 }) + assertChatCompletionSummary({ tx, modelId, chatSummary, numMsgs: events.length - 1 }) tx.end() - t.end() }) }) - tap.test('should record feedback message accordingly', (t) => { - const { bedrock, client, agent } = t.context + test('should record feedback message accordingly', async (t) => { + const { bedrock, client, agent } = t.nr const prompt = `text ${resKey} ultimate question` const input = requests[resKey](prompt, modelId) const command = new bedrock.InvokeModelCommand(input) const api = helper.getAgentApi() - helper.runInTransaction(agent, async (tx) => { + await helper.runInTransaction(agent, async (tx) => { await client.send(command) const { traceId } = api.getTraceMetadata() api.recordLlmFeedbackEvent({ @@ -247,7 +229,7 @@ tap.afterEach(async (t) => { const recordedEvents = agent.customEventAggregator.getEvents() const [[, feedback]] = recordedEvents.filter(([{ type }]) => type === 'LlmFeedbackMessage') - t.match(feedback, { + match(feedback, { id: /[\w\d]{32}/, trace_id: traceId, category: 'test-event', @@ -258,29 +240,27 @@ tap.afterEach(async (t) => { }) tx.end() - t.end() }) }) - tap.test(`${modelId}: should increment tracking metric for each chat completion event`, (t) => { - const { bedrock, client, agent } = t.context + test(`${modelId}: should increment tracking metric for each chat completion event`, async (t) => { + const { bedrock, client, agent } = t.nr const prompt = `text ${resKey} ultimate question` const input = requests[resKey](prompt, modelId) const command = new bedrock.InvokeModelCommand(input) - helper.runInTransaction(agent, async (tx) => { + await helper.runInTransaction(agent, async (tx) => { await client.send(command) const metrics = getPrefixedMetric({ agent, metricPrefix: 'Supportability/Nodejs/ML/Bedrock' }) - t.equal(metrics.callCount > 0, true) + assert.equal(metrics.callCount > 0, true) tx.end() - t.end() }) }) - tap.test(`${modelId}: should properly create errors on create completion`, (t) => { - const { bedrock, client, agent, expectedExternalPath } = t.context + test(`${modelId}: should properly create errors on create completion`, async (t) => { + const { bedrock, client, agent, expectedExternalPath } = t.nr const prompt = `text ${resKey} ultimate question error` const input = requests[resKey](prompt, modelId) @@ -290,17 +270,17 @@ tap.afterEach(async (t) => { const expectedType = 'ValidationException' const api = helper.getAgentApi() - helper.runInTransaction(agent, async (tx) => { + await helper.runInTransaction(agent, async (tx) => { api.addCustomAttribute('llm.conversation_id', 'convo-id') try { await client.send(command) } catch (err) { - t.equal(err.message, expectedMsg) - t.equal(err.name, expectedType) + assert.equal(err.message, expectedMsg) + assert.equal(err.name, expectedType) } - t.equal(tx.exceptions.length, 1) - t.match(tx.exceptions[0], { + assert.equal(tx.exceptions.length, 1) + match(tx.exceptions[0], { error: { name: expectedType, message: expectedMsg @@ -316,53 +296,51 @@ tap.afterEach(async (t) => { } }) - t.assertSegments( + assertSegments( tx.trace.root, ['Llm/completion/Bedrock/InvokeModelCommand', [expectedExternalPath(modelId)]], { exact: false } ) const events = agent.customEventAggregator.events.toArray() - t.equal(events.length, 2) + assert.equal(events.length, 2) const chatSummary = events.filter(([{ type }]) => type === 'LlmChatCompletionSummary')[0] const chatMsgs = events.filter(([{ type }]) => type === 'LlmChatCompletionMessage') - t.llmMessages({ + assertChatCompletionMessages({ modelId, prompt, tx, chatMsgs }) - t.llmSummary({ tx, modelId, chatSummary, error: true }) + assertChatCompletionSummary({ tx, modelId, chatSummary, error: true }) tx.end() - t.end() }) }) - tap.test(`{${modelId}:}: should add llm attribute to transaction`, (t) => { - const { bedrock, client, agent } = t.context + test(`{${modelId}:}: should add llm attribute to transaction`, async (t) => { + const { bedrock, client, agent } = t.nr const prompt = `text ${resKey} ultimate question` const input = requests[resKey](prompt, modelId) const command = new bedrock.InvokeModelCommand(input) - helper.runInTransaction(agent, async (tx) => { + await helper.runInTransaction(agent, async (tx) => { await client.send(command) const attributes = tx.trace.attributes.get(DESTINATIONS.TRANS_EVENT) - t.equal(attributes.llm, true) + assert.equal(attributes.llm, true) tx.end() - t.end() }) }) - tap.test(`${modelId}: should decorate messages with custom attrs`, (t) => { - const { bedrock, client, agent } = t.context + test(`${modelId}: should decorate messages with custom attrs`, async (t) => { + const { bedrock, client, agent } = t.nr const prompt = `text ${resKey} ultimate question` const input = requests[resKey](prompt, modelId) const command = new bedrock.InvokeModelCommand(input) - helper.runInTransaction(agent, async (tx) => { + await helper.runInTransaction(agent, async (tx) => { const api = helper.getAgentApi() api.addCustomAttribute('llm.foo', 'bar') @@ -378,17 +356,16 @@ tap.afterEach(async (t) => { .map((e) => e[1]) .pop() - t.equal(summary['llm.foo'], 'bar') - t.equal(completion['llm.foo'], 'bar') + assert.equal(summary['llm.foo'], 'bar') + assert.equal(completion['llm.foo'], 'bar') tx.end() - t.end() }) }) }) -tap.test(`cohere embedding streaming works`, (t) => { - const { bedrock, client, agent } = t.context +test(`cohere embedding streaming works`, async (t) => { + const { bedrock, client, agent } = t.nr const prompt = `embed text cohere stream` const input = { body: JSON.stringify({ @@ -400,7 +377,7 @@ tap.test(`cohere embedding streaming works`, (t) => { const command = new bedrock.InvokeModelWithResponseStreamCommand(input) const api = helper.getAgentApi() - helper.runInTransaction(agent, async (tx) => { + await helper.runInTransaction(agent, async (tx) => { api.addCustomAttribute('llm.conversation_id', 'convo-id') const response = await client.send(command) @@ -410,18 +387,17 @@ tap.test(`cohere embedding streaming works`, (t) => { } const events = agent.customEventAggregator.events.toArray() - t.equal(events.length, 1) + assert.equal(events.length, 1) const embedding = events.shift()[1] - t.equal(embedding.error, false) - t.equal(embedding.input, prompt) + assert.equal(embedding.error, false) + assert.equal(embedding.input, prompt) tx.end() - t.end() }) }) -tap.test(`ai21: should properly create errors on create completion (streamed)`, (t) => { - const { bedrock, client, agent, expectedExternalPath } = t.context +test(`ai21: should properly create errors on create completion (streamed)`, async (t) => { + const { bedrock, client, agent, expectedExternalPath } = t.nr const modelId = 'ai21.j2-mid-v1' const prompt = `text ai21 ultimate question error streamed` const input = requests.ai21(prompt, modelId) @@ -431,17 +407,17 @@ tap.test(`ai21: should properly create errors on create completion (streamed)`, const expectedType = 'ValidationException' const api = helper.getAgentApi() - helper.runInTransaction(agent, async (tx) => { + await helper.runInTransaction(agent, async (tx) => { api.addCustomAttribute('llm.conversation_id', 'convo-id') try { await client.send(command) } catch (err) { - t.equal(err.message, expectedMsg) - t.equal(err.name, expectedType) + assert.equal(err.message, expectedMsg) + assert.equal(err.name, expectedType) } - t.equal(tx.exceptions.length, 1) - t.match(tx.exceptions[0], { + assert.equal(tx.exceptions.length, 1) + match(tx.exceptions[0], { error: { name: expectedType, message: expectedMsg @@ -457,7 +433,7 @@ tap.test(`ai21: should properly create errors on create completion (streamed)`, } }) - t.assertSegments( + assertSegments( tx.trace.root, [ 'Llm/completion/Bedrock/InvokeModelWithResponseStreamCommand', @@ -467,25 +443,24 @@ tap.test(`ai21: should properly create errors on create completion (streamed)`, ) const events = agent.customEventAggregator.events.toArray() - t.equal(events.length, 2) + assert.equal(events.length, 2) const chatSummary = events.filter(([{ type }]) => type === 'LlmChatCompletionSummary')[0] const chatMsgs = events.filter(([{ type }]) => type === 'LlmChatCompletionMessage') - t.llmMessages({ + assertChatCompletionMessages({ modelId, prompt, tx, chatMsgs }) - t.llmSummary({ tx, modelId, chatSummary, error: true }) + assertChatCompletionSummary({ tx, modelId, chatSummary, error: true }) tx.end() - t.end() }) }) -tap.test(`models that do not support streaming should be handled`, (t) => { - const { bedrock, client, agent, expectedExternalPath } = t.context +test(`models that do not support streaming should be handled`, async (t) => { + const { bedrock, client, agent, expectedExternalPath } = t.nr const modelId = 'amazon.titan-embed-text-v1' const prompt = `embed text amazon error streamed` const input = requests.amazon(prompt, modelId) @@ -495,17 +470,17 @@ tap.test(`models that do not support streaming should be handled`, (t) => { const expectedType = 'ValidationException' const api = helper.getAgentApi() - helper.runInTransaction(agent, async (tx) => { + await helper.runInTransaction(agent, async (tx) => { api.addCustomAttribute('llm.conversation_id', 'convo-id') try { await client.send(command) } catch (err) { - t.equal(err.message, expectedMsg) - t.equal(err.name, expectedType) + assert.equal(err.message, expectedMsg) + assert.equal(err.name, expectedType) } - t.equal(tx.exceptions.length, 1) - t.match(tx.exceptions[0], { + assert.equal(tx.exceptions.length, 1) + match(tx.exceptions[0], { error: { name: expectedType, message: expectedMsg @@ -521,7 +496,7 @@ tap.test(`models that do not support streaming should be handled`, (t) => { } }) - t.assertSegments( + assertSegments( tx.trace.root, [ 'Llm/embedding/Bedrock/InvokeModelWithResponseStreamCommand', @@ -531,29 +506,28 @@ tap.test(`models that do not support streaming should be handled`, (t) => { ) const events = agent.customEventAggregator.events.toArray() - t.equal(events.length, 1) + assert.equal(events.length, 1) const embedding = events.shift()[1] - t.equal(embedding.error, true) + assert.equal(embedding.error, true) tx.end() - t.end() }) }) -tap.test(`models should properly create errors on stream interruption`, (t) => { - const { bedrock, client, agent } = t.context +test(`models should properly create errors on stream interruption`, async (t) => { + const { bedrock, client, agent } = t.nr const modelId = 'amazon.titan-text-express-v1' const prompt = `text amazon bad stream` const input = requests.amazon(prompt, modelId) const command = new bedrock.InvokeModelWithResponseStreamCommand(input) - helper.runInTransaction(agent, async (tx) => { + await helper.runInTransaction(agent, async (tx) => { try { await client.send(command) } catch (error) { - t.match(error, { + match(error, { code: 'ECONNRESET', - message: 'aborted', + message: /aborted/, $response: { statusCode: 500 } @@ -562,24 +536,23 @@ tap.test(`models should properly create errors on stream interruption`, (t) => { const events = agent.customEventAggregator.events.toArray() const summary = events.find((e) => e[0].type === 'LlmChatCompletionSummary')[1] - t.equal(tx.exceptions.length, 1) - t.equal(events.length, 2) - t.equal(summary.error, true) + assert.equal(tx.exceptions.length, 1) + assert.equal(events.length, 2) + assert.equal(summary.error, true) tx.end() - t.end() }) }) -tap.test('should not instrument stream when disabled', (t) => { +test('should not instrument stream when disabled', async (t) => { const modelId = 'amazon.titan-text-express-v1' - const { bedrock, client, agent } = t.context + const { bedrock, client, agent } = t.nr agent.config.ai_monitoring.streaming.enabled = false const prompt = `text amazon ultimate question streamed` const input = requests.amazon(prompt, modelId) const command = new bedrock.InvokeModelWithResponseStreamCommand(input) - helper.runInTransaction(agent, async (tx) => { + await helper.runInTransaction(agent, async (tx) => { const response = await client.send(command) let chunk = {} let inputCount = null @@ -595,7 +568,7 @@ tap.test('should not instrument stream when disabled', (t) => { } chunk.inputTextTokenCount = inputCount chunk.outputText = completion - t.same( + assert.deepEqual( chunk, { 'outputText': '42', @@ -614,52 +587,54 @@ tap.test('should not instrument stream when disabled', (t) => { ) const events = agent.customEventAggregator.events.toArray() - t.equal(events.length, 0, 'should not create Llm events when streaming is disabled') + assert.equal(events.length, 0, 'should not create Llm events when streaming is disabled') const attributes = tx.trace.attributes.get(DESTINATIONS.TRANS_EVENT) - t.equal(attributes.llm, true, 'should assign llm attribute to transaction trace') + assert.equal(attributes.llm, true, 'should assign llm attribute to transaction trace') const metrics = getPrefixedMetric({ agent, metricPrefix: 'Supportability/Nodejs/ML/Bedrock' }) - t.equal(metrics.callCount > 0, true, 'should set framework metric') + assert.equal(metrics.callCount > 0, true, 'should set framework metric') const supportabilityMetrics = agent.metrics.getOrCreateMetric( `Supportability/Nodejs/ML/Streaming/Disabled` ) - t.equal(supportabilityMetrics.callCount > 0, true, 'should increment streaming disabled metric') + assert.equal( + supportabilityMetrics.callCount > 0, + true, + 'should increment streaming disabled metric' + ) tx.end() - t.end() }) }) -tap.test('should utilize tokenCountCallback when set', (t) => { - t.plan(5) +test('should utilize tokenCountCallback when set', async (t) => { + const plan = tspl(t, { plan: 5 }) - const { bedrock, client, agent } = t.context + const { bedrock, client, agent } = t.nr const prompt = 'text amazon user token count callback response' const input = requests.amazon(prompt, 'amazon.titan-text-express-v1') agent.config.ai_monitoring.record_content.enabled = false agent.llm.tokenCountCallback = function (model, content) { - t.equal(model, 'amazon.titan-text-express-v1') - t.equal([prompt, '42'].includes(content), true) + plan.equal(model, 'amazon.titan-text-express-v1') + plan.equal([prompt, '42'].includes(content), true) return content?.split(' ')?.length } const command = new bedrock.InvokeModelCommand(input) - helper.runInTransaction(agent, async (tx) => { + await helper.runInTransaction(agent, async (tx) => { await client.send(command) // Chat completion messages should have the correct `token_count` value. const events = agent.customEventAggregator.events.toArray() const completions = events.filter((e) => e[0].type === 'LlmChatCompletionMessage') - t.equal( + plan.equal( completions.some((e) => e[1].token_count === 7), true ) tx.end() - t.end() }) }) diff --git a/test/versioned/aws-sdk-v3/bedrock-embeddings.tap.js b/test/versioned/aws-sdk-v3/bedrock-embeddings.tap.js index 5290b67f4d..830d750aab 100644 --- a/test/versioned/aws-sdk-v3/bedrock-embeddings.tap.js +++ b/test/versioned/aws-sdk-v3/bedrock-embeddings.tap.js @@ -4,14 +4,14 @@ */ 'use strict' - -const tap = require('tap') -require('./common') +const assert = require('node:assert') +const test = require('node:test') const helper = require('../../lib/agent_helper') -require('../../lib/metrics_helper') +const { assertSegments, match } = require('../../lib/custom-assertions') const createAiResponseServer = require('../../lib/aws-server-stubs/ai-server') const { FAKE_CREDENTIALS } = require('../../lib/aws-server-stubs') const { DESTINATIONS } = require('../../../lib/config/attribute-filter') +const { afterEach } = require('./common') const requests = { amazon: (prompt, modelId) => ({ body: JSON.stringify({ inputText: prompt }), @@ -22,81 +22,70 @@ const requests = { modelId }) } +const { tspl } = require('@matteo.collina/tspl') -tap.beforeEach(async (t) => { - t.context.agent = helper.instrumentMockedAgent({ +test.beforeEach(async (ctx) => { + ctx.nr = {} + ctx.nr.agent = helper.instrumentMockedAgent({ ai_monitoring: { enabled: true } }) const bedrock = require('@aws-sdk/client-bedrock-runtime') - t.context.bedrock = bedrock + ctx.nr.bedrock = bedrock const { server, baseUrl, responses, host, port } = await createAiResponseServer() - t.context.server = server - t.context.baseUrl = baseUrl - t.context.responses = responses - t.context.expectedExternalPath = (modelId) => `External/${host}:${port}/model/${modelId}/invoke` + ctx.nr.server = server + ctx.nr.baseUrl = baseUrl + ctx.nr.responses = responses + ctx.nr.expectedExternalPath = (modelId) => `External/${host}:${port}/model/${modelId}/invoke` const client = new bedrock.BedrockRuntimeClient({ region: 'us-east-1', credentials: FAKE_CREDENTIALS, endpoint: baseUrl }) - t.context.client = client + ctx.nr.client = client }) -tap.afterEach(async (t) => { - helper.unloadAgent(t.context.agent) - t.context.server.destroy() - Object.keys(require.cache).forEach((key) => { - if ( - key.includes('@smithy/smithy-client') || - key.includes('@aws-sdk/smithy-client') || - key.includes('@aws-sdk/client-bedrock-runtime') - ) { - delete require.cache[key] - } - }) -}) +test.afterEach(afterEach) ;[ { modelId: 'amazon.titan-embed-text-v1', resKey: 'amazon' }, { modelId: 'cohere.embed-english-v3', resKey: 'cohere' } ].forEach(({ modelId, resKey }) => { - tap.test(`${modelId}: should properly create embedding segment`, (t) => { - const { bedrock, client, responses, agent, expectedExternalPath } = t.context + test(`${modelId}: should properly create embedding segment`, async (t) => { + const { bedrock, client, responses, agent, expectedExternalPath } = t.nr const prompt = `text ${resKey} ultimate question` const input = requests[resKey](prompt, modelId) const command = new bedrock.InvokeModelCommand(input) const expected = responses[resKey].get(prompt) - helper.runInTransaction(agent, async (tx) => { + await helper.runInTransaction(agent, async (tx) => { const response = await client.send(command) const body = JSON.parse(response.body.transformToString('utf8')) - t.equal(response.$metadata.requestId, expected.headers['x-amzn-requestid']) - t.same(body, expected.body) - t.assertSegments( + assert.equal(response.$metadata.requestId, expected.headers['x-amzn-requestid']) + assert.deepEqual(body, expected.body) + assertSegments( tx.trace.root, ['Llm/embedding/Bedrock/InvokeModelCommand', [expectedExternalPath(modelId)]], { exact: false } ) tx.end() - t.end() }) }) - tap.test(`${modelId}: should properly create the LlmEmbedding event`, (t) => { - const { bedrock, client, agent } = t.context + test(`${modelId}: should properly create the LlmEmbedding event`, async (t) => { + const { bedrock, client, agent } = t.nr const prompt = `embed text ${resKey} success` const input = requests[resKey](prompt, modelId) const command = new bedrock.InvokeModelCommand(input) - helper.runInTransaction(agent, async (tx) => { + await helper.runInTransaction(agent, async (tx) => { await client.send(command) const events = agent.customEventAggregator.events.toArray() - t.equal(events.length, 1) + assert.equal(events.length, 1) const embedding = events.filter(([{ type }]) => type === 'LlmEmbedding')[0] const expectedEmbedding = { 'id': /[\w]{8}-[\w]{4}-[\w]{4}-[\w]{4}-[\w]{12}/, @@ -113,16 +102,15 @@ tap.afterEach(async (t) => { 'error': false } - t.equal(embedding[0].type, 'LlmEmbedding') - t.match(embedding[1], expectedEmbedding, 'should match embedding message') + assert.equal(embedding[0].type, 'LlmEmbedding') + match(embedding[1], expectedEmbedding) tx.end() - t.end() }) }) - tap.test(`${modelId}: text answer (streamed)`, async (t) => { - const { bedrock, client, responses } = t.context + test(`${modelId}: text answer (streamed)`, async (t) => { + const { bedrock, client, responses } = t.nr const prompt = `text ${resKey} ultimate question streamed` const input = requests[resKey](prompt, modelId) const command = new bedrock.InvokeModelWithResponseStreamCommand(input) @@ -131,12 +119,12 @@ tap.afterEach(async (t) => { try { await client.send(command) } catch (error) { - t.equal(error.message, expected.body.message) + assert.equal(error.message, expected.body.message) } }) - tap.test(`${modelId}: should properly create errors on embeddings`, (t) => { - const { bedrock, client, agent, expectedExternalPath } = t.context + test(`${modelId}: should properly create errors on embeddings`, async (t) => { + const { bedrock, client, agent, expectedExternalPath } = t.nr const prompt = `embed text ${resKey} error` const input = requests[resKey](prompt, modelId) const command = new bedrock.InvokeModelCommand(input) @@ -144,15 +132,15 @@ tap.afterEach(async (t) => { 'Malformed input request: 2 schema violations found, please reformat your input and try again.' const expectedType = 'ValidationException' - helper.runInTransaction(agent, async (tx) => { + await helper.runInTransaction(agent, async (tx) => { try { await client.send(command) } catch (err) { - t.equal(err.message, expectedMsg) - t.equal(err.name, expectedType) + assert.equal(err.message, expectedMsg) + assert.equal(err.name, expectedType) } - t.equal(tx.exceptions.length, 1) - t.match(tx.exceptions[0], { + assert.equal(tx.exceptions.length, 1) + match(tx.exceptions[0], { error: { name: expectedType, message: expectedMsg @@ -168,13 +156,13 @@ tap.afterEach(async (t) => { } }) - t.assertSegments( + assertSegments( tx.trace.root, ['Llm/embedding/Bedrock/InvokeModelCommand', [expectedExternalPath(modelId)]], { exact: false } ) const events = agent.customEventAggregator.events.toArray() - t.equal(events.length, 1) + assert.equal(events.length, 1) const embedding = events.filter(([{ type }]) => type === 'LlmEmbedding')[0] const expectedEmbedding = { 'id': /[\w]{8}-[\w]{4}-[\w]{4}-[\w]{4}-[\w]{12}/, @@ -191,76 +179,72 @@ tap.afterEach(async (t) => { 'error': true } - t.equal(embedding[0].type, 'LlmEmbedding') - t.match(embedding[1], expectedEmbedding, 'should match embedding message') + assert.equal(embedding[0].type, 'LlmEmbedding') + match(embedding[1], expectedEmbedding) tx.end() - t.end() }) }) - tap.test(`${modelId}: should add llm attribute to transaction`, (t) => { - const { bedrock, client, agent } = t.context + test(`${modelId}: should add llm attribute to transaction`, async (t) => { + const { bedrock, client, agent } = t.nr const prompt = `embed text ${resKey} success` const input = requests[resKey](prompt, modelId) const command = new bedrock.InvokeModelCommand(input) - helper.runInTransaction(agent, async (tx) => { + await helper.runInTransaction(agent, async (tx) => { await client.send(command) const attributes = tx.trace.attributes.get(DESTINATIONS.TRANS_EVENT) - t.equal(attributes.llm, true) + assert.equal(attributes.llm, true) tx.end() - t.end() }) }) - tap.test(`${modelId}: should decorate messages with custom attrs`, (t) => { - const { bedrock, client, agent } = t.context + test(`${modelId}: should decorate messages with custom attrs`, async (t) => { + const { bedrock, client, agent } = t.nr const prompt = `embed text ${resKey} success` const input = requests[resKey](prompt, modelId) const command = new bedrock.InvokeModelCommand(input) - helper.runInTransaction(agent, async (tx) => { + await helper.runInTransaction(agent, async (tx) => { const api = helper.getAgentApi() api.addCustomAttribute('llm.foo', 'bar') await client.send(command) const events = tx.agent.customEventAggregator.events.toArray() const msg = events[0][1] - t.equal(msg['llm.foo'], 'bar') + assert.equal(msg['llm.foo'], 'bar') tx.end() - t.end() }) }) }) -tap.test('should utilize tokenCountCallback when set', (t) => { - t.plan(3) +test('should utilize tokenCountCallback when set', async (t) => { + const plan = tspl(t, { plan: 3 }) - const { bedrock, client, agent } = t.context + const { bedrock, client, agent } = t.nr const prompt = 'embed text amazon token count callback response' const modelId = 'amazon.titan-embed-text-v1' const input = requests.amazon(prompt, modelId) agent.config.ai_monitoring.record_content.enabled = false agent.llm.tokenCountCallback = function (model, content) { - t.equal(model, modelId) - t.equal(content, prompt) + plan.equal(model, modelId) + plan.equal(content, prompt) return content?.split(' ')?.length } const command = new bedrock.InvokeModelCommand(input) - helper.runInTransaction(agent, async (tx) => { + await helper.runInTransaction(agent, async (tx) => { await client.send(command) const events = agent.customEventAggregator.events.toArray() const embeddings = events.filter((e) => e[0].type === 'LlmEmbedding') const msg = embeddings[0][1] - t.equal(msg.token_count, 7) + plan.equal(msg.token_count, 7) tx.end() - t.end() }) }) diff --git a/test/versioned/aws-sdk-v3/bedrock-negative-tests.tap.js b/test/versioned/aws-sdk-v3/bedrock-negative-tests.tap.js index cdf467bd3a..c6c420c28f 100644 --- a/test/versioned/aws-sdk-v3/bedrock-negative-tests.tap.js +++ b/test/versioned/aws-sdk-v3/bedrock-negative-tests.tap.js @@ -4,25 +4,25 @@ */ 'use strict' - -const tap = require('tap') -require('./common') +const assert = require('node:assert') +const test = require('node:test') const helper = require('../../lib/agent_helper') -require('../../lib/metrics_helper') const createAiResponseServer = require('../../lib/aws-server-stubs/ai-server') const { FAKE_CREDENTIALS } = require('../../lib/aws-server-stubs') const sinon = require('sinon') +const { afterEach } = require('./common') -tap.beforeEach(async (t) => { - t.context.agent = helper.instrumentMockedAgent() +test.beforeEach(async (ctx) => { + ctx.nr = {} + ctx.nr.agent = helper.instrumentMockedAgent() const bedrock = require('@aws-sdk/client-bedrock-runtime') - t.context.bedrock = bedrock + ctx.nr.bedrock = bedrock const { server, baseUrl, responses, host, port } = await createAiResponseServer() - t.context.server = server - t.context.baseUrl = baseUrl - t.context.responses = responses - t.context.expectedExternalPath = (modelId) => `External/${host}:${port}/model/${modelId}/invoke` + ctx.nr.server = server + ctx.nr.baseUrl = baseUrl + ctx.nr.responses = responses + ctx.nr.expectedExternalPath = (modelId) => `External/${host}:${port}/model/${modelId}/invoke` const client = new bedrock.BedrockRuntimeClient({ region: 'us-east-1', @@ -30,47 +30,31 @@ tap.beforeEach(async (t) => { endpoint: baseUrl }) sinon.spy(client.middlewareStack, 'add') - t.context.client = client -}) - -tap.afterEach(async (t) => { - helper.unloadAgent(t.context.agent) - t.context.server.destroy() - Object.keys(require.cache).forEach((key) => { - if ( - key.includes('@smithy/smithy-client') || - key.includes('@aws-sdk/smithy-client') || - key.includes('@aws-sdk/client-bedrock-runtime') - ) { - delete require.cache[key] - } - }) + ctx.nr.client = client }) -tap.test( - 'should not register instrumentation middleware when ai_monitoring is not enabled', - (t) => { - const { bedrock, client, responses, agent } = t.context - const resKey = 'amazon' - const modelId = 'amazon.titan-text-express-v1' - agent.config.ai_monitoring.enabled = false - const prompt = `text ${resKey} ultimate question` - const input = { - body: JSON.stringify({ inputText: prompt }), - modelId - } +test.afterEach(afterEach) + +test('should not register instrumentation middleware when ai_monitoring is not enabled', async (t) => { + const { bedrock, client, responses, agent } = t.nr + const resKey = 'amazon' + const modelId = 'amazon.titan-text-express-v1' + agent.config.ai_monitoring.enabled = false + const prompt = `text ${resKey} ultimate question` + const input = { + body: JSON.stringify({ inputText: prompt }), + modelId + } - const command = new bedrock.InvokeModelCommand(input) + const command = new bedrock.InvokeModelCommand(input) - const expected = responses[resKey].get(prompt) - helper.runInTransaction(agent, async (tx) => { - const response = await client.send(command) - t.equal(response.$metadata.requestId, expected.headers['x-amzn-requestid']) - t.equal(client.middlewareStack.add.callCount, 2) - const fns = client.middlewareStack.add.args.map(([mw]) => mw.name) - t.not(fns.includes('bound bedrockMiddleware')) - tx.end() - t.end() - }) - } -) + const expected = responses[resKey].get(prompt) + await helper.runInTransaction(agent, async (tx) => { + const response = await client.send(command) + assert.equal(response.$metadata.requestId, expected.headers['x-amzn-requestid']) + assert.equal(client.middlewareStack.add.callCount, 2) + const fns = client.middlewareStack.add.args.map(([mw]) => mw.name) + assert.ok(!fns.includes('bound bedrockMiddleware')) + tx.end() + }) +}) diff --git a/test/versioned/aws-sdk-v3/client-dynamodb.tap.js b/test/versioned/aws-sdk-v3/client-dynamodb.tap.js index c3f2647616..804a380d64 100644 --- a/test/versioned/aws-sdk-v3/client-dynamodb.tap.js +++ b/test/versioned/aws-sdk-v3/client-dynamodb.tap.js @@ -4,66 +4,58 @@ */ 'use strict' - -const tap = require('tap') +const assert = require('node:assert') +const test = require('node:test') const helper = require('../../lib/agent_helper') const common = require('./common') const { createEmptyResponseServer, FAKE_CREDENTIALS } = require('../../lib/aws-server-stubs') const sinon = require('sinon') +const { match } = require('../../lib/custom-assertions') const AWS_REGION = 'us-east-1' -tap.test('DynamoDB', (t) => { - t.beforeEach(async (t) => { +test('DynamoDB', async (t) => { + t.beforeEach(async (ctx) => { + ctx.nr = {} const server = createEmptyResponseServer() await new Promise((resolve) => { server.listen(0, resolve) }) - t.context.server = server - t.context.agent = helper.instrumentMockedAgent() + ctx.nr.server = server + ctx.nr.agent = helper.instrumentMockedAgent() const Shim = require('../../../lib/shim/datastore-shim') - t.context.setDatastoreSpy = sinon.spy(Shim.prototype, 'setDatastore') + ctx.nr.setDatastoreSpy = sinon.spy(Shim.prototype, 'setDatastore') const lib = require('@aws-sdk/client-dynamodb') - t.context.lib = lib + ctx.nr.lib = lib const DynamoDBClient = lib.DynamoDBClient - t.context.DynamoDBClient = DynamoDBClient - t.context.client = new DynamoDBClient({ + ctx.nr.DynamoDBClient = DynamoDBClient + ctx.nr.client = new DynamoDBClient({ credentials: FAKE_CREDENTIALS, endpoint: `http://localhost:${server.address().port}`, region: AWS_REGION }) const tableName = `delete-aws-sdk-test-table-${Math.floor(Math.random() * 100000)}` - t.context.tableName = tableName - t.context.commands = createCommands({ lib, tableName }) + ctx.nr.tableName = tableName + ctx.nr.commands = createCommands({ lib, tableName }) }) - t.afterEach(async (t) => { - t.context.setDatastoreSpy.restore() - t.context.server.destroy() - helper.unloadAgent(t.context.agent) - Object.keys(require.cache).forEach((key) => { - if ( - key.includes('@aws-sdk/client-dynamodb') || - key.includes('@aws-sdk/smithy-client') || - key.includes('@smithy/smithy-client') - ) { - delete require.cache[key] - } - }) + t.afterEach((ctx) => { + common.afterEach(ctx) + ctx.nr.setDatastoreSpy.restore() }) // See: https://github.com/newrelic/node-newrelic-aws-sdk/issues/160 // I do not care if this fails. the test is to make sure the instrumentation // does not crash - t.test('real endpoint test', async (t) => { + await t.test('real endpoint test', async (t) => { const { DynamoDBClient, lib: { QueryCommand }, tableName - } = t.context + } = t.nr const realClient = new DynamoDBClient({ credentials: FAKE_CREDENTIALS, region: AWS_REGION @@ -74,35 +66,28 @@ tap.test('DynamoDB', (t) => { await realClient.send(cmd) throw new Error('this should fail with IncompleteSignatureException') } catch (err) { - t.equal(err.name, 'IncompleteSignatureException') + assert.equal(err.name, 'IncompleteSignatureException') } }) - t.test('commands, promise-style', (t) => { - const { agent, commands, client } = t.context - helper.runInTransaction(agent, async (tx) => { + await t.test('commands, promise-style', async (t) => { + const { agent, commands, client, setDatastoreSpy } = t.nr + await helper.runInTransaction(agent, async (tx) => { for (const command of commands) { - t.comment(`Testing ${command.constructor.name}`) - try { - await client.send(command) - } catch (err) { - t.error(err) - } + await client.send(command) } tx.end() - finish(t, commands, tx) + finish({ commands, tx, setDatastoreSpy }) }) }) - t.test('commands, callback-style', (t) => { - const { agent, commands, client } = t.context - helper.runInTransaction(agent, async (tx) => { + await t.test('commands, callback-style', async (t) => { + const { agent, commands, client, setDatastoreSpy } = t.nr + await helper.runInTransaction(agent, async (tx) => { for (const command of commands) { - t.comment(`Testing ${command.constructor.name}`) - await new Promise((resolve) => { client.send(command, (err) => { - t.error(err) + assert.ok(!err) return setImmediate(resolve) }) @@ -110,113 +95,107 @@ tap.test('DynamoDB', (t) => { } tx.end() - finish(t, commands, tx) + finish({ commands, tx, setDatastoreSpy }) }) }) - t.end() +}) - function createCommands({ lib, tableName }) { - const { - CreateTableCommand, - PutItemCommand, - GetItemCommand, - UpdateItemCommand, - ScanCommand, - QueryCommand, - DeleteItemCommand, - BatchWriteItemCommand, - BatchGetItemCommand, - BatchExecuteStatementCommand, - UpdateTableCommand, - DeleteTableCommand - } = lib - const ddbUniqueArtist = `DELETE_One You Know ${Math.floor(Math.random() * 100000)}` - const createTblParams = getCreateTableParams(tableName) - const putItemParams = getPutItemParams(tableName, ddbUniqueArtist) - const itemParams = getItemParams(tableName, ddbUniqueArtist) - const queryParams = getQueryParams(tableName, ddbUniqueArtist) - const batchWriteItemCommandParams = getBatchWriteItemCommandParams(tableName, ddbUniqueArtist) - const batchGetItemCommandParams = getBatchGetItemCommandParams(tableName, ddbUniqueArtist) - const batchExecuteStatementCommandParams = getBatchExecuteStatementCommandParams( - tableName, - ddbUniqueArtist - ) - const updateTableCommandParams = getUpdateTableCommandParams(tableName) - const deleteTableParams = getDeleteTableParams(tableName) - const createTableCommand = new CreateTableCommand(createTblParams) - const putItemCommand = new PutItemCommand(putItemParams) - const getItemCommand = new GetItemCommand(itemParams) - const updateItemCommand = new UpdateItemCommand(itemParams) - const scanCommand = new ScanCommand({ TableName: tableName }) - const queryCommand = new QueryCommand(queryParams) - const deleteItemCommand = new DeleteItemCommand(itemParams) - const batchWriteItemCommand = new BatchWriteItemCommand(batchWriteItemCommandParams) - const batchGetItemCommand = new BatchGetItemCommand(batchGetItemCommandParams) - const batchExecuteStatementCommand = new BatchExecuteStatementCommand( - batchExecuteStatementCommandParams - ) - const updateTableCommand = new UpdateTableCommand(updateTableCommandParams) - const deleteTableCommand = new DeleteTableCommand(deleteTableParams) - return [ - createTableCommand, - putItemCommand, - getItemCommand, - updateItemCommand, - scanCommand, - queryCommand, - deleteItemCommand, - batchWriteItemCommand, - batchGetItemCommand, - batchExecuteStatementCommand, - updateTableCommand, - deleteTableCommand - ] - } +function createCommands({ lib, tableName }) { + const { + CreateTableCommand, + PutItemCommand, + GetItemCommand, + UpdateItemCommand, + ScanCommand, + QueryCommand, + DeleteItemCommand, + BatchWriteItemCommand, + BatchGetItemCommand, + BatchExecuteStatementCommand, + UpdateTableCommand, + DeleteTableCommand + } = lib + const ddbUniqueArtist = `DELETE_One You Know ${Math.floor(Math.random() * 100000)}` + const createTblParams = getCreateTableParams(tableName) + const putItemParams = getPutItemParams(tableName, ddbUniqueArtist) + const itemParams = getItemParams(tableName, ddbUniqueArtist) + const queryParams = getQueryParams(tableName, ddbUniqueArtist) + const batchWriteItemCommandParams = getBatchWriteItemCommandParams(tableName, ddbUniqueArtist) + const batchGetItemCommandParams = getBatchGetItemCommandParams(tableName, ddbUniqueArtist) + const batchExecuteStatementCommandParams = getBatchExecuteStatementCommandParams( + tableName, + ddbUniqueArtist + ) + const updateTableCommandParams = getUpdateTableCommandParams(tableName) + const deleteTableParams = getDeleteTableParams(tableName) + const createTableCommand = new CreateTableCommand(createTblParams) + const putItemCommand = new PutItemCommand(putItemParams) + const getItemCommand = new GetItemCommand(itemParams) + const updateItemCommand = new UpdateItemCommand(itemParams) + const scanCommand = new ScanCommand({ TableName: tableName }) + const queryCommand = new QueryCommand(queryParams) + const deleteItemCommand = new DeleteItemCommand(itemParams) + const batchWriteItemCommand = new BatchWriteItemCommand(batchWriteItemCommandParams) + const batchGetItemCommand = new BatchGetItemCommand(batchGetItemCommandParams) + const batchExecuteStatementCommand = new BatchExecuteStatementCommand( + batchExecuteStatementCommandParams + ) + const updateTableCommand = new UpdateTableCommand(updateTableCommandParams) + const deleteTableCommand = new DeleteTableCommand(deleteTableParams) + return [ + createTableCommand, + putItemCommand, + getItemCommand, + updateItemCommand, + scanCommand, + queryCommand, + deleteItemCommand, + batchWriteItemCommand, + batchGetItemCommand, + batchExecuteStatementCommand, + updateTableCommand, + deleteTableCommand + ] +} - function finish(t, cmds, tx) { - const root = tx.trace.root - const segments = common.checkAWSAttributes(t, root, common.DATASTORE_PATTERN) +function finish({ commands, tx, setDatastoreSpy }) { + const root = tx.trace.root + const segments = common.checkAWSAttributes(root, common.DATASTORE_PATTERN) - t.equal(segments.length, cmds.length, `should have ${cmds.length} AWS datastore segments`) + assert.equal( + segments.length, + commands.length, + `should have ${commands.length} AWS datastore segments` + ) - const externalSegments = common.checkAWSAttributes(t, root, common.EXTERN_PATTERN) - t.equal(externalSegments.length, 0, 'should not have any External segments') + const externalSegments = common.checkAWSAttributes(root, common.EXTERN_PATTERN) + assert.equal(externalSegments.length, 0, 'should not have any External segments') - segments.forEach((segment, i) => { - const command = cmds[i] - t.ok(command) - t.equal( - segment.name, - `Datastore/operation/DynamoDB/${command.constructor.name}`, - 'should have operation in segment name' - ) - const attrs = segment.attributes.get(common.SEGMENT_DESTINATION) - attrs.port_path_or_id = parseInt(attrs.port_path_or_id, 10) + segments.forEach((segment, i) => { + const command = commands[i] + assert.ok(command) + assert.equal( + segment.name, + `Datastore/operation/DynamoDB/${command.constructor.name}`, + 'should have operation in segment name' + ) + const attrs = segment.attributes.get(common.SEGMENT_DESTINATION) + attrs.port_path_or_id = parseInt(attrs.port_path_or_id, 10) - t.match( - attrs, - { - 'host': String, - 'port_path_or_id': Number, - 'product': 'DynamoDB', - 'collection': String, - 'aws.operation': command.constructor.name, - 'aws.requestId': String, - 'aws.region': 'us-east-1', - 'aws.service': /dynamodb|DynamoDB/ - }, - 'should have expected attributes' - ) + match(attrs, { + 'host': String, + 'port_path_or_id': Number, + 'product': 'DynamoDB', + 'collection': String, + 'aws.operation': command.constructor.name, + 'aws.requestId': String, + 'aws.region': 'us-east-1', + 'aws.service': /dynamodb|DynamoDB/ }) + }) - t.equal( - t.context.setDatastoreSpy.callCount, - 1, - 'should only call setDatastore once and not per call' - ) - t.end() - } -}) + assert.equal(setDatastoreSpy.callCount, 1, 'should only call setDatastore once and not per call') +} function getCreateTableParams(tableName) { return { diff --git a/test/versioned/aws-sdk-v3/common.js b/test/versioned/aws-sdk-v3/common.js index 033b1b9932..0a58c1a816 100644 --- a/test/versioned/aws-sdk-v3/common.js +++ b/test/versioned/aws-sdk-v3/common.js @@ -12,16 +12,12 @@ const SQS_PATTERN = /^MessageBroker\/SQS\/Queue/ const { DESTINATIONS: { TRANS_SEGMENT } } = require('../../../lib/config/attribute-filter') -const tap = require('tap') +const { match } = require('../../lib/custom-assertions') +const assert = require('node:assert') const SEGMENT_DESTINATION = TRANS_SEGMENT +const helper = require('../../lib/agent_helper') -tap.Test.prototype.addAssert('checkExternals', 1, checkExternals) -tap.Test.prototype.addAssert('llmMessages', 1, assertChatCompletionMessages) -tap.Test.prototype.addAssert('llmSummary', 1, assertChatCompletionSummary) - -// TODO: migrate to tap assertion, issue is variable number of args -// which doesn't seem to play nice with addAssert in tap -function checkAWSAttributes(t, segment, pattern, markedSegments = []) { +function checkAWSAttributes(segment, pattern, markedSegments = []) { const expectedAttrs = { 'aws.operation': String, 'aws.service': String, @@ -32,46 +28,46 @@ function checkAWSAttributes(t, segment, pattern, markedSegments = []) { if (pattern.test(segment.name)) { markedSegments.push(segment) const attrs = segment.attributes.get(TRANS_SEGMENT) - t.match(attrs, expectedAttrs, 'should have aws attributes') + match(attrs, expectedAttrs) } segment.children.forEach((child) => { - checkAWSAttributes(t, child, pattern, markedSegments) + checkAWSAttributes(child, pattern, markedSegments) }) return markedSegments } -function getMatchingSegments(t, segment, pattern, markedSegments = []) { +function getMatchingSegments(segment, pattern, markedSegments = []) { if (pattern.test(segment.name)) { markedSegments.push(segment) } segment.children.forEach((child) => { - getMatchingSegments(t, child, pattern, markedSegments) + getMatchingSegments(child, pattern, markedSegments) }) return markedSegments } -function checkExternals({ service, operations, tx }) { - const externals = checkAWSAttributes(this, tx.trace.root, EXTERN_PATTERN) - this.equal(externals.length, operations.length, `should have ${operations.length} aws externals`) +function checkExternals({ service, operations, tx, end }) { + const externals = checkAWSAttributes(tx.trace.root, EXTERN_PATTERN) + assert.equal( + externals.length, + operations.length, + `should have ${operations.length} aws externals` + ) operations.forEach((operation, index) => { const attrs = externals[index].attributes.get(TRANS_SEGMENT) - this.match( - attrs, - { - 'aws.operation': operation, - 'aws.requestId': String, - // in 3.1.0 they fixed service names from lower case - // see: https://github.com/aws/aws-sdk-js-v3/commit/0011af27a62d0d201296225e2a70276645b3231a - 'aws.service': new RegExp(`${service}|${service.toLowerCase().replace(/ /g, '')}`), - 'aws.region': 'us-east-1' - }, - 'should have expected attributes' - ) + match(attrs, { + 'aws.operation': operation, + 'aws.requestId': String, + // in 3.1.0 they fixed service names from lower case + // see: https://github.com/aws/aws-sdk-js-v3/commit/0011af27a62d0d201296225e2a70276645b3231a + 'aws.service': new RegExp(`${service}|${service.toLowerCase().replace(/ /g, '')}`), + 'aws.region': 'us-east-1' + }) }) - this.end() + end() } function assertChatCompletionMessages({ tx, chatMsgs, expectedId, modelId, prompt, resContent }) { @@ -109,8 +105,8 @@ function assertChatCompletionMessages({ tx, chatMsgs, expectedId, modelId, promp expectedChatMsg.is_response = true } - this.equal(msg[0].type, 'LlmChatCompletionMessage') - this.match(msg[1], expectedChatMsg, 'should match chat completion message') + assert.equal(msg[0].type, 'LlmChatCompletionMessage') + match(msg[1], expectedChatMsg) }) } @@ -134,11 +130,30 @@ function assertChatCompletionSummary({ tx, modelId, chatSummary, error = false, 'error': error } - this.equal(chatSummary[0].type, 'LlmChatCompletionSummary') - this.match(chatSummary[1], expectedChatSummary, 'should match chat summary message') + assert.equal(chatSummary[0].type, 'LlmChatCompletionSummary') + match(chatSummary[1], expectedChatSummary) +} + +/** + * Common afterEach hook that unloads agent, stops server, and deletes + * packages in require cache + * + * @param {object} ctx test context + */ +function afterEach(ctx) { + ctx.nr.server.destroy() + helper.unloadAgent(ctx.nr.agent) + Object.keys(require.cache).forEach((key) => { + if (key.includes('@aws-sdk') || key.includes('@smithy')) { + delete require.cache[key] + } + }) } module.exports = { + afterEach, + assertChatCompletionSummary, + assertChatCompletionMessages, DATASTORE_PATTERN, EXTERN_PATTERN, SNS_PATTERN, diff --git a/test/versioned/aws-sdk-v3/elasticache.tap.js b/test/versioned/aws-sdk-v3/elasticache.tap.js index 2daf0cd3d3..0eadba7782 100644 --- a/test/versioned/aws-sdk-v3/elasticache.tap.js +++ b/test/versioned/aws-sdk-v3/elasticache.tap.js @@ -4,37 +4,34 @@ */ 'use strict' - -const tap = require('tap') +const test = require('node:test') const helper = require('../../lib/agent_helper') -require('./common') +const { afterEach, checkExternals } = require('./common') const { createResponseServer, FAKE_CREDENTIALS } = require('../../lib/aws-server-stubs') -tap.test('ElastiCacheClient', (t) => { - t.beforeEach(async (t) => { +test('ElastiCacheClient', async (t) => { + t.beforeEach(async (ctx) => { + ctx.nr = {} const server = createResponseServer() await new Promise((resolve) => { server.listen(0, resolve) }) - t.context.server = server - t.context.agent = helper.instrumentMockedAgent() + ctx.nr.server = server + ctx.nr.agent = helper.instrumentMockedAgent() const { ElastiCacheClient, ...lib } = require('@aws-sdk/client-elasticache') - t.context.AddTagsToResourceCommand = lib.AddTagsToResourceCommand + ctx.nr.AddTagsToResourceCommand = lib.AddTagsToResourceCommand const endpoint = `http://localhost:${server.address().port}` - t.context.service = new ElastiCacheClient({ + ctx.nr.service = new ElastiCacheClient({ credentials: FAKE_CREDENTIALS, endpoint, region: 'us-east-1' }) }) - t.afterEach((t) => { - t.context.server.destroy() - helper.unloadAgent(t.context.agent) - }) + t.afterEach(afterEach) - t.test('AddTagsToResourceCommand', (t) => { - const { agent, service, AddTagsToResourceCommand } = t.context + await t.test('AddTagsToResourceCommand', (t, end) => { + const { agent, service, AddTagsToResourceCommand } = t.nr helper.runInTransaction(agent, async (tx) => { const cmd = new AddTagsToResourceCommand({ ResourceName: 'STRING_VALUE' /* required */, @@ -48,12 +45,12 @@ tap.test('ElastiCacheClient', (t) => { }) await service.send(cmd) tx.end() - setImmediate(t.checkExternals, { + setImmediate(checkExternals, { service: 'ElastiCache', operations: ['AddTagsToResourceCommand'], - tx + tx, + end }) }) }) - t.end() }) diff --git a/test/versioned/aws-sdk-v3/elb.tap.js b/test/versioned/aws-sdk-v3/elb.tap.js index fb51dfde5b..c299550c3c 100644 --- a/test/versioned/aws-sdk-v3/elb.tap.js +++ b/test/versioned/aws-sdk-v3/elb.tap.js @@ -5,36 +5,34 @@ 'use strict' -const tap = require('tap') +const test = require('node:test') const helper = require('../../lib/agent_helper') -require('./common') +const { afterEach, checkExternals } = require('./common') const { createEmptyResponseServer, FAKE_CREDENTIALS } = require('../../lib/aws-server-stubs') -tap.test('ElasticLoadBalancingClient', (t) => { - t.beforeEach(async (t) => { +test('ElasticLoadBalancingClient', async (t) => { + t.beforeEach(async (ctx) => { + ctx.nr = {} const server = createEmptyResponseServer() await new Promise((resolve) => { server.listen(0, resolve) }) - t.context.server = server - t.context.agent = helper.instrumentMockedAgent() + ctx.nr.server = server + ctx.nr.agent = helper.instrumentMockedAgent() const { ElasticLoadBalancingClient, ...lib } = require('@aws-sdk/client-elastic-load-balancing') - t.context.AddTagsCommand = lib.AddTagsCommand + ctx.nr.AddTagsCommand = lib.AddTagsCommand const endpoint = `http://localhost:${server.address().port}` - t.context.service = new ElasticLoadBalancingClient({ + ctx.nr.service = new ElasticLoadBalancingClient({ credentials: FAKE_CREDENTIALS, endpoint, region: 'us-east-1' }) }) - t.afterEach((t) => { - t.context.server.destroy() - helper.unloadAgent(t.context.agent) - }) + t.afterEach(afterEach) - t.test('AddTagsCommand', (t) => { - const { agent, service, AddTagsCommand } = t.context + await t.test('AddTagsCommand', (t, end) => { + const { agent, service, AddTagsCommand } = t.nr helper.runInTransaction(agent, async (tx) => { const cmd = new AddTagsCommand({ LoadBalancerNames: ['my-load-balancer'], @@ -51,12 +49,12 @@ tap.test('ElasticLoadBalancingClient', (t) => { }) await service.send(cmd) tx.end() - setImmediate(t.checkExternals, { + setImmediate(checkExternals, { service: 'Elastic Load Balancing', operations: ['AddTagsCommand'], - tx + tx, + end }) }) }) - t.end() }) diff --git a/test/versioned/aws-sdk-v3/lambda.tap.js b/test/versioned/aws-sdk-v3/lambda.tap.js index ffb1a8d111..e52f61c65a 100644 --- a/test/versioned/aws-sdk-v3/lambda.tap.js +++ b/test/versioned/aws-sdk-v3/lambda.tap.js @@ -5,36 +5,34 @@ 'use strict' -const tap = require('tap') +const test = require('node:test') const helper = require('../../lib/agent_helper') -require('./common') +const { afterEach, checkExternals } = require('./common') const { createEmptyResponseServer, FAKE_CREDENTIALS } = require('../../lib/aws-server-stubs') -tap.test('LambdaClient', (t) => { - t.beforeEach(async (t) => { +test('LambdaClient', async (t) => { + t.beforeEach(async (ctx) => { + ctx.nr = {} const server = createEmptyResponseServer() await new Promise((resolve) => { server.listen(0, resolve) }) - t.context.server = server - t.context.agent = helper.instrumentMockedAgent() + ctx.nr.server = server + ctx.nr.agent = helper.instrumentMockedAgent() const { LambdaClient, ...lib } = require('@aws-sdk/client-lambda') - t.context.AddLayerVersionPermissionCommand = lib.AddLayerVersionPermissionCommand + ctx.nr.AddLayerVersionPermissionCommand = lib.AddLayerVersionPermissionCommand const endpoint = `http://localhost:${server.address().port}` - t.context.service = new LambdaClient({ + ctx.nr.service = new LambdaClient({ credentials: FAKE_CREDENTIALS, endpoint, region: 'us-east-1' }) }) - t.afterEach((t) => { - t.context.server.destroy() - helper.unloadAgent(t.context.agent) - }) + t.afterEach(afterEach) - t.test('AddLayerVersionPermissionCommand', (t) => { - const { service, agent, AddLayerVersionPermissionCommand } = t.context + await t.test('AddLayerVersionPermissionCommand', (t, end) => { + const { service, agent, AddLayerVersionPermissionCommand } = t.nr helper.runInTransaction(agent, async (tx) => { const cmd = new AddLayerVersionPermissionCommand({ Action: 'lambda:GetLayerVersion' /* required */, @@ -47,12 +45,12 @@ tap.test('LambdaClient', (t) => { }) await service.send(cmd) tx.end() - setImmediate(t.checkExternals, { + setImmediate(checkExternals, { service: 'Lambda', operations: ['AddLayerVersionPermissionCommand'], - tx + tx, + end }) }) }) - t.end() }) diff --git a/test/versioned/aws-sdk-v3/lib-dynamodb.tap.js b/test/versioned/aws-sdk-v3/lib-dynamodb.tap.js index 67b16a88a6..71ce035056 100644 --- a/test/versioned/aws-sdk-v3/lib-dynamodb.tap.js +++ b/test/versioned/aws-sdk-v3/lib-dynamodb.tap.js @@ -4,27 +4,29 @@ */ 'use strict' - -const tap = require('tap') +const assert = require('node:assert') +const test = require('node:test') const helper = require('../../lib/agent_helper') const common = require('./common') const { createEmptyResponseServer, FAKE_CREDENTIALS } = require('../../lib/aws-server-stubs') +const { match } = require('../../lib/custom-assertions') -tap.test('DynamoDB', (t) => { - t.beforeEach(async (t) => { +test('DynamoDB', async (t) => { + t.beforeEach(async (ctx) => { + ctx.nr = {} const server = createEmptyResponseServer() await new Promise((resolve) => { server.listen(0, resolve) }) - t.context.server = server - t.context.agent = helper.instrumentMockedAgent() + ctx.nr.server = server + ctx.nr.agent = helper.instrumentMockedAgent() const lib = require('@aws-sdk/lib-dynamodb') - t.context.DynamoDBDocument = lib.DynamoDBDocument - t.context.DynamoDBDocumentClient = lib.DynamoDBDocumentClient + ctx.nr.DynamoDBDocument = lib.DynamoDBDocument + ctx.nr.DynamoDBDocumentClient = lib.DynamoDBDocumentClient const { DynamoDBClient } = require('@aws-sdk/client-dynamodb') - t.context.ddbCommands = { + ctx.nr.ddbCommands = { PutCommand: lib.PutCommand, GetCommand: lib.GetCommand, UpdateCommand: lib.UpdateCommand, @@ -34,63 +36,41 @@ tap.test('DynamoDB', (t) => { } const endpoint = `http://localhost:${server.address().port}` - t.context.client = new DynamoDBClient({ + ctx.nr.client = new DynamoDBClient({ credentials: FAKE_CREDENTIALS, endpoint, region: 'us-east-1' }) const tableName = `delete-aws-sdk-test-table-${Math.floor(Math.random() * 100000)}` - t.context.tests = createTests(tableName) + ctx.nr.tests = createTests(tableName) }) - t.afterEach((t) => { - t.context.server.destroy() - helper.unloadAgent(t.context.agent) - Object.keys(require.cache).forEach((key) => { - if ( - key.includes('@aws-sdk/lib-dynamodb') || - key.includes('@aws-sdk/client-dynamodb') || - key.includes('@aws-sdk/smithy-client') || - key.includes('@smithy/smithy-client') - ) { - delete require.cache[key] - } - }) - }) + t.afterEach(common.afterEach) - t.test('client commands', (t) => { - const { DynamoDBDocumentClient, ddbCommands, client, agent, tests } = t.context + await t.test('client commands', (t, end) => { + const { DynamoDBDocumentClient, ddbCommands, client, agent, tests } = t.nr const docClient = new DynamoDBDocumentClient(client) helper.runInTransaction(agent, async function (tx) { - for (let i = 0; i < tests.length; i++) { - const cfg = tests[i] - t.comment(`Testing ${cfg.operation}`) - - try { - await docClient.send(new ddbCommands[cfg.command](cfg.params)) - } catch (err) { - t.error(err) - } + for (const test of tests) { + await docClient.send(new ddbCommands[test.command](test.params)) } tx.end() - const args = [t, tests, tx] + const args = [end, tests, tx] setImmediate(finish, ...args) }) }) - t.test('client commands via callback', (t) => { - const { DynamoDBDocumentClient, ddbCommands, client, agent, tests } = t.context + await t.test('client commands via callback', (t, end) => { + const { DynamoDBDocumentClient, ddbCommands, client, agent, tests } = t.nr const docClient = new DynamoDBDocumentClient(client) helper.runInTransaction(agent, async function (tx) { for (const test of tests) { - t.comment(`Testing ${test.operation}`) - await new Promise((resolve) => { docClient.send(new ddbCommands[test.command](test.params), (err) => { - t.error(err) + assert.ok(!err) return setImmediate(resolve) }) @@ -99,117 +79,86 @@ tap.test('DynamoDB', (t) => { tx.end() - const args = [t, tests, tx] + const args = [end, tests, tx] setImmediate(finish, ...args) }) }) - t.test('client from commands', (t) => { - const { DynamoDBDocumentClient, ddbCommands, client, agent, tests } = t.context + await t.test('client from commands', (t, end) => { + const { DynamoDBDocumentClient, ddbCommands, client, agent, tests } = t.nr const docClientFrom = DynamoDBDocumentClient.from(client) helper.runInTransaction(agent, async function (tx) { - for (let i = 0; i < tests.length; i++) { - const cfg = tests[i] - t.comment(`Testing ${cfg.operation}`) - - try { - await docClientFrom.send(new ddbCommands[cfg.command](cfg.params)) - } catch (err) { - t.error(err) - } + for (const test of tests) { + await docClientFrom.send(new ddbCommands[test.command](test.params)) } tx.end() - const args = [t, tests, tx] + const args = [end, tests, tx] setImmediate(finish, ...args) }) }) - t.test('calling send on client and doc client', (t) => { - const { DynamoDBDocumentClient, ddbCommands, client, agent, tests } = t.context + await t.test('calling send on client and doc client', async (t) => { + const { DynamoDBDocumentClient, ddbCommands, client, agent, tests } = t.nr const docClientFrom = DynamoDBDocumentClient.from(client) - let errorOccurred = false - helper.runInTransaction(agent, async function (tx) { - for (let i = 0; i < tests.length; i++) { - const cfg = tests[i] - t.comment(`Testing ${cfg.operation}`) - - try { - await docClientFrom.send(new ddbCommands[cfg.command](cfg.params)) - await client.send(new ddbCommands[cfg.command](cfg.params)) - } catch (err) { - errorOccurred = true - t.error(err) - } + await helper.runInTransaction(agent, async function (tx) { + for (const test of tests) { + await docClientFrom.send(new ddbCommands[test.command](test.params)) + await client.send(new ddbCommands[test.command](test.params)) } - t.notOk(errorOccurred, 'should not have a middleware error with two clients') - tx.end() - t.end() }) }) - t.test('DynamoDBDocument client from commands', (t) => { - const { DynamoDBDocument, ddbCommands, client, agent, tests } = t.context + await t.test('DynamoDBDocument client from commands', (t, end) => { + const { DynamoDBDocument, ddbCommands, client, agent, tests } = t.nr const docClientFrom = DynamoDBDocument.from(client) helper.runInTransaction(agent, async function (tx) { - for (let i = 0; i < tests.length; i++) { - const cfg = tests[i] - t.comment(`Testing ${cfg.operation}`) - - try { - await docClientFrom.send(new ddbCommands[cfg.command](cfg.params)) - } catch (err) { - t.error(err) - } + for (const test of tests) { + await docClientFrom.send(new ddbCommands[test.command](test.params)) } tx.end() - const args = [t, tests, tx] + const args = [end, tests, tx] setImmediate(finish, ...args) }) }) - t.end() }) -function finish(t, tests, tx) { +function finish(end, tests, tx) { const root = tx.trace.root - const segments = common.checkAWSAttributes(t, root, common.DATASTORE_PATTERN) + const segments = common.checkAWSAttributes(root, common.DATASTORE_PATTERN) - t.equal(segments.length, tests.length, `should have ${tests.length} aws datastore segments`) + assert.equal(segments.length, tests.length, `should have ${tests.length} aws datastore segments`) - const externalSegments = common.checkAWSAttributes(t, root, common.EXTERN_PATTERN) - t.equal(externalSegments.length, 0, 'should not have any External segments') + const externalSegments = common.checkAWSAttributes(root, common.EXTERN_PATTERN) + assert.equal(externalSegments.length, 0, 'should not have any External segments') segments.forEach((segment, i) => { const operation = tests[i].operation - t.equal( + assert.equal( segment.name, `Datastore/operation/DynamoDB/${operation}`, 'should have operation in segment name' ) const attrs = segment.attributes.get(common.SEGMENT_DESTINATION) attrs.port_path_or_id = parseInt(attrs.port_path_or_id, 10) - t.match( - attrs, - { - 'host': String, - 'port_path_or_id': Number, - 'product': 'DynamoDB', - 'collection': String, - 'aws.operation': operation, - 'aws.requestId': String, - 'aws.region': 'us-east-1', - 'aws.service': 'DynamoDB' - }, - 'should have expected attributes' - ) + match(attrs, { + 'host': String, + 'port_path_or_id': Number, + 'product': 'DynamoDB', + 'collection': String, + 'aws.operation': operation, + 'aws.requestId': String, + 'aws.region': 'us-east-1', + 'aws.service': 'DynamoDB' + }) }) - t.end() + end() } function createTests(tableName) { diff --git a/test/versioned/aws-sdk-v3/rds.tap.js b/test/versioned/aws-sdk-v3/rds.tap.js index c314861611..b915588e60 100644 --- a/test/versioned/aws-sdk-v3/rds.tap.js +++ b/test/versioned/aws-sdk-v3/rds.tap.js @@ -5,36 +5,34 @@ 'use strict' -const tap = require('tap') +const test = require('node:test') const helper = require('../../lib/agent_helper') -require('./common') +const { afterEach, checkExternals } = require('./common') const { createEmptyResponseServer, FAKE_CREDENTIALS } = require('../../lib/aws-server-stubs') -tap.test('RDSClient', (t) => { - t.beforeEach(async (t) => { +test('RDSClient', async (t) => { + t.beforeEach(async (ctx) => { + ctx.nr = {} const server = createEmptyResponseServer() await new Promise((resolve) => { server.listen(0, resolve) }) - t.context.server = server - t.context.agent = helper.instrumentMockedAgent() + ctx.nr.server = server + ctx.nr.agent = helper.instrumentMockedAgent() const { RDSClient, ...lib } = require('@aws-sdk/client-rds') - t.context.AddRoleToDBClusterCommand = lib.AddRoleToDBClusterCommand + ctx.nr.AddRoleToDBClusterCommand = lib.AddRoleToDBClusterCommand const endpoint = `http://localhost:${server.address().port}` - t.context.service = new RDSClient({ + ctx.nr.service = new RDSClient({ credentials: FAKE_CREDENTIALS, endpoint, region: 'us-east-1' }) }) - t.afterEach((t) => { - t.context.server.destroy() - helper.unloadAgent(t.context.agent) - }) + t.afterEach(afterEach) - t.test('AddRoleToDBClusterCommand', (t) => { - const { service, agent, AddRoleToDBClusterCommand } = t.context + await t.test('AddRoleToDBClusterCommand', (t, end) => { + const { service, agent, AddRoleToDBClusterCommand } = t.nr helper.runInTransaction(agent, async (tx) => { const cmd = new AddRoleToDBClusterCommand({ Action: 'lambda:GetLayerVersion' /* required */, @@ -47,12 +45,12 @@ tap.test('RDSClient', (t) => { }) await service.send(cmd) tx.end() - setImmediate(t.checkExternals, { + setImmediate(checkExternals, { service: 'RDS', operations: ['AddRoleToDBClusterCommand'], - tx + tx, + end }) }) }) - t.end() }) diff --git a/test/versioned/aws-sdk-v3/redshift.tap.js b/test/versioned/aws-sdk-v3/redshift.tap.js index 7c7436ba49..bf7e88d136 100644 --- a/test/versioned/aws-sdk-v3/redshift.tap.js +++ b/test/versioned/aws-sdk-v3/redshift.tap.js @@ -5,36 +5,34 @@ 'use strict' -const tap = require('tap') +const test = require('node:test') const helper = require('../../lib/agent_helper') -require('./common') +const { afterEach, checkExternals } = require('./common') const { createResponseServer, FAKE_CREDENTIALS } = require('../../lib/aws-server-stubs') -tap.test('RedshiftClient', (t) => { - t.beforeEach(async (t) => { +test('RedshiftClient', async (t) => { + t.beforeEach(async (ctx) => { + ctx.nr = {} const server = createResponseServer() await new Promise((resolve) => { server.listen(0, resolve) }) - t.context.server = server - t.context.agent = helper.instrumentMockedAgent() + ctx.nr.server = server + ctx.nr.agent = helper.instrumentMockedAgent() const { RedshiftClient, ...lib } = require('@aws-sdk/client-redshift') - t.context.AcceptReservedNodeExchangeCommand = lib.AcceptReservedNodeExchangeCommand + ctx.nr.AcceptReservedNodeExchangeCommand = lib.AcceptReservedNodeExchangeCommand const endpoint = `http://localhost:${server.address().port}` - t.context.service = new RedshiftClient({ + ctx.nr.service = new RedshiftClient({ credentials: FAKE_CREDENTIALS, endpoint, region: 'us-east-1' }) }) - t.afterEach((t) => { - t.context.server.destroy() - helper.unloadAgent(t.context.agent) - }) + t.afterEach(afterEach) - t.test('AcceptReservedNodeExchangeCommand', (t) => { - const { agent, service, AcceptReservedNodeExchangeCommand } = t.context + await t.test('AcceptReservedNodeExchangeCommand', (t, end) => { + const { agent, service, AcceptReservedNodeExchangeCommand } = t.nr helper.runInTransaction(agent, async (tx) => { const cmd = new AcceptReservedNodeExchangeCommand({ ReservedNodeId: 'STRING_VALUE' /* required */, @@ -42,12 +40,12 @@ tap.test('RedshiftClient', (t) => { }) await service.send(cmd) tx.end() - setImmediate(t.checkExternals, { + setImmediate(checkExternals, { service: 'Redshift', operations: ['AcceptReservedNodeExchangeCommand'], - tx + tx, + end }) }) }) - t.end() }) diff --git a/test/versioned/aws-sdk-v3/rekognition.tap.js b/test/versioned/aws-sdk-v3/rekognition.tap.js index bc5d1f4d2c..183550f028 100644 --- a/test/versioned/aws-sdk-v3/rekognition.tap.js +++ b/test/versioned/aws-sdk-v3/rekognition.tap.js @@ -5,36 +5,34 @@ 'use strict' -const tap = require('tap') +const test = require('node:test') const helper = require('../../lib/agent_helper') -require('./common') +const { afterEach, checkExternals } = require('./common') const { createEmptyResponseServer, FAKE_CREDENTIALS } = require('../../lib/aws-server-stubs') -tap.test('RekognitionClient', (t) => { - t.beforeEach(async (t) => { +test('RekognitionClient', async (t) => { + t.beforeEach(async (ctx) => { + ctx.nr = {} const server = createEmptyResponseServer() await new Promise((resolve) => { server.listen(0, resolve) }) - t.context.server = server - t.context.agent = helper.instrumentMockedAgent() + ctx.nr.server = server + ctx.nr.agent = helper.instrumentMockedAgent() const { RekognitionClient, ...lib } = require('@aws-sdk/client-rekognition') - t.context.CompareFacesCommand = lib.CompareFacesCommand + ctx.nr.CompareFacesCommand = lib.CompareFacesCommand const endpoint = `http://localhost:${server.address().port}` - t.context.service = new RekognitionClient({ + ctx.nr.service = new RekognitionClient({ credentials: FAKE_CREDENTIALS, endpoint, region: 'us-east-1' }) }) - t.afterEach((t) => { - t.context.server.destroy() - helper.unloadAgent(t.context.agent) - }) + t.afterEach(afterEach) - t.test('CompareFacesCommand', (t) => { - const { service, agent, CompareFacesCommand } = t.context + await t.test('CompareFacesCommand', (t, end) => { + const { service, agent, CompareFacesCommand } = t.nr helper.runInTransaction(agent, async (tx) => { const cmd = new CompareFacesCommand({ SimilarityThreshold: 90, @@ -53,12 +51,12 @@ tap.test('RekognitionClient', (t) => { }) await service.send(cmd) tx.end() - setImmediate(t.checkExternals, { + setImmediate(checkExternals, { service: 'Rekognition', operations: ['CompareFacesCommand'], - tx + tx, + end }) }) }) - t.end() }) diff --git a/test/versioned/aws-sdk-v3/s3.tap.js b/test/versioned/aws-sdk-v3/s3.tap.js index c525bca797..c3895d37e6 100644 --- a/test/versioned/aws-sdk-v3/s3.tap.js +++ b/test/versioned/aws-sdk-v3/s3.tap.js @@ -5,23 +5,24 @@ 'use strict' -const tap = require('tap') +const test = require('node:test') const helper = require('../../lib/agent_helper') -require('./common') +const { afterEach, checkExternals } = require('./common') const { createEmptyResponseServer, FAKE_CREDENTIALS } = require('../../lib/aws-server-stubs') -tap.test('S3 buckets', (t) => { - t.beforeEach(async (t) => { +test('S3 buckets', async (t) => { + t.beforeEach(async (ctx) => { + ctx.nr = {} const server = createEmptyResponseServer() await new Promise((resolve) => { server.listen(0, resolve) }) - t.context.server = server - t.context.agent = helper.instrumentMockedAgent() + ctx.nr.server = server + ctx.nr.agent = helper.instrumentMockedAgent() const { S3Client, ...lib } = require('@aws-sdk/client-s3') - t.context.client = new S3Client({ + ctx.nr.client = new S3Client({ region: 'us-east-1', credentials: FAKE_CREDENTIALS, endpoint: `http://localhost:${server.address().port}`, @@ -30,40 +31,33 @@ tap.test('S3 buckets', (t) => { forcePathStyle: true }) - t.context.lib = lib + ctx.nr.lib = lib }) - t.afterEach((t) => { - t.context.server.destroy() - helper.unloadAgent(t.context.agent) - }) + t.afterEach(afterEach) - t.test('commands', (t) => { + await t.test('commands', (t, end) => { const { client, agent, lib: { HeadBucketCommand, CreateBucketCommand, DeleteBucketCommand } - } = t.context + } = t.nr const Bucket = 'delete-aws-sdk-test-bucket-' + Math.floor(Math.random() * 100000) helper.runInTransaction(agent, async (tx) => { - try { - await client.send(new HeadBucketCommand({ Bucket })) - await client.send(new CreateBucketCommand({ Bucket })) - await client.send(new DeleteBucketCommand({ Bucket })) - } catch (err) { - t.error(err) - } + await client.send(new HeadBucketCommand({ Bucket })) + await client.send(new CreateBucketCommand({ Bucket })) + await client.send(new DeleteBucketCommand({ Bucket })) tx.end() const args = { + end, tx, service: 'S3', operations: ['HeadBucketCommand', 'CreateBucketCommand', 'DeleteBucketCommand'] } - setImmediate(t.checkExternals, args) + setImmediate(checkExternals, args) }) }) - t.end() }) diff --git a/test/versioned/aws-sdk-v3/ses.tap.js b/test/versioned/aws-sdk-v3/ses.tap.js index d21bf0f23b..7ca52af281 100644 --- a/test/versioned/aws-sdk-v3/ses.tap.js +++ b/test/versioned/aws-sdk-v3/ses.tap.js @@ -5,36 +5,34 @@ 'use strict' -const tap = require('tap') +const test = require('node:test') const helper = require('../../lib/agent_helper') -require('./common') +const { afterEach, checkExternals } = require('./common') const { createResponseServer, FAKE_CREDENTIALS } = require('../../lib/aws-server-stubs') -tap.test('SESClient', (t) => { - t.beforeEach(async (t) => { +test('SESClient', async (t) => { + t.beforeEach(async (ctx) => { + ctx.nr = {} const server = createResponseServer() await new Promise((resolve) => { server.listen(0, resolve) }) - t.context.server = server - t.context.agent = helper.instrumentMockedAgent() + ctx.nr.server = server + ctx.nr.agent = helper.instrumentMockedAgent() const { SESClient, ...lib } = require('@aws-sdk/client-ses') - t.context.SendEmailCommand = lib.SendEmailCommand + ctx.nr.SendEmailCommand = lib.SendEmailCommand const endpoint = `http://localhost:${server.address().port}` - t.context.service = new SESClient({ + ctx.nr.service = new SESClient({ credentials: FAKE_CREDENTIALS, endpoint, region: 'us-east-1' }) }) - t.afterEach((t) => { - t.context.server.destroy() - helper.unloadAgent(t.context.agent) - }) + t.afterEach(afterEach) - t.test('SendEmailCommand', (t) => { - const { agent, service, SendEmailCommand } = t.context + await t.test('SendEmailCommand', (t, end) => { + const { agent, service, SendEmailCommand } = t.nr helper.runInTransaction(agent, async (tx) => { const cmd = new SendEmailCommand({ Destination: 'foo@bar.com', @@ -43,12 +41,12 @@ tap.test('SESClient', (t) => { }) await service.send(cmd) tx.end() - setImmediate(t.checkExternals, { + setImmediate(checkExternals, { + end, service: 'SES', operations: ['SendEmailCommand'], tx }) }) }) - t.end() }) diff --git a/test/versioned/aws-sdk-v3/sns.tap.js b/test/versioned/aws-sdk-v3/sns.tap.js index 0ab125cd4d..9f6b679143 100644 --- a/test/versioned/aws-sdk-v3/sns.tap.js +++ b/test/versioned/aws-sdk-v3/sns.tap.js @@ -4,194 +4,171 @@ */ 'use strict' - -const tap = require('tap') +const assert = require('node:assert') +const test = require('node:test') const helper = require('../../lib/agent_helper') const common = require('./common') const { createResponseServer, FAKE_CREDENTIALS } = require('../../lib/aws-server-stubs') const sinon = require('sinon') +const { tspl } = require('@matteo.collina/tspl') +const { match } = require('../../lib/custom-assertions') -tap.test('SNS', (t) => { - t.beforeEach(async (t) => { +test('SNS', async (t) => { + t.beforeEach(async (ctx) => { + ctx.nr = {} const server = createResponseServer() await new Promise((resolve) => { server.listen(0, resolve) }) - t.context.server = server - t.context.agent = helper.instrumentMockedAgent() + ctx.nr.server = server + ctx.nr.agent = helper.instrumentMockedAgent() const Shim = require('../../../lib/shim/message-shim') - t.context.setLibrarySpy = sinon.spy(Shim.prototype, 'setLibrary') + ctx.nr.setLibrarySpy = sinon.spy(Shim.prototype, 'setLibrary') const lib = require('@aws-sdk/client-sns') const SNSClient = lib.SNSClient - t.context.lib = lib - t.context.sns = new SNSClient({ + ctx.nr.lib = lib + ctx.nr.sns = new SNSClient({ credentials: FAKE_CREDENTIALS, endpoint: `http://localhost:${server.address().port}`, region: 'us-east-1' }) }) - t.afterEach((t) => { - t.context.server.destroy() - helper.unloadAgent(t.context.agent) - t.context.setLibrarySpy.restore() - // this may be brute force but i could not figure out - // which files within the modules were cached preventing the instrumenting - // from running on every test - Object.keys(require.cache).forEach((key) => { - if ( - key.includes('@aws-sdk/client-sns') || - key.includes('@aws-sdk/smithy-client') || - key.includes('@smithy/smithy-client') - ) { - delete require.cache[key] - } - }) + t.afterEach((ctx) => { + common.afterEach(ctx) + ctx.nr.setLibrarySpy.restore() }) - t.test('publish with callback', (t) => { + await t.test('publish with callback', (t, end) => { const { agent, sns, + setLibrarySpy, lib: { PublishCommand } - } = t.context + } = t.nr helper.runInTransaction(agent, (tx) => { const params = { Message: 'Hello!' } const cmd = new PublishCommand(params) sns.send(cmd, (err) => { - t.error(err) + assert.ok(!err) tx.end() const destName = 'PhoneNumber' - const args = [t, tx, destName] + const args = [end, tx, destName, setLibrarySpy] setImmediate(finish, ...args) }) }) }) - t.test('publish with default destination(PhoneNumber)', (t) => { + await t.test('publish with default destination(PhoneNumber)', (t, end) => { const { agent, sns, + setLibrarySpy, lib: { PublishCommand } - } = t.context + } = t.nr helper.runInTransaction(agent, async (tx) => { const params = { Message: 'Hello!' } - try { - const cmd = new PublishCommand(params) - await sns.send(cmd) - } catch (error) { - t.error(error) - } + const cmd = new PublishCommand(params) + await sns.send(cmd) tx.end() const destName = 'PhoneNumber' - const args = [t, tx, destName] + const args = [end, tx, destName, setLibrarySpy] setImmediate(finish, ...args) }) }) - t.test('publish with TopicArn as destination', (t) => { + await t.test('publish with TopicArn as destination', (t, end) => { const { agent, sns, + setLibrarySpy, lib: { PublishCommand } - } = t.context + } = t.nr helper.runInTransaction(agent, async (tx) => { const TopicArn = 'TopicArn' const params = { TopicArn, Message: 'Hello!' } - try { - const cmd = new PublishCommand(params) - await sns.send(cmd) - } catch (error) { - t.error(error) - } + const cmd = new PublishCommand(params) + await sns.send(cmd) tx.end() - const args = [t, tx, TopicArn] + const args = [end, tx, TopicArn, setLibrarySpy] setImmediate(finish, ...args) }) }) - t.test('publish with TargetArn as destination', (t) => { + await t.test('publish with TargetArn as destination', (t, end) => { const { agent, sns, + setLibrarySpy, lib: { PublishCommand } - } = t.context + } = t.nr helper.runInTransaction(agent, async (tx) => { const TargetArn = 'TargetArn' const params = { TargetArn, Message: 'Hello!' } - try { - const cmd = new PublishCommand(params) - await sns.send(cmd) - } catch (error) { - t.error(error) - } + const cmd = new PublishCommand(params) + await sns.send(cmd) tx.end() - const args = [t, tx, TargetArn] + const args = [end, tx, TargetArn, setLibrarySpy] setImmediate(finish, ...args) }) }) - t.test('publish with TopicArn as destination when both Topic and Target Arn are defined', (t) => { - const { - agent, - sns, - lib: { PublishCommand } - } = t.context - helper.runInTransaction(agent, async (tx) => { - const TargetArn = 'TargetArn' - const TopicArn = 'TopicArn' - const params = { TargetArn, TopicArn, Message: 'Hello!' } + await t.test( + 'publish with TopicArn as destination when both Topic and Target Arn are defined', + (t, end) => { + const { + agent, + sns, + setLibrarySpy, + lib: { PublishCommand } + } = t.nr + helper.runInTransaction(agent, async (tx) => { + const TargetArn = 'TargetArn' + const TopicArn = 'TopicArn' + const params = { TargetArn, TopicArn, Message: 'Hello!' } - try { const cmd = new PublishCommand(params) await sns.send(cmd) - } catch (error) { - t.error(error) - } - - tx.end() + tx.end() - const args = [t, tx, TopicArn] - setImmediate(finish, ...args) - }) - }) + const args = [end, tx, TopicArn, setLibrarySpy] + setImmediate(finish, ...args) + }) + } + ) - t.test( + await t.test( 'should record external segment and not a SNS segment for a command that is not PublishCommand', - (t) => { + (t, end) => { const { agent, sns, lib: { ListTopicsCommand } - } = t.context + } = t.nr helper.runInTransaction(agent, async (tx) => { const TargetArn = 'TargetArn' const TopicArn = 'TopicArn' const params = { TargetArn, TopicArn, Message: 'Hello!' } - try { - const cmd = new ListTopicsCommand(params) - await sns.send(cmd) - } catch (error) { - t.error(error) - } - + const cmd = new ListTopicsCommand(params) + await sns.send(cmd) tx.end() - setImmediate(t.checkExternals, { + setImmediate(common.checkExternals, { + end, tx, service: 'SNS', operations: ['ListTopicsCommand'] @@ -200,56 +177,50 @@ tap.test('SNS', (t) => { } ) - t.test('should mark requests to be dt-disabled', (t) => { + await t.test('should mark requests to be dt-disabled', async (t) => { const { agent, sns, lib: { ListTopicsCommand } - } = t.context - t.plan(2) + } = t.nr + const plan = tspl(t, { plan: 2 }) - helper.runInTransaction(agent, async (tx) => { + await helper.runInTransaction(agent, async (tx) => { const params = { Message: 'Hiya' } const cmd = new ListTopicsCommand(params) sns.middlewareStack.add( (next) => async (args) => { const result = await next(args) - const headers = result.response.body.req._headers - t.notOk(headers.traceparent, 'should not add traceparent header to request') + const headers = result.response.body.req.getHeaders() + plan.ok(!headers.traceparent, 'should not add traceparent header to request') return result }, { name: 'TestMw', step: 'deserialize' } ) const res = await sns.send(cmd) tx.end() - t.ok(res) + plan.ok(res) }) }) - t.end() }) -function finish(t, tx, destName) { +function finish(end, tx, destName, setLibrarySpy) { const root = tx.trace.root - const messages = common.checkAWSAttributes(t, root, common.SNS_PATTERN) - t.equal(messages.length, 1, 'should have 1 message broker segment') - t.ok(messages[0].name.endsWith(destName), 'should have appropriate destination') + const messages = common.checkAWSAttributes(root, common.SNS_PATTERN) + assert.equal(messages.length, 1, 'should have 1 message broker segment') + assert.ok(messages[0].name.endsWith(destName), 'should have appropriate destination') - const externalSegments = common.checkAWSAttributes(t, root, common.EXTERN_PATTERN) - t.equal(externalSegments.length, 0, 'should not have any External segments') + const externalSegments = common.checkAWSAttributes(root, common.EXTERN_PATTERN) + assert.equal(externalSegments.length, 0, 'should not have any External segments') const attrs = messages[0].attributes.get(common.SEGMENT_DESTINATION) - t.match( - attrs, - { - 'aws.operation': 'PublishCommand', - 'aws.requestId': String, - 'aws.service': /sns|SNS/, - 'aws.region': 'us-east-1' - }, - 'should have expected attributes for PublishCommand' - ) - - t.equal(t.context.setLibrarySpy.callCount, 1, 'should only call setLibrary once and not per call') - t.end() + match(attrs, { + 'aws.operation': 'PublishCommand', + 'aws.requestId': String, + 'aws.service': /sns|SNS/, + 'aws.region': 'us-east-1' + }), + assert.equal(setLibrarySpy.callCount, 1, 'should only call setLibrary once and not per call') + end() } diff --git a/test/versioned/aws-sdk-v3/sqs.tap.js b/test/versioned/aws-sdk-v3/sqs.tap.js index df1fb24d97..8f4b523fab 100644 --- a/test/versioned/aws-sdk-v3/sqs.tap.js +++ b/test/versioned/aws-sdk-v3/sqs.tap.js @@ -4,132 +4,133 @@ */ 'use strict' - -const tap = require('tap') +const assert = require('node:assert') +const test = require('node:test') const helper = require('../../lib/agent_helper') const common = require('./common') const { createResponseServer, FAKE_CREDENTIALS } = require('../../lib/aws-server-stubs') const sinon = require('sinon') +const { match } = require('../../lib/custom-assertions') const AWS_REGION = 'us-east-1' -tap.test('SQS API', (t) => { - t.beforeEach(async (t) => { +test('SQS API', async (t) => { + t.beforeEach(async (ctx) => { + ctx.nr = {} const server = createResponseServer() await new Promise((resolve) => { server.listen(0, resolve) }) - t.context.server = server - t.context.agent = helper.instrumentMockedAgent() + ctx.nr.server = server + ctx.nr.agent = helper.instrumentMockedAgent() const Shim = require('../../../lib/shim/message-shim') - t.context.setLibrarySpy = sinon.spy(Shim.prototype, 'setLibrary') + ctx.nr.setLibrarySpy = sinon.spy(Shim.prototype, 'setLibrary') const lib = require('@aws-sdk/client-sqs') const SQSClient = lib.SQSClient - t.context.lib = lib + ctx.nr.lib = lib - t.context.sqs = new SQSClient({ + ctx.nr.sqs = new SQSClient({ credentials: FAKE_CREDENTIALS, endpoint: `http://sqs.${AWS_REGION}.amazonaws.com:${server.address().port}`, region: AWS_REGION }) - t.context.queueName = 'delete-aws-sdk-test-queue-' + Math.floor(Math.random() * 100000) + ctx.nr.queueName = 'delete-aws-sdk-test-queue-' + Math.floor(Math.random() * 100000) }) - t.afterEach((t) => { - t.context.server.destroy() - helper.unloadAgent(t.context.agent) - t.context.setLibrarySpy.restore() + t.afterEach((ctx) => { + common.afterEach(ctx) + ctx.nr.setLibrarySpy.restore() }) - t.test('commands with promises', async (t) => { + await t.test('commands with promises', async (t) => { const { agent, queueName, sqs, + setLibrarySpy, lib: { CreateQueueCommand, SendMessageCommand, SendMessageBatchCommand, ReceiveMessageCommand } - } = t.context + } = t.nr // create queue const createParams = getCreateParams(queueName) const createCommand = new CreateQueueCommand(createParams) const { QueueUrl } = await sqs.send(createCommand) - t.ok(QueueUrl) + assert.ok(QueueUrl) // run send/receive commands in transaction await helper.runInTransaction(agent, async (transaction) => { // send message const sendMessageParams = getSendMessageParams(QueueUrl) const sendMessageCommand = new SendMessageCommand(sendMessageParams) const { MessageId } = await sqs.send(sendMessageCommand) - t.ok(MessageId) + assert.ok(MessageId) // send message batch const sendMessageBatchParams = getSendMessageBatchParams(QueueUrl) const sendMessageBatchCommand = new SendMessageBatchCommand(sendMessageBatchParams) const { Successful } = await sqs.send(sendMessageBatchCommand) - t.ok(Successful) + assert.ok(Successful) // receive message const receiveMessageParams = getReceiveMessageParams(QueueUrl) const receiveMessageCommand = new ReceiveMessageCommand(receiveMessageParams) const { Messages } = await sqs.send(receiveMessageCommand) - t.ok(Messages) + assert.ok(Messages) // wrap up transaction.end() - await finish({ t, transaction, queueName }) + await finish({ transaction, queueName, setLibrarySpy }) }) }) - t.end() }) -function finish({ t, transaction, queueName }) { +function finish({ transaction, queueName, setLibrarySpy }) { const expectedSegmentCount = 3 const root = transaction.trace.root - const segments = common.checkAWSAttributes(t, root, common.SQS_PATTERN) + const segments = common.checkAWSAttributes(root, common.SQS_PATTERN) - t.equal( + assert.equal( segments.length, expectedSegmentCount, `should have ${expectedSegmentCount} AWS MessageBroker/SQS segments` ) - const externalSegments = common.checkAWSAttributes(t, root, common.EXTERN_PATTERN) - t.equal(externalSegments.length, 0, 'should not have any External segments') + const externalSegments = common.checkAWSAttributes(root, common.EXTERN_PATTERN) + assert.equal(externalSegments.length, 0, 'should not have any External segments') const [sendMessage, sendMessageBatch, receiveMessage] = segments - checkName(t, sendMessage.name, 'Produce', queueName) - checkAttributes(t, sendMessage, 'SendMessageCommand') + checkName(sendMessage.name, 'Produce', queueName) + checkAttributes(sendMessage, 'SendMessageCommand') - checkName(t, sendMessageBatch.name, 'Produce', queueName) - checkAttributes(t, sendMessageBatch, 'SendMessageBatchCommand') + checkName(sendMessageBatch.name, 'Produce', queueName) + checkAttributes(sendMessageBatch, 'SendMessageBatchCommand') - checkName(t, receiveMessage.name, 'Consume', queueName) - checkAttributes(t, receiveMessage, 'ReceiveMessageCommand') - t.equal(t.context.setLibrarySpy.callCount, 1, 'should only call setLibrary once and not per call') + checkName(receiveMessage.name, 'Consume', queueName) + checkAttributes(receiveMessage, 'ReceiveMessageCommand') + assert.equal(setLibrarySpy.callCount, 1, 'should only call setLibrary once and not per call') // Verify that cloud entity relationship attributes are present: for (const segment of segments) { const attrs = segment.getAttributes() - t.equal(attrs['messaging.system'], 'aws_sqs') - t.equal(attrs['cloud.region'], 'us-east-1') - t.equal(attrs['cloud.account.id'], '1234567890') - t.equal(attrs['messaging.destination.name'], queueName) + assert.equal(attrs['messaging.system'], 'aws_sqs') + assert.equal(attrs['cloud.region'], 'us-east-1') + assert.equal(attrs['cloud.account.id'], '1234567890') + assert.equal(attrs['messaging.destination.name'], queueName) } } -function checkName(t, name, action, queueName) { +function checkName(name, action, queueName) { const specificName = `/${action}/Named/${queueName}` - t.match(name, specificName, 'should have correct name') + match(name, specificName) } -function checkAttributes(t, segment, operation) { +function checkAttributes(segment, operation) { const actualAttributes = segment.attributes.get(common.SEGMENT_DESTINATION) const expectedAttributes = { @@ -139,7 +140,7 @@ function checkAttributes(t, segment, operation) { 'aws.region': AWS_REGION } - t.match(actualAttributes, expectedAttributes, `should have expected attributes for ${operation}`) + match(actualAttributes, expectedAttributes) } function getCreateParams(queueName) {