Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(192)

Side by Side Diff: pkg/watcher/test/utils.dart

Issue 18612013: File watching package. (Closed) Base URL: https://dart.googlecode.com/svn/branches/bleeding_edge/dart
Patch Set: "pathos" -> "path" Created 7 years, 5 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
« no previous file with comments | « pkg/watcher/test/directory_watcher_test.dart ('k') | utils/apidoc/apidoc.gyp » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
(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 library watcher.test.utils;
6
7 import 'dart:async';
8 import 'dart:io';
9
10 import 'package:path/path.dart';
11 import 'package:scheduled_test/scheduled_test.dart';
12 import 'package:unittest/compact_vm_config.dart';
13 import 'package:watcher/watcher.dart';
14 import 'package:watcher/src/stat.dart';
15
16 /// The path to the temporary sandbox created for each test. All file
17 /// operations are implicitly relative to this directory.
18 String _sandboxDir;
19
20 /// The [DirectoryWatcher] being used for the current scheduled test.
21 DirectoryWatcher _watcher;
22
23 /// The index in [_watcher]'s event stream for the next event. When event
24 /// expectations are set using [expectEvent] (et. al.), they use this to
25 /// expect a series of events in order.
26 var _nextEvent = 0;
27
28 /// The mock modification times (in milliseconds since epoch) for each file.
29 ///
30 /// The actual file system has pretty coarse granularity for file modification
31 /// times. This means using the real file system requires us to put delays in
32 /// the tests to ensure we wait long enough between operations for the mod time
33 /// to be different.
34 ///
35 /// Instead, we'll just mock that out. Each time a file is written, we manually
36 /// increment the mod time for that file instantly.
37 Map<String, int> _mockFileModificationTimes;
38
39 void initConfig() {
40 useCompactVMConfiguration();
41 }
42
43 /// Creates the sandbox directory the other functions in this library use and
44 /// ensures it's deleted when the test ends.
45 ///
46 /// This should usually be called by [setUp].
47 void createSandbox() {
48 var dir = new Directory("").createTempSync();
49 _sandboxDir = dir.path;
50
51 _mockFileModificationTimes = new Map<String, int>();
52 mockGetModificationTime((path) {
53 path = relative(path, from: _sandboxDir);
54
55 // Make sure we got a path in the sandbox.
56 assert(isRelative(path) && !path.startsWith(".."));
57
58 return new DateTime.fromMillisecondsSinceEpoch(
59 _mockFileModificationTimes[path]);
60 });
61
62 // Delete the sandbox when done.
63 currentSchedule.onComplete.schedule(() {
64 if (_sandboxDir != null) {
65 new Directory(_sandboxDir).deleteSync(recursive: true);
66 _sandboxDir = null;
67 }
68
69 _mockFileModificationTimes = null;
70 mockGetModificationTime(null);
71 }, "delete sandbox");
72 }
73
74 /// Creates a new [DirectoryWatcher] that watches a temporary directory.
75 ///
76 /// Normally, this will pause the schedule until the watcher is done scanning
77 /// and is polling for changes. If you pass `false` for [waitForReady], it will
78 /// not schedule this delay.
79 DirectoryWatcher createWatcher({bool waitForReady}) {
80 _watcher = new DirectoryWatcher(_sandboxDir);
81
82 // Wait until the scan is finished so that we don't miss changes to files
83 // that could occur before the scan completes.
84 if (waitForReady != false) {
85 schedule(() => _watcher.ready);
86 }
87
88 currentSchedule.onComplete.schedule(() {
89 _nextEvent = 0;
90 _watcher = null;
91 }, "reset watcher");
92
93 return _watcher;
94 }
95
96 void expectEvent(ChangeType type, String path) {
97 // Immediately create the future. This ensures we don't register too late and
98 // drop the event before we receive it.
99 var future = _watcher.events.elementAt(_nextEvent++).then((event) {
100 expect(event, new _ChangeMatcher(type, path));
101 });
102
103 // Make sure the schedule is watching it in case it fails.
104 currentSchedule.wrapFuture(future);
105
106 // Schedule it so that later file modifications don't occur until after this
107 // event is received.
108 schedule(() => future);
109 }
110
111 void expectAddEvent(String path) {
112 expectEvent(ChangeType.ADD, join(_sandboxDir, path));
113 }
114
115 void expectModifyEvent(String path) {
116 expectEvent(ChangeType.MODIFY, join(_sandboxDir, path));
117 }
118
119 void expectRemoveEvent(String path) {
120 expectEvent(ChangeType.REMOVE, join(_sandboxDir, path));
121 }
122
123 /// Schedules writing a file in the sandbox at [path] with [contents].
124 ///
125 /// If [contents] is omitted, creates an empty file. If [updatedModified] is
126 /// `false`, the mock file modification time is not changed.
127 void writeFile(String path, {String contents, bool updateModified}) {
128 if (contents == null) contents = "";
129 if (updateModified == null) updateModified = true;
130
131 schedule(() {
132 var fullPath = join(_sandboxDir, path);
133
134 // Create any needed subdirectories.
135 var dir = new Directory(dirname(fullPath));
136 if (!dir.existsSync()) {
137 dir.createSync(recursive: true);
138 }
139
140 new File(fullPath).writeAsStringSync(contents);
141
142 // Manually update the mock modification time for the file.
143 if (updateModified) {
144 var milliseconds = _mockFileModificationTimes.putIfAbsent(path, () => 0);
145 _mockFileModificationTimes[path]++;
146 }
147 });
148 }
149
150 /// Schedules deleting a file in the sandbox at [path].
151 void deleteFile(String path) {
152 schedule(() {
153 new File(join(_sandboxDir, path)).deleteSync();
154 });
155 }
156
157 /// Schedules renaming a file in the sandbox from [from] to [to].
158 ///
159 /// If [contents] is omitted, creates an empty file.
160 void renameFile(String from, String to) {
161 schedule(() {
162 new File(join(_sandboxDir, from)).renameSync(join(_sandboxDir, to));
163
164 // Manually update the mock modification time for the file.
165 var milliseconds = _mockFileModificationTimes.putIfAbsent(to, () => 0);
166 _mockFileModificationTimes[to]++;
167 });
168 }
169
170 /// A [Matcher] for [WatchEvent]s.
171 class _ChangeMatcher extends BaseMatcher {
172 /// The expected change.
173 final ChangeType type;
174
175 /// The expected path.
176 final String path;
177
178 _ChangeMatcher(this.type, this.path);
179
180 Description describe(Description description) {
181 description.add("$type $path");
182 }
183
184 bool matches(item, Map matchState) =>
185 item is WatchEvent && item.type == type && item.path == path;
186 }
OLDNEW
« no previous file with comments | « pkg/watcher/test/directory_watcher_test.dart ('k') | utils/apidoc/apidoc.gyp » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698