[java-plugin-shibd] branch main updated: Add storage flow tests, more workarounds for Spring mock bugs.

Scott Cantor cantor.2 at osu.edu
Wed Jul 3 20:28:14 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=bb0c21e0715cade6ea343e0259c02feda9e3442d

The following commit(s) were added to refs/heads/main by this push:
     new bb0c21e  Add storage flow tests, more workarounds for Spring mock bugs.
bb0c21e is described below

commit bb0c21e0715cade6ea343e0259c02feda9e3442d
Author: Scott Cantor <cantor.2 at osu.edu>
AuthorDate: Wed Jul 3 16:28:11 2024 -0400

    Add storage flow tests, more workarounds for Spring mock bugs.
---
 .../shibboleth/sp/flows/AbstractSPFlowTest.java    |  21 +-
 .../java/net/shibboleth/sp/flows/PingFlowTest.java |   2 +-
 .../net/shibboleth/sp/flows/SealerFlowTest.java    |   8 +-
 .../net/shibboleth/sp/flows/StorageFlowTest.java   | 395 +++++++++++++++++++++
 4 files changed, 413 insertions(+), 13 deletions(-)

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
index 0241495..1ab60e2 100644
--- 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
@@ -120,10 +120,10 @@ public abstract class AbstractSPFlowTest extends AbstractFlowTest {
         setBasicAuth(AGENT_ID, "foo");
     }
 
-    protected void setRequest(final String method, final DDF body, final String contentType) throws IOException {
+    protected void setRequest(final String method, final DDF body) throws IOException {
         try (final ByteArrayOutputStream out = new ByteArrayOutputStream()) {
             body.serialize(out);
-            setRequest(request, method, out.toString(Charset.forName("UTF-8")) , contentType);
+            setRequest(request, method, out.toString(Charset.forName("UTF-8")) , "text/plain");
         }
     }
 
@@ -162,15 +162,20 @@ public abstract class AbstractSPFlowTest extends AbstractFlowTest {
         
         Assert.assertEquals(response.getContentType(), "text/plain");
         
-        try (final InputStream in = new ByteArrayInputStream(response.getContentAsByteArray())) {
-            final DDF body = DDF.deserialize(in);
+        final byte[] body = response.getContentAsByteArray();
+        if (body == null || body.length == 0) {
+            return null;
+        }
+        
+        try (final InputStream in = new ByteArrayInputStream(body)) {
+            final DDF obj = DDF.deserialize(in);
             if (eventId != null) {
-                Assert.assertTrue(body.isstruct());
-                Assert.assertEquals(body.getmember(EVENT_MEMBER_NAME).string(), eventId);
+                Assert.assertTrue(obj.isstruct());
+                Assert.assertEquals(obj.getmember(EVENT_MEMBER_NAME).string(), eventId);
             } else {
-                Assert.assertTrue(!body.isstruct() || body.getmember(EVENT_MEMBER_NAME).isnull());
+                Assert.assertTrue(!obj.isstruct() || obj.getmember(EVENT_MEMBER_NAME).isnull());
             }
-            return body;
+            return obj;
         } catch (final IOException e) {
             Assert.fail("DDF deserialization threw", e);
             return null;
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
index 0d2e2f5..0a5627d 100644
--- 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
@@ -80,7 +80,7 @@ public class PingFlowTest extends AbstractSPFlowTest {
     @Test
     public void testSuccess() throws IOException {
         setDefaultAuth();
-        setRequest("GET", new DDF(null), "text/plain");
+        setRequest("GET", new DDF(null));
         final FlowExecutionResult result = flowExecutor.launchExecution(FLOW_ID, null, externalContext);
         assertFlowExecutionResult(result, FLOW_ID);
         assertFlowExecutionOutcome(result.getOutcome());
diff --git a/sp-conf-impl/src/test/java/net/shibboleth/sp/flows/SealerFlowTest.java b/sp-conf-impl/src/test/java/net/shibboleth/sp/flows/SealerFlowTest.java
index 7d73956..abd7078 100644
--- a/sp-conf-impl/src/test/java/net/shibboleth/sp/flows/SealerFlowTest.java
+++ b/sp-conf-impl/src/test/java/net/shibboleth/sp/flows/SealerFlowTest.java
@@ -83,7 +83,7 @@ public class SealerFlowTest extends AbstractSPFlowTest {
         final DDF input = new DDF().structure();
         input.addmember(DoSealerOperation.VALUE).string(TEST_VALUE);
         input.addmember(DoSealerOperation.EXP).longinteger(Instant.now().minusSeconds(3600).toEpochMilli() / 1000);
-        setRequest("POST", input, "text/plain");
+        setRequest("POST", input);
         
         final FlowExecutionResult result = flowExecutor.launchExecution(FLOW_ID, null, externalContext);
         assertFlowExecutionResult(result, FLOW_ID);
@@ -113,7 +113,7 @@ public class SealerFlowTest extends AbstractSPFlowTest {
 
         final DDF input = new DDF().structure();
         input.addmember(DoSealerOperation.VALUE).string(TEST_VALUE);
-        setRequest("POST", input, "text/plain");
+        setRequest("POST", input);
         
         final FlowExecutionResult result = flowExecutor.launchExecution(FLOW_ID, null, externalContext);
         assertFlowExecutionResult(result, FLOW_ID);
@@ -153,7 +153,7 @@ public class SealerFlowTest extends AbstractSPFlowTest {
         
         final DDF input = new DDF().structure();
         input.addmember(DoSealerOperation.VALUE).string(wrapped);
-        setRequest("GET", input, "text/plain");
+        setRequest("GET", input);
         
         final FlowExecutionResult result = flowExecutor.launchExecution(FLOW_ID, null, externalContext);
         assertFlowExecutionResult(result, FLOW_ID);
@@ -175,7 +175,7 @@ public class SealerFlowTest extends AbstractSPFlowTest {
         
         final DDF input = new DDF().structure();
         input.addmember(DoSealerOperation.VALUE).string(wrapped);
-        setRequest("GET", input, "text/plain");
+        setRequest("GET", input);
         
         final FlowExecutionResult result = flowExecutor.launchExecution(FLOW_ID, null, externalContext);
         assertFlowExecutionResult(result, FLOW_ID);
diff --git a/sp-conf-impl/src/test/java/net/shibboleth/sp/flows/StorageFlowTest.java b/sp-conf-impl/src/test/java/net/shibboleth/sp/flows/StorageFlowTest.java
new file mode 100644
index 0000000..24938b1
--- /dev/null
+++ b/sp-conf-impl/src/test/java/net/shibboleth/sp/flows/StorageFlowTest.java
@@ -0,0 +1,395 @@
+/*
+ * 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 java.time.Instant;
+
+import javax.annotation.Nonnull;
+import javax.annotation.Nullable;
+
+import org.opensaml.profile.action.EventIds;
+import org.opensaml.storage.StorageRecord;
+import org.opensaml.storage.StorageService;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.beans.factory.annotation.Qualifier;
+import org.springframework.webflow.executor.FlowExecutionResult;
+import org.testng.Assert;
+import org.testng.annotations.AfterMethod;
+import org.testng.annotations.Test;
+
+import net.shibboleth.shared.annotation.constraint.NotEmpty;
+import net.shibboleth.sp.ddf.DDF;
+import net.shibboleth.sp.profile.impl.DoStorageOperation;
+
+/**
+ * Unit test for the SP sealer flow.
+ */
+public class StorageFlowTest extends AbstractSPFlowTest {
+    
+    /** Flow ID. */
+    @Nonnull public static final String FLOW_ID = "sp/storage";
+
+    /** Test data. */
+    @Nonnull public static final String TEST_CONTEXT = "org.example.context";
+
+    /** Test context. */
+    @Nonnull @NotEmpty private final static String AGENT_CONTEXT = AGENT_ID + '!' + TEST_CONTEXT;
+
+    /** Test key. */
+    @Nonnull public static final String TEST_KEY = "foo";
+
+    /** Test data. */
+    @Nonnull public static final String TEST_VALUE = "testValue";
+    
+    @Autowired
+    @Qualifier("shibboleth.StorageService")
+    @Nullable StorageService storageService;
+
+    protected StorageFlowTest() {
+        super(FLOW_ID);
+    }
+    
+    /**
+     * Get the auto-wired storage service.
+     * 
+     * @return storage service
+     */
+    @Nonnull public StorageService getStorageService() {
+        assert storageService != null;
+        return storageService;
+    }
+    
+    /**
+     * Clear the storage service between tests.
+     * 
+     * @throws IOException
+     */
+    @AfterMethod
+    public void clearStorage() throws IOException {
+        getStorageService().deleteContext(AGENT_CONTEXT);
+    }
+
+    /**
+     * Test invalid method.
+     * 
+     * @throws IOException 
+     */
+    @Test
+    public void invalidMethod() throws IOException {
+        setDefaultAuth();
+        setRequest("FOO", new DDF(null));
+        final FlowExecutionResult result = flowExecutor.launchExecution(FLOW_ID, null, externalContext);
+        assertFlowExecutionResult(result, FLOW_ID);
+        assertFlowExecutionOutcome(result.getOutcome());
+        assertOutputMessageEvent(result, EventIds.INVALID_MESSAGE);
+    }
+
+    /**
+     * Test wrap operation with no input.
+     * @throws IOException 
+     */
+    @Test
+    public void testMissingRead() throws IOException {
+        setDefaultAuth();
+
+        final DDF input = new DDF().structure();
+        input.addmember(DoStorageOperation.CONTEXT).string(TEST_CONTEXT);
+        input.addmember(DoStorageOperation.KEY).string(TEST_KEY);
+        setRequest("GET", input);
+
+        final FlowExecutionResult result = flowExecutor.launchExecution(FLOW_ID, null, externalContext);
+        assertFlowExecutionResult(result, FLOW_ID);
+        assertFlowExecutionOutcome(result.getOutcome());
+        assertOutputMessageEvent(result, DoStorageOperation.RECORD_NOT_FOUND);
+    }
+
+    /**
+     * Test successful get.
+     * 
+     * @throws IOException 
+     */
+    @Test
+    public void successRead() throws IOException {
+        setDefaultAuth();
+
+        final long exp = Instant.now().plusSeconds(900).toEpochMilli();
+        
+        getStorageService().create(AGENT_CONTEXT, TEST_KEY, TEST_VALUE, exp);
+        
+        final DDF input = new DDF().structure();
+        input.addmember(DoStorageOperation.CONTEXT).string(TEST_CONTEXT);
+        input.addmember(DoStorageOperation.KEY).string(TEST_KEY);
+        setRequest("GET", input);
+        
+        final FlowExecutionResult result = flowExecutor.launchExecution(FLOW_ID, null, externalContext);
+        assertFlowExecutionResult(result, FLOW_ID);
+        assertFlowExecutionOutcome(result.getOutcome());
+        final DDF output = assertOutputMessageEvent(result, null);
+        assert output != null;
+        
+        Assert.assertEquals(output.getmember(DoStorageOperation.VALUE).string(), TEST_VALUE);
+        Assert.assertEquals(output.getmember(DoStorageOperation.VERSION).longinteger(), 1);
+        Assert.assertEquals(output.getmember(DoStorageOperation.EXP).longinteger(), exp / 1000);
+    }
+
+    /**
+     * Test missing delete.
+     * 
+     * @throws IOException 
+     */
+    @Test
+    public void missingDelete() throws IOException {
+        setDefaultAuth();
+        
+        getStorageService().create(AGENT_CONTEXT, TEST_KEY, TEST_VALUE, null);
+        
+        final DDF input = new DDF().structure();
+        input.addmember(DoStorageOperation.CONTEXT).string(TEST_CONTEXT);
+        input.addmember(DoStorageOperation.KEY).string(TEST_KEY + "2");
+        setRequest("DELETE", input);
+
+        final FlowExecutionResult result = flowExecutor.launchExecution(FLOW_ID, null, externalContext);
+        assertFlowExecutionResult(result, FLOW_ID);
+        assertFlowExecutionOutcome(result.getOutcome());
+
+        assertOutputMessageEvent(result, DoStorageOperation.RECORD_NOT_FOUND);
+        
+        Assert.assertNotNull(getStorageService().read(AGENT_CONTEXT, TEST_KEY));
+    }
+    
+    /**
+     * Test successful delete.
+     * 
+     * @throws IOException 
+     */
+    @Test
+    public void successDelete() throws IOException  {
+        setDefaultAuth();
+        
+        getStorageService().create(AGENT_CONTEXT, TEST_KEY, TEST_VALUE, null);
+        
+        final DDF input = new DDF().structure();
+        input.addmember(DoStorageOperation.CONTEXT).string(TEST_CONTEXT);
+        input.addmember(DoStorageOperation.KEY).string(TEST_KEY);
+        setRequest("DELETE", input);
+
+        final FlowExecutionResult result = flowExecutor.launchExecution(FLOW_ID, null, externalContext);
+        assertFlowExecutionResult(result, FLOW_ID);
+        assertFlowExecutionOutcome(result.getOutcome());
+        
+        final DDF output = assertOutputMessageEvent(result, null);
+        Assert.assertNull(output);
+        
+        Assert.assertNull(getStorageService().read(AGENT_CONTEXT, TEST_KEY));
+    }
+
+    /**
+     * Test successful create.
+     * 
+     * @throws IOException 
+     */
+    @Test
+    public void successCreate() throws IOException {
+        setDefaultAuth();
+        
+        final DDF input = new DDF().structure();
+        input.addmember(DoStorageOperation.CONTEXT).string(TEST_CONTEXT);
+        input.addmember(DoStorageOperation.KEY).string(TEST_KEY);
+        input.addmember(DoStorageOperation.VALUE).string(TEST_VALUE);
+        setRequest("PUT", input);
+        
+        final FlowExecutionResult result = flowExecutor.launchExecution(FLOW_ID, null, externalContext);
+        assertFlowExecutionResult(result, FLOW_ID);
+        assertFlowExecutionOutcome(result.getOutcome());
+        
+        final DDF output = assertOutputMessageEvent(result, null);
+        Assert.assertNull(output);
+        
+        final StorageRecord<?> record = getStorageService().read(AGENT_CONTEXT, TEST_KEY);
+        assert record != null;
+        Assert.assertEquals(record.getVersion(), 1);
+        Assert.assertEquals(record.getValue(), TEST_VALUE);
+    }
+
+    /**
+     * Test duplicate create.
+     * 
+     * @throws IOException 
+     */
+    @Test
+    public void duplicateCreate() throws IOException {
+        setDefaultAuth();
+        
+        getStorageService().create(AGENT_CONTEXT, TEST_KEY, TEST_VALUE, null);
+        
+        final DDF input = new DDF().structure();
+        input.addmember(DoStorageOperation.CONTEXT).string(TEST_CONTEXT);
+        input.addmember(DoStorageOperation.KEY).string(TEST_KEY);
+        input.addmember(DoStorageOperation.VALUE).string(TEST_VALUE);
+        setRequest("PUT", input);
+        
+        final FlowExecutionResult result = flowExecutor.launchExecution(FLOW_ID, null, externalContext);
+        assertFlowExecutionResult(result, FLOW_ID);
+        assertFlowExecutionOutcome(result.getOutcome());
+        assertOutputMessageEvent(result, DoStorageOperation.DUPLICATE_RECORD);
+    }
+
+    /**
+     * Test successful update.
+     * 
+     * @throws IOException 
+     */
+    @Test
+    public void successUpdate() throws IOException {
+        setDefaultAuth();
+        
+        getStorageService().create(AGENT_CONTEXT, TEST_KEY, TEST_VALUE, null);
+        
+        final DDF input = new DDF().structure();
+        input.addmember(DoStorageOperation.CONTEXT).string(TEST_CONTEXT);
+        input.addmember(DoStorageOperation.KEY).string(TEST_KEY);
+        input.addmember(DoStorageOperation.VALUE).string("changed");
+        setRequest("POST", input);
+        
+        final FlowExecutionResult result = flowExecutor.launchExecution(FLOW_ID, null, externalContext);
+        assertFlowExecutionResult(result, FLOW_ID);
+        assertFlowExecutionOutcome(result.getOutcome());
+        
+        final DDF output = assertOutputMessageEvent(result, null);
+        Assert.assertNull(output);
+        
+        final StorageRecord<?> record = getStorageService().read(AGENT_CONTEXT, TEST_KEY);
+        assert record != null;
+        Assert.assertEquals(record.getVersion(), 2);
+        Assert.assertEquals(record.getValue(), "changed");
+    }
+
+    /**
+     * Test successful update as a create.
+     * 
+     * @throws IOException 
+     */
+    @Test
+    public void successUpdateAsCreate() throws IOException {
+        setDefaultAuth();
+        
+        final DDF input = new DDF().structure();
+        input.addmember(DoStorageOperation.CONTEXT).string(TEST_CONTEXT);
+        input.addmember(DoStorageOperation.KEY).string(TEST_KEY);
+        input.addmember(DoStorageOperation.VALUE).string(TEST_VALUE);
+        setRequest("POST", input);
+        
+        final FlowExecutionResult result = flowExecutor.launchExecution(FLOW_ID, null, externalContext);
+        assertFlowExecutionResult(result, FLOW_ID);
+        assertFlowExecutionOutcome(result.getOutcome());
+
+        final DDF output = assertOutputMessageEvent(result, null);
+        Assert.assertNull(output);
+        
+        final StorageRecord<?> record = getStorageService().read(AGENT_CONTEXT, TEST_KEY);
+        assert record != null;
+        Assert.assertEquals(record.getVersion(), 1);
+        Assert.assertEquals(record.getValue(), TEST_VALUE);
+    }
+
+    /**
+     * Test successful update with a version.
+     * 
+     * @throws IOException 
+     */
+    @Test
+    public void successUpdateWithVersion() throws IOException {
+        setDefaultAuth();
+        
+        getStorageService().create(AGENT_CONTEXT, TEST_KEY, TEST_VALUE, null);
+        
+        final DDF input = new DDF().structure();
+        input.addmember(DoStorageOperation.CONTEXT).string(TEST_CONTEXT);
+        input.addmember(DoStorageOperation.KEY).string(TEST_KEY);
+        input.addmember(DoStorageOperation.VALUE).string("changed");
+        input.addmember(DoStorageOperation.VERSION).longinteger(1);
+        setRequest("POST", input);
+        
+        final FlowExecutionResult result = flowExecutor.launchExecution(FLOW_ID, null, externalContext);
+        assertFlowExecutionResult(result, FLOW_ID);
+        assertFlowExecutionOutcome(result.getOutcome());
+        
+        final DDF output = assertOutputMessageEvent(result, null);
+        assert output != null;
+        Assert.assertEquals(output.getmember(DoStorageOperation.VERSION).longinteger(), 2);
+        
+        final StorageRecord<?> record = getStorageService().read(AGENT_CONTEXT, TEST_KEY);
+        assert record != null;
+        Assert.assertEquals(record.getVersion(), 2);
+        Assert.assertEquals(record.getValue(), "changed");
+    }
+
+    /**
+     * Test failed update with a version.
+     * 
+     * @throws IOException 
+     */
+    @Test
+    public void failedUpdateWithVersion() throws IOException {
+        setDefaultAuth();
+        
+        getStorageService().create(AGENT_CONTEXT, TEST_KEY, TEST_VALUE, null);
+
+        final DDF input = new DDF().structure();
+        input.addmember(DoStorageOperation.CONTEXT).string(TEST_CONTEXT);
+        input.addmember(DoStorageOperation.KEY).string(TEST_KEY);
+        input.addmember(DoStorageOperation.VALUE).string("changed");
+        input.addmember(DoStorageOperation.VERSION).longinteger(2);
+        setRequest("POST", input);
+        
+        final FlowExecutionResult result = flowExecutor.launchExecution(FLOW_ID, null, externalContext);
+        assertFlowExecutionResult(result, FLOW_ID);
+        assertFlowExecutionOutcome(result.getOutcome());
+        
+        assertOutputMessageEvent(result, DoStorageOperation.VERSION_MISMATCH);
+        
+        final StorageRecord<?> record = getStorageService().read(AGENT_CONTEXT, TEST_KEY);
+        assert record != null;
+        Assert.assertEquals(record.getVersion(), 1);
+        Assert.assertEquals(record.getValue(), TEST_VALUE);
+    }
+
+    /**
+     * Test failed update with a version when record missing.
+     * 
+     * @throws IOException 
+     */
+    @Test
+    public void missingUpdateWithVersion() throws IOException {
+        setDefaultAuth();
+        
+        final DDF input = new DDF().structure();
+        input.addmember(DoStorageOperation.CONTEXT).string(TEST_CONTEXT);
+        input.addmember(DoStorageOperation.KEY).string(TEST_KEY);
+        input.addmember(DoStorageOperation.VALUE).string("changed");
+        input.addmember(DoStorageOperation.VERSION).longinteger(2);
+        setRequest("POST", input);
+        
+        final FlowExecutionResult result = flowExecutor.launchExecution(FLOW_ID, null, externalContext);
+        assertFlowExecutionResult(result, FLOW_ID);
+        assertFlowExecutionOutcome(result.getOutcome());
+        
+        assertOutputMessageEvent(result, DoStorageOperation.RECORD_NOT_FOUND);
+
+        Assert.assertNull(getStorageService().read(AGENT_CONTEXT, TEST_KEY));
+    }
+    
+}
\ No newline at end of file

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


More information about the commits mailing list