Skip to content

Commit

Permalink
Merge branch 'master' into ugaitz/rasp-blocking
Browse files Browse the repository at this point in the history
  • Loading branch information
uurien authored Jul 1, 2024
2 parents 194ec41 + 5daf54d commit b9a5d4d
Show file tree
Hide file tree
Showing 24 changed files with 906 additions and 26 deletions.
17 changes: 17 additions & 0 deletions .github/workflows/project.yml
Original file line number Diff line number Diff line change
Expand Up @@ -110,6 +110,23 @@ jobs:
CYPRESS_VERSION: ${{ matrix.cypress-version }}
NODE_OPTIONS: '-r ./ci/init'

integration-vitest:
runs-on: ubuntu-latest
env:
DD_SERVICE: dd-trace-js-integration-tests
DD_CIVISIBILITY_AGENTLESS_ENABLED: 1
DD_API_KEY: ${{ secrets.DD_API_KEY_CI_APP }}
steps:
- uses: actions/checkout@v4
- uses: ./.github/actions/node/setup
- run: yarn install
- uses: actions/setup-node@v3
with:
node-version: 20
- run: yarn test:integration:vitest
env:
NODE_OPTIONS: '-r ./ci/init'

lint:
runs-on: ubuntu-latest
steps:
Expand Down
5 changes: 3 additions & 2 deletions .github/workflows/system-tests.yml
Original file line number Diff line number Diff line change
Expand Up @@ -86,9 +86,10 @@ jobs:
parametric:
needs:
- build-artifacts
uses: DataDog/system-tests/.github/workflows/system-tests.yml@main
uses: DataDog/system-tests/.github/workflows/run-parametric.yml@main
secrets: inherit
with:
scenarios: PARAMETRIC
library: nodejs
binaries_artifact: system_tests_binaries
_experimental_job_count: 8
_experimental_job_matrix: '[1,2,3,4,5,6,7,8]'
2 changes: 2 additions & 0 deletions docs/test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -363,6 +363,8 @@ tracer.use('sharedb');
tracer.use('sharedb', sharedbOptions);
tracer.use('tedious');
tracer.use('undici');
tracer.use('vitest');
tracer.use('vitest', { service: 'vitest-service' });
tracer.use('winston');

tracer.use('express', false)
Expand Down
2 changes: 1 addition & 1 deletion ext/exporters.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ declare const exporters: {
DATADOG: 'datadog',
AGENT_PROXY: 'agent_proxy',
JEST_WORKER: 'jest_worker',
CUCUMBER_WORKER: 'cucumber_worker'
CUCUMBER_WORKER: 'cucumber_worker',
MOCHA_WORKER: 'mocha_worker'
}

Expand Down
9 changes: 8 additions & 1 deletion index.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -198,6 +198,7 @@ interface Plugins {
"sharedb": tracer.plugins.sharedb;
"tedious": tracer.plugins.tedious;
"undici": tracer.plugins.undici;
"vitest": tracer.plugins.vitest;
"winston": tracer.plugins.winston;
}

Expand Down Expand Up @@ -1556,7 +1557,7 @@ declare namespace tracer {

/**
* This plugin automatically instruments the
* [jest](https://github.com/facebook/jest) module.
* [jest](https://github.com/jestjs/jest) module.
*/
interface jest extends Integration {}

Expand Down Expand Up @@ -1839,6 +1840,12 @@ declare namespace tracer {
*/
interface undici extends HttpClient {}

/**
* This plugin automatically instruments the
* [vitest](https://github.com/vitest-dev/vitest) module.
*/
interface vitest extends Integration {}

/**
* This plugin patches the [winston](https://github.com/winstonjs/winston)
* to automatically inject trace identifiers in log records when the
Expand Down
3 changes: 3 additions & 0 deletions integration-tests/ci-visibility/vitest-tests/sum.mjs
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
export function sum (a, b) {
return a + b
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
import { describe, test, expect, beforeEach, afterEach } from 'vitest'
import { sum } from './sum'

describe('context', () => {
beforeEach(() => {
throw new Error('failed before each')
})
test('can report failed test', () => {
expect(sum(1, 2)).to.equal(4)
})
test('can report more', () => {
expect(sum(1, 2)).to.equal(3)
})
})

describe('other context', () => {
afterEach(() => {
throw new Error('failed after each')
})
test('can report passed test', () => {
expect(sum(1, 2)).to.equal(3)
})
test('can report more', () => {
expect(sum(1, 2)).to.equal(3)
})
})
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
import { describe, test, expect, beforeEach, afterEach } from 'vitest'
import { sum } from './sum'

let preparedValue = 1

describe('test-visibility-failed-suite-first-describe', () => {
beforeEach(() => {
preparedValue = 2
})
test('can report failed test', () => {
expect(sum(1, 2)).to.equal(4)
})
test('can report more', () => {
expect(sum(1, 2)).to.equal(3)
expect(preparedValue).to.equal(2)
})
})

describe('test-visibility-failed-suite-second-describe', () => {
afterEach(() => {
preparedValue = 1
})
test('can report passed test', () => {
expect(sum(1, 2)).to.equal(3)
})
test('can report more', () => {
expect(sum(1, 2)).to.equal(3)
})
})
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
import { describe, test, expect } from 'vitest'
import { sum } from './sum'

describe('context', () => {
test('can report passed test', () => {
expect(sum(1, 2)).to.equal(3)
})
test('can report more', () => {
expect(sum(1, 2)).to.equal(3)
})
})

describe('other context', () => {
test('can report passed test', () => {
expect(sum(1, 2)).to.equal(3)
})
test('can report more', () => {
expect(sum(1, 2)).to.equal(3)
})
test.skip('can skip', () => {
expect(sum(1, 2)).to.equal(3)
})
test.todo('can todo', () => {
expect(sum(1, 2)).to.equal(3)
})
// eslint-disable-next-line
test('can programmatic skip', (context) => {
// eslint-disable-next-line
context.skip()
expect(sum(1, 2)).to.equal(3)
})
})
6 changes: 0 additions & 6 deletions integration-tests/esbuild/basic-test.js
Original file line number Diff line number Diff line change
@@ -1,11 +1,5 @@
#!/usr/bin/env node

// TODO: add support for Node.js v14.17+ and v16.0+
if (Number(process.versions.node.split('.')[0]) < 16) {
console.error(`Skip esbuild test for node@${process.version}`) // eslint-disable-line no-console
process.exit(0)
}

const tracer = require('../../').init() // dd-trace

const assert = require('assert')
Expand Down
9 changes: 9 additions & 0 deletions integration-tests/vitest.config.mjs
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
import { defineConfig } from 'vite'

export default defineConfig({
test: {
include: [
'ci-visibility/vitest-tests/test-visibility*'
]
}
})
137 changes: 137 additions & 0 deletions integration-tests/vitest/vitest.spec.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,137 @@
'use strict'

const { exec } = require('child_process')

const { assert } = require('chai')

const {
createSandbox,
getCiVisAgentlessConfig
} = require('../helpers')
const { FakeCiVisIntake } = require('../ci-visibility-intake')
const {
TEST_STATUS,
TEST_TYPE
} = require('../../packages/dd-trace/src/plugins/util/test')

// tested with 1.6.0
const versions = ['latest']

versions.forEach((version) => {
describe(`vitest@${version}`, () => {
let sandbox, cwd, receiver, childProcess

before(async function () {
sandbox = await createSandbox([`vitest@${version}`], true)
cwd = sandbox.folder
})

after(async () => {
await sandbox.remove()
})

beforeEach(async function () {
receiver = await new FakeCiVisIntake().start()
})

afterEach(async () => {
childProcess.kill()
await receiver.stop()
})

it('can run and report tests', (done) => {
receiver.gatherPayloadsMaxTimeout(({ url }) => url === '/api/v2/citestcycle', payloads => {
const events = payloads.flatMap(({ payload }) => payload.events)

const testSessionEvent = events.find(event => event.type === 'test_session_end')
const testModuleEvent = events.find(event => event.type === 'test_module_end')
const testSuiteEvents = events.filter(event => event.type === 'test_suite_end')
const testEvents = events.filter(event => event.type === 'test')

assert.include(testSessionEvent.content.resource, 'test_session.vitest run')
assert.equal(testSessionEvent.content.meta[TEST_STATUS], 'fail')
assert.include(testModuleEvent.content.resource, 'test_module.vitest run')
assert.equal(testModuleEvent.content.meta[TEST_STATUS], 'fail')
assert.equal(testSessionEvent.content.meta[TEST_TYPE], 'test')
assert.equal(testModuleEvent.content.meta[TEST_TYPE], 'test')

const passedSuite = testSuiteEvents.find(
suite => suite.content.resource === 'test_suite.ci-visibility/vitest-tests/test-visibility-passed-suite.mjs'
)
assert.equal(passedSuite.content.meta[TEST_STATUS], 'pass')

const failedSuite = testSuiteEvents.find(
suite => suite.content.resource === 'test_suite.ci-visibility/vitest-tests/test-visibility-failed-suite.mjs'
)
assert.equal(failedSuite.content.meta[TEST_STATUS], 'fail')

const failedSuiteHooks = testSuiteEvents.find(
suite => suite.content.resource === 'test_suite.ci-visibility/vitest-tests/test-visibility-failed-hooks.mjs'
)
assert.equal(failedSuiteHooks.content.meta[TEST_STATUS], 'fail')

assert.includeMembers(testEvents.map(test => test.content.resource),
[
'ci-visibility/vitest-tests/test-visibility-failed-suite.mjs' +
'.test-visibility-failed-suite-first-describe can report failed test',
'ci-visibility/vitest-tests/test-visibility-failed-suite.mjs' +
'.test-visibility-failed-suite-first-describe can report more',
'ci-visibility/vitest-tests/test-visibility-failed-suite.mjs' +
'.test-visibility-failed-suite-second-describe can report passed test',
'ci-visibility/vitest-tests/test-visibility-failed-suite.mjs' +
'.test-visibility-failed-suite-second-describe can report more',
'ci-visibility/vitest-tests/test-visibility-passed-suite.mjs.context can report passed test',
'ci-visibility/vitest-tests/test-visibility-passed-suite.mjs.context can report more',
'ci-visibility/vitest-tests/test-visibility-passed-suite.mjs.other context can report passed test',
'ci-visibility/vitest-tests/test-visibility-passed-suite.mjs.other context can report more',
'ci-visibility/vitest-tests/test-visibility-passed-suite.mjs.other context can skip',
'ci-visibility/vitest-tests/test-visibility-passed-suite.mjs.other context can todo',
'ci-visibility/vitest-tests/test-visibility-failed-hooks.mjs.context can report failed test',
'ci-visibility/vitest-tests/test-visibility-failed-hooks.mjs.context can report more',
'ci-visibility/vitest-tests/test-visibility-failed-hooks.mjs.other context can report passed test',
'ci-visibility/vitest-tests/test-visibility-failed-hooks.mjs.other context can report more'
]
)

const failedTests = testEvents.filter(test => test.content.meta[TEST_STATUS] === 'fail')

assert.includeMembers(
failedTests.map(test => test.content.resource),
[
'ci-visibility/vitest-tests/test-visibility-failed-suite.mjs' +
'.test-visibility-failed-suite-first-describe can report failed test',
'ci-visibility/vitest-tests/test-visibility-failed-hooks.mjs.context can report failed test',
'ci-visibility/vitest-tests/test-visibility-failed-hooks.mjs.context can report more',
'ci-visibility/vitest-tests/test-visibility-failed-hooks.mjs.other context can report passed test',
'ci-visibility/vitest-tests/test-visibility-failed-hooks.mjs.other context can report more'
]
)

const skippedTests = testEvents.filter(test => test.content.meta[TEST_STATUS] === 'skip')

assert.includeMembers(
skippedTests.map(test => test.content.resource),
[
'ci-visibility/vitest-tests/test-visibility-passed-suite.mjs.other context can skip',
'ci-visibility/vitest-tests/test-visibility-passed-suite.mjs.other context can todo',
'ci-visibility/vitest-tests/test-visibility-passed-suite.mjs.other context can programmatic skip'
]
)
// TODO: check error messages
}).then(() => done()).catch(done)

childProcess = exec(
'./node_modules/.bin/vitest run',
{
cwd,
env: {
...getCiVisAgentlessConfig(receiver.port),
// maybe only in node@20
NODE_OPTIONS: '--import dd-trace/register.js -r dd-trace/ci/init' // ESM requires more flags
},
stdio: 'pipe'
}
)
})
})
})
1 change: 1 addition & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,7 @@
"test:integration:cypress": "mocha --colors --timeout 30000 -r \"packages/dd-trace/test/setup/core.js\" \"integration-tests/cypress/*.spec.js\"",
"test:integration:playwright": "mocha --colors --timeout 30000 -r \"packages/dd-trace/test/setup/core.js\" \"integration-tests/playwright/*.spec.js\"",
"test:integration:selenium": "mocha --colors --timeout 30000 -r \"packages/dd-trace/test/setup/core.js\" \"integration-tests/selenium/*.spec.js\"",
"test:integration:vitest": "mocha --colors --timeout 30000 -r \"packages/dd-trace/test/setup/core.js\" \"integration-tests/vitest/*.spec.js\"",
"test:integration:profiler": "mocha --colors --timeout 180000 -r \"packages/dd-trace/test/setup/core.js\" \"integration-tests/profiler/*.spec.js\"",
"test:integration:serverless": "mocha --colors --timeout 30000 -r \"packages/dd-trace/test/setup/core.js\" \"integration-tests/serverless/*.spec.js\"",
"test:integration:plugins": "mocha --colors --exit -r \"packages/dd-trace/test/setup/mocha.js\" \"packages/datadog-plugin-@($(echo $PLUGINS))/test/integration-test/**/*.spec.js\"",
Expand Down
6 changes: 5 additions & 1 deletion packages/datadog-esbuild/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,11 @@ const hooks = require('../datadog-instrumentations/src/helpers/hooks.js')
const extractPackageAndModulePath = require('../datadog-instrumentations/src/utils/src/extract-package-and-module-path')

for (const hook of Object.values(hooks)) {
hook()
if (typeof hook === 'object') {
hook.fn()
} else {
hook()
}
}

const modulesOfInterest = new Set()
Expand Down
11 changes: 8 additions & 3 deletions packages/datadog-instrumentations/src/helpers/hook.js
Original file line number Diff line number Diff line change
Expand Up @@ -11,8 +11,13 @@ const ritm = require('../../../dd-trace/src/ritm')
* @param {string[]} modules list of modules to hook into
* @param {Function} onrequire callback to be executed upon encountering module
*/
function Hook (modules, onrequire) {
if (!(this instanceof Hook)) return new Hook(modules, onrequire)
function Hook (modules, hookOptions, onrequire) {
if (!(this instanceof Hook)) return new Hook(modules, hookOptions, onrequire)

if (typeof hookOptions === 'function') {
onrequire = hookOptions
hookOptions = {}
}

this._patched = Object.create(null)

Expand All @@ -28,7 +33,7 @@ function Hook (modules, onrequire) {
}

this._ritmHook = ritm(modules, {}, safeHook)
this._iitmHook = iitm(modules, {}, (moduleExports, moduleName, moduleBaseDir) => {
this._iitmHook = iitm(modules, hookOptions, (moduleExports, moduleName, moduleBaseDir) => {
// TODO: Move this logic to import-in-the-middle and only do it for CommonJS
// modules and not ESM. In the meantime, all the modules we instrument are
// CommonJS modules for which the default export is always moved to
Expand Down
Loading

0 comments on commit b9a5d4d

Please sign in to comment.