2
2
3
3
require ( './core' )
4
4
5
- const os = require ( 'os' )
5
+ const { platform } = require ( 'os' )
6
6
const path = require ( 'path' )
7
7
const semver = require ( 'semver' )
8
8
const externals = require ( '../plugins/externals.json' )
@@ -12,6 +12,8 @@ const Nomenclature = require('../../src/service-naming')
12
12
const { storage } = require ( '../../../datadog-core' )
13
13
const { getInstrumentation } = require ( './helpers/load-inst' )
14
14
15
+ const NODE_PATH_SEP = platform ( ) === 'win32' ? ';' : ':'
16
+
15
17
global . withVersions = withVersions
16
18
global . withExports = withExports
17
19
global . withNamingSchema = withNamingSchema
@@ -141,112 +143,157 @@ function withPeerService (tracer, pluginName, spanGenerationFn, service, service
141
143
} )
142
144
}
143
145
146
+ /**
147
+ * @overload
148
+ * @param {string|Plugin } plugin - The name of the plugin to test, e.g. 'fastify', or the exports object of an already
149
+ * loaded plugin
150
+ * @param {string|string[] } modules - The name(s) of the module(s) to test, e.g. 'fastify' or ['fastify', 'middie']
151
+ * @param {withVersionsCallback } cb - The callback function to call with the test case data
152
+ * @returns {void }
153
+ *
154
+ * @overload
155
+ * @param {string|Plugin } plugin - The name of the plugin to test, e.g. 'fastify', or the exports object of an already
156
+ * loaded plugin
157
+ * @param {string|string[] } modules - The name(s) of the module(s) to test, e.g. 'fastify' or ['fastify', 'middie']
158
+ * @param {string } range - The specific version or range of versions to test, e.g. '>=3' or '3.1.2'
159
+ * @param {withVersionsCallback } cb - The callback function to call with the test case data
160
+ * @returns {void }
161
+ *
162
+ * @typedef {object } Plugin
163
+ * @property {string } name
164
+ * @property {string } version
165
+ *
166
+ * @callback withVersionsCallback
167
+ * @param {string } versionKey - The version string used in the module path
168
+ * @param {string } moduleName - The name of the module being tested
169
+ * @param {string } resolvedVersion - The specific version of the module being tested
170
+ */
144
171
function withVersions ( plugin , modules , range , cb ) {
145
- const instrumentations = typeof plugin === 'string' ? getInstrumentation ( plugin ) : [ ] . concat ( plugin )
146
- const names = instrumentations . map ( instrumentation => instrumentation . name )
172
+ if ( typeof range === 'function' ) {
173
+ cb = range
174
+ range = undefined
175
+ }
147
176
148
- modules = [ ] . concat ( modules )
177
+ const instrumentations = typeof plugin === 'string' ? getInstrumentation ( plugin ) : [ plugin ]
178
+ const names = new Set ( instrumentations . map ( instrumentation => instrumentation . name ) )
149
179
150
- names . forEach ( name => {
151
- if ( externals [ name ] ) {
152
- [ ] . concat ( externals [ name ] ) . forEach ( external => {
153
- instrumentations . push ( external )
154
- } )
180
+ for ( const name of names ) {
181
+ if ( ! externals [ name ] ) continue
182
+ for ( const external of externals [ name ] ) {
183
+ instrumentations . push ( external )
155
184
}
156
- } )
157
-
158
- if ( ! cb ) {
159
- cb = range
160
- range = null
161
185
}
162
186
163
- modules . forEach ( moduleName => {
187
+ for ( const moduleName of Array . isArray ( modules ) ? modules : [ modules ] ) {
164
188
if ( process . env . PACKAGE_NAMES ) {
165
189
const packages = process . env . PACKAGE_NAMES . split ( ',' )
166
190
167
191
if ( ! packages . includes ( moduleName ) ) return
168
192
}
169
193
194
+ /** @type {Map<string, {versionRange: string, versionKey: string, resolvedVersion: string}> } */
170
195
const testVersions = new Map ( )
171
196
172
- instrumentations
173
- . filter ( instrumentation => instrumentation . name === moduleName )
174
- . forEach ( instrumentation => {
175
- const versions = process . env . PACKAGE_VERSION_RANGE
176
- ? [ process . env . PACKAGE_VERSION_RANGE ]
177
- : instrumentation . versions
178
- versions
179
- . filter ( version => ! process . env . RANGE || semver . subset ( version , process . env . RANGE ) )
180
- . forEach ( version => {
181
- if ( version !== '*' ) {
182
- const min = semver . coerce ( version ) . version
197
+ for ( const instrumentation of instrumentations ) {
198
+ if ( instrumentation . name !== moduleName ) continue
199
+
200
+ const versions = process . env . PACKAGE_VERSION_RANGE
201
+ ? [ process . env . PACKAGE_VERSION_RANGE ]
202
+ : instrumentation . versions
203
+
204
+ for ( const version of versions ) {
205
+ if ( process . env . RANGE && ! semver . subset ( version , process . env . RANGE ) ) continue
206
+ if ( version !== '*' ) {
207
+ const result = semver . coerce ( version )
208
+ if ( ! result ) throw new Error ( `Invalid version: ${ version } ` )
209
+ const min = result . version
210
+ testVersions . set ( min , { versionRange : version , versionKey : min , resolvedVersion : min } )
211
+ }
212
+
213
+ const max = require ( getModulePath ( moduleName , version ) ) . version ( )
214
+ testVersions . set ( max , { versionRange : version , versionKey : version , resolvedVersion : max } )
215
+ }
216
+ }
183
217
184
- testVersions . set ( min , { range : version , test : min } )
185
- }
218
+ const testCases = Array . from ( testVersions . values ( ) )
219
+ . filter ( ( { resolvedVersion } ) => ! range || semver . satisfies ( resolvedVersion , range ) )
220
+ . sort ( ( { resolvedVersion } ) => resolvedVersion . localeCompare ( resolvedVersion ) )
186
221
187
- const max = require ( `../../../../versions/${ moduleName } @${ version } ` ) . version ( )
222
+ for ( const testCase of testCases ) {
223
+ const absBasePath = path . resolve ( __dirname , getModulePath ( moduleName , testCase . versionKey ) )
224
+ const absNodeModulesPath = `${ absBasePath } /node_modules`
188
225
189
- testVersions . set ( max , { range : version , test : version } )
190
- } )
191
- } )
226
+ describe ( `with ${ moduleName } ${ testCase . versionRange } (${ testCase . resolvedVersion } )` , ( ) => {
227
+ let nodePath
192
228
193
- Array . from ( testVersions )
194
- . filter ( v => ! range || semver . satisfies ( v [ 0 ] , range ) )
195
- . sort ( v => v [ 0 ] . localeCompare ( v [ 0 ] ) )
196
- . map ( v => Object . assign ( { } , v [ 1 ] , { version : v [ 0 ] } ) )
197
- . forEach ( v => {
198
- const versionPath = path . resolve (
199
- __dirname , '../../../../versions/' ,
200
- `${ moduleName } @${ v . test } /node_modules`
201
- )
202
-
203
- describe ( `with ${ moduleName } ${ v . range } (${ v . version } )` , ( ) => {
204
- let nodePath
205
-
206
- before ( ( ) => {
207
- // set plugin name and version to later report to test agent regarding tested integrations and
208
- // their tested range of versions
209
- const lastPlugin = testedPlugins [ testedPlugins . length - 1 ]
210
- if ( ! lastPlugin || lastPlugin . pluginName !== plugin || lastPlugin . pluginVersion !== v . version ) {
211
- testedPlugins . push ( { pluginName : plugin , pluginVersion : v . version } )
212
- }
213
-
214
- nodePath = process . env . NODE_PATH
215
- process . env . NODE_PATH = [ process . env . NODE_PATH , versionPath ]
216
- . filter ( x => x && x !== 'undefined' )
217
- . join ( os . platform ( ) === 'win32' ? ';' : ':' )
218
-
219
- require ( 'module' ) . Module . _initPaths ( )
220
- } )
229
+ before ( ( ) => {
230
+ // set plugin name and version to later report to test agent regarding tested integrations and their tested
231
+ // range of versions
232
+ const lastPlugin = testedPlugins . at ( - 1 )
233
+ if (
234
+ ! lastPlugin || lastPlugin . pluginName !== plugin || lastPlugin . pluginVersion !== testCase . resolvedVersion
235
+ ) {
236
+ testedPlugins . push ( { pluginName : plugin , pluginVersion : testCase . resolvedVersion } )
237
+ }
238
+
239
+ nodePath = process . env . NODE_PATH
240
+ process . env . NODE_PATH += `${ NODE_PATH_SEP } ${ absNodeModulesPath } `
241
+
242
+ require ( 'module' ) . Module . _initPaths ( )
243
+ } )
221
244
222
- cb ( v . test , moduleName , v . version )
245
+ cb ( testCase . versionKey , moduleName , testCase . resolvedVersion )
223
246
224
- after ( ( ) => {
225
- process . env . NODE_PATH = nodePath
226
- require ( 'module' ) . Module . _initPaths ( )
227
- } )
247
+ after ( ( ) => {
248
+ process . env . NODE_PATH = nodePath
249
+ require ( 'module' ) . Module . _initPaths ( )
228
250
} )
229
251
} )
230
- } )
252
+ }
253
+ }
231
254
}
232
255
233
- function withExports ( moduleName , version , exportNames , versionRange , fn ) {
234
- const getExport = ( ) => require ( `../../../../versions/${ moduleName } @${ version } ` ) . get ( )
235
- describe ( 'with the default export' , ( ) => fn ( getExport ) )
236
-
256
+ /**
257
+ * @overload
258
+ * @param {string } moduleName - The name of the module being tested
259
+ * @param {string } version - The specific version of the module being tested
260
+ * @param {string[] } exportNames - The names of the module exports to be tested (the default export will always be
261
+ * tested)
262
+ * @param {withExportsCallback } cb
263
+ *
264
+ * @overload
265
+ * @param {string } moduleName - The name of the module being tested
266
+ * @param {string } version - The specific version of the module being tested
267
+ * @param {string[] } exportNames - The names of the module exports to be tested (the default export will always be
268
+ * tested)
269
+ * @param {string } versionRange - The version range in which the given version should reside. If not within this range,
270
+ * only the default export will be tested.
271
+ * @param {withExportsCallback } cb
272
+ *
273
+ * @callback withExportsCallback
274
+ * @param {function } getExport - A function that returns the module export to test
275
+ */
276
+ function withExports ( moduleName , version , exportNames , versionRange , cb ) {
237
277
if ( typeof versionRange === 'function' ) {
238
- fn = versionRange
278
+ cb = versionRange
239
279
versionRange = '*'
240
280
}
241
281
282
+ const getExport = ( ) => require ( getModulePath ( moduleName , version ) ) . get ( )
283
+ describe ( 'with the default export' , ( ) => cb ( getExport ) )
284
+
242
285
if ( ! semver . intersects ( version , versionRange ) ) return
243
286
244
287
for ( const exportName of exportNames ) {
245
- const getExport = ( ) => require ( `../../../../versions/ ${ moduleName } @ ${ version } ` ) . get ( ) [ exportName ]
246
- describe ( `with exports.${ exportName } ` , ( ) => fn ( getExport ) )
288
+ const getExport = ( ) => require ( getModulePath ( moduleName , version ) ) . get ( ) [ exportName ]
289
+ describe ( `with exports.${ exportName } ` , ( ) => cb ( getExport ) )
247
290
}
248
291
}
249
292
293
+ function getModulePath ( moduleName , version ) {
294
+ return `../../../../versions/${ moduleName } @${ version } `
295
+ }
296
+
250
297
exports . mochaHooks = {
251
298
afterEach ( ) {
252
299
agent . reset ( )
0 commit comments