aconfig: generate full fakefeatureflagsimpl in prod mode

This change will generate full fakefeatureflagsimpl in prod mode.
FakeFeatureFlagsImp will be the same in test mode and the prod mode.
FeatureFlagsImpl will be all unimplemented in test mode. setFlag,
resetAll are added into the interface FeatureFlags.

The reason to make this change is for project using injection pattern,
the project doesn't have to use test mode to test the flag guarded code.
The project can directly use the FakeFeatureFlagsImpl for testing.

Bug: 294838180
Test: atest AconfigJavaHostTest --host AND atest aconfig.test.java
Change-Id: Ib6d40fd3a9ef872e01594fd4f8d6c4cb10bb173a
This commit is contained in:
Zhi Dou
2023-08-15 19:33:27 +00:00
parent 5d7f9cb2a1
commit 06a448fac7
6 changed files with 81 additions and 148 deletions

View File

@@ -124,6 +124,7 @@ mod tests {
boolean enabledFixedRo(); boolean enabledFixedRo();
boolean enabledRo(); boolean enabledRo();
boolean enabledRw(); boolean enabledRw();
}
"#; "#;
const EXPECTED_FLAG_COMMON_CONTENT: &str = r#" const EXPECTED_FLAG_COMMON_CONTENT: &str = r#"
@@ -152,32 +153,62 @@ mod tests {
} }
"#; "#;
const EXPECTED_METHOD_NOT_IMPL_COMMON_CONTENT: &str = r#" const EXPECTED_FAKEFEATUREFLAGSIMPL_CONTENT: &str = r#"
package com.android.aconfig.test;
import java.util.HashMap;
import java.util.Map;
public class FakeFeatureFlagsImpl implements FeatureFlags {
public FakeFeatureFlagsImpl() {
resetAll();
}
@Override @Override
public boolean disabledRo() { public boolean disabledRo() {
throw new UnsupportedOperationException( return getFlag(Flags.FLAG_DISABLED_RO);
"Method is not implemented.");
} }
@Override @Override
public boolean disabledRw() { public boolean disabledRw() {
throw new UnsupportedOperationException( return getFlag(Flags.FLAG_DISABLED_RW);
"Method is not implemented.");
} }
@Override @Override
public boolean enabledFixedRo() { public boolean enabledFixedRo() {
throw new UnsupportedOperationException( return getFlag(Flags.FLAG_ENABLED_FIXED_RO);
"Method is not implemented.");
} }
@Override @Override
public boolean enabledRo() { public boolean enabledRo() {
throw new UnsupportedOperationException( return getFlag(Flags.FLAG_ENABLED_RO);
"Method is not implemented.");
} }
@Override @Override
public boolean enabledRw() { public boolean enabledRw() {
throw new UnsupportedOperationException( return getFlag(Flags.FLAG_ENABLED_RW);
"Method is not implemented.");
} }
public void setFlag(String flagName, boolean value) {
if (!this.mFlagMap.containsKey(flagName)) {
throw new IllegalArgumentException("no such flag " + flagName);
}
this.mFlagMap.put(flagName, value);
}
public void resetAll() {
for (Map.Entry entry : mFlagMap.entrySet()) {
entry.setValue(null);
}
}
private boolean getFlag(String flagName) {
Boolean value = this.mFlagMap.get(flagName);
if (value == null) {
throw new IllegalArgumentException(flagName + " is not set");
}
return value;
}
private Map<String, Boolean> mFlagMap = new HashMap<>(
Map.of(
Flags.FLAG_DISABLED_RO, false,
Flags.FLAG_DISABLED_RW, false,
Flags.FLAG_ENABLED_FIXED_RO, false,
Flags.FLAG_ENABLED_RO, false,
Flags.FLAG_ENABLED_RW, false
)
);
}
"#; "#;
#[test] #[test]
@@ -189,21 +220,11 @@ mod tests {
CodegenMode::Production, CodegenMode::Production,
) )
.unwrap(); .unwrap();
let expect_featureflags_content = EXPECTED_FEATUREFLAGS_COMMON_CONTENT.to_string()
+ r#"
}"#;
let expect_flags_content = EXPECTED_FLAG_COMMON_CONTENT.to_string() let expect_flags_content = EXPECTED_FLAG_COMMON_CONTENT.to_string()
+ r#" + r#"
private static FeatureFlags FEATURE_FLAGS = new FeatureFlagsImpl(); private static FeatureFlags FEATURE_FLAGS = new FeatureFlagsImpl();
}"#; }"#;
let expect_fakefeatureflagsimpl_content = r#"
package com.android.aconfig.test;
public class FakeFeatureFlagsImpl implements FeatureFlags {"#
.to_owned()
+ EXPECTED_METHOD_NOT_IMPL_COMMON_CONTENT
+ r#"
}
"#;
let expect_featureflagsimpl_content = r#" let expect_featureflagsimpl_content = r#"
package com.android.aconfig.test; package com.android.aconfig.test;
import android.provider.DeviceConfig; import android.provider.DeviceConfig;
@@ -241,10 +262,10 @@ mod tests {
let mut file_set = HashMap::from([ let mut file_set = HashMap::from([
("com/android/aconfig/test/Flags.java", expect_flags_content.as_str()), ("com/android/aconfig/test/Flags.java", expect_flags_content.as_str()),
("com/android/aconfig/test/FeatureFlagsImpl.java", expect_featureflagsimpl_content), ("com/android/aconfig/test/FeatureFlagsImpl.java", expect_featureflagsimpl_content),
("com/android/aconfig/test/FeatureFlags.java", expect_featureflags_content.as_str()), ("com/android/aconfig/test/FeatureFlags.java", EXPECTED_FEATUREFLAGS_COMMON_CONTENT),
( (
"com/android/aconfig/test/FakeFeatureFlagsImpl.java", "com/android/aconfig/test/FakeFeatureFlagsImpl.java",
expect_fakefeatureflagsimpl_content.as_str(), EXPECTED_FAKEFEATUREFLAGSIMPL_CONTENT,
), ),
]); ]);
@@ -275,11 +296,7 @@ mod tests {
CodegenMode::Test, CodegenMode::Test,
) )
.unwrap(); .unwrap();
let expect_featureflags_content = EXPECTED_FEATUREFLAGS_COMMON_CONTENT.to_string()
+ r#"
public void setFlag(String flagName, boolean value);
public void resetAll();
}"#;
let expect_flags_content = EXPECTED_FLAG_COMMON_CONTENT.to_string() let expect_flags_content = EXPECTED_FLAG_COMMON_CONTENT.to_string()
+ r#" + r#"
public static void setFeatureFlags(FeatureFlags featureFlags) { public static void setFeatureFlags(FeatureFlags featureFlags) {
@@ -293,94 +310,42 @@ mod tests {
"#; "#;
let expect_featureflagsimpl_content = r#" let expect_featureflagsimpl_content = r#"
package com.android.aconfig.test; package com.android.aconfig.test;
public final class FeatureFlagsImpl implements FeatureFlags {"# public final class FeatureFlagsImpl implements FeatureFlags {
.to_owned()
+ EXPECTED_METHOD_NOT_IMPL_COMMON_CONTENT
+ r#"
@Override
public void setFlag(String flagName, boolean value) {
throw new UnsupportedOperationException(
"Method is not implemented.");
}
@Override
public void resetAll() {
throw new UnsupportedOperationException(
"Method is not implemented.");
}
}
"#;
let expect_fakefeatureflagsimpl_content = r#"
package com.android.aconfig.test;
import static java.util.stream.Collectors.toMap;
import java.util.HashMap;
import java.util.Map;
import java.util.stream.Stream;
public class FakeFeatureFlagsImpl implements FeatureFlags {
@Override @Override
public boolean disabledRo() { public boolean disabledRo() {
return getFlag(Flags.FLAG_DISABLED_RO); throw new UnsupportedOperationException(
"Method is not implemented.");
} }
@Override @Override
public boolean disabledRw() { public boolean disabledRw() {
return getFlag(Flags.FLAG_DISABLED_RW); throw new UnsupportedOperationException(
"Method is not implemented.");
} }
@Override @Override
public boolean enabledFixedRo() { public boolean enabledFixedRo() {
return getFlag(Flags.FLAG_ENABLED_FIXED_RO); throw new UnsupportedOperationException(
"Method is not implemented.");
} }
@Override @Override
public boolean enabledRo() { public boolean enabledRo() {
return getFlag(Flags.FLAG_ENABLED_RO); throw new UnsupportedOperationException(
"Method is not implemented.");
} }
@Override @Override
public boolean enabledRw() { public boolean enabledRw() {
return getFlag(Flags.FLAG_ENABLED_RW); throw new UnsupportedOperationException(
"Method is not implemented.");
} }
@Override
public void setFlag(String flagName, boolean value) {
if (!this.mFlagMap.containsKey(flagName)) {
throw new IllegalArgumentException("no such flag" + flagName);
}
this.mFlagMap.put(flagName, value);
}
@Override
public void resetAll() {
for (Map.Entry entry : mFlagMap.entrySet()) {
entry.setValue(null);
}
}
private boolean getFlag(String flagName) {
Boolean value = this.mFlagMap.get(flagName);
if (value == null) {
throw new IllegalArgumentException(flagName + " is not set");
}
return value;
}
private HashMap<String, Boolean> mFlagMap = Stream.of(
Flags.FLAG_DISABLED_RO,
Flags.FLAG_DISABLED_RW,
Flags.FLAG_ENABLED_FIXED_RO,
Flags.FLAG_ENABLED_RO,
Flags.FLAG_ENABLED_RW
)
.collect(
HashMap::new,
(map, elem) -> map.put(elem, null),
HashMap::putAll
);
} }
"#; "#;
let mut file_set = HashMap::from([ let mut file_set = HashMap::from([
("com/android/aconfig/test/Flags.java", expect_flags_content.as_str()), ("com/android/aconfig/test/Flags.java", expect_flags_content.as_str()),
("com/android/aconfig/test/FeatureFlags.java", expect_featureflags_content.as_str()), ("com/android/aconfig/test/FeatureFlags.java", EXPECTED_FEATUREFLAGS_COMMON_CONTENT),
( ("com/android/aconfig/test/FeatureFlagsImpl.java", expect_featureflagsimpl_content),
"com/android/aconfig/test/FeatureFlagsImpl.java",
expect_featureflagsimpl_content.as_str(),
),
( (
"com/android/aconfig/test/FakeFeatureFlagsImpl.java", "com/android/aconfig/test/FakeFeatureFlagsImpl.java",
expect_fakefeatureflagsimpl_content, EXPECTED_FAKEFEATUREFLAGSIMPL_CONTENT,
), ),
]); ]);

View File

@@ -1,27 +1,26 @@
package {package_name}; package {package_name};
{{ if is_test_mode }}
import static java.util.stream.Collectors.toMap;
import java.util.HashMap; import java.util.HashMap;
import java.util.Map; import java.util.Map;
import java.util.stream.Stream;
public class FakeFeatureFlagsImpl implements FeatureFlags \{ public class FakeFeatureFlagsImpl implements FeatureFlags \{
public FakeFeatureFlagsImpl() \{
resetAll();
}
{{ for item in class_elements}} {{ for item in class_elements}}
@Override @Override
public boolean {item.method_name}() \{ public boolean {item.method_name}() \{
return getFlag(Flags.FLAG_{item.flag_name_constant_suffix}); return getFlag(Flags.FLAG_{item.flag_name_constant_suffix});
} }
{{ endfor}} {{ endfor}}
@Override
public void setFlag(String flagName, boolean value) \{ public void setFlag(String flagName, boolean value) \{
if (!this.mFlagMap.containsKey(flagName)) \{ if (!this.mFlagMap.containsKey(flagName)) \{
throw new IllegalArgumentException("no such flag" + flagName); throw new IllegalArgumentException("no such flag " + flagName);
} }
this.mFlagMap.put(flagName, value); this.mFlagMap.put(flagName, value);
} }
@Override
public void resetAll() \{ public void resetAll() \{
for (Map.Entry entry : mFlagMap.entrySet()) \{ for (Map.Entry entry : mFlagMap.entrySet()) \{
entry.setValue(null); entry.setValue(null);
@@ -36,26 +35,11 @@ public class FakeFeatureFlagsImpl implements FeatureFlags \{
return value; return value;
} }
private HashMap<String, Boolean> mFlagMap = Stream.of( private Map<String, Boolean> mFlagMap = new HashMap<>(
Map.of(
{{-for item in class_elements}} {{-for item in class_elements}}
Flags.FLAG_{item.flag_name_constant_suffix}{{ if not @last }},{{ endif }} Flags.FLAG_{item.flag_name_constant_suffix}, false{{ if not @last }},{{ endif }}
{{ -endfor }} {{ -endfor }}
) )
.collect( );
HashMap::new,
(map, elem) -> map.put(elem, null),
HashMap::putAll
);
} }
{{ else }}
{#- Generate only stub if in prod mode #}
public class FakeFeatureFlagsImpl implements FeatureFlags \{
{{ for item in class_elements}}
@Override
public boolean {item.method_name}() \{
throw new UnsupportedOperationException(
"Method is not implemented.");
}
{{ endfor}}
}
{{ endif }}

View File

@@ -4,10 +4,4 @@ public interface FeatureFlags \{
{{ for item in class_elements}} {{ for item in class_elements}}
boolean {item.method_name}(); boolean {item.method_name}();
{{ endfor }} {{ endfor }}
{{ -if is_test_mode }}
public void setFlag(String flagName, boolean value);
public void resetAll();
{{ -endif }}
} }

View File

@@ -17,7 +17,7 @@ public final class FeatureFlagsImpl implements FeatureFlags \{
return {item.default_value}; return {item.default_value};
{{ endif- }} {{ endif- }}
} }
{{ endfor- }} {{ endfor }}
} }
{{ else }} {{ else }}
{#- Generate only stub if in test mode #} {#- Generate only stub if in test mode #}
@@ -28,17 +28,6 @@ public final class FeatureFlagsImpl implements FeatureFlags \{
throw new UnsupportedOperationException( throw new UnsupportedOperationException(
"Method is not implemented."); "Method is not implemented.");
} }
{{ endfor- }} {{ endfor }}
@Override
public void setFlag(String flagName, boolean value) \{
throw new UnsupportedOperationException(
"Method is not implemented.");
}
@Override
public void resetAll() \{
throw new UnsupportedOperationException(
"Method is not implemented.");
}
} }
{{ endif }} {{ endif }}

View File

@@ -17,13 +17,13 @@ public final class AconfigHostTest {
@Test @Test
public void testThrowsExceptionIfFlagNotSet() { public void testThrowsExceptionIfFlagNotSet() {
assertThrows(NullPointerException.class, () -> Flags.disabledRo()); assertThrows(NullPointerException.class, () -> Flags.disabledRo());
FeatureFlags featureFlags = new FakeFeatureFlagsImpl(); FakeFeatureFlagsImpl featureFlags = new FakeFeatureFlagsImpl();
assertThrows(IllegalArgumentException.class, () -> featureFlags.disabledRo()); assertThrows(IllegalArgumentException.class, () -> featureFlags.disabledRo());
} }
@Test @Test
public void testSetFlagInFakeFeatureFlagsImpl() { public void testSetFlagInFakeFeatureFlagsImpl() {
FeatureFlags featureFlags = new FakeFeatureFlagsImpl(); FakeFeatureFlagsImpl featureFlags = new FakeFeatureFlagsImpl();
featureFlags.setFlag(Flags.FLAG_ENABLED_RW, true); featureFlags.setFlag(Flags.FLAG_ENABLED_RW, true);
assertTrue(featureFlags.enabledRw()); assertTrue(featureFlags.enabledRw());
featureFlags.setFlag(Flags.FLAG_ENABLED_RW, false); featureFlags.setFlag(Flags.FLAG_ENABLED_RW, false);
@@ -39,14 +39,14 @@ public final class AconfigHostTest {
@Test @Test
public void testSetFlagWithRandomName() { public void testSetFlagWithRandomName() {
FeatureFlags featureFlags = new FakeFeatureFlagsImpl(); FakeFeatureFlagsImpl featureFlags = new FakeFeatureFlagsImpl();
assertThrows(IllegalArgumentException.class, assertThrows(IllegalArgumentException.class,
() -> featureFlags.setFlag("Randome_name", true)); () -> featureFlags.setFlag("Randome_name", true));
} }
@Test @Test
public void testResetFlagsInFakeFeatureFlagsImpl() { public void testResetFlagsInFakeFeatureFlagsImpl() {
FeatureFlags featureFlags = new FakeFeatureFlagsImpl(); FakeFeatureFlagsImpl featureFlags = new FakeFeatureFlagsImpl();
featureFlags.setFlag(Flags.FLAG_ENABLED_RO, true); featureFlags.setFlag(Flags.FLAG_ENABLED_RO, true);
assertTrue(featureFlags.enabledRo()); assertTrue(featureFlags.enabledRo());
featureFlags.resetAll(); featureFlags.resetAll();
@@ -59,7 +59,7 @@ public final class AconfigHostTest {
@Test @Test
public void testFlagsSetFeatureFlags() { public void testFlagsSetFeatureFlags() {
FeatureFlags featureFlags = new FakeFeatureFlagsImpl(); FakeFeatureFlagsImpl featureFlags = new FakeFeatureFlagsImpl();
featureFlags.setFlag(Flags.FLAG_ENABLED_RW, true); featureFlags.setFlag(Flags.FLAG_ENABLED_RW, true);
assertThrows(NullPointerException.class, () -> Flags.enabledRw()); assertThrows(NullPointerException.class, () -> Flags.enabledRw());
Flags.setFeatureFlags(featureFlags); Flags.setFeatureFlags(featureFlags);
@@ -69,7 +69,7 @@ public final class AconfigHostTest {
@Test @Test
public void testFlagsUnsetFeatureFlags() { public void testFlagsUnsetFeatureFlags() {
FeatureFlags featureFlags = new FakeFeatureFlagsImpl(); FakeFeatureFlagsImpl featureFlags = new FakeFeatureFlagsImpl();
featureFlags.setFlag(Flags.FLAG_ENABLED_RW, true); featureFlags.setFlag(Flags.FLAG_ENABLED_RW, true);
assertThrows(NullPointerException.class, () -> Flags.enabledRw()); assertThrows(NullPointerException.class, () -> Flags.enabledRw());
Flags.setFeatureFlags(featureFlags); Flags.setFeatureFlags(featureFlags);

View File

@@ -59,8 +59,9 @@ public final class AconfigTest {
} }
@Test @Test
public void testFakeFeatureFlagsImplNotImpl() { public void testFakeFeatureFlagsImplImpled() {
FeatureFlags featureFlags = new FakeFeatureFlagsImpl(); FakeFeatureFlagsImpl fakeFeatureFlags = new FakeFeatureFlagsImpl();
assertThrows(UnsupportedOperationException.class, () -> featureFlags.enabledRw()); fakeFeatureFlags.setFlag(FLAG_ENABLED_RW, false);
assertFalse(fakeFeatureFlags.enabledRw());
} }
} }