xref: /aosp_15_r20/tools/metalava/metalava/src/test/java/com/android/tools/metalava/RequiresFeatureTest.kt (revision 115816f9299ab6ddd6b9673b81f34e707f6bacab)
1 /*
2  * Copyright (C) 2023 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
18 
19 import com.android.tools.metalava.lint.DefaultLintErrorMessage
20 import com.android.tools.metalava.testing.java
21 import org.junit.Test
22 
23 class RequiresFeatureTest : DriverTest() {
24 
checkRequiresFeatureHandlingnull25     private fun checkRequiresFeatureHandling(
26         feature: String,
27         import: String = "import android.content.pm.PackageManager;",
28         enforcement: String = "",
29         expectedText: String,
30         expectedIssues: String = "",
31     ) {
32         val attributes =
33             if (enforcement == "") feature else """value = $feature, enforcement = "$enforcement""""
34         check(
35             sourceFiles =
36                 arrayOf(
37                     java(
38                         """
39                         package test.pkg;
40                         import android.annotation.RequiresFeature;
41                         $import
42                         @SuppressWarnings("WeakerAccess")
43                         @RequiresFeature($attributes)
44                         public class FeatureUser {
45                         }
46                     """
47                     ),
48                     java(
49                         """
50                         package android.content.pm;
51                         public abstract class PackageManager {
52                             public static final String FEATURE_LOCATION = "android.hardware.location";
53                             /** @hide */
54                             public static final String FEATURE_HIDDEN = "android.feature.hidden";
55                             public boolean hasSystemFeature(String feature) { return false; }
56                         }
57                     """
58                     ),
59                     java(
60                         """
61                         package android.pkg.other;
62                         public abstract class OtherFeatureManager {
63                             public static final String FEATURE_OTHER = "android.pkg.other.feature";
64                             public boolean hasMyFeature(String feature) { return false; }
65                         }
66                     """
67                     ),
68                     requiresFeatureSource,
69                 ),
70             checkCompilation = true,
71             docStubs = true,
72             stubFiles =
73                 arrayOf(
74                     java(
75                         """
76                         package test.pkg;
77                         $import
78                         /**
79                          * $expectedText
80                          */
81                         @SuppressWarnings({"unchecked", "deprecation", "all"})
82                         public class FeatureUser {
83                         public FeatureUser() { throw new RuntimeException("Stub!"); }
84                         }
85                     """
86                     ),
87                 ),
88             expectedFail = if (expectedIssues.isBlank()) "" else DefaultLintErrorMessage,
89             expectedIssues = expectedIssues,
90         )
91     }
92 
93     @Test
94     fun `Check RequiresFeature handling`() {
95         checkRequiresFeatureHandling(
96             feature = "PackageManager.FEATURE_LOCATION",
97             expectedText =
98                 "Requires the {@link android.content.pm.PackageManager#FEATURE_LOCATION PackageManager#FEATURE_LOCATION} feature which can be detected using {@link android.content.pm.PackageManager#hasSystemFeature(String) PackageManager.hasSystemFeature(String)}.",
99         )
100     }
101 
102     @Test
103     fun `Check RequiresFeature handling - missing feature`() {
104         checkRequiresFeatureHandling(
105             feature = "PackageManager.FEATURE_UNKNOWN",
106             expectedText =
107                 "Requires the {@link PackageManager.FEATURE_UNKNOWN} feature which can be detected using {@link android.content.pm.PackageManager#hasSystemFeature(String) PackageManager.hasSystemFeature(String)}.",
108             expectedIssues =
109                 "src/test/pkg/FeatureUser.java:6: error: Cannot find feature field for PackageManager.FEATURE_UNKNOWN required by class test.pkg.FeatureUser (may be hidden or removed) [MissingPermission]",
110         )
111     }
112 
113     @Test
114     fun `Check RequiresFeature handling - hidden feature`() {
115         checkRequiresFeatureHandling(
116             feature = "PackageManager.FEATURE_HIDDEN",
117             expectedText =
118                 "Requires the PackageManager#FEATURE_HIDDEN feature which can be detected using {@link android.content.pm.PackageManager#hasSystemFeature(String) PackageManager.hasSystemFeature(String)}.",
119             expectedIssues =
120                 "src/test/pkg/FeatureUser.java:6: error: Feature field PackageManager.FEATURE_HIDDEN required by class test.pkg.FeatureUser is hidden or removed [MissingPermission]",
121         )
122     }
123 
124     @Test
125     fun `Check RequiresFeature handling - custom enforcement`() {
126         checkRequiresFeatureHandling(
127             feature = "OtherFeatureManager.FEATURE_OTHER",
128             import = "import android.pkg.other.OtherFeatureManager;",
129             enforcement = "android.pkg.other.OtherFeatureManager#hasMyFeature",
130             expectedText =
131                 "Requires the {@link android.pkg.other.OtherFeatureManager#FEATURE_OTHER OtherFeatureManager#FEATURE_OTHER} feature which can be detected using {@link android.pkg.other.OtherFeatureManager#hasMyFeature(String) OtherFeatureManager.hasMyFeature(String)}.",
132         )
133     }
134 
135     @Test
136     fun `Check RequiresFeature handling - invalid enforcement`() {
137         checkRequiresFeatureHandling(
138             feature = "OtherFeatureManager.FEATURE_OTHER",
139             import = "import android.pkg.other.OtherFeatureManager;",
140             enforcement = "invalid enforcement value",
141             expectedText =
142                 "Requires the {@link android.pkg.other.OtherFeatureManager#FEATURE_OTHER OtherFeatureManager#FEATURE_OTHER} feature which can be detected using {@link android.content.pm.PackageManager#hasSystemFeature(String) PackageManager.hasSystemFeature(String)}.",
143             expectedIssues =
144                 "src/test/pkg/FeatureUser.java:6: error: Invalid 'enforcement' value 'invalid enforcement value', must be of the form <qualified-class>#<method-name>, using default [InvalidFeatureEnforcement]",
145         )
146     }
147 }
148