Skip to content

Commit

Permalink
fix: handle missing package.json file when checking for version (#2450)
Browse files Browse the repository at this point in the history
* feat: handle missing version case

* feat: add test cases

* fix: cr comment

* fix: add comment to test

* fix: tests description
  • Loading branch information
nozik committed Sep 8, 2021
1 parent bec7791 commit 3acebdc
Show file tree
Hide file tree
Showing 2 changed files with 185 additions and 4 deletions.
Expand Up @@ -59,6 +59,18 @@ export abstract class InstrumentationBase<T = any>
}
}

private _extractPackageVersion(baseDir: string): string | undefined {
try {
// eslint-disable-next-line @typescript-eslint/no-var-requires
const version = require(path.join(baseDir, 'package.json')).version;
return typeof version === 'string' ? version : undefined;
} catch (error) {
diag.warn('Failed extracting version', baseDir);
}

return undefined;
}

private _onRequire<T>(
module: InstrumentationModuleDefinition<T>,
exports: T,
Expand All @@ -73,13 +85,11 @@ export abstract class InstrumentationBase<T = any>
return exports;
}

// eslint-disable-next-line @typescript-eslint/no-var-requires
const version = require(path.join(baseDir, 'package.json')).version;
const version = this._extractPackageVersion(baseDir);
module.moduleVersion = version;
if (module.name === name) {
// main module
if (
typeof version === 'string' &&
isSupported(module.supportedVersions, version, module.includePrerelease)
) {
if (typeof module.patch === 'function') {
Expand Down Expand Up @@ -167,7 +177,12 @@ export abstract class InstrumentationBase<T = any>
}
}

function isSupported(supportedVersions: string[], version: string, includePrerelease?: boolean): boolean {
function isSupported(supportedVersions: string[], version?: string, includePrerelease?: boolean): boolean {
if (typeof version === 'undefined') {
// If we don't have the version, accept the wildcard case only
return supportedVersions.includes('*');
}

return supportedVersions.some(supportedVersion => {
return satisfies(version, supportedVersion, { includePrerelease });
});
Expand Down
@@ -0,0 +1,166 @@
/*
* Copyright The OpenTelemetry Authors
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* https://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

import * as assert from 'assert';
import * as sinon from 'sinon';
import { InstrumentationBase, InstrumentationModuleDefinition } from '../../src';

const MODULE_NAME = 'test-module';
const MODULE_FILE_NAME = 'test-module-file';
const MODULE_VERSION = '0.1.0';
const WILDCARD_VERSION = '*';
const MODULE_DIR = '/random/dir';

class TestInstrumentation extends InstrumentationBase {
constructor() {
super(MODULE_NAME, MODULE_VERSION);
}

init() {}
}

describe('InstrumentationBase', () => {
describe('_onRequire - module version is not available', () => {
// For all of these cases, there is no indication of the actual module version,
// so we require there to be a wildcard supported version.

let instrumentation: TestInstrumentation;
let modulePatchSpy: sinon.SinonSpy;

beforeEach(() => {
instrumentation = new TestInstrumentation();
// @ts-expect-error access internal property for testing
instrumentation._enabled = true;
modulePatchSpy = sinon.spy();
});

describe('when patching a module', () => {
describe('AND there is no wildcard supported version', () => {
it('should not patch module', () => {
const moduleExports = {};
const instrumentationModule = {
supportedVersions: [`^${MODULE_VERSION}`],
name: MODULE_NAME,
patch: modulePatchSpy as unknown,
} as InstrumentationModuleDefinition<unknown>;

// @ts-expect-error access internal property for testing
instrumentation._onRequire<unknown>(
instrumentationModule,
moduleExports,
MODULE_NAME,
MODULE_DIR
);

assert.strictEqual(instrumentationModule.moduleVersion, undefined);
assert.strictEqual(instrumentationModule.moduleExports, undefined);
sinon.assert.notCalled(modulePatchSpy);
});
});

describe('AND there is a wildcard supported version', () => {
it('should patch module', () => {
const moduleExports = {};
const instrumentationModule = {
supportedVersions: [`^${MODULE_VERSION}`, WILDCARD_VERSION],
name: MODULE_NAME,
patch: modulePatchSpy as unknown,
} as InstrumentationModuleDefinition<unknown>;

// @ts-expect-error access internal property for testing
instrumentation._onRequire<unknown>(
instrumentationModule,
moduleExports,
MODULE_NAME,
MODULE_DIR
);

assert.strictEqual(instrumentationModule.moduleVersion, undefined);
assert.strictEqual(instrumentationModule.moduleExports, moduleExports);
sinon.assert.calledOnceWithExactly(modulePatchSpy, moduleExports, undefined);
});
});
});

describe('when patching module files', () => {
let filePatchSpy: sinon.SinonSpy;

beforeEach(() => {
filePatchSpy = sinon.spy();
})

describe('AND there is no wildcard supported version', () => {
it('should not patch module file', () => {
const moduleExports = {};
const supportedVersions = [`^${MODULE_VERSION}`];
const instrumentationModule = {
supportedVersions,
name: MODULE_NAME,
patch: modulePatchSpy as unknown,
files: [{
name: MODULE_FILE_NAME,
supportedVersions,
patch: filePatchSpy as unknown
}]
} as InstrumentationModuleDefinition<unknown>;

// @ts-expect-error access internal property for testing
instrumentation._onRequire<unknown>(
instrumentationModule,
moduleExports,
MODULE_FILE_NAME,
MODULE_DIR
);

assert.strictEqual(instrumentationModule.moduleVersion, undefined);
assert.strictEqual(instrumentationModule.moduleExports, undefined);
sinon.assert.notCalled(modulePatchSpy);
sinon.assert.notCalled(filePatchSpy);
});
});

describe('AND there is a wildcard supported version', () => {
it('should patch module file', () => {
const moduleExports = {};
const supportedVersions = [`^${MODULE_VERSION}`, WILDCARD_VERSION];
const instrumentationModule = {
supportedVersions,
name: MODULE_NAME,
patch: modulePatchSpy as unknown,
files: [{
name: MODULE_FILE_NAME,
supportedVersions,
patch: filePatchSpy as unknown
}]
} as InstrumentationModuleDefinition<unknown>;

// @ts-expect-error access internal property for testing
instrumentation._onRequire<unknown>(
instrumentationModule,
moduleExports,
MODULE_FILE_NAME,
MODULE_DIR
);

assert.strictEqual(instrumentationModule.moduleVersion, undefined);
assert.strictEqual(instrumentationModule.files[0].moduleExports, moduleExports);
sinon.assert.notCalled(modulePatchSpy);
sinon.assert.calledOnceWithExactly(filePatchSpy, moduleExports, undefined);
});
});
});
});
});

0 comments on commit 3acebdc

Please sign in to comment.