[java-plugin-shibd] 02/02: Getting flow testing framework in place.

Scott Cantor cantor.2 at osu.edu
Tue Jul 2 16:53:23 UTC 2024


This is an automated email from the git hooks/post-receive script.

scantor pushed a commit to branch main
in repository java-plugin-shibd.

View the commit online:
http://git.shibboleth.net/view/?p=java-plugin-shibd.git;a=commit;h=82fcbdb9053341e8ee30b62a876528c17e2b1206

commit 82fcbdb9053341e8ee30b62a876528c17e2b1206
Author: Scott Cantor <cantor.2 at osu.edu>
AuthorDate: Tue Jul 2 12:53:18 2024 -0400

    Getting flow testing framework in place.
---
 sp-conf-impl/pom.xml                               |  88 ++++++++++++
 .../shibboleth/sp/flows/AbstractSPFlowTest.java    | 159 +++++++++++++++++++++
 .../java/net/shibboleth/sp/flows/PingFlowTest.java |  49 +++++++
 .../java/net/shibboleth/sp/flows/package-info.java |  18 +++
 .../net/shibboleth/idp/module/conf/global.xml      |  72 ++++++++++
 5 files changed, 386 insertions(+)

diff --git a/sp-conf-impl/pom.xml b/sp-conf-impl/pom.xml
index 05a27ad..0c8c06e 100644
--- a/sp-conf-impl/pom.xml
+++ b/sp-conf-impl/pom.xml
@@ -20,6 +20,12 @@
     </properties>
         
     <dependencies>
+        <dependency>
+            <groupId>${project.groupId}</groupId>
+            <artifactId>sp-server-api</artifactId>
+            <version>${project.version}</version>
+            <scope>runtime</scope>
+        </dependency>
         <dependency>
             <groupId>${project.groupId}</groupId>
             <artifactId>sp-server-impl</artifactId>
@@ -108,6 +114,11 @@
             <artifactId>shib-networking-spring</artifactId>
             <scope>provided</scope>
         </dependency>
+        <dependency>
+            <groupId>${shib-shared.groupId}</groupId>
+            <artifactId>shib-security-spring</artifactId>
+            <scope>provided</scope>
+        </dependency>
         <dependency>
             <groupId>${shib-shared.groupId}</groupId>
             <artifactId>shib-spring</artifactId>
@@ -118,6 +129,12 @@
             <artifactId>shib-velocity-spring</artifactId>
             <scope>provided</scope>
         </dependency>
+    
+        <dependency>
+            <groupId>jakarta.servlet</groupId>
+            <artifactId>jakarta.servlet-api</artifactId>
+            <scope>provided</scope>
+        </dependency>
         
         <dependency>
             <groupId>com.google.guava</groupId>
@@ -137,6 +154,77 @@
         </dependency>
     
         <!-- Test Dependencies -->
+        <dependency>
+            <groupId>${idp.groupId}</groupId>
+            <artifactId>idp-conf-impl</artifactId>
+            <scope>test</scope>
+        </dependency>
+        <dependency>
+            <groupId>${idp.groupId}</groupId>
+            <artifactId>idp-conf-impl</artifactId>
+            <version>${idp.version}</version>
+            <type>test-jar</type>
+            <scope>test</scope>
+        </dependency>
+        <dependency>
+            <groupId>${idp.groupId}</groupId>
+            <artifactId>idp-spring</artifactId>
+            <scope>test</scope>
+        </dependency>
+
+        <dependency>
+            <groupId>${shib-shared.groupId}</groupId>
+            <artifactId>shib-testing</artifactId>
+            <scope>test</scope>
+        </dependency>
+
+        <dependency>
+            <groupId>${spring-webflow.groupId}</groupId>
+            <artifactId>spring-webflow</artifactId>
+            <scope>test</scope>
+        </dependency>
+        <dependency>
+            <groupId>${spring-webflow.groupId}</groupId>
+            <artifactId>spring-binding</artifactId>
+            <scope>test</scope>
+        </dependency>
+
+        <dependency>
+            <groupId>${spring.groupId}</groupId>
+            <artifactId>spring-beans</artifactId>
+            <scope>test</scope>
+        </dependency>
+        <dependency>
+            <groupId>${spring.groupId}</groupId>
+            <artifactId>spring-context</artifactId>
+            <scope>test</scope>
+        </dependency>
+        <dependency>
+            <groupId>${spring.groupId}</groupId>
+            <artifactId>spring-expression</artifactId>
+            <scope>test</scope>
+        </dependency>
+        <dependency>
+            <groupId>${spring.groupId}</groupId>
+            <artifactId>spring-test</artifactId>
+            <scope>test</scope>
+        </dependency>
+        <dependency>
+            <groupId>${spring.groupId}</groupId>
+            <artifactId>spring-web</artifactId>
+            <scope>test</scope>
+        </dependency>
+        <dependency>
+            <groupId>${spring.groupId}</groupId>
+            <artifactId>spring-webmvc</artifactId>
+            <scope>test</scope>
+        </dependency>
+
+        <dependency>
+            <groupId>org.codehaus.janino</groupId>
+            <artifactId>janino</artifactId>
+            <scope>test</scope>
+        </dependency>
     </dependencies>
 
     <build>
diff --git a/sp-conf-impl/src/test/java/net/shibboleth/sp/flows/AbstractSPFlowTest.java b/sp-conf-impl/src/test/java/net/shibboleth/sp/flows/AbstractSPFlowTest.java
new file mode 100644
index 0000000..28b5a00
--- /dev/null
+++ b/sp-conf-impl/src/test/java/net/shibboleth/sp/flows/AbstractSPFlowTest.java
@@ -0,0 +1,159 @@
+/*
+ * 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 net.shibboleth.sp.flows;
+
+import java.io.ByteArrayInputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.util.Map;
+
+import javax.annotation.Nonnull;
+
+import org.apache.commons.codec.binary.Base64;
+import org.opensaml.profile.context.ProfileRequestContext;
+import org.opensaml.storage.StorageService;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.beans.factory.annotation.Qualifier;
+import org.springframework.mock.web.MockHttpServletRequest;
+import org.springframework.mock.web.MockHttpServletResponse;
+import org.springframework.test.context.ContextConfiguration;
+import org.springframework.webflow.executor.FlowExecutionResult;
+import org.springframework.webflow.test.MockExternalContext;
+import org.testng.Assert;
+import org.testng.annotations.BeforeMethod;
+
+import net.shibboleth.idp.test.flows.AbstractFlowTest;
+import net.shibboleth.shared.security.DataSealer;
+import net.shibboleth.shared.servlet.impl.HttpServletRequestResponseContext;
+import net.shibboleth.sp.context.AgentRequestContext;
+import net.shibboleth.sp.ddf.DDF;
+
+/**
+ * Abstract unit test class for SP flows.
+ */
+ at ContextConfiguration(locations = { "classpath*:/META-INF/net.shibboleth.idp/postconfig.xml",})
+ at SuppressWarnings("null")
+public abstract class AbstractSPFlowTest extends AbstractFlowTest {
+    
+    /** End state ID. */
+    @Nonnull public static final String END_STATE_ID = "end";
+
+    /** Event member of output.. */
+    @Nonnull public static final String EVENT_MEMBER_NAME = "event";
+
+    protected String flowId;
+    
+    protected String endStateId;
+    
+    @Autowired
+    @Qualifier("shibboleth.DataSealer")
+    private DataSealer dataSealer;
+
+    @Autowired
+    @Qualifier("shibboleth.StorageService")
+    StorageService storageService;
+
+    protected AbstractSPFlowTest(final String id) {
+        this(id, END_STATE_ID);
+    }
+
+    protected AbstractSPFlowTest(final String id, final String endId) {
+        flowId = id;
+        endStateId = endId == null ? END_STATE_ID : endId;
+    }
+
+    /**
+     * Initialize mock request, response, and external context. Overrides to remove authorization header.
+     */
+    @Override
+    @BeforeMethod public void initializeMocks() {
+        overrideEndStateOutput(flowId, endStateId);
+
+        request = new MockHttpServletRequest();
+        response = new MockHttpServletResponse();
+        externalContext = new MockExternalContext();
+        externalContext.setNativeRequest(request);
+        externalContext.setNativeResponse(response);
+    }
+    
+    /**
+     * Load the mock request/response objects.
+     */
+    @Override
+    @BeforeMethod public void initializeThreadLocals() {
+        HttpServletRequestResponseContext.loadCurrent(request, response);
+    }
+    
+    @Nonnull protected DataSealer getDataSealer() {
+        assert dataSealer != null;
+        return dataSealer;
+    }
+        
+    protected void setJsonRequest(final String method, final String body) {
+        setRequest(method, body, "application/json");
+    }
+    
+    protected void setHttpFormRequest(final String method, final Map<String, String> parameters) {
+        setHttpFormRequest(request, method, parameters);
+    }
+
+    protected static void setHttpFormRequest(final MockHttpServletRequest request, final String method, final Map<String, String> parameters) {
+        setRequest(request, method, "", "application/x-www-form-urlencoded");
+        request.setParameters(parameters);
+    }
+
+    protected void setBasicAuth(final String username, final String password) {
+        request.removeHeader("Authorization");
+        request.addHeader("Authorization",
+                "Basic " + new String(Base64.encodeBase64(new String(username + ":" + password).getBytes())));
+    }
+    
+    protected void setRequest(final String method, final String body, final String contentType) {
+        setRequest(request, method, body, contentType);
+    }
+
+    protected static void setRequest(final MockHttpServletRequest request, final String method, final String body, final String contentType) {
+        request.setMethod(method);
+        request.setContentType(contentType);
+        request.setContent(body.getBytes());   
+    }
+
+    /**
+     * Checks that an output {@link DDF} was prepared, packaged in the response, and contains an event
+     * that matches the specified value.
+     * 
+     * @param result flow result
+     * @param eventId value to check for
+     * 
+     * @throws IOException on error 
+     */
+    protected void assertOutputMessageEvent(@Nonnull final FlowExecutionResult result, @Nonnull final String eventId)
+            throws IOException {
+        final ProfileRequestContext prc = retrieveProfileRequestContext(result);
+        final AgentRequestContext arc = prc.ensureSubcontext(AgentRequestContext.class);
+        final DDF output = arc.getOutput();
+        assert output != null;
+        Assert.assertTrue(output.isstruct());
+        Assert.assertEquals(output.getmember(EVENT_MEMBER_NAME).string(), eventId);
+        
+        Assert.assertEquals(response.getContentType(), "text/plain");
+        try (final InputStream in = new ByteArrayInputStream(response.getContentAsByteArray())) {
+            final DDF body = DDF.deserialize(in);
+            Assert.assertTrue(body.isstruct());
+            Assert.assertEquals(body.getmember(EVENT_MEMBER_NAME).string(), eventId);
+        }
+    }
+    
+}
\ No newline at end of file
diff --git a/sp-conf-impl/src/test/java/net/shibboleth/sp/flows/PingFlowTest.java b/sp-conf-impl/src/test/java/net/shibboleth/sp/flows/PingFlowTest.java
new file mode 100644
index 0000000..6d9d603
--- /dev/null
+++ b/sp-conf-impl/src/test/java/net/shibboleth/sp/flows/PingFlowTest.java
@@ -0,0 +1,49 @@
+/*
+ * 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 net.shibboleth.sp.flows;
+
+import java.io.IOException;
+
+import org.springframework.webflow.executor.FlowExecutionResult;
+import org.testng.annotations.Test;
+
+import net.shibboleth.idp.authn.AuthnEventIds;
+
+/**
+ * Unit test for the OP discovery flow.
+ */
+public class PingFlowTest extends AbstractSPFlowTest {
+    
+    /** Flow ID. */
+    public static final String FLOW_ID = "sp/ping";
+
+    protected PingFlowTest() {
+        super(FLOW_ID);
+    }
+    
+    /**
+     * Ping flow test.
+     * 
+     * @throws IOException
+     */
+    @Test
+    public void testUnauhenticated() throws IOException {
+        final FlowExecutionResult result = flowExecutor.launchExecution(FLOW_ID, null, externalContext);
+        assertFlowExecutionResult(result, FLOW_ID);
+        assertFlowExecutionOutcome(result.getOutcome());
+        assertOutputMessageEvent(result, AuthnEventIds.NO_CREDENTIALS);
+    }
+
+}
\ No newline at end of file
diff --git a/sp-conf-impl/src/test/java/net/shibboleth/sp/flows/package-info.java b/sp-conf-impl/src/test/java/net/shibboleth/sp/flows/package-info.java
new file mode 100644
index 0000000..ea8b2ad
--- /dev/null
+++ b/sp-conf-impl/src/test/java/net/shibboleth/sp/flows/package-info.java
@@ -0,0 +1,18 @@
+/*
+ * 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.
+ */
+
+/**
+ * Unit tests for SP flows.
+ */
+package net.shibboleth.sp.flows;
\ No newline at end of file
diff --git a/sp-conf-impl/src/test/resources/net/shibboleth/idp/module/conf/global.xml b/sp-conf-impl/src/test/resources/net/shibboleth/idp/module/conf/global.xml
new file mode 100644
index 0000000..cfe3329
--- /dev/null
+++ b/sp-conf-impl/src/test/resources/net/shibboleth/idp/module/conf/global.xml
@@ -0,0 +1,72 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<beans xmlns="http://www.springframework.org/schema/beans"
+       xmlns:context="http://www.springframework.org/schema/context"
+       xmlns:util="http://www.springframework.org/schema/util"
+       xmlns:jdbc="http://www.springframework.org/schema/jdbc"
+       xmlns:p="http://www.springframework.org/schema/p"
+       xmlns:c="http://www.springframework.org/schema/c"
+       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+       xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
+                           http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd
+                           http://www.springframework.org/schema/jdbc http://www.springframework.org/schema/jdbc/spring-jdbc.xsd
+                           http://www.springframework.org/schema/util http://www.springframework.org/schema/util/spring-util.xsd"
+                           
+       default-init-method="initialize"
+       default-destroy-method="destroy">
+
+    <!-- Use this file to define any custom beans needed globally. -->
+
+    <!--
+    Algorithm include/exclude sets that override or merge with library defaults. Normally you can leave these
+    empty or commented and use the system defaults, but you can override those defaults using these beans.
+    Each <value> element is an algorithm URI; you can also use <util:constant> elements in place of literal values.
+    -->
+    
+    <!--
+    <util:set id="shibboleth.IncludedSignatureAlgorithms">
+    </util:set>
+
+    <util:set id="shibboleth.ExcludedSignatureAlgorithms">
+    </util:set>
+
+    <util:set id="shibboleth.IncludedEncryptionAlgorithms">
+    </util:set>
+
+    <util:set id="shibboleth.ExcludedEncryptionAlgorithms">
+    </util:set>
+    -->
+
+    <!--
+    If you need to define and inject custom Java object(s) into the various views used throughout the
+    system (errors, login, logout, etc.), you can uncomment and define the bean below to be of any
+    type required. It will appear in the view scope as a variable named "custom".
+    
+    The example below defines the bean as a map, which allows you to inject multiple objects under
+    named keys to expand the feature to support multiple injected objects.
+    -->
+    
+    <!--
+    <util:map id="shibboleth.CustomViewContext">
+        <entry key="foo" value="bar"/>
+    </util:map>
+    -->
+    
+    <util:set id="testbed.MetadataIndexes">
+        <bean class="org.opensaml.saml.metadata.resolver.index.impl.SAMLArtifactMetadataIndex" />
+        <ref bean="shibboleth.CASMetadataIndices" />
+    </util:set>
+    
+    <bean id="exampleMetadata" class="org.springframework.core.io.ClassPathResource">
+        <constructor-arg value="/metadata/example-metadata.xml"/>
+    </bean>
+          
+    <bean id="exampleMetadata-sp123" class="org.springframework.core.io.ClassPathResource">
+        <constructor-arg value="/metadata/example-sp123-metadata.xml"/>
+    </bean>
+      
+    <util:list id="testbed.MetadataResolverResources">
+        <value>%{idp.home}/conf/metadata-providers.xml</value>
+        <value>%{idp.home}/conf/metadata-filters.xml</value>
+    </util:list>
+
+</beans>

-- 
To stop receiving notification emails like this one, please contact
the administrator of this repository.


More information about the commits mailing list