| OLD | NEW |
| 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. | 5 /// Test infrastructure for testing pub. |
| 6 /// | 6 /// |
| 7 /// Unlike typical unit tests, most pub tests are integration tests that stage | 7 /// Unlike typical unit tests, most pub tests are integration tests that stage |
| 8 /// some stuff on the file system, run pub, and then validate the results. This | 8 /// some stuff on the file system, run pub, and then validate the results. This |
| 9 /// library provides an API to build tests like that. | 9 /// library provides an API to build tests like that. |
| 10 import 'dart:async'; | 10 import 'dart:async'; |
| (...skipping 17 matching lines...) Expand all Loading... |
| 28 import 'package:pub/src/package.dart'; | 28 import 'package:pub/src/package.dart'; |
| 29 import 'package:pub/src/source_registry.dart'; | 29 import 'package:pub/src/source_registry.dart'; |
| 30 import 'package:pub/src/system_cache.dart'; | 30 import 'package:pub/src/system_cache.dart'; |
| 31 import 'package:pub/src/utils.dart'; | 31 import 'package:pub/src/utils.dart'; |
| 32 import 'package:pub/src/validator.dart'; | 32 import 'package:pub/src/validator.dart'; |
| 33 import 'package:pub_semver/pub_semver.dart'; | 33 import 'package:pub_semver/pub_semver.dart'; |
| 34 import 'package:scheduled_test/scheduled_process.dart'; | 34 import 'package:scheduled_test/scheduled_process.dart'; |
| 35 import 'package:scheduled_test/scheduled_server.dart'; | 35 import 'package:scheduled_test/scheduled_server.dart'; |
| 36 import 'package:scheduled_test/scheduled_stream.dart'; | 36 import 'package:scheduled_test/scheduled_stream.dart'; |
| 37 import 'package:scheduled_test/scheduled_test.dart' hide fail; | 37 import 'package:scheduled_test/scheduled_test.dart' hide fail; |
| 38 import 'package:shelf/shelf.dart' as shelf; | |
| 39 import 'package:shelf/shelf_io.dart' as shelf_io; | |
| 40 | 38 |
| 41 import 'descriptor.dart' as d; | 39 import 'descriptor.dart' as d; |
| 40 import 'descriptor_server.dart'; |
| 42 | 41 |
| 43 export 'serve_packages.dart'; | 42 export 'descriptor_server.dart'; |
| 44 | 43 export 'package_server.dart'; |
| 45 /// The current [HttpServer] created using [serve]. | |
| 46 var _server; | |
| 47 | |
| 48 /// The list of paths that have been requested from the server since the last | |
| 49 /// call to [getRequestedPaths]. | |
| 50 final _requestedPaths = <String>[]; | |
| 51 | |
| 52 /// The cached value for [_portCompleter]. | |
| 53 Completer<int> _portCompleterCache; | |
| 54 | 44 |
| 55 /// A [Matcher] that matches JavaScript generated by dart2js with minification | 45 /// A [Matcher] that matches JavaScript generated by dart2js with minification |
| 56 /// enabled. | 46 /// enabled. |
| 57 Matcher isMinifiedDart2JSOutput = | 47 Matcher isMinifiedDart2JSOutput = |
| 58 isNot(contains("// The code supports the following hooks")); | 48 isNot(contains("// The code supports the following hooks")); |
| 59 | 49 |
| 60 /// A [Matcher] that matches JavaScript generated by dart2js with minification | 50 /// A [Matcher] that matches JavaScript generated by dart2js with minification |
| 61 /// disabled. | 51 /// disabled. |
| 62 Matcher isUnminifiedDart2JSOutput = | 52 Matcher isUnminifiedDart2JSOutput = |
| 63 contains("// The code supports the following hooks"); | 53 contains("// The code supports the following hooks"); |
| 64 | 54 |
| 65 /// The entrypoint for pub itself. | 55 /// The entrypoint for pub itself. |
| 66 final _entrypoint = new Entrypoint( | 56 final _entrypoint = new Entrypoint( |
| 67 pubRoot, new SystemCache.withSources(isOffline: true)); | 57 pubRoot, new SystemCache.withSources(isOffline: true)); |
| 68 | 58 |
| 69 /// The completer for [port]. | |
| 70 Completer<int> get _portCompleter { | |
| 71 if (_portCompleterCache != null) return _portCompleterCache; | |
| 72 _portCompleterCache = new Completer<int>(); | |
| 73 currentSchedule.onComplete.schedule(() { | |
| 74 _portCompleterCache = null; | |
| 75 }, 'clearing the port completer'); | |
| 76 return _portCompleterCache; | |
| 77 } | |
| 78 | |
| 79 /// A future that will complete to the port used for the current server. | |
| 80 Future<int> get port => _portCompleter.future; | |
| 81 | |
| 82 /// Gets the list of paths that have been requested from the server since the | |
| 83 /// last time this was called (or since the server was first spun up). | |
| 84 Future<List<String>> getRequestedPaths() { | |
| 85 return schedule(() { | |
| 86 var paths = _requestedPaths.toList(); | |
| 87 _requestedPaths.clear(); | |
| 88 return paths; | |
| 89 }, "get previous network requests"); | |
| 90 } | |
| 91 | |
| 92 /// Creates an HTTP server to serve [contents] as static files. | |
| 93 /// | |
| 94 /// This server will exist only for the duration of the pub run. Subsequent | |
| 95 /// calls to [serve] replace the previous server. | |
| 96 void serve([List<d.Descriptor> contents]) { | |
| 97 var baseDir = d.dir("serve-dir", contents); | |
| 98 | |
| 99 _hasServer = true; | |
| 100 | |
| 101 schedule(() { | |
| 102 return _closeServer().then((_) { | |
| 103 return shelf_io.serve((request) { | |
| 104 var path = p.posix.fromUri(request.url.path); | |
| 105 _requestedPaths.add(path); | |
| 106 | |
| 107 return validateStream(baseDir.load(path)) | |
| 108 .then((stream) => new shelf.Response.ok(stream)) | |
| 109 .catchError((error) { | |
| 110 return new shelf.Response.notFound('File "$path" not found.'); | |
| 111 }); | |
| 112 }, 'localhost', 0).then((server) { | |
| 113 _server = server; | |
| 114 _portCompleter.complete(_server.port); | |
| 115 currentSchedule.onComplete.schedule(_closeServer); | |
| 116 }); | |
| 117 }); | |
| 118 }, 'starting a server serving:\n${baseDir.describe()}'); | |
| 119 } | |
| 120 | |
| 121 /// Like [serve], but reports an error if a request ever comes in to the server. | |
| 122 void serveErrors() { | |
| 123 _hasServer = true; | |
| 124 | |
| 125 schedule(() async { | |
| 126 await _closeServer(); | |
| 127 | |
| 128 _server = await shelf_io.serve((request) { | |
| 129 fail("The HTTP server received an unexpected request:\n" | |
| 130 "${request.method} ${request.requestedUri}"); | |
| 131 return new shelf.Response.forbidden(null); | |
| 132 }, 'localhost', 0); | |
| 133 | |
| 134 _portCompleter.complete(_server.port); | |
| 135 currentSchedule.onComplete.schedule(_closeServer); | |
| 136 }); | |
| 137 } | |
| 138 | |
| 139 /// Closes [_server]. | |
| 140 /// | |
| 141 /// Returns a [Future] that completes after the [_server] is closed. | |
| 142 Future _closeServer() { | |
| 143 if (_server == null) return new Future.value(); | |
| 144 var future = _server.close(); | |
| 145 _server = null; | |
| 146 _hasServer = false; | |
| 147 _portCompleterCache = null; | |
| 148 return future; | |
| 149 } | |
| 150 | |
| 151 /// `true` if the current test spins up an HTTP server. | |
| 152 bool _hasServer = false; | |
| 153 | |
| 154 /// Converts [value] into a YAML string. | 59 /// Converts [value] into a YAML string. |
| 155 String yaml(value) => JSON.encode(value); | 60 String yaml(value) => JSON.encode(value); |
| 156 | 61 |
| 157 /// The full path to the created sandbox directory for an integration test. | 62 /// The full path to the created sandbox directory for an integration test. |
| 158 String get sandboxDir => _sandboxDir; | 63 String get sandboxDir => _sandboxDir; |
| 159 String _sandboxDir; | 64 String _sandboxDir; |
| 160 | 65 |
| 161 /// The path of the package cache directory used for tests, relative to the | 66 /// The path of the package cache directory used for tests, relative to the |
| 162 /// sandbox directory. | 67 /// sandbox directory. |
| 163 final String cachePath = "cache"; | 68 final String cachePath = "cache"; |
| (...skipping 234 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 398 environment['_PUB_TESTING'] = 'true'; | 303 environment['_PUB_TESTING'] = 'true'; |
| 399 environment['PUB_CACHE'] = await schedule(() => _pathInSandbox(cachePath)); | 304 environment['PUB_CACHE'] = await schedule(() => _pathInSandbox(cachePath)); |
| 400 | 305 |
| 401 // Ensure a known SDK version is set for the tests that rely on that. | 306 // Ensure a known SDK version is set for the tests that rely on that. |
| 402 environment['_PUB_TEST_SDK_VERSION'] = "0.1.2+3"; | 307 environment['_PUB_TEST_SDK_VERSION'] = "0.1.2+3"; |
| 403 | 308 |
| 404 if (tokenEndpoint != null) { | 309 if (tokenEndpoint != null) { |
| 405 environment['_PUB_TEST_TOKEN_ENDPOINT'] = tokenEndpoint.toString(); | 310 environment['_PUB_TEST_TOKEN_ENDPOINT'] = tokenEndpoint.toString(); |
| 406 } | 311 } |
| 407 | 312 |
| 408 if (_hasServer) { | 313 if (globalServer != null) { |
| 409 environment['PUB_HOSTED_URL'] = "http://localhost:${await port}"; | 314 environment['PUB_HOSTED_URL'] = |
| 315 "http://localhost:${await globalServer.port}"; |
| 410 } | 316 } |
| 411 | 317 |
| 412 return environment; | 318 return environment; |
| 413 } | 319 } |
| 414 | 320 |
| 415 /// Starts a Pub process and returns a [ScheduledProcess] that supports | 321 /// Starts a Pub process and returns a [ScheduledProcess] that supports |
| 416 /// interaction with that process. | 322 /// interaction with that process. |
| 417 /// | 323 /// |
| 418 /// Any futures in [args] will be resolved before the process is started. | 324 /// Any futures in [args] will be resolved before the process is started. |
| 419 /// | 325 /// |
| (...skipping 427 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 847 _lastMatcher.matches(item.last, matchState); | 753 _lastMatcher.matches(item.last, matchState); |
| 848 } | 754 } |
| 849 | 755 |
| 850 Description describe(Description description) { | 756 Description describe(Description description) { |
| 851 return description.addAll("(", ", ", ")", [_firstMatcher, _lastMatcher]); | 757 return description.addAll("(", ", ", ")", [_firstMatcher, _lastMatcher]); |
| 852 } | 758 } |
| 853 } | 759 } |
| 854 | 760 |
| 855 /// A [StreamMatcher] that matches multiple lines of output. | 761 /// A [StreamMatcher] that matches multiple lines of output. |
| 856 StreamMatcher emitsLines(String output) => inOrder(output.split("\n")); | 762 StreamMatcher emitsLines(String output) => inOrder(output.split("\n")); |
| OLD | NEW |