You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@mina.apache.org by lg...@apache.org on 2016/07/26 18:27:03 UTC

mina-sshd git commit: [SSHD-681] Provide default implementations for ServerAuthenticationManager#getSetUserAuthFactories overloading with strings

Repository: mina-sshd
Updated Branches:
  refs/heads/master 3c6b0540c -> d8e681de4


[SSHD-681] Provide default implementations for ServerAuthenticationManager#getSetUserAuthFactories overloading with strings


Project: http://git-wip-us.apache.org/repos/asf/mina-sshd/repo
Commit: http://git-wip-us.apache.org/repos/asf/mina-sshd/commit/d8e681de
Tree: http://git-wip-us.apache.org/repos/asf/mina-sshd/tree/d8e681de
Diff: http://git-wip-us.apache.org/repos/asf/mina-sshd/diff/d8e681de

Branch: refs/heads/master
Commit: d8e681de402070911d1c75bebe468d266345a33b
Parents: 3c6b054
Author: Lyor Goldstein <ly...@gmail.com>
Authored: Tue Jul 26 21:28:27 2016 +0300
Committer: Lyor Goldstein <ly...@gmail.com>
Committed: Tue Jul 26 21:28:27 2016 +0300

----------------------------------------------------------------------
 .../server/ServerAuthenticationManager.java     |  27 ++++
 .../sshd/server/auth/AbstractUserAuth.java      |   1 +
 .../server/auth/BuiltinUserAuthFactories.java   | 142 +++++++++++++++++++
 .../client/ClientAuthenticationManagerTest.java |   2 +-
 .../server/ServerAuthenticationManagerTest.java | 127 +++++++++++++++++
 .../auth/BuiltinUserAuthFactoriesTest.java      | 117 +++++++++++++++
 6 files changed, 415 insertions(+), 1 deletion(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/mina-sshd/blob/d8e681de/sshd-core/src/main/java/org/apache/sshd/server/ServerAuthenticationManager.java
----------------------------------------------------------------------
diff --git a/sshd-core/src/main/java/org/apache/sshd/server/ServerAuthenticationManager.java b/sshd-core/src/main/java/org/apache/sshd/server/ServerAuthenticationManager.java
index 4298aa9..0d8a6e8 100644
--- a/sshd-core/src/main/java/org/apache/sshd/server/ServerAuthenticationManager.java
+++ b/sshd-core/src/main/java/org/apache/sshd/server/ServerAuthenticationManager.java
@@ -20,11 +20,16 @@
 package org.apache.sshd.server;
 
 import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Collection;
 import java.util.Collections;
 import java.util.List;
 
 import org.apache.sshd.common.NamedFactory;
+import org.apache.sshd.common.NamedResource;
 import org.apache.sshd.common.util.GenericUtils;
+import org.apache.sshd.common.util.ValidateUtils;
+import org.apache.sshd.server.auth.BuiltinUserAuthFactories;
 import org.apache.sshd.server.auth.UserAuth;
 import org.apache.sshd.server.auth.gss.GSSAuthenticator;
 import org.apache.sshd.server.auth.gss.UserAuthGSSFactory;
@@ -60,7 +65,29 @@ public interface ServerAuthenticationManager {
      * @return a list of named <code>UserAuth</code> factories, never {@code null}/empty
      */
     List<NamedFactory<UserAuth>> getUserAuthFactories();
+    default String getUserAuthFactoriesNameList() {
+        return NamedResource.Utils.getNames(getUserAuthFactories());
+    }
+    default List<String> getUserAuthFactoriesNames() {
+        return NamedResource.Utils.getNameList(getUserAuthFactories());
+    }
+
     void setUserAuthFactories(List<NamedFactory<UserAuth>> userAuthFactories);
+    default void setUserAuthFactoriesNameList(String names) {
+        setUserAuthFactoriesNames(GenericUtils.split(names, ','));
+    }
+    default void setUserAuthFactoriesNames(String ... names) {
+        setUserAuthFactoriesNames(GenericUtils.isEmpty((Object[]) names) ? Collections.<String>emptyList() : Arrays.asList(names));
+    }
+    default void setUserAuthFactoriesNames(Collection<String> names) {
+        BuiltinUserAuthFactories.ParseResult result = BuiltinUserAuthFactories.parseFactoriesList(names);
+        @SuppressWarnings({ "rawtypes", "unchecked" })
+        List<NamedFactory<UserAuth>> factories =
+                (List) ValidateUtils.checkNotNullAndNotEmpty(result.getParsedFactories(), "No supported cipher factories: %s", names);
+        Collection<String> unsupported = result.getUnsupportedFactories();
+        ValidateUtils.checkTrue(GenericUtils.isEmpty(unsupported), "Unsupported cipher factories found: %s", unsupported);
+        setUserAuthFactories(factories);
+    }
 
     /**
      * Retrieve the <code>PublickeyAuthenticator</code> to be used by SSH server.

http://git-wip-us.apache.org/repos/asf/mina-sshd/blob/d8e681de/sshd-core/src/main/java/org/apache/sshd/server/auth/AbstractUserAuth.java
----------------------------------------------------------------------
diff --git a/sshd-core/src/main/java/org/apache/sshd/server/auth/AbstractUserAuth.java b/sshd-core/src/main/java/org/apache/sshd/server/auth/AbstractUserAuth.java
index 578e1d1..7211b09 100644
--- a/sshd-core/src/main/java/org/apache/sshd/server/auth/AbstractUserAuth.java
+++ b/sshd-core/src/main/java/org/apache/sshd/server/auth/AbstractUserAuth.java
@@ -24,6 +24,7 @@ import org.apache.sshd.common.util.logging.AbstractLoggingBean;
 import org.apache.sshd.server.session.ServerSession;
 
 /**
+ * @author <a href="mailto:dev@mina.apache.org">Apache MINA SSHD Project</a>
  */
 public abstract class AbstractUserAuth extends AbstractLoggingBean implements UserAuth {
     private final String name;

http://git-wip-us.apache.org/repos/asf/mina-sshd/blob/d8e681de/sshd-core/src/main/java/org/apache/sshd/server/auth/BuiltinUserAuthFactories.java
----------------------------------------------------------------------
diff --git a/sshd-core/src/main/java/org/apache/sshd/server/auth/BuiltinUserAuthFactories.java b/sshd-core/src/main/java/org/apache/sshd/server/auth/BuiltinUserAuthFactories.java
new file mode 100644
index 0000000..05c395b
--- /dev/null
+++ b/sshd-core/src/main/java/org/apache/sshd/server/auth/BuiltinUserAuthFactories.java
@@ -0,0 +1,142 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you 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 org.apache.sshd.server.auth;
+
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Collection;
+import java.util.Collections;
+import java.util.EnumSet;
+import java.util.List;
+import java.util.Objects;
+import java.util.Set;
+
+import org.apache.sshd.common.Factory;
+import org.apache.sshd.common.NamedFactory;
+import org.apache.sshd.common.NamedResource;
+import org.apache.sshd.common.config.NamedFactoriesListParseResult;
+import org.apache.sshd.common.util.GenericUtils;
+import org.apache.sshd.server.auth.gss.UserAuthGSSFactory;
+import org.apache.sshd.server.auth.hostbased.UserAuthHostBasedFactory;
+import org.apache.sshd.server.auth.keyboard.UserAuthKeyboardInteractiveFactory;
+import org.apache.sshd.server.auth.password.UserAuthPasswordFactory;
+import org.apache.sshd.server.auth.pubkey.UserAuthPublicKeyFactory;
+
+/**
+ * Provides a centralized location for the default built-in authentication factories
+ *
+ * @author <a href="mailto:dev@mina.apache.org">Apache MINA SSHD Project</a>
+ */
+public enum BuiltinUserAuthFactories implements NamedFactory<UserAuthFactory> {
+    PASSWORD(UserAuthPasswordFactory.INSTANCE),
+    PUBLICKEY(UserAuthPublicKeyFactory.INSTANCE),
+    KBINTERACTIVE(UserAuthKeyboardInteractiveFactory.INSTANCE),
+    HOSTBASED(UserAuthHostBasedFactory.INSTANCE),
+    GSS(UserAuthGSSFactory.INSTANCE);
+
+    public static final Set<BuiltinUserAuthFactories> VALUES =
+            Collections.unmodifiableSet(EnumSet.allOf(BuiltinUserAuthFactories.class));
+
+    private final UserAuthFactory factory;
+
+    BuiltinUserAuthFactories(UserAuthFactory factory) {
+        this.factory = Objects.requireNonNull(factory, "No delegate factory instance");
+    }
+
+    @Override
+    public UserAuthFactory create() {
+        return factory;
+    }
+
+    @Override
+    public String getName() {
+        return factory.getName();
+    }
+
+    /**
+     * @param name The factory name (case <U>insensitive</U>) - ignored if {@code null}/empty
+     * @return The matching factory instance - {@code null} if no match found
+     */
+    public static UserAuthFactory fromFactoryName(String name) {
+        Factory<UserAuthFactory> factory = NamedResource.Utils.findByName(name, String.CASE_INSENSITIVE_ORDER, VALUES);
+        if (factory == null) {
+            return null;
+        }
+
+        return factory.create();
+    }
+
+    /**
+     * @param factories A comma-separated list of factories' names - ignored if {@code null}/empty
+     * @return A {@link ParseResult} containing the successfully parsed
+     * factories and the unknown ones. <B>Note:</B> it is up to caller to
+     * ensure that the lists do not contain duplicates
+     */
+    public static ParseResult parseFactoriesList(String factories) {
+        return parseFactoriesList(GenericUtils.split(factories, ','));
+    }
+
+    public static ParseResult parseFactoriesList(String... factories) {
+        return parseFactoriesList(GenericUtils.isEmpty((Object[]) factories) ? Collections.<String>emptyList() : Arrays.asList(factories));
+    }
+
+    public static ParseResult parseFactoriesList(Collection<String> factories) {
+        if (GenericUtils.isEmpty(factories)) {
+            return ParseResult.EMPTY;
+        }
+
+        List<UserAuthFactory> resolved = new ArrayList<>(factories.size());
+        List<String> unknown = Collections.emptyList();
+        for (String name : factories) {
+            UserAuthFactory c = resolveFactory(name);
+            if (c != null) {
+                resolved.add(c);
+            } else {
+                // replace the (unmodifiable) empty list with a real one
+                if (unknown.isEmpty()) {
+                    unknown = new ArrayList<>();
+                }
+                unknown.add(name);
+            }
+        }
+
+        return new ParseResult(resolved, unknown);
+    }
+
+    public static UserAuthFactory resolveFactory(String name) {
+        if (GenericUtils.isEmpty(name)) {
+            return null;
+        }
+
+        return fromFactoryName(name);
+    }
+
+    /**
+     * Holds the result of {@link BuiltinUserAuthFactories#parseFactoriesList(String)}
+     *
+     * @author <a href="mailto:dev@mina.apache.org">Apache MINA SSHD Project</a>
+     */
+    public static class ParseResult extends NamedFactoriesListParseResult<UserAuth, UserAuthFactory> {
+        public static final ParseResult EMPTY = new ParseResult(Collections.<UserAuthFactory>emptyList(), Collections.<String>emptyList());
+
+        public ParseResult(List<UserAuthFactory> parsed, List<String> unsupported) {
+            super(parsed, unsupported);
+        }
+    }
+}

http://git-wip-us.apache.org/repos/asf/mina-sshd/blob/d8e681de/sshd-core/src/test/java/org/apache/sshd/client/ClientAuthenticationManagerTest.java
----------------------------------------------------------------------
diff --git a/sshd-core/src/test/java/org/apache/sshd/client/ClientAuthenticationManagerTest.java b/sshd-core/src/test/java/org/apache/sshd/client/ClientAuthenticationManagerTest.java
index 61dc4a2..0d08497 100644
--- a/sshd-core/src/test/java/org/apache/sshd/client/ClientAuthenticationManagerTest.java
+++ b/sshd-core/src/test/java/org/apache/sshd/client/ClientAuthenticationManagerTest.java
@@ -68,7 +68,7 @@ public class ClientAuthenticationManagerTest extends BaseTestSupport {
     @Test
     public void testDefaultUserAuthFactoriesMethods() {
         AtomicReference<List<NamedFactory<UserAuth>>> factoriesHolder = new AtomicReference<>();
-        @SuppressWarnings({"checkstyle:anoninnerlength", "checkstyle:methodlength"})
+        @SuppressWarnings("checkstyle:anoninnerlength")
         ClientAuthenticationManager manager = new ClientAuthenticationManager() {
             @Override
             public List<NamedFactory<UserAuth>> getUserAuthFactories() {

http://git-wip-us.apache.org/repos/asf/mina-sshd/blob/d8e681de/sshd-core/src/test/java/org/apache/sshd/server/ServerAuthenticationManagerTest.java
----------------------------------------------------------------------
diff --git a/sshd-core/src/test/java/org/apache/sshd/server/ServerAuthenticationManagerTest.java b/sshd-core/src/test/java/org/apache/sshd/server/ServerAuthenticationManagerTest.java
new file mode 100644
index 0000000..75d49ae
--- /dev/null
+++ b/sshd-core/src/test/java/org/apache/sshd/server/ServerAuthenticationManagerTest.java
@@ -0,0 +1,127 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you 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 org.apache.sshd.server;
+
+import java.util.List;
+import java.util.concurrent.atomic.AtomicReference;
+
+import org.apache.sshd.common.NamedFactory;
+import org.apache.sshd.common.NamedResource;
+import org.apache.sshd.common.util.GenericUtils;
+import org.apache.sshd.server.auth.BuiltinUserAuthFactories;
+import org.apache.sshd.server.auth.UserAuth;
+import org.apache.sshd.server.auth.gss.GSSAuthenticator;
+import org.apache.sshd.server.auth.hostbased.HostBasedAuthenticator;
+import org.apache.sshd.server.auth.keyboard.KeyboardInteractiveAuthenticator;
+import org.apache.sshd.server.auth.password.PasswordAuthenticator;
+import org.apache.sshd.server.auth.pubkey.PublickeyAuthenticator;
+import org.apache.sshd.util.test.BaseTestSupport;
+import org.junit.FixMethodOrder;
+import org.junit.Test;
+import org.junit.runners.MethodSorters;
+
+/**
+ * @author <a href="mailto:dev@mina.apache.org">Apache MINA SSHD Project</a>
+ */
+@FixMethodOrder(MethodSorters.NAME_ASCENDING)
+public class ServerAuthenticationManagerTest extends BaseTestSupport {
+    public ServerAuthenticationManagerTest() {
+        super();
+    }
+
+    @Test
+    public void testDefaultUserAuthFactoriesMethods() {
+        AtomicReference<List<NamedFactory<UserAuth>>> factoriesHolder = new AtomicReference<>();
+        @SuppressWarnings("checkstyle:anoninnerlength")
+        ServerAuthenticationManager manager = new ServerAuthenticationManager() {
+            @Override
+            public List<NamedFactory<UserAuth>> getUserAuthFactories() {
+                return factoriesHolder.get();
+            }
+
+            @Override
+            public void setUserAuthFactories(List<NamedFactory<UserAuth>> userAuthFactories) {
+                assertNull("Unexpected multiple invocation", factoriesHolder.getAndSet(userAuthFactories));
+            }
+
+            @Override
+            public PasswordAuthenticator getPasswordAuthenticator() {
+                return null;
+            }
+
+            @Override
+            public void setPasswordAuthenticator(PasswordAuthenticator passwordAuthenticator) {
+                throw new UnsupportedOperationException("setPasswordAuthenticator(" + passwordAuthenticator + ")");
+            }
+
+            @Override
+            public PublickeyAuthenticator getPublickeyAuthenticator() {
+                return null;
+            }
+
+            @Override
+            public void setPublickeyAuthenticator(PublickeyAuthenticator publickeyAuthenticator) {
+                throw new UnsupportedOperationException("setPublickeyAuthenticator(" + publickeyAuthenticator + ")");
+            }
+
+            @Override
+            public KeyboardInteractiveAuthenticator getKeyboardInteractiveAuthenticator() {
+                return null;
+            }
+
+            @Override
+            public void setKeyboardInteractiveAuthenticator(KeyboardInteractiveAuthenticator interactiveAuthenticator) {
+                throw new UnsupportedOperationException("setKeyboardInteractiveAuthenticator(" + interactiveAuthenticator + ")");
+            }
+
+            @Override
+            public GSSAuthenticator getGSSAuthenticator() {
+                return null;
+            }
+
+            @Override
+            public void setGSSAuthenticator(GSSAuthenticator gssAuthenticator) {
+                throw new UnsupportedOperationException("setGSSAuthenticator(" + gssAuthenticator + ")");
+            }
+
+            @Override
+            public HostBasedAuthenticator getHostBasedAuthenticator() {
+                return null;
+            }
+
+            @Override
+            public void setHostBasedAuthenticator(HostBasedAuthenticator hostBasedAuthenticator) {
+                throw new UnsupportedOperationException("setHostBasedAuthenticator(" + hostBasedAuthenticator + ")");
+            }
+        };
+        assertEquals("Mismatched initial factories list", "", manager.getUserAuthFactoriesNameList());
+
+        String expected = NamedResource.Utils.getNames(BuiltinUserAuthFactories.VALUES);
+        manager.setUserAuthFactoriesNameList(expected);
+        assertEquals("Mismatched updated factories names", expected, manager.getUserAuthFactoriesNameList());
+
+        List<NamedFactory<UserAuth>> factories = factoriesHolder.get();
+        assertEquals("Mismatched factories count", BuiltinUserAuthFactories.VALUES.size(), GenericUtils.size(factories));
+        for (BuiltinUserAuthFactories f : BuiltinUserAuthFactories.VALUES) {
+            assertTrue("Missing factory=" + f.name(), factories.contains(f.create()));
+        }
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/mina-sshd/blob/d8e681de/sshd-core/src/test/java/org/apache/sshd/server/auth/BuiltinUserAuthFactoriesTest.java
----------------------------------------------------------------------
diff --git a/sshd-core/src/test/java/org/apache/sshd/server/auth/BuiltinUserAuthFactoriesTest.java b/sshd-core/src/test/java/org/apache/sshd/server/auth/BuiltinUserAuthFactoriesTest.java
new file mode 100644
index 0000000..df6ed4c
--- /dev/null
+++ b/sshd-core/src/test/java/org/apache/sshd/server/auth/BuiltinUserAuthFactoriesTest.java
@@ -0,0 +1,117 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you 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 org.apache.sshd.server.auth;
+
+import java.lang.reflect.Field;
+import java.lang.reflect.Modifier;
+import java.util.Collection;
+import java.util.List;
+import java.util.Objects;
+import java.util.TreeSet;
+
+import org.apache.sshd.common.auth.UserAuthMethodFactory;
+import org.apache.sshd.common.util.GenericUtils;
+import org.apache.sshd.server.auth.BuiltinUserAuthFactories.ParseResult;
+import org.apache.sshd.server.auth.gss.UserAuthGSSFactory;
+import org.apache.sshd.util.test.BaseTestSupport;
+import org.junit.BeforeClass;
+import org.junit.FixMethodOrder;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.junit.runners.MethodSorters;
+import org.junit.runners.Parameterized;
+import org.junit.runners.Parameterized.Parameters;
+
+/**
+ * @author <a href="mailto:dev@mina.apache.org">Apache MINA SSHD Project</a>
+ */
+@FixMethodOrder(MethodSorters.NAME_ASCENDING)
+@RunWith(Parameterized.class)   // see https://github.com/junit-team/junit/wiki/Parameterized-tests
+public class BuiltinUserAuthFactoriesTest extends BaseTestSupport {
+    private final BuiltinUserAuthFactories factory;
+
+    public BuiltinUserAuthFactoriesTest(BuiltinUserAuthFactories factory) {
+        this.factory = factory;
+    }
+
+    @Parameters(name = "Factory={0}")
+    public static Collection<Object[]> parameters() {
+        return parameterize(BuiltinUserAuthFactories.VALUES);
+    }
+
+    @BeforeClass
+    public static void testAllConstantsCovered() throws Exception {
+        Field[] fields = UserAuthMethodFactory.class.getDeclaredFields();
+        Collection<String> factories = new TreeSet<>(String.CASE_INSENSITIVE_ORDER);
+
+        for (Field f : fields) {
+            if (f.getType() != String.class) {
+                continue;
+            }
+
+            int mods = f.getModifiers();
+            if ((!Modifier.isStatic(mods)) || (!Modifier.isFinal(mods)) || (!Modifier.isPublic(mods))) {
+                continue;
+            }
+
+            String name = Objects.toString(f.get(null), null);
+            UserAuthFactory factory = BuiltinUserAuthFactories.fromFactoryName(name);
+            if (factory == null) {
+                continue;
+            }
+
+            assertTrue("Duplicate factory name constant: " + name, factories.add(name));
+        }
+
+        assertTrue("Unexpected GSS name constant", factories.add(UserAuthGSSFactory.NAME));
+        assertEquals("Mismatched factories names count: " + factories, factories.size(), BuiltinUserAuthFactories.VALUES.size());
+    }
+
+    @Test
+    public void testSingletonFactoryInstance() {
+        UserAuthFactory expected = factory.create();
+        for (int index = 1; index <= Byte.SIZE; index++) {
+            assertSame("Mismatched factory instance at invocation #" + index, expected, factory.create());
+        }
+    }
+
+    @Test
+    public void testFromFactoryName() {
+        String name = factory.getName();
+        UserAuthFactory expected = factory.create();
+        for (int index = 1, count = name.length(); index <= count; index++) {
+            UserAuthFactory actual = BuiltinUserAuthFactories.fromFactoryName(name);
+            assertSame("Mismatched factory instance for name=" + name, expected, actual);
+            name = shuffleCase(name);   // prepare for next iteration
+        }
+    }
+
+    @Test
+    public void testParseResult() {
+        ParseResult result = BuiltinUserAuthFactories.parseFactoriesList(factory.getName());
+        assertNotNull("No parse result", result);
+
+        List<UserAuthFactory> parsed = result.getParsedFactories();
+        assertEquals("Mismatched parsed count", 1, GenericUtils.size(parsed));
+        assertSame("Mismatched parsed factory instance", factory.create(), parsed.get(0));
+
+        Collection<String> unsupported = result.getUnsupportedFactories();
+        assertTrue("Unexpected unsupported values: " + unsupported, GenericUtils.isEmpty(unsupported));
+    }
+}