| 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 /// 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 |
| (...skipping 535 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 546 var dir = new Options().script; | 546 var dir = new Options().script; |
| 547 while (path.basename(dir) != 'pub') dir = path.dirname(dir); | 547 while (path.basename(dir) != 'pub') dir = path.dirname(dir); |
| 548 | 548 |
| 549 return path.absolute(dir); | 549 return path.absolute(dir); |
| 550 } | 550 } |
| 551 | 551 |
| 552 /// Schedules renaming (moving) the directory at [from] to [to], both of which | 552 /// Schedules renaming (moving) the directory at [from] to [to], both of which |
| 553 /// are assumed to be relative to [sandboxDir]. | 553 /// are assumed to be relative to [sandboxDir]. |
| 554 void scheduleRename(String from, String to) { | 554 void scheduleRename(String from, String to) { |
| 555 _schedule((sandboxDir) { | 555 _schedule((sandboxDir) { |
| 556 return renameDir(join(sandboxDir, from), join(sandboxDir, to)); | 556 return renameDir(path.join(sandboxDir, from), path.join(sandboxDir, to)); |
| 557 }); | 557 }); |
| 558 } | 558 } |
| 559 | 559 |
| 560 /// Schedules a call to the Pub command-line utility. Runs Pub with [args] and | 560 /// Schedules a call to the Pub command-line utility. Runs Pub with [args] and |
| 561 /// validates that its results match [output], [error], and [exitCode]. | 561 /// validates that its results match [output], [error], and [exitCode]. |
| 562 void schedulePub({List args, Pattern output, Pattern error, | 562 void schedulePub({List args, Pattern output, Pattern error, |
| 563 Future<Uri> tokenEndpoint, int exitCode: 0}) { | 563 Future<Uri> tokenEndpoint, int exitCode: 0}) { |
| 564 _schedule((sandboxDir) { | 564 _schedule((sandboxDir) { |
| 565 return _doPub(runProcess, sandboxDir, args, tokenEndpoint).then((result) { | 565 return _doPub(runProcess, sandboxDir, args, tokenEndpoint).then((result) { |
| 566 var failures = []; | 566 var failures = []; |
| (...skipping 58 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 625 expectLater(pub.nextLine(), equals("")); | 625 expectLater(pub.nextLine(), equals("")); |
| 626 | 626 |
| 627 pub.writeLine("y"); | 627 pub.writeLine("y"); |
| 628 } | 628 } |
| 629 | 629 |
| 630 /// Calls [fn] with appropriately modified arguments to run a pub process. [fn] | 630 /// Calls [fn] with appropriately modified arguments to run a pub process. [fn] |
| 631 /// should have the same signature as [startProcess], except that the returned | 631 /// should have the same signature as [startProcess], except that the returned |
| 632 /// [Future] may have a type other than [Process]. | 632 /// [Future] may have a type other than [Process]. |
| 633 Future _doPub(Function fn, sandboxDir, List args, Future<Uri> tokenEndpoint) { | 633 Future _doPub(Function fn, sandboxDir, List args, Future<Uri> tokenEndpoint) { |
| 634 String pathInSandbox(String relPath) { | 634 String pathInSandbox(String relPath) { |
| 635 return join(path.absolute(sandboxDir), relPath); | 635 return path.join(path.absolute(sandboxDir), relPath); |
| 636 } | 636 } |
| 637 | 637 |
| 638 return defer(() { | 638 return defer(() { |
| 639 ensureDir(pathInSandbox(appPath)); | 639 ensureDir(pathInSandbox(appPath)); |
| 640 return Future.wait([ | 640 return Future.wait([ |
| 641 _awaitObject(args), | 641 _awaitObject(args), |
| 642 tokenEndpoint == null ? new Future.immediate(null) : tokenEndpoint | 642 tokenEndpoint == null ? new Future.immediate(null) : tokenEndpoint |
| 643 ]); | 643 ]); |
| 644 }).then((results) { | 644 }).then((results) { |
| 645 var args = results[0]; | 645 var args = results[0]; |
| (...skipping 200 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 846 | 846 |
| 847 /// Asserts that the name of the descriptor is a [String] and returns it. | 847 /// Asserts that the name of the descriptor is a [String] and returns it. |
| 848 String get _stringName { | 848 String get _stringName { |
| 849 if (name is String) return name; | 849 if (name is String) return name; |
| 850 throw 'Pattern $name must be a string.'; | 850 throw 'Pattern $name must be a string.'; |
| 851 } | 851 } |
| 852 | 852 |
| 853 /// Validates that at least one file in [dir] matching [name] is valid | 853 /// Validates that at least one file in [dir] matching [name] is valid |
| 854 /// according to [validate]. [validate] should throw or complete to an | 854 /// according to [validate]. [validate] should throw or complete to an |
| 855 /// exception if the input path is invalid. | 855 /// exception if the input path is invalid. |
| 856 Future _validateOneMatch(String dir, Future validate(String path)) { | 856 Future _validateOneMatch(String dir, Future validate(String entry)) { |
| 857 // Special-case strings to support multi-level names like "myapp/packages". | 857 // Special-case strings to support multi-level names like "myapp/packages". |
| 858 if (name is String) { | 858 if (name is String) { |
| 859 var path = join(dir, name); | 859 var entry = path.join(dir, name); |
| 860 return defer(() { | 860 return defer(() { |
| 861 if (!entryExists(path)) { | 861 if (!entryExists(entry)) { |
| 862 throw new ExpectException('Entry $path not found.'); | 862 throw new ExpectException('Entry $entry not found.'); |
| 863 } | 863 } |
| 864 return validate(path); | 864 return validate(entry); |
| 865 }); | 865 }); |
| 866 } | 866 } |
| 867 | 867 |
| 868 // TODO(nweiz): remove this when issue 4061 is fixed. | 868 // TODO(nweiz): remove this when issue 4061 is fixed. |
| 869 var stackTrace; | 869 var stackTrace; |
| 870 try { | 870 try { |
| 871 throw ""; | 871 throw ""; |
| 872 } catch (_, localStackTrace) { | 872 } catch (_, localStackTrace) { |
| 873 stackTrace = localStackTrace; | 873 stackTrace = localStackTrace; |
| 874 } | 874 } |
| (...skipping 47 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 922 | 922 |
| 923 String get textContents => new String.fromCharCodes(contents); | 923 String get textContents => new String.fromCharCodes(contents); |
| 924 | 924 |
| 925 FileDescriptor.bytes(Pattern name, this.contents) : super(name); | 925 FileDescriptor.bytes(Pattern name, this.contents) : super(name); |
| 926 | 926 |
| 927 FileDescriptor(Pattern name, String contents) : | 927 FileDescriptor(Pattern name, String contents) : |
| 928 this.bytes(name, encodeUtf8(contents)); | 928 this.bytes(name, encodeUtf8(contents)); |
| 929 | 929 |
| 930 /// Creates the file within [dir]. Returns a [Future] that is completed after | 930 /// Creates the file within [dir]. Returns a [Future] that is completed after |
| 931 /// the creation is done. | 931 /// the creation is done. |
| 932 Future<File> create(dir) => | 932 Future<String> create(dir) => |
| 933 defer(() => writeBinaryFile(join(dir, _stringName), contents)); | 933 defer(() => writeBinaryFile(path.join(dir, _stringName), contents)); |
| 934 | 934 |
| 935 /// Deletes the file within [dir]. Returns a [Future] that is completed after | 935 /// Deletes the file within [dir]. Returns a [Future] that is completed after |
| 936 /// the deletion is done. | 936 /// the deletion is done. |
| 937 Future delete(dir) => | 937 Future delete(dir) => |
| 938 defer(() => deleteFile(join(dir, _stringName))); | 938 defer(() => deleteFile(path.join(dir, _stringName))); |
| 939 | 939 |
| 940 /// Validates that this file correctly matches the actual file at [path]. | 940 /// Validates that this file correctly matches the actual file at [path]. |
| 941 Future validate(String path) { | 941 Future validate(String path) { |
| 942 return _validateOneMatch(path, (file) { | 942 return _validateOneMatch(path, (file) { |
| 943 var text = readTextFile(file); | 943 var text = readTextFile(file); |
| 944 if (text == textContents) return null; | 944 if (text == textContents) return null; |
| 945 | 945 |
| 946 throw new ExpectException( | 946 throw new ExpectException( |
| 947 'File $file should contain:\n\n$textContents\n\n' | 947 'File $file should contain:\n\n$textContents\n\n' |
| 948 'but contained:\n\n$text'); | 948 'but contained:\n\n$text'); |
| (...skipping 16 matching lines...) Expand all Loading... |
| 965 class DirectoryDescriptor extends Descriptor { | 965 class DirectoryDescriptor extends Descriptor { |
| 966 /// The files and directories contained in this directory. | 966 /// The files and directories contained in this directory. |
| 967 final List<Descriptor> contents; | 967 final List<Descriptor> contents; |
| 968 | 968 |
| 969 DirectoryDescriptor(Pattern name, List<Descriptor> contents) | 969 DirectoryDescriptor(Pattern name, List<Descriptor> contents) |
| 970 : this.contents = contents == null ? <Descriptor>[] : contents, | 970 : this.contents = contents == null ? <Descriptor>[] : contents, |
| 971 super(name); | 971 super(name); |
| 972 | 972 |
| 973 /// Creates the file within [dir]. Returns a [Future] that is completed after | 973 /// Creates the file within [dir]. Returns a [Future] that is completed after |
| 974 /// the creation is done. | 974 /// the creation is done. |
| 975 Future<Directory> create(parentDir) { | 975 Future<String> create(parentDir) { |
| 976 return defer(() { | 976 return defer(() { |
| 977 // Create the directory. | 977 // Create the directory. |
| 978 var dir = ensureDir(join(parentDir, _stringName)); | 978 var dir = ensureDir(path.join(parentDir, _stringName)); |
| 979 if (contents == null) return dir; | 979 if (contents == null) return dir; |
| 980 | 980 |
| 981 // Recursively create all of its children. | 981 // Recursively create all of its children. |
| 982 var childFutures = contents.map((child) => child.create(dir)).toList(); | 982 var childFutures = contents.map((child) => child.create(dir)).toList(); |
| 983 // Only complete once all of the children have been created too. | 983 // Only complete once all of the children have been created too. |
| 984 return Future.wait(childFutures).then((_) => dir); | 984 return Future.wait(childFutures).then((_) => dir); |
| 985 }); | 985 }); |
| 986 } | 986 } |
| 987 | 987 |
| 988 /// Deletes the directory within [dir]. Returns a [Future] that is completed | 988 /// Deletes the directory within [dir]. Returns a [Future] that is completed |
| 989 /// after the deletion is done. | 989 /// after the deletion is done. |
| 990 Future delete(dir) { | 990 Future delete(dir) { |
| 991 return deleteDir(join(dir, _stringName)); | 991 return deleteDir(path.join(dir, _stringName)); |
| 992 } | 992 } |
| 993 | 993 |
| 994 /// Validates that the directory at [path] contains all of the expected | 994 /// Validates that the directory at [path] contains all of the expected |
| 995 /// contents in this descriptor. Note that this does *not* check that the | 995 /// contents in this descriptor. Note that this does *not* check that the |
| 996 /// directory doesn't contain other unexpected stuff, just that it *does* | 996 /// directory doesn't contain other unexpected stuff, just that it *does* |
| 997 /// contain the stuff we do expect. | 997 /// contain the stuff we do expect. |
| 998 Future validate(String path) { | 998 Future validate(String path) { |
| 999 return _validateOneMatch(path, (dir) { | 999 return _validateOneMatch(path, (dir) { |
| 1000 // Validate each of the items in this directory. | 1000 // Validate each of the items in this directory. |
| 1001 final entryFutures = | 1001 final entryFutures = |
| (...skipping 41 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1043 return new ByteStream(controller.stream); | 1043 return new ByteStream(controller.stream); |
| 1044 } | 1044 } |
| 1045 } | 1045 } |
| 1046 | 1046 |
| 1047 /// Describes a Git repository and its contents. | 1047 /// Describes a Git repository and its contents. |
| 1048 class GitRepoDescriptor extends DirectoryDescriptor { | 1048 class GitRepoDescriptor extends DirectoryDescriptor { |
| 1049 GitRepoDescriptor(Pattern name, List<Descriptor> contents) | 1049 GitRepoDescriptor(Pattern name, List<Descriptor> contents) |
| 1050 : super(name, contents); | 1050 : super(name, contents); |
| 1051 | 1051 |
| 1052 /// Creates the Git repository and commits the contents. | 1052 /// Creates the Git repository and commits the contents. |
| 1053 Future<Directory> create(parentDir) { | 1053 Future create(parentDir) { |
| 1054 return _runGitCommands(parentDir, [ | 1054 return _runGitCommands(parentDir, [ |
| 1055 ['init'], | 1055 ['init'], |
| 1056 ['add', '.'], | 1056 ['add', '.'], |
| 1057 ['commit', '-m', 'initial commit'] | 1057 ['commit', '-m', 'initial commit'] |
| 1058 ]); | 1058 ]); |
| 1059 } | 1059 } |
| 1060 | 1060 |
| 1061 /// Commits any changes to the Git repository. | 1061 /// Commits any changes to the Git repository. |
| 1062 Future commit(parentDir) { | 1062 Future commit(parentDir) { |
| 1063 return _runGitCommands(parentDir, [ | 1063 return _runGitCommands(parentDir, [ |
| (...skipping 10 matching lines...) Expand all Loading... |
| 1074 Future<String> revParse(String ref) { | 1074 Future<String> revParse(String ref) { |
| 1075 return _scheduleValue((parentDir) { | 1075 return _scheduleValue((parentDir) { |
| 1076 return super.create(parentDir).then((rootDir) { | 1076 return super.create(parentDir).then((rootDir) { |
| 1077 return _runGit(['rev-parse', ref], rootDir); | 1077 return _runGit(['rev-parse', ref], rootDir); |
| 1078 }).then((output) => output[0]); | 1078 }).then((output) => output[0]); |
| 1079 }); | 1079 }); |
| 1080 } | 1080 } |
| 1081 | 1081 |
| 1082 /// Schedule a Git command to run in this repository. | 1082 /// Schedule a Git command to run in this repository. |
| 1083 void scheduleGit(List<String> args) { | 1083 void scheduleGit(List<String> args) { |
| 1084 _schedule((parentDir) { | 1084 _schedule((parentDir) => _runGit(args, path.join(parentDir, name))); |
| 1085 var gitDir = new Directory(join(parentDir, name)); | |
| 1086 return _runGit(args, gitDir); | |
| 1087 }); | |
| 1088 } | 1085 } |
| 1089 | 1086 |
| 1090 Future _runGitCommands(parentDir, List<List<String>> commands) { | 1087 Future _runGitCommands(parentDir, List<List<String>> commands) { |
| 1091 var workingDir; | 1088 var workingDir; |
| 1092 | 1089 |
| 1093 Future runGitStep(_) { | 1090 Future runGitStep(_) { |
| 1094 if (commands.isEmpty) return new Future.immediate(workingDir); | 1091 if (commands.isEmpty) return new Future.immediate(workingDir); |
| 1095 var command = commands.removeAt(0); | 1092 var command = commands.removeAt(0); |
| 1096 return _runGit(command, workingDir).then(runGitStep); | 1093 return _runGit(command, workingDir).then(runGitStep); |
| 1097 } | 1094 } |
| 1098 | 1095 |
| 1099 return super.create(parentDir).then((rootDir) { | 1096 return super.create(parentDir).then((rootDir) { |
| 1100 workingDir = rootDir; | 1097 workingDir = rootDir; |
| 1101 return runGitStep(null); | 1098 return runGitStep(null); |
| 1102 }); | 1099 }); |
| 1103 } | 1100 } |
| 1104 | 1101 |
| 1105 Future<List<String>> _runGit(List<String> args, Directory workingDir) { | 1102 Future<List<String>> _runGit(List<String> args, String workingDir) { |
| 1106 // Explicitly specify the committer information. Git needs this to commit | 1103 // Explicitly specify the committer information. Git needs this to commit |
| 1107 // and we don't want to rely on the buildbots having this already set up. | 1104 // and we don't want to rely on the buildbots having this already set up. |
| 1108 var environment = { | 1105 var environment = { |
| 1109 'GIT_AUTHOR_NAME': 'Pub Test', | 1106 'GIT_AUTHOR_NAME': 'Pub Test', |
| 1110 'GIT_AUTHOR_EMAIL': 'pub@dartlang.org', | 1107 'GIT_AUTHOR_EMAIL': 'pub@dartlang.org', |
| 1111 'GIT_COMMITTER_NAME': 'Pub Test', | 1108 'GIT_COMMITTER_NAME': 'Pub Test', |
| 1112 'GIT_COMMITTER_EMAIL': 'pub@dartlang.org' | 1109 'GIT_COMMITTER_EMAIL': 'pub@dartlang.org' |
| 1113 }; | 1110 }; |
| 1114 | 1111 |
| 1115 return gitlib.run(args, workingDir: workingDir.path, | 1112 return gitlib.run(args, workingDir: workingDir, environment: environment); |
| 1116 environment: environment); | |
| 1117 } | 1113 } |
| 1118 } | 1114 } |
| 1119 | 1115 |
| 1120 /// Describes a gzipped tar file and its contents. | 1116 /// Describes a gzipped tar file and its contents. |
| 1121 class TarFileDescriptor extends Descriptor { | 1117 class TarFileDescriptor extends Descriptor { |
| 1122 final List<Descriptor> contents; | 1118 final List<Descriptor> contents; |
| 1123 | 1119 |
| 1124 TarFileDescriptor(Pattern name, this.contents) | 1120 TarFileDescriptor(Pattern name, this.contents) |
| 1125 : super(name); | 1121 : super(name); |
| 1126 | 1122 |
| 1127 /// Creates the files and directories within this tar file, then archives | 1123 /// Creates the files and directories within this tar file, then archives |
| 1128 /// them, compresses them, and saves the result to [parentDir]. | 1124 /// them, compresses them, and saves the result to [parentDir]. |
| 1129 Future<File> create(parentDir) { | 1125 Future<String> create(parentDir) { |
| 1130 return withTempDir((tempDir) { | 1126 return withTempDir((tempDir) { |
| 1131 return Future.wait(contents.map((child) => child.create(tempDir))) | 1127 return Future.wait(contents.map((child) => child.create(tempDir))) |
| 1132 .then((createdContents) { | 1128 .then((createdContents) { |
| 1133 return createTarGz(createdContents, baseDir: tempDir).toBytes(); | 1129 return createTarGz(createdContents, baseDir: tempDir).toBytes(); |
| 1134 }).then((bytes) { | 1130 }).then((bytes) { |
| 1135 return new File(join(parentDir, _stringName)).writeAsBytes(bytes); | 1131 var file = path.join(parentDir, _stringName); |
| 1132 writeBinaryFile(file, bytes); |
| 1133 return file; |
| 1136 }); | 1134 }); |
| 1137 }); | 1135 }); |
| 1138 } | 1136 } |
| 1139 | 1137 |
| 1140 /// Validates that the `.tar.gz` file at [path] contains the expected | 1138 /// Validates that the `.tar.gz` file at [path] contains the expected |
| 1141 /// contents. | 1139 /// contents. |
| 1142 Future validate(String path) { | 1140 Future validate(String path) { |
| 1143 throw "TODO(nweiz): implement this"; | 1141 throw "TODO(nweiz): implement this"; |
| 1144 } | 1142 } |
| 1145 | 1143 |
| 1146 Future delete(dir) { | 1144 Future delete(dir) { |
| 1147 throw new UnsupportedError(''); | 1145 throw new UnsupportedError(''); |
| 1148 } | 1146 } |
| 1149 | 1147 |
| 1150 /// Loads the contents of this tar file. | 1148 /// Loads the contents of this tar file. |
| 1151 ByteStream load(List<String> path) { | 1149 ByteStream load(List<String> path) { |
| 1152 if (!path.isEmpty) { | 1150 if (!path.isEmpty) { |
| 1153 throw "Can't load ${path.join('/')} from within $name: not a directory."; | 1151 throw "Can't load ${path.join('/')} from within $name: not a directory."; |
| 1154 } | 1152 } |
| 1155 | 1153 |
| 1156 var controller = new StreamController<List<int>>(); | 1154 var controller = new StreamController<List<int>>(); |
| 1157 // TODO(nweiz): propagate any errors to the return value. See issue 3657. | 1155 // TODO(nweiz): propagate any errors to the return value. See issue 3657. |
| 1158 withTempDir((tempDir) { | 1156 withTempDir((tempDir) { |
| 1159 return create(tempDir).then((tar) { | 1157 return create(tempDir).then((tar) { |
| 1160 var sourceStream = tar.openInputStream(); | 1158 var sourceStream = new File(tar).openInputStream(); |
| 1161 return store(wrapInputStream(sourceStream), controller); | 1159 return store(wrapInputStream(sourceStream), controller); |
| 1162 }); | 1160 }); |
| 1163 }); | 1161 }); |
| 1164 return new ByteStream(controller.stream); | 1162 return new ByteStream(controller.stream); |
| 1165 } | 1163 } |
| 1166 } | 1164 } |
| 1167 | 1165 |
| 1168 /// A descriptor that validates that no file exists with the given name. | 1166 /// A descriptor that validates that no file exists with the given name. |
| 1169 class NothingDescriptor extends Descriptor { | 1167 class NothingDescriptor extends Descriptor { |
| 1170 NothingDescriptor(String name) : super(name); | 1168 NothingDescriptor(String name) : super(name); |
| 1171 | 1169 |
| 1172 Future create(dir) => new Future.immediate(null); | 1170 Future create(dir) => new Future.immediate(null); |
| 1173 Future delete(dir) => new Future.immediate(null); | 1171 Future delete(dir) => new Future.immediate(null); |
| 1174 | 1172 |
| 1175 Future validate(String dir) { | 1173 Future validate(String dir) { |
| 1176 return defer(() { | 1174 return defer(() { |
| 1177 if (entryExists(join(dir, name))) { | 1175 if (entryExists(path.join(dir, name))) { |
| 1178 throw new ExpectException('File $name in $dir should not exist.'); | 1176 throw new ExpectException('File $name in $dir should not exist.'); |
| 1179 } | 1177 } |
| 1180 }); | 1178 }); |
| 1181 } | 1179 } |
| 1182 | 1180 |
| 1183 ByteStream load(List<String> path) { | 1181 ByteStream load(List<String> path) { |
| 1184 if (path.isEmpty) { | 1182 if (path.isEmpty) { |
| 1185 throw "Can't load the contents of $name: it doesn't exist."; | 1183 throw "Can't load the contents of $name: it doesn't exist."; |
| 1186 } else { | 1184 } else { |
| 1187 throw "Can't load ${path.join('/')} from within $name: $name doesn't " | 1185 throw "Can't load ${path.join('/')} from within $name: $name doesn't " |
| 1188 "exist."; | 1186 "exist."; |
| 1189 } | 1187 } |
| 1190 } | 1188 } |
| 1191 } | 1189 } |
| 1192 | 1190 |
| 1193 /// A function that creates a [Validator] subclass. | 1191 /// A function that creates a [Validator] subclass. |
| 1194 typedef Validator ValidatorCreator(Entrypoint entrypoint); | 1192 typedef Validator ValidatorCreator(Entrypoint entrypoint); |
| 1195 | 1193 |
| 1196 /// Schedules a single [Validator] to run on the [appPath]. Returns a scheduled | 1194 /// Schedules a single [Validator] to run on the [appPath]. Returns a scheduled |
| 1197 /// Future that contains the errors and warnings produced by that validator. | 1195 /// Future that contains the errors and warnings produced by that validator. |
| 1198 Future<Pair<List<String>, List<String>>> schedulePackageValidation( | 1196 Future<Pair<List<String>, List<String>>> schedulePackageValidation( |
| 1199 ValidatorCreator fn) { | 1197 ValidatorCreator fn) { |
| 1200 return _scheduleValue((sandboxDir) { | 1198 return _scheduleValue((sandboxDir) { |
| 1201 var cache = new SystemCache.withSources(join(sandboxDir, cachePath)); | 1199 var cache = new SystemCache.withSources(path.join(sandboxDir, cachePath)); |
| 1202 | 1200 |
| 1203 return defer(() { | 1201 return defer(() { |
| 1204 var validator = fn(new Entrypoint(join(sandboxDir, appPath), cache)); | 1202 var validator = fn(new Entrypoint(path.join(sandboxDir, appPath), cache)); |
| 1205 return validator.validate().then((_) { | 1203 return validator.validate().then((_) { |
| 1206 return new Pair(validator.errors, validator.warnings); | 1204 return new Pair(validator.errors, validator.warnings); |
| 1207 }); | 1205 }); |
| 1208 }); | 1206 }); |
| 1209 }); | 1207 }); |
| 1210 } | 1208 } |
| 1211 | 1209 |
| 1212 /// A matcher that matches a Pair. | 1210 /// A matcher that matches a Pair. |
| 1213 Matcher pairOf(Matcher firstMatcher, Matcher lastMatcher) => | 1211 Matcher pairOf(Matcher firstMatcher, Matcher lastMatcher) => |
| 1214 new _PairMatcher(firstMatcher, lastMatcher); | 1212 new _PairMatcher(firstMatcher, lastMatcher); |
| (...skipping 411 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1626 /// calling [completion] is unnecessary. | 1624 /// calling [completion] is unnecessary. |
| 1627 void expectLater(Future actual, matcher, {String reason, | 1625 void expectLater(Future actual, matcher, {String reason, |
| 1628 FailureHandler failureHandler, bool verbose: false}) { | 1626 FailureHandler failureHandler, bool verbose: false}) { |
| 1629 _schedule((_) { | 1627 _schedule((_) { |
| 1630 return actual.then((value) { | 1628 return actual.then((value) { |
| 1631 expect(value, matcher, reason: reason, failureHandler: failureHandler, | 1629 expect(value, matcher, reason: reason, failureHandler: failureHandler, |
| 1632 verbose: false); | 1630 verbose: false); |
| 1633 }); | 1631 }); |
| 1634 }); | 1632 }); |
| 1635 } | 1633 } |
| OLD | NEW |