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

Side by Side Diff: utils/tests/pub/test_pub.dart

Issue 10356133: Reverting 7566, which is causing build breakage. (Closed) Base URL: https://dart.googlecode.com/svn/branches/bleeding_edge/dart
Patch Set: Created 8 years, 7 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 | « utils/tests/pub/pub_test.dart ('k') | no next file » | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file 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 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. 3 // BSD-style license that can be found in the LICENSE file.
4 4
5 /** 5 /**
6 * Test infrastructure for testing pub. Unlike typical unit tests, most pub 6 * Test infrastructure for testing pub. Unlike typical unit tests, most pub
7 * tests are integration tests that stage some stuff on the file system, run 7 * tests are integration tests that stage some stuff on the file system, run
8 * pub, and then validate the results. This library provides an API to build 8 * pub, and then validate the results. This library provides an API to build
9 * tests like that. 9 * tests like that.
10 */ 10 */
(...skipping 10 matching lines...) Expand all
21 */ 21 */
22 FileDescriptor file(String name, String contents) => 22 FileDescriptor file(String name, String contents) =>
23 new FileDescriptor(name, contents); 23 new FileDescriptor(name, contents);
24 24
25 /** 25 /**
26 * Creates a new [DirectoryDescriptor] with [name] and [contents]. 26 * Creates a new [DirectoryDescriptor] with [name] and [contents].
27 */ 27 */
28 DirectoryDescriptor dir(String name, [List<Descriptor> contents]) => 28 DirectoryDescriptor dir(String name, [List<Descriptor> contents]) =>
29 new DirectoryDescriptor(name, contents); 29 new DirectoryDescriptor(name, contents);
30 30
31 /** 31 void testPub(String description, [List<Descriptor> cache, Descriptor app,
32 * The path of the package cache directory used for tests. Relative to the 32 List<String> args, List<Descriptor> expectedPackageDir,
33 * sandbox directory. 33 List<Descriptor> sdk, String output, int exitCode = 0]) {
34 */ 34 asyncTest(description, 1, () {
35 final String cachePath = "cache"; 35 var createdSandboxDir;
36 var createdAppDir;
37 var createdSdkDir;
36 38
37 /** 39 deleteSandboxIfCreated() {
38 * The path of the mock SDK directory used for tests. Relative to the sandbox 40 if (createdSandboxDir != null) {
39 * directory. 41 deleteDir(createdSandboxDir).then((_) {
40 */ 42 callbackDone();
41 final String sdkPath = "sdk"; 43 });
44 } else {
45 callbackDone();
46 }
47 }
42 48
43 /** 49 final future = _setUpSandbox().chain((sandboxDir) {
44 * The path of the mock app directory used for tests. Relative to the sandbox 50 createdSandboxDir = sandboxDir;
45 * directory. 51 return _setUpApp(sandboxDir, app);
46 */ 52 }).chain((appDir) {
47 final String appPath = "myapp"; 53 createdAppDir = appDir;
54 return _setUpSdk(createdSandboxDir, sdk);
55 }).chain((sdkDir) {
56 createdSdkDir = sdkDir;
57 return _setUpCache(createdSandboxDir, cache);
58 }).chain((cacheDir) {
59 var workingDir;
60 if (createdAppDir != null) workingDir = createdAppDir.path;
48 61
49 /** 62 if (cacheDir != null) {
50 * The path of the packages directory in the mock app used for tests. Relative 63 // TODO(rnystrom): Hack in the cache directory path. Should pass this
51 * to the sandbox directory. 64 // in using environment var once #752 is done.
52 */ 65 args.add('--cachedir=${getFullPath(cacheDir)}');
53 final String packagesPath = "$appPath/packages"; 66 }
54 67
55 /** 68 if (createdSdkDir != null) {
56 * The type for callbacks that will be fired during [runPub]. Takes the sandbox 69 // TODO(rnystrom): Hack in the SDK path. Should pass this in using
57 * directory as a parameter. 70 // environment var once #752 is done.
58 */ 71 args.add('--sdkdir=${getFullPath(createdSdkDir)}');
59 typedef Future _ScheduledEvent(Directory parentDir); 72 }
60 73
61 /** 74 return _runPub(args, workingDir);
62 * The list of events that are scheduled to run after the sandbox directory has 75 }).chain((result) {
63 * been created but before Pub is run. 76 _validateOutput(output, result.stdout);
64 */
65 List<_ScheduledEvent> _scheduledBeforePub;
66 77
67 /** 78 Expect.equals(result.stderr.length, 0,
68 * The list of events that are scheduled to run after Pub has been run. 79 'Did not expect any output on stderr, and got:\n' +
69 */ 80 Strings.join(result.stderr, '\n'));
70 List<_ScheduledEvent> _scheduledAfterPub;
71 81
72 void runPub([List<String> args, String output, int exitCode = 0]) { 82 Expect.equals(result.exitCode, exitCode,
73 var createdSandboxDir; 83 'Pub returned exit code ${result.exitCode}, expected $exitCode.');
74 84
75 var asyncDone = expectAsync0(() {}); 85 return _validateExpectedPackages(createdAppDir, expectedPackageDir);
86 });
76 87
77 deleteSandboxIfCreated(onDeleted()) { 88 future.then((error) {
78 _scheduledBeforePub = null; 89 // Null means there were no errors.
79 _scheduledAfterPub = null; 90 if (error != null) Expect.fail(error);
80 if (createdSandboxDir != null) {
81 deleteDir(createdSandboxDir).then((_) => onDeleted());
82 } else {
83 onDeleted();
84 }
85 }
86 91
87 String pathInSandbox(path) => join(getFullPath(createdSandboxDir), path); 92 deleteSandboxIfCreated();
93 });
88 94
89 final future = _setUpSandbox().chain((sandboxDir) { 95 future.handleException((error) {
90 createdSandboxDir = sandboxDir; 96 deleteSandboxIfCreated();
91 return _runScheduled(sandboxDir, _scheduledBeforePub); 97 // If we encounter an error, we want to pass it to the test framework. In
92 }).chain((_) { 98 // order to get the stack trace information, we need to re-throw and
93 return ensureDir(pathInSandbox(appPath)); 99 // re-catch it.
94 }).chain((_) { 100 try {
95 // TODO(rnystrom): Hack in the cache directory path. Should pass this 101 throw error;
96 // in using environment var once #752 is done. 102 } catch (var e, var stack) {
97 args.add('--cachedir=${pathInSandbox(cachePath)}'); 103 reportTestError('$e', '$stack');
98 104 }
99 // TODO(rnystrom): Hack in the SDK path. Should pass this in using 105 return true;
100 // environment var once #752 is done.
101 args.add('--sdkdir=${pathInSandbox(sdkPath)}');
102
103 return _runPub(args, pathInSandbox(appPath));
104 }).chain((result) {
105 _validateOutput(output, result.stdout);
106
107 Expect.equals(result.stderr.length, 0,
108 'Did not expect any output on stderr, and got:\n' +
109 Strings.join(result.stderr, '\n'));
110
111 Expect.equals(result.exitCode, exitCode,
112 'Pub returned exit code ${result.exitCode}, expected $exitCode.');
113
114 return _runScheduled(createdSandboxDir, _scheduledAfterPub);
115 });
116
117 future.then((_) {
118 deleteSandboxIfCreated(asyncDone);
119 });
120
121 future.handleException((error) {
122 // If an error occurs during testing, delete the sandbox, throw the error so
123 // that the test framework sees it, then finally call asyncDone so that the
124 // test framework knows we're done doing asynchronous stuff.
125 deleteSandboxIfCreated(() {
126 guardAsync(() { throw error; }, asyncDone);
127 }); 106 });
128 return true;
129 }); 107 });
130 } 108 }
131 109
132 Future<Directory> _setUpSandbox() { 110 Future<Directory> _setUpSandbox() {
133 return createTempDir('pub-test-sandbox-'); 111 return createTempDir('pub-test-sandbox-');
134 } 112 }
135 113
136 _runScheduled(Directory parentDir, List<_ScheduledEvent> scheduled) { 114 Future _setUpCache(Directory sandboxDir, List<Descriptor> cache) {
137 if (scheduled == null) return new Future.immediate(null); 115 // No cache.
138 var future = Futures.wait(scheduled.map((event) => event(parentDir))); 116 if (cache == null) return new Future.immediate(null);
139 scheduled.clear(); 117
140 return future; 118 return dir('pub-cache', cache).create(sandboxDir);
119 }
120
121 Future _setUpApp(Directory sandboxDir, Descriptor app) {
122 // No app directory.
123 if (app == null) return new Future.immediate(null);
124
125 return app.create(sandboxDir);
126 }
127
128 Future _setUpSdk(Directory sandboxDir, List<Descriptor> sdk) {
129 // No SDK directory.
130 if (sdk == null) return new Future.immediate(null);
131
132 return dir('sdk', sdk).create(sandboxDir);
141 } 133 }
142 134
143 Future<ProcessResult> _runPub(List<String> pubArgs, String workingDir) { 135 Future<ProcessResult> _runPub(List<String> pubArgs, String workingDir) {
144 // Find a dart executable we can use to run pub. Uses the one that the 136 // Find a dart executable we can use to run pub. Uses the one that the
145 // test infrastructure uses. 137 // test infrastructure uses.
146 final scriptDir = new File(new Options().script).directorySync().path; 138 final scriptDir = new File(new Options().script).directorySync().path;
147 final platform = Platform.operatingSystem; 139 final platform = Platform.operatingSystem;
148 final dartBin = new File(new Options().executable).fullPathSync(); 140 final dartBin = new File(new Options().executable).fullPathSync();
149 141
150 // Find the main pub entrypoint. 142 // Find the main pub entrypoint.
151 final pubPath = fs.joinPaths(scriptDir, '../../pub/pub.dart'); 143 final pubPath = fs.joinPaths(scriptDir, '../../pub/pub.dart');
152 144
153 final args = ['--enable-type-checks', '--enable-asserts', pubPath]; 145 final args = ['--enable-type-checks', '--enable-asserts', pubPath];
154 args.addAll(pubArgs); 146 args.addAll(pubArgs);
155 147
156 return runProcess(dartBin, args, workingDir); 148 return runProcess(dartBin, args, workingDir);
157 } 149 }
158 150
159 /** 151 /**
152 * Validates the contents of the "packages" directory inside [appDir] against
153 * [expectedPackageDir].
154 */
155 Future<String> _validateExpectedPackages(Directory appDir,
156 List<Descriptor> expectedPackageDir) {
157 // No expectation.
158 if (expectedPackageDir == null) return new Future.immediate(null);
159
160 return dir('packages', expectedPackageDir).validate(appDir.path);
161 }
162
163 /**
160 * Compares the [actual] output from running pub with [expectedText]. Ignores 164 * Compares the [actual] output from running pub with [expectedText]. Ignores
161 * leading and trailing whitespace differences and tries to report the 165 * leading and trailing whitespace differences and tries to report the
162 * offending difference in a nice way. 166 * offending difference in a nice way.
163 */ 167 */
164 void _validateOutput(String expectedText, List<String> actual) { 168 void _validateOutput(String expectedText, List<String> actual) {
165 final expected = expectedText.split('\n'); 169 final expected = expectedText.split('\n');
166 170
167 // Strip off the last line. This lets us have expected multiline strings 171 // Strip off the last line. This lets us have expected multiline strings
168 // where the closing ''' is on its own line. It also fixes '' expected output 172 // where the closing ''' is on its own line. It also fixes '' expected output
169 // to expect zero lines of output, not a single empty line. 173 // to expect zero lines of output, not a single empty line.
(...skipping 45 matching lines...) Expand 10 before | Expand all | Expand 10 after
215 219
216 /** 220 /**
217 * Creates the file or directory within [dir]. Returns a [Future] that is 221 * Creates the file or directory within [dir]. Returns a [Future] that is
218 * completed after the creation is done. 222 * completed after the creation is done.
219 */ 223 */
220 abstract Future create(dir); 224 abstract Future create(dir);
221 225
222 /** 226 /**
223 * Validates that this descriptor correctly matches the corresponding file 227 * Validates that this descriptor correctly matches the corresponding file
224 * system entry within [dir]. Returns a [Future] that completes to `null` if 228 * system entry within [dir]. Returns a [Future] that completes to `null` if
225 * the entry is valid, or throws an error if it failed. 229 * the entry is valid, or a message describing the error if it failed.
226 */ 230 */
227 abstract Future validate(String dir); 231 abstract Future<String> validate(String dir);
228
229 /**
230 * Schedules the directory to be created before Pub is run with [runPub]. The
231 * directory will be created relative to the sandbox directory.
232 */
233 void scheduleCreate() => _scheduleBeforePub(create);
234
235 /**
236 * Schedules the directory to be validated after Pub is run with [runPub]. The
237 * directory will be validated relative to the sandbox directory.
238 */
239 void scheduleValidate() =>
240 _scheduleAfterPub((parentDir) => validate(parentDir));
241 } 232 }
242 233
243 /** 234 /**
244 * Describes a file. These are used both for setting up an expected directory 235 * Describes a file. These are used both for setting up an expected directory
245 * tree before running a test, and for validating that the file system matches 236 * tree before running a test, and for validating that the file system matches
246 * some expectations after running it. 237 * some expectations after running it.
247 */ 238 */
248 class FileDescriptor extends Descriptor { 239 class FileDescriptor extends Descriptor {
249 /** 240 /**
250 * The text contents of the file. 241 * The text contents of the file.
251 */ 242 */
252 final String contents; 243 final String contents;
253 244
254 FileDescriptor(String name, this.contents) : super(name); 245 FileDescriptor(String name, this.contents) : super(name);
255 246
256 /** 247 /**
257 * Creates the file within [dir]. Returns a [Future] that is completed after 248 * Creates the file within [dir]. Returns a [Future] that is completed after
258 * the creation is done. 249 * the creation is done.
259 */ 250 */
260 Future<File> create(dir) { 251 Future<File> create(dir) {
261 return writeTextFile(join(dir, name), contents); 252 return writeTextFile(join(dir, name), contents);
262 } 253 }
263 254
264 /** 255 /**
265 * Validates that this file correctly matches the actual file at [path]. 256 * Validates that this file correctly matches the actual file at [path].
266 */ 257 */
267 Future validate(String path) { 258 Future<String> validate(String path) {
268 path = join(path, name); 259 path = join(path, name);
269 return fileExists(path).chain((exists) { 260 return fileExists(path).chain((exists) {
270 if (!exists) Expect.fail('Expected file $path does not exist.'); 261 if (!exists) {
262 return new Future.immediate('Expected file $path does not exist.');
263 }
271 264
272 return readTextFile(path).transform((text) { 265 return readTextFile(path).transform((text) {
273 if (text == contents) return null; 266 if (text == contents) return null;
274 267
275 Expect.fail('File $path should contain:\n\n$contents\n\n' 268 return 'File $path should contain:\n\n$contents\n\n'
276 'but contained:\n\n$text'); 269 'but contained:\n\n$text';
277 }); 270 });
278 }); 271 });
279 } 272 }
280 } 273 }
281 274
282 /** 275 /**
283 * Describes a directory and its contents. These are used both for setting up 276 * Describes a directory and its contents. These are used both for setting up
284 * an expected directory tree before running a test, and for validating that 277 * an expected directory tree before running a test, and for validating that
285 * the file system matches some expectations after running it. 278 * the file system matches some expectations after running it.
286 */ 279 */
(...skipping 28 matching lines...) Expand all
315 308
316 return completer.future; 309 return completer.future;
317 } 310 }
318 311
319 /** 312 /**
320 * Validates that the directory at [path] contains all of the expected 313 * Validates that the directory at [path] contains all of the expected
321 * contents in this descriptor. Note that this does *not* check that the 314 * contents in this descriptor. Note that this does *not* check that the
322 * directory doesn't contain other unexpected stuff, just that it *does* 315 * directory doesn't contain other unexpected stuff, just that it *does*
323 * contain the stuff we do expect. 316 * contain the stuff we do expect.
324 */ 317 */
325 Future validate(String path) { 318 Future<String> validate(String path) {
326 // Validate each of the items in this directory. 319 // Validate each of the items in this directory.
327 final entryFutures = contents.map( 320 final entryFutures = contents.map(
328 (entry) => entry.validate(join(path, name))); 321 (entry) => entry.validate(join(path, name)));
329 322
330 // If they are all valid, the directory is valid. 323 // If they are all valid, the directory is valid.
331 return Futures.wait(entryFutures).transform((entries) => null); 324 return Futures.wait(entryFutures).transform((entries) {
325 for (final entry in entries) {
326 if (entry != null) return entry;
327 }
328
329 // If we got here, all of the sub-entries were valid.
330 return null;
331 });
332 } 332 }
333 } 333 }
334
335 /**
336 * Schedules a callback to be called before Pub is run with [runPub].
337 */
338 void _scheduleBeforePub(_ScheduledEvent event) {
339 if (_scheduledBeforePub == null) _scheduledBeforePub = [];
340 _scheduledBeforePub.add(event);
341 }
342
343 /**
344 * Schedules a callback to be called after Pub is run with [runPub].
345 */
346 void _scheduleAfterPub(_ScheduledEvent event) {
347 if (_scheduledAfterPub == null) _scheduledAfterPub = [];
348 _scheduledAfterPub.add(event);
349 }
OLDNEW
« no previous file with comments | « utils/tests/pub/pub_test.dart ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698