Skip to content

Commit

Permalink
chore(node): run tests against multiple package managers
Browse files Browse the repository at this point in the history
This changes how `lavamoat` runs its tests.

To prepare the tests, `test/prepare.js` is run.  This invokes [corepack](https://npm.im/corepack) to switch between package managers and performs a clean install and setup using each.  The package manager can be changed via environment variable.

Motivation:  After changing from Yarn to npm, we were concerned about breaking compat.  This should ease our nerves a bit!

Notes:

- a new policy file was created in project `2` for `atob`; I'm not sure what caused this change.
- Yarn _must_ have lockfiles or it will get confused about workspaces.
  • Loading branch information
boneskull committed Oct 26, 2023
1 parent 8a5f851 commit 7e8e354
Show file tree
Hide file tree
Showing 32 changed files with 1,159 additions and 1,817 deletions.
41 changes: 40 additions & 1 deletion package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

7 changes: 6 additions & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@
"@typescript-eslint/parser": "^6.7.3",
"ava": "^5.3.1",
"conventional-changelog-conventionalcommits": "^6.1.0",
"cross-env": "^7.0.3",
"depcheck": "^1.4.0",
"eslint": "^8.45.0",
"eslint-config-prettier": "^9.0.0",
Expand All @@ -30,8 +31,12 @@
"type-fest": "^2.19.0",
"typescript": "^5.2.2"
},
"optionalDependencies": {
"corepack": "0.20.0"
},
"engines": {
"node": "^16.20.0 || ^18.0.0 || ^20.0.0"
"node": "^16.20.0 || ^18.0.0 || ^20.0.0",
"npm": ">=7.0.0"
},
"scripts": {
"build": "npm run --workspaces --if-present build && npm run build:types",
Expand Down
3 changes: 3 additions & 0 deletions packages/node/.depcheckrc.yml
Original file line number Diff line number Diff line change
Expand Up @@ -3,3 +3,6 @@ ignores:
- 'ava'
# tests - fake packages
- 'two'

# invoked as executable
- 'corepack'
9 changes: 5 additions & 4 deletions packages/node/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -8,10 +8,11 @@
"main": "src/index.js",
"license": "MIT",
"scripts": {
"lint:deps": "depcheck",
"test": "npm run test:prep && npm run test:ava",
"test:prep": "for d in ./test/projects/*/ ; do (cd \"$d\" && NODE_ENV=development yarn setup && ../../../src/cli.js -a index.js); done",
"test:ava": "ava"
"test": "npm run test:npm && npm run test:yarn1",
"test:prepare": "node ./test/prepare.js",
"test:npm": "cross-env LAVAMOAT_PM=npm@latest npm run test:prepare && ava",
"test:yarn1": "cross-env LAVAMOAT_PM=yarn@1 npm run test:prepare && ava",
"lint:deps": "depcheck"
},
"dependencies": {
"@babel/code-frame": "^7.22.13",
Expand Down
27 changes: 26 additions & 1 deletion packages/node/src/defaults.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,30 @@ const { getDefaultPaths } = require('lavamoat-core')

const defaultPaths = getDefaultPaths('node')

module.exports = {
/**
* @typedef LavaMoatScuttleOpts
* @property {boolean} [enabled]
* @property {string[]} [exceptions]
* @property {string} [scuttlerName]
*/

/**
* @typedef LavaMoatOpts
* @property {LavaMoatScuttleOpts} [scuttleGlobalThis]
* @property {string[]} [scuttleGlobalThisExceptions]
* @property {boolean} [writeAutoPolicy]
* @property {boolean} [writeAutoPolicyDebug]
* @property {boolean} [writeAutoPolicyAndRun]
* @property {string} [policyPath]
* @property {string} [policyDebugPath]
* @property {string} [policyOverridePath]
* @property {string} [projectRoot]
* @property {boolean} [debugMode]
* @property {boolean} [statsMode]
*/

/** @type {LavaMoatOpts} */
const defaults = {
scuttleGlobalThis: {},
scuttleGlobalThisExceptions: [],
writeAutoPolicy: false,
Expand All @@ -15,3 +38,5 @@ module.exports = {
debugMode: false,
statsMode: false,
}

module.exports = defaults
29 changes: 15 additions & 14 deletions packages/node/test/index.spec.js
Original file line number Diff line number Diff line change
@@ -1,14 +1,15 @@
const path = require('node:path')
const test = require('ava')
const { parseForPolicy } = require('../src/parseForPolicy')
const { runLavamoat } = require('./util')

test('parseForPolicy - resolutions', async (t) => {
const projectRoot = `${__dirname}/projects/1`
const entryId = `${projectRoot}/index.js`
const projectRoot = path.join(__dirname, 'projects', '1')
const entryId = path.join(projectRoot, 'index.js')
const resolutions = {
a: {
fs: `${projectRoot}/fake-fs.js`,
b: `${projectRoot}/fake-b.js`,
fs: path.join(projectRoot, 'fake-fs.js'),
b: path.join(projectRoot, 'fake-b.js'),
},
}

Expand Down Expand Up @@ -53,8 +54,8 @@ test('parseForPolicy - resolutions', async (t) => {
})

test('parseForPolicy - require a userspace package with a builtin name', async (t) => {
const projectRoot = `${__dirname}/projects/4`
const entryId = `${projectRoot}/index.js`
const projectRoot = path.join(__dirname, 'projects', '4')
const entryId = path.join(projectRoot, 'index.js')

const policy = await parseForPolicy({ entryId, projectRoot })
t.deepEqual(policy, {
Expand All @@ -79,8 +80,8 @@ test('parseForPolicy - require a userspace package with a builtin name', async (
})

test("parseForPolicy - indirectly used packages are included in parent's allowlist", async (t) => {
const projectRoot = `${__dirname}/projects/5`
const entryId = `${projectRoot}/index.js`
const projectRoot = path.join(__dirname, 'projects', '5')
const entryId = path.join(projectRoot, 'index.js')
const policy = await parseForPolicy({ entryId, projectRoot })
t.deepEqual(policy, {
resources: { a: { builtin: { crypto: true } } },
Expand All @@ -104,8 +105,8 @@ test('parseForPolicy - find node:-prefixed builtins', async (t) => {

// run lavamoat-node
test('execute - resolutions', async (t) => {
const projectRoot = `${__dirname}/projects/1`
const entryId = './index.js'
const projectRoot = path.join(__dirname, 'projects', '1')
const entryId = path.join(projectRoot, 'index.js')
const { output } = await runLavamoat({
cwd: projectRoot,
args: [entryId],
Expand All @@ -118,8 +119,8 @@ test('execute - resolutions', async (t) => {
})

test('execute - keccak with native modules', async (t) => {
const projectRoot = `${__dirname}/projects/2`
const entryId = './index.js'
const projectRoot = path.join(__dirname, 'projects', '2')
const entryId = path.join(projectRoot, 'index.js')
const { output } = await runLavamoat({
cwd: projectRoot,
args: [entryId],
Expand All @@ -135,8 +136,8 @@ test('execute - keccak with native modules', async (t) => {
})

test('execute - core modules and buffers', async (t) => {
const projectRoot = `${__dirname}/projects/3`
const entryId = './index.js'
const projectRoot = path.join(__dirname, 'projects', '3')
const entryId = path.join(projectRoot, 'index.js')
const { output } = await runLavamoat({
cwd: projectRoot,
args: [entryId],
Expand Down
77 changes: 77 additions & 0 deletions packages/node/test/prepare.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,77 @@
// @ts-check

/**
* Prepares test fixture directories for use by the test suite using an
* arbitrary package manager set via the `LAVAMOAT_PM` env var.
*
* The default package manager is `npm@latest`.
*
* @packageDocumentation
*/

'use strict'

const path = require('node:path')
const { execFile } = require('node:child_process')
const { promisify } = require('node:util')
const { rm, readdir } = require('node:fs/promises')

const exec = promisify(execFile)

const LAVAMOAT_PM = process.env.LAVAMOAT_PM ?? 'npm@latest'
const PROJECTS_DIR = path.join(__dirname, 'projects')

/**
* Blast `node_modules` in `cwd`
* @param {string} cwd - Project dir
* @returns {Promise<void>}
*/
async function clean(cwd) {
await rm(path.join(cwd, 'node_modules'), { recursive: true, force: true })
}

/**
* Install a project's deps via a package manager, run the `setup` script, then
* execute `lavamoat` on the `index.js` file.
* @param {string} cwd - Project dir
* @returns {Promise<void>}
*/
async function setup(cwd) {
// it just so happens that both yarn and npm use the same commands here.
// this is not guaranteed to always be the case!
await exec('corepack', [LAVAMOAT_PM, 'install'], { cwd })
await exec('corepack', [LAVAMOAT_PM, 'run', 'setup'], { cwd })
await exec('node', [require.resolve('../src/cli'), '-a', 'index.js'], {
cwd,
})
}

async function main() {
if (process.version.startsWith('v14') && LAVAMOAT_PM.startsWith('yarn')) {
console.error('Skipping Yarn setup for Node.js v14 due to incompatibilities')
return
}

const dirents = await readdir(PROJECTS_DIR, { withFileTypes: true })

for (const dirent of dirents) {
if (dirent.isDirectory()) {
const cwd = path.join(PROJECTS_DIR, dirent.name)
const relative = path.relative(process.cwd(), cwd)

await clean(cwd)
await setup(cwd)

console.debug('Initialized "%s" using %s', relative, LAVAMOAT_PM)
}
}

console.debug('Test fixtures prepared successfully')
}

if (require.main === module) {
main().catch((err) => {
console.error(err)
process.exitCode = 1
})
}
1 change: 1 addition & 0 deletions packages/node/test/projects/1/.npmrc
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
package-lock = false
28 changes: 0 additions & 28 deletions packages/node/test/projects/1/package-lock.json

This file was deleted.

2 changes: 1 addition & 1 deletion packages/node/test/projects/1/package.json
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
{
"name": "test-1",
"scripts": {
"setup": "npm install"
"setup": "exit 0"
},
"dependencies": {
"a": "file:./fake_node_modules/a",
Expand Down
9 changes: 9 additions & 0 deletions packages/node/test/projects/1/yarn.lock
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
# THIS IS AN AUTOGENERATED FILE. DO NOT EDIT THIS FILE DIRECTLY.
# yarn lockfile v1


"a@file:./fake_node_modules/a":
version "1.0.0"

"b@file:./fake_node_modules/b":
version "1.0.0"
1 change: 1 addition & 0 deletions packages/node/test/projects/2/.npmrc
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
package-lock = false
1 change: 0 additions & 1 deletion packages/node/test/projects/2/.nvmrc

This file was deleted.

0 comments on commit 7e8e354

Please sign in to comment.