diff --git a/openam-audit/openam-audit-context/src/test/java/org/forgerock/openam/audit/AuditContextFilterTest.java b/openam-audit/openam-audit-context/src/test/java/org/forgerock/openam/audit/AuditContextFilterTest.java index ea82d00a56..a488da3c5f 100644 --- a/openam-audit/openam-audit-context/src/test/java/org/forgerock/openam/audit/AuditContextFilterTest.java +++ b/openam-audit/openam-audit-context/src/test/java/org/forgerock/openam/audit/AuditContextFilterTest.java @@ -12,7 +12,7 @@ * information: "Portions copyright [year] [name of copyright owner]". * * Copyright 2015 ForgeRock AS. - * Portions Copyrighted 2025 3A Systems LLC. + * Portions Copyrighted 2025-2026 3A Systems LLC. */ package org.forgerock.openam.audit; @@ -21,11 +21,8 @@ import static org.mockito.Mockito.doAnswer; import static org.mockito.Mockito.when; -import java.lang.annotation.Annotation; import java.util.Collections; -import java.util.Set; -import org.forgerock.guice.core.GuiceModuleLoader; import org.forgerock.guice.core.InjectorConfiguration; import org.forgerock.http.header.TransactionIdHeader; import org.forgerock.openam.audit.context.AuditContextFilter; @@ -35,8 +32,9 @@ import org.mockito.MockitoAnnotations; import org.mockito.invocation.InvocationOnMock; import org.mockito.stubbing.Answer; -import org.testng.annotations.BeforeClass; +import org.testng.annotations.AfterMethod; import org.testng.annotations.BeforeMethod; +import org.testng.annotations.BeforeSuite; import org.testng.annotations.Test; import jakarta.servlet.FilterChain; @@ -44,7 +42,6 @@ import jakarta.servlet.http.HttpServletResponse; import com.google.inject.AbstractModule; -import com.google.inject.Module; /** * @since 13.0.0 @@ -55,14 +52,23 @@ public class AuditContextFilterTest { @Mock private HttpServletResponse httpServletResponse; @Mock private FilterChain filterChain; - @BeforeClass - public void setUpSuite() throws Exception { - InjectorConfiguration.setGuiceModuleLoader(new GuiceModuleLoader() { - @Override - public Set> getGuiceModules(Class aClass) { - return Collections.>singleton(TestGuiceModule.class); - } - }); + /** + * {@link AuditContextFilter} asks {@link org.forgerock.guice.core.InjectorHolder} for a + * {@link TransactionIdConfiguration}, which no module the default loader finds on this classpath binds. This class + * is not a {@code GuiceTestCase}, so no per-test injector is registered: the binding from {@link TestGuiceModule} + * has to be in the holder's own injector, the first injector of the JVM. The holder builds that injector from the + * module loader in place at that moment and never consults the loader again, so ask for {@link TestGuiceModule} + * before any test of the suite runs: a {@code @BeforeClass} comes too late whenever surefire happens to run another + * class that touches the holder ahead of this one. + * + * Two limits remain. TestNG creates the instances of all test classes before any {@code @BeforeSuite} method runs, + * so a constructor or field initializer that reaches the holder still goes first. And the loader is set for the + * whole JVM: every other class in it that reaches the holder sees this binding, and a second class that sets a + * different loader from its own {@code @BeforeSuite} would make the winner depend on class order again. + */ + @BeforeSuite(alwaysRun = true) + public void setupGuiceModuleLoader() { + InjectorConfiguration.setGuiceModuleLoader(moduleAnnotation -> Collections.singleton(TestGuiceModule.class)); } @BeforeMethod @@ -70,6 +76,15 @@ public void setupTests() { MockitoAnnotations.initMocks(this); } + /** + * The binding from {@link TestGuiceModule} serves every class in the JVM, so put the flag the tests change back to + * its default. + */ + @AfterMethod(alwaysRun = true) + public void resetTrustHeader() { + TransactionIdConfigurationImpl.trustHeader = true; + } + @Test public void shouldSetTransactionIdFromHttpHeaderAndClearRequestContextWhenFinished() throws Exception { // Given diff --git a/openam-scripting/src/test/java/org/forgerock/openam/scripting/EmptyGuiceModuleLoaderListener.java b/openam-scripting/src/test/java/org/forgerock/openam/scripting/EmptyGuiceModuleLoaderListener.java new file mode 100644 index 0000000000..21eefbdd2f --- /dev/null +++ b/openam-scripting/src/test/java/org/forgerock/openam/scripting/EmptyGuiceModuleLoaderListener.java @@ -0,0 +1,48 @@ +/* + * The contents of this file are subject to the terms of the Common Development and + * Distribution License (the License). You may not use this file except in compliance with the + * License. + * + * You can obtain a copy of the License at legal/CDDLv1.0.txt. See the License for the + * specific language governing permission and limitations under the License. + * + * When distributing Covered Software, include this CDDL Header Notice in each file and include + * the License file at legal/CDDLv1.0.txt. If applicable, add the following below the CDDL + * Header, with the fields enclosed by brackets [] replaced by your own identifying + * information: "Portions copyright [year] [name of copyright owner]". + * + * Copyright 2026 3A Systems, LLC. + */ + +package org.forgerock.openam.scripting; + +import java.util.Collections; + +import org.forgerock.guice.core.InjectorConfiguration; +import org.forgerock.guice.core.InjectorHolder; +import org.testng.IExecutionListener; + +/** + * Has {@link InjectorHolder} build its injector from no modules in every TestNG run of this module. + * + *

The {@code GuiceTestCase} subclasses here ask the holder for its injector before each test, and then register an + * injector of their own built from {@code @GuiceModules}. The holder builds the first injector of the JVM from the + * module loader in place at that moment and never consults the loader again. The default loader collects every Guice + * module on the test classpath, Guice cannot build an injector from those, and the holder class then stays broken for + * every later test in the same JVM. So the empty loader has to be in place before any class reaches the holder.

+ * + *

TestNG loads this listener through {@code META-INF/services/org.testng.ITestNGListener} and calls + * {@link #onExecutionStart()} before it creates any test instance. That covers constructors and field initializers, + * and every run of the module, whichever classes it includes and however surefire forks it.

+ */ +public class EmptyGuiceModuleLoaderListener implements IExecutionListener { + + @Override + public void onExecutionStart() { + InjectorConfiguration.setGuiceModuleLoader(moduleAnnotation -> Collections.emptySet()); + } + + @Override + public void onExecutionFinish() { + } +} diff --git a/openam-scripting/src/test/java/org/forgerock/openam/scripting/GroovyAstTransformEscapeTest.java b/openam-scripting/src/test/java/org/forgerock/openam/scripting/GroovyAstTransformEscapeTest.java index 29cd6ecddd..8a8d89e487 100644 --- a/openam-scripting/src/test/java/org/forgerock/openam/scripting/GroovyAstTransformEscapeTest.java +++ b/openam-scripting/src/test/java/org/forgerock/openam/scripting/GroovyAstTransformEscapeTest.java @@ -16,21 +16,15 @@ package org.forgerock.openam.scripting; -import com.google.inject.Module; -import org.forgerock.guice.core.GuiceModuleLoader; import org.forgerock.guice.core.GuiceModules; import org.forgerock.guice.core.GuiceTestCase; -import org.forgerock.guice.core.InjectorConfiguration; import org.forgerock.openam.scripting.guice.ScriptingGuiceModule; import org.forgerock.openam.shared.guice.SharedGuiceModule; import org.testng.annotations.AfterMethod; import org.testng.annotations.BeforeMethod; import org.testng.annotations.Test; -import java.lang.annotation.Annotation; -import java.util.HashSet; import java.util.List; -import java.util.Set; import static org.assertj.core.api.Assertions.assertThat; @@ -47,19 +41,6 @@ public class GroovyAstTransformEscapeTest extends GuiceTestCase { private static final String CANARY = "openam.test.ghsa_5hgj_6j53_p729.executed"; @BeforeMethod - @Override - public void setupGuiceModules() throws Exception { - // Mirror GroovyValidatorTest: don't let other Guice modules on the classpath load. - InjectorConfiguration.setGuiceModuleLoader(new GuiceModuleLoader() { - @Override - public Set> getGuiceModules(Class aClass) { - return new HashSet<>(); - } - }); - super.setupGuiceModules(); - System.clearProperty(CANARY); - } - @AfterMethod public void clearCanary() { System.clearProperty(CANARY); diff --git a/openam-scripting/src/test/java/org/forgerock/openam/scripting/GroovyValidatorTest.java b/openam-scripting/src/test/java/org/forgerock/openam/scripting/GroovyValidatorTest.java index 24fa355514..bf4307e2a4 100644 --- a/openam-scripting/src/test/java/org/forgerock/openam/scripting/GroovyValidatorTest.java +++ b/openam-scripting/src/test/java/org/forgerock/openam/scripting/GroovyValidatorTest.java @@ -12,25 +12,18 @@ * information: "Portions copyright [year] [name of copyright owner]". * * Copyright 2014-2015 ForgeRock AS. + * Portions Copyright 2026 3A Systems, LLC. */ package org.forgerock.openam.scripting; -import com.google.inject.Module; -import org.forgerock.guice.core.GuiceModuleLoader; import org.forgerock.guice.core.GuiceModules; import org.forgerock.guice.core.GuiceTestCase; -import org.forgerock.guice.core.InjectorConfiguration; -import org.forgerock.guice.core.InjectorHolder; import org.forgerock.openam.scripting.guice.ScriptingGuiceModule; import org.forgerock.openam.shared.guice.SharedGuiceModule; -import org.testng.annotations.BeforeMethod; import org.testng.annotations.Test; -import java.lang.annotation.Annotation; -import java.util.HashSet; import java.util.List; -import java.util.Set; import static org.assertj.core.api.Assertions.assertThat; @@ -40,20 +33,6 @@ @GuiceModules({SharedGuiceModule.class, ScriptingGuiceModule.class}) public class GroovyValidatorTest extends GuiceTestCase { - @BeforeMethod - @Override - public void setupGuiceModules() throws Exception { - //This ensures that the other Guice modules on the classpath don't get - //loaded as Guice will balk. - InjectorConfiguration.setGuiceModuleLoader(new GuiceModuleLoader() { - @Override - public Set> getGuiceModules(Class aClass) { - return new HashSet<>(); - } - }); - super.setupGuiceModules(); - } - @Test(expectedExceptions = NullPointerException.class) public void shouldRejectNullScript() { SupportedScriptingLanguage.GROOVY.getScriptValidator().validateScript(null); diff --git a/openam-scripting/src/test/java/org/forgerock/openam/scripting/JavaScriptValidatorTest.java b/openam-scripting/src/test/java/org/forgerock/openam/scripting/JavaScriptValidatorTest.java index cbfbb792c7..c7b0afc176 100644 --- a/openam-scripting/src/test/java/org/forgerock/openam/scripting/JavaScriptValidatorTest.java +++ b/openam-scripting/src/test/java/org/forgerock/openam/scripting/JavaScriptValidatorTest.java @@ -12,44 +12,24 @@ * information: "Portions copyright [year] [name of copyright owner]". * * Copyright 2014-2015 ForgeRock AS. + * Portions Copyright 2026 3A Systems, LLC. */ package org.forgerock.openam.scripting; -import com.google.inject.Module; -import org.forgerock.guice.core.GuiceModuleLoader; import org.forgerock.guice.core.GuiceModules; import org.forgerock.guice.core.GuiceTestCase; -import org.forgerock.guice.core.InjectorConfiguration; import org.forgerock.openam.scripting.guice.ScriptingGuiceModule; import org.forgerock.openam.shared.guice.SharedGuiceModule; -import org.testng.annotations.BeforeMethod; import org.testng.annotations.Test; -import java.lang.annotation.Annotation; -import java.util.HashSet; import java.util.List; -import java.util.Set; import static org.assertj.core.api.Assertions.assertThat; @GuiceModules({SharedGuiceModule.class, ScriptingGuiceModule.class}) public class JavaScriptValidatorTest extends GuiceTestCase { - @BeforeMethod - @Override - public void setupGuiceModules() throws Exception { - //This ensures that the other Guice modules on the classpath don't get - //loaded as Guice will balk. - InjectorConfiguration.setGuiceModuleLoader(new GuiceModuleLoader() { - @Override - public Set> getGuiceModules(Class aClass) { - return new HashSet<>(); - } - }); - super.setupGuiceModules(); - } - @Test(expectedExceptions = NullPointerException.class) public void shouldRejectNullScript() { SupportedScriptingLanguage.JAVASCRIPT.getScriptValidator().validateScript(null); diff --git a/openam-scripting/src/test/resources/META-INF/services/org.testng.ITestNGListener b/openam-scripting/src/test/resources/META-INF/services/org.testng.ITestNGListener new file mode 100644 index 0000000000..d1e4472465 --- /dev/null +++ b/openam-scripting/src/test/resources/META-INF/services/org.testng.ITestNGListener @@ -0,0 +1,16 @@ +# +# The contents of this file are subject to the terms of the Common Development and +# Distribution License (the License). You may not use this file except in compliance with the +# License. +# +# You can obtain a copy of the License at legal/CDDLv1.0.txt. See the License for the +# specific language governing permission and limitations under the License. +# +# When distributing Covered Software, include this CDDL Header Notice in each file and include +# the License file at legal/CDDLv1.0.txt. If applicable, add the following below the CDDL +# Header, with the fields enclosed by brackets [] replaced by your own identifying +# information: "Portions copyright [year] [name of copyright owner]". +# +# Copyright 2026 3A Systems, LLC. +# +org.forgerock.openam.scripting.EmptyGuiceModuleLoaderListener