From f291af2b621d05fa4391b3fd75021b72b93fa96f Mon Sep 17 00:00:00 2001 From: David Luna Date: Tue, 5 Dec 2023 09:55:46 +0100 Subject: [PATCH] tests: refactor ignore config options tests (strings, regexp) (#3768) --- test/config.test.js | 68 ---------------------- test/config/_json-utils.js | 60 +++++++++++++++++++ test/config/config.test.js | 96 ++++++++++++++++++++++++++++++- test/config/fixtures/use-agent.js | 10 +--- 4 files changed, 157 insertions(+), 77 deletions(-) create mode 100644 test/config/_json-utils.js diff --git a/test/config.test.js b/test/config.test.js index 421877b665..15de8bb67d 100644 --- a/test/config.test.js +++ b/test/config.test.js @@ -13,7 +13,6 @@ var os = require('os'); var path = require('path'); var util = require('util'); -var isRegExp = require('core-util-is').isRegExp; var test = require('tape'); const Agent = require('../lib/agent'); @@ -93,25 +92,6 @@ function assertEncodedError(t, error, result, trans, parent) { // ---- tests -var keyValuePairValues = ['addPatch', 'globalLabels']; - -keyValuePairValues.forEach(function (key) { - var pairs = [ - ['foo', 'bar'], - ['baz', 'buz'], - ]; - - test(key + ' should support pair form', function (t) { - var agent = new Agent(); - var opts = {}; - opts[key] = pairs; - agent.start(Object.assign({}, agentOptsNoopTransport, opts)); - t.deepEqual(agent._conf[key], pairs); - agent.destroy(); - t.end(); - }); -}); - test('should overwrite option property active by ELASTIC_APM_ACTIVE', function (t) { var agent = new Agent(); var opts = { serviceName: 'foo', secretToken: 'baz', active: true }; @@ -123,54 +103,6 @@ test('should overwrite option property active by ELASTIC_APM_ACTIVE', function ( t.end(); }); -test('should separate strings and regexes into their own ignore arrays', function (t) { - var agent = new Agent(); - agent.start( - Object.assign({}, agentOptsNoopTransport, { - ignoreUrls: ['str1', /regex1/], - ignoreUserAgents: ['str2', /regex2/], - }), - ); - - t.deepEqual(agent._conf.ignoreUrlStr, ['str1']); - t.deepEqual(agent._conf.ignoreUserAgentStr, ['str2']); - - t.strictEqual(agent._conf.ignoreUrlRegExp.length, 1); - t.ok(isRegExp(agent._conf.ignoreUrlRegExp[0])); - t.strictEqual(agent._conf.ignoreUrlRegExp[0].toString(), '/regex1/'); - - t.strictEqual(agent._conf.ignoreUserAgentRegExp.length, 1); - t.ok(isRegExp(agent._conf.ignoreUserAgentRegExp[0])); - t.strictEqual(agent._conf.ignoreUserAgentRegExp[0].toString(), '/regex2/'); - - agent.destroy(); - t.end(); -}); - -test('should prepare WildcardMatcher array config vars', function (t) { - var agent = new Agent(); - agent.start( - Object.assign({}, agentOptsNoopTransport, { - transactionIgnoreUrls: ['foo', 'bar', '/wil*card'], - elasticsearchCaptureBodyUrls: ['*/_search', '*/_eql/search'], - }), - ); - - t.equal( - agent._conf.transactionIgnoreUrlRegExp.toString(), - '/^foo$/i,/^bar$/i,/^\\/wil.*card$/i', - 'transactionIgnoreUrlRegExp', - ); - t.equal( - agent._conf.elasticsearchCaptureBodyUrlsRegExp.toString(), - '/^.*\\/_search$/i,/^.*\\/_eql\\/search$/i', - 'elasticsearchCaptureBodyUrlsRegExp', - ); - - agent.destroy(); - t.end(); -}); - test('invalid serviceName => inactive', function (t) { const logger = new MockLogger(); const agent = new Agent(); diff --git a/test/config/_json-utils.js b/test/config/_json-utils.js new file mode 100644 index 0000000000..e7014d4a6b --- /dev/null +++ b/test/config/_json-utils.js @@ -0,0 +1,60 @@ +/* + * Copyright Elasticsearch B.V. and other contributors where applicable. + * Licensed under the BSD 2-Clause License; you may not use this file except in + * compliance with the BSD 2-Clause License. + */ + +/** + * Replaces some special values to be printed in stdout or env vars and + * be revived by the test script or the fixture. These are + * - Infinity which serializes to `null` by default + * - RegExp serializes to `{}` by default + * @param {string} key + * @param {any} value + * @returns {any} + */ +function replacer(key, value) { + if (value === Infinity) { + return 'Infinity'; + } + if (Array.isArray(value)) { + return value.map((item) => { + if (item instanceof RegExp || typeof item === 'string') { + return item.toString(); + } + return item; + }); + } + + return value; +} + +/** + * Revives values from the serialized JSON with `replacer` + * @param {string} key + * @param {any} value + * @returns {any} + */ +function reviver(key, value) { + if (value === 'Infinity') { + return Infinity; + } + + if (Array.isArray(value)) { + return value.map((item) => { + if (typeof item === 'string' && /^\/.+\/i?$/.test(item)) { + if (item.endsWith('i')) { + return new RegExp(item.slice(1, item.length - 2), 'i'); + } + return new RegExp(item.slice(1, item.length - 1)); + } + return item; + }); + } + return value; +} + +module.exports = { + replacer, + reviver, +}; diff --git a/test/config/config.test.js b/test/config/config.test.js index f006fb31b3..baecf73a50 100644 --- a/test/config/config.test.js +++ b/test/config/config.test.js @@ -12,6 +12,7 @@ const { normalize } = require('../../lib/config/config'); const { CONFIG_SCHEMA, getDefaultOptions } = require('../../lib/config/schema'); const { runTestFixtures } = require('../_utils'); +const { reviver, replacer } = require('./_json-utils.js'); const defaultOptions = getDefaultOptions(); @@ -301,7 +302,6 @@ const testFixtures = [ }, checkScriptResult: (t, err, stdout) => { t.error(err, `use-agent.js script succeeded: err=${err}`); - const reviver = (k, v) => (v === 'Infinity' ? Infinity : v); const useAgentLogs = getUseAgentLogs(stdout); const resolvedConfig = JSON.parse(useAgentLogs[2], reviver); const warnLogs = getApmLogs(stdout, 'warn'); @@ -392,7 +392,7 @@ const testFixtures = [ }, }, { - name: 'use agent - should support ket/value pairs formats', + name: 'use agent - should support key/value pairs formats (string & object)', script: 'fixtures/use-agent.js', cwd: __dirname, noConvenienceConfig: true, @@ -423,6 +423,35 @@ const testFixtures = [ ); }, }, + { + name: 'use agent - should support key/value pairs formats (array)', + script: 'fixtures/use-agent.js', + cwd: __dirname, + noConvenienceConfig: true, + env: { + TEST_APM_START_OPTIONS: JSON.stringify({ + globalLabels: [ + ['foo', 'bar'], + ['baz', 'buz'], + ], + }), + }, + checkScriptResult: (t, err, stdout) => { + t.error(err, `use-agent.js script succeeded: err=${err}`); + const useAgentLogs = getUseAgentLogs(stdout); + const resolvedConfig = JSON.parse(useAgentLogs[2]); + const pairs = [ + ['foo', 'bar'], + ['baz', 'buz'], + ]; + + t.deepEqual( + resolvedConfig.globalLabels, + pairs, + 'globalLabels is parsed correctly from environment (array)', + ); + }, + }, { name: 'use agent - should support duration options', script: 'fixtures/use-agent.js', @@ -504,6 +533,69 @@ const testFixtures = [ ); }, }, + { + name: 'use agent - should support string, regex & wildcards in ignore options', + script: 'fixtures/use-agent.js', + cwd: __dirname, + noConvenienceConfig: true, + env: { + ELASTIC_APM_TRANSACTION_IGNORE_URLS: 'foo,bar,/wil*card', + ELASTIC_APM_ELASTICSEARCH_CAPTURE_BODY_URLS: '*/_search,*/_eql/search', + TEST_APM_START_OPTIONS: JSON.stringify( + { + ignoreUrls: ['str1', /regex1/], + ignoreUserAgents: ['str2', /regex2/], + }, + replacer, + ), + }, + checkScriptResult: (t, err, stdout) => { + t.error(err, `use-agent.js script succeeded: err=${err}`); + const useAgentLogs = getUseAgentLogs(stdout); + const resolvedConfig = JSON.parse(useAgentLogs[2], reviver); + + t.deepEqual( + resolvedConfig.transactionIgnoreUrls, + ['foo', 'bar', '/wil*card'], + 'transactionIgnoreUrls is parsed correctly from environment (wildcards)', + ); + t.deepEqual( + resolvedConfig.transactionIgnoreUrlRegExp, + [/^foo$/i, /^bar$/i, /^\/wil.*card$/i], + 'transactionIgnoreUrlRegExp is parsed correctly from environment (wildcards)', + ); + t.deepEqual( + resolvedConfig.elasticsearchCaptureBodyUrls, + ['*/_search', '*/_eql/search'], + 'elasticsearchCaptureBodyUrls is parsed correctly from environment (wildcards)', + ); + t.deepEqual( + resolvedConfig.elasticsearchCaptureBodyUrlsRegExp, + [/^.*\/_search$/i, /^.*\/_eql\/search$/i], + 'elasticsearchCaptureBodyUrls is parsed correctly from environment (wildcards)', + ); + t.deepEqual( + resolvedConfig.ignoreUrlStr, + ['str1'], + 'string items of ignoreUrl are added to the right config (ignoreUrlStr)', + ); + t.deepEqual( + resolvedConfig.ignoreUrlRegExp, + [/regex1/], + 'regexp items of ignoreUrl are added to the right config (ignoreUrlRegExp)', + ); + t.deepEqual( + resolvedConfig.ignoreUserAgentStr, + ['str2'], + 'string items of ignoreUserAgents are added to the right config (ignoreUserAgentStr)', + ); + t.deepEqual( + resolvedConfig.ignoreUserAgentRegExp, + [/regex2/], + 'regexp items of ignoreUserAgents are added to the right config (ignoreUserAgentRegExp)', + ); + }, + }, ]; test('agent config fixtures', (suite) => { diff --git a/test/config/fixtures/use-agent.js b/test/config/fixtures/use-agent.js index b3d078a95f..c7bfbf6d2f 100644 --- a/test/config/fixtures/use-agent.js +++ b/test/config/fixtures/use-agent.js @@ -8,6 +8,8 @@ const { NoopApmClient } = require('../../../lib/apm-client/noop-apm-client'); +const { replacer, reviver } = require('../_json-utils'); + const APM_START_OPTIONS = { transport: () => new NoopApmClient(), }; @@ -16,7 +18,7 @@ const APM_START_OPTIONS = { if (process.env.TEST_APM_START_OPTIONS) { Object.assign( APM_START_OPTIONS, - JSON.parse(process.env.TEST_APM_START_OPTIONS), + JSON.parse(process.env.TEST_APM_START_OPTIONS, reviver), ); } // this prefix will be used to get info from the test suite @@ -31,12 +33,6 @@ const APM_ENV_OPTIONS = Object.keys(process.env).reduce((acc, key) => { return acc; }, {}); -// Make sure values like Infinity are passe back to test -// TODO: check if necessary to add NaN and others -function replacer(key, value) { - return value === Infinity ? 'Infinity' : value; -} - // Report options passed by env console.log(`${logPrefix}${JSON.stringify(APM_ENV_OPTIONS, replacer)}`);