Skip to content

Commit 7929379

Browse files
authored
Add test coverage for file watcher and symlinks. (#2178)
1 parent d0e3edd commit 7929379

File tree

2 files changed

+196
-0
lines changed

2 files changed

+196
-0
lines changed
Lines changed: 168 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,168 @@
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({required bool isNative}) {
10+
setUp(() async {
11+
writeFile('target.txt');
12+
writeLink(link: 'link.txt', target: 'target.txt');
13+
});
14+
15+
test("doesn't notify if nothing is modified", () async {
16+
await startWatcher(path: 'link.txt');
17+
await expectNoEvents();
18+
});
19+
20+
test('notifies when a link is overwritten with an identical file', () async {
21+
await startWatcher(path: 'link.txt');
22+
writeFile('link.txt');
23+
await expectModifyEvent('link.txt');
24+
});
25+
26+
test('notifies when a link is overwritten with a different file', () async {
27+
await startWatcher(path: 'link.txt');
28+
writeFile('link.txt', contents: 'modified');
29+
await expectModifyEvent('link.txt');
30+
});
31+
32+
test(
33+
'notifies when a link target is overwritten with an identical file',
34+
() async {
35+
await startWatcher(path: 'link.txt');
36+
writeFile('target.txt');
37+
38+
// TODO(davidmorgan): reconcile differences.
39+
if (isNative) {
40+
await expectModifyEvent('link.txt');
41+
} else {
42+
await expectNoEvents();
43+
}
44+
},
45+
);
46+
47+
test('notifies when a link target is modified', () async {
48+
await startWatcher(path: 'link.txt');
49+
writeFile('target.txt', contents: 'modified');
50+
51+
// TODO(davidmorgan): reconcile differences.
52+
if (isNative) {
53+
await expectModifyEvent('link.txt');
54+
} else {
55+
await expectNoEvents();
56+
}
57+
});
58+
59+
test('notifies when a link is removed', () async {
60+
await startWatcher(path: 'link.txt');
61+
deleteFile('link.txt');
62+
63+
// TODO(davidmorgan): reconcile differences.
64+
if (isNative) {
65+
await expectNoEvents();
66+
} else {
67+
await expectRemoveEvent('link.txt');
68+
}
69+
});
70+
71+
test('notifies when a link target is removed', () async {
72+
await startWatcher(path: 'link.txt');
73+
deleteFile('target.txt');
74+
await expectRemoveEvent('link.txt');
75+
});
76+
77+
test('notifies when a link target is modified multiple times', () async {
78+
await startWatcher(path: 'link.txt');
79+
80+
writeFile('target.txt', contents: 'modified');
81+
82+
// TODO(davidmorgan): reconcile differences.
83+
if (isNative) {
84+
await expectModifyEvent('link.txt');
85+
} else {
86+
await expectNoEvents();
87+
}
88+
89+
writeFile('target.txt', contents: 'modified again');
90+
91+
// TODO(davidmorgan): reconcile differences.
92+
if (isNative) {
93+
await expectModifyEvent('link.txt');
94+
} else {
95+
await expectNoEvents();
96+
}
97+
});
98+
99+
test('notifies when a link is moved away', () async {
100+
await startWatcher(path: 'link.txt');
101+
renameFile('link.txt', 'new.txt');
102+
103+
// TODO(davidmorgan): reconcile differences.
104+
if (isNative) {
105+
await expectNoEvents();
106+
} else {
107+
await expectRemoveEvent('link.txt');
108+
}
109+
});
110+
111+
test('notifies when a link target is moved away', () async {
112+
await startWatcher(path: 'link.txt');
113+
renameFile('target.txt', 'new.txt');
114+
await expectRemoveEvent('link.txt');
115+
});
116+
117+
test('notifies when an identical file is moved over the link', () async {
118+
await startWatcher(path: 'link.txt');
119+
writeFile('old.txt');
120+
renameFile('old.txt', 'link.txt');
121+
122+
// TODO(davidmorgan): reconcile differences.
123+
if (isNative) {
124+
await expectNoEvents();
125+
} else {
126+
await expectModifyEvent('link.txt');
127+
}
128+
});
129+
130+
test('notifies when an different file is moved over the link', () async {
131+
await startWatcher(path: 'link.txt');
132+
writeFile('old.txt', contents: 'modified');
133+
renameFile('old.txt', 'link.txt');
134+
135+
// TODO(davidmorgan): reconcile differences.
136+
if (isNative) {
137+
await expectNoEvents();
138+
} else {
139+
await expectModifyEvent('link.txt');
140+
}
141+
});
142+
143+
test('notifies when an identical file is moved over the target', () async {
144+
await startWatcher(path: 'link.txt');
145+
writeFile('old.txt');
146+
renameFile('old.txt', 'target.txt');
147+
148+
// TODO(davidmorgan): reconcile differences.
149+
if (isNative) {
150+
await expectModifyEvent('link.txt');
151+
} else {
152+
await expectNoEvents();
153+
}
154+
});
155+
156+
test('notifies when a different file is moved over the target', () async {
157+
await startWatcher(path: 'link.txt');
158+
writeFile('old.txt', contents: 'modified');
159+
renameFile('old.txt', 'target.txt');
160+
161+
// TODO(davidmorgan): reconcile differences.
162+
if (isNative) {
163+
await expectModifyEvent('link.txt');
164+
} else {
165+
await expectNoEvents();
166+
}
167+
});
168+
}

pkgs/watcher/test/utils.dart

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -246,6 +246,34 @@ void writeFile(String path, {String? contents, bool? updateModified}) {
246246
}
247247
}
248248

249+
/// Schedules writing a file in the sandbox at [link] pointing to [target].
250+
///
251+
/// If [updateModified] is `false`, the mock file modification time is not
252+
/// changed.
253+
void writeLink({
254+
required String link,
255+
required String target,
256+
bool? updateModified,
257+
}) {
258+
updateModified ??= true;
259+
260+
var fullPath = p.join(d.sandbox, link);
261+
262+
// Create any needed subdirectories.
263+
var dir = Directory(p.dirname(fullPath));
264+
if (!dir.existsSync()) {
265+
dir.createSync(recursive: true);
266+
}
267+
268+
Link(fullPath).createSync(target);
269+
270+
if (updateModified) {
271+
link = p.normalize(link);
272+
273+
_mockFileModificationTimes[link] = _nextTimestamp++;
274+
}
275+
}
276+
249277
/// Schedules deleting a file in the sandbox at [path].
250278
void deleteFile(String path) {
251279
File(p.join(d.sandbox, path)).deleteSync();

0 commit comments

Comments
 (0)