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 |