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