-
Notifications
You must be signed in to change notification settings - Fork 1.8k
WIP [SPIKE] - test(NODE-7345): custom vm.Context runner for mocha #4844
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Conversation
test/tools/runner/vm_runner.js
Outdated
| @@ -0,0 +1,206 @@ | |||
| /* eslint-disable no-restricted-globals */ | |||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
| /* eslint-disable no-restricted-globals */ | |
| 'use strict'; | |
| /* eslint-disable no-restricted-globals */ |
(this is a script, not an ES module, so strict mode is not the default)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The file had been converted to ts as @PavelSafronov suggested
test/tools/runner/vm_runner.js
Outdated
| reporter: 'test/tools/reporter/mongodb_reporter.js', | ||
| sort: true, | ||
| color: true, | ||
| ignore: [ |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Maybe add a comment about why these are being ignored?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yes, thanks! I copied this configuration from the integration tests setup, will link these files together.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I included the original file all along instead of manually picking up its' options
test/tools/runner/vm_runner.js
Outdated
|
|
||
| function createSandboxContext(filename) { | ||
| const exportsContainer = {}; | ||
| return { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
| return { | |
| return { | |
| __proto__: null, |
Just so none of the property lookups for built-ins fall back to the global one unintentionally
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
thanks, included!
test/tools/runner/vm_runner.js
Outdated
| exports: exportsContainer, | ||
| module: { exports: exportsContainer }, | ||
| __filename: filename, | ||
| __dirname: path.dirname(filename), |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'd try to emulate the behavior of the built-in CommonJS evaluator as closely as possible.
None of these are typically globals, and modules do share a single global – all of require, module, exports, __filenameand__dirname` are injected as parameters to an implicit function that is used to wrap around user code
(you should generally be able to use that file as a reference for a lot of this)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
That is awesome, thanks! I haven't seen this file before, this is huge help indeed.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Added the same style wrapper around the script and define "globals" (context) just once so it's shared.
test/tools/runner/vm_runner.js
Outdated
| return function sandboxRequire(moduleIdentifier) { | ||
| if (!moduleIdentifier.startsWith('.')) { | ||
| return require(moduleIdentifier); | ||
| } |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Is this intentional? I figured we'd want to require almost everything inside the sandbox except for Node.js built-ins and maybe a list of modules that are explicit exceptions to this rule
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is temporary solution to be able to import all dev dependencies and to highlight the more general idea (this ticket and PR is spike), so I was focusing mostly on "running existing integration tests inside vm.Context sandbox". But you are absolutely right, ideally all prod dependencies should be required from the inside, otherwise it's pointless (if driver is browser-compatible but, say bson not - we can't run application).
test/tools/runner/vm_runner.js
Outdated
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Can we switch this file to TS? Some of our test runners are JS, but most are TS, would be nice if all new code was TS. Unless there's some reason that we can't/shouldn't.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
done!
|
Re: testing - there's a command for running tests against 3 local servers, but what is the command we should use to start those 3 servers? I tried starting a replica set ( |
test/tools/runner/vm_runner.js
Outdated
| let compilerOptions = { module: ts.ModuleKind.CommonJS }; | ||
| const tsConfigPath = path.join(__dirname, '../../tsconfig.json'); | ||
| const configFile = ts.readConfigFile(tsConfigPath, ts.sys.readFile); | ||
| if (!configFile.error) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Throw if configFile.error is present?
I actually don't know the answer yet. I mean you did everything right, I personally use |
| // force instanceof to work across contexts by defining custom `instanceof` function | ||
| Object.defineProperty(value, Symbol.hasInstance, { | ||
| value: (instance: any) => { | ||
| return ( | ||
| instance && (instance.constructor.name === value.name || instance instanceof value) | ||
| ); | ||
| } | ||
| }); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I don't really like this part, but I found this problem a little bit tricky. The problem is that host environment (and consequently chai) has its' own set of Error classes, so instanceof from inside the sandbox is broken. @addaleax, maybe there is more convenient way to make it work rather than re-defining instanceof?
| const sandboxedDependencies = ['bson']; | ||
| const isSandboxedDep = sandboxedDependencies.some( | ||
| dep => moduleIdentifier === dep || moduleIdentifier.startsWith(`${dep}/`) | ||
| ); | ||
| if (!moduleIdentifier.startsWith('.') && !isSandboxedDep) { | ||
| return require(moduleIdentifier); | ||
| } |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@addaleax this seems to work kinda of fine, we can list dependencies that should be loaded from within the sandbox. i decided to go with this approach because list of dev and prod dependencies we need to import in host is large. but maybe i'm missing something and it should be the other way around (everything is inside except certain builtin modules)?
Description
Summary of Changes
Notes for Reviewers
To run the tests:
What is the motivation for this change?
Release Highlight
Release notes highlight
Double check the following
npm run check:lint)type(NODE-xxxx)[!]: descriptionfeat(NODE-1234)!: rewriting everything in coffeescript