Skip to content

Commit fe7c4f6

Browse files
committed
test(instrumentations): make the instrumentation tests for mysql, pg and mongodb run on CI
1 parent 22a9b32 commit fe7c4f6

23 files changed

Lines changed: 556 additions & 154 deletions

.editorconfig

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -11,11 +11,11 @@ indent_style = space
1111
indent_size = 4
1212
trim_trailing_whitespace = true
1313

14-
[Makefile]
14+
[{Makefile,**.mk}]
1515
indent_style = tab
1616
indent_size = 4
1717

18-
[*.{js,json,yaml,yml}]
18+
[**.{js,json,yaml,yml}]
1919
indent_style = space
2020
indent_size = 2
2121
charset = utf-8

circle.yml

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,12 +2,14 @@ machine:
22
node:
33
version: 4.4.4
44
environment:
5+
NODE_VERSION_FW: 6
56
NODE_VERSIONS: 0.12 4 5 6 7
67
RELEASE_REPONAME: trace-nodejs
78
RELEASE_BRANCH: master
89

910
dependencies:
1011
pre:
12+
- NODE_VERSION=$NODE_VERSION_FW ./scripts/run-ci.sh ./scripts/install-node.sh
1113
- ./scripts/run-ci.sh ./scripts/node-matrix.sh ./scripts/install-node.sh
1214
override:
1315
- exit 0
@@ -16,6 +18,7 @@ test:
1618
override:
1719
- ./scripts/run-ci.sh ./scripts/node-matrix.sh ./scripts/prepare.sh ./scripts/lint.sh ./scripts/test-unit.sh ./scripts/test-cover.sh ./scripts/test-e2e.sh:
1820
parallel: true
21+
- ./scripts/run-ci.sh ./scripts/test-instrumentations.sh
1922

2023
deployment:
2124
release:

package.json

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "@risingstack/trace",
3-
"version": "3.0.2",
3+
"version": "3.1.0",
44
"author": "RisingStack, Inc.",
55
"license": "SEE LICENSE IN LICENSE",
66
"contributors": "RisingStack",
@@ -17,7 +17,7 @@
1717
],
1818
"release": {
1919
"verifyConditions": {
20-
"path": "./node_modules/semantic-release/src/lib/plugin-noop.js"
20+
"path": "./node_modules/semantic-release/src/lib/plugin-noop.js"
2121
}
2222
},
2323
"main": "lib/index.js",

scripts/test-instrumentations.sh

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
#!/usr/bin/env bash
2+
set -e
3+
source ./scripts/util/env-node.sh
4+
5+
nvm use $NODE_VERSION_FW
6+
7+
if [[ -z $INSTR_TARGET_VERSIONS ]]; then
8+
INSTR_TARGET_VERSIONS=some
9+
fi
10+
11+
cd ./test/instrumentations
12+
make test TARGET_VERSIONS=$INSTR_TARGET_VERSIONS

scripts/util/env-essential.sh

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@ if [[ -z $ENV_ESSENTIAL_SOURCED ]]; then
2222
if [[ -n "$REPOSITORY_URL" ]] && [[ -n "$GH_TOKEN" ]]; then
2323
export REPOSITORY_PUSH_URL=$(echo $REPOSITORY_URL | sed -r "s|https?://(.+)/|https://risingbot:$GH_TOKEN@\1/|")
2424
fi
25+
export NODE_VERSION_FW=6
2526
else
2627
# local
2728
export CURRENT_BRANCH=$(git branch --no-color | awk '/\*/{ print $2 }')
@@ -35,6 +36,7 @@ if [[ -z $ENV_ESSENTIAL_SOURCED ]]; then
3536
export COMMIT_AUTHOR=$(git log -1 --pretty=%an)
3637
export REPOSITORY_URL=$(git config --get remote.origin.url)
3738
export REPOSITORY_PUSH_URL=$REPOSITORY_URL
39+
export NODE_VERSION_FW=6
3840
fi
3941
fi
4042

test/instrumentations/Makefile

Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
.PHONY: before test
2+
3+
cur_path := $(abspath $(lastword $(MAKEFILE_LIST)))
4+
cur_dir := $(dir $(cur_path))
5+
cur_base := $(notdir $(cur_path))
6+
7+
# Use this variable for invoking the test runner
8+
export MOCHA := $(shell npm bin)/mocha
9+
10+
# You can have multiple set of target versions tested for each library.
11+
# Obviously we cannot accept a list of concrete versions, because then
12+
# it should be listed for every library. Instead, there are 3 target sets
13+
# all: all versions
14+
# some: important / recent versions
15+
# one: most important version, stable version for smoke test
16+
#
17+
# Default is all, but it can be overriden from the command line
18+
TARGET_VERSIONS?=all
19+
configure_targets = $(if $(filter one,$(TARGET_VERSIONS)),$(1),$(if $(filter some,$(TARGET_VERSIONS)),$(2),)$(if $(filter all,$(TARGET_VERSIONS)),$(3),))
20+
21+
# Every library instrumentation should have a subrecipe in its directory
22+
# containing the target test_suite_<LIBRARY_NAME>
23+
# and should append <LIBRARY_NAME> to the variable `targets`
24+
include $(cur_dir)/*/*.mk
25+
26+
# We have a common package json for every test suite, because it is much more
27+
# fast this way. Of course you could install other dependencies in the test
28+
# suites. This is actually needed for versioning.
29+
before :
30+
npm i
31+
32+
test : $(targets:%=test_suite_%)
33+
34+
# On best practices for writing a test suite for an instrumentation, please
35+
# see mysql/mysql.mk

test/instrumentations/amqp/amqp.spec.cls.js

Lines changed: 0 additions & 27 deletions
This file was deleted.
Lines changed: 54 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,54 @@
1+
target := pg
2+
3+
all = 0.2.0 0.2.1 0.3.0 0.3.2 0.4.0 0.4.2 0.5.0 0.5.1
4+
some = 0.3.0 0.4.0 0.5.0
5+
one = 0.4.0
6+
7+
versions := $(call configure_targets,$(one),$(some),$(all))
8+
9+
targets := $(targets) $(target)
10+
11+
# set up as target specific variables to avoid collision in other
12+
# makefiles
13+
test_suite_$(target) : target := $(target)
14+
test_suite_$(target) : versions := $(versions)
15+
test_suite_$(target) : cur_path := $(abspath $(lastword $(MAKEFILE_LIST)))
16+
test_suite_$(target) : cur_dir := $(dir $(cur_path))
17+
test_suite_$(target) : cur_base := $(notdir $(cur_path))
18+
test_suite_$(target) : amqp_url := amqp://localhost
19+
test_suite_$(target) : errors := 0
20+
21+
# normally all tasks should be phony
22+
.PHONY : before_$(target) \
23+
$(versions:%=before_version_$(target)_%) \
24+
$(versions:%=test_$(target)_%) \
25+
$(versions:%=after_version_$(target)_%) \
26+
after_$(target) \
27+
test_suite_$(target)
28+
29+
# 'this should run before the test
30+
before_$(target) : before
31+
@echo '*---------------*'
32+
@echo '| amqplib |'
33+
@echo '*---------------*'
34+
AMQP_URL=$(amqp_url) $(addprefix $(cur_dir), verify.js)
35+
36+
# this should run after `before` for each of the version targets
37+
# before the test
38+
$(versions:%=before_version_$(target)_%) : before_$(target)
39+
npm i amqplib@$(subst before_version_$(target)_,,$@)
40+
41+
42+
# run the test for each of the versions
43+
$(versions:%=test_$(target)_%) : test_% : before_version_%
44+
AMQP_URL=$(db_host) $(MOCHA) $(addprefix $(cur_dir), *.spec.js) || exit 0;
45+
46+
# this should run before `after` for each of the version targets
47+
# after the test suite
48+
$(versions:%=after_version_$(target)_%) : $(versions:%=test_$(target)_%)
49+
50+
# this should run after the test
51+
after_$(target) : $(versions:%=after_version_$(target)_%)
52+
53+
## this is the whole test suite
54+
test_suite_$(target) : after_$(target)

test/instrumentations/amqp/amqplib.spec.js renamed to test/instrumentations/amqplib/amqplib.spec.js

Lines changed: 88 additions & 41 deletions
Original file line numberDiff line numberDiff line change
@@ -1,42 +1,73 @@
11
'use strict'
22

3+
require('../test-setup.spec.js')
4+
35
var expect = require('chai').expect
46
var wrapper = require('@risingstack/trace/lib/instrumentations/amqplib')
57
var microtime = require('@risingstack/trace/lib/optionalDependencies/microtime')
8+
var Storage = require('@risingstack/trace/lib/agent/storage')
9+
10+
describe.only('amqplib', function () {
11+
var fakeAgent
612

7-
describe('amqplib module wrapper', function () {
813
beforeEach(function () {
9-
delete require.cache[require.resolve('amqplib/lib/connection')]
10-
delete require.cache[require.resolve('amqplib/lib/callback_model')]
11-
delete require.cache[require.resolve('amqplib/lib/channel_model')]
12-
delete require.cache[require.resolve('amqplib/callback_api')]
13-
delete require.cache[require.resolve('amqplib/channel_api')]
14-
delete require.cache[require.resolve('amqplib')]
14+
fakeAgent = {
15+
incomingEdgeMetrics: {
16+
report: this.sandbox.spy()
17+
},
18+
getRequestId: this.sandbox.spy(),
19+
generateRequestId: this.sandbox.stub().returns('42'),
20+
generateCommId: this.sandbox.stub().returns('52'),
21+
getServiceKey: this.sandbox.stub().returns('62'),
22+
storage: new Storage()
23+
}
24+
this.sandbox.stub(microtime, 'now').returns(42)
1525
})
1626

17-
describe('channel api', function () {
27+
describe('channel api module wrapper', function () {
1828
beforeEach(function () {
29+
wrapper.instrumentations[5].post(require('amqplib/lib/connection'), fakeAgent)
30+
wrapper.instrumentations[3].post(require('amqplib/lib/channel_model'), fakeAgent)
31+
})
32+
33+
afterEach(function () {
1934
delete require.cache[require.resolve('amqplib/lib/connection')]
2035
delete require.cache[require.resolve('amqplib/lib/channel_model')]
2136
delete require.cache[require.resolve('amqplib/channel_api')]
2237
delete require.cache[require.resolve('amqplib')]
2338
})
2439

25-
it('instruments publish - consume', function (done) {
26-
this.sandbox.stub(microtime, 'now').returns(42)
27-
var fakeAgent = {
28-
incomingEdgeMetrics: {
29-
report: this.sandbox.spy()
30-
},
31-
getRequestId: this.sandbox.spy(),
32-
generateRequestId: this.sandbox.stub().returns('42'),
33-
generateCommId: this.sandbox.stub().returns('52'),
34-
getServiceKey: this.sandbox.stub().returns('62')
35-
}
36-
wrapper.instrumentations[5].post(require('amqplib/lib/connection'), fakeAgent)
37-
wrapper.instrumentations[3].post(require('amqplib/lib/channel_model'), fakeAgent)
40+
it('looks transparent', function (done) {
41+
var open = require('amqplib').connect(process.env.AMQP_URL)
42+
open.then(function (conn) {
43+
return conn.createChannel()
44+
}).then(function (ch) {
45+
ch.assertQueue('test').then(function (ok) {
46+
return ch.sendToQueue('test', new Buffer('something'))
47+
}).catch(function (err) {
48+
done(err)
49+
}).then(function () {
50+
ch.consume('test', function (msg) {
51+
try {
52+
ch.ack(msg)
53+
expect(fakeAgent.incomingEdgeMetrics.report).to.have.been.calledWith({
54+
protocol: 'amqp',
55+
serviceKey: 62,
56+
transportDelay: 0
57+
})
58+
ch.close()
59+
done()
60+
} catch (err) {
61+
ch.close()
62+
done(err)
63+
}
64+
})
65+
})
66+
})
67+
})
3868

39-
var open = require('amqplib').connect('amqp://localhost')
69+
it('is instrumented for incoming edges', function (done) {
70+
var open = require('amqplib').connect(process.env.AMQP_URL)
4071

4172
// Publisher
4273
open.then(function (conn) {
@@ -55,9 +86,10 @@ describe('amqplib module wrapper', function () {
5586
serviceKey: 62,
5687
transportDelay: 0
5788
})
58-
expect(msg.content.toString()).to.eql('something')
89+
ch.close()
5990
done()
6091
} catch (err) {
92+
ch.close()
6193
done(err)
6294
}
6395
})
@@ -66,35 +98,49 @@ describe('amqplib module wrapper', function () {
6698
})
6799
})
68100

69-
describe('callback api', function () {
101+
describe('callback api module wrapper', function () {
70102
beforeEach(function () {
103+
wrapper.instrumentations[5].post(require('amqplib/lib/connection'), fakeAgent)
104+
wrapper.instrumentations[4].post(require('amqplib/lib/callback_model'), fakeAgent)
105+
})
106+
107+
afterEach(function () {
71108
delete require.cache[require.resolve('amqplib/lib/connection')]
72109
delete require.cache[require.resolve('amqplib/lib/callback_model')]
73110
delete require.cache[require.resolve('amqplib/callback_api')]
74111
delete require.cache[require.resolve('amqplib')]
75112
})
76113

77-
it('instruments publish - consume', function (done) {
78-
this.sandbox.stub(microtime, 'now').returns(42)
79-
var fakeAgent = {
80-
incomingEdgeMetrics: {
81-
report: this.sandbox.spy()
82-
},
83-
getRequestId: this.sandbox.spy(),
84-
generateRequestId: this.sandbox.stub().returns('42'),
85-
generateCommId: this.sandbox.stub().returns('52'),
86-
getServiceKey: this.sandbox.stub().returns('62')
87-
}
88-
wrapper.instrumentations[5].post(require('amqplib/lib/connection'), fakeAgent)
89-
wrapper.instrumentations[4].post(require('amqplib/lib/callback_model'), fakeAgent)
114+
it('looks transparent', function (done) {
115+
require('amqplib/callback_api')
116+
.connect(process.env.AMQP_URL, function (err, conn) {
117+
if (err != null) done(err)
118+
conn.createChannel(onOpen)
119+
function onOpen (err, ch) {
120+
if (err != null) done(err)
121+
ch.consume('test-cb', function (msg) {
122+
try {
123+
ch.ack(msg)
124+
expect(msg.content.toString()).to.eql('callback')
125+
ch.close()
126+
done()
127+
} catch (err) {
128+
ch.close()
129+
done(err)
130+
}
131+
})
132+
ch.sendToQueue('test-cb', new Buffer('callback'))
133+
}
134+
})
135+
})
90136

137+
it('is instrumented for incoming edges', function (done) {
91138
require('amqplib/callback_api')
92-
.connect('amqp://localhost', function (err, conn) {
139+
.connect(process.env.AMQP_URL, function (err, conn) {
93140
if (err != null) done(err)
94141
conn.createChannel(onOpen)
95142
function onOpen (err, ch) {
96143
if (err != null) done(err)
97-
ch.assertQueue('test-cb')
98144
ch.consume('test-cb', function (msg) {
99145
try {
100146
ch.ack(msg)
@@ -103,13 +149,14 @@ describe('amqplib module wrapper', function () {
103149
serviceKey: 62,
104150
transportDelay: 0
105151
})
106-
expect(msg.content.toString()).to.eql('callback')
152+
ch.close()
107153
done()
108154
} catch (err) {
155+
ch.close()
109156
done(err)
110157
}
111158
})
112-
ch.sendToQueue('test-cb', new Buffer('callback'))
159+
ch.sendToQueue('test-cb', new Buffer(''))
113160
}
114161
})
115162
})

0 commit comments

Comments
 (0)