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