Skip to content

Commit

Permalink
tests
Browse files Browse the repository at this point in the history
  • Loading branch information
mhennoch committed Sep 13, 2024
1 parent ada939c commit 32cd33c
Show file tree
Hide file tree
Showing 27 changed files with 969 additions and 366 deletions.
617 changes: 575 additions & 42 deletions package-lock.json

Large diffs are not rendered by default.

2 changes: 2 additions & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@
"test": "npm run test:unit && npm run test:debug-metrics && npm run test:instrumentations",
"test:unit": "cross-env TEST_ALLOW_DOUBLE_START=y nyc ts-mocha --exclude 'test/instrumentation/external/**/*.test.ts' --exclude 'test/separate_process/*' --timeout 60s --parallel --jobs 8 -p tsconfig.json 'test/**/*.test.ts'",
"unittest": "ts-mocha -p tsconfig.json 'test/api.test.ts'",
"test:unit:node": "cross-env TEST_ALLOW_DOUBLE_START=y glob -c \"node --require ts-node/register/transpile-only --test --test-timeout=10000 \" \"./test/**/*.test.ts\"",
"test:debug-metrics": "nyc --no-clean ts-mocha --timeout 10000 -p tsconfig.json 'test/separate_process/debug_metrics.test.ts'",
"test:instrumentations": "nyc ts-mocha --require test/instrumentation/external/setup.ts --jobs 1 'test/instrumentation/external/**/*.test.ts'",
"prebuild:current": "node scripts/prebuild-current.js",
Expand Down Expand Up @@ -153,6 +154,7 @@
"@opentelemetry/sdk-trace-base": "1.25.1",
"@opentelemetry/sdk-trace-node": "1.25.1",
"@opentelemetry/semantic-conventions": "1.25.1",
"glob": "^11.0.0",
"is-promise": "^4.0.0",
"nan": "^2.20.0",
"node-gyp-build": "^4.8.1",
Expand Down
20 changes: 7 additions & 13 deletions test/instrument.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,44 +14,38 @@
* limitations under the License.
*/

import { strict as assert } from 'assert';
import { afterEach, beforeEach, describe, it, mock } from 'node:test';
import * as tracing from '../src/tracing';
import * as metrics from '../src/metrics';
import { cleanEnvironment } from './utils';
import { strict as assert } from 'assert';
import { describe, it, beforeEach, afterEach, mock } from 'node:test';

describe('instrumentation', () => {
let startTracingMock;
let startMetricsMock;

beforeEach(() => {
delete require.cache[require.resolve('../src/instrument')];
cleanEnvironment();
startTracingMock = mock.method(tracing, 'startTracing').mock;
startMetricsMock = mock.method(metrics, 'startMetrics').mock;
startTracingMock = mock.method(tracing, 'startTracing', () => {});
});

afterEach(() => {
startTracingMock.restore();
startMetricsMock.restore();
startTracingMock.mock.restore();
});

it('importing auto calls startTracing', () => {
require('../src/instrument');
assert.strictEqual(startTracingMock.callCount(), 1);
assert.strictEqual(startTracingMock.mock.callCount(), 1);
});

it('calls startTracing when SPLUNK_AUTOINSTRUMENT_PACKAGE_NAMES contains a matching package name', () => {
process.env.SPLUNK_AUTOINSTRUMENT_PACKAGE_NAMES = '@splunk/otel,foo';
require('../src/instrument');
// sinon.assert.calledOnce(startTracingMock);
assert.equal(startTracingMock.callCount(), 1);
assert.equal(startTracingMock.mock.callCount(), 1);
});

it('does not call startTracing when SPLUNK_AUTOINSTRUMENT_PACKAGE_NAMES does not contain a matching package name', () => {
process.env.SPLUNK_AUTOINSTRUMENT_PACKAGE_NAMES = 'foo,@splunk/zotel';
require('../src/instrument');
// sinon.assert.notCalled(startTracingMock);
assert.equal(startTracingMock.callCount(), 0);
assert.equal(startTracingMock.mock.callCount(), 0);
});
});
13 changes: 3 additions & 10 deletions test/instrumentation/external/elasticsearch/elasticsearch.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,20 +13,13 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
import { strict as assert } from 'assert';
import * as nock from 'nock';
import * as assert from 'assert';
import { after, before, describe, it } from 'node:test';
import * as os from 'os';
import { ElasticsearchInstrumentation } from '../../../../src/instrumentations/external/elasticsearch';

import {
NodeTracerProvider,
NodeTracerConfig,
} from '@opentelemetry/sdk-trace-node';
import {
InMemorySpanExporter,
SimpleSpanProcessor,
} from '@opentelemetry/sdk-trace-base';
import { setInstrumentation, getTestSpans } from '../setup';
import { getTestSpans, setInstrumentation } from '../setup';

const instrumentation = new ElasticsearchInstrumentation();

Expand Down
98 changes: 51 additions & 47 deletions test/instrumentation/external/elasticsearch/utils.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,11 +13,12 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
import * as sinon from 'sinon';
import * as assert from 'assert';
import * as Utils from '../../../../src/instrumentations/external/elasticsearch/utils';
import { SpanKind, SpanStatusCode } from '@opentelemetry/api';
import { SemanticAttributes } from '@opentelemetry/semantic-conventions';
import { strict as assert } from 'assert';
import { describe, it, mock } from 'node:test';
import * as Utils from '../../../../src/instrumentations/external/elasticsearch/utils';
import { calledWithExactly } from '../../../utils';

describe('elasticsearch utils', () => {
const spanMock = {
Expand All @@ -27,7 +28,7 @@ describe('elasticsearch utils', () => {
setAttributes: (obj) => {},
};

context('defaultDbStatementSerializer', () => {
describe('defaultDbStatementSerializer', () => {
it('should serialize', () => {
const result = Utils.defaultDbStatementSerializer(
'operationName',
Expand All @@ -41,80 +42,80 @@ describe('elasticsearch utils', () => {
});
});

context('onError', () => {
describe('onError', () => {
it('should record error', () => {
const recordExceptionStub = sinon.stub(spanMock, 'recordException');
const setStatusStub = sinon.stub(spanMock, 'setStatus');
const endStub = sinon.stub(spanMock, 'end');
const recordExceptionStub = mock.method(spanMock, 'recordException');
const setStatusStub = mock.method(spanMock, 'setStatus');
const endStub = mock.method(spanMock, 'end');

const error = new Error('test error');

Utils.onError(spanMock, error);

sinon.assert.calledOnce(recordExceptionStub);
sinon.assert.calledWith(recordExceptionStub, error);
assert(recordExceptionStub.mock.callCount() === 1);
calledWithExactly(recordExceptionStub, error);

sinon.assert.calledOnce(setStatusStub);
sinon.assert.calledWith(setStatusStub, {
assert(setStatusStub.mock.callCount() === 1);
calledWithExactly(setStatusStub, {
code: SpanStatusCode.ERROR,
message: error.message,
});

sinon.assert.calledOnce(endStub);
assert(endStub.mock.callCount() === 1);

recordExceptionStub.restore();
setStatusStub.restore();
endStub.restore();
recordExceptionStub.mock.resetCalls();
setStatusStub.mock.resetCalls();
endStub.mock.resetCalls();
});
});

context('onResponse', () => {
describe('onResponse', () => {
it('should record response without responseHook', () => {
const setAttributesStub = sinon.stub(spanMock, 'setAttributes');
const setStatusStub = sinon.stub(spanMock, 'setStatus');
const endStub = sinon.stub(spanMock, 'end');
const setAttributesStub = mock.method(spanMock, 'setAttributes');
const setStatusStub = mock.method(spanMock, 'setStatus');
const endStub = mock.method(spanMock, 'end');

Utils.onResponse(spanMock, {
meta: { connection: { url: 'http://localhost' } },
});

sinon.assert.calledOnce(setAttributesStub);
sinon.assert.calledOnce(setStatusStub);
sinon.assert.calledOnce(endStub);
sinon.assert.calledWith(setStatusStub, { code: SpanStatusCode.OK });
assert(setAttributesStub.mock.callCount() === 1);
assert(setStatusStub.mock.callCount() === 1);
assert(endStub.mock.callCount() === 1);
calledWithExactly(setStatusStub, { code: SpanStatusCode.OK });

setAttributesStub.restore();
setStatusStub.restore();
endStub.restore();
setAttributesStub.mock.resetCalls();
setStatusStub.mock.resetCalls();
endStub.mock.resetCalls();
});

it('should record response with responseHook', () => {
const setAttributesStub = sinon.stub(spanMock, 'setAttributes');
const setStatusStub = sinon.stub(spanMock, 'setStatus');
const endStub = sinon.stub(spanMock, 'end');
const setAttributesStub = mock.method(spanMock, 'setAttributes');
const setStatusStub = mock.method(spanMock, 'setStatus');
const endStub = mock.method(spanMock, 'end');

const responseHook = sinon.spy();
const responseHook = mock.fn();

Utils.onResponse(
spanMock,
{ meta: { connection: { url: 'http://localhost' } } },
responseHook
);

sinon.assert.calledOnce(setAttributesStub);
sinon.assert.calledOnce(setStatusStub);
sinon.assert.calledOnce(endStub);
sinon.assert.calledWith(setStatusStub, { code: SpanStatusCode.OK });
assert(setAttributesStub.mock.callCount() === 1);
assert(setStatusStub.mock.callCount() === 1);
assert(endStub.mock.callCount() === 1);
calledWithExactly(setStatusStub, { code: SpanStatusCode.OK });

assert.strictEqual(responseHook.called, true);
assert(responseHook.mock.callCount() === 1);

setAttributesStub.restore();
setStatusStub.restore();
endStub.restore();
setAttributesStub.mock.resetCalls();
setStatusStub.mock.resetCalls();
endStub.mock.resetCalls();
});
});

context('getNetAttributes', () => {
describe('getNetAttributes', () => {
const url = 'http://localhost:9200';
const attributes = Utils.getNetAttributes(url);

Expand All @@ -137,7 +138,7 @@ describe('elasticsearch utils', () => {
});
});

context('getPort', () => {
describe('getPort', () => {
it('should get port', () => {
const result = Utils.getPort('3030', 'http:');
assert.strictEqual(result, '3030');
Expand All @@ -154,7 +155,7 @@ describe('elasticsearch utils', () => {
});
});

context('normalizeArguments', () => {
describe('normalizeArguments', () => {
it('should normalize with callback only', () => {
const callbackFunction = () => {};
const [params, options, callback] =
Expand All @@ -176,7 +177,7 @@ describe('elasticsearch utils', () => {
});
});

context('getIndexName', () => {
describe('getIndexName', () => {
it('should accept index string', () => {
const index = Utils.getIndexName({ index: 'test' });
assert.strictEqual(index, 'test');
Expand Down Expand Up @@ -205,22 +206,25 @@ describe('elasticsearch utils', () => {
});
});

context('startSpan', () => {
describe('startSpan', () => {
const tracerMock = {
startSpan: (name, options?, context?): any => {},
startActiveSpan: () => {},
};
it('should start span with client kind', () => {
const startSpanStub = sinon.stub(tracerMock, 'startSpan');
const startSpanStub = mock.method(tracerMock, 'startSpan');

Utils.startSpan({
tracer: tracerMock,
attributes: { testAttribute: 'testValue' },
});

sinon.assert.calledOnce(startSpanStub);
assert(startSpanStub.mock.callCount() === 1);

const [operation, options] = startSpanStub.getCall(0).args;
// const [operation, options] = startSpanStub.getCall(0).args;
console.log('startSpanStub.mock.calls[0].arguments');
console.log(startSpanStub.mock.calls[0].arguments);
const [operation, options] = startSpanStub.mock.calls[0].arguments;

assert.strictEqual(operation, 'elasticsearch.request');
assert.strictEqual(options.kind, SpanKind.CLIENT);
Expand Down
27 changes: 18 additions & 9 deletions test/instrumentation/external/sequelize/sequelize.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,22 +13,29 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
import * as assert from 'assert';
import { SequelizeInstrumentation } from '../../../../src/instrumentations/external/sequelize';
import { extractTableFromQuery } from '../../../../src/instrumentations/external/sequelize/utils';
import { ReadableSpan, Span } from '@opentelemetry/sdk-trace-base';
import {
context,
diag,
SpanStatusCode,
DiagConsoleLogger,
ROOT_CONTEXT,
SpanStatusCode,
context,
diag,
} from '@opentelemetry/api';
import { ReadableSpan, Span } from '@opentelemetry/sdk-trace-base';
import { SemanticAttributes } from '@opentelemetry/semantic-conventions';
import { getTestSpans, setInstrumentation, sqlite3MockModule } from '../setup';
import { strict as assert } from 'assert';
import { afterEach, before, beforeEach, describe, it } from 'node:test';
import { SequelizeInstrumentation } from '../../../../src/instrumentations/external/sequelize';
import { extractTableFromQuery } from '../../../../src/instrumentations/external/sequelize/utils';
import {
getTestSpans,
setInstrumentation,
sqlite3MockModule,
provider,
exporter,
} from '../setup';

const instrumentation = new SequelizeInstrumentation();

provider.register();
import * as sequelize from 'sequelize';

describe('instrumentation-sequelize', () => {
Expand All @@ -43,6 +50,8 @@ describe('instrumentation-sequelize', () => {
});

beforeEach(() => {
exporter.reset();
instrumentation.setConfig({});
instrumentation.enable();
});

Expand Down
19 changes: 3 additions & 16 deletions test/instrumentation/external/setup.ts
Original file line number Diff line number Diff line change
Expand Up @@ -25,15 +25,14 @@ import { diag, DiagConsoleLogger, DiagLogLevel } from '@opentelemetry/api';

diag.setLogger(new DiagConsoleLogger(), DiagLogLevel.ERROR);

const exporter = new InMemorySpanExporter();
const provider: NodeTracerProvider = new NodeTracerProvider({
export const exporter = new InMemorySpanExporter();
export const provider: NodeTracerProvider = new NodeTracerProvider({
resource: new Resource({
[SemanticResourceAttributes.SERVICE_NAME]: 'instrumentations-test',
}),
});
provider.addSpanProcessor(new SimpleSpanProcessor(exporter));

let instrumentation: Instrumentation | undefined = undefined;
export let instrumentation: Instrumentation | undefined = undefined;

export function getTestSpans() {
return exporter.getFinishedSpans();
Expand All @@ -44,18 +43,6 @@ export function setInstrumentation(instr: Instrumentation) {
instrumentation = instr;
}

export const mochaHooks = {
beforeAll(done: Function) {
provider.register();
done();
},
beforeEach(done: Function) {
exporter.reset();
instrumentation?.setConfig({});
done();
},
};

export class MockSqlite3Db {
constructor(_db, a, b) {
const callback = typeof b === 'function' ? b : a;
Expand Down
Loading

0 comments on commit 32cd33c

Please sign in to comment.