-
Notifications
You must be signed in to change notification settings - Fork 162
Speed up directory monitoring tests #1325
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
|
@swift-ci please test |
d-ronnqvist
left a comment
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.
Only one of these changes make the directory monitor test faster, the rest only make them more fragile without running faster.
| } | ||
|
|
||
| wait(for: [didNotTriggerUpdateForHiddenFile], timeout: 20) | ||
| wait(for: [didNotTriggerUpdateForHiddenFile], timeout: 2) |
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 also doesn't speed up the test as long as it passes. Even if I increase both of these to 200 second testMonitorDoesNotTriggerUpdates only takes ~20 seconds for me to run locally.
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, the speed-up comes from reducing the timeout for .fulfill() a few lines above. Since the fulfillment happens in 1.5s, this wait() will always complete shortly after that duration, irrespective of whether the timeout is 2s or 20s. I reduced it to 2s just so it's clear that it waits slightly longer than the time taken for .fulfill() to run. I'm happy to revert it to 20s if you prefer that, but I don't see how that makes the test any less fragile.
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 think either is fine. The only subtle thing I like about the 20s timeout—but that reason may not apply generally—is that it's large enough that my mind interprets it as a timeout that won't be waited for in practice. In other words; if I see a 20s timeout I think "this finishes as soon as the expectation is fulfilled" whereas if I see a 2s timeout there's some doubt in my mind that it needs to wait the full two seconds.
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.
Taking a second look at this test now I find it to be overly complicated. I feel that this function would be simpler if it creates an expectation that it expected not to be fulfilled. Then we wouldn't need both the asyncAfter and the wait.
let fileUpdateEvent = expectation(description: "Unexpectedly triggered an update event")
fileUpdateEvent.isInverted = true // We don't expect any file updates
let monitor = try DirectoryMonitor(root: url) { rootURL, url in
fileUpdateEvent.fulfill()
}
try monitor.start()
defer {
monitor.stop()
}
// For the test purposes we assume a file change event will be delivered within 1.5 seconds.
waitForExpectations(timeout: 1.5)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.
Similarly, the other monitor helper function could be simplified by removing the notifications and waiting for the expectations directly:
let fileUpdatedExpectation = expectedChangeOrigin != nil
? expectation(description: "File updated event")
: nil
let treeRefreshedExpectation = isTreeReloadExpected
? expectation(description: "Watched tree was refreshed")
: nil
// Create a directory monitor and handle its events.
let monitor = try DirectoryMonitor(root: rootURL) { _, url in
if let expectedChangeOrigin {
XCTAssertTrue(fileURLsAreEqual(expectedChangeOrigin, url), "'\(expectedChangeOrigin.path)' is not equal to \(url.path)", file: file, line: line)
}
fileUpdatedExpectation?.fulfill()
}
monitor.didReloadWatchedDirectoryTree = { _ in
treeRefreshedExpectation?.fulfill()
}
try monitor.start()
defer {
monitor.stop()
}
// Run the block that's supposed to create the trigger events in the file system.
try triggerBlock()
if fileUpdatedExpectation != nil || treeRefreshedExpectation != nil {
waitForExpectations(timeout: 5.0)
}The directory monitoring tests check for whether the documentation is rebuilt if the documentation catalog is edited when running a live server with `docc preview`. These tests assumed an extremely generous timeout for receiving the directory change signal, and ran much slower than the rest of the test suite. The timeouts have been reduced to a more reasonable threshold that succeeds even with throttled resources on a single-core machine.
|
@swift-ci please test |
Summary
The directory monitoring tests check for whether the documentation is rebuilt if the documentation catalog is edited when running a live server with
docc preview. These tests assumed an extremely generous timeout of 5 seconds for changes to the directory, and 10 seconds for a lack of change. Thus, they ran much slower than the rest of the test suite. The timeouts have been reduced to a more reasonable threshold of 1.5 seconds, which still succeeds with throttled CPU resources.Dependencies
N/A
Testing
This was tested by restricting CPU resources to 20% of a single core and running the tests 100 times:
Checklist
Make sure you check off the following items. If they cannot be completed, provide a reason.
[ ] Added tests./bin/testscript and it succeeded[ ] Updated documentation if necessary