Index: tests/compiler/dart2js/lookup_map_test.dart |
diff --git a/tests/compiler/dart2js/lookup_map_test.dart b/tests/compiler/dart2js/lookup_map_test.dart |
new file mode 100644 |
index 0000000000000000000000000000000000000000..d73bc75ea7d1e467e78d21e712446140b62fd37f |
--- /dev/null |
+++ b/tests/compiler/dart2js/lookup_map_test.dart |
@@ -0,0 +1,261 @@ |
+// Copyright (c) 2015, the Dart project authors. Please see the AUTHORS file |
+// for details. All rights reserved. Use of this source code is governed by a |
+// BSD-style license that can be found in the LICENSE file. |
+ |
+library tests.dart2js.lookup_map_test; |
+ |
+import 'package:test/test.dart'; |
+import 'compiler_helper.dart'; |
+ |
+main() { |
+ test('live entries are kept', () async { |
+ String generated = await compileAll(r""" |
+ import 'package:lookup_map/lookup_map.dart'; |
+ class A{} |
+ const map = const LookupMap(const [ |
+ A, "the-text-for-A", |
+ ]); |
+ main() => print(map[A]); |
+ """); |
+ expect(generated, contains("the-text-for-A")); |
+ }); |
+ |
+ test('live entries are kept - single-pair', () async { |
+ String generated = await compileAll(r""" |
+ import 'package:lookup_map/lookup_map.dart'; |
+ class A{} |
+ const map = const LookupMap.pair(A, "the-text-for-A"); |
+ main() => print(map[A]); |
+ """); |
+ expect(generated, contains("the-text-for-A")); |
+ }); |
+ |
+ test('unused entries are removed', () async { |
+ String generated = await compileAll(r""" |
+ import 'package:lookup_map/lookup_map.dart'; |
+ class A{} |
+ class B{} |
+ const map = const LookupMap(const [ |
+ A, "the-text-for-A", |
+ B, "the-text-for-B", |
+ ]); |
+ main() => print(map[A]); |
+ """); |
+ expect(generated, isNot(contains("the-text-for-B"))); |
+ }); |
+ |
+ test('unused entries are removed - nested maps', () async { |
+ String generated = await compileAll(r""" |
+ import 'package:lookup_map/lookup_map.dart'; |
+ class A{} |
+ class B{} |
+ const map = const LookupMap(const [], const [ |
+ const LookupMap(const [ |
+ A, "the-text-for-A", |
+ B, "the-text-for-B", |
+ ]), |
+ ]); |
+ main() => print(map[A]); |
+ """); |
+ expect(generated, isNot(contains("the-text-for-B"))); |
+ }); |
+ |
+ test('unused entries are removed - single-pair', () async { |
+ String generated = await compileAll(r""" |
+ import 'package:lookup_map/lookup_map.dart'; |
+ class A{} |
+ class B{} |
+ const map = const LookupMap.pair(A, "the-text-for-A"); |
+ main() => print(map[A]); |
+ """); |
+ expect(generated, isNot(contains("the-text-for-B"))); |
+ }); |
+ |
+ test('unused entries are removed - nested single-pair', () async { |
+ String generated = await compileAll(r""" |
+ import 'package:lookup_map/lookup_map.dart'; |
+ class A{} |
+ class B{} |
+ const map = const LookupMap(const [], const [ |
+ const LookupMap.pair(A, "the-text-for-A"), |
+ const LookupMap.pair(B, "the-text-for-B"), |
+ ]); |
+ main() => print(map[A]); |
+ """); |
+ expect(generated, isNot(contains("the-text-for-B"))); |
+ }); |
+ |
+ test('works if entries are declared separate from map', () async { |
+ String generated = await compileAll(r""" |
+ import 'package:lookup_map/lookup_map.dart'; |
+ class A{} |
+ class B{} |
+ const entries = const [ |
+ A, "the-text-for-A", |
+ B, "the-text-for-B", |
+ ]; |
+ const map = const LookupMap(entries); |
+ main() => print(map[A]); |
+ """); |
+ expect(generated, isNot(contains("the-text-for-B"))); |
+ }); |
+ |
+ test('escaping entries disable tree-shaking', () async { |
+ String generated = await compileAll(r""" |
+ import 'package:lookup_map/lookup_map.dart'; |
+ class A{} |
+ class B{} |
+ const entries = const [ |
+ A, "the-text-for-A", |
+ B, "the-text-for-B", |
+ ]; |
+ const map = const LookupMap(entries); |
+ main() { |
+ entries.forEach(print); |
+ print(map[A]); |
+ } |
+ """); |
+ expect(generated, contains("the-text-for-B")); |
+ }); |
+ |
+ test('uses include recursively reachable data', () async { |
+ String generated = await compileAll(r""" |
+ import 'package:lookup_map/lookup_map.dart'; |
+ class A{} |
+ class B{} |
+ class C{} |
+ class D{} |
+ class E{} |
+ const map = const LookupMap(const [ |
+ A, const ["the-text-for-A", B], |
+ B, const ["the-text-for-B", C], |
+ C, const ["the-text-for-C"], |
+ D, const ["the-text-for-D", E], |
+ E, const ["the-text-for-E"], |
+ ]); |
+ main() => print(map[map[A][1]]); |
+ """); |
+ expect(generated, contains("the-text-for-A")); |
+ expect(generated, contains("the-text-for-B")); |
+ expect(generated, contains("the-text-for-C")); |
+ expect(generated, isNot(contains("the-text-for-D"))); |
+ expect(generated, isNot(contains("the-text-for-E"))); |
+ }); |
+ |
+ test('uses are found through newly discovered code', () async { |
+ String generated = await compileAll(r""" |
+ import 'package:lookup_map/lookup_map.dart'; |
+ class A{ A(B x);} |
+ class B{} |
+ class C{} |
+ class D{} |
+ class E{} |
+ createA() => new A(map[B][1]()); |
+ createB() => new B(); |
+ const map = const LookupMap(const [ |
+ A, const ["the-text-for-A", createA], |
+ B, const ["the-text-for-B", createB], |
+ C, const ["the-text-for-C"], |
+ ]); |
+ main() => print(map[A][1]()); |
+ """); |
+ expect(generated, contains("the-text-for-A")); |
+ expect(generated, contains("the-text-for-B")); |
+ expect(generated, isNot(contains("the-text-for-C"))); |
+ }); |
+ |
+ test('generic type allocations are considered used', () async { |
+ String generated = await compileAll(r""" |
+ import 'package:lookup_map/lookup_map.dart'; |
+ class A{} |
+ class M<T>{ get type => T; } |
+ const map = const LookupMap(const [ |
+ A, "the-text-for-A", |
+ ]); |
+ main() => print(map[new M<A>().type]); |
+ """); |
+ expect(generated, contains("the-text-for-A")); |
+ }); |
+ |
+ test('generics in type signatures are ignored', () async { |
+ String generated = await compileAll(r""" |
+ import 'package:lookup_map/lookup_map.dart'; |
+ class A{} |
+ class B{} |
+ class M<T>{ get type => T; } |
+ _factory(M<B> t) => t; |
+ const map = const LookupMap(const [ |
+ A, const ["the-text-for-A", _factory], |
+ B, "the-text-for-B", |
+ ]); |
+ main() => print(map[A]); |
+ """); |
+ expect(generated, isNot(contains("the-text-for-B"))); |
+ }); |
+ |
+ test('metadata is ignored', () async { |
+ String generated = await compileAll(r""" |
+ import 'package:lookup_map/lookup_map.dart'; |
+ class A{ const A(); } |
+ |
+ @A() |
+ class M {} |
+ const map = const LookupMap(const [ |
+ A, "the-text-for-A", |
+ ]); |
+ main() => print(map[M]); |
+ """); |
+ expect(generated, isNot(contains("the-text-for-A"))); |
+ }); |
+ |
+ test('shared constants used in metadata are ignored', () async { |
+ String generated = await compileAll(r""" |
+ import 'package:lookup_map/lookup_map.dart'; |
+ const annot = const B(foo: A); |
+ |
+ @B(foo: annot) |
+ class A{ const A(); } |
+ class B{ final Type foo; const B({this.foo}); } |
+ |
+ class M {} |
+ const map = const LookupMap(const [ |
+ A, const ["the-text-for-A", annot] |
+ ]); |
+ main() => print(map[M]); |
+ """); |
+ expect(generated, isNot(contains("the-text-for-A"))); |
+ }); |
+ |
+ // regression test for a failure when looking up `dynamic` in a generic. |
+ test('do not choke on dynamic types', () async { |
+ await compileAll(r""" |
+ import 'package:lookup_map/lookup_map.dart'; |
+ class A{} |
+ class M<T>{ get type => T; } |
+ const map = const LookupMap(const [ |
+ A, "the-text-for-A", |
+ ]); |
+ main() => print(map[new M<dynamic>().type]); |
+ """); |
+ }); |
+ |
+ |
+ test('support subclassing LookupMap', () async { |
+ String generated = await compileAll(r""" |
+ import 'package:lookup_map/lookup_map.dart'; |
+ class A{} |
+ class B{} |
+ class S extends LookupMap { |
+ const S(list) : super(list); |
+ } |
+ const map = const S(const [ |
+ A, "the-text-for-A", |
+ B, "the-text-for-B", |
+ ]); |
+ |
+ main() => print(map[A]); |
+ """); |
+ expect(generated, contains("the-text-for-A")); |
+ expect(generated, isNot(contains("the-text-for-B"))); |
+ }); |
+} |