Skip to content

Commit 4c362f3

Browse files
committed
Add DirectoryWatcher symlink tests.
1 parent 4c7dae1 commit 4c362f3

File tree

7 files changed

+109
-10
lines changed

7 files changed

+109
-10
lines changed

pkgs/watcher/test/directory_watcher/shared.dart renamed to pkgs/watcher/test/directory_watcher/file_tests.dart

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
// Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file
22
// for details. All rights reserved. Use of this source code is governed by a
33
// BSD-style license that can be found in the LICENSE file.
4+
45
import 'dart:io' as io;
56
import 'dart:isolate';
67

@@ -10,7 +11,7 @@ import 'package:watcher/src/utils.dart';
1011

1112
import '../utils.dart';
1213

13-
void sharedTests() {
14+
void fileTests() {
1415
test('does not notify for files that already exist when started', () async {
1516
// Make some pre-existing files.
1617
writeFile('a.txt');
Lines changed: 81 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,81 @@
1+
// Copyright (c) 2025, the Dart project authors. Please see the AUTHORS file
2+
// for details. All rights reserved. Use of this source code is governed by a
3+
// BSD-style license that can be found in the LICENSE file.
4+
5+
import 'package:test/test.dart';
6+
7+
import '../utils.dart';
8+
9+
void linkTests() {
10+
test('notifies when a link is added', () async {
11+
createDir('targets');
12+
createDir('links');
13+
writeFile('targets/a.target');
14+
await startWatcher(path: 'links');
15+
writeLink(link: 'links/a.link', target: 'targets/a.target');
16+
await expectAddEvent('links/a.link');
17+
});
18+
19+
test(
20+
'notifies when a link is replaced with a link to a different target '
21+
'with the same contents', () async {
22+
createDir('targets');
23+
createDir('links');
24+
writeFile('targets/a.target');
25+
writeFile('targets/b.target');
26+
writeLink(link: 'links/a.link', target: 'targets/a.target');
27+
await startWatcher(path: 'links');
28+
29+
deleteLink('links/a.link');
30+
writeLink(link: 'links/a.link', target: 'targets/b.target');
31+
32+
await expectModifyEvent('links/a.link');
33+
});
34+
35+
test(
36+
'notifies when a link is replaced with a link to a different target '
37+
'with different contents', () async {
38+
writeFile('targets/a.target', contents: 'a');
39+
writeFile('targets/b.target', contents: 'b');
40+
writeLink(link: 'links/a.link', target: 'targets/a.target');
41+
await startWatcher(path: 'links');
42+
43+
deleteLink('links/a.link');
44+
writeLink(link: 'links/a.link', target: 'targets/b.target');
45+
46+
await expectModifyEvent('links/a.link');
47+
});
48+
49+
test('does not notify when a link target is modified', () async {
50+
createDir('targets');
51+
createDir('links');
52+
writeFile('targets/a.targt');
53+
writeLink(link: 'links/a.link', target: 'targets/a.target');
54+
await startWatcher(path: 'links');
55+
writeFile('targets/a.target', contents: 'modified');
56+
await expectNoEvents();
57+
});
58+
59+
test('does not notify when a link target is removed', () async {
60+
createDir('targets');
61+
createDir('links');
62+
writeFile('targets/a.target');
63+
writeLink(link: 'links/a.link', target: 'targets/a.target');
64+
await startWatcher(path: 'links');
65+
deleteFile('targets/a.target');
66+
await expectNoEvents();
67+
});
68+
69+
test('notifies when a link is moved within the watched directory', () async {
70+
createDir('targets');
71+
createDir('links');
72+
writeFile('targets/a.target');
73+
writeLink(link: 'links/a.link', target: 'targets/a.target');
74+
await startWatcher(path: 'links');
75+
76+
renameLink('links/a.link', 'links/b.link');
77+
78+
await inAnyOrder(
79+
[isAddEvent('links/b.link'), isRemoveEvent('links/a.link')]);
80+
});
81+
}

pkgs/watcher/test/directory_watcher/linux_test.dart

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -10,12 +10,14 @@ import 'package:watcher/src/directory_watcher/linux.dart';
1010
import 'package:watcher/watcher.dart';
1111

1212
import '../utils.dart';
13-
import 'shared.dart';
13+
import 'file_tests.dart';
14+
import 'link_tests.dart';
1415

1516
void main() {
1617
watcherFactory = LinuxDirectoryWatcher.new;
1718

18-
sharedTests();
19+
fileTests();
20+
linkTests();
1921

2022
test('DirectoryWatcher creates a LinuxDirectoryWatcher on Linux', () {
2123
expect(DirectoryWatcher('.'), const TypeMatcher<LinuxDirectoryWatcher>());

pkgs/watcher/test/directory_watcher/mac_os_test.dart

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -10,12 +10,14 @@ import 'package:watcher/src/directory_watcher/mac_os.dart';
1010
import 'package:watcher/watcher.dart';
1111

1212
import '../utils.dart';
13-
import 'shared.dart';
13+
import 'file_tests.dart';
14+
import 'link_tests.dart';
1415

1516
void main() {
1617
watcherFactory = MacOSDirectoryWatcher.new;
1718

18-
sharedTests();
19+
fileTests();
20+
linkTests();
1921

2022
test('DirectoryWatcher creates a MacOSDirectoryWatcher on Mac OS', () {
2123
expect(DirectoryWatcher('.'), const TypeMatcher<MacOSDirectoryWatcher>());

pkgs/watcher/test/directory_watcher/polling_test.dart

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -9,14 +9,14 @@ import 'package:test/test.dart';
99
import 'package:watcher/watcher.dart';
1010

1111
import '../utils.dart';
12-
import 'shared.dart';
12+
import 'file_tests.dart';
1313

1414
void main() {
1515
// Use a short delay to make the tests run quickly.
1616
watcherFactory = (dir) => PollingDirectoryWatcher(dir,
1717
pollingDelay: const Duration(milliseconds: 100));
1818

19-
sharedTests();
19+
fileTests();
2020

2121
test('does not notify if the modification time did not change', () async {
2222
writeFile('a.txt', contents: 'before');

pkgs/watcher/test/directory_watcher/windows_test.dart

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -15,12 +15,14 @@ import 'package:watcher/src/directory_watcher/windows.dart';
1515
import 'package:watcher/watcher.dart';
1616

1717
import '../utils.dart';
18-
import 'shared.dart';
18+
import 'file_tests.dart';
19+
import 'link_tests.dart';
1920

2021
void main() {
2122
watcherFactory = WindowsDirectoryWatcher.new;
2223

23-
group('Shared Tests:', sharedTests);
24+
fileTests();
25+
linkTests();
2426

2527
test('DirectoryWatcher creates a WindowsDirectoryWatcher on Windows', () {
2628
expect(DirectoryWatcher('.'), const TypeMatcher<WindowsDirectoryWatcher>());

pkgs/watcher/test/utils.dart

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -265,7 +265,7 @@ void writeLink({
265265
dir.createSync(recursive: true);
266266
}
267267

268-
Link(fullPath).createSync(target);
268+
Link(fullPath).createSync(p.join(d.sandbox, target));
269269

270270
if (updateModified) {
271271
link = p.normalize(link);
@@ -281,6 +281,17 @@ void deleteFile(String path) {
281281
_mockFileModificationTimes.remove(path);
282282
}
283283

284+
/// Schedules deleting a link in the sandbox at [path].
285+
///
286+
/// On Linux a link must be deleted with this method.
287+
/// TODO(davidmorgan): other platforms? Does this delete link or target?
288+
/// Check other delete links.
289+
void deleteLink(String path) {
290+
Link(p.join(d.sandbox, path)).deleteSync();
291+
292+
_mockFileModificationTimes.remove(path);
293+
}
294+
284295
/// Schedules renaming a file in the sandbox from [from] to [to].
285296
void renameFile(String from, String to) {
286297
File(p.join(d.sandbox, from)).renameSync(p.join(d.sandbox, to));

0 commit comments

Comments
 (0)