• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2024 The Android Open Source Project
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 package com.android.adservices.shared.testing;
17 
18 import android.annotation.CallSuper;
19 import android.content.Context;
20 
21 import androidx.test.platform.app.InstrumentationRegistry;
22 
23 import org.junit.Rule;
24 import org.junit.Test;
25 
26 /**
27  * Superclass for all device-side tests, it contains just the bare minimum features used by all
28  * tests.
29  */
30 public abstract class DeviceSideTestCase extends SidelessTestCase {
31 
32     private static final String TAG = DeviceSideTestCase.class.getSimpleName();
33 
34     private static final String REASON_SESSION_MANAGED_BY_RULE =
35             "mockito session is automatically managed by a @Rule";
36     private static final String REASON_NO_TARGET_CONTEXT =
37             "tests should use mContext instead - if it needs the target context, please add to"
38                     + " DeviceSideTestCase instead";
39     protected static final String REASON_USE_FAKE_DEBUG_FLAGS_INSTEAD =
40             "should use mFakeDebugFlags and debugFlags rule instead";
41 
42     // TODO(b/335935200): This (and RavenwoodConfig) should be removed once Ravenwood starts
43     // using the package name from the build file.
44     private static final String RAVENWOOD_PACKAGE_NAME = "com.android.adservices.shared.tests";
45 
46     /** {@code logcat} tag. */
47     protected final String mTag = getClass().getSimpleName();
48 
49     // NOTE: references below CANNOT be set when declared as the call to InstrumentationRegistry
50     // would fail when running on host / under Ravenwood
51 
52     /**
53      * @deprecated use {@link #mContext}
54      */
55     @Deprecated
56     protected static final Context sContext =
57             InstrumentationRegistry.getInstrumentation().getContext();
58 
59     /**
60      * Package name of the app being instrumented.
61      *
62      * @deprecated use {@link #mPackageName} instead.
63      */
64     @Deprecated protected static final String sPackageName = sContext.getPackageName();
65 
66     /**
67      * Reference to the context of this test's instrumentation package (as defined by {@link
68      * android.app.Instrumentation#getContext()})
69      */
70     protected final Context mContext = sContext;
71 
72     /**
73      * Package name of this test's instrumentation package (as defined by {@link
74      * android.app.Instrumentation#getContext()})
75      */
76     protected final String mPackageName = sPackageName;
77 
78     // TODO(b/342639109): make sure it's the right order
79     @Rule(order = 0)
80     public final SdkLevelSupportRule sdkLevel = SdkLevelSupportRule.forAnyLevel();
81 
82     // TODO(b/342639109): set order
83     @Rule
84     public final ProcessLifeguardRule processLifeguard =
85             new ProcessLifeguardRule(ProcessLifeguardRule.Mode.IGNORE);
86 
87     // TODO(b/361555631): merge 2 classes below into testDeviceSideTestCaseFixtures() and annotate
88     // it with @MetaTest
89     @Test
90     @Override
testValidTestCaseFixtures()91     public final void testValidTestCaseFixtures() throws Exception {
92         assertValidTestCaseFixtures();
93     }
94 
95     @CallSuper
96     @Override
assertValidTestCaseFixtures()97     protected void assertValidTestCaseFixtures() throws Exception {
98         super.assertValidTestCaseFixtures();
99 
100         assertTestClassHasNoFieldsFromSuperclass(
101                 DeviceSideTestCase.class,
102                 "mContext",
103                 "mPackageName",
104                 "mTag",
105                 "ravenwood",
106                 "sdkLevel",
107                 "processLifeGuard",
108                 "sContext",
109                 "sPackageName",
110                 "sRavenWood",
111                 "RAVENWOOD_PACKAGE_NAME");
112         assertTestClassHasNoSuchField(
113                 "CONTEXT",
114                 "should use existing mContext (or sContext when that's not possible) instead");
115         assertTestClassHasNoSuchField(
116                 "APPLICATION_CONTEXT",
117                 "should use existing mContext (or sContext when that's not possible) instead");
118         assertTestClassHasNoSuchField("context", "should use existing mContext instead");
119         assertTestClassHasNoSuchField("mTargetContext", REASON_NO_TARGET_CONTEXT);
120         assertTestClassHasNoSuchField("mTargetPackageName", REASON_NO_TARGET_CONTEXT);
121         assertTestClassHasNoSuchField("sTargetContext", REASON_NO_TARGET_CONTEXT);
122         assertTestClassHasNoSuchField("sTargetPackageName", REASON_NO_TARGET_CONTEXT);
123     }
124 
125     // NOTE: it's static so it can be used by other mockito-related superclasses, as often test
126     // cases are converted to use AdServicesMockitoTestCase and still defined the ExtendedMockito
127     // session - they should migrate to AdServicesExtendedMockitoTestCase instead.
checkProhibitedMockitoFields( Class<T> superclass, T testInstance)128     protected static <T extends DeviceSideTestCase> void checkProhibitedMockitoFields(
129             Class<T> superclass, T testInstance) throws Exception {
130         // NOTE: same fields below are not defined (yet?) SharedExtendedMockitoTestCase or
131         // SharedMockitoTestCase, but they might; and even if they don't, this method is also used
132         // by the classes on AdServices (AdServicesMockitoTestCase /
133         // AdServicesExtendedMockitoTestCase)
134         testInstance.assertTestClassHasNoFieldsFromSuperclass(
135                 superclass,
136                 "mMockContext",
137                 "mSpyContext",
138                 "extendedMockito",
139                 "errorLogUtilUsageRule",
140                 "mocker",
141                 "sInlineCleaner",
142                 "sSpyContext"
143                 // NOTE: mMockFlags is now checked by AdServicesUnitTestCase itself
144                 );
145         testInstance.assertTestClassHasNoSuchField(
146                 "mContextMock", "should use existing mMockContext instead");
147         testInstance.assertTestClassHasNoSuchField(
148                 "mContextSpy", "should use existing mSpyContext instead");
149         testInstance.assertTestClassHasNoSuchField("mockito", "already taken care by @Rule");
150         testInstance.assertTestClassHasNoSuchField(
151                 "mFlagsMock", "should use existing mMockFlags instead");
152         testInstance.assertTestClassHasNoSuchField(
153                 "mMockDebugFlags", REASON_USE_FAKE_DEBUG_FLAGS_INSTEAD);
154         testInstance.assertTestClassHasNoSuchField(
155                 "mDebugFlagsMock", REASON_USE_FAKE_DEBUG_FLAGS_INSTEAD);
156 
157         testInstance.assertTestClassHasNoSuchField(
158                 "sMockFlags", "should use existing mMockFlags instead");
159         testInstance.assertTestClassHasNoSuchField(
160                 "mFlags",
161                 superclass.getSimpleName()
162                         + " already define a mMockFlags, and often subclasses define a @Mock"
163                         + " mFlags; to avoid confusion, either use the existing mMockFlags, or"
164                         + " create a non-mock instance like mFakeFlags");
165 
166         // Listed below are existing names for the extended mockito session on test classes that
167         // don't use the rule / superclass:
168         // TODO(b/368153625): should check for type instead
169         testInstance.assertTestClassHasNoSuchField(
170                 "mStaticMockSession", REASON_SESSION_MANAGED_BY_RULE);
171         testInstance.assertTestClassHasNoSuchField(
172                 "mMockitoSession", REASON_SESSION_MANAGED_BY_RULE);
173         testInstance.assertTestClassHasNoSuchField(
174                 "mockitoSession", REASON_SESSION_MANAGED_BY_RULE);
175         testInstance.assertTestClassHasNoSuchField("session", REASON_SESSION_MANAGED_BY_RULE);
176         testInstance.assertTestClassHasNoSuchField(
177                 "sStaticMockitoSession", REASON_SESSION_MANAGED_BY_RULE);
178         testInstance.assertTestClassHasNoSuchField(
179                 "staticMockitoSession", REASON_SESSION_MANAGED_BY_RULE);
180         testInstance.assertTestClassHasNoSuchField(
181                 "staticMockSession", REASON_SESSION_MANAGED_BY_RULE);
182     }
183 }
184