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

Side by Side Diff: sdk/lib/_internal/pub/test/test_pub.dart

Issue 164773003: Change ScheduledProcess's output streams over to be ScheduledStreams. (Closed) Base URL: https://dart.googlecode.com/svn/branches/bleeding_edge/dart
Patch Set: update pubspecs Created 6 years, 10 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
OLDNEW
1 // Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file 1 // Copyright (c) 2013, 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 /// Test infrastructure for testing pub. Unlike typical unit tests, most pub 5 /// Test infrastructure for testing pub. Unlike typical unit tests, most pub
6 /// tests are integration tests that stage some stuff on the file system, run 6 /// tests are integration tests that stage some stuff on the file system, run
7 /// pub, and then validate the results. This library provides an API to build 7 /// pub, and then validate the results. This library provides an API to build
8 /// tests like that. 8 /// tests like that.
9 library test_pub; 9 library test_pub;
10 10
11 import 'dart:async'; 11 import 'dart:async';
12 import 'dart:convert'; 12 import 'dart:convert';
13 import 'dart:io'; 13 import 'dart:io';
14 import 'dart:math'; 14 import 'dart:math';
15 15
16 import 'package:http/testing.dart'; 16 import 'package:http/testing.dart';
17 import 'package:path/path.dart' as path; 17 import 'package:path/path.dart' as path;
18 import 'package:scheduled_test/scheduled_process.dart'; 18 import 'package:scheduled_test/scheduled_process.dart';
19 import 'package:scheduled_test/scheduled_server.dart'; 19 import 'package:scheduled_test/scheduled_server.dart';
20 import 'package:scheduled_test/scheduled_stream.dart';
20 import 'package:scheduled_test/scheduled_test.dart'; 21 import 'package:scheduled_test/scheduled_test.dart';
21 import 'package:unittest/compact_vm_config.dart'; 22 import 'package:unittest/compact_vm_config.dart';
22 import 'package:yaml/yaml.dart'; 23 import 'package:yaml/yaml.dart';
23 24
24 import '../lib/src/entrypoint.dart'; 25 import '../lib/src/entrypoint.dart';
25 import '../lib/src/exit_codes.dart' as exit_codes; 26 import '../lib/src/exit_codes.dart' as exit_codes;
26 // TODO(rnystrom): Using "gitlib" as the prefix here is ugly, but "git" collides 27 // TODO(rnystrom): Using "gitlib" as the prefix here is ugly, but "git" collides
27 // with the git descriptor method. Maybe we should try to clean up the top level 28 // with the git descriptor method. Maybe we should try to clean up the top level
28 // scope a bit? 29 // scope a bit?
29 import '../lib/src/git.dart' as gitlib; 30 import '../lib/src/git.dart' as gitlib;
(...skipping 357 matching lines...) Expand 10 before | Expand all | Expand 10 after
387 // Cannot pass both output and outputJson. 388 // Cannot pass both output and outputJson.
388 assert(output == null || outputJson == null); 389 assert(output == null || outputJson == null);
389 390
390 var pub = startPub(args: args, tokenEndpoint: tokenEndpoint); 391 var pub = startPub(args: args, tokenEndpoint: tokenEndpoint);
391 pub.shouldExit(exitCode); 392 pub.shouldExit(exitCode);
392 393
393 var failures = []; 394 var failures = [];
394 var stderr; 395 var stderr;
395 396
396 expect(Future.wait([ 397 expect(Future.wait([
397 pub.remainingStdout(), 398 pub.stdoutStream().toList(),
398 pub.remainingStderr() 399 pub.stderrStream().toList()
399 ]).then((results) { 400 ]).then((results) {
400 stderr = results[1]; 401 var stdout = results[0].join("\n");
402 stderr = results[1].join("\n");
401 403
402 if (outputJson == null) { 404 if (outputJson == null) {
403 _validateOutput(failures, 'stdout', output, results[0]); 405 _validateOutput(failures, 'stdout', output, stdout);
404 return null; 406 return null;
405 } 407 }
406 408
407 // Allow the expected JSON to contain futures. 409 // Allow the expected JSON to contain futures.
408 return awaitObject(outputJson).then((resolved) { 410 return awaitObject(outputJson).then((resolved) {
409 _validateOutputJson(failures, 'stdout', resolved, results[0]); 411 _validateOutputJson(failures, 'stdout', resolved, stdout);
410 }); 412 });
411 }).then((_) { 413 }).then((_) {
412 _validateOutput(failures, 'stderr', error, stderr); 414 _validateOutput(failures, 'stderr', error, stderr);
413 415
414 if (!failures.isEmpty) throw new TestFailure(failures.join('\n')); 416 if (!failures.isEmpty) throw new TestFailure(failures.join('\n'));
415 }), completes); 417 }), completes);
416 } 418 }
417 419
418 /// Like [startPub], but runs `pub lish` in particular with [server] used both 420 /// Like [startPub], but runs `pub lish` in particular with [server] used both
419 /// as the OAuth2 server (with "/token" as the token endpoint) and as the 421 /// as the OAuth2 server (with "/token" as the token endpoint) and as the
420 /// package server. 422 /// package server.
421 /// 423 ///
422 /// Any futures in [args] will be resolved before the process is started. 424 /// Any futures in [args] will be resolved before the process is started.
423 ScheduledProcess startPublish(ScheduledServer server, {List args}) { 425 ScheduledProcess startPublish(ScheduledServer server, {List args}) {
424 var tokenEndpoint = server.url.then((url) => 426 var tokenEndpoint = server.url.then((url) =>
425 url.resolve('/token').toString()); 427 url.resolve('/token').toString());
426 if (args == null) args = []; 428 if (args == null) args = [];
427 args = flatten(['lish', '--server', tokenEndpoint, args]); 429 args = flatten(['lish', '--server', tokenEndpoint, args]);
428 return startPub(args: args, tokenEndpoint: tokenEndpoint); 430 return startPub(args: args, tokenEndpoint: tokenEndpoint);
429 } 431 }
430 432
431 /// Handles the beginning confirmation process for uploading a packages. 433 /// Handles the beginning confirmation process for uploading a packages.
432 /// Ensures that the right output is shown and then enters "y" to confirm the 434 /// Ensures that the right output is shown and then enters "y" to confirm the
433 /// upload. 435 /// upload.
434 void confirmPublish(ScheduledProcess pub) { 436 void confirmPublish(ScheduledProcess pub) {
435 // TODO(rnystrom): This is overly specific and inflexible regarding different 437 // TODO(rnystrom): This is overly specific and inflexible regarding different
436 // test packages. Should validate this a little more loosely. 438 // test packages. Should validate this a little more loosely.
437 expect(pub.nextLine(), completion(startsWith( 439 pub.stdout.expect(startsWith('Publishing test_pkg 1.0.0 to '));
438 'Publishing test_pkg 1.0.0 to '))); 440 pub.stdout.expect(emitsString(
439 expect(pub.nextLine(), completion(equals("|-- LICENSE"))); 441 "|-- LICENSE\n"
440 expect(pub.nextLine(), completion(equals("|-- lib"))); 442 "|-- lib\n"
441 expect(pub.nextLine(), completion(equals("| '-- test_pkg.dart"))); 443 "| '-- test_pkg.dart\n"
442 expect(pub.nextLine(), completion(equals("'-- pubspec.yaml"))); 444 "'-- pubspec.yaml\n"
443 expect(pub.nextLine(), completion(equals(""))); 445 "\n"
444 expect(pub.nextLine(), completion(equals('Looks great! Are you ready to ' 446 "Looks great! Are you ready to upload your package (y/n)?"));
Bob Nystrom 2014/02/14 17:55:02 Multi-line string?
nweiz 2014/02/18 22:01:10 Same response as before -- why here and not elsewh
Bob Nystrom 2014/02/18 22:12:59 Same response as before. It's already six lines of
445 'upload your package (y/n)?')));
446
447 pub.writeLine("y"); 447 pub.writeLine("y");
448 } 448 }
449 449
450 /// Starts a Pub process and returns a [ScheduledProcess] that supports 450 /// Starts a Pub process and returns a [ScheduledProcess] that supports
451 /// interaction with that process. 451 /// interaction with that process.
452 /// 452 ///
453 /// Any futures in [args] will be resolved before the process is started. 453 /// Any futures in [args] will be resolved before the process is started.
454 ScheduledProcess startPub({List args, Future<Uri> tokenEndpoint}) { 454 ScheduledProcess startPub({List args, Future<Uri> tokenEndpoint}) {
455 String pathInSandbox(String relPath) { 455 String pathInSandbox(String relPath) {
456 return path.join(path.absolute(sandboxDir), relPath); 456 return path.join(path.absolute(sandboxDir), relPath);
(...skipping 44 matching lines...) Expand 10 before | Expand all | Expand 10 after
501 return environment; 501 return environment;
502 }); 502 });
503 503
504 return new PubProcess.start(dartBin, dartArgs, environment: environmentFuture, 504 return new PubProcess.start(dartBin, dartArgs, environment: environmentFuture,
505 workingDirectory: pathInSandbox(appPath), 505 workingDirectory: pathInSandbox(appPath),
506 description: args.isEmpty ? 'pub' : 'pub ${args.first}'); 506 description: args.isEmpty ? 'pub' : 'pub ${args.first}');
507 } 507 }
508 508
509 /// A subclass of [ScheduledProcess] that parses pub's verbose logging output 509 /// A subclass of [ScheduledProcess] that parses pub's verbose logging output
510 /// and makes [nextLine], [nextErrLine], [remainingStdout], and 510 /// and makes [nextLine], [nextErrLine], [remainingStdout], and
511 /// [remainingStderr] work as though pub weren't running in verbose mode. 511 /// [remainingStderr] work as though pub weren't running in verbose mode.
Bob Nystrom 2014/02/14 17:55:02 Update docs.
nweiz 2014/02/18 22:01:10 Done.
512 class PubProcess extends ScheduledProcess { 512 class PubProcess extends ScheduledProcess {
513 Stream<Pair<log.Level, String>> _log; 513 Stream<Pair<log.Level, String>> _log;
514 Stream<String> _stdout; 514 Stream<String> _stdout;
515 Stream<String> _stderr; 515 Stream<String> _stderr;
516 516
517 PubProcess.start(executable, arguments, 517 PubProcess.start(executable, arguments,
518 {workingDirectory, environment, String description, 518 {workingDirectory, environment, String description,
519 Encoding encoding: UTF8}) 519 Encoding encoding: UTF8})
520 : super.start(executable, arguments, 520 : super.start(executable, arguments,
521 workingDirectory: workingDirectory, 521 workingDirectory: workingDirectory,
(...skipping 45 matching lines...) Expand 10 before | Expand all | Expand 10 after
567 } 567 }
568 568
569 var pair = tee(_stdout); 569 var pair = tee(_stdout);
570 _stdout = pair.first; 570 _stdout = pair.first;
571 return pair.last; 571 return pair.last;
572 } 572 }
573 573
574 Stream<String> stderrStream() { 574 Stream<String> stderrStream() {
575 if (_stderr == null) { 575 if (_stderr == null) {
576 _stderr = _logStream().expand((entry) { 576 _stderr = _logStream().expand((entry) {
577 if (entry.first != log.Level.ERROR && entry.first != log.Level.WARNING) { 577 if (entry.first != log.Level.ERROR && entry.first != log.Level.WARNING) {
Bob Nystrom 2014/02/14 17:55:02 How'd this long line sneak in?
nweiz 2014/02/18 22:01:10 Fixed.
578 return []; 578 return [];
579 } 579 }
580 return [entry.last]; 580 return [entry.last];
581 }); 581 });
582 } 582 }
583 583
584 var pair = tee(_stderr); 584 var pair = tee(_stderr);
585 _stderr = pair.first; 585 _stderr = pair.first;
586 return pair.last; 586 return pair.last;
587 } 587 }
(...skipping 271 matching lines...) Expand 10 before | Expand all | Expand 10 after
859 bool matches(item, Map matchState) { 859 bool matches(item, Map matchState) {
860 if (item is! Pair) return false; 860 if (item is! Pair) return false;
861 return _firstMatcher.matches(item.first, matchState) && 861 return _firstMatcher.matches(item.first, matchState) &&
862 _lastMatcher.matches(item.last, matchState); 862 _lastMatcher.matches(item.last, matchState);
863 } 863 }
864 864
865 Description describe(Description description) { 865 Description describe(Description description) {
866 description.addAll("(", ", ", ")", [_firstMatcher, _lastMatcher]); 866 description.addAll("(", ", ", ")", [_firstMatcher, _lastMatcher]);
867 } 867 }
868 } 868 }
869
870 /// A [StreamMatcher] that matches multiple lines of output.
871 StreamMatcher emitsString(String output) => inOrder(output.split("\n"));
Bob Nystrom 2014/02/14 17:55:02 How about "emitsLines"?
nweiz 2014/02/18 22:01:10 I considered that name, but it felt weird that it
Bob Nystrom 2014/02/18 22:12:59 Yeah, I think it does. Before I saw the doc commen
nweiz 2014/02/18 22:28:02 Done.
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698