| OLD | NEW |
| (Empty) |
| 1 // Copyright (c) 2012, 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:scheduled_test/scheduled_test.dart'; | |
| 6 import 'package:watcher/src/utils.dart'; | |
| 7 | |
| 8 import '../utils.dart'; | |
| 9 | |
| 10 void sharedTests() { | |
| 11 test('does not notify for files that already exist when started', () { | |
| 12 // Make some pre-existing files. | |
| 13 writeFile("a.txt"); | |
| 14 writeFile("b.txt"); | |
| 15 | |
| 16 startWatcher(); | |
| 17 | |
| 18 // Change one after the watcher is running. | |
| 19 writeFile("b.txt", contents: "modified"); | |
| 20 | |
| 21 // We should get a modify event for the changed file, but no add events | |
| 22 // for them before this. | |
| 23 expectModifyEvent("b.txt"); | |
| 24 }); | |
| 25 | |
| 26 test('notifies when a file is added', () { | |
| 27 startWatcher(); | |
| 28 writeFile("file.txt"); | |
| 29 expectAddEvent("file.txt"); | |
| 30 }); | |
| 31 | |
| 32 test('notifies when a file is modified', () { | |
| 33 writeFile("file.txt"); | |
| 34 startWatcher(); | |
| 35 writeFile("file.txt", contents: "modified"); | |
| 36 expectModifyEvent("file.txt"); | |
| 37 }); | |
| 38 | |
| 39 test('notifies when a file is removed', () { | |
| 40 writeFile("file.txt"); | |
| 41 startWatcher(); | |
| 42 deleteFile("file.txt"); | |
| 43 expectRemoveEvent("file.txt"); | |
| 44 }); | |
| 45 | |
| 46 test('notifies when a file is modified multiple times', () { | |
| 47 writeFile("file.txt"); | |
| 48 startWatcher(); | |
| 49 writeFile("file.txt", contents: "modified"); | |
| 50 expectModifyEvent("file.txt"); | |
| 51 writeFile("file.txt", contents: "modified again"); | |
| 52 expectModifyEvent("file.txt"); | |
| 53 }); | |
| 54 | |
| 55 test('notifies even if the file contents are unchanged', () { | |
| 56 writeFile("a.txt", contents: "same"); | |
| 57 writeFile("b.txt", contents: "before"); | |
| 58 startWatcher(); | |
| 59 | |
| 60 writeFile("a.txt", contents: "same"); | |
| 61 writeFile("b.txt", contents: "after"); | |
| 62 inAnyOrder([ | |
| 63 isModifyEvent("a.txt"), | |
| 64 isModifyEvent("b.txt") | |
| 65 ]); | |
| 66 }); | |
| 67 | |
| 68 test('when the watched directory is deleted, removes all files', () { | |
| 69 writeFile("dir/a.txt"); | |
| 70 writeFile("dir/b.txt"); | |
| 71 | |
| 72 startWatcher(dir: "dir"); | |
| 73 | |
| 74 deleteDir("dir"); | |
| 75 inAnyOrder([ | |
| 76 isRemoveEvent("dir/a.txt"), | |
| 77 isRemoveEvent("dir/b.txt") | |
| 78 ]); | |
| 79 }); | |
| 80 | |
| 81 test('when the watched directory is moved, removes all files', () { | |
| 82 writeFile("dir/a.txt"); | |
| 83 writeFile("dir/b.txt"); | |
| 84 | |
| 85 startWatcher(dir: "dir"); | |
| 86 | |
| 87 renameDir("dir", "moved_dir"); | |
| 88 createDir("dir"); | |
| 89 inAnyOrder([ | |
| 90 isRemoveEvent("dir/a.txt"), | |
| 91 isRemoveEvent("dir/b.txt") | |
| 92 ]); | |
| 93 }); | |
| 94 | |
| 95 group("moves", () { | |
| 96 test('notifies when a file is moved within the watched directory', () { | |
| 97 writeFile("old.txt"); | |
| 98 startWatcher(); | |
| 99 renameFile("old.txt", "new.txt"); | |
| 100 | |
| 101 inAnyOrder([ | |
| 102 isAddEvent("new.txt"), | |
| 103 isRemoveEvent("old.txt") | |
| 104 ]); | |
| 105 }); | |
| 106 | |
| 107 test('notifies when a file is moved from outside the watched directory', | |
| 108 () { | |
| 109 writeFile("old.txt"); | |
| 110 createDir("dir"); | |
| 111 startWatcher(dir: "dir"); | |
| 112 | |
| 113 renameFile("old.txt", "dir/new.txt"); | |
| 114 expectAddEvent("dir/new.txt"); | |
| 115 }); | |
| 116 | |
| 117 test('notifies when a file is moved outside the watched directory', () { | |
| 118 writeFile("dir/old.txt"); | |
| 119 startWatcher(dir: "dir"); | |
| 120 | |
| 121 renameFile("dir/old.txt", "new.txt"); | |
| 122 expectRemoveEvent("dir/old.txt"); | |
| 123 }); | |
| 124 }); | |
| 125 | |
| 126 // Most of the time, when multiple filesystem actions happen in sequence, | |
| 127 // they'll be batched together and the watcher will see them all at once. | |
| 128 // These tests verify that the watcher normalizes and combine these events | |
| 129 // properly. However, very occasionally the events will be reported in | |
| 130 // separate batches, and the watcher will report them as though they occurred | |
| 131 // far apart in time, so each of these tests has a "backup case" to allow for | |
| 132 // that as well. | |
| 133 group("clustered changes", () { | |
| 134 test("doesn't notify when a file is created and then immediately removed", | |
| 135 () { | |
| 136 startWatcher(); | |
| 137 writeFile("file.txt"); | |
| 138 deleteFile("file.txt"); | |
| 139 | |
| 140 // Backup case. | |
| 141 startClosingEventStream(); | |
| 142 allowEvents(() { | |
| 143 expectAddEvent("file.txt"); | |
| 144 expectRemoveEvent("file.txt"); | |
| 145 }); | |
| 146 }); | |
| 147 | |
| 148 test("reports a modification when a file is deleted and then immediately " | |
| 149 "recreated", () { | |
| 150 writeFile("file.txt"); | |
| 151 startWatcher(); | |
| 152 | |
| 153 deleteFile("file.txt"); | |
| 154 writeFile("file.txt", contents: "re-created"); | |
| 155 | |
| 156 allowEither(() { | |
| 157 expectModifyEvent("file.txt"); | |
| 158 }, () { | |
| 159 // Backup case. | |
| 160 expectRemoveEvent("file.txt"); | |
| 161 expectAddEvent("file.txt"); | |
| 162 }); | |
| 163 }); | |
| 164 | |
| 165 test("reports a modification when a file is moved and then immediately " | |
| 166 "recreated", () { | |
| 167 writeFile("old.txt"); | |
| 168 startWatcher(); | |
| 169 | |
| 170 renameFile("old.txt", "new.txt"); | |
| 171 writeFile("old.txt", contents: "re-created"); | |
| 172 | |
| 173 allowEither(() { | |
| 174 inAnyOrder([ | |
| 175 isModifyEvent("old.txt"), | |
| 176 isAddEvent("new.txt") | |
| 177 ]); | |
| 178 }, () { | |
| 179 // Backup case. | |
| 180 expectRemoveEvent("old.txt"); | |
| 181 expectAddEvent("new.txt"); | |
| 182 expectAddEvent("old.txt"); | |
| 183 }); | |
| 184 }); | |
| 185 | |
| 186 test("reports a removal when a file is modified and then immediately " | |
| 187 "removed", () { | |
| 188 writeFile("file.txt"); | |
| 189 startWatcher(); | |
| 190 | |
| 191 writeFile("file.txt", contents: "modified"); | |
| 192 deleteFile("file.txt"); | |
| 193 | |
| 194 // Backup case. | |
| 195 allowModifyEvent("file.txt"); | |
| 196 | |
| 197 expectRemoveEvent("file.txt"); | |
| 198 }); | |
| 199 | |
| 200 test("reports an add when a file is added and then immediately modified", | |
| 201 () { | |
| 202 startWatcher(); | |
| 203 | |
| 204 writeFile("file.txt"); | |
| 205 writeFile("file.txt", contents: "modified"); | |
| 206 | |
| 207 expectAddEvent("file.txt"); | |
| 208 | |
| 209 // Backup case. | |
| 210 startClosingEventStream(); | |
| 211 allowModifyEvent("file.txt"); | |
| 212 }); | |
| 213 }); | |
| 214 | |
| 215 group("subdirectories", () { | |
| 216 test('watches files in subdirectories', () { | |
| 217 startWatcher(); | |
| 218 writeFile("a/b/c/d/file.txt"); | |
| 219 expectAddEvent("a/b/c/d/file.txt"); | |
| 220 }); | |
| 221 | |
| 222 test('notifies when a subdirectory is moved within the watched directory ' | |
| 223 'and then its contents are modified', () { | |
| 224 writeFile("old/file.txt"); | |
| 225 startWatcher(); | |
| 226 | |
| 227 renameDir("old", "new"); | |
| 228 inAnyOrder([ | |
| 229 isRemoveEvent("old/file.txt"), | |
| 230 isAddEvent("new/file.txt") | |
| 231 ]); | |
| 232 | |
| 233 writeFile("new/file.txt", contents: "modified"); | |
| 234 expectModifyEvent("new/file.txt"); | |
| 235 }); | |
| 236 | |
| 237 test('emits events for many nested files added at once', () { | |
| 238 withPermutations((i, j, k) => | |
| 239 writeFile("sub/sub-$i/sub-$j/file-$k.txt")); | |
| 240 | |
| 241 createDir("dir"); | |
| 242 startWatcher(dir: "dir"); | |
| 243 renameDir("sub", "dir/sub"); | |
| 244 | |
| 245 inAnyOrder(withPermutations((i, j, k) => | |
| 246 isAddEvent("dir/sub/sub-$i/sub-$j/file-$k.txt"))); | |
| 247 }); | |
| 248 | |
| 249 test('emits events for many nested files removed at once', () { | |
| 250 withPermutations((i, j, k) => | |
| 251 writeFile("dir/sub/sub-$i/sub-$j/file-$k.txt")); | |
| 252 | |
| 253 createDir("dir"); | |
| 254 startWatcher(dir: "dir"); | |
| 255 | |
| 256 // Rename the directory rather than deleting it because native watchers | |
| 257 // report a rename as a single DELETE event for the directory, whereas | |
| 258 // they report recursive deletion with DELETE events for every file in the | |
| 259 // directory. | |
| 260 renameDir("dir/sub", "sub"); | |
| 261 | |
| 262 inAnyOrder(withPermutations((i, j, k) => | |
| 263 isRemoveEvent("dir/sub/sub-$i/sub-$j/file-$k.txt"))); | |
| 264 }); | |
| 265 | |
| 266 test('emits events for many nested files moved at once', () { | |
| 267 withPermutations((i, j, k) => | |
| 268 writeFile("dir/old/sub-$i/sub-$j/file-$k.txt")); | |
| 269 | |
| 270 createDir("dir"); | |
| 271 startWatcher(dir: "dir"); | |
| 272 renameDir("dir/old", "dir/new"); | |
| 273 | |
| 274 inAnyOrder(unionAll(withPermutations((i, j, k) { | |
| 275 return new Set.from([ | |
| 276 isRemoveEvent("dir/old/sub-$i/sub-$j/file-$k.txt"), | |
| 277 isAddEvent("dir/new/sub-$i/sub-$j/file-$k.txt") | |
| 278 ]); | |
| 279 }))); | |
| 280 }); | |
| 281 | |
| 282 test("emits events for many files added at once in a subdirectory with the " | |
| 283 "same name as a removed file", () { | |
| 284 writeFile("dir/sub"); | |
| 285 withPermutations((i, j, k) => | |
| 286 writeFile("old/sub-$i/sub-$j/file-$k.txt")); | |
| 287 startWatcher(dir: "dir"); | |
| 288 | |
| 289 deleteFile("dir/sub"); | |
| 290 renameDir("old", "dir/sub"); | |
| 291 | |
| 292 var events = withPermutations((i, j, k) => | |
| 293 isAddEvent("dir/sub/sub-$i/sub-$j/file-$k.txt")); | |
| 294 events.add(isRemoveEvent("dir/sub")); | |
| 295 inAnyOrder(events); | |
| 296 }); | |
| 297 }); | |
| 298 } | |
| OLD | NEW |