| 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
|
| index d73bc75ea7d1e467e78d21e712446140b62fd37f..a93e0a64a02d86388debdb93b1423ecd5939a2f4 100644
|
| --- a/tests/compiler/dart2js/lookup_map_test.dart
|
| +++ b/tests/compiler/dart2js/lookup_map_test.dart
|
| @@ -8,10 +8,49 @@ import 'package:test/test.dart';
|
| import 'compiler_helper.dart';
|
|
|
| main() {
|
| + Map<String, String> testDeclarations = {
|
| + 'types': r'''
|
| + import 'package:lookup_map/lookup_map.dart';
|
| + class A {}
|
| + class B {}
|
| + class C {}
|
| + class D {}
|
| + class E {}''',
|
| +
|
| + 'const keys': r'''
|
| + import 'package:lookup_map/lookup_map.dart';
|
| + class Key { final name; const Key(this.name); }
|
| + const A = const Key("A");
|
| + const B = const Key("B");
|
| + const C = const Key("C");
|
| + const D = const Key("D");
|
| + const E = const Key("E");''',
|
| +
|
| + 'mixed keys': r'''
|
| + import 'package:lookup_map/lookup_map.dart';
|
| + class Key { final name; const Key(this.name); }
|
| + const A = const Key("A");
|
| + class B {}
|
| + const C = const Key("C");
|
| + class D {}
|
| + const E = const Key("E");''',
|
| + };
|
| +
|
| + testDeclarations.forEach((name, declarations) {
|
| + group(name, () => _commonTests(declarations));
|
| + });
|
| + group('generic', _genericTests);
|
| + group('metadata', _metadataTests);
|
| + group('unsupported', _unsupportedKeysTests);
|
| +}
|
| +
|
| +/// Common tests for both declarations that use Types or other const expressions
|
| +/// as keys. The argument [declaration] should contain a declaration for
|
| +/// constant keys named `A`, `B`, `C`, `D`, and `E`.
|
| +_commonTests(String declarations) {
|
| test('live entries are kept', () async {
|
| - String generated = await compileAll(r"""
|
| - import 'package:lookup_map/lookup_map.dart';
|
| - class A{}
|
| + String generated = await compileAll("""
|
| + $declarations
|
| const map = const LookupMap(const [
|
| A, "the-text-for-A",
|
| ]);
|
| @@ -21,9 +60,8 @@ main() {
|
| });
|
|
|
| test('live entries are kept - single-pair', () async {
|
| - String generated = await compileAll(r"""
|
| - import 'package:lookup_map/lookup_map.dart';
|
| - class A{}
|
| + String generated = await compileAll("""
|
| + $declarations
|
| const map = const LookupMap.pair(A, "the-text-for-A");
|
| main() => print(map[A]);
|
| """);
|
| @@ -31,10 +69,8 @@ main() {
|
| });
|
|
|
| test('unused entries are removed', () async {
|
| - String generated = await compileAll(r"""
|
| - import 'package:lookup_map/lookup_map.dart';
|
| - class A{}
|
| - class B{}
|
| + String generated = await compileAll("""
|
| + $declarations
|
| const map = const LookupMap(const [
|
| A, "the-text-for-A",
|
| B, "the-text-for-B",
|
| @@ -45,10 +81,8 @@ main() {
|
| });
|
|
|
| test('unused entries are removed - nested maps', () async {
|
| - String generated = await compileAll(r"""
|
| - import 'package:lookup_map/lookup_map.dart';
|
| - class A{}
|
| - class B{}
|
| + String generated = await compileAll("""
|
| + $declarations
|
| const map = const LookupMap(const [], const [
|
| const LookupMap(const [
|
| A, "the-text-for-A",
|
| @@ -61,10 +95,8 @@ main() {
|
| });
|
|
|
| test('unused entries are removed - single-pair', () async {
|
| - String generated = await compileAll(r"""
|
| - import 'package:lookup_map/lookup_map.dart';
|
| - class A{}
|
| - class B{}
|
| + String generated = await compileAll("""
|
| + $declarations
|
| const map = const LookupMap.pair(A, "the-text-for-A");
|
| main() => print(map[A]);
|
| """);
|
| @@ -72,10 +104,9 @@ main() {
|
| });
|
|
|
| test('unused entries are removed - nested single-pair', () async {
|
| - String generated = await compileAll(r"""
|
| + String generated = await compileAll("""
|
| import 'package:lookup_map/lookup_map.dart';
|
| - class A{}
|
| - class B{}
|
| + $declarations
|
| const map = const LookupMap(const [], const [
|
| const LookupMap.pair(A, "the-text-for-A"),
|
| const LookupMap.pair(B, "the-text-for-B"),
|
| @@ -86,10 +117,8 @@ main() {
|
| });
|
|
|
| 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{}
|
| + String generated = await compileAll("""
|
| + $declarations
|
| const entries = const [
|
| A, "the-text-for-A",
|
| B, "the-text-for-B",
|
| @@ -101,10 +130,8 @@ main() {
|
| });
|
|
|
| test('escaping entries disable tree-shaking', () async {
|
| - String generated = await compileAll(r"""
|
| - import 'package:lookup_map/lookup_map.dart';
|
| - class A{}
|
| - class B{}
|
| + String generated = await compileAll("""
|
| + $declarations
|
| const entries = const [
|
| A, "the-text-for-A",
|
| B, "the-text-for-B",
|
| @@ -119,13 +146,8 @@ main() {
|
| });
|
|
|
| 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{}
|
| + String generated = await compileAll("""
|
| + $declarations
|
| const map = const LookupMap(const [
|
| A, const ["the-text-for-A", B],
|
| B, const ["the-text-for-B", C],
|
| @@ -143,27 +165,62 @@ main() {
|
| });
|
|
|
| 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();
|
| + String generated = await compileAll("""
|
| + $declarations
|
| + f1() => map[B][1]();
|
| + f2() => E;
|
| const map = const LookupMap(const [
|
| - A, const ["the-text-for-A", createA],
|
| - B, const ["the-text-for-B", createB],
|
| + A, const ["the-text-for-A", f1],
|
| + B, const ["the-text-for-B", f2],
|
| C, const ["the-text-for-C"],
|
| + D, const ["the-text-for-D"],
|
| + E, const ["the-text-for-E"],
|
| ]);
|
| 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")));
|
| + expect(generated, isNot(contains("the-text-for-C")));
|
| + expect(generated, contains("the-text-for-E"));
|
| + });
|
| +
|
| + test('support subclassing LookupMap', () async {
|
| + String generated = await compileAll("""
|
| + $declarations
|
| + 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")));
|
| });
|
|
|
| + test('constants keys are processed recursively', () async {
|
| + String generated = await compileAll("""
|
| + $declarations
|
| +
|
| + const nested = const [ B ];
|
| + const map = const LookupMap(const [
|
| + A, "the-text-for-A",
|
| + B, "the-text-for-B",
|
| + ]);
|
| + main() => print(map[nested]);
|
| + """);
|
| + expect(generated, isNot(contains("the-text-for-A")));
|
| + expect(generated, contains("the-text-for-B"));
|
| + });
|
| +}
|
| +
|
| +/// Tests specific to type keys, we ensure that generic type arguments are
|
| +/// considered.
|
| +_genericTests() {
|
| test('generic type allocations are considered used', () async {
|
| String generated = await compileAll(r"""
|
| import 'package:lookup_map/lookup_map.dart';
|
| @@ -193,6 +250,23 @@ main() {
|
| expect(generated, isNot(contains("the-text-for-B")));
|
| });
|
|
|
| + // regression test for a failure when looking up `dynamic` in a generic.
|
| + test('do not choke with dynamic type arguments', () 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]);
|
| + """);
|
| + });
|
| +}
|
| +
|
| +/// Sanity checks about metadata: it is ignored for codegen even though it is
|
| +/// visited during resolution.
|
| +_metadataTests() {
|
| test('metadata is ignored', () async {
|
| String generated = await compileAll(r"""
|
| import 'package:lookup_map/lookup_map.dart';
|
| @@ -225,37 +299,47 @@ main() {
|
| """);
|
| 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"""
|
| +_unsupportedKeysTests() {
|
| + test('primitive and string keys are always kept', () async {
|
| + String generated = await compileAll("""
|
| import 'package:lookup_map/lookup_map.dart';
|
| - class A{}
|
| - class M<T>{ get type => T; }
|
| + const A = "A";
|
| + const B = "B";
|
| const map = const LookupMap(const [
|
| A, "the-text-for-A",
|
| + B, "the-text-for-B",
|
| + 3, "the-text-for-3",
|
| + 1.1, "the-text-for-1.1",
|
| + false, "the-text-for-false",
|
| ]);
|
| - main() => print(map[new M<dynamic>().type]);
|
| + main() => print(map[A]);
|
| """);
|
| + expect(generated, contains("the-text-for-A"));
|
| + expect(generated, contains("the-text-for-B"));
|
| + expect(generated, contains("the-text-for-3"));
|
| + expect(generated, contains("the-text-for-1.1"));
|
| + expect(generated, contains("the-text-for-false"));
|
| });
|
|
|
| -
|
| - test('support subclassing LookupMap', () async {
|
| - String generated = await compileAll(r"""
|
| + test('non-type const keys implementing equals are not removed', () async {
|
| + String generated = await compileAll("""
|
| import 'package:lookup_map/lookup_map.dart';
|
| - class A{}
|
| - class B{}
|
| - class S extends LookupMap {
|
| - const S(list) : super(list);
|
| + class Key {
|
| + final name;
|
| + const Key(this.name);
|
| + int get hashCode => name.hashCode * 13;
|
| + operator ==(other) => other is Key && name == other.name;
|
| }
|
| - const map = const S(const [
|
| + const A = const Key("A");
|
| + const B = const Key("B");
|
| + const map = const LookupMap(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")));
|
| + expect(generated, contains("the-text-for-B"));
|
| });
|
| }
|
|
|