OLD | NEW |
(Empty) | |
| 1 // Copyright (c) 2014, the Dart project authors. Please see the AUTHORS file |
| 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. |
| 4 |
| 5 library code_transformers.test.resolver_test; |
| 6 |
| 7 import 'dart:async'; |
| 8 |
| 9 import 'package:barback/barback.dart'; |
| 10 import 'package:code_transformers/resolver.dart'; |
| 11 import 'package:code_transformers/tests.dart'; |
| 12 import 'package:unittest/compact_vm_config.dart'; |
| 13 import 'package:unittest/unittest.dart'; |
| 14 |
| 15 import 'package:code_transformers/src/dart_sdk.dart' show mockSdkSources; |
| 16 |
| 17 main() { |
| 18 useCompactVMConfiguration(); |
| 19 group('mock sdk', () { |
| 20 resolverTests(new Resolvers.fromMock(mockSdkSources)); |
| 21 }); |
| 22 |
| 23 group('real sdk', () { |
| 24 resolverTests(new Resolvers(testingDartSdkDirectory)); |
| 25 }); |
| 26 } |
| 27 |
| 28 resolverTests(Resolvers resolvers) { |
| 29 var entryPoint = new AssetId('a', 'web/main.dart'); |
| 30 Future validateResolver({Map<String, String> inputs, validator(Resolver), |
| 31 List<String> messages: const []}) { |
| 32 return applyTransformers( |
| 33 [[new TestTransformer(resolvers, entryPoint, validator)]], |
| 34 inputs: inputs, messages: messages); |
| 35 } |
| 36 |
| 37 group('Resolver', () { |
| 38 test('should handle initial files', () { |
| 39 return validateResolver( |
| 40 inputs: {'a|web/main.dart': ' main() {}',}, validator: (resolver) { |
| 41 var source = resolver.sources[entryPoint]; |
| 42 expect(source.modificationStamp, 1); |
| 43 |
| 44 var lib = resolver.getLibrary(entryPoint); |
| 45 expect(lib, isNotNull); |
| 46 }); |
| 47 }); |
| 48 |
| 49 test('should update when sources change', () { |
| 50 return validateResolver(inputs: { |
| 51 'a|web/main.dart': ''' main() { |
| 52 } ''', |
| 53 }, validator: (resolver) { |
| 54 var source = resolver.sources[entryPoint]; |
| 55 expect(source.modificationStamp, 2); |
| 56 |
| 57 var lib = resolver.getLibrary(entryPoint); |
| 58 expect(lib, isNotNull); |
| 59 expect(lib.entryPoint, isNotNull); |
| 60 }); |
| 61 }); |
| 62 |
| 63 test('should follow imports', () { |
| 64 return validateResolver(inputs: { |
| 65 'a|web/main.dart': ''' |
| 66 import 'a.dart'; |
| 67 |
| 68 main() { |
| 69 } ''', |
| 70 'a|web/a.dart': ''' |
| 71 library a; |
| 72 ''', |
| 73 }, validator: (resolver) { |
| 74 var lib = resolver.getLibrary(entryPoint); |
| 75 expect(lib.importedLibraries.length, 2); |
| 76 var libA = lib.importedLibraries.where((l) => l.name == 'a').single; |
| 77 expect(libA.getType('Foo'), isNull); |
| 78 }); |
| 79 }); |
| 80 |
| 81 test('should update changed imports', () { |
| 82 return validateResolver(inputs: { |
| 83 'a|web/main.dart': ''' |
| 84 import 'a.dart'; |
| 85 |
| 86 main() { |
| 87 } ''', |
| 88 'a|web/a.dart': ''' |
| 89 library a; |
| 90 class Foo {} |
| 91 ''', |
| 92 }, validator: (resolver) { |
| 93 var lib = resolver.getLibrary(entryPoint); |
| 94 expect(lib.importedLibraries.length, 2); |
| 95 var libA = lib.importedLibraries.where((l) => l.name == 'a').single; |
| 96 expect(libA.getType('Foo'), isNotNull); |
| 97 }); |
| 98 }); |
| 99 |
| 100 test('should follow package imports', () { |
| 101 return validateResolver(inputs: { |
| 102 'a|web/main.dart': ''' |
| 103 import 'package:b/b.dart'; |
| 104 |
| 105 main() { |
| 106 } ''', |
| 107 'b|lib/b.dart': ''' |
| 108 library b; |
| 109 ''', |
| 110 }, validator: (resolver) { |
| 111 var lib = resolver.getLibrary(entryPoint); |
| 112 expect(lib.importedLibraries.length, 2); |
| 113 var libB = lib.importedLibraries.where((l) => l.name == 'b').single; |
| 114 expect(libB.getType('Foo'), isNull); |
| 115 }); |
| 116 }); |
| 117 |
| 118 test('handles missing files', () { |
| 119 return validateResolver(inputs: { |
| 120 'a|web/main.dart': ''' |
| 121 import 'package:b/missing.dart'; |
| 122 |
| 123 main() { |
| 124 } ''', |
| 125 }, validator: (resolver) { |
| 126 var lib = resolver.getLibrary(entryPoint); |
| 127 expect(lib.importedLibraries.length, 1); |
| 128 }); |
| 129 }); |
| 130 |
| 131 test('should update on changed package imports', () { |
| 132 // TODO(sigmund): remove modification below, see dartbug.com/22638 |
| 133 return validateResolver(inputs: { |
| 134 'a|web/main.dart': ''' |
| 135 import 'package:b/missing.dart'; |
| 136 |
| 137 main() { |
| 138 } // modified, but we shouldn't need to! ''', |
| 139 'b|lib/missing.dart': ''' |
| 140 library b; |
| 141 class Bar {} |
| 142 ''', |
| 143 }, validator: (resolver) { |
| 144 var lib = resolver.getLibrary(entryPoint); |
| 145 expect(lib.importedLibraries.length, 2); |
| 146 var libB = lib.importedLibraries.where((l) => l.name == 'b').single; |
| 147 expect(libB.getType('Bar'), isNotNull); |
| 148 }); |
| 149 }); |
| 150 |
| 151 test('should handle deleted files', () { |
| 152 return validateResolver(inputs: { |
| 153 'a|web/main.dart': ''' |
| 154 import 'package:b/missing.dart'; |
| 155 |
| 156 main() { |
| 157 } ''', |
| 158 }, validator: (resolver) { |
| 159 var lib = resolver.getLibrary(entryPoint); |
| 160 expect(lib.importedLibraries.length, 1); |
| 161 }); |
| 162 }); |
| 163 |
| 164 test('should fail on absolute URIs', () { |
| 165 var warningPrefix = 'warning: absolute paths not allowed'; |
| 166 return validateResolver(inputs: { |
| 167 'a|web/main.dart': ''' |
| 168 import '/b.dart'; |
| 169 |
| 170 main() { |
| 171 } ''', |
| 172 }, messages: [ |
| 173 // First from the AST walker |
| 174 '$warningPrefix: "/b.dart" (web/main.dart 0 14)', |
| 175 '$warningPrefix: "/b.dart"', |
| 176 ], validator: (resolver) { |
| 177 var lib = resolver.getLibrary(entryPoint); |
| 178 expect(lib.importedLibraries.length, 1); |
| 179 }); |
| 180 }); |
| 181 |
| 182 test('should list all libraries', () { |
| 183 return validateResolver(inputs: { |
| 184 'a|web/main.dart': ''' |
| 185 library a.main; |
| 186 import 'package:a/a.dart'; |
| 187 import 'package:a/b.dart'; |
| 188 export 'package:a/d.dart'; |
| 189 ''', |
| 190 'a|lib/a.dart': 'library a.a;\n import "package:a/c.dart";', |
| 191 'a|lib/b.dart': 'library a.b;\n import "c.dart";', |
| 192 'a|lib/c.dart': 'library a.c;', |
| 193 'a|lib/d.dart': 'library a.d;' |
| 194 }, validator: (resolver) { |
| 195 var libs = resolver.libraries.where((l) => !l.isInSdk); |
| 196 expect(libs.map((l) => l.name), |
| 197 unorderedEquals(['a.main', 'a.a', 'a.b', 'a.c', 'a.d',])); |
| 198 }); |
| 199 }); |
| 200 |
| 201 test('should resolve types and library uris', () { |
| 202 return validateResolver(inputs: { |
| 203 'a|web/main.dart': ''' |
| 204 import 'dart:core'; |
| 205 import 'package:a/a.dart'; |
| 206 import 'package:a/b.dart'; |
| 207 import 'sub_dir/d.dart'; |
| 208 class Foo {} |
| 209 ''', |
| 210 'a|lib/a.dart': 'library a.a;\n import "package:a/c.dart";', |
| 211 'a|lib/b.dart': 'library a.b;\n import "c.dart";', |
| 212 'a|lib/c.dart': ''' |
| 213 library a.c; |
| 214 class Bar {} |
| 215 ''', |
| 216 'a|web/sub_dir/d.dart': ''' |
| 217 library a.web.sub_dir.d; |
| 218 class Baz{} |
| 219 ''', |
| 220 }, validator: (resolver) { |
| 221 var a = resolver.getLibraryByName('a.a'); |
| 222 expect(a, isNotNull); |
| 223 expect(resolver.getImportUri(a).toString(), 'package:a/a.dart'); |
| 224 expect(resolver.getLibraryByUri(Uri.parse('package:a/a.dart')), a); |
| 225 |
| 226 var main = resolver.getLibraryByName(''); |
| 227 expect(main, isNotNull); |
| 228 expect(resolver.getImportUri(main), isNull); |
| 229 |
| 230 var fooType = resolver.getType('Foo'); |
| 231 expect(fooType, isNotNull); |
| 232 expect(fooType.library, main); |
| 233 |
| 234 var barType = resolver.getType('a.c.Bar'); |
| 235 expect(barType, isNotNull); |
| 236 expect(resolver.getImportUri(barType.library).toString(), |
| 237 'package:a/c.dart'); |
| 238 expect( |
| 239 resolver.getSourceAssetId(barType), new AssetId('a', 'lib/c.dart')); |
| 240 |
| 241 var bazType = resolver.getType('a.web.sub_dir.d.Baz'); |
| 242 expect(bazType, isNotNull); |
| 243 expect(resolver.getImportUri(bazType.library), isNull); |
| 244 expect( |
| 245 resolver.getImportUri(bazType.library, from: entryPoint).toString(), |
| 246 'sub_dir/d.dart'); |
| 247 |
| 248 var hashMap = resolver.getType('dart.collection.HashMap'); |
| 249 expect(resolver.getImportUri(hashMap.library).toString(), |
| 250 'dart:collection'); |
| 251 expect(resolver.getLibraryByUri(Uri.parse('dart:collection')), |
| 252 hashMap.library); |
| 253 }); |
| 254 }); |
| 255 |
| 256 test('deleted files should be removed', () { |
| 257 return validateResolver( |
| 258 inputs: { |
| 259 'a|web/main.dart': '''import 'package:a/a.dart';''', |
| 260 'a|lib/a.dart': '''import 'package:a/b.dart';''', |
| 261 'a|lib/b.dart': '''class Engine{}''', |
| 262 }, |
| 263 validator: (resolver) { |
| 264 var engine = resolver.getType('Engine'); |
| 265 var uri = resolver.getImportUri(engine.library); |
| 266 expect(uri.toString(), 'package:a/b.dart'); |
| 267 }).then((_) { |
| 268 return validateResolver( |
| 269 inputs: { |
| 270 'a|web/main.dart': '''import 'package:a/a.dart';''', |
| 271 'a|lib/a.dart': '''lib a;\n class Engine{}''' |
| 272 }, |
| 273 validator: (resolver) { |
| 274 var engine = resolver.getType('Engine'); |
| 275 var uri = resolver.getImportUri(engine.library); |
| 276 expect(uri.toString(), 'package:a/a.dart'); |
| 277 |
| 278 // Make sure that we haven't leaked any sources. |
| 279 expect(resolver.sources.length, 2); |
| 280 }); |
| 281 }); |
| 282 }); |
| 283 |
| 284 test('handles circular imports', () { |
| 285 return validateResolver(inputs: { |
| 286 'a|web/main.dart': ''' |
| 287 library main; |
| 288 import 'package:a/a.dart'; ''', |
| 289 'a|lib/a.dart': ''' |
| 290 library a; |
| 291 import 'package:a/b.dart'; ''', |
| 292 'a|lib/b.dart': ''' |
| 293 library b; |
| 294 import 'package:a/a.dart'; ''', |
| 295 }, validator: (resolver) { |
| 296 var libs = resolver.libraries.map((lib) => lib.name); |
| 297 expect(libs.contains('a'), isTrue); |
| 298 expect(libs.contains('b'), isTrue); |
| 299 }); |
| 300 }); |
| 301 |
| 302 test('handles parallel resolves', () { |
| 303 return Future.wait([ |
| 304 validateResolver(inputs: { |
| 305 'a|web/main.dart': ''' |
| 306 library foo;''' |
| 307 }, validator: (resolver) { |
| 308 expect(resolver.getLibrary(entryPoint).name, 'foo'); |
| 309 }), |
| 310 validateResolver(inputs: { |
| 311 'a|web/main.dart': ''' |
| 312 library bar;''' |
| 313 }, validator: (resolver) { |
| 314 expect(resolver.getLibrary(entryPoint).name, 'bar'); |
| 315 }), |
| 316 ]); |
| 317 }); |
| 318 }); |
| 319 } |
| 320 |
| 321 class TestTransformer extends Transformer with ResolverTransformer { |
| 322 final AssetId primary; |
| 323 final Function validator; |
| 324 |
| 325 TestTransformer(Resolvers resolvers, this.primary, this.validator) { |
| 326 this.resolvers = resolvers; |
| 327 } |
| 328 |
| 329 // TODO(nweiz): This should just take an AssetId when barback <0.13.0 support |
| 330 // is dropped. |
| 331 Future<bool> isPrimary(idOrAsset) { |
| 332 var id = idOrAsset is AssetId ? idOrAsset : idOrAsset.id; |
| 333 return new Future.value(id == primary); |
| 334 } |
| 335 |
| 336 applyResolver(Transform transform, Resolver resolver) => validator(resolver); |
| 337 } |
OLD | NEW |