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 17 package android.adservices.lint.test 18 19 import android.adservices.lint.test.ErrorLogUtilMockingUsageDetector.Constants.INVALID_ANNOTATION_MESSAGE 20 import android.adservices.lint.test.ErrorLogUtilMockingUsageDetector.Constants.INVALID_MOCKING_MESSAGE 21 import com.android.tools.lint.checks.infrastructure.LintDetectorTest 22 import com.android.tools.lint.checks.infrastructure.TestFile 23 import com.android.tools.lint.checks.infrastructure.TestLintTask 24 import com.android.tools.lint.detector.api.Detector 25 import com.android.tools.lint.detector.api.Issue 26 import org.junit.Test 27 import org.junit.runner.RunWith 28 import org.junit.runners.JUnit4 29 30 @RunWith(JUnit4::class) 31 class ErrorLogUtilMockingUsageDetectorTest : LintDetectorTest() { getDetectornull32 override fun getDetector(): Detector = ErrorLogUtilMockingUsageDetector() 33 34 override fun getIssues(): List<Issue> = 35 listOf( 36 ErrorLogUtilMockingUsageDetector.INVALID_ANNOTATION_ISSUE, 37 ErrorLogUtilMockingUsageDetector.MOCKING_INVOCATION_ISSUE 38 ) 39 40 override fun lint(): TestLintTask = super.lint().allowMissingSdk(true) 41 42 @Test 43 fun testNoErrorLogUtilMocksSpies_pass() { 44 lint() 45 .files( 46 java( 47 """ 48 @MockStatic(Foo1.class) 49 @SpyStatic(Foo2.class) 50 public final class FooTest extends AdServicesExtendedMockitoTestCase { 51 @Test 52 @MockStatic(Foo3.class) 53 @SpyStatic(Foo4.class) 54 public void testFoo() { 55 } 56 } 57 """ 58 ) 59 .indented() 60 ) 61 .run() 62 .expectClean() 63 } 64 65 @Test testSpyErrorLogUtilInSuperclass_passnull66 fun testSpyErrorLogUtilInSuperclass_pass() { 67 lint() 68 .files( 69 java( 70 """ 71 @SpyStatic(ErrorLogUtil.class) 72 public class AdServicesExtendedMockitoTestCase { 73 } 74 """ 75 ) 76 .indented() 77 ) 78 .run() 79 .expectClean() 80 } 81 82 @Test testMockErrorLogUtilOverClass_throwsnull83 fun testMockErrorLogUtilOverClass_throws() { 84 lint() 85 .files( 86 java( 87 """ 88 @MockStatic(Foo1.class) 89 @MockStatic(ErrorLogUtil.class) 90 public final class FooTest extends AdServicesExtendedMockitoTestCase { 91 @Test 92 public void testFoo() { 93 } 94 } 95 """ 96 ) 97 .indented() 98 ) 99 .run() 100 .expectErrorCount(1) 101 .expectContains(INVALID_ANNOTATION_MESSAGE) 102 } 103 104 @Test testSpyErrorLogUtilOverClass_throwsnull105 fun testSpyErrorLogUtilOverClass_throws() { 106 lint() 107 .files( 108 java( 109 """ 110 @MockStatic(Foo1.class) 111 @SpyStatic(ErrorLogUtil.class) 112 public final class FooTest extends AdServicesExtendedMockitoTestCase { 113 @Test 114 public void testFoo() { 115 } 116 } 117 """ 118 ) 119 .indented() 120 ) 121 .run() 122 .expectErrorCount(1) 123 .expectContains(INVALID_ANNOTATION_MESSAGE) 124 } 125 126 @Test testMockErrorLogUtilOverMethod_throwsnull127 fun testMockErrorLogUtilOverMethod_throws() { 128 lint() 129 .files( 130 java( 131 """ 132 @MockStatic(Foo1.class) 133 public final class FooTest extends AdServicesExtendedMockitoTestCase { 134 @Test 135 @MockStatic(ErrorLogUtil.class) 136 public void testFoo() { 137 } 138 } 139 """ 140 ) 141 .indented() 142 ) 143 .run() 144 .expectErrorCount(1) 145 .expectContains(INVALID_ANNOTATION_MESSAGE) 146 } 147 148 @Test testSpyErrorLogUtilOverMethod_throwsnull149 fun testSpyErrorLogUtilOverMethod_throws() { 150 lint() 151 .files( 152 java( 153 """ 154 @MockStatic(Foo1.class) 155 public final class FooTest extends AdServicesExtendedMockitoTestCase { 156 @Test 157 @SpyStatic(ErrorLogUtil.class) 158 public void testFoo() { 159 } 160 } 161 """ 162 ) 163 .indented() 164 ) 165 .run() 166 .expectErrorCount(1) 167 .expectContains(INVALID_ANNOTATION_MESSAGE) 168 } 169 170 @Test testErrorLogUtilMockingInNonExtendedMockitoSubclass_passesnull171 fun testErrorLogUtilMockingInNonExtendedMockitoSubclass_passes() { 172 lint() 173 .files( 174 java( 175 """ 176 package com.test; 177 import static com.test.ExtendedMockito.doNothing; 178 public final class FooTest { 179 @Before 180 public void setup() { 181 doNothing().when(() -> ErrorLogUtil.e(anyInt(), anyInt())); 182 } 183 } 184 """ 185 ) 186 .indented(), 187 *stubs 188 ) 189 .run() 190 .expectClean() 191 } 192 193 @Test testNoErrorLogUtilMockingIssues_passesnull194 fun testNoErrorLogUtilMockingIssues_passes() { 195 lint() 196 .files( 197 java( 198 """ 199 package com.test; 200 @MockStatic(Foo1.class) 201 @SpyStatic(Foo2.class) 202 public final class FooTest extends AdServicesExtendedMockitoTestCase { 203 @Before 204 public void setup() { 205 fooMethod(); 206 } 207 @Test 208 public void testFoo() { 209 foo(); 210 } 211 } 212 """ 213 ) 214 .indented(), 215 *stubs 216 ) 217 .run() 218 .expectClean() 219 } 220 221 @Test testErrorLogUtilMockingUsingUtilsInNonExtendedMockitoSubclass_passesnull222 fun testErrorLogUtilMockingUsingUtilsInNonExtendedMockitoSubclass_passes() { 223 lint() 224 .files( 225 java( 226 """ 227 package com.test; 228 import static com.test.ExtendedMockitoExpectations.doNothingOnErrorLogUtilError; 229 public final class FooTest extends IntermediateClass { 230 @Before 231 public void setup() { 232 doNothingOnErrorLogUtilError(); 233 } 234 } 235 """ 236 ) 237 .indented(), 238 *stubs 239 ) 240 .run() 241 .expectClean() 242 } 243 244 @Test testErrorLogUtilMockingInExtendedMockitoSubclass_throwsnull245 fun testErrorLogUtilMockingInExtendedMockitoSubclass_throws() { 246 lint() 247 .files( 248 java( 249 """ 250 package com.test; 251 import static com.test.ExtendedMockito.doNothing; 252 public final class FooTest extends IntermediateClassExtendsSuperclass { 253 @Before 254 public void setup() { 255 doNothing().when(() -> ErrorLogUtil.e(anyInt(), anyInt())); 256 } 257 } 258 """ 259 ) 260 .indented(), 261 *stubs 262 ) 263 .run() 264 .expectErrorCount(1) 265 .expectContains(INVALID_MOCKING_MESSAGE) 266 } 267 268 @Test testErrorLogUtilMockingUsingUtilsInExtendedMockitoSubclass_throwsnull269 fun testErrorLogUtilMockingUsingUtilsInExtendedMockitoSubclass_throws() { 270 lint() 271 .files( 272 java( 273 """ 274 package com.test; 275 import static com.test.ExtendedMockitoExpectations.doNothingOnErrorLogUtilError; 276 public final class FooTest extends IntermediateClassExtendsSuperclass { 277 @Before 278 public void setup() { 279 doNothingOnErrorLogUtilError(); 280 } 281 } 282 """ 283 ) 284 .indented(), 285 *stubs 286 ) 287 .run() 288 .expectErrorCount(1) 289 .expectContains(INVALID_MOCKING_MESSAGE) 290 } 291 292 @Test testMultipleErrorLogUtilMockingIssues_throwsMultiplenull293 fun testMultipleErrorLogUtilMockingIssues_throwsMultiple() { 294 lint() 295 .files( 296 java( 297 """ 298 package com.test; 299 import static com.test.ExtendedMockitoExpectations.doNothingOnErrorLogUtilError; 300 @SpyStatic(ErrorLogUtil.class) 301 public final class FooTest extends IntermediateClassExtendsSuperclass { 302 @Before 303 public void setup() { 304 doNothingOnErrorLogUtilError(); 305 } 306 } 307 """ 308 ) 309 .indented(), 310 *stubs 311 ) 312 .run() 313 .expectErrorCount(2) 314 .expectContains(INVALID_ANNOTATION_MESSAGE) 315 .expectContains(INVALID_MOCKING_MESSAGE) 316 } 317 318 private val extendedMockitoExpectations: TestFile = 319 java( 320 """ 321 package com.test; 322 public final class ExtendedMockitoExpectations { 323 public static void doNothingOnErrorLogUtilError(){ 324 } 325 } 326 """ 327 ) 328 .indented() 329 330 private val adServicesExtendedMockitoTestCase: TestFile = 331 java( 332 """ 333 package com.test; 334 public class AdServicesExtendedMockitoTestCase { 335 } 336 """ 337 ) 338 .indented() 339 340 private val intermediateClassExtendsSuperclass: TestFile = 341 java( 342 """ 343 package com.test; 344 public class IntermediateClassExtendsSuperclass extends AdServicesExtendedMockitoTestCase { 345 } 346 """ 347 ) 348 .indented() 349 350 private val intermediateClass: TestFile = 351 java( 352 """ 353 package com.test; 354 public class IntermediateClass { 355 } 356 """ 357 ) 358 .indented() 359 360 private val extendedMockito: TestFile = 361 java( 362 """ 363 package com.test; 364 public final class ExtendedMockito { 365 public static StaticCapableStubber doNothing() {} 366 } 367 """ 368 ) 369 .indented() 370 371 private val staticCapableStubber: TestFile = 372 java( 373 """ 374 package com.test; 375 public final class StaticCapableStubber { 376 public void when(MockedVoidMethod method) {} 377 } 378 """ 379 ) 380 .indented() 381 382 private val stubs = 383 arrayOf( 384 extendedMockitoExpectations, 385 adServicesExtendedMockitoTestCase, 386 intermediateClassExtendsSuperclass, 387 intermediateClass, 388 extendedMockito, 389 staticCapableStubber 390 ) 391 } 392