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 com.android.tools.metalava.lint
18 
19 import com.android.tools.lint.checks.infrastructure.TestFile
20 import com.android.tools.metalava.DriverTest
21 import com.android.tools.metalava.testing.java
22 import org.junit.Test
23 import org.junit.runners.Parameterized
24 
25 /** Tests for the filtering of issues done by [ApiLint]. */
26 class ApiLintFilteringTest(private val previouslyReleasedApiUse: PreviouslyReleasedApiUse) :
27     DriverTest() {
28 
29     enum class PreviouslyReleasedApiUse {
30         WITH,
31         WITHOUT,
32     }
33 
34     companion object {
35         /** Run each test with and without the previously released API. */
36         @JvmStatic
37         @Parameterized.Parameters(name = "{0}")
testParametersnull38         fun testParameters() = PreviouslyReleasedApiUse.values()
39     }
40 
41     private fun checkFiltering(
42         sourceFiles: Array<TestFile>,
43         expectedIssuesWithoutPreviouslyReleasedApi: String,
44         previouslyReleasedApi: String,
45         expectedIssuesWithPreviouslyReleasedApi: String,
46     ) {
47         val (apiLint, expectedIssues) =
48             if (previouslyReleasedApiUse == PreviouslyReleasedApiUse.WITH)
49                 Pair(previouslyReleasedApi, expectedIssuesWithPreviouslyReleasedApi)
50             else Pair("", expectedIssuesWithoutPreviouslyReleasedApi)
51         val expectedFail = if (expectedIssues == "") "" else DefaultLintErrorMessage
52         check(
53             apiLint = apiLint,
54             sourceFiles = sourceFiles,
55             expectedFail = expectedFail,
56             expectedIssues = expectedIssues,
57         )
58     }
59 
60     @Test
test errors are ignored on previously released APIsnull61     fun `test errors are ignored on previously released APIs`() {
62         checkFiltering(
63             sourceFiles =
64                 arrayOf(
65                     java(
66                         """
67                             package test.pkg;
68                             public class Foo {
69                                 public void method(String s) {}
70                                 public int hashCode() {return 0;}
71                                 public String field;
72                             }
73                         """
74                     ),
75                 ),
76             expectedIssuesWithoutPreviouslyReleasedApi =
77                 """
78                     src/test/pkg/Foo.java:4: error: Must override both equals and hashCode; missing one in test.pkg.Foo [EqualsAndHashCode]
79                     src/test/pkg/Foo.java:3: error: Missing nullability on parameter `s` in method `method` [MissingNullability]
80                     src/test/pkg/Foo.java:5: error: Bare field field must be marked final, or moved behind accessors if mutable [MutableBareField]
81                     src/test/pkg/Foo.java:5: error: Missing nullability on field `field` in class `class test.pkg.Foo` [MissingNullability]
82                 """,
83             previouslyReleasedApi =
84                 """
85                     // Signature format: 2.0
86                     package test.pkg {
87                       public class Foo {
88                         method public void method(String);
89                         method public int hashCode();
90                         field public String field;
91                       }
92                     }
93                 """,
94             expectedIssuesWithPreviouslyReleasedApi = "",
95         )
96     }
97 
98     @Test
test checkClass produced errors are treated as warnings on new members of previously released classesnull99     fun `test checkClass produced errors are treated as warnings on new members of previously released classes`() {
100         // The `EqualsAndHashCode` check is performed by `checkEquals()` which is called by
101         // `checkClass()` and so was previously only called for new classes. This test checks that
102         // behavior is maintained.
103         checkFiltering(
104             sourceFiles =
105                 arrayOf(
106                     java(
107                         """
108                             package test.pkg;
109                             public class Foo {
110                                 public void method(String s) {}
111                                 public String field;
112                                 public int hashCode() {return 0;}
113                             }
114                         """
115                     ),
116                 ),
117             expectedIssuesWithoutPreviouslyReleasedApi =
118                 """
119                     src/test/pkg/Foo.java:5: error: Must override both equals and hashCode; missing one in test.pkg.Foo [EqualsAndHashCode]
120                     src/test/pkg/Foo.java:3: error: Missing nullability on parameter `s` in method `method` [MissingNullability]
121                     src/test/pkg/Foo.java:4: error: Bare field field must be marked final, or moved behind accessors if mutable [MutableBareField]
122                     src/test/pkg/Foo.java:4: error: Missing nullability on field `field` in class `class test.pkg.Foo` [MissingNullability]
123                 """,
124             previouslyReleasedApi =
125                 """
126                     // Signature format: 2.0
127                     package test.pkg {
128                       public class Foo {
129                       }
130                     }
131                 """,
132             expectedIssuesWithPreviouslyReleasedApi =
133                 // Notice that the `EqualsAndHashCode` issue is reported as a warning, not an error.
134                 """
135                     src/test/pkg/Foo.java:5: warning: Must override both equals and hashCode; missing one in test.pkg.Foo (ErrorWhenNew) [EqualsAndHashCode]
136                     src/test/pkg/Foo.java:3: error: Missing nullability on parameter `s` in method `method` [MissingNullability]
137                     src/test/pkg/Foo.java:4: error: Bare field field must be marked final, or moved behind accessors if mutable [MutableBareField]
138                     src/test/pkg/Foo.java:4: error: Missing nullability on field `field` in class `class test.pkg.Foo` [MissingNullability]
139                 """,
140         )
141     }
142 }
143