Skip to content

Commit

Permalink
[native_*] Make locking tests less timing sensitive (#1459)
Browse files Browse the repository at this point in the history
  • Loading branch information
dcharkes authored Aug 26, 2024
1 parent ec42097 commit 6eeb6d9
Show file tree
Hide file tree
Showing 2 changed files with 39 additions and 36 deletions.
16 changes: 3 additions & 13 deletions pkgs/native_assets_builder/test/build_runner/concurrency_test.dart
Original file line number Diff line number Diff line change
Expand Up @@ -189,20 +189,10 @@ void main() async {
final cachedInvocationDuration = s.elapsed;
// Give a hook longer to run than it needs. So we're sure it's being
// held up by the lock not being released.
final singleHookTimeout = Duration(
milliseconds: min(
cachedInvocationDuration.inMilliseconds * 2,
cachedInvocationDuration.inMilliseconds + 2000,
),
);
final singleHookTimeout = cachedInvocationDuration * 2;
// And give the timer to end this test and release the lock even more
// time.
final helperTimeout = Duration(
milliseconds: min(
singleHookTimeout.inMilliseconds * 2,
singleHookTimeout.inMilliseconds + 4000,
),
);
// time. In a normal test run, the timer should always be cancelled.
final helperTimeout = singleHookTimeout * 10;
printOnFailure([
'cachedInvocationDuration',
cachedInvocationDuration,
Expand Down
59 changes: 36 additions & 23 deletions pkgs/native_assets_cli/test/locking/locking_test.dart
Original file line number Diff line number Diff line change
Expand Up @@ -117,11 +117,11 @@ void main() async {

test('Timeout exits process', timeout: longTimeout, () async {
await inTempDir((tempUri) async {
Future<ProcessResult> runProcess({
Future<void> runProcess({
Duration? timeout,
bool expectTimeOut = false,
}) async {
final result = await Process.run(
final process = await Process.start(
dartExecutable.toFilePath(),
[
packageUri
Expand All @@ -131,13 +131,27 @@ void main() async {
if (timeout != null) timeout.inMilliseconds.toString(),
],
);

final stdoutSub = process.stdout
.transform(utf8.decoder)
.transform(const LineSplitter())
.listen(logger.fine);
final stderrSub = process.stderr
.transform(utf8.decoder)
.transform(const LineSplitter())
.listen(logger.severe);

final (exitCode, _, _) = await (
process.exitCode,
stdoutSub.asFuture<void>(),
stderrSub.asFuture<void>()
).wait;

if (expectTimeOut) {
expect(result.exitCode, isNot(0));
expect(exitCode, isNot(0));
} else {
expect(result.exitCode, 0);
expect(exitCode, 0);
}

return result;
}

await runProcess();
Expand All @@ -150,37 +164,36 @@ void main() async {
s.start();
await runProcess();
s.stop();
final cachedInvocationDuration = s.elapsed;
final singleHookTimeout = Duration(
milliseconds: min(
cachedInvocationDuration.inMilliseconds * 2,
cachedInvocationDuration.inMilliseconds + 1000,
),
);
final helperTimeout = Duration(
milliseconds: min(
singleHookTimeout.inMilliseconds * 2,
singleHookTimeout.inMilliseconds + 1000,
),
);
final oneTimeRun = s.elapsed;
printOnFailure('oneTimeRun: $oneTimeRun');
// Some arbitrary time that the inner process will wait to try to grab the
// lock. At least a multiple of the magic constant of 50 milliseconds.
const helperProcessTimeout = Duration(milliseconds: 200);
printOnFailure('helperProcessTimeout: $helperProcessTimeout');
// In a normal test run, the timer should always be cancelled. But pass
// some reasonable upper bound.
final timerTimeout = oneTimeRun * 10;
printOnFailure('timerTimeout: $timerTimeout');

final randomAccessFile = await lockFile.open(mode: FileMode.write);
final lock = await randomAccessFile.lock(FileLock.exclusive);
var helperCompletedFirst = false;
var timeoutCompletedFirst = false;
final timer = Timer(helperTimeout, () async {
printOnFailure('timer expired');
final timer = Timer(timerTimeout, () async {
printOnFailure('${DateTime.now()}: Timer expired.');
if (!helperCompletedFirst) {
printOnFailure('${DateTime.now()}: timeoutCompletedFirst');
timeoutCompletedFirst = true;
}
await lock.unlock();
});
await runProcess(
timeout: singleHookTimeout,
timeout: helperProcessTimeout,
expectTimeOut: true,
).then((v) async {
printOnFailure('helper exited');
printOnFailure('${DateTime.now()}: Helper exited.');
if (!timeoutCompletedFirst) {
printOnFailure('${DateTime.now()}: timeoutCompletedFirst');
helperCompletedFirst = true;
}
timer.cancel();
Expand Down

0 comments on commit 6eeb6d9

Please sign in to comment.