-
Notifications
You must be signed in to change notification settings - Fork 404
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
test: added unit tests for MySQL instrumentation
- Loading branch information
1 parent
d1781b1
commit b693ba0
Showing
13 changed files
with
1,142 additions
and
5 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,39 @@ | ||
/* | ||
* Copyright 2023 New Relic Corporation. All rights reserved. | ||
* SPDX-License-Identifier: Apache-2.0 | ||
*/ | ||
|
||
'use strict' | ||
|
||
const tap = require('tap') | ||
const sinon = require('sinon') | ||
const instrumentation = require('../../../../lib/instrumentation/mysql/mysql') | ||
|
||
tap.test('describeQuery', (t) => { | ||
t.autoend() | ||
|
||
t.test('should pull the configuration for the query segment', (t) => { | ||
const mockShim = { | ||
logger: { | ||
trace: sinon.stub().returns() | ||
}, | ||
isString: sinon.stub().returns(true), | ||
isArray: sinon.stub().returns(false) | ||
} | ||
|
||
const mockArgs = ['SELECT * FROM foo', sinon.stub()] | ||
|
||
const result = instrumentation.describePoolQuery(mockShim, null, null, mockArgs) | ||
t.same(result, { | ||
stream: true, | ||
query: null, | ||
callback: 1, | ||
name: 'MySQL Pool#query', | ||
record: false | ||
}) | ||
|
||
t.ok(mockShim.logger.trace.calledWith('Recording pool query')) | ||
|
||
t.end() | ||
}) | ||
}) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,51 @@ | ||
/* | ||
* Copyright 2023 New Relic Corporation. All rights reserved. | ||
* SPDX-License-Identifier: Apache-2.0 | ||
*/ | ||
|
||
'use strict' | ||
|
||
const tap = require('tap') | ||
const sinon = require('sinon') | ||
const instrumentation = require('../../../../lib/instrumentation/mysql/mysql') | ||
const symbols = require('../../../../lib/symbols') | ||
|
||
tap.test('describeQuery', (t) => { | ||
t.autoend() | ||
|
||
t.test('should pull the configuration for the query segment', (t) => { | ||
const mockShim = { | ||
logger: { | ||
trace: sinon.stub().returns() | ||
}, | ||
isString: sinon.stub().returns(true), | ||
isArray: sinon.stub().returns(false) | ||
} | ||
|
||
const mockArgs = ['SELECT * FROM foo', sinon.stub()] | ||
|
||
instrumentation[symbols.databaseName] = 'my-db-name' | ||
instrumentation.config = { | ||
host: 'example.com', | ||
port: '1234' | ||
} | ||
const result = instrumentation.describeQuery(mockShim, null, null, mockArgs) | ||
t.same(result, { | ||
stream: true, | ||
query: 'SELECT * FROM foo', | ||
callback: 1, | ||
parameters: { host: 'example.com', port_path_or_id: '1234', database_name: 'my-db-name' }, | ||
record: true | ||
}) | ||
|
||
t.ok(mockShim.logger.trace.calledWith('Recording query')) | ||
t.ok( | ||
mockShim.logger.trace.calledWith( | ||
{ query: true, callback: true, parameters: true }, | ||
'Query segment descriptor' | ||
) | ||
) | ||
|
||
t.end() | ||
}) | ||
}) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,51 @@ | ||
/* | ||
* Copyright 2023 New Relic Corporation. All rights reserved. | ||
* SPDX-License-Identifier: Apache-2.0 | ||
*/ | ||
|
||
'use strict' | ||
|
||
const tap = require('tap') | ||
const sinon = require('sinon') | ||
const instrumentation = require('../../../../lib/instrumentation/mysql/mysql') | ||
|
||
tap.test('extractQueryArgs', (t) => { | ||
t.autoend() | ||
|
||
let mockShim | ||
let mockArgs | ||
let mockCallback | ||
|
||
t.beforeEach(() => { | ||
mockShim = { | ||
isString: sinon.stub().returns(), | ||
isArray: sinon.stub().returns() | ||
} | ||
|
||
mockArgs = [] | ||
|
||
mockCallback = sinon.stub() | ||
}) | ||
|
||
t.test('should extract the query and callback when the first arg is a string', (t) => { | ||
mockShim.isString.returns(true) | ||
mockArgs.push('SELECT * FROM foo', mockCallback) | ||
|
||
const results = instrumentation.extractQueryArgs(mockShim, mockArgs) | ||
t.same(results, { query: 'SELECT * FROM foo', callback: 1 }) | ||
|
||
t.end() | ||
}) | ||
|
||
t.test('should extract the query and callback when the first arg is an object property', (t) => { | ||
mockShim.isString.returns(false) | ||
mockShim.isArray.returns(true) | ||
|
||
mockArgs.push({ sql: 'SELECT * FROM foo' }, [], mockCallback) | ||
|
||
const results = instrumentation.extractQueryArgs(mockShim, mockArgs) | ||
t.same(results, { query: 'SELECT * FROM foo', callback: 2 }) | ||
|
||
t.end() | ||
}) | ||
}) |
107 changes: 107 additions & 0 deletions
107
test/unit/instrumentation/mysql/getInstanceParameters.test.js
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,107 @@ | ||
/* | ||
* Copyright 2023 New Relic Corporation. All rights reserved. | ||
* SPDX-License-Identifier: Apache-2.0 | ||
*/ | ||
|
||
'use strict' | ||
|
||
const tap = require('tap') | ||
const sinon = require('sinon') | ||
const instrumentation = require('../../../../lib/instrumentation/mysql/mysql') | ||
const symbols = require('../../../../lib/symbols') | ||
|
||
tap.test('getInstanceParameters', (t) => { | ||
t.autoend() | ||
|
||
let mockShim | ||
let mockQueryable | ||
let mockQuery | ||
|
||
t.beforeEach(() => { | ||
mockShim = { | ||
logger: { | ||
trace: sinon.stub().returns() | ||
} | ||
} | ||
|
||
mockQueryable = {} | ||
|
||
mockQuery = 'SELECT * FROM foo' | ||
}) | ||
|
||
t.test('should log if unable to find configuration to pull info', (t) => { | ||
const result = instrumentation.getInstanceParameters(mockShim, mockQueryable, mockQuery) | ||
|
||
t.same( | ||
result, | ||
{ host: null, port_path_or_id: null, database_name: null }, | ||
'should return the default parameters' | ||
) | ||
t.ok( | ||
mockShim.logger.trace.calledWith('No query config detected, not collecting db instance data'), | ||
'should log' | ||
) | ||
|
||
t.end() | ||
}) | ||
|
||
t.test('should favor connectionConfig over config', (t) => { | ||
mockQueryable = { | ||
config: { | ||
port: '1234', | ||
connectionConfig: { | ||
port: '5678' | ||
} | ||
} | ||
} | ||
|
||
const result = instrumentation.getInstanceParameters(mockShim, mockQueryable, mockQuery) | ||
t.equal(result.port_path_or_id, '5678') | ||
t.end() | ||
}) | ||
|
||
t.test('should favor the symbol DB name over config', (t) => { | ||
mockQueryable = { | ||
config: { | ||
database: 'database-a' | ||
} | ||
} | ||
|
||
mockQueryable[symbols.databaseName] = 'database-b' | ||
|
||
const result = instrumentation.getInstanceParameters(mockShim, mockQueryable, mockQuery) | ||
t.equal(result.database_name, 'database-b') | ||
t.end() | ||
}) | ||
|
||
t.test('should set the appropriate parameters for "normal" connections', (t) => { | ||
mockQueryable = { | ||
config: { | ||
database: 'test-database', | ||
host: 'example.com', | ||
port: '1234' | ||
} | ||
} | ||
|
||
const result = instrumentation.getInstanceParameters(mockShim, mockQueryable, mockQuery) | ||
t.same(result, { host: 'example.com', port_path_or_id: '1234', database_name: 'test-database' }) | ||
t.end() | ||
}) | ||
|
||
t.test('should set the appropriate parameters for unix socket connections', (t) => { | ||
mockQueryable = { | ||
config: { | ||
database: 'test-database', | ||
socketPath: '/var/run/mysqld/mysqld.sock' | ||
} | ||
} | ||
|
||
const result = instrumentation.getInstanceParameters(mockShim, mockQueryable, mockQuery) | ||
t.same(result, { | ||
host: 'localhost', | ||
port_path_or_id: '/var/run/mysqld/mysqld.sock', | ||
database_name: 'test-database' | ||
}) | ||
t.end() | ||
}) | ||
}) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,80 @@ | ||
/* | ||
* Copyright 2023 New Relic Corporation. All rights reserved. | ||
* SPDX-License-Identifier: Apache-2.0 | ||
*/ | ||
|
||
'use strict' | ||
|
||
const tap = require('tap') | ||
const sinon = require('sinon') | ||
const proxyquire = require('proxyquire') | ||
|
||
const symbols = require('../../../../lib/symbols') | ||
|
||
tap.test('mysql instrumentation', (t) => { | ||
t.autoend() | ||
|
||
let mockShim | ||
let mockMysql | ||
let instrumentation | ||
|
||
t.beforeEach(() => { | ||
mockShim = { | ||
MYSQL: 'test-mysql', | ||
setDatastore: sinon.stub().returns(), | ||
wrapReturn: sinon.stub().returns(), | ||
isWrapped: sinon.stub().returns(), | ||
require: sinon.stub().returns(mockMysql) | ||
} | ||
|
||
mockMysql = { | ||
createConnection: sinon.stub().returns(), | ||
createPool: sinon.stub().returns(), | ||
createPoolCluster: sinon.stub().returns() | ||
} | ||
|
||
instrumentation = proxyquire('../../../../lib/instrumentation/mysql/mysql', {}) | ||
}) | ||
|
||
t.test('callbackInitialize should set the datastore and symbols', (t) => { | ||
instrumentation.callbackInitialize(mockShim, mockMysql) | ||
|
||
t.ok(mockShim.setDatastore.calledWith('test-mysql'), 'should set the datastore to mysql') | ||
t.equal( | ||
mockShim[symbols.wrappedPoolConnection], | ||
false, | ||
'should default the wrappedPoolConnection symbol to false' | ||
) | ||
t.end() | ||
}) | ||
|
||
t.test( | ||
'promiseInitialize not should call callbackInitialized if createConnection is already wrapped', | ||
(t) => { | ||
instrumentation.callbackInitialize = sinon.stub().returns() | ||
mockShim.isWrapped.returns(true) | ||
instrumentation.promiseInitialize(mockShim, mockMysql) | ||
|
||
t.notOk( | ||
mockShim[symbols.wrappedPoolConnection], | ||
|
||
'should not have applied the symbol' | ||
) | ||
t.end() | ||
} | ||
) | ||
|
||
t.test('promiseInitialize should call callbackInitialized', (t) => { | ||
instrumentation.callbackInitialize = sinon.stub().returns() | ||
mockShim.isWrapped.returns(false) | ||
instrumentation.promiseInitialize(mockShim, mockMysql) | ||
|
||
t.ok(mockShim.setDatastore.calledWith('test-mysql'), 'should set the datastore to mysql') | ||
t.equal( | ||
mockShim[symbols.wrappedPoolConnection], | ||
false, | ||
'should default the wrappedPoolConnection symbol to false' | ||
) | ||
t.end() | ||
}) | ||
}) |
Oops, something went wrong.