blob: 3cd6a2425603a961df6c45202110d7fb0c05de2d [file] [log] [blame]
Mårten Kongstadf242ec82024-04-16 17:12:26 +02001/*
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 */
16package com.android.checkflaggedapis
17
Mårten Kongstad387ff6c2024-04-16 12:42:14 +020018import android.aconfig.Aconfig
Mårten Kongstad18ff19a2024-04-26 05:48:57 +020019import android.aconfig.Aconfig.flag_state.DISABLED
20import android.aconfig.Aconfig.flag_state.ENABLED
Mårten Kongstad387ff6c2024-04-16 12:42:14 +020021import java.io.ByteArrayInputStream
22import java.io.ByteArrayOutputStream
Mårten Kongstad9238a3a2024-04-16 13:19:50 +020023import java.io.InputStream
Mårten Kongstad20de4052024-04-16 11:33:56 +020024import org.junit.Assert.assertEquals
Mårten Kongstadf242ec82024-04-16 17:12:26 +020025import org.junit.Test
26import org.junit.runner.RunWith
Mårten Kongstad7cc21742024-04-18 10:23:20 +020027import org.junit.runners.JUnit4
Mårten Kongstadf242ec82024-04-16 17:12:26 +020028
Mårten Kongstad20de4052024-04-16 11:33:56 +020029private val API_SIGNATURE =
30 """
31 // Signature format: 2.0
32 package android {
Mårten Kongstad18ff19a2024-04-26 05:48:57 +020033 @FlaggedApi("android.flag.foo") public final class Clazz {
Mårten Kongstad40da9702024-04-27 01:42:51 +020034 ctor @FlaggedApi("android.flag.foo") public Clazz();
Mårten Kongstad20de4052024-04-16 11:33:56 +020035 field @FlaggedApi("android.flag.foo") public static final int FOO = 1; // 0x1
Mårten Kongstad40da9702024-04-27 01:42:51 +020036 method @FlaggedApi("android.flag.foo") public int getErrorCode();
Mårten Kongstadb4a14bf2024-04-28 00:21:11 +020037 method @FlaggedApi("android.flag.foo") public boolean setData(int, int[][], @NonNull android.util.Utility<T, U>);
38 method @FlaggedApi("android.flag.foo") public boolean setVariableData(int, android.util.Atom...);
39 method @FlaggedApi("android.flag.foo") public boolean innerClassArg(android.Clazz.Builder);
Mårten Kongstad20de4052024-04-16 11:33:56 +020040 }
Mårten Kongstad18ff19a2024-04-26 05:48:57 +020041 @FlaggedApi("android.flag.bar") public static class Clazz.Builder {
42 }
Mårten Kongstad20de4052024-04-16 11:33:56 +020043 }
44"""
45 .trim()
46
Mårten Kongstadb673d3b2024-04-16 18:34:20 +020047private val API_VERSIONS =
48 """
49 <?xml version="1.0" encoding="utf-8"?>
50 <api version="3">
51 <class name="android/Clazz" since="1">
52 <method name="&lt;init>()V"/>
53 <field name="FOO"/>
Mårten Kongstad40da9702024-04-27 01:42:51 +020054 <method name="getErrorCode()I"/>
Mårten Kongstadb4a14bf2024-04-28 00:21:11 +020055 <method name="setData(I[[ILandroid/util/Utility;)Z"/>
56 <method name="setVariableData(I[Landroid/util/Atom;)Z"/>
57 <method name="innerClassArg(Landroid/Clazz${"$"}Builder;)"/>
Mårten Kongstadb673d3b2024-04-16 18:34:20 +020058 </class>
Mårten Kongstad18ff19a2024-04-26 05:48:57 +020059 <class name="android/Clazz${"$"}Builder" since="2">
60 </class>
Mårten Kongstadb673d3b2024-04-16 18:34:20 +020061 </api>
62"""
63 .trim()
64
Mårten Kongstad18ff19a2024-04-26 05:48:57 +020065private fun generateFlagsProto(
66 fooState: Aconfig.flag_state,
67 barState: Aconfig.flag_state
68): InputStream {
69 val fooFlag =
Mårten Kongstad9238a3a2024-04-16 13:19:50 +020070 Aconfig.parsed_flag
71 .newBuilder()
72 .setPackage("android.flag")
73 .setName("foo")
74 .setState(fooState)
75 .setPermission(Aconfig.flag_permission.READ_ONLY)
76 .build()
Mårten Kongstad18ff19a2024-04-26 05:48:57 +020077 val barFlag =
78 Aconfig.parsed_flag
79 .newBuilder()
80 .setPackage("android.flag")
81 .setName("bar")
82 .setState(barState)
83 .setPermission(Aconfig.flag_permission.READ_ONLY)
84 .build()
85 val flags =
86 Aconfig.parsed_flags.newBuilder().addParsedFlag(fooFlag).addParsedFlag(barFlag).build()
Mårten Kongstad9238a3a2024-04-16 13:19:50 +020087 val binaryProto = ByteArrayOutputStream()
Mårten Kongstad18ff19a2024-04-26 05:48:57 +020088 flags.writeTo(binaryProto)
Mårten Kongstad9238a3a2024-04-16 13:19:50 +020089 return ByteArrayInputStream(binaryProto.toByteArray())
90}
91
Mårten Kongstad7cc21742024-04-18 10:23:20 +020092@RunWith(JUnit4::class)
93class CheckFlaggedApisTest {
Mårten Kongstad20de4052024-04-16 11:33:56 +020094 @Test
95 fun testParseApiSignature() {
Mårten Kongstad18ff19a2024-04-26 05:48:57 +020096 val expected =
97 setOf(
Mårten Kongstad7c3571f2024-05-06 14:53:54 +020098 Pair(Symbol.createClass("android/Clazz", setOf()), Flag("android.flag.foo")),
Mårten Kongstada1fe3712024-05-06 13:46:21 +020099 Pair(Symbol.createMethod("android/Clazz", "Clazz()"), Flag("android.flag.foo")),
100 Pair(Symbol.createField("android/Clazz", "FOO"), Flag("android.flag.foo")),
101 Pair(Symbol.createMethod("android/Clazz", "getErrorCode()"), Flag("android.flag.foo")),
Mårten Kongstadb4a14bf2024-04-28 00:21:11 +0200102 Pair(
Mårten Kongstada1fe3712024-05-06 13:46:21 +0200103 Symbol.createMethod("android/Clazz", "setData(I[[ILandroid/util/Utility;)"),
Mårten Kongstadb4a14bf2024-04-28 00:21:11 +0200104 Flag("android.flag.foo")),
105 Pair(
Mårten Kongstada1fe3712024-05-06 13:46:21 +0200106 Symbol.createMethod("android/Clazz", "setVariableData(I[Landroid/util/Atom;)"),
Mårten Kongstadb4a14bf2024-04-28 00:21:11 +0200107 Flag("android.flag.foo")),
108 Pair(
Mårten Kongstada1fe3712024-05-06 13:46:21 +0200109 Symbol.createMethod("android/Clazz", "innerClassArg(Landroid/Clazz/Builder;)"),
Mårten Kongstadb4a14bf2024-04-28 00:21:11 +0200110 Flag("android.flag.foo")),
Mårten Kongstad7c3571f2024-05-06 14:53:54 +0200111 Pair(Symbol.createClass("android/Clazz/Builder", setOf()), Flag("android.flag.bar")),
Mårten Kongstad18ff19a2024-04-26 05:48:57 +0200112 )
Mårten Kongstad20de4052024-04-16 11:33:56 +0200113 val actual = parseApiSignature("in-memory", API_SIGNATURE.byteInputStream())
114 assertEquals(expected, actual)
115 }
Mårten Kongstad387ff6c2024-04-16 12:42:14 +0200116
117 @Test
118 fun testParseFlagValues() {
Mårten Kongstad18ff19a2024-04-26 05:48:57 +0200119 val expected: Map<Flag, Boolean> =
120 mapOf(Flag("android.flag.foo") to true, Flag("android.flag.bar") to true)
121 val actual = parseFlagValues(generateFlagsProto(ENABLED, ENABLED))
Mårten Kongstad387ff6c2024-04-16 12:42:14 +0200122 assertEquals(expected, actual)
123 }
Mårten Kongstadb673d3b2024-04-16 18:34:20 +0200124
125 @Test
126 fun testParseApiVersions() {
Mårten Kongstad18ff19a2024-04-26 05:48:57 +0200127 val expected: Set<Symbol> =
128 setOf(
Mårten Kongstad7c3571f2024-05-06 14:53:54 +0200129 Symbol.createClass("android/Clazz", setOf()),
Mårten Kongstada1fe3712024-05-06 13:46:21 +0200130 Symbol.createMethod("android/Clazz", "Clazz()"),
131 Symbol.createField("android/Clazz", "FOO"),
132 Symbol.createMethod("android/Clazz", "getErrorCode()"),
133 Symbol.createMethod("android/Clazz", "setData(I[[ILandroid/util/Utility;)"),
134 Symbol.createMethod("android/Clazz", "setVariableData(I[Landroid/util/Atom;)"),
135 Symbol.createMethod("android/Clazz", "innerClassArg(Landroid/Clazz/Builder;)"),
Mårten Kongstad7c3571f2024-05-06 14:53:54 +0200136 Symbol.createClass("android/Clazz/Builder", setOf()),
Mårten Kongstad18ff19a2024-04-26 05:48:57 +0200137 )
Mårten Kongstadb673d3b2024-04-16 18:34:20 +0200138 val actual = parseApiVersions(API_VERSIONS.byteInputStream())
139 assertEquals(expected, actual)
140 }
Mårten Kongstad9238a3a2024-04-16 13:19:50 +0200141
142 @Test
Mårten Kongstad02525a82024-05-06 10:28:02 +0200143 fun testParseApiVersionsNestedClasses() {
144 val apiVersions =
145 """
146 <?xml version="1.0" encoding="utf-8"?>
147 <api version="3">
148 <class name="android/Clazz${'$'}Foo${'$'}Bar" since="1">
149 <method name="&lt;init>()V"/>
150 </class>
151 </api>
152 """
153 .trim()
154 val expected: Set<Symbol> =
155 setOf(
Mårten Kongstad7c3571f2024-05-06 14:53:54 +0200156 Symbol.createClass("android/Clazz/Foo/Bar", setOf()),
Mårten Kongstada1fe3712024-05-06 13:46:21 +0200157 Symbol.createMethod("android/Clazz/Foo/Bar", "Bar()"),
Mårten Kongstad02525a82024-05-06 10:28:02 +0200158 )
159 val actual = parseApiVersions(apiVersions.byteInputStream())
160 assertEquals(expected, actual)
161 }
162
163 @Test
Mårten Kongstad9238a3a2024-04-16 13:19:50 +0200164 fun testFindErrorsNoErrors() {
165 val expected = setOf<ApiError>()
166 val actual =
167 findErrors(
168 parseApiSignature("in-memory", API_SIGNATURE.byteInputStream()),
Mårten Kongstad18ff19a2024-04-26 05:48:57 +0200169 parseFlagValues(generateFlagsProto(ENABLED, ENABLED)),
Mårten Kongstad9238a3a2024-04-16 13:19:50 +0200170 parseApiVersions(API_VERSIONS.byteInputStream()))
171 assertEquals(expected, actual)
172 }
173
174 @Test
Mårten Kongstadd2c70762024-05-06 14:58:18 +0200175 fun testFindErrorsVerifyImplements() {
176 val apiSignature =
177 """
178 // Signature format: 2.0
179 package android {
180 @FlaggedApi("android.flag.foo") public final class Clazz implements android.Interface {
181 method @FlaggedApi("android.flag.foo") public boolean foo();
182 method @FlaggedApi("android.flag.foo") public boolean bar();
183 }
184 public interface Interface {
185 method public boolean bar();
186 }
187 }
188 """
189 .trim()
190
191 val apiVersions =
192 """
193 <?xml version="1.0" encoding="utf-8"?>
194 <api version="3">
195 <class name="android/Clazz" since="1">
196 <implements name="android/Interface"/>
197 <method name="foo()Z"/>
198 </class>
199 <class name="android/Interface" since="1">
200 <method name="bar()Z"/>
201 </class>
202 </api>
203 """
204 .trim()
205
206 val expected = setOf<ApiError>()
207 val actual =
208 findErrors(
209 parseApiSignature("in-memory", apiSignature.byteInputStream()),
210 parseFlagValues(generateFlagsProto(ENABLED, ENABLED)),
211 parseApiVersions(apiVersions.byteInputStream()))
212 assertEquals(expected, actual)
213 }
214
215 @Test
Mårten Kongstad9238a3a2024-04-16 13:19:50 +0200216 fun testFindErrorsDisabledFlaggedApiIsPresent() {
217 val expected =
218 setOf<ApiError>(
Mårten Kongstad40da9702024-04-27 01:42:51 +0200219 DisabledFlaggedApiIsPresentError(
Mårten Kongstad7c3571f2024-05-06 14:53:54 +0200220 Symbol.createClass("android/Clazz", setOf()), Flag("android.flag.foo")),
Mårten Kongstad18ff19a2024-04-26 05:48:57 +0200221 DisabledFlaggedApiIsPresentError(
Mårten Kongstada1fe3712024-05-06 13:46:21 +0200222 Symbol.createMethod("android/Clazz", "Clazz()"), Flag("android.flag.foo")),
Mårten Kongstad40da9702024-04-27 01:42:51 +0200223 DisabledFlaggedApiIsPresentError(
Mårten Kongstada1fe3712024-05-06 13:46:21 +0200224 Symbol.createField("android/Clazz", "FOO"), Flag("android.flag.foo")),
225 DisabledFlaggedApiIsPresentError(
226 Symbol.createMethod("android/Clazz", "getErrorCode()"), Flag("android.flag.foo")),
227 DisabledFlaggedApiIsPresentError(
228 Symbol.createMethod("android/Clazz", "setData(I[[ILandroid/util/Utility;)"),
Mårten Kongstadb4a14bf2024-04-28 00:21:11 +0200229 Flag("android.flag.foo")),
230 DisabledFlaggedApiIsPresentError(
Mårten Kongstada1fe3712024-05-06 13:46:21 +0200231 Symbol.createMethod("android/Clazz", "setVariableData(I[Landroid/util/Atom;)"),
Mårten Kongstadb4a14bf2024-04-28 00:21:11 +0200232 Flag("android.flag.foo")),
233 DisabledFlaggedApiIsPresentError(
Mårten Kongstada1fe3712024-05-06 13:46:21 +0200234 Symbol.createMethod("android/Clazz", "innerClassArg(Landroid/Clazz/Builder;)"),
Mårten Kongstadb4a14bf2024-04-28 00:21:11 +0200235 Flag("android.flag.foo")),
236 DisabledFlaggedApiIsPresentError(
Mårten Kongstad7c3571f2024-05-06 14:53:54 +0200237 Symbol.createClass("android/Clazz/Builder", setOf()), Flag("android.flag.bar")),
Mårten Kongstad18ff19a2024-04-26 05:48:57 +0200238 )
Mårten Kongstad9238a3a2024-04-16 13:19:50 +0200239 val actual =
240 findErrors(
241 parseApiSignature("in-memory", API_SIGNATURE.byteInputStream()),
Mårten Kongstad18ff19a2024-04-26 05:48:57 +0200242 parseFlagValues(generateFlagsProto(DISABLED, DISABLED)),
Mårten Kongstad9238a3a2024-04-16 13:19:50 +0200243 parseApiVersions(API_VERSIONS.byteInputStream()))
244 assertEquals(expected, actual)
245 }
Mårten Kongstadf242ec82024-04-16 17:12:26 +0200246}