blob: 3a738fdfcd590292b076e2dc5b2938ea17e22de4 [file] [log] [blame]
// Copyright (c) 2014, the Dart project authors. Please see the AUTHORS file
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.
@TestOn('windows')
@Timeout.factor(2)
library;
import 'dart:async';
import 'dart:io';
import 'package:path/path.dart' as p;
import 'package:test/test.dart';
import 'package:watcher/src/directory_watcher/windows_resubscribable_watcher.dart';
import 'package:watcher/watcher.dart';
import '../utils.dart';
import 'end_to_end_tests.dart';
import 'file_tests.dart';
import 'link_tests.dart';
void main() {
watcherFactory = WindowsDirectoryWatcher.new;
fileTests(isNative: true);
linkTests(isNative: true);
endToEndTests();
test('DirectoryWatcher creates a WindowsDirectoryWatcher on Windows', () {
expect(DirectoryWatcher('.'), const TypeMatcher<WindowsDirectoryWatcher>());
});
test(
'Regression test for https://github.com/dart-lang/tools/issues/2110',
() async {
late StreamSubscription<WatchEvent> sub;
try {
final temp = Directory.systemTemp.createTempSync();
final watcher = DirectoryWatcher(temp.path);
final events = <WatchEvent>[];
sub = watcher.events.listen(events.add);
await watcher.ready;
// Create a file in a directory that doesn't exist. This forces the
// directory to be created first before the child file.
//
// When directory creation is detected by the watcher, it calls
// `Directory.list` on the directory to determine if there's files that
// have been created or modified. It's possible that the watcher will
// have already detected the file creation event before `Directory.list`
// returns. Before https://github.com/dart-lang/tools/issues/2110 was
// resolved, the check to ensure an event hadn't already been emitted
// for the file creation was incorrect, leading to the event being
// emitted again in some circumstances.
final file = File(p.join(temp.path, 'foo', 'file.txt'))
..createSync(recursive: true);
// Introduce a short delay to allow for the directory watcher to detect
// the creation of foo/ and foo/file.txt.
await Future<void>.delayed(const Duration(seconds: 1));
// There should only be a single file added event.
expect(events, hasLength(1));
expect(
events.first.toString(),
WatchEvent(ChangeType.ADD, file.path).toString(),
);
} finally {
await sub.cancel();
}
},
);
// Regression test for https://github.com/dart-lang/tools/issues/2152:
// watcher can throws if a directory is created then quickly deleted.
group('Transient directory', () {
late StreamSubscription<Object> subscription;
late Directory temp;
late Watcher watcher;
late int errorsSeen;
setUp(() async {
temp = Directory.systemTemp.createTempSync();
watcher = DirectoryWatcher(temp.path);
errorsSeen = 0;
subscription = watcher.events.listen(
(e) {},
onError: (Object e, _) {
print('Event stream error: $e');
++errorsSeen;
},
);
await watcher.ready;
});
tearDown(() {
subscription.cancel();
});
test('does not break watching', () async {
// Iterate creating 10 directories and deleting 1-10 of them. This means
// the directories will exist for different lengths of times, exploring
// possible race conditions in directory handling.
for (var i = 0; i != 50; ++i) {
for (var j = 0; j != 10; ++j) {
File('${temp.path}\\$j\\file').createSync(recursive: true);
}
await Future<void>.delayed(const Duration(milliseconds: 1));
for (var j = 0; j != i % 10 + 1; ++j) {
final d = Directory('${temp.path}\\$j');
d.deleteSync(recursive: true);
}
await Future<void>.delayed(const Duration(milliseconds: 1));
}
expect(errorsSeen, 0);
});
});
}