Skip to content
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

test-runner: run tests as soon as find them #48584

Closed
wants to merge 20 commits into from

Conversation

rluvaton
Copy link
Member

@rluvaton rluvaton commented Jun 28, 2023

currently find the tests files to run and then run them, this runs the tests as soon as finding them

Following our conversation in NodeTLV 2023:
Cc @MoLow @cjihrig

this is still WIP, just want the CI to run and general feedback

TODOs:

@nodejs-github-bot
Copy link
Collaborator

Review requested:

  • @nodejs/test_runner

@nodejs-github-bot nodejs-github-bot added fs Issues and PRs related to the fs subsystem / file system. needs-ci PRs that need a full CI run. test_runner Issues and PRs related to the test runner subsystem. labels Jun 28, 2023
@rluvaton rluvaton force-pushed the run-tests-as-soon-as-get-a-file branch from 337a2ac to 1d80a2b Compare June 28, 2023 13:35
Comment on lines +89 to +100
async readdir(path) {
const cached = this.#readdirCache.get(path);
if (cached) {
return cached;
}
let val;
try {
val = await readdir(path, { __proto__: null, withFileTypes: true });
} catch {
val = [];
}
this.#readdirCache.set(path, val);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If the goal is to streamline the process of finding test files, shouldn't we be using opendir rather than readdir?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

thanks, I need to check how I can insert it here, I did not change the logic...

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

+1 for opendir

@@ -14,7 +14,7 @@ const testFixtures = fixtures.path('test-runner');

assert.strictEqual(child.status, 1);
assert.strictEqual(child.signal, null);
assert.strictEqual(child.stdout.toString(), '');
assert.strictEqual(child.stdout.toString(), 'TAP version 13\n');
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

as we first start running and then check as we get the files asynchronously

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

this should not be outputed if no test files are fond. we should emit the start event only at the first test

Comment on lines 485 to 486
// TODO - find better way to check if promise
if (typeof testFiles.then === 'function') {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

if it's not a promise, it's an array, right? could this check be inverted, so it can use IsArray, and then PromisePrototypeThen can be used unconditionally, and if it's not a promise, it'll throw?

(or if it's not an array and i'm just confused because it has .map, presumably there's another way to check whatever it is)

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

files can be array when provided by the user

it can be:

  • array: when provided by the user
  • stream: when we find the tests
  • promise: when we find the tests but we are in watch mode

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ok, so IsArray works for array, and surely we have a way to brand check node's own streams?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

do we need to? checked array and promise...

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

right, but there isn't a brand check for Promise, and this TODO comment references it.

Therefore, if you flip the conditions so you check the two other options, then you can just assume it's a promise.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

gotcha, thanks

on another note, is there a way not to get a bazillion emails when the build cancels due to a new commit being pushed? it's really annoying!

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think the common interface should be anything that is async iterable. (arrays are, so are readable streams, so only watch mode needs to be adjusted to use an async iterable - that should not be hard since it uses an event emitter)

// Overriding testFiles so we won't try to consume again the stream
testFiles = ArrayIsArray(testFiles) ? testFiles : testFiles.toArray();

// TODO - should not pass a promise
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Any idea how can I avoid passing promise? as the tests need to have the filesWatcher, should I just mark the run function as async and await it normally?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

testFiles should probably just be async iterable


if (isNodeStream(testFiles)) {
return testFiles
.map(runSingleFile, { __proto__: null, signal, concurrency: NumberMAX_SAFE_INTEGER })
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

used this concurrency to not wait for tests otherwise tests that not finish not allow us to run other tests, and this is also to keep the behavior of AllSettled...

will be changed to Infinity once the below PR is merged:

@@ -152,7 +152,7 @@ function setup(root) {

const terminationHandler = async () => {
await exitHandler();
process.exit();
process.exit(1);
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

changed to 1 as otherwise this test failed:

assert.strictEqual(code, 1);

the exit code is equal to 0 instead of 1

weird it worked before...

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I feel strongly like this should not be changed

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I agree, changed it here until I fix the rest of the things

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

needed to change this file as the order of the tests file are not sorted anymore

Copy link
Member

@MoLow MoLow left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

There is a lot going on in this PR.
I suggest to break out pieces to make it easier to review and test,
for example make globSync use Symbol.Iterator can be split out

@@ -376,6 +396,238 @@ class Glob {
}
}
}

async *#addSubpatterns(path, pattern) {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

we should try to avoid this code duplication, perhaps extracting logic to common methods will allow that

Copy link
Member Author

@rluvaton rluvaton Jun 29, 2023

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@MoLow
Copy link
Member

MoLow commented Jul 2, 2023

I know I am the one who suggested this optimization, but rethinking - this will make it much harder to implement feature requests such as #48619 or #48385, and I am not sure that it is really worth it

@rluvaton
Copy link
Member Author

rluvaton commented Jul 2, 2023

Why do you think it's harder to implement that way?

we can get all files in that case like we do in watch mode...

Also, sharding and randomization isn't the common case IMO

@MoLow
Copy link
Member

MoLow commented Jul 2, 2023

I am Just saying there are many cases whre this optimization will not work with that it might be an overkill, since the gain isnt vert big anyway

@cjihrig
Copy link
Contributor

cjihrig commented Aug 11, 2023

Is this still being worked on or can it be closed?

@rluvaton
Copy link
Member Author

Depending on what @MoLow thinks, I implemented sharding and this should not affect that It is just like watch - precomputing the file list (which will be the same as randomization tests)

@MoLow
Copy link
Member

MoLow commented Aug 12, 2023

I am not blocking this - but it is probably a breaking change since tests wont run in the same order anymore

@cjihrig
Copy link
Contributor

cjihrig commented Sep 27, 2023

I'm going to close this for now since it doesn't appear to be progressing.

@cjihrig cjihrig closed this Sep 27, 2023
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
fs Issues and PRs related to the fs subsystem / file system. needs-ci PRs that need a full CI run. test_runner Issues and PRs related to the test runner subsystem.
Projects
None yet
Development

Successfully merging this pull request may close these issues.

6 participants