• 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.common;
17 
18 import static com.android.adservices.mockito.ExtendedMockitoInlineCleanerRule.Mode.CLEAR_AFTER_TEST_CLASS;
19 import static com.android.adservices.service.DebugFlagsConstants.KEY_CONSENT_NOTIFICATION_DEBUG_MODE;
20 import static com.android.dx.mockito.inline.extended.ExtendedMockito.doNothing;
21 
22 import static org.mockito.ArgumentMatchers.any;
23 import static org.mockito.ArgumentMatchers.anyInt;
24 
25 import android.annotation.CallSuper;
26 import android.annotation.Nullable;
27 import android.content.Context;
28 import android.content.pm.PackageManager;
29 import android.content.pm.ResolveInfo;
30 
31 import com.android.adservices.common.AdServicesMockerLessExtendedMockitoTestCase.InternalMocker;
32 import com.android.adservices.common.logging.AdServicesLoggingUsageRule;
33 import com.android.adservices.common.logging.annotations.ExpectErrorLogUtilCall;
34 import com.android.adservices.common.logging.annotations.ExpectErrorLogUtilWithExceptionCall;
35 import com.android.adservices.common.logging.annotations.SetErrorLogUtilDefaultParams;
36 import com.android.adservices.errorlogging.ErrorLogUtil;
37 import com.android.adservices.mockito.AdServicesExtendedMockitoMocker;
38 import com.android.adservices.mockito.AdServicesExtendedMockitoRule;
39 import com.android.adservices.mockito.AdServicesFlagsMocker;
40 import com.android.adservices.mockito.AdServicesMockitoFlagsMocker;
41 import com.android.adservices.mockito.AdServicesMockitoMocker;
42 import com.android.adservices.mockito.AdServicesPragmaticMocker;
43 import com.android.adservices.mockito.AdServicesStaticMocker;
44 import com.android.adservices.mockito.AndroidExtendedMockitoMocker;
45 import com.android.adservices.mockito.AndroidMocker;
46 import com.android.adservices.mockito.AndroidMockitoMocker;
47 import com.android.adservices.mockito.AndroidStaticMocker;
48 import com.android.adservices.mockito.ExtendedMockitoInlineCleanerRule;
49 import com.android.adservices.mockito.ExtendedMockitoInlineCleanerRule.ClearInlineMocksMode;
50 import com.android.adservices.mockito.LogInterceptor;
51 import com.android.adservices.mockito.SharedMocker;
52 import com.android.adservices.mockito.SharedMockitoMocker;
53 import com.android.adservices.mockito.StaticClassChecker;
54 import com.android.adservices.service.DebugFlags;
55 import com.android.adservices.service.Flags;
56 import com.android.adservices.service.stats.AdServicesLogger;
57 import com.android.adservices.service.stats.AdServicesLoggerImpl;
58 import com.android.adservices.service.stats.ApiCallStats;
59 import com.android.adservices.shared.spe.logging.JobServiceLogger;
60 import com.android.adservices.shared.testing.JobServiceLoggingCallback;
61 import com.android.adservices.shared.testing.concurrency.ResultSyncCallback;
62 import com.android.adservices.shared.util.Clock;
63 import com.android.adservices.spe.AdServicesJobScheduler;
64 import com.android.adservices.spe.AdServicesJobServiceFactory;
65 import com.android.modules.utils.testing.ExtendedMockitoRule.MockStatic;
66 
67 import org.junit.ClassRule;
68 import org.junit.Rule;
69 import org.mockito.Mock;
70 import org.mockito.Spy;
71 import org.mockito.quality.Strictness;
72 
73 /**
74  * Base class for {@link AdServicesExtendedMockitoTestCase}, but leaving a hook ({@link
75  * #newMocker(AdServicesExtendedMockitoRule, Flags)} for subclasses to provide the {@code mocker}
76  * object.
77  *
78  * @param <M> mocker type
79  */
80 @ClearInlineMocksMode(CLEAR_AFTER_TEST_CLASS)
81 @MockStatic(ErrorLogUtil.class)
82 public abstract class AdServicesMockerLessExtendedMockitoTestCase<M extends InternalMocker>
83         extends AdServicesUnitTestCase {
84 
85     @Mock protected Context mMockContext;
86 
87     /** Spy the {@link AdServicesUnitTestCase#mContext} */
88     @Spy protected final Context mSpyContext = mContext;
89 
90     // NOTE: must use CLEAR_AFTER_TEST_CLASS by default (defined as a class annotation, so it's used
91     // by both ExtendedMockitoInlineCleanerRule and AdServicesExtendedMockitoRule), as some tests
92     // performing complicated static class initialization on @Before methods, which often cause test
93     // failure when called after the mocks are cleared (for example, DialogFragmentTest would fail
94     // after the first method was executed)
95     @ClassRule
96     public static final ExtendedMockitoInlineCleanerRule sInlineCleaner =
97             new ExtendedMockitoInlineCleanerRule();
98 
99     @Rule(order = 10)
100     public final AdServicesExtendedMockitoRule extendedMockito = getAdServicesExtendedMockitoRule();
101 
102     /**
103      * Scans for usage of {@code ErrorLogUtil.e(int, int)} and {@code ErrorLogUtil.e(Throwable, int
104      * int)} invocations. Fails the test if calls haven't been verified using {@link
105      * ExpectErrorLogUtilCall} and/or {@link ExpectErrorLogUtilWithExceptionCall}.
106      *
107      * <p>Also see {@link SetErrorLogUtilDefaultParams} to set common default logging params.
108      */
109     // TODO(b/342639109): Fix the order of the rules.
110     @Rule(order = 11)
111     public final AdServicesLoggingUsageRule errorLogUtilUsageRule =
112             AdServicesLoggingUsageRule.errorLogUtilUsageRule();
113 
114     /** Provides common expectations. */
115     public final M mocker = newMocker(extendedMockito, mMockFlags);
116 
117     /**
118      * Gets the {@link AdServicesExtendedMockitoRule} that will be set as the {@code
119      * extendedMockito} rule.
120      *
121      * <p>By default returns a rule created using {@link
122      * #newDefaultAdServicesExtendedMockitoRuleBuilder()}, which is enough for most tests. But
123      * subclasses can override it to handle special cases that cannot be configured through
124      * annotations, like :
125      *
126      * <ul>
127      *   <li>Changing the strictness mode.
128      *   <li>Setting the {@link com.android.modules.utils.testing.StaticMockFixture}s.
129      * </ul>
130      */
getAdServicesExtendedMockitoRule()131     protected AdServicesExtendedMockitoRule getAdServicesExtendedMockitoRule() {
132         return newDefaultAdServicesExtendedMockitoRuleBuilder().build();
133     }
134 
135     /** Returns the object that will be referenced by {@code mocker}. */
newMocker(AdServicesExtendedMockitoRule rule, Flags mockFlags)136     protected abstract M newMocker(AdServicesExtendedMockitoRule rule, Flags mockFlags);
137 
138     /**
139      * Creates a new {@link AdServicesExtendedMockitoRule.Builder} with the default properties.
140      *
141      * @return builder that initialize mocks for the class, using {@link Strictness.LENIENT lenient}
142      *     mode.
143      */
144     protected final AdServicesExtendedMockitoRule.Builder
newDefaultAdServicesExtendedMockitoRuleBuilder()145             newDefaultAdServicesExtendedMockitoRuleBuilder() {
146         return new AdServicesExtendedMockitoRule.Builder(this).setStrictness(Strictness.LENIENT);
147     }
148 
149     // TODO(b/361555631): rename to testAdServicesExtendedMockitoTestCaseFixtures() and annotate
150     // it with @MetaTest
151     @CallSuper
152     @Override
assertValidTestCaseFixtures()153     protected void assertValidTestCaseFixtures() throws Exception {
154         super.assertValidTestCaseFixtures();
155 
156         checkProhibitedMockitoFields(AdServicesMockerLessExtendedMockitoTestCase.class, this);
157     }
158 
159     /**
160      * @deprecated TODO(b/338067482): temporary method, ideally it should be inlined or replaced
161      *     by @EnableDebugFlag / @DisableDebugFlag; if not, then it should be unit tested (on
162      *     AdServicesExtendedMockitoTestCaseTest)
163      */
164     @Deprecated
mockGetConsentNotificationDebugMode(boolean mode)165     protected void mockGetConsentNotificationDebugMode(boolean mode) {
166         mLog.v(
167                 "mockGetConsentNotificationDebugMode(%b): delegating to debugFlags rule (%s)",
168                 mode, debugFlags);
169         debugFlags.setDebugFlag(KEY_CONSENT_NOTIFICATION_DEBUG_MODE, mode);
170     }
171 
172     private static final String REASON_SESSION_MANAGED_BY_RULE =
173             "mockito session is automatically managed by a @Rule";
174 
175     public abstract static class InternalMocker
176             implements AndroidMocker,
177                     AndroidStaticMocker,
178                     AdServicesPragmaticMocker,
179                     AdServicesFlagsMocker,
180                     AdServicesStaticMocker,
181                     SharedMocker {
182 
183         private final AndroidMocker mAndroidMocker = new AndroidMockitoMocker();
184         private final SharedMocker mSharedMocker = new SharedMockitoMocker();
185         private final AdServicesPragmaticMocker mAdServicesMocker = new AdServicesMockitoMocker();
186         @Nullable private final AdServicesFlagsMocker mAdServicesFlagsMocker;
187         @Nullable private final AndroidStaticMocker mAndroidStaticMocker;
188         @Nullable private final AdServicesStaticMocker mAdServicesStaticMocker;
189 
InternalMocker(StaticClassChecker checker, Flags flags)190         protected InternalMocker(StaticClassChecker checker, Flags flags) {
191             if (checker != null) {
192                 mAndroidStaticMocker = new AndroidExtendedMockitoMocker(checker);
193                 mAdServicesStaticMocker = new AdServicesExtendedMockitoMocker(checker);
194             } else {
195                 mAndroidStaticMocker = null;
196                 mAdServicesStaticMocker = null;
197             }
198             mAdServicesFlagsMocker = flags != null ? new AdServicesMockitoFlagsMocker(flags) : null;
199         }
200 
201         // AndroidMocker methods
202 
203         @Override
mockQueryIntentService(PackageManager mockPm, ResolveInfo... resolveInfos)204         public void mockQueryIntentService(PackageManager mockPm, ResolveInfo... resolveInfos) {
205             mAndroidMocker.mockQueryIntentService(mockPm, resolveInfos);
206         }
207 
208         @Override
mockGetApplicationContext(Context mockContext, Context appContext)209         public void mockGetApplicationContext(Context mockContext, Context appContext) {
210             mAndroidMocker.mockGetApplicationContext(mockContext, appContext);
211         }
212 
213         // AndroidStaticMocker methods
214 
215         @Override
mockGetCallingUidOrThrow(int uid)216         public void mockGetCallingUidOrThrow(int uid) {
217             mAndroidStaticMocker.mockGetCallingUidOrThrow(uid);
218         }
219 
220         @Override
mockGetCallingUidOrThrow()221         public void mockGetCallingUidOrThrow() {
222             mAndroidStaticMocker.mockGetCallingUidOrThrow();
223         }
224 
225         @Override
mockIsAtLeastR(boolean isIt)226         public void mockIsAtLeastR(boolean isIt) {
227             mAndroidStaticMocker.mockIsAtLeastR(isIt);
228         }
229 
230         @Override
mockIsAtLeastS(boolean isIt)231         public void mockIsAtLeastS(boolean isIt) {
232             mAndroidStaticMocker.mockIsAtLeastS(isIt);
233         }
234 
235         @Override
mockIsAtLeastT(boolean isIt)236         public void mockIsAtLeastT(boolean isIt) {
237             mAndroidStaticMocker.mockIsAtLeastT(isIt);
238         }
239 
240         @Override
mockIsAtLeastV(boolean isIt)241         public void mockIsAtLeastV(boolean isIt) {
242             mAndroidStaticMocker.mockIsAtLeastV(isIt);
243         }
244 
245         @Override
mockSdkLevelR()246         public void mockSdkLevelR() {
247             mAndroidStaticMocker.mockSdkLevelR();
248         }
249 
250         @Override
mockSdkLevelS()251         public void mockSdkLevelS() {
252             mAndroidStaticMocker.mockSdkLevelS();
253         }
254 
255         @Override
mockGetCurrentUser(int user)256         public void mockGetCurrentUser(int user) {
257             mAndroidStaticMocker.mockGetCurrentUser(user);
258         }
259 
260         @Override
interceptLogD(String tag)261         public LogInterceptor interceptLogD(String tag) {
262             return mAndroidStaticMocker.interceptLogD(tag);
263         }
264 
265         @Override
interceptLogV(String tag)266         public LogInterceptor interceptLogV(String tag) {
267             return mAndroidStaticMocker.interceptLogV(tag);
268         }
269 
270         @Override
interceptLogE(String tag)271         public LogInterceptor interceptLogE(String tag) {
272             return mAndroidStaticMocker.interceptLogE(tag);
273         }
274 
275         // AdServicesPragmaticMocker methods
276 
277         @Override
mockLogApiCallStats( AdServicesLogger adServicesLogger)278         public ResultSyncCallback<ApiCallStats> mockLogApiCallStats(
279                 AdServicesLogger adServicesLogger) {
280             return mAdServicesMocker.mockLogApiCallStats(adServicesLogger);
281         }
282 
283         @Override
mockLogApiCallStats( AdServicesLogger adServicesLogger, long timeoutMs)284         public ResultSyncCallback<ApiCallStats> mockLogApiCallStats(
285                 AdServicesLogger adServicesLogger, long timeoutMs) {
286             return mAdServicesMocker.mockLogApiCallStats(adServicesLogger, timeoutMs);
287         }
288 
289         // AdServicesFlagsMocker methods
290         @Override
mockGetBackgroundJobsLoggingKillSwitch(boolean value)291         public void mockGetBackgroundJobsLoggingKillSwitch(boolean value) {
292             mAdServicesFlagsMocker.mockGetBackgroundJobsLoggingKillSwitch(value);
293         }
294 
295         @Override
mockGetCobaltLoggingEnabled(boolean value)296         public void mockGetCobaltLoggingEnabled(boolean value) {
297             mAdServicesFlagsMocker.mockGetCobaltLoggingEnabled(value);
298         }
299 
300         @Override
mockGetAppNameApiErrorCobaltLoggingEnabled(boolean value)301         public void mockGetAppNameApiErrorCobaltLoggingEnabled(boolean value) {
302             mAdServicesFlagsMocker.mockGetAppNameApiErrorCobaltLoggingEnabled(value);
303         }
304 
305         @Override
mockGetEnableApiCallResponseLoggingEnabled(boolean value)306         public void mockGetEnableApiCallResponseLoggingEnabled(boolean value) {
307             mAdServicesFlagsMocker.mockGetEnableApiCallResponseLoggingEnabled(value);
308         }
309 
310         @Override
mockGetAdservicesReleaseStageForCobalt(String stage)311         public void mockGetAdservicesReleaseStageForCobalt(String stage) {
312             mAdServicesFlagsMocker.mockGetAdservicesReleaseStageForCobalt(stage);
313         }
314 
315         @Override
mockAllCobaltLoggingFlags(boolean enabled)316         public void mockAllCobaltLoggingFlags(boolean enabled) {
317             mAdServicesFlagsMocker.mockAllCobaltLoggingFlags(enabled);
318         }
319 
320         // AdServicesStaticMocker methods
321 
322         @Override
mockGetFlags(Flags mockedFlags)323         public void mockGetFlags(Flags mockedFlags) {
324             mAdServicesStaticMocker.mockGetFlags(mockedFlags);
325         }
326 
327         @Override
mockGetDebugFlags(DebugFlags mockedDebugFlags)328         public void mockGetDebugFlags(DebugFlags mockedDebugFlags) {
329             mAdServicesStaticMocker.mockGetDebugFlags(mockedDebugFlags);
330         }
331 
332         @Override
mockSpeJobScheduler(AdServicesJobScheduler mockedAdServicesJobScheduler)333         public void mockSpeJobScheduler(AdServicesJobScheduler mockedAdServicesJobScheduler) {
334             mAdServicesStaticMocker.mockSpeJobScheduler(mockedAdServicesJobScheduler);
335         }
336 
337         @Override
mockAdServicesJobServiceFactory( AdServicesJobServiceFactory mockedAdServicesJobServiceFactory)338         public void mockAdServicesJobServiceFactory(
339                 AdServicesJobServiceFactory mockedAdServicesJobServiceFactory) {
340             mAdServicesStaticMocker.mockAdServicesJobServiceFactory(
341                     mockedAdServicesJobServiceFactory);
342         }
343 
344         @Override
mockAdServicesLoggerImpl(AdServicesLoggerImpl mockedAdServicesLoggerImpl)345         public void mockAdServicesLoggerImpl(AdServicesLoggerImpl mockedAdServicesLoggerImpl) {
346             mAdServicesStaticMocker.mockAdServicesLoggerImpl(mockedAdServicesLoggerImpl);
347         }
348 
349         // SharedMocker methods
350 
351         @Override
setApplicationContextSingleton()352         public Context setApplicationContextSingleton() {
353             return mSharedMocker.setApplicationContextSingleton();
354         }
355 
356         @Override
mockSetApplicationContextSingleton(Context context)357         public void mockSetApplicationContextSingleton(Context context) {
358             mSharedMocker.mockSetApplicationContextSingleton(context);
359         }
360 
361         @Override
syncRecordOnStopJob(JobServiceLogger logger)362         public JobServiceLoggingCallback syncRecordOnStopJob(JobServiceLogger logger) {
363             return mSharedMocker.syncRecordOnStopJob(logger);
364         }
365 
366         @Override
mockCurrentTimeMillis(Clock mockClock, long... mockedValues)367         public void mockCurrentTimeMillis(Clock mockClock, long... mockedValues) {
368             mSharedMocker.mockCurrentTimeMillis(mockClock, mockedValues);
369         }
370 
371         @Override
mockElapsedRealtime(Clock mockClock, long... mockedValues)372         public void mockElapsedRealtime(Clock mockClock, long... mockedValues) {
373             mSharedMocker.mockElapsedRealtime(mockClock, mockedValues);
374         }
375     }
376 
377     /**
378      * @deprecated Use {@link AdServicesLoggingUsageRule} to verify {@link ErrorLogUtil#e()} calls.
379      *     Tests using this rule should NOT mock {@link ErrorLogUtil#e()} calls as it's taken care
380      *     of under the hood.
381      */
382     // TODO(b/359964245): final use case that needs some investigation before this can be deleted
383     @Deprecated
doNothingOnErrorLogUtilError()384     protected final void doNothingOnErrorLogUtilError() {
385         doNothing().when(() -> ErrorLogUtil.e(any(), anyInt(), anyInt()));
386         doNothing().when(() -> ErrorLogUtil.e(anyInt(), anyInt()));
387     }
388 }
389