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