OLD | NEW |
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 */ |
11 #library('test_pub'); | 11 #library('test_pub'); |
12 | 12 |
13 #import('dart:io'); | 13 #import('dart:io'); |
| 14 #import('dart:isolate'); |
| 15 #import('dart:json'); |
14 #import('dart:uri'); | 16 #import('dart:uri'); |
15 | 17 |
16 #import('../../../lib/unittest/unittest.dart'); | 18 #import('../../../lib/unittest/unittest.dart'); |
17 #import('../../lib/file_system.dart', prefix: 'fs'); | 19 #import('../../lib/file_system.dart', prefix: 'fs'); |
18 #import('../../pub/io.dart'); | 20 #import('../../pub/io.dart'); |
19 #import('../../pub/utils.dart'); | 21 #import('../../pub/utils.dart'); |
20 #import('../../pub/yaml/yaml.dart'); | 22 #import('../../pub/yaml/yaml.dart'); |
21 | 23 |
22 /** | 24 /** |
23 * Creates a new [FileDescriptor] with [name] and [contents]. | 25 * Creates a new [FileDescriptor] with [name] and [contents]. |
(...skipping 26 matching lines...) Expand all Loading... |
50 void serve(String host, int port, [List<Descriptor> contents]) { | 52 void serve(String host, int port, [List<Descriptor> contents]) { |
51 var baseDir = dir("serve-dir", contents); | 53 var baseDir = dir("serve-dir", contents); |
52 if (host == 'localhost') { | 54 if (host == 'localhost') { |
53 host = '127.0.0.1'; | 55 host = '127.0.0.1'; |
54 } | 56 } |
55 | 57 |
56 _schedule((_) { | 58 _schedule((_) { |
57 var server = new HttpServer(); | 59 var server = new HttpServer(); |
58 server.defaultRequestHandler = (request, response) { | 60 server.defaultRequestHandler = (request, response) { |
59 var path = request.uri.replaceFirst("/", "").split("/"); | 61 var path = request.uri.replaceFirst("/", "").split("/"); |
60 var stream = baseDir.load(path); | |
61 response.persistentConnection = false; | 62 response.persistentConnection = false; |
62 if (stream == null) { | 63 var stream; |
| 64 try { |
| 65 stream = baseDir.load(path); |
| 66 } catch (var e) { |
63 response.statusCode = 404; | 67 response.statusCode = 404; |
| 68 response.contentLength = 0; |
64 response.outputStream.close(); | 69 response.outputStream.close(); |
65 return; | 70 return; |
66 } | 71 } |
67 | 72 |
68 var future = consumeInputStream(stream); | 73 var future = consumeInputStream(stream); |
69 future.then((data) { | 74 future.then((data) { |
70 response.statusCode = 200; | 75 response.statusCode = 200; |
71 response.contentLength = data.length; | 76 response.contentLength = data.length; |
72 response.outputStream.write(data); | 77 response.outputStream.write(data); |
73 response.outputStream.close(); | 78 response.outputStream.close(); |
(...skipping 21 matching lines...) Expand all Loading... |
95 void servePackages(String host, int port, List<String> pubspecs) { | 100 void servePackages(String host, int port, List<String> pubspecs) { |
96 var packages = <Map<String, String>>{}; | 101 var packages = <Map<String, String>>{}; |
97 pubspecs.forEach((spec) { | 102 pubspecs.forEach((spec) { |
98 var parsed = loadYaml(spec); | 103 var parsed = loadYaml(spec); |
99 var name = parsed['name']; | 104 var name = parsed['name']; |
100 var version = parsed['version']; | 105 var version = parsed['version']; |
101 packages.putIfAbsent(name, () => <String>{})[version] = spec; | 106 packages.putIfAbsent(name, () => <String>{})[version] = spec; |
102 }); | 107 }); |
103 | 108 |
104 serve(host, port, [ | 109 serve(host, port, [ |
105 dir('packages', packages.getKeys().map((name) { | 110 dir('packages', flatten(packages.getKeys().map((name) { |
106 return dir(name, [ | 111 return [ |
107 dir('versions', packages[name].getKeys().map((version) { | 112 file('$name.json', |
108 return tar('$version.tar.gz', [ | 113 JSON.stringify({'versions': packages[name].getKeys()})), |
109 file('pubspec.yaml', packages[name][version]), | 114 dir(name, [ |
110 file('$name.dart', 'main() => print("$name $version");') | 115 dir('versions', flatten(packages[name].getKeys().map((version) { |
111 ]); | 116 return [ |
112 })) | 117 file('$version.yaml', packages[name][version]), |
113 ]); | 118 tar('$version.tar.gz', [ |
114 })) | 119 file('pubspec.yaml', packages[name][version]), |
| 120 file('$name.dart', 'main() => print("$name $version");') |
| 121 ]) |
| 122 ]; |
| 123 }))) |
| 124 ]) |
| 125 ]; |
| 126 }))) |
115 ]); | 127 ]); |
116 } | 128 } |
117 | 129 |
118 /** | 130 /** |
119 * The path of the package cache directory used for tests. Relative to the | 131 * The path of the package cache directory used for tests. Relative to the |
120 * sandbox directory. | 132 * sandbox directory. |
121 */ | 133 */ |
122 final String cachePath = "cache"; | 134 final String cachePath = "cache"; |
123 | 135 |
124 /** | 136 /** |
(...skipping 378 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
503 'but contained:\n\n$text'); | 515 'but contained:\n\n$text'); |
504 }); | 516 }); |
505 }); | 517 }); |
506 } | 518 } |
507 | 519 |
508 /** | 520 /** |
509 * Loads the contents of the file. | 521 * Loads the contents of the file. |
510 */ | 522 */ |
511 InputStream load(List<String> path) { | 523 InputStream load(List<String> path) { |
512 if (!path.isEmpty()) { | 524 if (!path.isEmpty()) { |
513 var joinedPath = Strings.join('/', path); | 525 var joinedPath = Strings.join(path, '/'); |
514 throw "Can't load $joinedPath from within $name: not a directory."; | 526 throw "Can't load $joinedPath from within $name: not a directory."; |
515 } | 527 } |
516 | 528 |
517 var stream = new ListInputStream(); | 529 var stream = new ListInputStream(); |
518 stream.write(contents.charCodes()); | 530 stream.write(contents.charCodes()); |
| 531 stream.markEndOfStream(); |
519 return stream; | 532 return stream; |
520 } | 533 } |
521 } | 534 } |
522 | 535 |
523 /** | 536 /** |
524 * Describes a directory and its contents. These are used both for setting up | 537 * Describes a directory and its contents. These are used both for setting up |
525 * an expected directory tree before running a test, and for validating that | 538 * an expected directory tree before running a test, and for validating that |
526 * the file system matches some expectations after running it. | 539 * the file system matches some expectations after running it. |
527 */ | 540 */ |
528 class DirectoryDescriptor extends Descriptor { | 541 class DirectoryDescriptor extends Descriptor { |
(...skipping 59 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
588 if (path.isEmpty()) { | 601 if (path.isEmpty()) { |
589 throw "Can't load the contents of $name: is a directory."; | 602 throw "Can't load the contents of $name: is a directory."; |
590 } | 603 } |
591 | 604 |
592 for (var descriptor in contents) { | 605 for (var descriptor in contents) { |
593 if (descriptor.name == path[0]) { | 606 if (descriptor.name == path[0]) { |
594 return descriptor.load(path.getRange(1, path.length - 1)); | 607 return descriptor.load(path.getRange(1, path.length - 1)); |
595 } | 608 } |
596 } | 609 } |
597 | 610 |
598 throw "Directory $name doesn't contain ${Strings.join('/', path)}."; | 611 throw "Directory $name doesn't contain ${Strings.join(path, '/')}."; |
599 } | 612 } |
600 } | 613 } |
601 | 614 |
602 /** | 615 /** |
603 * Describes a Git repository and its contents. | 616 * Describes a Git repository and its contents. |
604 */ | 617 */ |
605 class GitRepoDescriptor extends DirectoryDescriptor { | 618 class GitRepoDescriptor extends DirectoryDescriptor { |
606 GitRepoDescriptor(Pattern name, List<Descriptor> contents) | 619 GitRepoDescriptor(Pattern name, List<Descriptor> contents) |
607 : super(name, contents); | 620 : super(name, contents); |
608 | 621 |
(...skipping 78 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
687 */ | 700 */ |
688 Future validate(String path) { | 701 Future validate(String path) { |
689 throw "TODO(nweiz): implement this"; | 702 throw "TODO(nweiz): implement this"; |
690 } | 703 } |
691 | 704 |
692 /** | 705 /** |
693 * Loads the contents of this tar file. | 706 * Loads the contents of this tar file. |
694 */ | 707 */ |
695 InputStream load(List<String> path) { | 708 InputStream load(List<String> path) { |
696 if (!path.isEmpty()) { | 709 if (!path.isEmpty()) { |
697 var joinedPath = Strings.join('/', path); | 710 var joinedPath = Strings.join(path, '/'); |
698 throw "Can't load $joinedPath from within $name: not a directory."; | 711 throw "Can't load $joinedPath from within $name: not a directory."; |
699 } | 712 } |
700 | 713 |
701 var sinkStream = new ListInputStream(); | 714 var sinkStream = new ListInputStream(); |
702 var tempDir; | 715 var tempDir; |
703 // TODO(nweiz): propagate any errors to the return value. See issue 3657. | 716 // TODO(nweiz): propagate any errors to the return value. See issue 3657. |
704 createTempDir("pub-test-tmp-").chain((_tempDir) { | 717 createTempDir("pub-test-tmp-").chain((_tempDir) { |
705 tempDir = _tempDir; | 718 tempDir = _tempDir; |
706 return create(tempDir); | 719 return create(tempDir); |
707 }).then((tar) { | 720 }).then((tar) { |
(...skipping 14 matching lines...) Expand all Loading... |
722 } | 735 } |
723 | 736 |
724 /** | 737 /** |
725 * Schedules a callback to be called after Pub is run with [runPub], even if it | 738 * Schedules a callback to be called after Pub is run with [runPub], even if it |
726 * fails. | 739 * fails. |
727 */ | 740 */ |
728 void _scheduleCleanup(_ScheduledEvent event) { | 741 void _scheduleCleanup(_ScheduledEvent event) { |
729 if (_scheduledCleanup == null) _scheduledCleanup = []; | 742 if (_scheduledCleanup == null) _scheduledCleanup = []; |
730 _scheduledCleanup.add(event); | 743 _scheduledCleanup.add(event); |
731 } | 744 } |
OLD | NEW |