1 /* 2 * Copyright (C) 2020 The Dagger Authors. 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17 package dagger.hilt.android; 18 19 import static com.google.common.truth.Truth.assertThat; 20 21 import android.os.Build; 22 import androidx.activity.ComponentActivity; 23 import androidx.test.ext.junit.runners.AndroidJUnit4; 24 import dagger.hilt.android.other.pkg.AndroidEntryPointBaseClassOtherPkg; 25 import org.junit.Test; 26 import org.junit.runner.RunWith; 27 import org.robolectric.annotation.Config; 28 29 /** 30 * Regression test for https://github.com/google/dagger/issues/1910 31 * 32 * <p>There are 8 different tests to cover 3 levels of inheritance where each level uses either the 33 * long-form (L) or short-form (S) of @AndroidEntryPoint: 34 * 35 * <ol> 36 * <li> L -> L -> L 37 * <li> L -> L -> S 38 * <li> L -> S -> L 39 * <li> L -> S -> S 40 * <li> S -> L -> L 41 * <li> S -> L -> S 42 * <li> S -> S -> L 43 * <li> S -> S -> S 44 * </ol> 45 * 46 * Note: We don't actually test injection in this class because Bazel doesn't do bytecode injection. 47 * We're only testing that the classes build, and verifying their inheritance matches what we 48 * expect. 49 */ 50 @RunWith(AndroidJUnit4.class) 51 // Robolectric requires Java9 to run API 29 and above, so use API 28 instead 52 @Config(sdk = Build.VERSION_CODES.P) 53 public final class AndroidEntryPointBaseClassTest { 54 55 @AndroidEntryPoint 56 public static final class SSActivity extends AndroidEntryPointBaseClassOtherPkg.SBaseActivity {} 57 58 @AndroidEntryPoint 59 public static final class SLActivity extends AndroidEntryPointBaseClassOtherPkg.LBaseActivity {} 60 61 @AndroidEntryPoint(AndroidEntryPointBaseClassOtherPkg.SBaseActivity.class) 62 public static final class LSActivity extends Hilt_AndroidEntryPointBaseClassTest_LSActivity {} 63 64 @AndroidEntryPoint(AndroidEntryPointBaseClassOtherPkg.LBaseActivity.class) 65 public static final class LLActivity extends Hilt_AndroidEntryPointBaseClassTest_LLActivity {} 66 67 @AndroidEntryPoint(LL.class) 68 public static final class LLL extends Hilt_AndroidEntryPointBaseClassTest_LLL {} 69 70 @AndroidEntryPoint(LS.class) 71 public static final class LLS extends Hilt_AndroidEntryPointBaseClassTest_LLS {} 72 73 @AndroidEntryPoint(SL.class) 74 public static final class LSL extends Hilt_AndroidEntryPointBaseClassTest_LSL {} 75 76 @AndroidEntryPoint(SS.class) 77 public static final class LSS extends Hilt_AndroidEntryPointBaseClassTest_LSS {} 78 79 @AndroidEntryPoint 80 public static final class SLL extends LL {} 81 82 @AndroidEntryPoint 83 public static final class SLS extends LS {} 84 85 @AndroidEntryPoint 86 public static final class SSL extends SL {} 87 88 @AndroidEntryPoint 89 public static final class SSS extends SS {} 90 91 @AndroidEntryPoint(L.class) 92 public static class LL extends Hilt_AndroidEntryPointBaseClassTest_LL {} 93 94 @AndroidEntryPoint(S.class) 95 public static class LS extends Hilt_AndroidEntryPointBaseClassTest_LS {} 96 97 @AndroidEntryPoint 98 public static class SL extends L {} 99 100 @AndroidEntryPoint 101 public static class SS extends S {} 102 103 @AndroidEntryPoint(ComponentActivity.class) 104 public static class L extends Hilt_AndroidEntryPointBaseClassTest_L {} 105 106 @AndroidEntryPoint 107 public static class S extends ComponentActivity {} 108 109 @Test checkGeneratedClassHierarchy_shortForm()110 public void checkGeneratedClassHierarchy_shortForm() throws Exception { 111 // When using the short form notation, the generated top level class is not actually assignable 112 // to the generated base classes at compile time 113 assertIsNotAssignableTo( 114 Hilt_AndroidEntryPointBaseClassTest_SSS.class, 115 Hilt_AndroidEntryPointBaseClassTest_S.class); 116 assertIsNotAssignableTo( 117 Hilt_AndroidEntryPointBaseClassTest_SS.class, 118 Hilt_AndroidEntryPointBaseClassTest_S.class); 119 } 120 121 @Test checkGeneratedClassHierarchy_longForm()122 public void checkGeneratedClassHierarchy_longForm() throws Exception { 123 // When using the long form notation, they are assignable at compile time 124 assertIsAssignableTo( 125 Hilt_AndroidEntryPointBaseClassTest_LLL.class, 126 Hilt_AndroidEntryPointBaseClassTest_LL.class); 127 assertIsAssignableTo( 128 Hilt_AndroidEntryPointBaseClassTest_LL.class, 129 Hilt_AndroidEntryPointBaseClassTest_L.class); 130 } 131 132 @Test checkGeneratedClassHierarchy_shortFormRoot()133 public void checkGeneratedClassHierarchy_shortFormRoot() throws Exception { 134 // If the root is short-form, then the child class cannot be assigned to it. 135 assertIsNotAssignableTo( 136 Hilt_AndroidEntryPointBaseClassTest_LLS.class, 137 Hilt_AndroidEntryPointBaseClassTest_S.class); 138 assertIsNotAssignableTo( 139 Hilt_AndroidEntryPointBaseClassTest_LS.class, 140 Hilt_AndroidEntryPointBaseClassTest_S.class); 141 } 142 143 @Test checkGeneratedClassHierarchy_longFormRoot()144 public void checkGeneratedClassHierarchy_longFormRoot() throws Exception { 145 // If the root is long-form, then the child class can be assigned to it. 146 assertIsAssignableTo( 147 Hilt_AndroidEntryPointBaseClassTest_SSL.class, 148 Hilt_AndroidEntryPointBaseClassTest_L.class); 149 assertIsAssignableTo( 150 Hilt_AndroidEntryPointBaseClassTest_SL.class, 151 Hilt_AndroidEntryPointBaseClassTest_L.class); 152 } 153 154 /** Asserts that the {@code class1} is not assignable to the {@code class2}. */ assertIsNotAssignableTo(Class<?> class1, Class<?> class2)155 private static void assertIsNotAssignableTo(Class<?> class1, Class<?> class2) { 156 assertThat(class2.isAssignableFrom(class1)).isFalse(); 157 } 158 159 /** Asserts that the {@code class1} is assignable to the {@code class2}. */ assertIsAssignableTo(Class<?> class1, Class<?> class2)160 private static void assertIsAssignableTo(Class<?> class1, Class<?> class2) { 161 assertThat(class1).isAssignableTo(class2); 162 } 163 } 164