[java-oidfed-common] 02/02: Improved value handling for federation constraints

Codeberg noreply at shibboleth.net
Wed Sep 30 17:33:09 UTC 2026


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

codeberg pushed a commit to branch main
in repository java-oidfed-common.

View the commit online:
https://codeberg.org/Shibboleth/java-oidfed-common/commit/4490987664a64d763becb4becd7b50c11a9ef7fd

commit 4490987664a64d763becb4becd7b50c11a9ef7fd
Author: Henri Mikkonen <henri.mikkonen at iki.fi>
AuthorDate: Wed Sep 30 18:00:17 2026 +0300

    Improved value handling for federation constraints
    
    - Null-checks before the value is passed to the constraint implementations
    - Unit tests (missing for allowed_entity_types)
---
 .../impl/AbstractFederationPolicyConstraint.java   |  14 +-
 .../impl/DefaultAllowedEntityTypesConstraint.java  |  14 +-
 .../impl/DefaultMaxPathLengthConstraint.java       |  10 +-
 .../impl/DefaultNamingConstraintsConstraint.java   |  31 +++--
 .../constraints/impl/AbstractConstraintTest.java   |  53 +++++++
 .../impl/DefaultMaxPathLengthConstraintTest.java   |  79 +++++++++++
 .../DefaultNamingConstraintsConstraintTest.java    | 154 +++++++++++++++++++++
 7 files changed, 321 insertions(+), 34 deletions(-)

diff --git a/oidfed-common-impl/src/main/java/net/shibboleth/oidfed/metadata/constraints/impl/AbstractFederationPolicyConstraint.java b/oidfed-common-impl/src/main/java/net/shibboleth/oidfed/metadata/constraints/impl/AbstractFederationPolicyConstraint.java
index 20c26da..979eb9d 100644
--- a/oidfed-common-impl/src/main/java/net/shibboleth/oidfed/metadata/constraints/impl/AbstractFederationPolicyConstraint.java
+++ b/oidfed-common-impl/src/main/java/net/shibboleth/oidfed/metadata/constraints/impl/AbstractFederationPolicyConstraint.java
@@ -45,15 +45,15 @@ public abstract class AbstractFederationPolicyConstraint<T extends Object>
     public boolean validate(@Nullable final Object constraint, @Nonnull final SubordinateStatement subordinateStatement,
             @Nonnull @Live final List<EntityStatement<?>> trustChain) {
         checkComponentActive();
+        if (constraint == null) {
+            log.debug("No constraint value provided: null is not allowed by syntax");
+            return false;
+        }
         try {
             log.trace("Attempting to parse raw constraint value: {}", constraint);
-            final T constraintData = parseConstraint(constraint);
-            if (constraintData != null) {
-                return doValidate(constraintData, subordinateStatement, trustChain);
-            } else {
-                return true;
-            }
+            return doValidate(parseConstraint(constraint), subordinateStatement, trustChain);
         } catch (final ConstraintViolationException e) {
+            log.trace("Exception caught when validating the constraint {}", constraint, e);
             return false;
         }
     }
@@ -65,7 +65,7 @@ public abstract class AbstractFederationPolicyConstraint<T extends Object>
      * @return parsed constraint data
      * @throws ConstraintViolationException if the parsing was not successful
      */
-    @Nullable protected abstract T parseConstraint(@Nullable final Object constraint)
+    @Nonnull protected abstract T parseConstraint(@Nonnull final Object constraint)
         throws ConstraintViolationException;
 
     /**
diff --git a/oidfed-common-impl/src/main/java/net/shibboleth/oidfed/metadata/constraints/impl/DefaultAllowedEntityTypesConstraint.java b/oidfed-common-impl/src/main/java/net/shibboleth/oidfed/metadata/constraints/impl/DefaultAllowedEntityTypesConstraint.java
index b1ddfb3..ff054af 100644
--- a/oidfed-common-impl/src/main/java/net/shibboleth/oidfed/metadata/constraints/impl/DefaultAllowedEntityTypesConstraint.java
+++ b/oidfed-common-impl/src/main/java/net/shibboleth/oidfed/metadata/constraints/impl/DefaultAllowedEntityTypesConstraint.java
@@ -74,15 +74,17 @@ public class DefaultAllowedEntityTypesConstraint extends AbstractFederationPolic
     }
 
     /** {@inheritDoc} */
-    @Override @Nullable
-    protected List<String> parseConstraint(@Nullable final Object constraint)
+    @Override @Nonnull
+    protected List<String> parseConstraint(@Nonnull final Object constraint)
             throws ConstraintViolationException {
         if (constraint instanceof List<?> list) {
-            return list.stream().filter(String.class::isInstance).map(String::valueOf).toList();
-        } else if (constraint != null) {
-            throw new ConstraintViolationException("Unexpected value type for allowed_entity_types: " + constraint);
+            final List<String> result = list.stream().filter(String.class::isInstance).map(String::valueOf).toList();
+            if (result.size() == list.size()) {
+                return result;
+            }
         }
-        return null;
+        log.debug("Unexpected value type for allowed_entity_types: {}", constraint);
+        throw new ConstraintViolationException("Unexpected value type for allowed_entity_types: " + constraint);
     }
 
     /** {@inheritDoc} */
diff --git a/oidfed-common-impl/src/main/java/net/shibboleth/oidfed/metadata/constraints/impl/DefaultMaxPathLengthConstraint.java b/oidfed-common-impl/src/main/java/net/shibboleth/oidfed/metadata/constraints/impl/DefaultMaxPathLengthConstraint.java
index 53600fd..0bc8fd4 100644
--- a/oidfed-common-impl/src/main/java/net/shibboleth/oidfed/metadata/constraints/impl/DefaultMaxPathLengthConstraint.java
+++ b/oidfed-common-impl/src/main/java/net/shibboleth/oidfed/metadata/constraints/impl/DefaultMaxPathLengthConstraint.java
@@ -17,7 +17,6 @@ package net.shibboleth.oidfed.metadata.constraints.impl;
 import java.util.List;
 
 import javax.annotation.Nonnull;
-import javax.annotation.Nullable;
 
 import org.slf4j.Logger;
 
@@ -35,15 +34,14 @@ public class DefaultMaxPathLengthConstraint extends AbstractFederationPolicyCons
     @Nonnull private final Logger log = LoggerFactory.getLogger(DefaultMaxPathLengthConstraint.class);
 
     /** {@inheritDoc} */
-    @Override @Nullable
-    protected Integer parseConstraint(@Nullable final Object constraint)
+    @Override @Nonnull
+    protected Integer parseConstraint(@Nonnull final Object constraint)
             throws ConstraintViolationException {
         if (constraint instanceof Integer integer) {
             return integer;
-        } else if (constraint != null) {
-            throw new ConstraintViolationException("Unexpected value type for max_path_length: " + constraint);
         }
-        return null;
+        log.debug("Unexpected value type for max_path_length: {}", constraint);
+        throw new ConstraintViolationException("Unexpected value type for max_path_length: " + constraint);
     }
 
     /** {@inheritDoc} */
diff --git a/oidfed-common-impl/src/main/java/net/shibboleth/oidfed/metadata/constraints/impl/DefaultNamingConstraintsConstraint.java b/oidfed-common-impl/src/main/java/net/shibboleth/oidfed/metadata/constraints/impl/DefaultNamingConstraintsConstraint.java
index 167c85b..210d207 100644
--- a/oidfed-common-impl/src/main/java/net/shibboleth/oidfed/metadata/constraints/impl/DefaultNamingConstraintsConstraint.java
+++ b/oidfed-common-impl/src/main/java/net/shibboleth/oidfed/metadata/constraints/impl/DefaultNamingConstraintsConstraint.java
@@ -17,7 +17,6 @@ package net.shibboleth.oidfed.metadata.constraints.impl;
 import java.net.URI;
 import java.util.List;
 import java.util.Map;
-import java.util.Objects;
 import java.util.Optional;
 import java.util.stream.Collectors;
 
@@ -46,18 +45,19 @@ public class DefaultNamingConstraintsConstraint extends AbstractFederationPolicy
     @Nonnull private final Logger log = LoggerFactory.getLogger(DefaultNamingConstraintsConstraint.class);
 
     /** {@inheritDoc} */
-    @Override @Nullable
-    protected Map<String, List<String>> parseConstraint(@Nullable final Object constraint)
+    @Override @Nonnull
+    protected Map<String, List<String>> parseConstraint(@Nonnull final Object constraint)
             throws ConstraintViolationException {
         if (constraint instanceof Map<?,?> map) {
-            return map.keySet().stream()
+            final Map<String, List<String>> result = map.keySet().stream()
                     .filter(key -> "permitted".equals(key) || "excluded".equals(key))
                     .map(String::valueOf)
                     .collect(Collectors.toMap(key -> key, key -> parseListOfStrings(key, map.get(key))));
-        } else if (constraint != null) {
-            throw new ConstraintViolationException("Unexpected value type for naming_constraints: " + constraint);
+            assert result != null;
+            return result;
         }
-        return null;
+        log.debug("Unexpected value type for naming_constraints: {}", constraint);
+        throw new ConstraintViolationException("Unexpected value type for naming_constraints: " + constraint);
     }
 
     /**
@@ -65,18 +65,19 @@ public class DefaultNamingConstraintsConstraint extends AbstractFederationPolicy
      * 
      * @param key the key (used solely in a potential exception)
      * @param raw the value to be parsed
-     * @return the value as list of strings, or null if the input was null
-     * @throws ConstraintViolationException if a non-null value could not be parsed
+     * @return the value as list of strings
+     * @throws ConstraintViolationException if a non-null value could not be parsed or if a value was null
      */
-    @Nullable private List<String> parseListOfStrings(@Nullable final String key, @Nullable final Object raw)
+    @Nonnull private List<String> parseListOfStrings(@Nullable final String key, @Nullable final Object raw)
             throws ConstraintViolationException {
         if (raw instanceof List<?> list) {
-            final List<String> result = list.stream().filter(Objects::nonNull).map(String::valueOf).toList();
-            return result;
-        } else if (raw != null) {
-            throw new ConstraintViolationException("The value for " + key + " is not a list: " + raw);
+            final List<String> result = list.stream().filter(String.class::isInstance).map(String::valueOf).toList();
+            if (result.size() == list.size()) {
+                return result;
+            }
         }
-        return null;
+        log.debug("The value for {} is not a list of strings: {}", key, raw);
+        throw new ConstraintViolationException("The value for " + key + " is not a list of strings: " + raw);
     }
 
     /** {@inheritDoc} */
diff --git a/oidfed-common-impl/src/test/java/net/shibboleth/oidfed/metadata/constraints/impl/AbstractConstraintTest.java b/oidfed-common-impl/src/test/java/net/shibboleth/oidfed/metadata/constraints/impl/AbstractConstraintTest.java
new file mode 100644
index 0000000..58e6faa
--- /dev/null
+++ b/oidfed-common-impl/src/test/java/net/shibboleth/oidfed/metadata/constraints/impl/AbstractConstraintTest.java
@@ -0,0 +1,53 @@
+/*
+ * 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.oidfed.metadata.constraints.impl;
+
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.when;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import net.shibboleth.oidfed.metadata.EntityConfiguration;
+import net.shibboleth.oidfed.metadata.EntityStatement;
+import net.shibboleth.oidfed.metadata.SubordinateStatement;
+
+/**
+ * Abstract test class constraints.
+ */
+public class AbstractConstraintTest {
+
+    protected List<EntityStatement<?>> initTrustChain(final EntityConfiguration entity,
+            final SubordinateStatement... subordinates) {
+        final EntityConfiguration anchor = mock(EntityConfiguration.class);
+        final List<EntityStatement<?>> trustChain = new ArrayList<>();
+        trustChain.add(entity);
+        List.of(subordinates).forEach(subordinate -> trustChain.add(subordinate));
+        trustChain.add(anchor);
+        return trustChain;
+    }
+
+    protected EntityConfiguration initEntityConfiguration(final String entityId) {
+        final EntityConfiguration entity = mock(EntityConfiguration.class);
+        when(entity.getSubject()).thenReturn(entityId);
+        return entity;
+    }
+
+    protected SubordinateStatement initSubordinateStatement(final String entityId) {
+        final SubordinateStatement subordinate = mock(SubordinateStatement.class);
+        when(subordinate.getSubject()).thenReturn(entityId);
+        return subordinate;
+    }
+}
diff --git a/oidfed-common-impl/src/test/java/net/shibboleth/oidfed/metadata/constraints/impl/DefaultMaxPathLengthConstraintTest.java b/oidfed-common-impl/src/test/java/net/shibboleth/oidfed/metadata/constraints/impl/DefaultMaxPathLengthConstraintTest.java
new file mode 100644
index 0000000..150ea96
--- /dev/null
+++ b/oidfed-common-impl/src/test/java/net/shibboleth/oidfed/metadata/constraints/impl/DefaultMaxPathLengthConstraintTest.java
@@ -0,0 +1,79 @@
+/*
+ * 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.oidfed.metadata.constraints.impl;
+
+import static org.mockito.Mockito.mock;
+
+import org.testng.Assert;
+import org.testng.annotations.BeforeMethod;
+import org.testng.annotations.Test;
+
+import net.shibboleth.oidfed.metadata.EntityConfiguration;
+import net.shibboleth.oidfed.metadata.SubordinateStatement;
+import net.shibboleth.shared.component.ComponentInitializationException;
+
+/**
+ * Unit tests for {@linkDefaultMaxPathLengthConstraint}.
+ */
+ at SuppressWarnings("null")
+public class DefaultMaxPathLengthConstraintTest extends AbstractConstraintTest {
+
+    DefaultMaxPathLengthConstraint constraint;
+
+    @BeforeMethod
+    public void init() throws ComponentInitializationException {
+        constraint = new DefaultMaxPathLengthConstraint();
+        constraint.setId("mockId");
+        constraint.initialize();
+    }
+
+    @Test
+    public void validate_nullInput_shouldReturnFalse() {
+        final EntityConfiguration entity = mock(EntityConfiguration.class);
+        final SubordinateStatement subordinate = mock(SubordinateStatement.class);
+        Assert.assertFalse(constraint.validate(null, subordinate, initTrustChain(entity, subordinate)));
+    }
+
+    @Test
+    public void validate_wrongInput_shouldReturnFalse() {
+        final var constraints = "should_not_be_string";
+        final EntityConfiguration entity = mock(EntityConfiguration.class);
+        final SubordinateStatement subordinate = mock(SubordinateStatement.class);
+        Assert.assertFalse(constraint.validate(constraints, subordinate, initTrustChain(entity, subordinate)));
+    }
+
+    @Test
+    public void validate_validInput_shouldReturnTrue() {
+        final EntityConfiguration entity = mock(EntityConfiguration.class);
+        final SubordinateStatement subordinate = mock(SubordinateStatement.class);
+        Assert.assertTrue(constraint.validate(1, subordinate, initTrustChain(entity, subordinate)));
+        Assert.assertTrue(constraint.validate(0, subordinate, initTrustChain(entity, subordinate)));
+        Assert.assertTrue(constraint.validate(2, subordinate,
+                initTrustChain(entity, initSubordinateStatement("https://sub1.federation.local"),
+                        initSubordinateStatement("https://sub2.federation.local"), subordinate,
+                        initSubordinateStatement("https://nomatter.other-federation.local"))));
+    }
+
+    @Test
+    public void validate_invalidInput_shouldReturnFalse() {
+        final EntityConfiguration entity = mock(EntityConfiguration.class);
+        final SubordinateStatement subordinate = mock(SubordinateStatement.class);
+        Assert.assertFalse(constraint.validate(1, subordinate,
+                initTrustChain(entity, initSubordinateStatement("https://sub1.federation.local"),
+                        initSubordinateStatement("https://sub2.federation.local"), subordinate,
+                        initSubordinateStatement("https://nomatter.other-federation.local"))));
+    }
+
+}
diff --git a/oidfed-common-impl/src/test/java/net/shibboleth/oidfed/metadata/constraints/impl/DefaultNamingConstraintsConstraintTest.java b/oidfed-common-impl/src/test/java/net/shibboleth/oidfed/metadata/constraints/impl/DefaultNamingConstraintsConstraintTest.java
new file mode 100644
index 0000000..4632b63
--- /dev/null
+++ b/oidfed-common-impl/src/test/java/net/shibboleth/oidfed/metadata/constraints/impl/DefaultNamingConstraintsConstraintTest.java
@@ -0,0 +1,154 @@
+/*
+ * 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.oidfed.metadata.constraints.impl;
+
+import static org.mockito.Mockito.mock;
+
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+import org.testng.Assert;
+import org.testng.annotations.BeforeMethod;
+import org.testng.annotations.Test;
+
+import net.shibboleth.oidfed.metadata.EntityConfiguration;
+import net.shibboleth.oidfed.metadata.SubordinateStatement;
+import net.shibboleth.shared.component.ComponentInitializationException;
+
+/**
+ * Unit tests for {@link DefaultNamingConstraintsConstraint}.
+ */
+ at SuppressWarnings("null")
+public class DefaultNamingConstraintsConstraintTest extends AbstractConstraintTest {
+
+    DefaultNamingConstraintsConstraint constraint;
+    
+    @BeforeMethod
+    public void init() throws ComponentInitializationException {
+        constraint = new DefaultNamingConstraintsConstraint();
+        constraint.setId("mockId");
+        constraint.initialize();
+    }
+
+    @Test
+    public void validate_nullInput_shouldReturnFalse() {
+        final EntityConfiguration entity = mock(EntityConfiguration.class);
+        final SubordinateStatement subordinate = mock(SubordinateStatement.class);
+        Assert.assertFalse(constraint.validate(null, subordinate, initTrustChain(entity, subordinate)));
+    }
+
+    @Test
+    public void validate_wrongInput_shouldReturnFalse() {
+        final var constraints = List.of("should", "not", "be", "list");
+        final EntityConfiguration entity = mock(EntityConfiguration.class);
+        final SubordinateStatement subordinate = mock(SubordinateStatement.class);
+        Assert.assertFalse(constraint.validate(constraints, subordinate, initTrustChain(entity, subordinate)));
+    }
+
+    @Test
+    public void validate_wrongInput_nullPermitted_shouldReturnFalse() {
+        final var constraints = new HashMap<String, List<String>>();
+        constraints.put("permitted", null);
+        final EntityConfiguration entity = initEntityConfiguration("https://entity.federation.local");
+        final SubordinateStatement subordinate = mock(SubordinateStatement.class);
+        Assert.assertFalse(constraint.validate(constraints, subordinate, initTrustChain(entity, subordinate)));
+    }
+
+    @Test
+    public void validate_wrongInput_nullExcluded_shouldReturnFalse() {
+        final var constraints = new HashMap<String, List<String>>();
+        constraints.put("excluded", null);
+        final EntityConfiguration entity = initEntityConfiguration("https://entity.federation.local");
+        final SubordinateStatement subordinate = mock(SubordinateStatement.class);
+        Assert.assertFalse(constraint.validate(constraints, subordinate, initTrustChain(entity, subordinate)));
+    }
+
+    @Test
+    public void validate_validInput_leafPassingPermitted_shouldReturnTrue() {
+        final var constraints = Map.of("permitted", List.of(".federation.local"));
+        final EntityConfiguration entity = initEntityConfiguration("https://entity.federation.local");
+        final SubordinateStatement subordinate = mock(SubordinateStatement.class);
+        Assert.assertTrue(constraint.validate(constraints, subordinate, initTrustChain(entity, subordinate)));
+    }
+
+    @Test
+    public void validate_validInput_longerChainPassingPermitted_shouldReturnTrue() {
+        final var constraints = Map.of("permitted", List.of(".federation.local"));
+        final EntityConfiguration entity = initEntityConfiguration("https://entity.federation.local");
+        final SubordinateStatement subordinate = mock(SubordinateStatement.class);
+        Assert.assertTrue(constraint.validate(constraints, subordinate,
+                initTrustChain(entity, initSubordinateStatement("https://sub1.federation.local"),
+                        initSubordinateStatement("https://sub2.federation.local"), subordinate,
+                        initSubordinateStatement("https://nomatter.other-federation.local"))));
+    }
+
+    @Test
+    public void validate_validInput_notPassingPermitted_shouldReturnFalse() {
+        final var constraints = Map.of("permitted", List.of(".federation.local"));
+        final EntityConfiguration entity = initEntityConfiguration("https://entity.other-federation.local");
+        final SubordinateStatement subordinate = mock(SubordinateStatement.class);
+        Assert.assertFalse(constraint.validate(constraints, subordinate, initTrustChain(entity, subordinate)));
+    }
+
+    @Test
+    public void validate_validInput_subordinateNotPassingPermitted_shouldReturnFalse() {
+        final var constraints = Map.of("permitted", List.of(".federation.local"));
+        final EntityConfiguration entity = initEntityConfiguration("https://entity.federation.local");
+        final SubordinateStatement subordinate = mock(SubordinateStatement.class);
+        Assert.assertFalse(constraint.validate(constraints, subordinate,
+                initTrustChain(entity, initSubordinateStatement("https://sub1.other-federation.local"),
+                        initSubordinateStatement("https://sub2.federation.local"), subordinate,
+                        initSubordinateStatement("https://nomatter.other-federation.local"))));
+    }
+
+    @Test
+    public void validate_validInput_passingExcluded_shouldReturnTrue() {
+        final var constraints = Map.of("excluded", List.of(".federation.local"));
+        final EntityConfiguration entity = initEntityConfiguration("https://entity.other-federation.local");
+        final SubordinateStatement subordinate = mock(SubordinateStatement.class);
+        Assert.assertTrue(constraint.validate(constraints, subordinate, initTrustChain(entity, subordinate)));
+    }
+
+    @Test
+    public void validate_validInput_longerChainPassingExcluded_shouldReturnTrue() {
+        final var constraints = Map.of("excluded", List.of(".federation.local"));
+        final EntityConfiguration entity = initEntityConfiguration("https://entity.other-federation.local");
+        final SubordinateStatement subordinate = mock(SubordinateStatement.class);
+        Assert.assertTrue(constraint.validate(constraints, subordinate,
+                initTrustChain(entity, initSubordinateStatement("https://sub1.other-federation.local"),
+                        initSubordinateStatement("https://sub2.other-federation.local"), subordinate,
+                        initSubordinateStatement("https://nomatter.federation.local"))));
+    }
+
+    @Test
+    public void validate_validInput_notPassingExcluded_shouldReturnFalse() {
+        final var constraints = Map.of("excluded", List.of(".federation.local"));
+        final EntityConfiguration entity = initEntityConfiguration("https://entity.federation.local");
+        final SubordinateStatement subordinate = mock(SubordinateStatement.class);
+        Assert.assertFalse(constraint.validate(constraints, subordinate, initTrustChain(entity, subordinate)));
+    }
+
+    @Test
+    public void validate_validInput_subordinateNotPassingExcluded_shouldReturnFalse() {
+        final var constraints = Map.of("excluded", List.of(".federation.local"));
+        final EntityConfiguration entity = initEntityConfiguration("https://entity.other-federation.local");
+        final SubordinateStatement subordinate = mock(SubordinateStatement.class);
+        Assert.assertFalse(constraint.validate(constraints, subordinate,
+                initTrustChain(entity, initSubordinateStatement("https://sub1.federation.local"),
+                        initSubordinateStatement("https://sub2.other-federation.local"), subordinate,
+                        initSubordinateStatement("https://nomatter.federation.local"))));
+    }
+}

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


More information about the commits mailing list