Skip to content

Commit 0a9a07f

Browse files
ludochgae-java-bot
authored andcommitted
Refactor AppEngineWebXmlInitialParse to allow mocking environment variables and add a test.
New Test Permutations We added new test cases to AppEngineWebXmlInitialParseTest.java to ensure full coverage of Runtime, Jetty, and Jakarta EE version combinations: testJava17WithExperimentEnableJetty12: Verifies that when the environment variable EXPERIMENT_ENABLE_JETTY12_FOR_JAVA is set to true for the java17 runtime (simulated via envProvider), the configuration correctly defaults to appengine.use.EE8=true (Jetty 12.0 in EE8 mode) instead of the standard Jetty 9.4 legacy mode. testHttpConnectorExperiment: Verifies that when EXPERIMENT_ENABLE_HTTP_CONNECTOR_FOR_JAVA is set to true, the system properties appengine.use.HttpConnector and appengine.ignore.cancelerror are automatically enabled. testJava17WithJetty121: Verifies that for the java17 runtime, enabling appengine.use.jetty121 alone does not inadvertently enable Jakarta EE 8, 10, or 11. It confirms that the configuration remains valid with only the Jetty 12.1 flag set. testJava17WithEE8AndJetty121: Verifies that for java17, explicitly enabling both appengine.use.EE8 and appengine.use.jetty121 correctly sets both properties to true, supporting the legacy EE8 environment on the newer Jetty infrastructure. testJava21WithEE10Explicit: Confirms that explicitly setting appengine.use.EE10 for java21 (which is the default) works as expected, ensuring EE10 is true and jetty121 remains false (mapping to Jetty 12.0). testJava21WithEE8AndJetty121: Verifies that for java21, combining appengine.use.EE8 with appengine.use.jetty121 correctly enables both flags. Environment Variable Emulation To reliably test logic dependent on environment variables (such as EXPERIMENT_ENABLE_JETTY12_FOR_JAVA or EXPERIMENT_ENABLE_HTTP_CONNECTOR_FOR_JAVA) without modifying the actual system environment or affecting other tests: The AppEngineWebXmlInitialParse class now accepts a custom envProvider (a UnaryOperator<String>) via the package-private setEnvProvider method. By default, this provider delegates to System::getenv. In tests, we inject a lambda function (e.g., key -> "true") to simulate specific environment variables being set. This allows us to verify that the parser correctly activates experimental features or defaults based on the environment. testSystemPropertyOverrideRuntime: This test sets the GAE_RUNTIME system property to "java21" (while the XML specifies "java17") and verifies that the runtime logic correctly switches to "java21" behavior (defaulting to EE10). This kills the mutant where runtimeId re-fetching from system properties (line 178) was removed, as the test would fail if runtimeId remained "java17". testSystemPropertyOverrideRuntimeWithWhitespace: This test sets GAE_RUNTIME to " java21 " (with whitespace) and asserts that the code correctly handles it as "java21" (setting EE10 to true). This kills the mutant where the trim() call (lines 179-181) was removed, as the test would fail if the whitespace prevented the "java21" logic from triggering. testLogEE8: This test captures the logs generated by AppEngineWebXmlInitialParse and asserts that "appengine.use.EE8=true" is logged when EE8 is enabled. This kills the mutant where the logging logic for EE8 (lines 249-251) was removed. PiperOrigin-RevId: 862787419 Change-Id: I1bc08a2ee06faa1018f0f225e8ca90f358cc094d
1 parent e758d24 commit 0a9a07f

File tree

2 files changed

+556
-4
lines changed

2 files changed

+556
-4
lines changed

appengine_init/src/main/java/com/google/appengine/init/AppEngineWebXmlInitialParse.java

Lines changed: 43 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@
2020
import java.io.InputStream;
2121
import java.util.Objects;
2222
import java.util.Properties;
23+
import java.util.function.UnaryOperator;
2324
import java.util.logging.Level;
2425
import java.util.logging.Logger;
2526
import javax.xml.namespace.QName;
@@ -34,6 +35,10 @@ public final class AppEngineWebXmlInitialParse {
3435

3536
private static final Logger logger =
3637
Logger.getLogger(AppEngineWebXmlInitialParse.class.getName());
38+
39+
/** Provider for environment variables, allowing for substitution in tests. */
40+
private UnaryOperator<String> envProvider = System::getenv;
41+
3742
private String runtimeId = "";
3843
private final String appEngineWebXmlFile;
3944

@@ -128,7 +133,7 @@ public final class AppEngineWebXmlInitialParse {
128133
public void handleRuntimeProperties() {
129134

130135
// See if the Mendel experiment to enable HttpConnector is set automatically via env var:
131-
if (Objects.equals(System.getenv("EXPERIMENT_ENABLE_HTTP_CONNECTOR_FOR_JAVA"), "true")) {
136+
if (Objects.equals(envProvider.apply("EXPERIMENT_ENABLE_HTTP_CONNECTOR_FOR_JAVA"), "true")) {
132137
System.setProperty("appengine.ignore.cancelerror", "true");
133138
System.setProperty("appengine.use.HttpConnector", "true");
134139
}
@@ -144,7 +149,7 @@ public void handleRuntimeProperties() {
144149
&& event.asStartElement().getName().getLocalPart().equals(RUNTIME)) {
145150
XMLEvent runtime = reader.nextEvent();
146151
if (runtime.isCharacters()) {
147-
runtimeId = runtime.asCharacters().getData();
152+
runtimeId = runtime.asCharacters().getData().trim();
148153
appEngineWebXmlProperties.setProperty("GAE_RUNTIME", runtimeId);
149154
}
150155
}
@@ -170,7 +175,10 @@ public void handleRuntimeProperties() {
170175
}
171176
}
172177
// reset runtimeId to the value possibly overridden by system properties
173-
runtimeId = systemProps.getProperty("GAE_RUNTIME");
178+
runtimeId = System.getProperty("GAE_RUNTIME");
179+
if (runtimeId != null) {
180+
runtimeId = runtimeId.trim();
181+
}
174182

175183
if ((Objects.equals(runtimeId, "java17") || Objects.equals(runtimeId, "java21"))
176184
&& Boolean.parseBoolean(System.getProperty("appengine.use.EE10", "false"))
@@ -208,7 +216,7 @@ public void handleRuntimeProperties() {
208216
System.setProperty(
209217
"appengine.use.EE8",
210218
String.valueOf(
211-
Objects.equals(System.getenv("EXPERIMENT_ENABLE_JETTY12_FOR_JAVA"), "true")));
219+
Objects.equals(envProvider.apply("EXPERIMENT_ENABLE_JETTY12_FOR_JAVA"), "true")));
212220
} else if (Objects.equals(runtimeId, "java21")) {
213221
if (Boolean.parseBoolean(System.getProperty("appengine.use.jetty121", "false"))) {
214222
System.setProperty("appengine.use.EE11", "true");
@@ -233,6 +241,33 @@ public void handleRuntimeProperties() {
233241
if (Objects.equals(runtimeId, "java25") && Boolean.getBoolean("appengine.use.EE10")) {
234242
throw new IllegalArgumentException("appengine.use.EE10 is not supported in Jetty121");
235243
}
244+
245+
// Log the runtime configuration so we can see it in the app logs.
246+
StringBuilder configLog =
247+
new StringBuilder("AppEngine runtime configuration: runtimeId=").append(runtimeId);
248+
if (Objects.equals(envProvider.apply("EXPERIMENT_ENABLE_JETTY12_FOR_JAVA"), "true")) {
249+
configLog.append(", with Jetty 12");
250+
}
251+
if (Objects.equals(envProvider.apply("EXPERIMENT_ENABLE_HTTP_CONNECTOR_FOR_JAVA"), "true")) {
252+
configLog.append(", with HTTP Connector");
253+
}
254+
int initialLength = configLog.length();
255+
if (Boolean.getBoolean("appengine.use.EE8")) {
256+
configLog.append(", appengine.use.EE8=true");
257+
}
258+
if (Boolean.getBoolean("appengine.use.EE10")) {
259+
configLog.append(", appengine.use.EE10=true");
260+
}
261+
if (Boolean.getBoolean("appengine.use.EE11")) {
262+
configLog.append(", appengine.use.EE11=true");
263+
}
264+
if (Boolean.getBoolean("appengine.use.jetty121")) {
265+
configLog.append(", appengine.use.jetty121=true");
266+
}
267+
if (configLog.length() == initialLength) {
268+
configLog.append(" no extra flag set");
269+
}
270+
logger.info(configLog.toString());
236271
}
237272

238273
/**
@@ -283,4 +318,8 @@ public AppEngineWebXmlInitialParse(String file) {
283318
new Object[] {BUILD_TIMESTAMP, GIT_HASH, BUILD_VERSION});
284319
}
285320
}
321+
322+
void setEnvProvider(UnaryOperator<String> envProvider) {
323+
this.envProvider = envProvider;
324+
}
286325
}

0 commit comments

Comments
 (0)