Loading tools/systemfeatures/Android.bp +1 −0 Original line number Diff line number Diff line Loading @@ -58,6 +58,7 @@ java_test_host { "junit", "objenesis", "mockito", "systemfeatures-gen-lib", "truth", ], } Loading tools/systemfeatures/src/com/android/systemfeatures/SystemFeaturesGenerator.kt +30 −4 Original line number Diff line number Diff line Loading @@ -89,6 +89,17 @@ object SystemFeaturesGenerator { /** Main entrypoint for build-time system feature codegen. */ @JvmStatic fun main(args: Array<String>) { generate(args, System.out) } /** * Simple API entrypoint for build-time system feature codegen. * * Note: Typically this would be implemented in terms of a proper Builder-type input argument, * but it's primarily used for testing as opposed to direct production usage. */ @JvmStatic fun generate(args: Array<String>, output: Appendable) { if (args.size < 1) { usage() return Loading Loading @@ -155,7 +166,7 @@ object SystemFeaturesGenerator { .addFileComment("This file is auto-generated. DO NOT MODIFY.\n") .addFileComment("Args: ${args.joinToString(" \\\n ")}") .build() .writeTo(System.out) .writeTo(output) } /* Loading @@ -171,12 +182,27 @@ object SystemFeaturesGenerator { return when (featureArgs.getOrNull(1)) { null, "" -> FeatureInfo(name, null, readonly = false) "UNAVAILABLE" -> FeatureInfo(name, null, readonly = true) else -> FeatureInfo(name, featureArgs[1].toIntOrNull(), readonly = true) else -> { val featureVersion = featureArgs[1].toIntOrNull() ?: throw IllegalArgumentException( "Invalid feature version input for $name: ${featureArgs[1]}" ) FeatureInfo(name, featureArgs[1].toInt(), readonly = true) } } } private fun parseFeatureName(name: String): String = if (name.startsWith("FEATURE_")) name else "FEATURE_$name" when { name.startsWith("android") -> throw IllegalArgumentException( "Invalid feature name input: \"android\"-namespaced features must be " + "provided as PackageManager.FEATURE_* suffixes, not raw feature strings." ) name.startsWith("FEATURE_") -> name else -> "FEATURE_$name" } /* * Adds per-feature query methods to the class with the form: Loading tools/systemfeatures/tests/src/SystemFeaturesGeneratorApiTest.java 0 → 100644 +81 −0 Original line number Diff line number Diff line /* * Copyright (C) 2024 The Android Open Source Project * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package com.android.systemfeatures; import static org.mockito.Mockito.any; import static org.mockito.Mockito.atLeastOnce; import static org.mockito.Mockito.never; import static org.mockito.Mockito.verify; import org.junit.Rule; import org.junit.Test; import org.junit.runner.RunWith; import org.junit.runners.JUnit4; import org.mockito.Mock; import org.mockito.junit.MockitoJUnit; import org.mockito.junit.MockitoRule; import java.io.IOException; // Note: This is a very simple argument test to validate certain behaviors for // invalid arguments. Correctness and validity is largely exercised by // SystemFeaturesGeneratorTest. @RunWith(JUnit4.class) public class SystemFeaturesGeneratorApiTest { @Rule public final MockitoRule mockito = MockitoJUnit.rule(); @Mock private Appendable mOut; @Test public void testEmpty() throws IOException { final String[] args = new String[] {}; // This should just print the commandline and return. SystemFeaturesGenerator.generate(args, mOut); verify(mOut, never()).append(any()); } @Test public void testBasic() throws IOException { final String[] args = new String[] { "com.foo.Features", "--feature=TELEVISION:0", }; SystemFeaturesGenerator.generate(args, mOut); verify(mOut, atLeastOnce()).append(any()); } @Test(expected = IllegalArgumentException.class) public void testInvalidFeatureVersion() throws IOException { final String[] args = new String[] { "com.foo.Features", "--feature=TELEVISION:blarg", }; SystemFeaturesGenerator.generate(args, mOut); verify(mOut, never()).append(any()); } @Test(expected = IllegalArgumentException.class) public void testInvalidFeatureNameFromAndroidNamespace() throws IOException { final String[] args = new String[] { "com.foo.Features", "--feature=android.hardware.doesntexist:0", }; SystemFeaturesGenerator.generate(args, mOut); verify(mOut, never()).append(any()); } } Loading
tools/systemfeatures/Android.bp +1 −0 Original line number Diff line number Diff line Loading @@ -58,6 +58,7 @@ java_test_host { "junit", "objenesis", "mockito", "systemfeatures-gen-lib", "truth", ], } Loading
tools/systemfeatures/src/com/android/systemfeatures/SystemFeaturesGenerator.kt +30 −4 Original line number Diff line number Diff line Loading @@ -89,6 +89,17 @@ object SystemFeaturesGenerator { /** Main entrypoint for build-time system feature codegen. */ @JvmStatic fun main(args: Array<String>) { generate(args, System.out) } /** * Simple API entrypoint for build-time system feature codegen. * * Note: Typically this would be implemented in terms of a proper Builder-type input argument, * but it's primarily used for testing as opposed to direct production usage. */ @JvmStatic fun generate(args: Array<String>, output: Appendable) { if (args.size < 1) { usage() return Loading Loading @@ -155,7 +166,7 @@ object SystemFeaturesGenerator { .addFileComment("This file is auto-generated. DO NOT MODIFY.\n") .addFileComment("Args: ${args.joinToString(" \\\n ")}") .build() .writeTo(System.out) .writeTo(output) } /* Loading @@ -171,12 +182,27 @@ object SystemFeaturesGenerator { return when (featureArgs.getOrNull(1)) { null, "" -> FeatureInfo(name, null, readonly = false) "UNAVAILABLE" -> FeatureInfo(name, null, readonly = true) else -> FeatureInfo(name, featureArgs[1].toIntOrNull(), readonly = true) else -> { val featureVersion = featureArgs[1].toIntOrNull() ?: throw IllegalArgumentException( "Invalid feature version input for $name: ${featureArgs[1]}" ) FeatureInfo(name, featureArgs[1].toInt(), readonly = true) } } } private fun parseFeatureName(name: String): String = if (name.startsWith("FEATURE_")) name else "FEATURE_$name" when { name.startsWith("android") -> throw IllegalArgumentException( "Invalid feature name input: \"android\"-namespaced features must be " + "provided as PackageManager.FEATURE_* suffixes, not raw feature strings." ) name.startsWith("FEATURE_") -> name else -> "FEATURE_$name" } /* * Adds per-feature query methods to the class with the form: Loading
tools/systemfeatures/tests/src/SystemFeaturesGeneratorApiTest.java 0 → 100644 +81 −0 Original line number Diff line number Diff line /* * Copyright (C) 2024 The Android Open Source Project * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package com.android.systemfeatures; import static org.mockito.Mockito.any; import static org.mockito.Mockito.atLeastOnce; import static org.mockito.Mockito.never; import static org.mockito.Mockito.verify; import org.junit.Rule; import org.junit.Test; import org.junit.runner.RunWith; import org.junit.runners.JUnit4; import org.mockito.Mock; import org.mockito.junit.MockitoJUnit; import org.mockito.junit.MockitoRule; import java.io.IOException; // Note: This is a very simple argument test to validate certain behaviors for // invalid arguments. Correctness and validity is largely exercised by // SystemFeaturesGeneratorTest. @RunWith(JUnit4.class) public class SystemFeaturesGeneratorApiTest { @Rule public final MockitoRule mockito = MockitoJUnit.rule(); @Mock private Appendable mOut; @Test public void testEmpty() throws IOException { final String[] args = new String[] {}; // This should just print the commandline and return. SystemFeaturesGenerator.generate(args, mOut); verify(mOut, never()).append(any()); } @Test public void testBasic() throws IOException { final String[] args = new String[] { "com.foo.Features", "--feature=TELEVISION:0", }; SystemFeaturesGenerator.generate(args, mOut); verify(mOut, atLeastOnce()).append(any()); } @Test(expected = IllegalArgumentException.class) public void testInvalidFeatureVersion() throws IOException { final String[] args = new String[] { "com.foo.Features", "--feature=TELEVISION:blarg", }; SystemFeaturesGenerator.generate(args, mOut); verify(mOut, never()).append(any()); } @Test(expected = IllegalArgumentException.class) public void testInvalidFeatureNameFromAndroidNamespace() throws IOException { final String[] args = new String[] { "com.foo.Features", "--feature=android.hardware.doesntexist:0", }; SystemFeaturesGenerator.generate(args, mOut); verify(mOut, never()).append(any()); } }