[java-metadata-aggregator] branch master updated: MDA-247 - Ensure immutability of ItemMetadata classes

Ian Young ian at iay.org.uk
Tue Jun 16 09:16:22 UTC 2020


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

iay pushed a commit to branch master
in repository java-metadata-aggregator.

View the commit online:
http://git.shibboleth.net/view/?p=java-metadata-aggregator.git;a=commit;h=2e2ad6b13a09f5b422434e069a35f9ee58138232

The following commit(s) were added to refs/heads/master by this push:
       new  2e2ad6b   MDA-247 - Ensure immutability of ItemMetadata classes
2e2ad6b is described below

commit 2e2ad6b13a09f5b422434e069a35f9ee58138232
Author: Ian Young <ian at iay.org.uk>
AuthorDate: Tue Jun 16 10:16:18 2020 +0100

    MDA-247 - Ensure immutability of ItemMetadata classes
    
    https://issues.shibboleth.net/jira/browse/MDA-247
---
 .../java/net/shibboleth/metadata/ErrorStatus.java  |  2 +
 .../java/net/shibboleth/metadata/InfoStatus.java   |  2 +
 .../main/java/net/shibboleth/metadata/ItemId.java  | 22 +++---
 .../java/net/shibboleth/metadata/ItemMetadata.java |  6 +-
 .../main/java/net/shibboleth/metadata/ItemTag.java | 14 ++--
 .../net/shibboleth/metadata/StatusMetadata.java    | 14 ++--
 .../net/shibboleth/metadata/WarningStatus.java     |  2 +
 .../dom/saml/mdrpi/RegistrationAuthority.java      | 12 ++--
 .../metadata/pipeline/AbstractStage.java           | 16 ++---
 .../metadata/pipeline/ComponentInfo.java           | 80 ++++++----------------
 .../metadata/pipeline/SimplePipeline.java          | 23 ++++---
 .../dom/MultiOutputXSLTransformationStageTest.java |  3 +
 .../metadata/dom/XSLTtransformationStageTest.java  |  2 +
 .../metadata/dom/XSLValidationStageTest.java       |  3 +
 .../metadata/pipeline/ComponentInfoTest.java       | 53 ++++++++++++++
 15 files changed, 141 insertions(+), 113 deletions(-)

diff --git a/aggregator-pipeline/src/main/java/net/shibboleth/metadata/ErrorStatus.java b/aggregator-pipeline/src/main/java/net/shibboleth/metadata/ErrorStatus.java
index 6a030fc..dd311f0 100644
--- a/aggregator-pipeline/src/main/java/net/shibboleth/metadata/ErrorStatus.java
+++ b/aggregator-pipeline/src/main/java/net/shibboleth/metadata/ErrorStatus.java
@@ -18,10 +18,12 @@
 package net.shibboleth.metadata;
 
 import javax.annotation.Nonnull;
+import javax.annotation.concurrent.Immutable;
 
 import net.shibboleth.utilities.java.support.annotation.constraint.NotEmpty;
 
 /** A type of {@link StatusMetadata} that indicates something is definitely wrong with the Item. */
+ at Immutable
 public class ErrorStatus extends StatusMetadata {
 
     /**
diff --git a/aggregator-pipeline/src/main/java/net/shibboleth/metadata/InfoStatus.java b/aggregator-pipeline/src/main/java/net/shibboleth/metadata/InfoStatus.java
index c6543c5..7d7ff6f 100644
--- a/aggregator-pipeline/src/main/java/net/shibboleth/metadata/InfoStatus.java
+++ b/aggregator-pipeline/src/main/java/net/shibboleth/metadata/InfoStatus.java
@@ -18,6 +18,7 @@
 package net.shibboleth.metadata;
 
 import javax.annotation.Nonnull;
+import javax.annotation.concurrent.Immutable;
 
 import net.shibboleth.utilities.java.support.annotation.constraint.NotEmpty;
 
@@ -25,6 +26,7 @@ import net.shibboleth.utilities.java.support.annotation.constraint.NotEmpty;
  * A type of {@link StatusMetadata} that carries informational messages. These messages should never be used to carry
  * status messages that would indicate an error or failing of the Item in some way.
  */
+ at Immutable
 public class InfoStatus extends StatusMetadata {
 
     /**
diff --git a/aggregator-pipeline/src/main/java/net/shibboleth/metadata/ItemId.java b/aggregator-pipeline/src/main/java/net/shibboleth/metadata/ItemId.java
index 911f90a..2157133 100644
--- a/aggregator-pipeline/src/main/java/net/shibboleth/metadata/ItemId.java
+++ b/aggregator-pipeline/src/main/java/net/shibboleth/metadata/ItemId.java
@@ -20,7 +20,7 @@ package net.shibboleth.metadata;
 import java.util.Objects;
 
 import javax.annotation.Nonnull;
-import javax.annotation.concurrent.ThreadSafe;
+import javax.annotation.concurrent.Immutable;
 
 import net.shibboleth.utilities.java.support.annotation.constraint.NotEmpty;
 import net.shibboleth.utilities.java.support.logic.Constraint;
@@ -33,16 +33,16 @@ import net.shibboleth.utilities.java.support.primitive.StringSupport;
  * have the same {@link ItemId} as any other {@link net.shibboleth.metadata.Item} in a given
  * context.
  */
- at ThreadSafe
+ at Immutable
 public class ItemId implements ItemMetadata, Comparable<ItemId> {
 
     /** Unique ID for the Item. */
-    private final String id;
+    @Nonnull @NotEmpty private final String id;
 
     /**
      * Constructor.
      * 
-     * @param itemId a unique identifier for the entity, never null
+     * @param itemId a unique identifier for the entity, never null or empty
      */
     public ItemId(@Nonnull @NotEmpty final String itemId) {
         id = Constraint.isNotNull(StringSupport.trimOrNull(itemId), "Item ID may not be null or empty");
@@ -53,17 +53,17 @@ public class ItemId implements ItemMetadata, Comparable<ItemId> {
      * 
      * @return unique identifier for the data carried by the Item
      */
-    @Nonnull public String getId() {
+    @Nonnull @NotEmpty public String getId() {
         return id;
     }
 
-    /** {@inheritDoc} */
-    @Override public int hashCode() {
+    @Override
+    public int hashCode() {
         return id.hashCode();
     }
 
-    /** {@inheritDoc} */
-    @Override public boolean equals(final Object obj) {
+    @Override
+    public boolean equals(final Object obj) {
         if (this == obj) {
             return true;
         }
@@ -78,8 +78,8 @@ public class ItemId implements ItemMetadata, Comparable<ItemId> {
         return Objects.equals(id, other.id);
     }
 
-    /** {@inheritDoc} */
-    @Override public int compareTo(final ItemId o) {
+    @Override
+    public int compareTo(final ItemId o) {
         return id.compareTo(o.id);
     }
 }
diff --git a/aggregator-pipeline/src/main/java/net/shibboleth/metadata/ItemMetadata.java b/aggregator-pipeline/src/main/java/net/shibboleth/metadata/ItemMetadata.java
index cf9dcb9..02ba572 100644
--- a/aggregator-pipeline/src/main/java/net/shibboleth/metadata/ItemMetadata.java
+++ b/aggregator-pipeline/src/main/java/net/shibboleth/metadata/ItemMetadata.java
@@ -17,7 +17,7 @@
 
 package net.shibboleth.metadata;
 
-import javax.annotation.concurrent.ThreadSafe;
+import javax.annotation.concurrent.Immutable;
 
 /**
  * Additional information associated with an {@link Item} while it is being worked with.
@@ -25,7 +25,7 @@ import javax.annotation.concurrent.ThreadSafe;
  * Implementations of this class <strong>MUST</strong> be immutable. When an {@link Item} is cloned, the clone will
  * reference the same {@link ItemMetadata} objects as the original.
  */
- at ThreadSafe
+ at Immutable
 public interface ItemMetadata {
 
-}
\ No newline at end of file
+}
diff --git a/aggregator-pipeline/src/main/java/net/shibboleth/metadata/ItemTag.java b/aggregator-pipeline/src/main/java/net/shibboleth/metadata/ItemTag.java
index aad9775..c3c22a8 100644
--- a/aggregator-pipeline/src/main/java/net/shibboleth/metadata/ItemTag.java
+++ b/aggregator-pipeline/src/main/java/net/shibboleth/metadata/ItemTag.java
@@ -18,34 +18,34 @@
 package net.shibboleth.metadata;
 
 import javax.annotation.Nonnull;
-import javax.annotation.concurrent.ThreadSafe;
+import javax.annotation.concurrent.Immutable;
 
 import net.shibboleth.utilities.java.support.annotation.constraint.NotEmpty;
 import net.shibboleth.utilities.java.support.logic.Constraint;
 import net.shibboleth.utilities.java.support.primitive.StringSupport;
 
 /** A {@link ItemMetadata} that associates a tag with a given {@link Item}. */
- at ThreadSafe
+ at Immutable
 public class ItemTag implements ItemMetadata {
 
     /** Item tag. */
-    private final String tag;
+    @Nonnull @NotEmpty private final String tag;
 
     /**
      * Constructor.
      * 
-     * @param itemTag a tag for a metadata element
+     * @param itemTag a tag for an item, must not be either null or empty
      */
     public ItemTag(@Nonnull @NotEmpty final String itemTag) {
         tag = Constraint.isNotNull(StringSupport.trimOrNull(itemTag), "Tag may not be null or empty");
     }
 
     /**
-     * Gets the tag for the metadata element.
+     * Gets the tag for the item.
      * 
-     * @return tag for the metadata element, never null
+     * @return tag for the item, never null or empty
      */
-    @Nonnull public String getTag() {
+    @Nonnull @NotEmpty public String getTag() {
         return tag;
     }
 }
diff --git a/aggregator-pipeline/src/main/java/net/shibboleth/metadata/StatusMetadata.java b/aggregator-pipeline/src/main/java/net/shibboleth/metadata/StatusMetadata.java
index 3464cdd..cb3ea3b 100644
--- a/aggregator-pipeline/src/main/java/net/shibboleth/metadata/StatusMetadata.java
+++ b/aggregator-pipeline/src/main/java/net/shibboleth/metadata/StatusMetadata.java
@@ -18,19 +18,21 @@
 package net.shibboleth.metadata;
 
 import javax.annotation.Nonnull;
+import javax.annotation.concurrent.Immutable;
 
 import net.shibboleth.utilities.java.support.annotation.constraint.NotEmpty;
 import net.shibboleth.utilities.java.support.logic.Constraint;
 import net.shibboleth.utilities.java.support.primitive.StringSupport;
 
 /** A {@link ItemMetadata} implementation that carries status information about an {@link Item}. */
+ at Immutable
 public class StatusMetadata implements ItemMetadata {
 
     /** The component that generated this status information. */
-    private final String component;
+    @Nonnull @NotEmpty private final String component;
 
     /** The message associated with this status. */
-    private final String message;
+    @Nonnull @NotEmpty private final String message;
 
     /**
      * Constructor.
@@ -48,18 +50,18 @@ public class StatusMetadata implements ItemMetadata {
     /**
      * Gets the ID of the component that generated the status message.
      * 
-     * @return ID of the component that generated the status message, never null
+     * @return ID of the component that generated the status message, never null or empty
      */
-    @Nonnull public String getComponentId() {
+    @Nonnull @NotEmpty public String getComponentId() {
         return component;
     }
 
     /**
      * Gets the status message.
      * 
-     * @return the status message, never null
+     * @return the status message, never null or empty
      */
-    @Nonnull public String getStatusMessage() {
+    @Nonnull @NotEmpty public String getStatusMessage() {
         return message;
     }
 }
diff --git a/aggregator-pipeline/src/main/java/net/shibboleth/metadata/WarningStatus.java b/aggregator-pipeline/src/main/java/net/shibboleth/metadata/WarningStatus.java
index b4c6ea6..ce239ca 100644
--- a/aggregator-pipeline/src/main/java/net/shibboleth/metadata/WarningStatus.java
+++ b/aggregator-pipeline/src/main/java/net/shibboleth/metadata/WarningStatus.java
@@ -18,6 +18,7 @@
 package net.shibboleth.metadata;
 
 import javax.annotation.Nonnull;
+import javax.annotation.concurrent.Immutable;
 
 import net.shibboleth.utilities.java.support.annotation.constraint.NotEmpty;
 
@@ -28,6 +29,7 @@ import net.shibboleth.utilities.java.support.annotation.constraint.NotEmpty;
  * {@link net.shibboleth.metadata.pipeline.Stage} thinks something about the Item may be wrong but does not have enough
  * information to verify it.
  */
+ at Immutable
 public class WarningStatus extends StatusMetadata {
 
     /**
diff --git a/aggregator-pipeline/src/main/java/net/shibboleth/metadata/dom/saml/mdrpi/RegistrationAuthority.java b/aggregator-pipeline/src/main/java/net/shibboleth/metadata/dom/saml/mdrpi/RegistrationAuthority.java
index 32c7db5..9ac0f63 100644
--- a/aggregator-pipeline/src/main/java/net/shibboleth/metadata/dom/saml/mdrpi/RegistrationAuthority.java
+++ b/aggregator-pipeline/src/main/java/net/shibboleth/metadata/dom/saml/mdrpi/RegistrationAuthority.java
@@ -18,7 +18,7 @@
 package net.shibboleth.metadata.dom.saml.mdrpi;
 
 import javax.annotation.Nonnull;
-import javax.annotation.concurrent.ThreadSafe;
+import javax.annotation.concurrent.Immutable;
 
 import net.shibboleth.metadata.ItemMetadata;
 import net.shibboleth.utilities.java.support.annotation.constraint.NotEmpty;
@@ -31,16 +31,16 @@ import net.shibboleth.utilities.java.support.primitive.StringSupport;
  * Although the value is formally a URI, we represent it as a String for now
  * to prevent running into trouble if people use malformed values.
  */
- at ThreadSafe
+ at Immutable
 public class RegistrationAuthority implements ItemMetadata {
 
     /** Registration authority URI. */
-    private final String registrationAuthority;
+    @Nonnull @NotEmpty private final String registrationAuthority;
 
     /**
      * Constructor.
      * 
-     * @param authority The registration authority for the entity, never null
+     * @param authority The registration authority for the item, never null or empty
      */
     public RegistrationAuthority(@Nonnull @NotEmpty final String authority) {
         registrationAuthority = Constraint.isNotNull(StringSupport.trimOrNull(authority),
@@ -50,9 +50,9 @@ public class RegistrationAuthority implements ItemMetadata {
     /**
      * Gets the registration authority value.
      * 
-     * @return unique identifier for the data carried by the Item
+     * @return unique The registration authority for the item, never null or empty
      */
-    @Nonnull public String getRegistrationAuthority() {
+    @Nonnull @NotEmpty public String getRegistrationAuthority() {
         return registrationAuthority;
     }
 
diff --git a/aggregator-pipeline/src/main/java/net/shibboleth/metadata/pipeline/AbstractStage.java b/aggregator-pipeline/src/main/java/net/shibboleth/metadata/pipeline/AbstractStage.java
index 154e2f1..6461d18 100644
--- a/aggregator-pipeline/src/main/java/net/shibboleth/metadata/pipeline/AbstractStage.java
+++ b/aggregator-pipeline/src/main/java/net/shibboleth/metadata/pipeline/AbstractStage.java
@@ -17,6 +17,7 @@
 
 package net.shibboleth.metadata.pipeline;
 
+import java.time.Instant;
 import java.util.Collection;
 import java.util.Collections;
 import java.util.function.Predicate;
@@ -69,24 +70,19 @@ public abstract class AbstractStage<T> extends BaseIdentifiableInitializableComp
         return collectionPredicate;
     }
 
-    /**
-     * Creates an {@link ComponentInfo}, delegates actual work on the collection to {@link #doExecute(Collection)}, adds
-     * the {@link ComponentInfo} to all the resultant Item elements and then sets its completion time.
-     * 
-     * {@inheritDoc}
-     */
-    @Override public void execute(@Nonnull @NonnullElements final Collection<Item<T>> itemCollection)
+    @Override
+    public void execute(@Nonnull @NonnullElements final Collection<Item<T>> itemCollection)
             throws StageProcessingException {
         throwComponentStateExceptions();
 
-        final ComponentInfo compInfo = new ComponentInfo(this);
+        final var start = Instant.now();
 
         if (collectionPredicate.test(itemCollection)) {
             doExecute(itemCollection);
         }
 
-        ItemMetadataSupport.addToAll(itemCollection, Collections.singleton(compInfo));
-        compInfo.setCompleteInstant();
+        final var componentInfo = new ComponentInfo(getId(), getClass(), start, Instant.now());
+        ItemMetadataSupport.addToAll(itemCollection, Collections.singleton(componentInfo));
     }
 
     /**
diff --git a/aggregator-pipeline/src/main/java/net/shibboleth/metadata/pipeline/ComponentInfo.java b/aggregator-pipeline/src/main/java/net/shibboleth/metadata/pipeline/ComponentInfo.java
index 38511bf..4e13257 100644
--- a/aggregator-pipeline/src/main/java/net/shibboleth/metadata/pipeline/ComponentInfo.java
+++ b/aggregator-pipeline/src/main/java/net/shibboleth/metadata/pipeline/ComponentInfo.java
@@ -21,42 +21,42 @@ import java.time.Instant;
 
 import javax.annotation.Nonnull;
 import javax.annotation.Nullable;
+import javax.annotation.concurrent.Immutable;
 
 import net.shibboleth.metadata.ItemMetadata;
-import net.shibboleth.utilities.java.support.component.IdentifiedComponent;
-import net.shibboleth.utilities.java.support.logic.Constraint;
-import net.shibboleth.utilities.java.support.primitive.StringSupport;
 
 /** Some basic information related to a component's processing of an {@link net.shibboleth.metadata.Item}. */
+ at Immutable
 public class ComponentInfo implements ItemMetadata {
 
     /** ID of the component that operated on the element. */
-    private String componentId;
+    private final String componentId;
 
     /** Gets the type of the component that operated on the element. */
-    private Class<?> componentType;
+    private final Class<?> componentType;
 
     /** Instant when the component operation started. */
-    private Instant startInstant;
+    private final Instant startInstant;
 
     /** Instant when the component operation completed. */
-    private Instant completeInstant;
-
-    /** Constructor. */
-    public ComponentInfo() {
-
-    }
+    private final Instant completeInstant;
 
     /**
-     * Constructor. Sets the ID and component type from the given component. Sets the start instant to now.
-     * 
-     * @param component component which this info describes
+     * Constructor.
+     *
+     * @param cId ID of the component performing the processing
+     * @param cType type of the component performing the processing
+     * @param start time at which the component started processing
+     * @param complete time at which the component completed processing
+     *
+     * @since 0.10.0
      */
-    public ComponentInfo(@Nonnull final IdentifiedComponent component) {
-        Constraint.isNotNull(component, "Component can not be null");
-        componentId = component.getId();
-        componentType = component.getClass();
-        startInstant = Instant.now();
+    public ComponentInfo(@Nonnull final String cId, @Nonnull final Class<?> cType,
+            @Nonnull final Instant start, @Nonnull final Instant complete) {
+        componentId = cId;
+        componentType = cType;
+        startInstant = start;
+        completeInstant = complete;
     }
 
     /**
@@ -68,15 +68,6 @@ public class ComponentInfo implements ItemMetadata {
         return componentId;
     }
 
-    /**
-     * Sets the ID of the component that operated on the element.
-     * 
-     * @param id ID of the component that operated on the element
-     */
-    public void setComponentId(@Nullable final String id) {
-        componentId = StringSupport.trimOrNull(id);
-    }
-
     /**
      * Gets the type of the component that operated on the element.
      * 
@@ -86,15 +77,6 @@ public class ComponentInfo implements ItemMetadata {
         return componentType;
     }
 
-    /**
-     * Sets the type of the component that operated on the element.
-     * 
-     * @param type type of the component that operated on the element
-     */
-    public void setComponentType(@Nullable final Class<?> type) {
-        componentType = type;
-    }
-
     /**
      * Gets the instant when the component operation started.
      * 
@@ -104,15 +86,6 @@ public class ComponentInfo implements ItemMetadata {
         return startInstant;
     }
 
-    /**
-     * Sets the instant when the component operation started.
-     * 
-     * @param instant instant when the component operation started
-     */
-    public void setStartInstant(@Nullable final Instant instant) {
-        startInstant = instant;
-    }
-
     /**
      * Gets the instant when the component operation completed.
      * 
@@ -122,17 +95,4 @@ public class ComponentInfo implements ItemMetadata {
         return completeInstant;
     }
 
-    /** Sets the complete instant of the component to now. */
-    public void setCompleteInstant() {
-        completeInstant = Instant.now();
-    }
-
-    /**
-     * Sets the instant when the component operation completed.
-     * 
-     * @param instant when the component operation completed
-     */
-    public void setCompleteInstant(@Nullable final Instant instant) {
-        completeInstant = instant;
-    }
 }
diff --git a/aggregator-pipeline/src/main/java/net/shibboleth/metadata/pipeline/SimplePipeline.java b/aggregator-pipeline/src/main/java/net/shibboleth/metadata/pipeline/SimplePipeline.java
index 5c3a008..cfa259b 100644
--- a/aggregator-pipeline/src/main/java/net/shibboleth/metadata/pipeline/SimplePipeline.java
+++ b/aggregator-pipeline/src/main/java/net/shibboleth/metadata/pipeline/SimplePipeline.java
@@ -17,6 +17,7 @@
 
 package net.shibboleth.metadata.pipeline;
 
+import java.time.Instant;
 import java.util.Collection;
 import java.util.Collections;
 import java.util.List;
@@ -41,6 +42,7 @@ public class SimplePipeline<T> extends BaseIdentifiableInitializableComponent
         implements Pipeline<T> {
 
     /** Stages for this pipeline. */
+    @Nonnull @NonnullElements
     private List<Stage<T>> pipelineStages = Collections.emptyList();
 
     @Override
@@ -60,28 +62,29 @@ public class SimplePipeline<T> extends BaseIdentifiableInitializableComponent
         pipelineStages = List.copyOf(stages);
     }
 
-    /** {@inheritDoc} */
-    @Override public void execute(@Nonnull @NonnullElements final Collection<Item<T>> itemCollection)
+    @Override
+    public void execute(@Nonnull @NonnullElements final Collection<Item<T>> itemCollection)
             throws PipelineProcessingException {
-        final ComponentInfo compInfo = new ComponentInfo(this);
+
+        final var start = Instant.now();
 
         for (final Stage<T> stage : pipelineStages) {
             stage.execute(itemCollection);
         }
 
-        compInfo.setCompleteInstant();
-        ItemMetadataSupport.addToAll(itemCollection, Collections.singleton(compInfo));
+        final var componentInfo = new ComponentInfo(getId(), getClass(), start, Instant.now());
+        ItemMetadataSupport.addToAll(itemCollection, Collections.singleton(componentInfo));
     }
 
-    /** {@inheritDoc} */
-    @Override protected void doDestroy() {
+    @Override
+    protected void doDestroy() {
         pipelineStages = null;
 
         super.doDestroy();
     }
 
-    /** {@inheritDoc} */
-    @Override protected void doInitialize() throws ComponentInitializationException {
+    @Override
+    protected void doInitialize() throws ComponentInitializationException {
         super.doInitialize();
 
         for (final Stage<T> stage : pipelineStages) {
@@ -90,4 +93,4 @@ public class SimplePipeline<T> extends BaseIdentifiableInitializableComponent
             }
         }
     }
-}
\ No newline at end of file
+}
diff --git a/aggregator-pipeline/src/test/java/net/shibboleth/metadata/dom/MultiOutputXSLTransformationStageTest.java b/aggregator-pipeline/src/test/java/net/shibboleth/metadata/dom/MultiOutputXSLTransformationStageTest.java
index 2f5e91c..f41a698 100644
--- a/aggregator-pipeline/src/test/java/net/shibboleth/metadata/dom/MultiOutputXSLTransformationStageTest.java
+++ b/aggregator-pipeline/src/test/java/net/shibboleth/metadata/dom/MultiOutputXSLTransformationStageTest.java
@@ -24,6 +24,8 @@ import java.util.List;
 import java.util.Map;
 import java.util.Set;
 
+import javax.annotation.concurrent.Immutable;
+
 import net.shibboleth.metadata.AssertSupport;
 import net.shibboleth.metadata.ErrorStatus;
 import net.shibboleth.metadata.InfoStatus;
@@ -255,6 +257,7 @@ public class MultiOutputXSLTransformationStageTest extends BaseDOMTest {
     }
 
     /** Simple marker object to test correct passage of {@link ItemMetadata} through pipeline stages. */
+    @Immutable
     private static class TestInfo implements ItemMetadata {
 
     }
diff --git a/aggregator-pipeline/src/test/java/net/shibboleth/metadata/dom/XSLTtransformationStageTest.java b/aggregator-pipeline/src/test/java/net/shibboleth/metadata/dom/XSLTtransformationStageTest.java
index 75f8146..b947b64 100644
--- a/aggregator-pipeline/src/test/java/net/shibboleth/metadata/dom/XSLTtransformationStageTest.java
+++ b/aggregator-pipeline/src/test/java/net/shibboleth/metadata/dom/XSLTtransformationStageTest.java
@@ -25,6 +25,7 @@ import java.util.List;
 import java.util.Map;
 import java.util.Set;
 
+import javax.annotation.concurrent.Immutable;
 import javax.xml.transform.Source;
 import javax.xml.transform.TransformerException;
 import javax.xml.transform.URIResolver;
@@ -244,6 +245,7 @@ public class XSLTtransformationStageTest extends BaseDOMTest {
     }
 
     /** Simple marker object to test correct passage of {@link ItemMetadata} through pipeline stages. */
+    @Immutable
     private static class TestInfo implements ItemMetadata {
 
     }
diff --git a/aggregator-pipeline/src/test/java/net/shibboleth/metadata/dom/XSLValidationStageTest.java b/aggregator-pipeline/src/test/java/net/shibboleth/metadata/dom/XSLValidationStageTest.java
index 7c9f55e..fe270c0 100644
--- a/aggregator-pipeline/src/test/java/net/shibboleth/metadata/dom/XSLValidationStageTest.java
+++ b/aggregator-pipeline/src/test/java/net/shibboleth/metadata/dom/XSLValidationStageTest.java
@@ -20,6 +20,8 @@ package net.shibboleth.metadata.dom;
 import java.util.ArrayList;
 import java.util.List;
 
+import javax.annotation.concurrent.Immutable;
+
 import net.shibboleth.metadata.AssertSupport;
 import net.shibboleth.metadata.ErrorStatus;
 import net.shibboleth.metadata.InfoStatus;
@@ -137,6 +139,7 @@ public class XSLValidationStageTest extends BaseDOMTest {
     }
     
     /** Simple marker object to test correct passage of {@link ItemMetadata} through pipeline stages. */
+    @Immutable
     private static class TestInfo implements ItemMetadata {
 
     }
diff --git a/aggregator-pipeline/src/test/java/net/shibboleth/metadata/pipeline/ComponentInfoTest.java b/aggregator-pipeline/src/test/java/net/shibboleth/metadata/pipeline/ComponentInfoTest.java
index 7c08598..e2cc9dd 100644
--- a/aggregator-pipeline/src/test/java/net/shibboleth/metadata/pipeline/ComponentInfoTest.java
+++ b/aggregator-pipeline/src/test/java/net/shibboleth/metadata/pipeline/ComponentInfoTest.java
@@ -1,8 +1,11 @@
 
 package net.shibboleth.metadata.pipeline;
 
+import java.time.Duration;
 import java.util.ArrayList;
+import java.util.Collection;
 import java.util.List;
+import java.util.function.Predicate;
 
 import org.testng.Assert;
 import org.testng.annotations.Test;
@@ -14,26 +17,52 @@ public class ComponentInfoTest {
 
     @Test
     public void testBasicOperation() throws Exception {
+        
+        // A predicate which just delays for 11ms and then returns true.
+        final var delayingCollectionPredicate = new Predicate<Collection<Item<String>>>() {
+            public boolean test(Collection<Item<String>> t) {
+                try {
+                    Thread.sleep(11);
+                } catch (InterruptedException e) {
+                }
+                return true;
+            }
+        };
+
         final Item<String> item = new MockItem("test");
         final List<Item<String>> items = new ArrayList<>();
         items.add(item);
+
+        // comp1 is a CompositeStage which does nothing other than delay for 10ms
         final CompositeStage<String> comp1 = new CompositeStage<>();
         comp1.setId("comp1");
+        comp1.setCollectionPredicate(delayingCollectionPredicate);
         comp1.initialize();
+
+        // comp2 is a CompositeStage which does nothing other than delay for 10ms
         final CompositeStage<String> comp2 = new CompositeStage<>();
         comp2.setId("comp2");
+        comp2.setCollectionPredicate(delayingCollectionPredicate);
         comp2.initialize();
+
         final List<Stage<String>> stages = new ArrayList<>();
         stages.add(comp1);
         stages.add(comp2);
+
         final SimplePipeline<String> pipe = new SimplePipeline<>();
         pipe.setId("pipe");
         pipe.setStages(stages);
         pipe.initialize();
+
         pipe.execute(items);
+
         final List<ComponentInfo> infos = item.getItemMetadata().get(ComponentInfo.class);
+
         // expect one for each CompositeStage and one for the SimplePipeline
         Assert.assertEquals(infos.size(), 3);
+        final var info0 = infos.get(0);
+        final var info1 = infos.get(1);
+        final var info2 = infos.get(2);
 
         Assert.assertSame(infos.get(0).getComponentType(), CompositeStage.class, "0");
         Assert.assertEquals(infos.get(0).getComponentId(), "comp1", "0");
@@ -44,6 +73,30 @@ public class ComponentInfoTest {
         Assert.assertSame(infos.get(2).getComponentType(), SimplePipeline.class, "2");
         Assert.assertEquals(infos.get(2).getComponentId(), "pipe", "2");
 
+        // Timing for first stage: takes at least 10ms.
+        final var time0 = Duration.between(info0.getStartInstant(), info0.getCompleteInstant());
+        final var nano0 = time0.toNanos();
+        Assert.assertTrue(nano0 >= 10_000_000);
+
+        // Timing for second stage: takes at least 10ms.
+        final var time1 = Duration.between(info1.getStartInstant(), info1.getCompleteInstant());
+        final var nano1 = time1.toNanos();
+        Assert.assertTrue(nano1 >= 10_000_000);
+
+        // Second stage does not start before first stage ends
+        Assert.assertFalse(info1.getStartInstant().isBefore(info0.getCompleteInstant()));
+
+        // Timing for pipeline: takes at least 20ms
+        final var time2 = Duration.between(info2.getStartInstant(), info2.getCompleteInstant());
+        final var nano2 = time2.toNanos();
+        Assert.assertTrue(nano2 >= 20_000_000);
+
+        // Stage 1 does not start earlier than pipeline
+        Assert.assertFalse(info0.getStartInstant().isBefore(info2.getStartInstant()));
+        
+        // Pipeline does not end earlier than stage 2
+        Assert.assertFalse(info2.getCompleteInstant().isBefore(info1.getCompleteInstant()));
+
         // Check that we're getting ISO 8601 Z time out from toString
         // Java 8 gives a result with three sub-second digits (millisecond precision)
         // Java 9 gives six digits (microsecond precision)

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


More information about the commits mailing list