| 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 library test_pub; | 10 library test_pub; |
| (...skipping 27 matching lines...) Expand all Loading... |
| 38 import '../lib/src/package.dart'; | 38 import '../lib/src/package.dart'; |
| 39 import '../lib/src/pubspec.dart'; | 39 import '../lib/src/pubspec.dart'; |
| 40 import '../lib/src/source/hosted.dart'; | 40 import '../lib/src/source/hosted.dart'; |
| 41 import '../lib/src/source/path.dart'; | 41 import '../lib/src/source/path.dart'; |
| 42 import '../lib/src/source_registry.dart'; | 42 import '../lib/src/source_registry.dart'; |
| 43 import '../lib/src/system_cache.dart'; | 43 import '../lib/src/system_cache.dart'; |
| 44 import '../lib/src/utils.dart'; | 44 import '../lib/src/utils.dart'; |
| 45 import '../lib/src/validator.dart'; | 45 import '../lib/src/validator.dart'; |
| 46 import '../lib/src/version.dart'; | 46 import '../lib/src/version.dart'; |
| 47 import 'descriptor.dart' as d; | 47 import 'descriptor.dart' as d; |
| 48 import 'serve_packages.dart'; |
| 49 |
| 50 export 'serve_packages.dart'; |
| 48 | 51 |
| 49 /// This should be called at the top of a test file to set up an appropriate | 52 /// This should be called at the top of a test file to set up an appropriate |
| 50 /// test configuration for the machine running the tests. | 53 /// test configuration for the machine running the tests. |
| 51 initConfig() { | 54 initConfig() { |
| 52 useCompactVMConfiguration(); | 55 useCompactVMConfiguration(); |
| 53 filterStacks = true; | 56 filterStacks = true; |
| 54 unittestConfiguration.timeout = null; | 57 unittestConfiguration.timeout = null; |
| 55 } | 58 } |
| 56 | 59 |
| 57 /// The current [HttpServer] created using [serve]. | 60 /// The current [HttpServer] created using [serve]. |
| (...skipping 157 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 215 var future = _server.close(); | 218 var future = _server.close(); |
| 216 _server = null; | 219 _server = null; |
| 217 _hasServer = false; | 220 _hasServer = false; |
| 218 _portCompleterCache = null; | 221 _portCompleterCache = null; |
| 219 return future; | 222 return future; |
| 220 } | 223 } |
| 221 | 224 |
| 222 /// `true` if the current test spins up an HTTP server. | 225 /// `true` if the current test spins up an HTTP server. |
| 223 bool _hasServer = false; | 226 bool _hasServer = false; |
| 224 | 227 |
| 225 /// The [d.DirectoryDescriptor] describing the server layout of `/api/packages` | |
| 226 /// on the test server. | |
| 227 /// | |
| 228 /// This contains metadata for packages that are being served via | |
| 229 /// [servePackages]. It's `null` if [servePackages] has not yet been called for | |
| 230 /// this test. | |
| 231 d.DirectoryDescriptor _servedApiPackageDir; | |
| 232 | |
| 233 /// The [d.DirectoryDescriptor] describing the server layout of `/packages` on | |
| 234 /// the test server. | |
| 235 /// | |
| 236 /// This contains the tarballs for packages that are being served via | |
| 237 /// [servePackages]. It's `null` if [servePackages] has not yet been called for | |
| 238 /// this test. | |
| 239 d.DirectoryDescriptor _servedPackageDir; | |
| 240 | |
| 241 /// A map from package names to parsed pubspec maps for those packages. | |
| 242 /// | |
| 243 /// This represents the packages currently being served by [servePackages], and | |
| 244 /// is `null` if [servePackages] has not yet been called for this test. | |
| 245 Map<String, List<Map>> _servedPackages; | |
| 246 | |
| 247 /// Creates an HTTP server that replicates the structure of pub.dartlang.org. | |
| 248 /// | |
| 249 /// [pubspecs] is a list of unserialized pubspecs representing the packages to | |
| 250 /// serve. | |
| 251 /// | |
| 252 /// If [replace] is false, subsequent calls to [servePackages] will add to the | |
| 253 /// set of packages that are being served. Previous packages will continue to be | |
| 254 /// served. Otherwise, the previous packages will no longer be served. | |
| 255 /// | |
| 256 /// If [contents] is given, its contents are added to every served | |
| 257 /// package. | |
| 258 /// | |
| 259 /// If [serveBarback] is true, the repo versions of barback and its dependencies | |
| 260 /// will be served as well. | |
| 261 void servePackages(List<Map> pubspecs, {bool replace: false, | |
| 262 Iterable<d.Descriptor> contents, bool serveBarback: false}) { | |
| 263 if (_servedPackages == null || _servedPackageDir == null) { | |
| 264 _servedPackages = <String, List<Map>>{}; | |
| 265 _servedApiPackageDir = d.dir('packages', []); | |
| 266 _servedPackageDir = d.dir('packages', []); | |
| 267 serve([ | |
| 268 d.dir('api', [_servedApiPackageDir]), | |
| 269 _servedPackageDir | |
| 270 ]); | |
| 271 | |
| 272 currentSchedule.onComplete.schedule(() { | |
| 273 _servedPackages = null; | |
| 274 _servedApiPackageDir = null; | |
| 275 _servedPackageDir = null; | |
| 276 }, 'cleaning up served packages'); | |
| 277 } | |
| 278 | |
| 279 schedule(() { | |
| 280 return awaitObject(pubspecs).then((resolvedPubspecs) { | |
| 281 if (replace) _servedPackages.clear(); | |
| 282 | |
| 283 for (var pubspec in resolvedPubspecs) { | |
| 284 var name = pubspec['name']; | |
| 285 var version = pubspec['version']; | |
| 286 var versions = _servedPackages.putIfAbsent(name, () => []); | |
| 287 versions.add(pubspec); | |
| 288 } | |
| 289 | |
| 290 var repoPackages = new Set(); | |
| 291 if (serveBarback) { | |
| 292 _addPackage(name) { | |
| 293 if (_servedPackages.containsKey(name)) return; | |
| 294 repoPackages.add(name); | |
| 295 | |
| 296 var pubspec = new Map.from(loadYaml( | |
| 297 readTextFile(path.join(repoRoot, 'pkg', name, 'pubspec.yaml')))); | |
| 298 | |
| 299 // Remove any SDK constraints since we don't have a valid SDK version | |
| 300 // while testing. | |
| 301 pubspec.remove('environment'); | |
| 302 | |
| 303 _servedPackages[name] = [pubspec]; | |
| 304 if (pubspec.containsKey('dependencies')) { | |
| 305 pubspec['dependencies'].keys.forEach(_addPackage); | |
| 306 } | |
| 307 } | |
| 308 | |
| 309 _addPackage('barback'); | |
| 310 } | |
| 311 | |
| 312 _servedApiPackageDir.contents.clear(); | |
| 313 _servedPackageDir.contents.clear(); | |
| 314 for (var name in _servedPackages.keys) { | |
| 315 _servedApiPackageDir.contents.addAll([ | |
| 316 d.file('$name', JSON.encode({ | |
| 317 'name': name, | |
| 318 'uploaders': ['nweiz@google.com'], | |
| 319 'versions': _servedPackages[name].map(packageVersionApiMap).toList() | |
| 320 })), | |
| 321 d.dir(name, [ | |
| 322 d.dir('versions', _servedPackages[name].map((pubspec) { | |
| 323 return d.file(pubspec['version'], JSON.encode( | |
| 324 packageVersionApiMap(pubspec, full: true))); | |
| 325 })) | |
| 326 ]) | |
| 327 ]); | |
| 328 | |
| 329 _servedPackageDir.contents.add(d.dir(name, [ | |
| 330 d.dir('versions', _servedPackages[name].map((pubspec) { | |
| 331 var version = pubspec['version']; | |
| 332 | |
| 333 if (repoPackages.contains(name)) { | |
| 334 return d.tar('$version.tar.gz', [ | |
| 335 d.file('pubspec.yaml', JSON.encode(pubspec)), | |
| 336 new d.DirectoryDescriptor.fromFilesystem('lib', | |
| 337 path.join(repoRoot, 'pkg', name, 'lib')) | |
| 338 ]); | |
| 339 } | |
| 340 | |
| 341 var archiveContents = [ | |
| 342 d.file('pubspec.yaml', JSON.encode(pubspec)), | |
| 343 d.libDir(name, '$name $version') | |
| 344 ]; | |
| 345 | |
| 346 if (contents != null) { | |
| 347 archiveContents.addAll(contents); | |
| 348 } | |
| 349 | |
| 350 return d.tar('$version.tar.gz', archiveContents); | |
| 351 })) | |
| 352 ])); | |
| 353 } | |
| 354 }); | |
| 355 }, 'initializing the package server'); | |
| 356 } | |
| 357 | |
| 358 /// Converts [value] into a YAML string. | 228 /// Converts [value] into a YAML string. |
| 359 String yaml(value) => JSON.encode(value); | 229 String yaml(value) => JSON.encode(value); |
| 360 | 230 |
| 361 /// The full path to the created sandbox directory for an integration test. | 231 /// The full path to the created sandbox directory for an integration test. |
| 362 String get sandboxDir => _sandboxDir; | 232 String get sandboxDir => _sandboxDir; |
| 363 String _sandboxDir; | 233 String _sandboxDir; |
| 364 | 234 |
| 365 /// The path to the Dart repo's packages. | 235 /// The path to the Dart repo's packages. |
| 366 final String pkgPath = path.absolute(path.join( | 236 final String pkgPath = path.absolute(path.join( |
| 367 path.dirname(Platform.executable), | 237 path.dirname(Platform.executable), |
| (...skipping 403 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 771 /// Schedules activating a global package [package] without running | 641 /// Schedules activating a global package [package] without running |
| 772 /// "pub global activate". | 642 /// "pub global activate". |
| 773 /// | 643 /// |
| 774 /// This is useful because global packages must be hosted, but the test hosted | 644 /// This is useful because global packages must be hosted, but the test hosted |
| 775 /// server doesn't serve barback. The other parameters here follow | 645 /// server doesn't serve barback. The other parameters here follow |
| 776 /// [createLockFile]. | 646 /// [createLockFile]. |
| 777 void makeGlobalPackage(String package, String version, | 647 void makeGlobalPackage(String package, String version, |
| 778 Iterable<d.Descriptor> contents, {Iterable<String> pkg, | 648 Iterable<d.Descriptor> contents, {Iterable<String> pkg, |
| 779 Map<String, String> hosted}) { | 649 Map<String, String> hosted}) { |
| 780 // Start the server so we know what port to use in the cache directory name. | 650 // Start the server so we know what port to use in the cache directory name. |
| 781 servePackages([]); | 651 servePackages((_) {}); |
| 782 | 652 |
| 783 // Create the package in the hosted cache. | 653 // Create the package in the hosted cache. |
| 784 d.hostedCache([ | 654 d.hostedCache([ |
| 785 d.dir("$package-$version", contents) | 655 d.dir("$package-$version", contents) |
| 786 ]).create(); | 656 ]).create(); |
| 787 | 657 |
| 788 var lockFile = _createLockFile(pkg: pkg, hosted: hosted); | 658 var lockFile = _createLockFile(pkg: pkg, hosted: hosted); |
| 789 | 659 |
| 790 // Add the root package to the lockfile. | 660 // Add the root package to the lockfile. |
| 791 var id = new PackageId(package, "hosted", new Version.parse(version), | 661 var id = new PackageId(package, "hosted", new Version.parse(version), |
| (...skipping 281 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1073 _lastMatcher.matches(item.last, matchState); | 943 _lastMatcher.matches(item.last, matchState); |
| 1074 } | 944 } |
| 1075 | 945 |
| 1076 Description describe(Description description) { | 946 Description describe(Description description) { |
| 1077 return description.addAll("(", ", ", ")", [_firstMatcher, _lastMatcher]); | 947 return description.addAll("(", ", ", ")", [_firstMatcher, _lastMatcher]); |
| 1078 } | 948 } |
| 1079 } | 949 } |
| 1080 | 950 |
| 1081 /// A [StreamMatcher] that matches multiple lines of output. | 951 /// A [StreamMatcher] that matches multiple lines of output. |
| 1082 StreamMatcher emitsLines(String output) => inOrder(output.split("\n")); | 952 StreamMatcher emitsLines(String output) => inOrder(output.split("\n")); |
| OLD | NEW |