Simplify class_hierarchy_test: Move tests of getLegacyLeastUpperBound to own file

Change-Id: Iff64676644f17c32dea2b01e0c25e92af1f63774
Reviewed-on: https://dart-review.googlesource.com/c/93024
Commit-Queue: Peter von der Ahé <ahe@google.com>
Reviewed-by: Jens Johansen <jensj@google.com>
diff --git a/pkg/front_end/test/fasta/types/legacy_upper_bound_test.dart b/pkg/front_end/test/fasta/types/legacy_upper_bound_test.dart
new file mode 100644
index 0000000..24b04d2
--- /dev/null
+++ b/pkg/front_end/test/fasta/types/legacy_upper_bound_test.dart
@@ -0,0 +1,292 @@
+// Copyright (c) 2019, 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.
+
+import "package:expect/matchers_lite.dart";
+
+import "package:kernel/ast.dart";
+import "package:kernel/class_hierarchy.dart";
+import "package:kernel/core_types.dart";
+import "package:kernel/testing/mock_sdk_component.dart";
+import "package:kernel/text/ast_to_text.dart";
+import "package:kernel/type_algebra.dart";
+
+main() {
+  new LegacyUpperBoundTest().test_getLegacyLeastUpperBound_expansive();
+
+  new LegacyUpperBoundTest().test_getLegacyLeastUpperBound_generic();
+
+  new LegacyUpperBoundTest().test_getLegacyLeastUpperBound_nonGeneric();
+}
+
+class LegacyUpperBoundTest {
+  final Component component = createMockSdkComponent();
+
+  CoreTypes coreTypes;
+
+  final Library library =
+      new Library(Uri.parse('org-dartlang:///test.dart'), name: 'test');
+
+  ClassHierarchy _hierarchy;
+
+  LegacyUpperBoundTest() {
+    coreTypes = new CoreTypes(component);
+    library.parent = component;
+    component.libraries.add(library);
+  }
+
+  Class get objectClass => coreTypes.objectClass;
+
+  Supertype get objectSuper => coreTypes.objectClass.asThisSupertype;
+
+  ClassHierarchy get hierarchy {
+    return _hierarchy ??= createClassHierarchy(component);
+  }
+
+  Class addClass(Class c) {
+    if (_hierarchy != null) {
+      fail('The classs hierarchy has already been created.');
+    }
+    library.addClass(c);
+    return c;
+  }
+
+  /// Assert that the test [library] has the [expectedText] presentation.
+  /// The presentation is close, but not identical to the normal Kernel one.
+  void _assertTestLibraryText(String expectedText) {
+    _assertLibraryText(library, expectedText);
+  }
+
+  void _assertLibraryText(Library lib, String expectedText) {
+    StringBuffer sb = new StringBuffer();
+    Printer printer = new Printer(sb);
+    printer.writeLibraryFile(lib);
+
+    String actualText = sb.toString();
+
+    // Clean up the text a bit.
+    const oftenUsedPrefix = '''
+library test;
+import self as self;
+import "dart:core" as core;
+
+''';
+    if (actualText.startsWith(oftenUsedPrefix)) {
+      actualText = actualText.substring(oftenUsedPrefix.length);
+    }
+    actualText = actualText.replaceAll('{\n}', '{}');
+    actualText = actualText.replaceAll(' extends core::Object', '');
+
+    if (actualText != expectedText) {
+      print('-------- Actual --------');
+      print(actualText + '------------------------');
+    }
+
+    expect(actualText, expectedText);
+  }
+
+  ClassHierarchy createClassHierarchy(Component component) {
+    return new ClassHierarchy(component);
+  }
+
+  /// Add a new generic class with the given [name] and [typeParameterNames].
+  /// The [TypeParameterType]s corresponding to [typeParameterNames] are
+  /// passed to optional [extends_] and [implements_] callbacks.
+  Class addGenericClass(String name, List<String> typeParameterNames,
+      {Supertype extends_(List<DartType> typeParameterTypes),
+      List<Supertype> implements_(List<DartType> typeParameterTypes)}) {
+    var typeParameters = typeParameterNames
+        .map((name) => new TypeParameter(name, objectClass.rawType))
+        .toList();
+    var typeParameterTypes = typeParameters
+        .map((parameter) => new TypeParameterType(parameter))
+        .toList();
+    var supertype =
+        extends_ != null ? extends_(typeParameterTypes) : objectSuper;
+    var implementedTypes =
+        implements_ != null ? implements_(typeParameterTypes) : <Supertype>[];
+    return addClass(new Class(
+        name: name,
+        typeParameters: typeParameters,
+        supertype: supertype,
+        implementedTypes: implementedTypes));
+  }
+
+  /// Add a new class with the given [name] that extends `Object` and
+  /// [implements_] the given classes.
+  Class addImplementsClass(String name, List<Class> implements_) {
+    return addClass(new Class(
+        name: name,
+        supertype: objectSuper,
+        implementedTypes: implements_.map((c) => c.asThisSupertype).toList()));
+  }
+
+  /// Copy of the tests/language/least_upper_bound_expansive_test.dart test.
+  void test_getLegacyLeastUpperBound_expansive() {
+    var int = coreTypes.intClass.rawType;
+    var string = coreTypes.stringClass.rawType;
+
+    // class N<T> {}
+    var NT = new TypeParameter('T', objectClass.rawType);
+    var N = addClass(
+        new Class(name: 'N', typeParameters: [NT], supertype: objectSuper));
+
+    // class C1<T> extends N<N<C1<T>>> {}
+    Class C1;
+    {
+      var T = new TypeParameter('T', objectClass.rawType);
+      C1 = addClass(
+          new Class(name: 'C1', typeParameters: [T], supertype: objectSuper));
+      DartType C1_T = Substitution.fromMap({T: new TypeParameterType(T)})
+          .substituteType(C1.thisType);
+      DartType N_C1_T =
+          Substitution.fromMap({NT: C1_T}).substituteType(N.thisType);
+      Supertype N_N_C1_T = Substitution.fromMap({NT: N_C1_T})
+          .substituteSupertype(N.asThisSupertype);
+      C1.supertype = N_N_C1_T;
+    }
+
+    // class C2<T> extends N<N<C2<N<C2<T>>>>> {}
+    Class C2;
+    {
+      var T = new TypeParameter('T', objectClass.rawType);
+      C2 = addClass(
+          new Class(name: 'C2', typeParameters: [T], supertype: objectSuper));
+      DartType C2_T = Substitution.fromMap({T: new TypeParameterType(T)})
+          .substituteType(C2.thisType);
+      DartType N_C2_T =
+          Substitution.fromMap({NT: C2_T}).substituteType(N.thisType);
+      DartType C2_N_C2_T =
+          Substitution.fromMap({T: N_C2_T}).substituteType(C2.thisType);
+      DartType N_C2_N_C2_T =
+          Substitution.fromMap({NT: C2_N_C2_T}).substituteType(N.thisType);
+      Supertype N_N_C2_N_C2_T = Substitution.fromMap({NT: N_C2_N_C2_T})
+          .substituteSupertype(N.asThisSupertype);
+      C2.supertype = N_N_C2_N_C2_T;
+    }
+
+    _assertTestLibraryText('''
+class N<T> {}
+class C1<T> extends self::N<self::N<self::C1<self::C1::T>>> {}
+class C2<T> extends self::N<self::N<self::C2<self::N<self::C2<self::C2::T>>>>> {}
+''');
+
+    // The least upper bound of C1<int> and N<C1<String>> is Object since the
+    // supertypes are
+    //     {C1<int>, N<N<C1<int>>>, Object} for C1<int> and
+    //     {N<C1<String>>, Object} for N<C1<String>> and
+    // Object is the most specific type in the intersection of the supertypes.
+    expect(
+        hierarchy.getLegacyLeastUpperBound(
+            new InterfaceType(C1, [int]),
+            new InterfaceType(N, [
+              new InterfaceType(C1, [string])
+            ])),
+        objectClass.thisType);
+
+    // The least upper bound of C2<int> and N<C2<String>> is Object since the
+    // supertypes are
+    //     {C2<int>, N<N<C2<N<C2<int>>>>>, Object} for C2<int> and
+    //     {N<C2<String>>, Object} for N<C2<String>> and
+    // Object is the most specific type in the intersection of the supertypes.
+    expect(
+        hierarchy.getLegacyLeastUpperBound(
+            new InterfaceType(C2, [int]),
+            new InterfaceType(N, [
+              new InterfaceType(C2, [string])
+            ])),
+        objectClass.thisType);
+  }
+
+  void test_getLegacyLeastUpperBound_generic() {
+    var int = coreTypes.intClass.rawType;
+    var double = coreTypes.doubleClass.rawType;
+    var bool = coreTypes.boolClass.rawType;
+
+    var a = addGenericClass('A', []);
+    var b =
+        addGenericClass('B', ['T'], implements_: (_) => [a.asThisSupertype]);
+    var c =
+        addGenericClass('C', ['U'], implements_: (_) => [a.asThisSupertype]);
+    var d = addGenericClass('D', ['T', 'U'], implements_: (typeParameterTypes) {
+      var t = typeParameterTypes[0];
+      var u = typeParameterTypes[1];
+      return [
+        new Supertype(b, [t]),
+        new Supertype(c, [u])
+      ];
+    });
+    var e = addGenericClass('E', [],
+        implements_: (_) => [
+              new Supertype(d, [int, double])
+            ]);
+    var f = addGenericClass('F', [],
+        implements_: (_) => [
+              new Supertype(d, [int, bool])
+            ]);
+
+    _assertTestLibraryText('''
+class A {}
+class B<T> implements self::A {}
+class C<U> implements self::A {}
+class D<T, U> implements self::B<self::D::T>, self::C<self::D::U> {}
+class E implements self::D<core::int, core::double> {}
+class F implements self::D<core::int, core::bool> {}
+''');
+
+    expect(
+        hierarchy.getLegacyLeastUpperBound(new InterfaceType(d, [int, double]),
+            new InterfaceType(d, [int, double])),
+        new InterfaceType(d, [int, double]));
+    expect(
+        hierarchy.getLegacyLeastUpperBound(new InterfaceType(d, [int, double]),
+            new InterfaceType(d, [int, bool])),
+        new InterfaceType(b, [int]));
+    expect(
+        hierarchy.getLegacyLeastUpperBound(new InterfaceType(d, [int, double]),
+            new InterfaceType(d, [bool, double])),
+        new InterfaceType(c, [double]));
+    expect(
+        hierarchy.getLegacyLeastUpperBound(new InterfaceType(d, [int, double]),
+            new InterfaceType(d, [bool, int])),
+        a.rawType);
+    expect(hierarchy.getLegacyLeastUpperBound(e.rawType, f.rawType),
+        new InterfaceType(b, [int]));
+  }
+
+  void test_getLegacyLeastUpperBound_nonGeneric() {
+    var a = addImplementsClass('A', []);
+    var b = addImplementsClass('B', []);
+    var c = addImplementsClass('C', [a]);
+    var d = addImplementsClass('D', [a]);
+    var e = addImplementsClass('E', [a]);
+    var f = addImplementsClass('F', [c, d]);
+    var g = addImplementsClass('G', [c, d]);
+    var h = addImplementsClass('H', [c, d, e]);
+    var i = addImplementsClass('I', [c, d, e]);
+
+    _assertTestLibraryText('''
+class A {}
+class B {}
+class C implements self::A {}
+class D implements self::A {}
+class E implements self::A {}
+class F implements self::C, self::D {}
+class G implements self::C, self::D {}
+class H implements self::C, self::D, self::E {}
+class I implements self::C, self::D, self::E {}
+''');
+
+    expect(hierarchy.getLegacyLeastUpperBound(a.rawType, b.rawType),
+        objectClass.rawType);
+    expect(hierarchy.getLegacyLeastUpperBound(a.rawType, objectClass.rawType),
+        objectClass.rawType);
+    expect(hierarchy.getLegacyLeastUpperBound(objectClass.rawType, b.rawType),
+        objectClass.rawType);
+    expect(hierarchy.getLegacyLeastUpperBound(c.rawType, d.rawType), a.rawType);
+    expect(hierarchy.getLegacyLeastUpperBound(c.rawType, a.rawType), a.rawType);
+    expect(hierarchy.getLegacyLeastUpperBound(a.rawType, d.rawType), a.rawType);
+    expect(hierarchy.getLegacyLeastUpperBound(f.rawType, g.rawType), a.rawType);
+    expect(hierarchy.getLegacyLeastUpperBound(h.rawType, i.rawType), a.rawType);
+  }
+}
diff --git a/pkg/kernel/test/class_hierarchy_test.dart b/pkg/kernel/test/class_hierarchy_test.dart
index c98017a..c195192 100644
--- a/pkg/kernel/test/class_hierarchy_test.dart
+++ b/pkg/kernel/test/class_hierarchy_test.dart
@@ -9,7 +9,6 @@
 import "package:kernel/core_types.dart";
 import "package:kernel/testing/mock_sdk_component.dart";
 import "package:kernel/text/ast_to_text.dart";
-import "package:kernel/type_algebra.dart";
 
 main() {
   new ClosedWorldClassHierarchyTest().test_applyTreeChanges();
@@ -53,13 +52,6 @@
   new ClosedWorldClassHierarchyTest()
       .test_getClassAsInstanceOf_notGeneric_with();
 
-  new ClosedWorldClassHierarchyTest().test_getLegacyLeastUpperBound_expansive();
-
-  new ClosedWorldClassHierarchyTest().test_getLegacyLeastUpperBound_generic();
-
-  new ClosedWorldClassHierarchyTest()
-      .test_getLegacyLeastUpperBound_nonGeneric();
-
   new ClosedWorldClassHierarchyTest().test_getDeclaredMembers();
 
   new ClosedWorldClassHierarchyTest().test_getDispatchTarget();
@@ -330,15 +322,6 @@
         implementedTypes: implementedTypes));
   }
 
-  /// Add a new class with the given [name] that extends `Object` and
-  /// [implements_] the given classes.
-  Class addImplementsClass(String name, List<Class> implements_) {
-    return addClass(new Class(
-        name: name,
-        supertype: objectSuper,
-        implementedTypes: implements_.map((c) => c.asThisSupertype).toList()));
-  }
-
   Procedure newEmptyGetter(String name,
       {DartType returnType: const DynamicType(), bool isAbstract: false}) {
     var body =
@@ -704,175 +687,6 @@
     expect(hierarchy.getClassAsInstanceOf(z, a), null);
   }
 
-  /// Copy of the tests/language/least_upper_bound_expansive_test.dart test.
-  void test_getLegacyLeastUpperBound_expansive() {
-    var int = coreTypes.intClass.rawType;
-    var string = coreTypes.stringClass.rawType;
-
-    // class N<T> {}
-    var NT = new TypeParameter('T', objectClass.rawType);
-    var N = addClass(
-        new Class(name: 'N', typeParameters: [NT], supertype: objectSuper));
-
-    // class C1<T> extends N<N<C1<T>>> {}
-    Class C1;
-    {
-      var T = new TypeParameter('T', objectClass.rawType);
-      C1 = addClass(
-          new Class(name: 'C1', typeParameters: [T], supertype: objectSuper));
-      DartType C1_T = Substitution.fromMap({T: new TypeParameterType(T)})
-          .substituteType(C1.thisType);
-      DartType N_C1_T =
-          Substitution.fromMap({NT: C1_T}).substituteType(N.thisType);
-      Supertype N_N_C1_T = Substitution.fromMap({NT: N_C1_T})
-          .substituteSupertype(N.asThisSupertype);
-      C1.supertype = N_N_C1_T;
-    }
-
-    // class C2<T> extends N<N<C2<N<C2<T>>>>> {}
-    Class C2;
-    {
-      var T = new TypeParameter('T', objectClass.rawType);
-      C2 = addClass(
-          new Class(name: 'C2', typeParameters: [T], supertype: objectSuper));
-      DartType C2_T = Substitution.fromMap({T: new TypeParameterType(T)})
-          .substituteType(C2.thisType);
-      DartType N_C2_T =
-          Substitution.fromMap({NT: C2_T}).substituteType(N.thisType);
-      DartType C2_N_C2_T =
-          Substitution.fromMap({T: N_C2_T}).substituteType(C2.thisType);
-      DartType N_C2_N_C2_T =
-          Substitution.fromMap({NT: C2_N_C2_T}).substituteType(N.thisType);
-      Supertype N_N_C2_N_C2_T = Substitution.fromMap({NT: N_C2_N_C2_T})
-          .substituteSupertype(N.asThisSupertype);
-      C2.supertype = N_N_C2_N_C2_T;
-    }
-
-    _assertTestLibraryText('''
-class N<T> {}
-class C1<T> extends self::N<self::N<self::C1<self::C1::T>>> {}
-class C2<T> extends self::N<self::N<self::C2<self::N<self::C2<self::C2::T>>>>> {}
-''');
-
-    // The least upper bound of C1<int> and N<C1<String>> is Object since the
-    // supertypes are
-    //     {C1<int>, N<N<C1<int>>>, Object} for C1<int> and
-    //     {N<C1<String>>, Object} for N<C1<String>> and
-    // Object is the most specific type in the intersection of the supertypes.
-    expect(
-        hierarchy.getLegacyLeastUpperBound(
-            new InterfaceType(C1, [int]),
-            new InterfaceType(N, [
-              new InterfaceType(C1, [string])
-            ])),
-        objectClass.thisType);
-
-    // The least upper bound of C2<int> and N<C2<String>> is Object since the
-    // supertypes are
-    //     {C2<int>, N<N<C2<N<C2<int>>>>>, Object} for C2<int> and
-    //     {N<C2<String>>, Object} for N<C2<String>> and
-    // Object is the most specific type in the intersection of the supertypes.
-    expect(
-        hierarchy.getLegacyLeastUpperBound(
-            new InterfaceType(C2, [int]),
-            new InterfaceType(N, [
-              new InterfaceType(C2, [string])
-            ])),
-        objectClass.thisType);
-  }
-
-  void test_getLegacyLeastUpperBound_generic() {
-    var int = coreTypes.intClass.rawType;
-    var double = coreTypes.doubleClass.rawType;
-    var bool = coreTypes.boolClass.rawType;
-
-    var a = addGenericClass('A', []);
-    var b =
-        addGenericClass('B', ['T'], implements_: (_) => [a.asThisSupertype]);
-    var c =
-        addGenericClass('C', ['U'], implements_: (_) => [a.asThisSupertype]);
-    var d = addGenericClass('D', ['T', 'U'], implements_: (typeParameterTypes) {
-      var t = typeParameterTypes[0];
-      var u = typeParameterTypes[1];
-      return [
-        new Supertype(b, [t]),
-        new Supertype(c, [u])
-      ];
-    });
-    var e = addGenericClass('E', [],
-        implements_: (_) => [
-              new Supertype(d, [int, double])
-            ]);
-    var f = addGenericClass('F', [],
-        implements_: (_) => [
-              new Supertype(d, [int, bool])
-            ]);
-
-    _assertTestLibraryText('''
-class A {}
-class B<T> implements self::A {}
-class C<U> implements self::A {}
-class D<T, U> implements self::B<self::D::T>, self::C<self::D::U> {}
-class E implements self::D<core::int, core::double> {}
-class F implements self::D<core::int, core::bool> {}
-''');
-
-    expect(
-        hierarchy.getLegacyLeastUpperBound(new InterfaceType(d, [int, double]),
-            new InterfaceType(d, [int, double])),
-        new InterfaceType(d, [int, double]));
-    expect(
-        hierarchy.getLegacyLeastUpperBound(new InterfaceType(d, [int, double]),
-            new InterfaceType(d, [int, bool])),
-        new InterfaceType(b, [int]));
-    expect(
-        hierarchy.getLegacyLeastUpperBound(new InterfaceType(d, [int, double]),
-            new InterfaceType(d, [bool, double])),
-        new InterfaceType(c, [double]));
-    expect(
-        hierarchy.getLegacyLeastUpperBound(new InterfaceType(d, [int, double]),
-            new InterfaceType(d, [bool, int])),
-        a.rawType);
-    expect(hierarchy.getLegacyLeastUpperBound(e.rawType, f.rawType),
-        new InterfaceType(b, [int]));
-  }
-
-  void test_getLegacyLeastUpperBound_nonGeneric() {
-    var a = addImplementsClass('A', []);
-    var b = addImplementsClass('B', []);
-    var c = addImplementsClass('C', [a]);
-    var d = addImplementsClass('D', [a]);
-    var e = addImplementsClass('E', [a]);
-    var f = addImplementsClass('F', [c, d]);
-    var g = addImplementsClass('G', [c, d]);
-    var h = addImplementsClass('H', [c, d, e]);
-    var i = addImplementsClass('I', [c, d, e]);
-
-    _assertTestLibraryText('''
-class A {}
-class B {}
-class C implements self::A {}
-class D implements self::A {}
-class E implements self::A {}
-class F implements self::C, self::D {}
-class G implements self::C, self::D {}
-class H implements self::C, self::D, self::E {}
-class I implements self::C, self::D, self::E {}
-''');
-
-    expect(hierarchy.getLegacyLeastUpperBound(a.rawType, b.rawType),
-        objectClass.rawType);
-    expect(hierarchy.getLegacyLeastUpperBound(a.rawType, objectClass.rawType),
-        objectClass.rawType);
-    expect(hierarchy.getLegacyLeastUpperBound(objectClass.rawType, b.rawType),
-        objectClass.rawType);
-    expect(hierarchy.getLegacyLeastUpperBound(c.rawType, d.rawType), a.rawType);
-    expect(hierarchy.getLegacyLeastUpperBound(c.rawType, a.rawType), a.rawType);
-    expect(hierarchy.getLegacyLeastUpperBound(a.rawType, d.rawType), a.rawType);
-    expect(hierarchy.getLegacyLeastUpperBound(f.rawType, g.rawType), a.rawType);
-    expect(hierarchy.getLegacyLeastUpperBound(h.rawType, i.rawType), a.rawType);
-  }
-
   void test_getDeclaredMembers() {
     var method = newEmptyMethod('method');
     var getter = newEmptyGetter('getter');