AMBARI-21307 Added unit tests, doumented the code
Project: http://git-wip-us.apache.org/repos/asf/ambari/repo Commit: http://git-wip-us.apache.org/repos/asf/ambari/commit/78007771 Tree: http://git-wip-us.apache.org/repos/asf/ambari/tree/78007771 Diff: http://git-wip-us.apache.org/repos/asf/ambari/diff/78007771 Branch: refs/heads/feature-branch-AMBARI-21307 Commit: 78007771ac13100673e68901a9cd44c693b78cf9 Parents: 23aa377 Author: lpuskas <lpus...@apache.org> Authored: Thu Oct 19 14:41:33 2017 +0200 Committer: lpuskas <lpus...@apache.org> Committed: Thu Oct 26 11:28:52 2017 +0200 ---------------------------------------------------------------------- .../ads/detectors/ChainedAttributeDetector.java | 9 +- .../ads/detectors/GroupMemberAttrDetector.java | 2 +- .../ads/detectors/UserObjectClassDetector.java | 1 - .../server/ldap/LdapModuleFunctionalTest.java | 106 ++++++------------ .../detectors/GroupMemberAttrDetectorTest.java | 107 +++++++++++++++++++ 5 files changed, 151 insertions(+), 74 deletions(-) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/ambari/blob/78007771/ambari-server/src/main/java/org/apache/ambari/server/ldap/service/ads/detectors/ChainedAttributeDetector.java ---------------------------------------------------------------------- diff --git a/ambari-server/src/main/java/org/apache/ambari/server/ldap/service/ads/detectors/ChainedAttributeDetector.java b/ambari-server/src/main/java/org/apache/ambari/server/ldap/service/ads/detectors/ChainedAttributeDetector.java index 1fb7a4c..094922b 100644 --- a/ambari-server/src/main/java/org/apache/ambari/server/ldap/service/ads/detectors/ChainedAttributeDetector.java +++ b/ambari-server/src/main/java/org/apache/ambari/server/ldap/service/ads/detectors/ChainedAttributeDetector.java @@ -39,7 +39,7 @@ public class ChainedAttributeDetector implements AttributeDetector<Entry> { /** * The set of detectors this instance delegates to */ - private Set<AttributeDetector> detectors; + private final Set<AttributeDetector> detectors; @Inject public ChainedAttributeDetector(Set<AttributeDetector> detectors) { @@ -63,4 +63,11 @@ public class ChainedAttributeDetector implements AttributeDetector<Entry> { } return detectedAttributes; } + + @Override + public String toString() { + return "ChainedAttributeDetector{" + + "detectors=" + detectors + + '}'; + } } http://git-wip-us.apache.org/repos/asf/ambari/blob/78007771/ambari-server/src/main/java/org/apache/ambari/server/ldap/service/ads/detectors/GroupMemberAttrDetector.java ---------------------------------------------------------------------- diff --git a/ambari-server/src/main/java/org/apache/ambari/server/ldap/service/ads/detectors/GroupMemberAttrDetector.java b/ambari-server/src/main/java/org/apache/ambari/server/ldap/service/ads/detectors/GroupMemberAttrDetector.java index ffe4027..8c34ef8 100644 --- a/ambari-server/src/main/java/org/apache/ambari/server/ldap/service/ads/detectors/GroupMemberAttrDetector.java +++ b/ambari-server/src/main/java/org/apache/ambari/server/ldap/service/ads/detectors/GroupMemberAttrDetector.java @@ -21,7 +21,7 @@ import org.apache.directory.api.ldap.model.entry.Entry; public class GroupMemberAttrDetector extends OccurrenceAndWeightBasedDetector { - private enum GroupMemberAttr { + enum GroupMemberAttr { MEMBER("member", 1), MEMBER_UID("memberUid", 1), http://git-wip-us.apache.org/repos/asf/ambari/blob/78007771/ambari-server/src/main/java/org/apache/ambari/server/ldap/service/ads/detectors/UserObjectClassDetector.java ---------------------------------------------------------------------- diff --git a/ambari-server/src/main/java/org/apache/ambari/server/ldap/service/ads/detectors/UserObjectClassDetector.java b/ambari-server/src/main/java/org/apache/ambari/server/ldap/service/ads/detectors/UserObjectClassDetector.java index 53aad8b..bf2f5b8 100644 --- a/ambari-server/src/main/java/org/apache/ambari/server/ldap/service/ads/detectors/UserObjectClassDetector.java +++ b/ambari-server/src/main/java/org/apache/ambari/server/ldap/service/ads/detectors/UserObjectClassDetector.java @@ -53,7 +53,6 @@ public class UserObjectClassDetector extends OccurrenceAndWeightBasedDetector { occurrenceMap().put(ocVal.ocVal(), 0); weightsMap().put(ocVal.ocVal(), ocVal.weight()); } - } @Override http://git-wip-us.apache.org/repos/asf/ambari/blob/78007771/ambari-server/src/test/java/org/apache/ambari/server/ldap/LdapModuleFunctionalTest.java ---------------------------------------------------------------------- diff --git a/ambari-server/src/test/java/org/apache/ambari/server/ldap/LdapModuleFunctionalTest.java b/ambari-server/src/test/java/org/apache/ambari/server/ldap/LdapModuleFunctionalTest.java index 875ce97..c43e06c 100644 --- a/ambari-server/src/test/java/org/apache/ambari/server/ldap/LdapModuleFunctionalTest.java +++ b/ambari-server/src/test/java/org/apache/ambari/server/ldap/LdapModuleFunctionalTest.java @@ -18,23 +18,21 @@ import java.util.Map; import org.apache.ambari.server.ldap.domain.AmbariLdapConfigKeys; import org.apache.ambari.server.ldap.domain.AmbariLdapConfiguration; +import org.apache.ambari.server.ldap.domain.AmbariLdapConfigurationFactory; import org.apache.ambari.server.ldap.domain.TestAmbariLdapConfigurationFactory; -import org.apache.ambari.server.ldap.service.LdapConfigurationService; -import org.apache.ambari.server.ldap.service.LdapFacade; import org.apache.ambari.server.ldap.service.ads.LdapConnectionTemplateFactory; import org.apache.ambari.server.ldap.service.ads.detectors.AttributeDetectorFactory; import org.apache.directory.api.ldap.model.constants.SchemaConstants; import org.apache.directory.api.ldap.model.exception.LdapException; -import org.apache.directory.api.ldap.model.exception.LdapInvalidDnException; -import org.apache.directory.api.ldap.model.name.Dn; import org.apache.directory.ldap.client.api.LdapConnection; import org.apache.directory.ldap.client.template.ConnectionCallback; import org.apache.directory.ldap.client.template.LdapConnectionTemplate; -import org.apache.directory.ldap.client.template.exception.PasswordException; import org.junit.Assert; import org.junit.BeforeClass; import org.junit.Ignore; import org.junit.Test; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; import com.google.common.collect.Maps; import com.google.inject.AbstractModule; @@ -43,47 +41,61 @@ import com.google.inject.Injector; import com.google.inject.Module; import com.google.inject.util.Modules; +/** + * Test for the GUICE LdapModule setup + * + * - checks the module's bindings (can the GUICE context be created properely) + * - checks for specific instances in the GUICE context (re they constructed properly, what is the instance' scope) + * + * It's named functional test as it creates a GUICE context. ("Real" unit tests only mock a class' collaborators, and + * are more lightweight) + * + * By default the test is ignored, as it connects to external LDAP instances, thus in different environments may fail + */ @Ignore public class LdapModuleFunctionalTest { + private static final Logger LOG = LoggerFactory.getLogger(LdapModuleFunctionalTest.class); private static Injector injector; - private static Module testModule; - private static TestAmbariLdapConfigurationFactory ldapConfigurationFactory = new TestAmbariLdapConfigurationFactory(); + @BeforeClass public static void beforeClass() throws Exception { // overriding bindings for testing purposes - testModule = Modules.override(new LdapModule()).with(new AbstractModule() { + Module testModule = Modules.override(new LdapModule()).with(new AbstractModule() { @Override protected void configure() { // override the configuration instance binding not to access the database - bind(AmbariLdapConfiguration.class).toInstance(ldapConfigurationFactory.createLdapConfiguration(getProps())); + bind(AmbariLdapConfiguration.class).toInstance(new TestAmbariLdapConfigurationFactory().createLdapConfiguration(getADProps())); } }); injector = Guice.createInjector(testModule); } - @Test() - public void shouldLdapTemplateBeInstantiated() throws LdapInvalidDnException, PasswordException { + @Test + public void shouldLdapTemplateBeInstantiated() throws Exception { // GIVEN // the injector is set up Assert.assertNotNull(injector); // WHEN - // the ldap connection template is retrieved - LdapConnectionTemplate template = injector.getInstance(LdapConnectionTemplate.class); + LdapConnectionTemplateFactory ldapConnectionTemplateFactory = injector.getInstance(LdapConnectionTemplateFactory.class); + AmbariLdapConfigurationFactory ambariLdapConfigurationFactory = injector.getInstance(AmbariLdapConfigurationFactory.class); + AmbariLdapConfiguration ldapConfiguration = ambariLdapConfigurationFactory.createLdapConfiguration(getADProps()); + LdapConnectionTemplate template = ldapConnectionTemplateFactory.create(ldapConfiguration); // THEN Assert.assertNotNull(template); - template.authenticate(new Dn("cn=read-only-admin,dc=example,dc=com"), "password".toCharArray()); + //template.authenticate(new Dn("cn=read-only-admin,dc=example,dc=com"), "password".toCharArray()); Boolean success = template.execute(new ConnectionCallback<Boolean>() { @Override public Boolean doWithConnection(LdapConnection connection) throws LdapException { connection.unBind(); - connection.bind(new Dn("cn=read-only-admin,dc=example,dc=com"), "password"); + connection.bind(ldapConfiguration.bindDn(), ldapConfiguration.bindPassword()); + return connection.isConnected() && connection.isAuthenticated(); } }); @@ -93,39 +105,6 @@ public class LdapModuleFunctionalTest { } - @Test - public void testShouldConnectionCheckSucceedWhenProperConfigurationProvided() throws Exception { - // GIVEN - AmbariLdapConfiguration ambariLdapConfiguration = ldapConfigurationFactory.createLdapConfiguration(getProps()); - - LdapFacade ldapFacade = injector.getInstance(LdapFacade.class); - - - // WHEN - ldapFacade.checkConnection(ambariLdapConfiguration); - - ldapFacade.detectAttributes(ambariLdapConfiguration); - - // THEN - // no exceptions thrown - - } - - @Test - public void testShouldAttributeDetectionSucceedWhenProperConfigurationProvided() throws Exception { - // GIVEN - AmbariLdapConfiguration ambariLdapConfiguration = ldapConfigurationFactory.createLdapConfiguration(getProps()); - LdapConfigurationService ldapConfigurationService = injector.getInstance(LdapConfigurationService.class); - - - // WHEN - ldapConfigurationService.checkUserAttributes("euclid", "", ambariLdapConfiguration); - - // THEN - // no exceptions thrown - - } - private static Map<String, Object> getProps() { Map<String, Object> ldapPropsMap = Maps.newHashMap(); @@ -134,45 +113,28 @@ public class LdapModuleFunctionalTest { ldapPropsMap.put(AmbariLdapConfigKeys.SERVER_PORT.key(), "389"); ldapPropsMap.put(AmbariLdapConfigKeys.BIND_DN.key(), "cn=read-only-admin,dc=example,dc=com"); ldapPropsMap.put(AmbariLdapConfigKeys.BIND_PASSWORD.key(), "password"); - ldapPropsMap.put(AmbariLdapConfigKeys.USE_SSL.key(), "true"); +// ldapPropsMap.put(AmbariLdapConfigKeys.USE_SSL.key(), "true"); ldapPropsMap.put(AmbariLdapConfigKeys.USER_OBJECT_CLASS.key(), SchemaConstants.PERSON_OC); ldapPropsMap.put(AmbariLdapConfigKeys.USER_NAME_ATTRIBUTE.key(), SchemaConstants.UID_AT); ldapPropsMap.put(AmbariLdapConfigKeys.USER_SEARCH_BASE.key(), "dc=example,dc=com"); ldapPropsMap.put(AmbariLdapConfigKeys.DN_ATTRIBUTE.key(), SchemaConstants.UID_AT); - ldapPropsMap.put(AmbariLdapConfigKeys.TRUST_STORE.key(), "custom"); +// ldapPropsMap.put(AmbariLdapConfigKeys.TRUST_STORE.key(), "custom"); ldapPropsMap.put(AmbariLdapConfigKeys.TRUST_STORE_TYPE.key(), "JKS"); - ldapPropsMap.put(AmbariLdapConfigKeys.TRUST_STORE_PATH.key(), "/Users/lpuskas/my_truststore/KeyStore.jks"); - ldapPropsMap.put(AmbariLdapConfigKeys.TRUST_STORE_PASSWORD.key(), "lofasz"); +// ldapPropsMap.put(AmbariLdapConfigKeys.TRUST_STORE_PATH.key(), "/Users/lpuskas/my_truststore/KeyStore.jks"); return ldapPropsMap; } + private static Map<String, Object> getADProps() { + Map<String, Object> ldapPropsMap = Maps.newHashMap(); - @Test - public void testShouldCustomTrustManagersBeSetForLdapConnection() throws Exception { - // GIVEN - AmbariLdapConfiguration ambariLdapConfiguration = ldapConfigurationFactory.createLdapConfiguration(getProps()); - - LdapFacade ldapFacade = injector.getInstance(LdapFacade.class); - - LdapConnectionTemplateFactory lctFactory = injector.getInstance(LdapConnectionTemplateFactory.class); - - LdapConnectionTemplate template1 = lctFactory.load(); - LdapConnectionTemplate template2 = lctFactory.create(ambariLdapConfiguration); - - - // WHEN - ldapFacade.checkConnection(ambariLdapConfiguration); - ldapFacade.detectAttributes(ambariLdapConfiguration); - // THEN - // no exceptions thrown + return ldapPropsMap; } - @Test public void testShouldDetectorsBeBound() throws Exception { // GIVEN @@ -182,6 +144,8 @@ public class LdapModuleFunctionalTest { // THEN Assert.assertNotNull(f); + LOG.info(f.groupAttributeDetector().toString()); + LOG.info(f.userAttributDetector().toString()); } } \ No newline at end of file http://git-wip-us.apache.org/repos/asf/ambari/blob/78007771/ambari-server/src/test/java/org/apache/ambari/server/ldap/service/ads/detectors/GroupMemberAttrDetectorTest.java ---------------------------------------------------------------------- diff --git a/ambari-server/src/test/java/org/apache/ambari/server/ldap/service/ads/detectors/GroupMemberAttrDetectorTest.java b/ambari-server/src/test/java/org/apache/ambari/server/ldap/service/ads/detectors/GroupMemberAttrDetectorTest.java new file mode 100644 index 0000000..79af467 --- /dev/null +++ b/ambari-server/src/test/java/org/apache/ambari/server/ldap/service/ads/detectors/GroupMemberAttrDetectorTest.java @@ -0,0 +1,107 @@ +/* + * 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 org.apache.ambari.server.ldap.service.ads.detectors; + +import java.util.List; +import java.util.Map; + +import org.apache.directory.api.ldap.model.entry.DefaultAttribute; +import org.apache.directory.api.ldap.model.entry.DefaultEntry; +import org.apache.directory.api.ldap.model.entry.Entry; +import org.apache.directory.api.ldap.model.entry.StringValue; +import org.easymock.TestSubject; +import org.junit.Assert; +import org.junit.Test; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import com.google.common.collect.Lists; + +/** + * Test suite for the attribute detector implementation + */ +public class GroupMemberAttrDetectorTest { + + private static final Logger LOG = LoggerFactory.getLogger(GroupMemberAttrDetector.class); + + @TestSubject + GroupMemberAttrDetector groupMemberAttrDetector = new GroupMemberAttrDetector(); + + @Test + public void testShouldDetectAttributeBasedOnOccurrence() throws Exception { + // GIVEN + // Mimic a sample set of entries where group membership attributes are different + List<Entry> sampleEntryList = Lists.newArrayList(); + + sampleEntryList.addAll(getSampleEntryList(GroupMemberAttrDetector.GroupMemberAttr.MEMBER_UID, 2)); + + // this is the expected property to be detected as in the sample set the most entries have it + sampleEntryList.addAll(getSampleEntryList(GroupMemberAttrDetector.GroupMemberAttr.UNIQUE_MEMBER, 7)); + sampleEntryList.addAll(getSampleEntryList(GroupMemberAttrDetector.GroupMemberAttr.MEMBER, 5)); + + // WHEN + for (Entry entry : sampleEntryList) { + groupMemberAttrDetector.collect(entry); + } + + // The most frequently encountered attribute will be selected + Map<String, String> detectedAttributeMap = groupMemberAttrDetector.detect(); + + // THEN + Assert.assertEquals(1, detectedAttributeMap.size()); + Map.Entry<String, String> selectedEntry = detectedAttributeMap.entrySet().iterator().next(); + + Assert.assertEquals("The selected configuration property is not the expected one", groupMemberAttrDetector.detectedProperty(), selectedEntry.getKey()); + Assert.assertEquals("The selected configuration property value is not the expected one", GroupMemberAttrDetector.GroupMemberAttr.UNIQUE_MEMBER.attrName(), selectedEntry.getValue()); + + + } + + @Test + public void testShouldDetectorPassWhenEmptySampleSetProvided() throws Exception { + // GIVEN + List<Entry> sampleEntryList = Lists.newArrayList(); + + // WHEN + // WHEN + for (Entry entry : sampleEntryList) { + groupMemberAttrDetector.collect(entry); + } + + Map<String, String> detectedAttributeMap = groupMemberAttrDetector.detect(); + // THEN + Assert.assertEquals(1, detectedAttributeMap.size()); + Map.Entry<String, String> selectedEntry = detectedAttributeMap.entrySet().iterator().next(); + + Assert.assertEquals("The selected configuration property is not the expected one", groupMemberAttrDetector.detectedProperty(), selectedEntry.getKey()); + Assert.assertEquals("The selected configuration property value is not the expected one", "N/A", selectedEntry.getValue()); + + } + + private List<Entry> getSampleEntryList(GroupMemberAttrDetector.GroupMemberAttr member, int count) { + List<Entry> entryList = Lists.newArrayList(); + for (int i = 0; i < count; i++) { + Entry entry = new DefaultEntry(); + try { + entry.setDn("dn=" + member.name() + "-" + i); + entry.add(new DefaultAttribute(member.attrName(), new StringValue("xxx"))); + entryList.add(entry); + } catch (Exception e) { + LOG.error(e.getMessage()); + } + } + return entryList; + } +} \ No newline at end of file