Skip to content

Commit efcf981

Browse files
committed
chore: add tests for api semver check
1 parent bb718d9 commit efcf981

File tree

4 files changed

+157
-60
lines changed

4 files changed

+157
-60
lines changed

packages/opentelemetry-api/src/internal/global-utils.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,7 @@ import type { MeterProvider } from '../metrics/MeterProvider';
2020
import { _globalThis } from '../platform';
2121
import type { TracerProvider } from '../trace/tracer_provider';
2222
import { VERSION } from '../version';
23-
import { isVersionCompatible } from './semver';
23+
import { isCompatible } from './semver';
2424

2525
const GLOBAL_OPENTELEMETRY_API_KEY = Symbol.for('io.opentelemetry.js.api');
2626

@@ -58,7 +58,7 @@ export function getGlobal<Type extends keyof OTelGlobalAPI>(
5858
type: Type
5959
): OTelGlobalAPI[Type] | undefined {
6060
const version = _global[GLOBAL_OPENTELEMETRY_API_KEY]?.version;
61-
if (!version || !isVersionCompatible(version)) {
61+
if (!version || !isCompatible(version)) {
6262
return;
6363
}
6464
return _global[GLOBAL_OPENTELEMETRY_API_KEY]?.[type];

packages/opentelemetry-api/src/internal/semver.ts

Lines changed: 54 additions & 58 deletions
Original file line numberDiff line numberDiff line change
@@ -18,79 +18,75 @@ import { VERSION } from '../version';
1818

1919
const re = /^(\d+)\.(\d+)\.(\d+)(?:-(.*))?$/;
2020

21-
const acceptedVersions = new Set<string>([VERSION]);
22-
const rejectedVersions = new Set<string>();
21+
export function _makeCompatibilityCheck(
22+
myVersion: string
23+
): (version: string) => boolean {
24+
const acceptedVersions = new Set<string>([myVersion]);
25+
const rejectedVersions = new Set<string>();
2326

24-
const myVersionMatch = VERSION.match(re);
25-
if (!myVersionMatch) {
26-
throw new Error('Cannot parse own version');
27-
}
28-
29-
const ownVersion = {
30-
major: +myVersionMatch[1],
31-
minor: +myVersionMatch[2],
32-
patch: +myVersionMatch[3],
33-
};
34-
35-
/**
36-
* Test an API version to see if it is compatible with this API.
37-
*
38-
* Exact match is always compatible
39-
* Major versions must always match
40-
* The minor version of the API module requesting access to the global API must be greater or equal to the minor version of this API
41-
* Patch and build tag differences are not considered at this time
42-
*
43-
* @param version version of the API requesting an instance of the global API
44-
*/
45-
export function isVersionCompatible(version: string): boolean {
46-
if (acceptedVersions.has(version)) {
47-
return true;
27+
const myVersionMatch = myVersion.match(re);
28+
if (!myVersionMatch) {
29+
throw new Error('Cannot parse own version');
4830
}
4931

50-
if (rejectedVersions.has(version)) {
51-
return false;
52-
}
32+
const ownVersion = {
33+
major: +myVersionMatch[1],
34+
minor: +myVersionMatch[2],
35+
patch: +myVersionMatch[3],
36+
};
5337

54-
const m = version.match(re);
55-
if (!m) {
56-
// cannot parse other version
57-
rejectedVersions.add(version);
58-
return false;
59-
}
38+
return function isCompatible(version: string): boolean {
39+
if (acceptedVersions.has(version)) {
40+
return true;
41+
}
6042

61-
const other = {
62-
major: +m[1],
63-
minor: +m[2],
64-
patch: +m[3],
65-
};
43+
if (rejectedVersions.has(version)) {
44+
return false;
45+
}
6646

67-
// major versions must match
68-
if (ownVersion.major != other.major) {
69-
rejectedVersions.add(version);
70-
return false;
71-
}
47+
const m = version.match(re);
48+
if (!m) {
49+
// cannot parse other version
50+
rejectedVersions.add(version);
51+
return false;
52+
}
53+
54+
const other = {
55+
major: +m[1],
56+
minor: +m[2],
57+
patch: +m[3],
58+
};
7259

73-
// if major version is 0, minor is treated like major and patch is treated like minor
74-
if (ownVersion.major === 0) {
75-
if (ownVersion.minor != other.minor) {
60+
// major versions must match
61+
if (ownVersion.major != other.major) {
7662
rejectedVersions.add(version);
7763
return false;
7864
}
7965

80-
if (ownVersion.patch < other.patch) {
66+
// if major version is 0, minor is treated like major and patch is treated like minor
67+
if (ownVersion.major === 0) {
68+
if (ownVersion.minor != other.minor) {
69+
rejectedVersions.add(version);
70+
return false;
71+
}
72+
73+
if (ownVersion.patch < other.patch) {
74+
rejectedVersions.add(version);
75+
return false;
76+
}
77+
78+
acceptedVersions.add(version);
79+
return true;
80+
}
81+
82+
if (ownVersion.minor < other.minor) {
8183
rejectedVersions.add(version);
8284
return false;
8385
}
8486

8587
acceptedVersions.add(version);
8688
return true;
87-
}
88-
89-
if (ownVersion.minor < other.minor) {
90-
rejectedVersions.add(version);
91-
return false;
92-
}
93-
94-
acceptedVersions.add(version);
95-
return true;
89+
};
9690
}
91+
92+
export const isCompatible = _makeCompatibilityCheck(VERSION);
Lines changed: 101 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,101 @@
1+
/*
2+
* Copyright The OpenTelemetry Authors
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* https://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
17+
import * as assert from 'assert';
18+
import {
19+
isCompatible,
20+
_makeCompatibilityCheck,
21+
} from '../../src/internal/semver';
22+
import { VERSION } from '../../src/version';
23+
24+
describe('Version Compatibility', () => {
25+
it('should be compatible if versions are equal', () => {
26+
assert.ok(isCompatible(VERSION));
27+
});
28+
29+
describe('throws if own version cannot be parsed', () => {
30+
assert.throws(() => {
31+
_makeCompatibilityCheck('this is not semver');
32+
});
33+
});
34+
35+
describe('incompatible if other version cannot be parsed', () => {
36+
const check = _makeCompatibilityCheck('0.1.2');
37+
assert.ok(!check('this is not semver'));
38+
});
39+
40+
describe('>= 1.x', () => {
41+
it('should be compatible if major and minor versions are equal', () => {
42+
const check = _makeCompatibilityCheck('1.2.3');
43+
assert.ok(check('1.2.2'));
44+
assert.ok(check('1.2.2-alpha'));
45+
assert.ok(check('1.2.4'));
46+
assert.ok(check('1.2.4-alpha'));
47+
});
48+
49+
it('should be compatible if major versions are equal and minor version is lesser', () => {
50+
const check = _makeCompatibilityCheck('1.2.3');
51+
assert.ok(check('1.1.2'));
52+
assert.ok(check('1.1.2-alpha'));
53+
assert.ok(check('1.1.4'));
54+
assert.ok(check('1.1.4-alpha'));
55+
});
56+
57+
it('should be incompatible if major versions do not match', () => {
58+
const check = _makeCompatibilityCheck('3.3.3');
59+
assert.ok(!check('0.3.3'));
60+
assert.ok(!check('0.3.3'));
61+
});
62+
63+
it('should be incompatible if major versions match but other minor version is greater than our minor version', () => {
64+
const check = _makeCompatibilityCheck('1.2.3');
65+
assert.ok(!check('1.3.3-alpha'));
66+
assert.ok(!check('1.3.3'));
67+
});
68+
});
69+
70+
describe('0.x', () => {
71+
it('should be compatible if minor and patch versions are equal', () => {
72+
const check = _makeCompatibilityCheck('0.1.2');
73+
assert.ok(check('0.1.2'));
74+
assert.ok(check('0.1.2-alpha'));
75+
});
76+
77+
it('should be compatible if minor versions are equal and patch version is lesser', () => {
78+
const check = _makeCompatibilityCheck('0.1.2');
79+
assert.ok(check('0.1.1'));
80+
assert.ok(check('0.1.1-alpha'));
81+
});
82+
83+
it('should be incompatible if minor versions do not match', () => {
84+
const check = _makeCompatibilityCheck('0.3.3');
85+
assert.ok(!check('0.2.3'));
86+
assert.ok(!check('0.4.3'));
87+
});
88+
89+
it('should be incompatible if minor versions do not match', () => {
90+
const check = _makeCompatibilityCheck('0.3.3');
91+
assert.ok(!check('0.2.3'));
92+
assert.ok(!check('0.4.3'));
93+
});
94+
95+
it('should be incompatible if minor versions match but other patch version is greater than our patch version', () => {
96+
const check = _makeCompatibilityCheck('0.3.3');
97+
assert.ok(!check('0.3.4-alpha'));
98+
assert.ok(!check('0.3.4'));
99+
});
100+
});
101+
});

0 commit comments

Comments
 (0)