diff --git a/README.md b/README.md index f183537..8318b98 100755 --- a/README.md +++ b/README.md @@ -1,7 +1,7 @@ # embedded-ldap-junit [![Build Status](https://github.com/zapodot/embedded-ldap-junit/actions/workflows/maven.yml/badge.svg)](https://github.com/zapodot/embedded-ldap-junit/actions/workflows/maven.yml) [![codecov](https://codecov.io/gh/zapodot/embedded-ldap-junit/branch/master/graph/badge.svg?token=2jm8uT1bJg)](https://codecov.io/gh/zapodot/embedded-ldap-junit) [![Maven Central](https://maven-badges.herokuapp.com/maven-central/org.zapodot/embedded-ldap-junit/badge.svg)](https://maven-badges.herokuapp.com/maven-central/org.zapodot/embedded-ldap-junit) [![Libraries.io for GitHub](https://img.shields.io/librariesio/github/zapodot/embedded-ldap-junit.svg)](https://libraries.io/github/zapodot/embedded-ldap-junit) [![GitHub](https://img.shields.io/github/license/zapodot/embedded-ldap-junit)](https://github.com/zapodot/embedded-ldap-junit/blob/master/LICENSE) [![Analytics](https://ga-beacon.appspot.com/UA-40926073-2/embedded-ldap-junit/README.md)](https://github.com/igrigorik/ga-beacon) -A [JUnit Rule](//github.com/junit-team/junit/wiki/Rules) for running an embedded LDAP server in your JUnit test based on the wonderful [UnboundID LDAP SDK](https://www.ldap.com/unboundid-ldap-sdk-for-java). Inspired by the [Embedded Database JUnit Rule](//github.com/zapodot/embedded-db-junit). +A [JUnit 4 Rule](//github.com/junit-team/junit/wiki/Rules) and [JUnit 5 Extension](https://junit.org/junit5/docs/current/user-guide/#extensions) for running an embedded LDAP server in your JUnit test based on the wonderful [UnboundID LDAP SDK](https://www.ldap.com/unboundid-ldap-sdk-for-java). Inspired by the [Embedded Database JUnit Rule](//github.com/zapodot/embedded-db-junit). ## Why? * you want to test your LDAP integration code without affecting your LDAP server @@ -29,7 +29,9 @@ See [releases](//github.com/zapodot/embedded-ldap-junit/releases) ``` -### Add to Junit test +### Add to JUnit test + +#### JUnit 4 ```java import com.unboundid.ldap.sdk.LDAPInterface; import javax.naming.Context; @@ -79,3 +81,19 @@ public void testContext() throws Exception { assertNotNull(user); } ``` + +#### JUnit 5 +For JUnit 5 tests, simply use `EmbeddedLdapExtensionBuilder` instead of `EmbeddedLdapRuleBuilder`: + +```java +@RegisterExtension +public EmbeddedLdapExtension embeddedLdapRule = EmbeddedLdapExtensionBuilder + .newInstance() + .usingDomainDsn("dc=example,dc=com") + .importingLdifs("example.ldif") + .build(); + +... +``` + +Both JUnit 4 and JUnit 5 builders share the same API, as do the rule and the extension. diff --git a/embedded-ldap-core/pom.xml b/embedded-ldap-core/pom.xml new file mode 100644 index 0000000..dde3d64 --- /dev/null +++ b/embedded-ldap-core/pom.xml @@ -0,0 +1,57 @@ + + + 4.0.0 + + + embedded-ldap-parent + org.zapodot + 0.9-SNAPSHOT + + + embedded-ldap-core + + + + com.unboundid + unboundid-ldapsdk + ${unboundid-ldapsdk.version} + + + com.google.guava + guava + ${guava.version} + + + net.bytebuddy + byte-buddy + ${byte-buddy.version} + + + org.slf4j + slf4j-api + ${slf4j.version} + + + + + junit + junit + ${junit.version} + test + + + org.bouncycastle + bcprov-jdk15on + ${bouncycastle.version} + test + + + org.bouncycastle + bcpkix-jdk15on + ${bouncycastle.version} + test + + + diff --git a/src/main/java/org/zapodot/junit/ldap/EmbeddedLdapRule.java b/embedded-ldap-core/src/main/java/org/zapodot/junit/ldap/EmbeddedLdapServer.java old mode 100755 new mode 100644 similarity index 89% rename from src/main/java/org/zapodot/junit/ldap/EmbeddedLdapRule.java rename to embedded-ldap-core/src/main/java/org/zapodot/junit/ldap/EmbeddedLdapServer.java index 0b742b4..b73a258 --- a/src/main/java/org/zapodot/junit/ldap/EmbeddedLdapRule.java +++ b/embedded-ldap-core/src/main/java/org/zapodot/junit/ldap/EmbeddedLdapServer.java @@ -3,16 +3,12 @@ import com.unboundid.ldap.sdk.LDAPConnection; import com.unboundid.ldap.sdk.LDAPException; import com.unboundid.ldap.sdk.LDAPInterface; -import org.junit.rules.TestRule; import javax.naming.Context; import javax.naming.NamingException; import javax.naming.directory.DirContext; -/** - * A JUnit rule that may be used as either a @Rule or a @ClassRule - */ -public interface EmbeddedLdapRule extends TestRule { +public interface EmbeddedLdapServer { /** * For tests depending on the UnboundID LDAP SDK. Returns a proxied version of an Unboundid interface that will be @@ -57,9 +53,8 @@ public interface EmbeddedLdapRule extends TestRule { *

* * @return the port number that the embedded server is listening to - * @see org.zapodot.junit.ldap.EmbeddedLdapRuleBuilder#bindingToAddress(String) + * @see org.zapodot.junit.ldap.internal.AbstractEmbeddedLdapBuilder#bindingToAddress(String) */ int embeddedServerPort(); - } diff --git a/src/main/java/org/zapodot/junit/ldap/EmbeddedLdapRuleBuilder.java b/embedded-ldap-core/src/main/java/org/zapodot/junit/ldap/internal/AbstractEmbeddedLdapBuilder.java old mode 100755 new mode 100644 similarity index 70% rename from src/main/java/org/zapodot/junit/ldap/EmbeddedLdapRuleBuilder.java rename to embedded-ldap-core/src/main/java/org/zapodot/junit/ldap/internal/AbstractEmbeddedLdapBuilder.java index 83ba6f5..240cdd4 --- a/src/main/java/org/zapodot/junit/ldap/EmbeddedLdapRuleBuilder.java +++ b/embedded-ldap-core/src/main/java/org/zapodot/junit/ldap/internal/AbstractEmbeddedLdapBuilder.java @@ -1,4 +1,4 @@ -package org.zapodot.junit.ldap; +package org.zapodot.junit.ldap.internal; import com.google.common.base.Function; import com.google.common.collect.Lists; @@ -8,8 +8,6 @@ import com.unboundid.ldap.sdk.LDAPException; import com.unboundid.ldap.sdk.schema.Schema; import com.unboundid.ldif.LDIFException; -import org.zapodot.junit.ldap.internal.AuthenticationConfiguration; -import org.zapodot.junit.ldap.internal.EmbeddedLdapRuleImpl; import javax.net.ssl.SSLSocketFactory; import java.io.File; @@ -23,9 +21,10 @@ import java.util.Objects; /** - * A builder providing a fluent way of defining EmbeddedLdapRule instances + * A builder providing a fluent way of defining EmbeddedLdapRule + * or EmbeddedLdapExtension instances. */ -public class EmbeddedLdapRuleBuilder { +public abstract class AbstractEmbeddedLdapBuilder> { public static final String DEFAULT_DOMAIN = "dc=example,dc=com"; public static final String DEFAULT_BIND_DSN = "cn=Directory manager"; @@ -35,11 +34,11 @@ public class EmbeddedLdapRuleBuilder { public static final int MAX_PORT_EXCLUSIVE = 65535; private List domainDsn = new LinkedList<>(); - private String bindDSN = DEFAULT_BIND_DSN; + protected String bindDSN = DEFAULT_BIND_DSN; private String bindCredentials = DEFAULT_BIND_CREDENTIALS; - private List ldifsToImport = new LinkedList<>(); + protected List ldifsToImport = new LinkedList<>(); private List schemaLdifs = new LinkedList<>(); @@ -49,84 +48,73 @@ public class EmbeddedLdapRuleBuilder { private InetAddress bindAddress = InetAddress.getLoopbackAddress(); - private AuthenticationConfiguration authenticationConfiguration; + protected AuthenticationConfiguration authenticationConfiguration; private InMemoryListenerConfig listenerConfig = null; - private boolean useTls = false; - private SSLSocketFactory socketFactory = null; + protected boolean useTls = false; + protected SSLSocketFactory socketFactory = null; private Integer maxSizeLimit = null; - public EmbeddedLdapRuleBuilder() { - } - - /** - * Creates a new builder - * - * @return a new EmbeddedLdapRuleBuilder instance - */ - public static EmbeddedLdapRuleBuilder newInstance() { - return new EmbeddedLdapRuleBuilder(); - } /** * Sets a domainDsn to be used. May be multiple values. If not set, it will default to the value of the {@link #DEFAULT_DOMAIN DEFAULT_DOMAIN} field * * @param domainDsn a valid DSN string - * @return same EmbeddedLdapRuleBuilder instance with the domainDsn field set + * @return same builder instance with the domainDsn field set */ - public EmbeddedLdapRuleBuilder usingDomainDsn(final String domainDsn) { + public Self usingDomainDsn(final String domainDsn) { this.domainDsn.add(domainDsn); - return this; + return getThis(); } /** * Sets the DSN to bind to when authenticating. If not set, it will default to the value of the {@link #DEFAULT_BIND_DSN DEFAULT_BIND_DSN} field * * @param bindDSN a valid DSN string - * @return same EmbeddedLdapRuleBuilder instance with the bindDSN field set + * @return same builder instance with the bindDSN field set */ - public EmbeddedLdapRuleBuilder usingBindDSN(final String bindDSN) { + public Self usingBindDSN(final String bindDSN) { this.bindDSN = bindDSN; - return this; + return getThis(); } /** * Sets the credentials to be used to authenticate. If not set, it will default to the value of the {@link #DEFAULT_BIND_CREDENTIALS DEFAULT_BIND_CREDENTIALS} field * * @param bindCredentials a password string - * @return same EmbeddedLdapRuleBuilder instance with the bindCredentials field set + * @return same builder instance with the bindCredentials field set */ - public EmbeddedLdapRuleBuilder usingBindCredentials(final String bindCredentials) { + public Self usingBindCredentials(final String bindCredentials) { this.bindCredentials = bindCredentials; - return this; + return getThis(); } /** * Sets the port that the in-memory LDAP server will bind to. If not set, an available port will be picked automatically * * @param port a port number - * @return same EmbeddedLdapRuleBuilder instance with the port field set + * @return same builder instance with the port field set * @throws IllegalArgumentException if the provided value for port is not between @{link MIN_PORT_EXCLUSIVE} * and @{MAX_PORT_EXCLUSIVE} (exclusive) */ - public EmbeddedLdapRuleBuilder bindingToPort(final int port) { + public Self bindingToPort(final int port) { if ((port < MIN_PORT_EXCLUSIVE) || (port > MAX_PORT_EXCLUSIVE)) { throw new IllegalArgumentException(String.format("Value \"%s\" is not a valid port number", port)); } this.bindPort = Integer.valueOf(port); - return this; + return getThis(); } /** * Allows the listening address for the embedded LDAP server to be set. If not set it will bind to localhost/127.0.0.1. * * @param address a valid hostname or textual representation of an IP address - * @return same EmbeddedLdapRuleBuilder instance with the bindAddress field set + * @return same builder instance with the bindAddress field set * @throws IllegalArgumentException if the value provided for \"address\" is invalid */ - public EmbeddedLdapRuleBuilder bindingToAddress(final String address) { + public Self bindingToAddress(final String address) { Objects.requireNonNull(address); try { final InetAddress addressByName = InetAddress.getByName(address); @@ -134,71 +122,61 @@ public EmbeddedLdapRuleBuilder bindingToAddress(final String address) { } catch (UnknownHostException e) { throw new IllegalArgumentException(String.format("Unknown host address \"%s\"", address), e); } - return this; + return getThis(); } - public EmbeddedLdapRuleBuilder withMaxSizeLimit(final int maxSizeLimit) { + public Self withMaxSizeLimit(final int maxSizeLimit) { this.maxSizeLimit = Integer.valueOf(maxSizeLimit); - return this; + return getThis(); } /** * Avoid adding UnboundID's default schema that contains the most common LDAP elements defined through various RFC's. * - * @return same EmbeddedLdapRuleBuilder instance with the withoutDefaultSchema field set to FALSE + * @return same builder instance with the withoutDefaultSchema field set to FALSE */ - public EmbeddedLdapRuleBuilder withoutDefaultSchema() { + public Self withoutDefaultSchema() { this.addDefaultSchema = false; - return this; + return getThis(); } /** * Define schemas to be used for the server. If not defined, UnboundID will set up a default schema. * * @param ldifSchemaFiles LDIF-files containing schema element definitions - * @return same EmbeddedLdapRuleBuilder with the given LDIF-files added to the internal schema file collection. + * @return same builder with the given LDIF-files added to the internal schema file collection. */ - public EmbeddedLdapRuleBuilder withSchema(final String... ldifSchemaFiles) { + public Self withSchema(final String... ldifSchemaFiles) { this.schemaLdifs.addAll(Arrays.asList(ldifSchemaFiles)); - return this; + return getThis(); } /** * Specify one or more LDIF resources to be imported on startup. * * @param ldifFiles LDIF-files to import - * @return same EmbeddedLdapRuleBuilder instance with the provided ldifFiles added to the list of LDIF files to import + * @return same builder instance with the provided ldifFiles added to the list of LDIF files to import */ - public EmbeddedLdapRuleBuilder importingLdifs(final String... ldifFiles) { + public Self importingLdifs(final String... ldifFiles) { if (ldifFiles != null) { ldifsToImport.addAll(Arrays.asList(ldifFiles)); } - return this; + return getThis(); } - public EmbeddedLdapRuleBuilder withListener(InMemoryListenerConfig listenerConfig) { + public Self withListener(InMemoryListenerConfig listenerConfig) { this.listenerConfig = listenerConfig; - return this; + return getThis(); } - public EmbeddedLdapRuleBuilder useTls(boolean useTls) { + public Self useTls(boolean useTls) { this.useTls = useTls; - return this; + return getThis(); } - /** - * Creates a new rule based on the information that was previously provided - * - * @return a new EmbeddedLdapRule instance - */ - public EmbeddedLdapRule build() { - Objects.requireNonNull(bindDSN, "\"bindDSN\" can not be null"); - return EmbeddedLdapRuleImpl.createForConfiguration(createInMemoryServerConfiguration(), - authenticationConfiguration, - ldifsToImport, useTls, socketFactory); - } + protected abstract Self getThis(); - private InMemoryDirectoryServerConfig createInMemoryServerConfiguration() { + protected InMemoryDirectoryServerConfig createInMemoryServerConfiguration() { try { final InMemoryDirectoryServerConfig inMemoryDirectoryServerConfig = new InMemoryDirectoryServerConfig(domainDsnArray()); @@ -278,8 +256,8 @@ public File apply(final String input) { })); } - public EmbeddedLdapRuleBuilder withSocketFactory(SSLSocketFactory socketFactory) { + public Self withSocketFactory(SSLSocketFactory socketFactory) { this.socketFactory = socketFactory; - return this; + return getThis(); } } diff --git a/src/main/java/org/zapodot/junit/ldap/internal/AuthenticationConfiguration.java b/embedded-ldap-core/src/main/java/org/zapodot/junit/ldap/internal/AuthenticationConfiguration.java old mode 100755 new mode 100644 similarity index 100% rename from src/main/java/org/zapodot/junit/ldap/internal/AuthenticationConfiguration.java rename to embedded-ldap-core/src/main/java/org/zapodot/junit/ldap/internal/AuthenticationConfiguration.java diff --git a/src/main/java/org/zapodot/junit/ldap/internal/EmbeddedLdapRuleImpl.java b/embedded-ldap-core/src/main/java/org/zapodot/junit/ldap/internal/EmbeddedLdapServerImpl.java old mode 100755 new mode 100644 similarity index 78% rename from src/main/java/org/zapodot/junit/ldap/internal/EmbeddedLdapRuleImpl.java rename to embedded-ldap-core/src/main/java/org/zapodot/junit/ldap/internal/EmbeddedLdapServerImpl.java index a394874..7ae90c5 --- a/src/main/java/org/zapodot/junit/ldap/internal/EmbeddedLdapRuleImpl.java +++ b/embedded-ldap-core/src/main/java/org/zapodot/junit/ldap/internal/EmbeddedLdapServerImpl.java @@ -7,11 +7,12 @@ import com.unboundid.ldap.sdk.LDAPConnection; import com.unboundid.ldap.sdk.LDAPException; import com.unboundid.ldap.sdk.LDAPInterface; -import org.junit.runner.Description; -import org.junit.runners.model.Statement; +import net.bytebuddy.ByteBuddy; +import net.bytebuddy.dynamic.loading.ClassLoadingStrategy; +import net.bytebuddy.implementation.FixedValue; import org.slf4j.Logger; import org.slf4j.LoggerFactory; -import org.zapodot.junit.ldap.EmbeddedLdapRule; +import org.zapodot.junit.ldap.EmbeddedLdapServer; import org.zapodot.junit.ldap.internal.jndi.ContextProxyFactory; import org.zapodot.junit.ldap.internal.unboundid.LDAPInterfaceProxyFactory; @@ -20,14 +21,11 @@ import javax.naming.directory.DirContext; import javax.naming.directory.InitialDirContext; import javax.naming.ldap.LdapContext; -import java.io.UnsupportedEncodingException; -import java.lang.reflect.Modifier; - import javax.net.SocketFactory; import javax.net.ssl.SSLSocketFactory; - import java.io.IOException; import java.io.UnsupportedEncodingException; +import java.lang.reflect.Modifier; import java.net.InetAddress; import java.net.Socket; import java.net.URLDecoder; @@ -35,17 +33,12 @@ import java.util.Hashtable; import java.util.List; -import net.bytebuddy.ByteBuddy; -import net.bytebuddy.dynamic.loading.ClassLoadingStrategy; -import net.bytebuddy.implementation.FixedValue; - -public class EmbeddedLdapRuleImpl implements EmbeddedLdapRule { - +abstract class EmbeddedLdapServerImpl implements EmbeddedLdapServer { private static final String JAVA_RT_CONTROL_FACTORY = "com.sun.jndi.ldap.DefaultResponseControlFactory"; private static final String JAVA_RT_CONTEXT_FACTORY = "com.sun.jndi.ldap.LdapCtxFactory"; - private static Logger logger = LoggerFactory.getLogger(EmbeddedLdapRuleImpl.class); + private static Logger logger = LoggerFactory.getLogger(EmbeddedLdapServerImpl.class); private final InMemoryDirectoryServer inMemoryDirectoryServer; private final AuthenticationConfiguration authenticationConfiguration; private LDAPConnection ldapConnection; @@ -54,28 +47,16 @@ public class EmbeddedLdapRuleImpl implements EmbeddedLdapRule { private final boolean useTls; private final SSLSocketFactory socketFactory; - private EmbeddedLdapRuleImpl(final InMemoryDirectoryServer inMemoryDirectoryServer, - final AuthenticationConfiguration authenticationConfiguration1, - final boolean useTls, SSLSocketFactory socketFactory) { + public EmbeddedLdapServerImpl(final InMemoryDirectoryServer inMemoryDirectoryServer, + final AuthenticationConfiguration authenticationConfiguration1, + final boolean useTls, SSLSocketFactory socketFactory) { this.inMemoryDirectoryServer = inMemoryDirectoryServer; this.authenticationConfiguration = authenticationConfiguration1; this.useTls = useTls; this.socketFactory = socketFactory; } - public static EmbeddedLdapRule createForConfiguration( - final InMemoryDirectoryServerConfig inMemoryDirectoryServerConfig, - final AuthenticationConfiguration authenticationConfiguration, - final List ldifs, boolean useTls, SSLSocketFactory socketFactory) { - try { - return new EmbeddedLdapRuleImpl(createServer(inMemoryDirectoryServerConfig, ldifs), - authenticationConfiguration, useTls, socketFactory); - } catch (LDAPException e) { - throw new IllegalStateException("Can not initiate in-memory LDAP server due to an exception", e); - } - } - - private static InMemoryDirectoryServer createServer(final InMemoryDirectoryServerConfig inMemoryDirectoryServerConfig, + protected static InMemoryDirectoryServer createServer(final InMemoryDirectoryServerConfig inMemoryDirectoryServerConfig, final List ldifs) throws LDAPException { final InMemoryDirectoryServer ldapServer = new InMemoryDirectoryServer(inMemoryDirectoryServerConfig); @@ -83,10 +64,10 @@ private static InMemoryDirectoryServer createServer(final InMemoryDirectoryServe for (final String ldif : ldifs) { try { ldapServer.importFromLDIF(false, URLDecoder.decode(Resources.getResource(ldif).getPath(), - Charsets.UTF_8.name())); + Charsets.UTF_8.name())); } catch (UnsupportedEncodingException e) { throw new IllegalStateException("Can not URL decode path:" + Resources.getResource(ldif).getPath(), - e); + e); } } } @@ -203,8 +184,8 @@ private Hashtable createLdapEnvironment() { environment.put(LdapContext.CONTROL_FACTORIES, JAVA_RT_CONTROL_FACTORY); environment.put(Context.PROVIDER_URL, String.format("%s://%s:%s", useTls ? "ldaps" : "ldap", - inMemoryDirectoryServer.getListenAddress().getHostName(), - embeddedServerPort())); + inMemoryDirectoryServer.getListenAddress().getHostName(), + embeddedServerPort())); environment.put(Context.INITIAL_CONTEXT_FACTORY, JAVA_RT_CONTEXT_FACTORY); if (authenticationConfiguration != null) { environment.putAll(authenticationConfiguration.toAuthenticationEnvironment()); @@ -212,31 +193,12 @@ private Hashtable createLdapEnvironment() { return environment; } - @Override - public Statement apply(final Statement base, final Description description) { - return statement(base); - } - - private Statement statement(final Statement base) { - return new Statement() { - @Override - public void evaluate() throws Throwable { - startEmbeddedLdapServer(); - try { - base.evaluate(); - } finally { - takeDownEmbeddedLdapServer(); - } - } - }; - } - - private void startEmbeddedLdapServer() throws LDAPException { + protected void startEmbeddedLdapServer() throws LDAPException { inMemoryDirectoryServer.startListening(); isStarted = true; } - private void takeDownEmbeddedLdapServer() { + protected void takeDownEmbeddedLdapServer() { try { if (ldapConnection != null && ldapConnection.isConnected()) { ldapConnection.close(); @@ -251,6 +213,4 @@ private void takeDownEmbeddedLdapServer() { } } - - } diff --git a/src/main/java/org/zapodot/junit/ldap/internal/jndi/ContextInterceptor.java b/embedded-ldap-core/src/main/java/org/zapodot/junit/ldap/internal/jndi/ContextInterceptor.java old mode 100755 new mode 100644 similarity index 100% rename from src/main/java/org/zapodot/junit/ldap/internal/jndi/ContextInterceptor.java rename to embedded-ldap-core/src/main/java/org/zapodot/junit/ldap/internal/jndi/ContextInterceptor.java diff --git a/src/main/java/org/zapodot/junit/ldap/internal/jndi/ContextProxy.java b/embedded-ldap-core/src/main/java/org/zapodot/junit/ldap/internal/jndi/ContextProxy.java old mode 100755 new mode 100644 similarity index 100% rename from src/main/java/org/zapodot/junit/ldap/internal/jndi/ContextProxy.java rename to embedded-ldap-core/src/main/java/org/zapodot/junit/ldap/internal/jndi/ContextProxy.java diff --git a/src/main/java/org/zapodot/junit/ldap/internal/jndi/ContextProxyFactory.java b/embedded-ldap-core/src/main/java/org/zapodot/junit/ldap/internal/jndi/ContextProxyFactory.java old mode 100755 new mode 100644 similarity index 100% rename from src/main/java/org/zapodot/junit/ldap/internal/jndi/ContextProxyFactory.java rename to embedded-ldap-core/src/main/java/org/zapodot/junit/ldap/internal/jndi/ContextProxyFactory.java diff --git a/src/main/java/org/zapodot/junit/ldap/internal/jndi/DirContextProxy.java b/embedded-ldap-core/src/main/java/org/zapodot/junit/ldap/internal/jndi/DirContextProxy.java old mode 100755 new mode 100644 similarity index 100% rename from src/main/java/org/zapodot/junit/ldap/internal/jndi/DirContextProxy.java rename to embedded-ldap-core/src/main/java/org/zapodot/junit/ldap/internal/jndi/DirContextProxy.java diff --git a/src/main/java/org/zapodot/junit/ldap/internal/package-info.java b/embedded-ldap-core/src/main/java/org/zapodot/junit/ldap/internal/package-info.java old mode 100755 new mode 100644 similarity index 100% rename from src/main/java/org/zapodot/junit/ldap/internal/package-info.java rename to embedded-ldap-core/src/main/java/org/zapodot/junit/ldap/internal/package-info.java diff --git a/src/main/java/org/zapodot/junit/ldap/internal/unboundid/LDAPConnectionProxy.java b/embedded-ldap-core/src/main/java/org/zapodot/junit/ldap/internal/unboundid/LDAPConnectionProxy.java old mode 100755 new mode 100644 similarity index 100% rename from src/main/java/org/zapodot/junit/ldap/internal/unboundid/LDAPConnectionProxy.java rename to embedded-ldap-core/src/main/java/org/zapodot/junit/ldap/internal/unboundid/LDAPConnectionProxy.java diff --git a/src/main/java/org/zapodot/junit/ldap/internal/unboundid/LDAPInterfaceProxyFactory.java b/embedded-ldap-core/src/main/java/org/zapodot/junit/ldap/internal/unboundid/LDAPInterfaceProxyFactory.java old mode 100755 new mode 100644 similarity index 100% rename from src/main/java/org/zapodot/junit/ldap/internal/unboundid/LDAPInterfaceProxyFactory.java rename to embedded-ldap-core/src/main/java/org/zapodot/junit/ldap/internal/unboundid/LDAPInterfaceProxyFactory.java diff --git a/src/main/java/org/zapodot/junit/ldap/package-info.java b/embedded-ldap-core/src/main/java/org/zapodot/junit/ldap/package-info.java old mode 100755 new mode 100644 similarity index 100% rename from src/main/java/org/zapodot/junit/ldap/package-info.java rename to embedded-ldap-core/src/main/java/org/zapodot/junit/ldap/package-info.java diff --git a/embedded-ldap-core/src/test/java/org/zapodot/junit/ldap/internal/AbstractEmbeddedLdapBuilderTest.java b/embedded-ldap-core/src/test/java/org/zapodot/junit/ldap/internal/AbstractEmbeddedLdapBuilderTest.java new file mode 100644 index 0000000..9754cb4 --- /dev/null +++ b/embedded-ldap-core/src/test/java/org/zapodot/junit/ldap/internal/AbstractEmbeddedLdapBuilderTest.java @@ -0,0 +1,88 @@ +package org.zapodot.junit.ldap.internal; + +import org.junit.Test; + +import static org.junit.Assert.assertNotNull; + +public class AbstractEmbeddedLdapBuilderTest { + + @Test + public void bindingToLegalPort() { + assertNotNull(FakeEmbeddedLdapBuilder.newInstance().bindingToPort(9999)); + } + + @Test(expected = IllegalStateException.class) + public void testPrematureLdapConnection() throws Exception { + FakeEmbeddedLdapBuilder.newInstance().build().ldapConnection(); + + } + + @Test(expected = IllegalStateException.class) + public void testPrematureContext() throws Exception { + FakeEmbeddedLdapBuilder.newInstance().build().context(); + + } + + @Test(expected = IllegalArgumentException.class) + public void testUnknownLDIF() { + FakeEmbeddedLdapBuilder.newInstance().importingLdifs("nonExisting.ldif").build(); + + } + + @Test + public void testNullLDIF() { + assertNotNull(FakeEmbeddedLdapBuilder.newInstance().importingLdifs(null).build()); + + } + + @Test(expected = IllegalStateException.class) + public void testIllegalDSN() { + FakeEmbeddedLdapBuilder.newInstance().usingBindDSN("bindDsn").build(); + + } + + @Test(expected = IllegalArgumentException.class) + public void testIllegalPort() { + FakeEmbeddedLdapBuilder.newInstance().bindingToPort(Integer.MIN_VALUE).build(); + + } + + @Test(expected = IllegalArgumentException.class) + public void testSchemaNotFound() { + FakeEmbeddedLdapBuilder.newInstance().withSchema("non-existing-schema.ldif").build(); + + } + + @Test(expected = IllegalArgumentException.class) + public void testSchemaIsNotAFile() { + FakeEmbeddedLdapBuilder.newInstance().withSchema("folder").build(); + + } + + @Test(expected = IllegalArgumentException.class) + public void testSchemaIsInvalid() { + FakeEmbeddedLdapBuilder.newInstance().withSchema("invalid.ldif").build(); + + } + + @Test(expected = IllegalArgumentException.class) + public void testSchemaFileUnsupportedIsInvalid() { + FakeEmbeddedLdapBuilder.newInstance().withSchema("\"#%¤&&%/¤##¤¤").build(); + + } + + @Test(expected = IllegalArgumentException.class) + public void testInvalidPort() { + FakeEmbeddedLdapBuilder.newInstance().bindingToPort(Integer.MAX_VALUE); + + } + + @Test(expected = IllegalArgumentException.class) + public void testInvalidBindAddress() { + FakeEmbeddedLdapBuilder.newInstance().bindingToAddress("åpsldfåpl"); + + } + + +} + diff --git a/src/test/java/org/zapodot/junit/ldap/internal/AuthenticationConfigurationTest.java b/embedded-ldap-core/src/test/java/org/zapodot/junit/ldap/internal/AuthenticationConfigurationTest.java old mode 100755 new mode 100644 similarity index 100% rename from src/test/java/org/zapodot/junit/ldap/internal/AuthenticationConfigurationTest.java rename to embedded-ldap-core/src/test/java/org/zapodot/junit/ldap/internal/AuthenticationConfigurationTest.java diff --git a/embedded-ldap-core/src/test/java/org/zapodot/junit/ldap/internal/EmbeddedLdapServerCustomSchemaDuplicatedTest.java b/embedded-ldap-core/src/test/java/org/zapodot/junit/ldap/internal/EmbeddedLdapServerCustomSchemaDuplicatedTest.java new file mode 100644 index 0000000..2afa57d --- /dev/null +++ b/embedded-ldap-core/src/test/java/org/zapodot/junit/ldap/internal/EmbeddedLdapServerCustomSchemaDuplicatedTest.java @@ -0,0 +1,35 @@ +package org.zapodot.junit.ldap.internal; + +import com.unboundid.ldap.sdk.LDAPException; +import com.unboundid.ldap.sdk.schema.AttributeTypeDefinition; +import org.junit.After; +import org.junit.Before; +import org.junit.Test; +import org.zapodot.junit.ldap.EmbeddedLdapServer; + +import static org.junit.Assert.assertNotNull; + +public class EmbeddedLdapServerCustomSchemaDuplicatedTest { + + private final EmbeddedLdapServer embeddedLdapRule = FakeEmbeddedLdapBuilder.newInstance() + .withSchema("standard-schema.ldif") + .build(); + + @Before + public void setup() throws LDAPException { + ((EmbeddedLdapServerImpl) embeddedLdapRule).startEmbeddedLdapServer(); + } + + @After + public void teardown() throws LDAPException { + ((EmbeddedLdapServerImpl) embeddedLdapRule).takeDownEmbeddedLdapServer(); + } + + @Test + public void testFindCustomAttribute() throws Exception { + final AttributeTypeDefinition changelogAttribute = + embeddedLdapRule.ldapConnection().getSchema().getAttributeType("changelog"); + assertNotNull(changelogAttribute); + + } +} diff --git a/embedded-ldap-core/src/test/java/org/zapodot/junit/ldap/internal/EmbeddedLdapServerCustomStandardAndCustomSchemaTest.java b/embedded-ldap-core/src/test/java/org/zapodot/junit/ldap/internal/EmbeddedLdapServerCustomStandardAndCustomSchemaTest.java new file mode 100644 index 0000000..eba39eb --- /dev/null +++ b/embedded-ldap-core/src/test/java/org/zapodot/junit/ldap/internal/EmbeddedLdapServerCustomStandardAndCustomSchemaTest.java @@ -0,0 +1,37 @@ +package org.zapodot.junit.ldap.internal; + +import com.unboundid.ldap.sdk.LDAPException; +import com.unboundid.ldap.sdk.schema.AttributeTypeDefinition; +import com.unboundid.ldap.sdk.schema.Schema; +import org.junit.After; +import org.junit.Before; +import org.junit.Test; +import org.zapodot.junit.ldap.EmbeddedLdapServer; + +import static org.junit.Assert.assertNotNull; + +public class EmbeddedLdapServerCustomStandardAndCustomSchemaTest { + + private final EmbeddedLdapServer embeddedLdapRule = FakeEmbeddedLdapBuilder.newInstance() + .withSchema("custom-schema.ldif") + .build(); + + @Before + public void setup() throws LDAPException { + ((EmbeddedLdapServerImpl) embeddedLdapRule).startEmbeddedLdapServer(); + } + + @After + public void teardown() throws LDAPException { + ((EmbeddedLdapServerImpl) embeddedLdapRule).takeDownEmbeddedLdapServer(); + } + + @Test + public void testFindCustomAttribute() throws Exception { + final Schema currentSchema = embeddedLdapRule.ldapConnection().getSchema(); + final AttributeTypeDefinition changelogAttribute = + currentSchema.getAttributeType("attribute"); + assertNotNull(changelogAttribute); + assertNotNull(currentSchema.getObjectClass("type")); + } +} diff --git a/embedded-ldap-core/src/test/java/org/zapodot/junit/ldap/internal/EmbeddedLdapServerCustomWithoutSchemaTest.java b/embedded-ldap-core/src/test/java/org/zapodot/junit/ldap/internal/EmbeddedLdapServerCustomWithoutSchemaTest.java new file mode 100644 index 0000000..3daaceb --- /dev/null +++ b/embedded-ldap-core/src/test/java/org/zapodot/junit/ldap/internal/EmbeddedLdapServerCustomWithoutSchemaTest.java @@ -0,0 +1,35 @@ +package org.zapodot.junit.ldap.internal; + +import com.unboundid.ldap.sdk.LDAPException; +import com.unboundid.ldap.sdk.schema.Schema; +import org.junit.After; +import org.junit.Before; +import org.junit.Test; +import org.zapodot.junit.ldap.EmbeddedLdapServer; + +import static org.junit.Assert.assertTrue; + +public class EmbeddedLdapServerCustomWithoutSchemaTest { + + private final EmbeddedLdapServer embeddedLdapRule = FakeEmbeddedLdapBuilder.newInstance() + .withoutDefaultSchema() + .build(); + + @Before + public void setup() throws LDAPException { + ((EmbeddedLdapServerImpl) embeddedLdapRule).startEmbeddedLdapServer(); + } + + @After + public void teardown() throws LDAPException { + ((EmbeddedLdapServerImpl) embeddedLdapRule).takeDownEmbeddedLdapServer(); + } + + @Test + public void testEmptySchema() throws Exception { + final Schema schema = + embeddedLdapRule.ldapConnection().getSchema(); + assertTrue(schema.getAttributeTypes().isEmpty()); + + } +} diff --git a/embedded-ldap-core/src/test/java/org/zapodot/junit/ldap/internal/EmbeddedLdapServerCustomWithoutStandardSchemaTest.java b/embedded-ldap-core/src/test/java/org/zapodot/junit/ldap/internal/EmbeddedLdapServerCustomWithoutStandardSchemaTest.java new file mode 100644 index 0000000..84e8639 --- /dev/null +++ b/embedded-ldap-core/src/test/java/org/zapodot/junit/ldap/internal/EmbeddedLdapServerCustomWithoutStandardSchemaTest.java @@ -0,0 +1,36 @@ +package org.zapodot.junit.ldap.internal; + +import com.unboundid.ldap.sdk.LDAPException; +import com.unboundid.ldap.sdk.schema.AttributeTypeDefinition; +import org.junit.After; +import org.junit.Before; +import org.junit.Test; +import org.zapodot.junit.ldap.EmbeddedLdapServer; + +import static org.junit.Assert.assertNotNull; + +public class EmbeddedLdapServerCustomWithoutStandardSchemaTest { + + private final EmbeddedLdapServer embeddedLdapRule = FakeEmbeddedLdapBuilder.newInstance() + .withoutDefaultSchema() + .withSchema("standard-schema.ldif") + .build(); + + @Before + public void setup() throws LDAPException { + ((EmbeddedLdapServerImpl) embeddedLdapRule).startEmbeddedLdapServer(); + } + + @After + public void teardown() throws LDAPException { + ((EmbeddedLdapServerImpl) embeddedLdapRule).takeDownEmbeddedLdapServer(); + } + + @Test + public void testFindCustomAttribute() throws Exception { + final AttributeTypeDefinition changelogAttribute = + embeddedLdapRule.ldapConnection().getSchema().getAttributeType("changelog"); + assertNotNull(changelogAttribute); + + } +} diff --git a/embedded-ldap-core/src/test/java/org/zapodot/junit/ldap/internal/EmbeddedLdapServerMultipleDSNs.java b/embedded-ldap-core/src/test/java/org/zapodot/junit/ldap/internal/EmbeddedLdapServerMultipleDSNs.java new file mode 100644 index 0000000..7ec4dab --- /dev/null +++ b/embedded-ldap-core/src/test/java/org/zapodot/junit/ldap/internal/EmbeddedLdapServerMultipleDSNs.java @@ -0,0 +1,40 @@ +package org.zapodot.junit.ldap.internal; + +import com.unboundid.ldap.sdk.LDAPException; +import com.unboundid.ldap.sdk.LDAPInterface; +import org.junit.After; +import org.junit.Before; +import org.junit.Test; +import org.zapodot.junit.ldap.EmbeddedLdapServer; + +import static org.junit.Assert.assertArrayEquals; + +public class EmbeddedLdapServerMultipleDSNs { + + public static final String DSN_ROOT_ONE = "dc=zapodot,dc=com"; + public static final String DSN_ROOT_TWO = "dc=zapodot,dc=org"; + + private final EmbeddedLdapServer embeddedLdapRule = FakeEmbeddedLdapBuilder.newInstance() + .usingDomainDsn(DSN_ROOT_ONE) + .usingDomainDsn(DSN_ROOT_TWO) + .importingLdifs("example.ldif") + .build(); + + @Before + public void setup() throws LDAPException { + ((EmbeddedLdapServerImpl) embeddedLdapRule).startEmbeddedLdapServer(); + } + + @After + public void teardown() throws LDAPException { + ((EmbeddedLdapServerImpl) embeddedLdapRule).takeDownEmbeddedLdapServer(); + } + + @Test + public void testCheckNamingContexts() throws Exception { + final LDAPInterface ldapConnection = embeddedLdapRule.ldapConnection(); + final String[] namingContextDNs = ldapConnection.getRootDSE().getNamingContextDNs(); + assertArrayEquals(new String[]{DSN_ROOT_ONE, DSN_ROOT_TWO}, namingContextDNs); + + } +} diff --git a/embedded-ldap-core/src/test/java/org/zapodot/junit/ldap/internal/EmbeddedLdapServerNoAuthTest.java b/embedded-ldap-core/src/test/java/org/zapodot/junit/ldap/internal/EmbeddedLdapServerNoAuthTest.java new file mode 100644 index 0000000..39e5fe3 --- /dev/null +++ b/embedded-ldap-core/src/test/java/org/zapodot/junit/ldap/internal/EmbeddedLdapServerNoAuthTest.java @@ -0,0 +1,35 @@ +package org.zapodot.junit.ldap.internal; + +import com.unboundid.ldap.sdk.LDAPException; +import org.junit.After; +import org.junit.Before; +import org.junit.Test; +import org.zapodot.junit.ldap.EmbeddedLdapServer; + +import static org.junit.Assert.assertNotNull; + +public class EmbeddedLdapServerNoAuthTest { + + private final EmbeddedLdapServer embeddedLdapRule = FakeEmbeddedLdapBuilder + .newInstance() + .usingBindCredentials(null) + .usingDomainDsn("dc=zapodot,dc=org") + .importingLdifs("example.ldif") + .build(); + + @Before + public void setup() throws LDAPException { + ((EmbeddedLdapServerImpl) embeddedLdapRule).startEmbeddedLdapServer(); + } + + @After + public void teardown() throws LDAPException { + ((EmbeddedLdapServerImpl) embeddedLdapRule).takeDownEmbeddedLdapServer(); + } + + @Test + public void testConnect() throws Exception { + assertNotNull(embeddedLdapRule.dirContext().search("cn=Sondre Eikanger Kvalo,ou=people,dc=zapodot,dc=org", null)); + + } +} diff --git a/embedded-ldap-core/src/test/java/org/zapodot/junit/ldap/internal/EmbeddedLdapServerStandardContext.java b/embedded-ldap-core/src/test/java/org/zapodot/junit/ldap/internal/EmbeddedLdapServerStandardContext.java new file mode 100644 index 0000000..1848975 --- /dev/null +++ b/embedded-ldap-core/src/test/java/org/zapodot/junit/ldap/internal/EmbeddedLdapServerStandardContext.java @@ -0,0 +1,33 @@ +package org.zapodot.junit.ldap.internal; + +import com.unboundid.ldap.sdk.LDAPException; +import org.junit.After; +import org.junit.Before; +import org.junit.Test; +import org.zapodot.junit.ldap.EmbeddedLdapServer; + +import static org.junit.Assert.assertArrayEquals; + +public class EmbeddedLdapServerStandardContext { + + private final EmbeddedLdapServer embeddedLdapRule = FakeEmbeddedLdapBuilder.newInstance() + .build(); + + @Before + public void setup() throws LDAPException { + ((EmbeddedLdapServerImpl) embeddedLdapRule).startEmbeddedLdapServer(); + } + + @After + public void teardown() throws LDAPException { + ((EmbeddedLdapServerImpl) embeddedLdapRule).takeDownEmbeddedLdapServer(); + } + + @Test + public void testUsingDefaultDomain() throws Exception { + assertArrayEquals(new String[]{FakeEmbeddedLdapBuilder.DEFAULT_DOMAIN}, + embeddedLdapRule.ldapConnection().getRootDSE().getNamingContextDNs()); + + + } +} diff --git a/embedded-ldap-core/src/test/java/org/zapodot/junit/ldap/internal/EmbeddedLdapServerStarttlsTest.java b/embedded-ldap-core/src/test/java/org/zapodot/junit/ldap/internal/EmbeddedLdapServerStarttlsTest.java new file mode 100644 index 0000000..a19a991 --- /dev/null +++ b/embedded-ldap-core/src/test/java/org/zapodot/junit/ldap/internal/EmbeddedLdapServerStarttlsTest.java @@ -0,0 +1,151 @@ +package org.zapodot.junit.ldap.internal; + +import com.unboundid.ldap.listener.InMemoryListenerConfig; +import com.unboundid.ldap.sdk.*; +import com.unboundid.ldap.sdk.extensions.StartTLSExtendedRequest; +import org.bouncycastle.asn1.ASN1ObjectIdentifier; +import org.bouncycastle.asn1.x509.BasicConstraints; +import org.bouncycastle.cert.X509CertificateHolder; +import org.bouncycastle.cert.jcajce.JcaX509CertificateConverter; +import org.bouncycastle.cert.jcajce.JcaX509v3CertificateBuilder; +import org.bouncycastle.jce.provider.BouncyCastleProvider; +import org.bouncycastle.operator.ContentSigner; +import org.bouncycastle.operator.OperatorCreationException; +import org.bouncycastle.operator.jcajce.JcaContentSignerBuilder; +import org.junit.After; +import org.junit.Before; +import org.junit.Test; +import org.zapodot.junit.ldap.EmbeddedLdapServer; + +import javax.net.ssl.*; +import java.io.IOException; +import java.math.BigInteger; +import java.net.InetAddress; +import java.security.*; +import java.security.cert.Certificate; +import java.security.cert.CertificateException; +import java.security.cert.X509Certificate; +import java.util.Arrays; +import java.util.Calendar; +import java.util.Date; + +import static org.junit.Assert.assertNotNull; + +public class EmbeddedLdapServerStarttlsTest { + + public static final String DOMAIN_DSN = "dc=zapodot,dc=org"; + + final SSLContext sslContext; + { + try { + sslContext = buildSslContext(); + } catch (Exception e) { + throw new IllegalStateException("Failed to create LDAPS config", e); + } + } + + private final EmbeddedLdapServer embeddedLdapRule = FakeEmbeddedLdapBuilder + .newInstance() + .usingDomainDsn(DOMAIN_DSN) + .importingLdifs("example.ldif") + .withListener(getListenerConfig()) + .build(); + + @Before + public void setup() throws LDAPException { + ((EmbeddedLdapServerImpl) embeddedLdapRule).startEmbeddedLdapServer(); + } + + @After + public void teardown() throws LDAPException { + ((EmbeddedLdapServerImpl) embeddedLdapRule).takeDownEmbeddedLdapServer(); + } + + private InMemoryListenerConfig getListenerConfig() { + try { + return InMemoryListenerConfig.createLDAPConfig( + "tls", InetAddress.getLoopbackAddress(), 0, sslContext.getSocketFactory() + ); + } catch (Exception e) { + throw new IllegalStateException("Failed to create LDAPS config", e); + } + } + + @Test + public void testRawLdapConnection() throws Exception { + final String commonName = "Test person"; + final String dn = String.format( + "cn=%s,ou=people,dc=zapodot,dc=org", + commonName); + LDAPConnection ldapConnection = embeddedLdapRule.unsharedLdapConnection(); + ldapConnection.processExtendedOperation(new StartTLSExtendedRequest(sslContext)); + try { + ldapConnection.add(new AddRequest(dn, Arrays.asList( + new Attribute("objectclass", "top", "person", "organizationalPerson", "inetOrgPerson"), + new Attribute("cn", commonName), new Attribute("sn", "Person"), new Attribute("uid", "test")))); + } finally { + // Forces the LDAP connection to be closed. This is not necessary as the rule will usually close it for you. + ldapConnection.close(); + } + ldapConnection = embeddedLdapRule.unsharedLdapConnection(); + final SearchResultEntry entry = ldapConnection.searchForEntry(new SearchRequest(dn, + SearchScope.BASE, + "(objectClass=person)")); + assertNotNull(entry); + } + + public static SSLContext buildSslContext() + throws KeyStoreException, IOException, CertificateException, NoSuchAlgorithmException, + UnrecoverableKeyException, KeyManagementException, OperatorCreationException { + KeyStore keystore = KeyStore.getInstance("jks"); + keystore.load(null, new char[] {}); + KeyPairGenerator gen = KeyPairGenerator.getInstance("RSA"); + gen.initialize(2014); + final KeyPair keyPair = gen.generateKeyPair(); + + Provider bcProvider = new BouncyCastleProvider(); + Security.addProvider(bcProvider); + + long now = System.currentTimeMillis(); + Date startDate = new Date(now); + + org.bouncycastle.asn1.x500.X500Name dn = new org.bouncycastle.asn1.x500.X500Name("cn=localhost"); + BigInteger sn = new BigInteger(Long.toString(now)); + + Calendar calendar = Calendar.getInstance(); + calendar.setTime(startDate); + calendar.add(Calendar.HOUR, 1); + Date endDate = calendar.getTime(); + + String signatureAlgorithm = "SHA256WithRSA"; + + final ContentSigner contentSigner = new JcaContentSignerBuilder(signatureAlgorithm).build(keyPair.getPrivate()); + + final X509CertificateHolder holder = + new JcaX509v3CertificateBuilder(dn, sn, startDate, endDate, dn, keyPair.getPublic()) + .addExtension(new ASN1ObjectIdentifier("2.5.29.19"), true, new BasicConstraints(true)) + .build(contentSigner); + final X509Certificate cert = new JcaX509CertificateConverter() + .setProvider(bcProvider) + .getCertificate(holder); + keystore.setCertificateEntry("test", cert); + keystore.setKeyEntry("key", keyPair.getPrivate(), new char[] {}, new Certificate[] { cert }); + + final KeyManagerFactory kmfactory = KeyManagerFactory.getInstance(KeyManagerFactory.getDefaultAlgorithm()); + kmfactory.init(keystore, new char[] {}); + final KeyManager[] kms = kmfactory.getKeyManagers(); + + KeyStore truststore = KeyStore.getInstance("jks"); + truststore.load(null, new char[] {}); + truststore.setCertificateEntry("test", cert); + + final TrustManagerFactory tmfactory = TrustManagerFactory.getInstance( + TrustManagerFactory.getDefaultAlgorithm() + ); + tmfactory.init(truststore); + final TrustManager[] tms = tmfactory.getTrustManagers(); + final SSLContext sslcontext = SSLContext.getInstance("TLS"); + sslcontext.init(kms, tms, null); + return sslcontext; + } +} diff --git a/embedded-ldap-core/src/test/java/org/zapodot/junit/ldap/internal/EmbeddedLdapServerTest.java b/embedded-ldap-core/src/test/java/org/zapodot/junit/ldap/internal/EmbeddedLdapServerTest.java new file mode 100644 index 0000000..7267fcf --- /dev/null +++ b/embedded-ldap-core/src/test/java/org/zapodot/junit/ldap/internal/EmbeddedLdapServerTest.java @@ -0,0 +1,104 @@ +package org.zapodot.junit.ldap.internal; + +import com.google.common.collect.Iterators; +import com.unboundid.ldap.sdk.*; +import org.junit.After; +import org.junit.Before; +import org.junit.Test; +import org.zapodot.junit.ldap.EmbeddedLdapServer; + +import javax.naming.Context; +import javax.naming.NamingEnumeration; +import javax.naming.directory.DirContext; +import javax.naming.directory.SearchControls; +import java.util.Arrays; + +import static org.junit.Assert.*; + +public class EmbeddedLdapServerTest { + + public static final String DOMAIN_DSN = "dc=zapodot,dc=org"; + + private final EmbeddedLdapServer embeddedLdapRule = FakeEmbeddedLdapBuilder + .newInstance() + .usingDomainDsn(DOMAIN_DSN) + .importingLdifs("example.ldif") + .build(); + + @Before + public void setup() throws LDAPException { + ((EmbeddedLdapServerImpl) embeddedLdapRule).startEmbeddedLdapServer(); + } + + @After + public void teardown() throws LDAPException { + ((EmbeddedLdapServerImpl) embeddedLdapRule).takeDownEmbeddedLdapServer(); + } + + @Test + public void testLdapConnection() throws Exception { + final LDAPInterface ldapConnection = embeddedLdapRule.ldapConnection(); + final SearchResult searchResult = ldapConnection.search(DOMAIN_DSN, SearchScope.SUB, "(objectClass=person)"); + assertEquals(1, searchResult.getEntryCount()); + } + + @Test + public void testRawLdapConnection() throws Exception { + final String commonName = "Test person"; + final String dn = String.format( + "cn=%s,ou=people,dc=zapodot,dc=org", + commonName); + LDAPConnection ldapConnection = embeddedLdapRule.unsharedLdapConnection(); + try { + ldapConnection.add(new AddRequest(dn, Arrays.asList( + new Attribute("objectclass", "top", "person", "organizationalPerson", "inetOrgPerson"), + new Attribute("cn", commonName), new Attribute("sn", "Person"), new Attribute("uid", "test")))); + } finally { + // Forces the LDAP connection to be closed. This is not necessary as the rule will usually close it for you. + ldapConnection.close(); + } + ldapConnection = embeddedLdapRule.unsharedLdapConnection(); + final SearchResultEntry entry = ldapConnection.searchForEntry(new SearchRequest(dn, + SearchScope.BASE, + "(objectClass=person)")); + assertNotNull(entry); + } + + @Test + public void testDirContext() throws Exception { + final DirContext dirContext = embeddedLdapRule.dirContext(); + final SearchControls searchControls = new SearchControls(); + searchControls.setSearchScope(SearchControls.SUBTREE_SCOPE); + final NamingEnumeration resultNamingEnumeration = + dirContext.search(DOMAIN_DSN, "(objectClass=person)", searchControls); + assertEquals(1, Iterators.size(Iterators.forEnumeration(resultNamingEnumeration))); + } + + @Test + public void testContext() throws Exception { + final Context context = embeddedLdapRule.context(); + final Object user = context.lookup("cn=Sondre Eikanger Kvalo,ou=people,dc=zapodot,dc=org"); + assertNotNull(user); + } + + @Test + public void testContextClose() throws Exception { + final Context context = embeddedLdapRule.context(); + context.close(); + assertNotNull(context.getNameInNamespace()); + + } + + @Test + public void testEmbeddedServerPort() throws Exception { + assertTrue(embeddedLdapRule.embeddedServerPort() > 0); + + } + + @Test(expected = IllegalStateException.class) + public void testNoPortAssignedYet() throws Exception { + final EmbeddedLdapServer embeddedLdapRule = new FakeEmbeddedLdapBuilder().build(); + embeddedLdapRule.embeddedServerPort(); + + } +} diff --git a/embedded-ldap-core/src/test/java/org/zapodot/junit/ldap/internal/EmbeddedLdapServerWithListeningAddressProvidedTest.java b/embedded-ldap-core/src/test/java/org/zapodot/junit/ldap/internal/EmbeddedLdapServerWithListeningAddressProvidedTest.java new file mode 100644 index 0000000..f653ca5 --- /dev/null +++ b/embedded-ldap-core/src/test/java/org/zapodot/junit/ldap/internal/EmbeddedLdapServerWithListeningAddressProvidedTest.java @@ -0,0 +1,46 @@ +package org.zapodot.junit.ldap.internal; + +import com.unboundid.ldap.sdk.LDAPException; +import org.junit.After; +import org.junit.Before; +import org.junit.BeforeClass; +import org.junit.Test; +import org.zapodot.junit.ldap.EmbeddedLdapServer; + +import java.net.InetAddress; + +import static org.junit.Assert.assertEquals; + +public class EmbeddedLdapServerWithListeningAddressProvidedTest { + + public static InetAddress inetAddress; + + private final EmbeddedLdapServer embeddedLdapRule = FakeEmbeddedLdapBuilder + .newInstance() + .usingDomainDsn("dc=zapodot,dc=org") + .importingLdifs("example.ldif") + .bindingToAddress(inetAddress.getHostAddress()) + .build(); + + @Before + public void setup() throws LDAPException { + ((EmbeddedLdapServerImpl) embeddedLdapRule).startEmbeddedLdapServer(); + } + + @After + public void teardown() throws LDAPException { + ((EmbeddedLdapServerImpl) embeddedLdapRule).takeDownEmbeddedLdapServer(); + } + + @BeforeClass + public static void setupAddress() throws Exception { + inetAddress = InetAddress.getLocalHost(); + } + + @Test + public void testLookupAddress() throws Exception { + assertEquals(inetAddress.getHostAddress(), + embeddedLdapRule.unsharedLdapConnection().getConnectedAddress()); + + } +} diff --git a/embedded-ldap-core/src/test/java/org/zapodot/junit/ldap/internal/EmbeddedLdapServerWithSpacesTest.java b/embedded-ldap-core/src/test/java/org/zapodot/junit/ldap/internal/EmbeddedLdapServerWithSpacesTest.java new file mode 100644 index 0000000..7b5ec78 --- /dev/null +++ b/embedded-ldap-core/src/test/java/org/zapodot/junit/ldap/internal/EmbeddedLdapServerWithSpacesTest.java @@ -0,0 +1,34 @@ +package org.zapodot.junit.ldap.internal; + +import com.unboundid.ldap.sdk.LDAPException; +import org.junit.After; +import org.junit.Before; +import org.junit.Test; +import org.zapodot.junit.ldap.EmbeddedLdapServer; + +import static org.junit.Assert.assertNotNull; + +public class EmbeddedLdapServerWithSpacesTest { + + private final EmbeddedLdapServer embeddedLdapRule = FakeEmbeddedLdapBuilder + .newInstance() + .usingDomainDsn("dc=zapodot,dc=org") + .importingLdifs("folder with space/example.ldif") + .build(); + + @Before + public void setup() throws LDAPException { + ((EmbeddedLdapServerImpl) embeddedLdapRule).startEmbeddedLdapServer(); + } + + @After + public void teardown() throws LDAPException { + ((EmbeddedLdapServerImpl) embeddedLdapRule).takeDownEmbeddedLdapServer(); + } + + @Test + public void testIsUp() throws Exception { + assertNotNull(embeddedLdapRule.ldapConnection().getRootDSE()); + + } +} diff --git a/embedded-ldap-core/src/test/java/org/zapodot/junit/ldap/internal/FakeEmbeddedLdapBuilder.java b/embedded-ldap-core/src/test/java/org/zapodot/junit/ldap/internal/FakeEmbeddedLdapBuilder.java new file mode 100644 index 0000000..e23ba63 --- /dev/null +++ b/embedded-ldap-core/src/test/java/org/zapodot/junit/ldap/internal/FakeEmbeddedLdapBuilder.java @@ -0,0 +1,30 @@ +package org.zapodot.junit.ldap.internal; + +import com.unboundid.ldap.listener.InMemoryDirectoryServer; +import com.unboundid.ldap.sdk.LDAPException; +import org.zapodot.junit.ldap.EmbeddedLdapServer; + +import static org.zapodot.junit.ldap.internal.EmbeddedLdapServerImpl.createServer; + +class FakeEmbeddedLdapBuilder extends AbstractEmbeddedLdapBuilder { + + static FakeEmbeddedLdapBuilder newInstance() { + return new FakeEmbeddedLdapBuilder(); + } + + @Override + protected FakeEmbeddedLdapBuilder getThis() { + return this; + } + + EmbeddedLdapServer build() { + try { + InMemoryDirectoryServer server = createServer(createInMemoryServerConfiguration(), ldifsToImport); + return new EmbeddedLdapServerImpl(server, authenticationConfiguration, false, null) { + + }; + } catch (LDAPException e) { + throw new IllegalStateException("Can not initiate in-memory LDAP server due to an exception", e); + } + } +} diff --git a/src/test/java/org/zapodot/junit/ldap/internal/jndi/ContextProxyFactoryTest.java b/embedded-ldap-core/src/test/java/org/zapodot/junit/ldap/internal/jndi/ContextProxyFactoryTest.java similarity index 100% rename from src/test/java/org/zapodot/junit/ldap/internal/jndi/ContextProxyFactoryTest.java rename to embedded-ldap-core/src/test/java/org/zapodot/junit/ldap/internal/jndi/ContextProxyFactoryTest.java diff --git a/src/test/java/org/zapodot/junit/ldap/internal/unboundid/LDAPInterfaceProxyFactoryTest.java b/embedded-ldap-core/src/test/java/org/zapodot/junit/ldap/internal/unboundid/LDAPInterfaceProxyFactoryTest.java similarity index 100% rename from src/test/java/org/zapodot/junit/ldap/internal/unboundid/LDAPInterfaceProxyFactoryTest.java rename to embedded-ldap-core/src/test/java/org/zapodot/junit/ldap/internal/unboundid/LDAPInterfaceProxyFactoryTest.java diff --git a/src/test/resources/custom-schema.ldif b/embedded-ldap-core/src/test/resources/custom-schema.ldif old mode 100755 new mode 100644 similarity index 100% rename from src/test/resources/custom-schema.ldif rename to embedded-ldap-core/src/test/resources/custom-schema.ldif diff --git a/src/test/resources/example.ldif b/embedded-ldap-core/src/test/resources/example.ldif old mode 100755 new mode 100644 similarity index 100% rename from src/test/resources/example.ldif rename to embedded-ldap-core/src/test/resources/example.ldif diff --git a/src/test/resources/folder with space/example.ldif b/embedded-ldap-core/src/test/resources/folder with space/example.ldif old mode 100755 new mode 100644 similarity index 100% rename from src/test/resources/folder with space/example.ldif rename to embedded-ldap-core/src/test/resources/folder with space/example.ldif diff --git a/src/test/resources/folder/.placeholder b/embedded-ldap-core/src/test/resources/folder/.placeholder old mode 100755 new mode 100644 similarity index 100% rename from src/test/resources/folder/.placeholder rename to embedded-ldap-core/src/test/resources/folder/.placeholder diff --git a/src/test/resources/invalid.ldif b/embedded-ldap-core/src/test/resources/invalid.ldif old mode 100755 new mode 100644 similarity index 100% rename from src/test/resources/invalid.ldif rename to embedded-ldap-core/src/test/resources/invalid.ldif diff --git a/src/test/resources/standard-schema.ldif b/embedded-ldap-core/src/test/resources/standard-schema.ldif old mode 100755 new mode 100644 similarity index 100% rename from src/test/resources/standard-schema.ldif rename to embedded-ldap-core/src/test/resources/standard-schema.ldif diff --git a/embedded-ldap-junit/pom.xml b/embedded-ldap-junit/pom.xml new file mode 100644 index 0000000..16ac926 --- /dev/null +++ b/embedded-ldap-junit/pom.xml @@ -0,0 +1,48 @@ + + + 4.0.0 + + + embedded-ldap-parent + org.zapodot + 0.9-SNAPSHOT + + + embedded-ldap-junit + + + + org.zapodot + embedded-ldap-core + ${project.version} + + + + junit + junit + ${junit.version} + + + + + ch.qos.logback + logback-classic + ${logback.version} + test + + + org.bouncycastle + bcprov-jdk15on + ${bouncycastle.version} + test + + + org.bouncycastle + bcpkix-jdk15on + ${bouncycastle.version} + test + + + diff --git a/embedded-ldap-junit/src/main/java/org/zapodot/junit/ldap/EmbeddedLdapRule.java b/embedded-ldap-junit/src/main/java/org/zapodot/junit/ldap/EmbeddedLdapRule.java new file mode 100644 index 0000000..4aa70d4 --- /dev/null +++ b/embedded-ldap-junit/src/main/java/org/zapodot/junit/ldap/EmbeddedLdapRule.java @@ -0,0 +1,10 @@ +package org.zapodot.junit.ldap; + +import org.junit.rules.TestRule; + +/** + * A JUnit rule that may be used as either a @Rule or a @ClassRule + */ +public interface EmbeddedLdapRule extends EmbeddedLdapServer, TestRule { + +} diff --git a/embedded-ldap-junit/src/main/java/org/zapodot/junit/ldap/EmbeddedLdapRuleBuilder.java b/embedded-ldap-junit/src/main/java/org/zapodot/junit/ldap/EmbeddedLdapRuleBuilder.java new file mode 100644 index 0000000..b43e4d8 --- /dev/null +++ b/embedded-ldap-junit/src/main/java/org/zapodot/junit/ldap/EmbeddedLdapRuleBuilder.java @@ -0,0 +1,43 @@ +package org.zapodot.junit.ldap; + +import org.zapodot.junit.ldap.internal.AbstractEmbeddedLdapBuilder; +import org.zapodot.junit.ldap.internal.EmbeddedLdapRuleImpl; + +import java.util.Objects; + +/** + * A builder providing a fluent way of defining EmbeddedLdapRule instances + */ +public class EmbeddedLdapRuleBuilder extends AbstractEmbeddedLdapBuilder { + + /** + * Creates a new builder + * + * @return a new EmbeddedLdapRuleBuilder instance + */ + public static EmbeddedLdapRuleBuilder newInstance() { + return new EmbeddedLdapRuleBuilder(); + } + + @Override + protected EmbeddedLdapRuleBuilder getThis() { + return this; + } + + /** + * Creates a new rule based on the information that was previously provided + * + * @return a new EmbeddedLdapRule instance + */ + public EmbeddedLdapRule build() { + Objects.requireNonNull(bindDSN, "\"bindDSN\" can not be null"); + return EmbeddedLdapRuleImpl.createForConfiguration( + createInMemoryServerConfiguration(), + authenticationConfiguration, + ldifsToImport, + useTls, + socketFactory + ); + } + +} diff --git a/embedded-ldap-junit/src/main/java/org/zapodot/junit/ldap/internal/EmbeddedLdapRuleImpl.java b/embedded-ldap-junit/src/main/java/org/zapodot/junit/ldap/internal/EmbeddedLdapRuleImpl.java new file mode 100644 index 0000000..aeac793 --- /dev/null +++ b/embedded-ldap-junit/src/main/java/org/zapodot/junit/ldap/internal/EmbeddedLdapRuleImpl.java @@ -0,0 +1,51 @@ +package org.zapodot.junit.ldap.internal; + +import com.unboundid.ldap.listener.InMemoryDirectoryServer; +import com.unboundid.ldap.listener.InMemoryDirectoryServerConfig; +import com.unboundid.ldap.sdk.LDAPException; +import org.junit.runner.Description; +import org.junit.runners.model.Statement; +import org.zapodot.junit.ldap.EmbeddedLdapRule; + +import javax.net.ssl.SSLSocketFactory; +import java.util.List; + +public class EmbeddedLdapRuleImpl extends EmbeddedLdapServerImpl implements EmbeddedLdapRule { + + public static EmbeddedLdapRule createForConfiguration(final InMemoryDirectoryServerConfig inMemoryDirectoryServerConfig, + final AuthenticationConfiguration authenticationConfiguration, + final List ldifs, boolean useTls, SSLSocketFactory socketFactory) { + try { + return new EmbeddedLdapRuleImpl(EmbeddedLdapServerImpl.createServer(inMemoryDirectoryServerConfig, ldifs), + authenticationConfiguration, useTls, socketFactory); + } catch (LDAPException e) { + throw new IllegalStateException("Can not initiate in-memory LDAP server due to an exception", e); + } + } + + public EmbeddedLdapRuleImpl(InMemoryDirectoryServer inMemoryDirectoryServer, AuthenticationConfiguration authenticationConfiguration1, + boolean useTls, SSLSocketFactory socketFactory) { + super(inMemoryDirectoryServer, authenticationConfiguration1, useTls, socketFactory); + } + + + @Override + public Statement apply(final Statement base, final Description description) { + return statement(base); + } + + private Statement statement(final Statement base) { + return new Statement() { + @Override + public void evaluate() throws Throwable { + startEmbeddedLdapServer(); + try { + base.evaluate(); + } finally { + takeDownEmbeddedLdapServer(); + } + } + }; + } + +} diff --git a/src/test/java/org/zapodot/junit/ldap/EmbeddedLdapRuleBuilderTest.java b/embedded-ldap-junit/src/test/java/org/zapodot/junit/ldap/EmbeddedLdapRuleBuilderTest.java old mode 100755 new mode 100644 similarity index 100% rename from src/test/java/org/zapodot/junit/ldap/EmbeddedLdapRuleBuilderTest.java rename to embedded-ldap-junit/src/test/java/org/zapodot/junit/ldap/EmbeddedLdapRuleBuilderTest.java diff --git a/src/test/java/org/zapodot/junit/ldap/EmbeddedLdapRuleClassRuleTest.java b/embedded-ldap-junit/src/test/java/org/zapodot/junit/ldap/EmbeddedLdapRuleClassRuleTest.java old mode 100755 new mode 100644 similarity index 100% rename from src/test/java/org/zapodot/junit/ldap/EmbeddedLdapRuleClassRuleTest.java rename to embedded-ldap-junit/src/test/java/org/zapodot/junit/ldap/EmbeddedLdapRuleClassRuleTest.java diff --git a/src/test/java/org/zapodot/junit/ldap/EmbeddedLdapRuleCustomSchemaDuplicatedTest.java b/embedded-ldap-junit/src/test/java/org/zapodot/junit/ldap/EmbeddedLdapRuleCustomSchemaDuplicatedTest.java old mode 100755 new mode 100644 similarity index 100% rename from src/test/java/org/zapodot/junit/ldap/EmbeddedLdapRuleCustomSchemaDuplicatedTest.java rename to embedded-ldap-junit/src/test/java/org/zapodot/junit/ldap/EmbeddedLdapRuleCustomSchemaDuplicatedTest.java diff --git a/src/test/java/org/zapodot/junit/ldap/EmbeddedLdapRuleCustomStandardAndCustomSchemaTest.java b/embedded-ldap-junit/src/test/java/org/zapodot/junit/ldap/EmbeddedLdapRuleCustomStandardAndCustomSchemaTest.java old mode 100755 new mode 100644 similarity index 100% rename from src/test/java/org/zapodot/junit/ldap/EmbeddedLdapRuleCustomStandardAndCustomSchemaTest.java rename to embedded-ldap-junit/src/test/java/org/zapodot/junit/ldap/EmbeddedLdapRuleCustomStandardAndCustomSchemaTest.java diff --git a/src/test/java/org/zapodot/junit/ldap/EmbeddedLdapRuleCustomWithoutSchemaTest.java b/embedded-ldap-junit/src/test/java/org/zapodot/junit/ldap/EmbeddedLdapRuleCustomWithoutSchemaTest.java old mode 100755 new mode 100644 similarity index 100% rename from src/test/java/org/zapodot/junit/ldap/EmbeddedLdapRuleCustomWithoutSchemaTest.java rename to embedded-ldap-junit/src/test/java/org/zapodot/junit/ldap/EmbeddedLdapRuleCustomWithoutSchemaTest.java diff --git a/src/test/java/org/zapodot/junit/ldap/EmbeddedLdapRuleCustomWithoutStandardSchemaTest.java b/embedded-ldap-junit/src/test/java/org/zapodot/junit/ldap/EmbeddedLdapRuleCustomWithoutStandardSchemaTest.java old mode 100755 new mode 100644 similarity index 100% rename from src/test/java/org/zapodot/junit/ldap/EmbeddedLdapRuleCustomWithoutStandardSchemaTest.java rename to embedded-ldap-junit/src/test/java/org/zapodot/junit/ldap/EmbeddedLdapRuleCustomWithoutStandardSchemaTest.java diff --git a/src/test/java/org/zapodot/junit/ldap/EmbeddedLdapRuleMultipleDSNs.java b/embedded-ldap-junit/src/test/java/org/zapodot/junit/ldap/EmbeddedLdapRuleMultipleDSNs.java old mode 100755 new mode 100644 similarity index 100% rename from src/test/java/org/zapodot/junit/ldap/EmbeddedLdapRuleMultipleDSNs.java rename to embedded-ldap-junit/src/test/java/org/zapodot/junit/ldap/EmbeddedLdapRuleMultipleDSNs.java diff --git a/src/test/java/org/zapodot/junit/ldap/EmbeddedLdapRuleNoAuthTest.java b/embedded-ldap-junit/src/test/java/org/zapodot/junit/ldap/EmbeddedLdapRuleNoAuthTest.java old mode 100755 new mode 100644 similarity index 100% rename from src/test/java/org/zapodot/junit/ldap/EmbeddedLdapRuleNoAuthTest.java rename to embedded-ldap-junit/src/test/java/org/zapodot/junit/ldap/EmbeddedLdapRuleNoAuthTest.java diff --git a/src/test/java/org/zapodot/junit/ldap/EmbeddedLdapRuleStandardContext.java b/embedded-ldap-junit/src/test/java/org/zapodot/junit/ldap/EmbeddedLdapRuleStandardContext.java old mode 100755 new mode 100644 similarity index 100% rename from src/test/java/org/zapodot/junit/ldap/EmbeddedLdapRuleStandardContext.java rename to embedded-ldap-junit/src/test/java/org/zapodot/junit/ldap/EmbeddedLdapRuleStandardContext.java diff --git a/src/test/java/org/zapodot/junit/ldap/EmbeddedLdapRuleStarttlsTest.java b/embedded-ldap-junit/src/test/java/org/zapodot/junit/ldap/EmbeddedLdapRuleStarttlsTest.java old mode 100755 new mode 100644 similarity index 100% rename from src/test/java/org/zapodot/junit/ldap/EmbeddedLdapRuleStarttlsTest.java rename to embedded-ldap-junit/src/test/java/org/zapodot/junit/ldap/EmbeddedLdapRuleStarttlsTest.java diff --git a/src/test/java/org/zapodot/junit/ldap/EmbeddedLdapRuleTest.java b/embedded-ldap-junit/src/test/java/org/zapodot/junit/ldap/EmbeddedLdapRuleTest.java old mode 100755 new mode 100644 similarity index 100% rename from src/test/java/org/zapodot/junit/ldap/EmbeddedLdapRuleTest.java rename to embedded-ldap-junit/src/test/java/org/zapodot/junit/ldap/EmbeddedLdapRuleTest.java diff --git a/src/test/java/org/zapodot/junit/ldap/EmbeddedLdapRuleTlsTest.java b/embedded-ldap-junit/src/test/java/org/zapodot/junit/ldap/EmbeddedLdapRuleTlsTest.java old mode 100755 new mode 100644 similarity index 99% rename from src/test/java/org/zapodot/junit/ldap/EmbeddedLdapRuleTlsTest.java rename to embedded-ldap-junit/src/test/java/org/zapodot/junit/ldap/EmbeddedLdapRuleTlsTest.java index 43c703d..bedf39f --- a/src/test/java/org/zapodot/junit/ldap/EmbeddedLdapRuleTlsTest.java +++ b/embedded-ldap-junit/src/test/java/org/zapodot/junit/ldap/EmbeddedLdapRuleTlsTest.java @@ -20,7 +20,6 @@ import java.security.cert.Certificate; import java.security.cert.CertificateException; import java.security.cert.X509Certificate; -import java.util.Arrays; import java.util.Calendar; import java.util.Date; diff --git a/src/test/java/org/zapodot/junit/ldap/EmbeddedLdapRuleWithListeningAddressProvidedTest.java b/embedded-ldap-junit/src/test/java/org/zapodot/junit/ldap/EmbeddedLdapRuleWithListeningAddressProvidedTest.java old mode 100755 new mode 100644 similarity index 100% rename from src/test/java/org/zapodot/junit/ldap/EmbeddedLdapRuleWithListeningAddressProvidedTest.java rename to embedded-ldap-junit/src/test/java/org/zapodot/junit/ldap/EmbeddedLdapRuleWithListeningAddressProvidedTest.java diff --git a/src/test/java/org/zapodot/junit/ldap/EmbeddedLdapRuleWithSpacesTest.java b/embedded-ldap-junit/src/test/java/org/zapodot/junit/ldap/EmbeddedLdapRuleWithSpacesTest.java old mode 100755 new mode 100644 similarity index 100% rename from src/test/java/org/zapodot/junit/ldap/EmbeddedLdapRuleWithSpacesTest.java rename to embedded-ldap-junit/src/test/java/org/zapodot/junit/ldap/EmbeddedLdapRuleWithSpacesTest.java diff --git a/embedded-ldap-junit/src/test/resources/custom-schema.ldif b/embedded-ldap-junit/src/test/resources/custom-schema.ldif new file mode 100644 index 0000000..552eeca --- /dev/null +++ b/embedded-ldap-junit/src/test/resources/custom-schema.ldif @@ -0,0 +1,7 @@ +dn: cn=custom-schema +objectClass: top +objectClass: ldapSubEntry +objectClass: subschema +cn: custom-schema +attributeTypes: ( 1.3.6.1.4.1.41609.1.75 NAME 'attribute' DESC 'A simple attribute' SUP name SINGLE-VALUE ) +objectClasses: ( 1.3.6.1.4.1.41609.2.13 NAME 'type' DESC 'A simple objectClass' SUP top STRUCTURAL MUST ( cn $ attribute ) MAY ( description ) ) diff --git a/embedded-ldap-junit/src/test/resources/example.ldif b/embedded-ldap-junit/src/test/resources/example.ldif new file mode 100644 index 0000000..5eb286a --- /dev/null +++ b/embedded-ldap-junit/src/test/resources/example.ldif @@ -0,0 +1,28 @@ +version: 1 + +dn: dc=zapodot,dc=org +objectClass: domain +objectClass: top +dc: zapodot + +dn: ou=groups,dc=zapodot,dc=org +objectclass: top +objectclass: organizationalUnit +ou: groups + +dn: ou=people,dc=zapodot,dc=org +objectclass: top +objectclass: organizationalUnit +ou: people + +dn: cn=Sondre Eikanger Kvalo,ou=people,dc=zapodot,dc=org +objectclass: top +objectclass: person +objectclass: organizationalPerson +objectclass: inetOrgPerson +uid: zapodot +userPassword: password +cn: Sondre Eikanger Kvalo +cn:: U29uZHJlIEVpa2FuZ2VyIEt2YWzDuA== +sn: Person +description: Developer \ No newline at end of file diff --git a/embedded-ldap-junit/src/test/resources/folder with space/example.ldif b/embedded-ldap-junit/src/test/resources/folder with space/example.ldif new file mode 100644 index 0000000..5eb286a --- /dev/null +++ b/embedded-ldap-junit/src/test/resources/folder with space/example.ldif @@ -0,0 +1,28 @@ +version: 1 + +dn: dc=zapodot,dc=org +objectClass: domain +objectClass: top +dc: zapodot + +dn: ou=groups,dc=zapodot,dc=org +objectclass: top +objectclass: organizationalUnit +ou: groups + +dn: ou=people,dc=zapodot,dc=org +objectclass: top +objectclass: organizationalUnit +ou: people + +dn: cn=Sondre Eikanger Kvalo,ou=people,dc=zapodot,dc=org +objectclass: top +objectclass: person +objectclass: organizationalPerson +objectclass: inetOrgPerson +uid: zapodot +userPassword: password +cn: Sondre Eikanger Kvalo +cn:: U29uZHJlIEVpa2FuZ2VyIEt2YWzDuA== +sn: Person +description: Developer \ No newline at end of file diff --git a/embedded-ldap-junit/src/test/resources/folder/.placeholder b/embedded-ldap-junit/src/test/resources/folder/.placeholder new file mode 100644 index 0000000..e69de29 diff --git a/embedded-ldap-junit/src/test/resources/invalid.ldif b/embedded-ldap-junit/src/test/resources/invalid.ldif new file mode 100644 index 0000000..bbd8c77 --- /dev/null +++ b/embedded-ldap-junit/src/test/resources/invalid.ldif @@ -0,0 +1,2 @@ +zndskjnckjdsn +daf diff --git a/embedded-ldap-junit/src/test/resources/standard-schema.ldif b/embedded-ldap-junit/src/test/resources/standard-schema.ldif new file mode 100644 index 0000000..063a7d8 --- /dev/null +++ b/embedded-ldap-junit/src/test/resources/standard-schema.ldif @@ -0,0 +1,1546 @@ +# Retrieved from the UnboundID LDAP SDK repository http://sourceforge.net/p/ldap-sdk/code/HEAD/tree/trunk/resource/standard-schema.ldif +# This file contains a set of standard schema definitions from various RFCs and +# Internet Drafts. It is not intended to be a complete comprehensive schema +# for all purposes, but it may be used by the LDAP SDK for cases in which +# schema information may be required and no other definitions are available. +# +# Definitions in this class come from the following sources: +# * RFC 2798: +# Definition of the inetOrgPerson LDAP Object Class +# * RFC 3045: +# Storing Vendor Information in the LDAP Root DSE +# * RFC 3112: +# LDAP Authentication Password Schema +# * RFC 3296: +# Named Subordinate References in LDAP Directories +# * RFC 4512: +# LDAP Directory Information Models +# * RFC 4519: +# LDAP Schema for User Applications +# * RFC 4523: +# LDAP Schema Definitions for X.509 Certificates +# * RFC 4524: +# COSINE LDAP/X.500 Schema +# * RFC 4530: +# LDAP entryUUID Operational Attribute +# * RFC 5020: +# The LDAP entryDN Operational Attribute +# * draft-good-ldap-changelog: +# Definition of an Object Class to Hold LDAP Change Records +# * draft-howard-namedobject: +# A Structural Object Class for Arbitrary Auxiliary Object Classes +# * draft-ietf-boreham-numsubordinates: +# numSubordinates LDAP Operational Attribute +# * draft-ietf-ldup-subentry: +# LDAP Subentry Schema +dn: cn=schema +objectClass: top +objectClass: ldapSubEntry +objectClass: subschema +cn: schema +ldapSyntaxes: ( 1.3.6.1.4.1.1466.115.121.1.3 + DESC 'Attribute Type Description' + X-ORIGIN 'RFC 4517' ) +ldapSyntaxes: ( 1.3.6.1.4.1.1466.115.121.1.6 + DESC 'Bit String' + X-ORIGIN 'RFC 4517') +ldapSyntaxes: ( 1.3.6.1.4.1.1466.115.121.1.7 + DESC 'Boolean' + X-ORIGIN 'RFC 4517') +ldapSyntaxes: ( 1.3.6.1.4.1.1466.115.121.1.11 + DESC 'Country String' + X-ORIGIN 'RFC 4517') +ldapSyntaxes: ( 1.3.6.1.4.1.1466.115.121.1.14 + DESC 'Delivery Method' + X-ORIGIN 'RFC 4517') +ldapSyntaxes: ( 1.3.6.1.4.1.1466.115.121.1.15 + DESC 'Directory String' + X-ORIGIN 'RFC 4517') +ldapSyntaxes: ( 1.3.6.1.4.1.1466.115.121.1.16 + DESC 'DIT Content Rule Description' + X-ORIGIN 'RFC 4517') +ldapSyntaxes: ( 1.3.6.1.4.1.1466.115.121.1.17 + DESC 'DIT Structure Rule Description' + X-ORIGIN 'RFC 4517') +ldapSyntaxes: ( 1.3.6.1.4.1.1466.115.121.1.12 + DESC 'DN' + X-ORIGIN 'RFC 4517') +ldapSyntaxes: ( 1.3.6.1.4.1.1466.115.121.1.21 + DESC 'Enhanced Guide' + X-ORIGIN 'RFC 4517') +ldapSyntaxes: ( 1.3.6.1.4.1.1466.115.121.1.22 + DESC 'Facsimile Telephone Number' + X-ORIGIN 'RFC 4517') +ldapSyntaxes: ( 1.3.6.1.4.1.1466.115.121.1.23 + DESC 'Fax' + X-ORIGIN 'RFC 4517') +ldapSyntaxes: ( 1.3.6.1.4.1.1466.115.121.1.24 + DESC 'Generalized Time' + X-ORIGIN 'RFC 4517') +ldapSyntaxes: ( 1.3.6.1.4.1.1466.115.121.1.25 + DESC 'Guide' + X-ORIGIN 'RFC 4517') +ldapSyntaxes: ( 1.3.6.1.4.1.1466.115.121.1.26 + DESC 'IA5 String' + X-ORIGIN 'RFC 4517') +ldapSyntaxes: ( 1.3.6.1.4.1.1466.115.121.1.27 + DESC 'INTEGER' + X-ORIGIN 'RFC 4517') +ldapSyntaxes: ( 1.3.6.1.4.1.1466.115.121.1.28 + DESC 'JPEG' + X-ORIGIN 'RFC 4517') +ldapSyntaxes: ( 1.3.6.1.4.1.1466.115.121.1.54 + DESC 'LDAP Syntax Description' + X-ORIGIN 'RFC 4517') +ldapSyntaxes: ( 1.3.6.1.4.1.1466.115.121.1.30 + DESC 'Matching Rule Description' + X-ORIGIN 'RFC 4517') +ldapSyntaxes: ( 1.3.6.1.4.1.1466.115.121.1.31 + DESC 'Matching Rule Use Description' + X-ORIGIN 'RFC 4517') +ldapSyntaxes: ( 1.3.6.1.4.1.1466.115.121.1.34 + DESC 'Name And Optional UID' + X-ORIGIN 'RFC 4517') +ldapSyntaxes: ( 1.3.6.1.4.1.1466.115.121.1.35 + DESC 'Name Form Description' + X-ORIGIN 'RFC 4517') +ldapSyntaxes: ( 1.3.6.1.4.1.1466.115.121.1.36 + DESC 'Numeric String' + X-ORIGIN 'RFC 4517') +ldapSyntaxes: ( 1.3.6.1.4.1.1466.115.121.1.37 + DESC 'Object Class Description' + X-ORIGIN 'RFC 4517') +ldapSyntaxes: ( 1.3.6.1.4.1.1466.115.121.1.40 + DESC 'Octet String' + X-ORIGIN 'RFC 4517') +ldapSyntaxes: ( 1.3.6.1.4.1.1466.115.121.1.38 + DESC 'OID' + X-ORIGIN 'RFC 4517') +ldapSyntaxes: ( 1.3.6.1.4.1.1466.115.121.1.39 + DESC 'Other Mailbox' + X-ORIGIN 'RFC 4517') +ldapSyntaxes: ( 1.3.6.1.4.1.1466.115.121.1.41 + DESC 'Postal Address' + X-ORIGIN 'RFC 4517') +ldapSyntaxes: ( 1.3.6.1.4.1.1466.115.121.1.44 + DESC 'Printable String' + X-ORIGIN 'RFC 4517') +ldapSyntaxes: ( 1.3.6.1.4.1.1466.115.121.1.58 + DESC 'Substring Assertion' + X-ORIGIN 'RFC 4517') +ldapSyntaxes: ( 1.3.6.1.4.1.1466.115.121.1.50 + DESC 'Telephone Number' + X-ORIGIN 'RFC 4517') +ldapSyntaxes: ( 1.3.6.1.4.1.1466.115.121.1.51 + DESC 'Teletex Terminal Identifier' + X-ORIGIN 'RFC 4517') +ldapSyntaxes: ( 1.3.6.1.4.1.1466.115.121.1.52 + DESC 'Telex Number' + X-ORIGIN 'RFC 4517') +ldapSyntaxes: ( 1.3.6.1.4.1.1466.115.121.1.53 + DESC 'UTC Time' + X-ORIGIN 'RFC 4517') +matchingRules: ( 2.5.13.16 + NAME 'bitStringMatch' + SYNTAX 1.3.6.1.4.1.1466.115.121.1.6 + X-ORIGIN 'RFC 4517' ) +matchingRules: ( 2.5.13.13 + NAME 'booleanMatch' + SYNTAX 1.3.6.1.4.1.1466.115.121.1.7 + X-ORIGIN 'RFC 4517' ) +matchingRules: ( 1.3.6.1.4.1.1466.109.114.1 + NAME 'caseExactIA5Match' + SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 + X-ORIGIN 'RFC 4517' ) +matchingRules: ( 2.5.13.5 + NAME 'caseExactMatch' + SYNTAX 1.3.6.1.4.1.1466.115.121.1.15 + X-ORIGIN 'RFC 4517' ) +matchingRules: ( 2.5.13.6 + NAME 'caseExactOrderingMatch' + SYNTAX 1.3.6.1.4.1.1466.115.121.1.15 + X-ORIGIN 'RFC 4517' ) +matchingRules: ( 2.5.13.7 + NAME 'caseExactSubstringsMatch' + SYNTAX 1.3.6.1.4.1.1466.115.121.1.58 + X-ORIGIN 'RFC 4517' ) +matchingRules: ( 1.3.6.1.4.1.1466.109.114.2 + NAME 'caseIgnoreIA5Match' + SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 + X-ORIGIN 'RFC 4517' ) +matchingRules: ( 1.3.6.1.4.1.1466.109.114.3 + NAME 'caseIgnoreIA5SubstringsMatch' + SYNTAX 1.3.6.1.4.1.1466.115.121.1.58 + X-ORIGIN 'RFC 4517' ) +matchingRules: ( 2.5.13.11 + NAME 'caseIgnoreListMatch' + SYNTAX 1.3.6.1.4.1.1466.115.121.1.41 + X-ORIGIN 'RFC 4517' ) +matchingRules: ( 2.5.13.12 + NAME 'caseIgnoreListSubstringsMatch' + SYNTAX 1.3.6.1.4.1.1466.115.121.1.58 + X-ORIGIN 'RFC 4517' ) +matchingRules: ( 2.5.13.2 + NAME 'caseIgnoreMatch' + SYNTAX 1.3.6.1.4.1.1466.115.121.1.15 + X-ORIGIN 'RFC 4517' ) +matchingRules: ( 2.5.13.3 + NAME 'caseIgnoreOrderingMatch' + SYNTAX 1.3.6.1.4.1.1466.115.121.1.15 + X-ORIGIN 'RFC 4517' ) +matchingRules: ( 2.5.13.4 + NAME 'caseIgnoreSubstringsMatch' + SYNTAX 1.3.6.1.4.1.1466.115.121.1.58 + X-ORIGIN 'RFC 4517' ) +matchingRules: ( 2.5.13.31 + NAME 'directoryStringFirstComponentMatch' + SYNTAX 1.3.6.1.4.1.1466.115.121.1.15 + X-ORIGIN 'RFC 4517' ) +matchingRules: ( 2.5.13.1 + NAME 'distinguishedNameMatch' + SYNTAX 1.3.6.1.4.1.1466.115.121.1.12 + X-ORIGIN 'RFC 4517' ) +matchingRules: ( 2.5.13.27 + NAME 'generalizedTimeMatch' + SYNTAX 1.3.6.1.4.1.1466.115.121.1.24 + X-ORIGIN 'RFC 4517' ) +matchingRules: ( 2.5.13.28 + NAME 'generalizedTimeOrderingMatch' + SYNTAX 1.3.6.1.4.1.1466.115.121.1.24 + X-ORIGIN 'RFC 4517' ) +matchingRules: ( 2.5.13.29 + NAME 'integerFirstComponentMatch' + SYNTAX 1.3.6.1.4.1.1466.115.121.1.27 + X-ORIGIN 'RFC 4517' ) +matchingRules: ( 2.5.13.14 + NAME 'integerMatch' + SYNTAX 1.3.6.1.4.1.1466.115.121.1.27 + X-ORIGIN 'RFC 4517' ) +matchingRules: ( 2.5.13.15 + NAME 'integerOrderingMatch' + SYNTAX 1.3.6.1.4.1.1466.115.121.1.27 + X-ORIGIN 'RFC 4517' ) +matchingRules: ( 2.5.13.33 + NAME 'keywordMatch' + SYNTAX 1.3.6.1.4.1.1466.115.121.1.15 + X-ORIGIN 'RFC 4517' ) +matchingRules: ( 2.5.13.8 + NAME 'numericStringMatch' + SYNTAX 1.3.6.1.4.1.1466.115.121.1.36 + X-ORIGIN 'RFC 4517' ) +matchingRules: ( 2.5.13.9 + NAME 'numericStringOrderingMatch' + SYNTAX 1.3.6.1.4.1.1466.115.121.1.36 + X-ORIGIN 'RFC 4517' ) +matchingRules: ( 2.5.13.10 + NAME 'numericStringSubstringsMatch' + SYNTAX 1.3.6.1.4.1.1466.115.121.1.58 + X-ORIGIN 'RFC 4517' ) +matchingRules: ( 2.5.13.30 + NAME 'objectIdentifierFirstComponentMatch' + SYNTAX 1.3.6.1.4.1.1466.115.121.1.38 + X-ORIGIN 'RFC 4517' ) +matchingRules: ( 2.5.13.0 + NAME 'objectIdentifierMatch' + SYNTAX 1.3.6.1.4.1.1466.115.121.1.38 + X-ORIGIN 'RFC 4517' ) +matchingRules: ( 2.5.13.17 + NAME 'octetStringMatch' + SYNTAX 1.3.6.1.4.1.1466.115.121.1.40 + X-ORIGIN 'RFC 4517' ) +matchingRules: ( 2.5.13.18 + NAME 'octetStringOrderingMatch' + SYNTAX 1.3.6.1.4.1.1466.115.121.1.40 + X-ORIGIN 'RFC 4517' ) +matchingRules: ( 2.5.13.20 + NAME 'telephoneNumberMatch' + SYNTAX 1.3.6.1.4.1.1466.115.121.1.50 + X-ORIGIN 'RFC 4517' ) +matchingRules: ( 2.5.13.21 + NAME 'telephoneNumberSubstringsMatch' + SYNTAX 1.3.6.1.4.1.1466.115.121.1.58 + X-ORIGIN 'RFC 4517' ) +matchingRules: ( 2.5.13.23 + NAME 'uniqueMemberMatch' + SYNTAX 1.3.6.1.4.1.1466.115.121.1.34 + X-ORIGIN 'RFC 4517' ) +matchingRules: ( 2.5.13.32 + NAME 'wordMatch' + SYNTAX 1.3.6.1.4.1.1466.115.121.1.15 + X-ORIGIN 'RFC 4517' ) +attributeTypes: ( 2.5.4.0 + NAME 'objectClass' + EQUALITY objectIdentifierMatch + SYNTAX 1.3.6.1.4.1.1466.115.121.1.38 + X-ORIGIN 'RFC 4512' ) +attributeTypes: ( 2.5.4.1 + NAME 'aliasedObjectName' + EQUALITY distinguishedNameMatch + SYNTAX 1.3.6.1.4.1.1466.115.121.1.12 + SINGLE-VALUE + X-ORIGIN 'RFC 4512' ) +attributeTypes: ( 2.5.18.3 + NAME 'creatorsName' + EQUALITY distinguishedNameMatch + SYNTAX 1.3.6.1.4.1.1466.115.121.1.12 + SINGLE-VALUE + NO-USER-MODIFICATION + USAGE directoryOperation + X-ORIGIN 'RFC 4512' ) +attributeTypes: ( 2.5.18.1 + NAME 'createTimestamp' + EQUALITY generalizedTimeMatch + ORDERING generalizedTimeOrderingMatch + SYNTAX 1.3.6.1.4.1.1466.115.121.1.24 + SINGLE-VALUE + NO-USER-MODIFICATION + USAGE directoryOperation + X-ORIGIN 'RFC 4512' ) +attributeTypes: ( 2.5.18.4 + NAME 'modifiersName' + EQUALITY distinguishedNameMatch + SYNTAX 1.3.6.1.4.1.1466.115.121.1.12 + SINGLE-VALUE + NO-USER-MODIFICATION + USAGE directoryOperation + X-ORIGIN 'RFC 4512' ) +attributeTypes: ( 2.5.18.2 + NAME 'modifyTimestamp' + EQUALITY generalizedTimeMatch + ORDERING generalizedTimeOrderingMatch + SYNTAX 1.3.6.1.4.1.1466.115.121.1.24 + SINGLE-VALUE + NO-USER-MODIFICATION + USAGE directoryOperation + X-ORIGIN 'RFC 4512' ) +attributeTypes: ( 2.5.21.9 + NAME 'structuralObjectClass' + EQUALITY objectIdentifierMatch + SYNTAX 1.3.6.1.4.1.1466.115.121.1.38 + SINGLE-VALUE + NO-USER-MODIFICATION + USAGE directoryOperation + X-ORIGIN 'RFC 4512' ) +attributeTypes: ( 2.5.21.10 + NAME 'governingStructureRule' + EQUALITY integerMatch + SYNTAX 1.3.6.1.4.1.1466.115.121.1.27 + SINGLE-VALUE + NO-USER-MODIFICATION + USAGE directoryOperation + X-ORIGIN 'RFC 4512' ) +attributeTypes: ( 2.5.18.10 + NAME 'subschemaSubentry' + EQUALITY distinguishedNameMatch + SYNTAX 1.3.6.1.4.1.1466.115.121.1.12 + SINGLE-VALUE + NO-USER-MODIFICATION + USAGE directoryOperation + X-ORIGIN 'RFC 4512' ) +attributeTypes: ( 2.5.21.6 + NAME 'objectClasses' + EQUALITY objectIdentifierFirstComponentMatch + SYNTAX 1.3.6.1.4.1.1466.115.121.1.37 + USAGE directoryOperation + X-ORIGIN 'RFC 4512' ) +attributeTypes: ( 2.5.21.5 + NAME 'attributeTypes' + EQUALITY objectIdentifierFirstComponentMatch + SYNTAX 1.3.6.1.4.1.1466.115.121.1.3 + USAGE directoryOperation + X-ORIGIN 'RFC 4512' ) +attributeTypes: ( 2.5.21.4 + NAME 'matchingRules' + EQUALITY objectIdentifierFirstComponentMatch + SYNTAX 1.3.6.1.4.1.1466.115.121.1.30 + USAGE directoryOperation + X-ORIGIN 'RFC 4512' ) +attributeTypes: ( 2.5.21.8 + NAME 'matchingRuleUse' + EQUALITY objectIdentifierFirstComponentMatch + SYNTAX 1.3.6.1.4.1.1466.115.121.1.31 + USAGE directoryOperation + X-ORIGIN 'RFC 4512' ) +attributeTypes: ( 1.3.6.1.4.1.1466.101.120.16 + NAME 'ldapSyntaxes' + EQUALITY objectIdentifierFirstComponentMatch + SYNTAX 1.3.6.1.4.1.1466.115.121.1.54 + USAGE directoryOperation + X-ORIGIN 'RFC 4512' ) +attributeTypes: ( 2.5.21.2 + NAME 'dITContentRules' + EQUALITY objectIdentifierFirstComponentMatch + SYNTAX 1.3.6.1.4.1.1466.115.121.1.16 + USAGE directoryOperation + X-ORIGIN 'RFC 4512' ) +attributeTypes: ( 2.5.21.1 + NAME 'dITStructureRules' + EQUALITY integerFirstComponentMatch + SYNTAX 1.3.6.1.4.1.1466.115.121.1.17 + USAGE directoryOperation + X-ORIGIN 'RFC 4512' ) +attributeTypes: ( 2.5.21.7 + NAME 'nameForms' + EQUALITY objectIdentifierFirstComponentMatch + SYNTAX 1.3.6.1.4.1.1466.115.121.1.35 + USAGE directoryOperation + X-ORIGIN 'RFC 4512' ) +attributeTypes: ( 1.3.6.1.4.1.1466.101.120.6 + NAME 'altServer' + SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 + USAGE dSAOperation + X-ORIGIN 'RFC 4512' ) +attributeTypes: ( 1.3.6.1.4.1.1466.101.120.5 + NAME 'namingContexts' + SYNTAX 1.3.6.1.4.1.1466.115.121.1.12 + USAGE dSAOperation + X-ORIGIN 'RFC 4512' ) +attributeTypes: ( 1.3.6.1.4.1.1466.101.120.13 + NAME 'supportedControl' + SYNTAX 1.3.6.1.4.1.1466.115.121.1.38 + USAGE dSAOperation + X-ORIGIN 'RFC 4512' ) +attributeTypes: ( 1.3.6.1.4.1.1466.101.120.7 + NAME 'supportedExtension' + SYNTAX 1.3.6.1.4.1.1466.115.121.1.38 + USAGE dSAOperation + X-ORIGIN 'RFC 4512' ) +attributeTypes: ( 1.3.6.1.4.1.4203.1.3.5 + NAME 'supportedFeatures' + EQUALITY objectIdentifierMatch + SYNTAX 1.3.6.1.4.1.1466.115.121.1.38 + USAGE dSAOperation + X-ORIGIN 'RFC 4512' ) +attributeTypes: ( 1.3.6.1.4.1.1466.101.120.15 + NAME 'supportedLDAPVersion' + SYNTAX 1.3.6.1.4.1.1466.115.121.1.27 + USAGE dSAOperation + X-ORIGIN 'RFC 4512' ) +attributeTypes: ( 1.3.6.1.4.1.1466.101.120.14 + NAME 'supportedSASLMechanisms' + SYNTAX 1.3.6.1.4.1.1466.115.121.1.15 + USAGE dSAOperation + X-ORIGIN 'RFC 4512' ) +attributeTypes: ( 2.5.4.41 + NAME 'name' + EQUALITY caseIgnoreMatch + SUBSTR caseIgnoreSubstringsMatch + SYNTAX 1.3.6.1.4.1.1466.115.121.1.15 + X-ORIGIN 'RFC 4519' ) +attributeTypes: ( 2.5.4.15 + NAME 'businessCategory' + EQUALITY caseIgnoreMatch + SUBSTR caseIgnoreSubstringsMatch + SYNTAX 1.3.6.1.4.1.1466.115.121.1.15 + X-ORIGIN 'RFC 4519' ) +attributeTypes: ( 2.5.4.6 + NAME 'c' + SUP name + SYNTAX 1.3.6.1.4.1.1466.115.121.1.11 + SINGLE-VALUE + X-ORIGIN 'RFC 4519' ) +attributeTypes: ( 2.5.4.3 + NAME 'cn' + SUP name + X-ORIGIN 'RFC 4519' ) +attributeTypes: ( 0.9.2342.19200300.100.1.25 + NAME 'dc' + EQUALITY caseIgnoreIA5Match + SUBSTR caseIgnoreIA5SubstringsMatch + SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 + SINGLE-VALUE + X-ORIGIN 'RFC 4519' ) +attributeTypes: ( 2.5.4.13 + NAME 'description' + EQUALITY caseIgnoreMatch + SUBSTR caseIgnoreSubstringsMatch + SYNTAX 1.3.6.1.4.1.1466.115.121.1.15 + X-ORIGIN 'RFC 4519' ) +attributeTypes: ( 2.5.4.27 + NAME 'destinationIndicator' + EQUALITY caseIgnoreMatch + SUBSTR caseIgnoreSubstringsMatch + SYNTAX 1.3.6.1.4.1.1466.115.121.1.44 + X-ORIGIN 'RFC 4519' ) +attributeTypes: ( 2.5.4.49 + NAME 'distinguishedName' + EQUALITY distinguishedNameMatch + SYNTAX 1.3.6.1.4.1.1466.115.121.1.12 + X-ORIGIN 'RFC 4519' ) +attributeTypes: ( 2.5.4.46 + NAME 'dnQualifier' + EQUALITY caseIgnoreMatch + ORDERING caseIgnoreOrderingMatch + SUBSTR caseIgnoreSubstringsMatch + SYNTAX 1.3.6.1.4.1.1466.115.121.1.44 + X-ORIGIN 'RFC 4519' ) +attributeTypes: ( 2.5.4.47 + NAME 'enhancedSearchGuide' + SYNTAX 1.3.6.1.4.1.1466.115.121.1.21 + X-ORIGIN 'RFC 4519' ) +attributeTypes: ( 2.5.4.23 + NAME 'facsimileTelephoneNumber' + SYNTAX 1.3.6.1.4.1.1466.115.121.1.22 + X-ORIGIN 'RFC 4519' ) +attributeTypes: ( 2.5.4.44 + NAME 'generationQualifier' + SUP name + X-ORIGIN 'RFC 4519' ) +attributeTypes: ( 2.5.4.42 + NAME 'givenName' + SUP name + X-ORIGIN 'RFC 4519' ) +attributeTypes: ( 2.5.4.51 + NAME 'houseIdentifier' + EQUALITY caseIgnoreMatch + SUBSTR caseIgnoreSubstringsMatch + SYNTAX 1.3.6.1.4.1.1466.115.121.1.15 + X-ORIGIN 'RFC 4519' ) +attributeTypes: ( 2.5.4.43 + NAME 'initials' + SUP name + X-ORIGIN 'RFC 4519' ) +attributeTypes: ( 2.5.4.25 + NAME 'internationalISDNNumber' + EQUALITY numericStringMatch + SUBSTR numericStringSubstringsMatch + SYNTAX 1.3.6.1.4.1.1466.115.121.1.36 + X-ORIGIN 'RFC 4519' ) +attributeTypes: ( 2.5.4.7 + NAME 'l' + SUP name + X-ORIGIN 'RFC 4519' ) +attributeTypes: ( 2.5.4.31 + NAME 'member' + SUP distinguishedName + X-ORIGIN 'RFC 4519' ) +attributeTypes: ( 2.5.4.10 + NAME 'o' + SUP name + X-ORIGIN 'RFC 4519' ) +attributeTypes: ( 2.5.4.11 + NAME 'ou' + SUP name + X-ORIGIN 'RFC 4519' ) +attributeTypes: ( 2.5.4.32 + NAME 'owner' + SUP distinguishedName + X-ORIGIN 'RFC 4519' ) +attributeTypes: ( 2.5.4.19 + NAME 'physicalDeliveryOfficeName' + EQUALITY caseIgnoreMatch + SUBSTR caseIgnoreSubstringsMatch + SYNTAX 1.3.6.1.4.1.1466.115.121.1.15 + X-ORIGIN 'RFC 4519' ) +attributeTypes: ( 2.5.4.16 + NAME 'postalAddress' + EQUALITY caseIgnoreListMatch + SUBSTR caseIgnoreListSubstringsMatch + SYNTAX 1.3.6.1.4.1.1466.115.121.1.41 + X-ORIGIN 'RFC 4519' ) +attributeTypes: ( 2.5.4.17 + NAME 'postalCode' + EQUALITY caseIgnoreMatch + SUBSTR caseIgnoreSubstringsMatch + SYNTAX 1.3.6.1.4.1.1466.115.121.1.15 + X-ORIGIN 'RFC 4519' ) +attributeTypes: ( 2.5.4.18 + NAME 'postOfficeBox' + EQUALITY caseIgnoreMatch + SUBSTR caseIgnoreSubstringsMatch + SYNTAX 1.3.6.1.4.1.1466.115.121.1.15 + X-ORIGIN 'RFC 4519' ) +attributeTypes: ( 2.5.4.28 + NAME 'preferredDeliveryMethod' + SYNTAX 1.3.6.1.4.1.1466.115.121.1.14 + SINGLE-VALUE + X-ORIGIN 'RFC 4519' ) +attributeTypes: ( 2.5.4.26 + NAME 'registeredAddress' + SUP postalAddress + SYNTAX 1.3.6.1.4.1.1466.115.121.1.41 + X-ORIGIN 'RFC 4519' ) +attributeTypes: ( 2.5.4.33 + NAME 'roleOccupant' + SUP distinguishedName + X-ORIGIN 'RFC 4519' ) +attributeTypes: ( 2.5.4.14 + NAME 'searchGuide' + SYNTAX 1.3.6.1.4.1.1466.115.121.1.25 + X-ORIGIN 'RFC 4519' ) +attributeTypes: ( 2.5.4.34 + NAME 'seeAlso' + SUP distinguishedName + X-ORIGIN 'RFC 4519' ) +attributeTypes: ( 2.5.4.5 + NAME 'serialNumber' + EQUALITY caseIgnoreMatch + SUBSTR caseIgnoreSubstringsMatch + SYNTAX 1.3.6.1.4.1.1466.115.121.1.44 + X-ORIGIN 'RFC 4519' ) +attributeTypes: ( 2.5.4.4 + NAME 'sn' + SUP name + X-ORIGIN 'RFC 4519' ) +attributeTypes: ( 2.5.4.8 + NAME 'st' + SUP name + X-ORIGIN 'RFC 4519' ) +attributeTypes: ( 2.5.4.9 + NAME 'street' + EQUALITY caseIgnoreMatch + SUBSTR caseIgnoreSubstringsMatch + SYNTAX 1.3.6.1.4.1.1466.115.121.1.15 + X-ORIGIN 'RFC 4519' ) +attributeTypes: ( 2.5.4.20 + NAME 'telephoneNumber' + EQUALITY telephoneNumberMatch + SUBSTR telephoneNumberSubstringsMatch + SYNTAX 1.3.6.1.4.1.1466.115.121.1.50 + X-ORIGIN 'RFC 4519' ) +attributeTypes: ( 2.5.4.22 + NAME 'teletexTerminalIdentifier' + SYNTAX 1.3.6.1.4.1.1466.115.121.1.51 + X-ORIGIN 'RFC 4519' ) +attributeTypes: ( 2.5.4.21 + NAME 'telexNumber' + SYNTAX 1.3.6.1.4.1.1466.115.121.1.52 + X-ORIGIN 'RFC 4519' ) +attributeTypes: ( 2.5.4.12 + NAME 'title' + SUP name + X-ORIGIN 'RFC 4519' ) +attributeTypes: ( 0.9.2342.19200300.100.1.1 + NAME 'uid' + EQUALITY caseIgnoreMatch + SUBSTR caseIgnoreSubstringsMatch + SYNTAX 1.3.6.1.4.1.1466.115.121.1.15 + X-ORIGIN 'RFC 4519' ) +attributeTypes: ( 2.5.4.50 + NAME 'uniqueMember' + EQUALITY uniqueMemberMatch + SYNTAX 1.3.6.1.4.1.1466.115.121.1.34 + X-ORIGIN 'RFC 4519' ) +attributeTypes: ( 2.5.4.35 + NAME 'userPassword' + EQUALITY octetStringMatch + SYNTAX 1.3.6.1.4.1.1466.115.121.1.40 + X-ORIGIN 'RFC 4519' ) +attributeTypes: ( 2.5.4.24 + NAME 'x121Address' + EQUALITY numericStringMatch + SUBSTR numericStringSubstringsMatch + SYNTAX 1.3.6.1.4.1.1466.115.121.1.36 + X-ORIGIN 'RFC 4519' ) +attributeTypes: ( 2.5.4.45 + NAME 'x500UniqueIdentifier' + EQUALITY bitStringMatch + SYNTAX 1.3.6.1.4.1.1466.115.121.1.6 + X-ORIGIN 'RFC 4519' ) +attributeTypes: ( 2.16.840.1.113730.3.1.1 + NAME 'carLicense' + DESC 'vehicle license or registration plate' + EQUALITY caseIgnoreMatch + SUBSTR caseIgnoreSubstringsMatch + SYNTAX 1.3.6.1.4.1.1466.115.121.1.15 + X-ORIGIN 'RFC 2798' ) +attributeTypes: ( 2.16.840.1.113730.3.1.2 + NAME 'departmentNumber' + DESC 'identifies a department within an organization' + EQUALITY caseIgnoreMatch + SUBSTR caseIgnoreSubstringsMatch + SYNTAX 1.3.6.1.4.1.1466.115.121.1.15 + X-ORIGIN 'RFC 2798' ) +attributeTypes: ( 2.16.840.1.113730.3.1.241 + NAME 'displayName' + DESC 'preferred name of a person to be used when displaying entries' + EQUALITY caseIgnoreMatch + SUBSTR caseIgnoreSubstringsMatch + SYNTAX 1.3.6.1.4.1.1466.115.121.1.15 + SINGLE-VALUE + X-ORIGIN 'RFC 2798' ) +attributeTypes: ( 2.16.840.1.113730.3.1.3 + NAME 'employeeNumber' + DESC 'numerically identifies an employee within an organization' + EQUALITY caseIgnoreMatch + SUBSTR caseIgnoreSubstringsMatch + SYNTAX 1.3.6.1.4.1.1466.115.121.1.15 + SINGLE-VALUE + X-ORIGIN 'RFC 2798' ) +attributeTypes: ( 2.16.840.1.113730.3.1.4 + NAME 'employeeType' + DESC 'type of employment for a person' + EQUALITY caseIgnoreMatch + SUBSTR caseIgnoreSubstringsMatch + SYNTAX 1.3.6.1.4.1.1466.115.121.1.15 + X-ORIGIN 'RFC 2798' ) +attributeTypes: ( 0.9.2342.19200300.100.1.60 + NAME 'jpegPhoto' + DESC 'a JPEG image' + SYNTAX 1.3.6.1.4.1.1466.115.121.1.28 + X-ORIGIN 'RFC 2798' ) +attributeTypes: ( 2.16.840.1.113730.3.1.39 + NAME 'preferredLanguage' + DESC 'preferred written or spoken language for a person' + EQUALITY caseIgnoreMatch + SUBSTR caseIgnoreSubstringsMatch + SYNTAX 1.3.6.1.4.1.1466.115.121.1.15 + SINGLE-VALUE + X-ORIGIN 'RFC 2798' ) +attributeTypes: ( 2.16.840.1.113730.3.1.40 + NAME 'userSMIMECertificate' + DESC 'PKCS#7 SignedData used to support S/MIME' + SYNTAX 1.3.6.1.4.1.1466.115.121.1.5 + X-ORIGIN 'RFC 2798' ) +attributeTypes: ( 2.16.840.1.113730.3.1.216 + NAME 'userPKCS12' + DESC 'PKCS #12 PFX PDU for exchange of personal identity information' + SYNTAX 1.3.6.1.4.1.1466.115.121.1.5 + X-ORIGIN 'RFC 2798' ) +attributeTypes: ( 2.5.4.36 + NAME 'userCertificate' + DESC 'X.509 user certificate' + EQUALITY certificateExactMatch + SYNTAX 1.3.6.1.4.1.1466.115.121.1.8 + X-ORIGIN 'RFC 4523' ) +attributeTypes: ( 2.5.4.37 + NAME 'cACertificate' + DESC 'X.509 CA certificate' + EQUALITY certificateExactMatch + SYNTAX 1.3.6.1.4.1.1466.115.121.1.8 + X-ORIGIN 'RFC 4523' ) +attributeTypes: ( 2.5.4.40 + NAME 'crossCertificatePair' + DESC 'X.509 cross certificate pair' + EQUALITY certificatePairExactMatch + SYNTAX 1.3.6.1.4.1.1466.115.121.1.10 + X-ORIGIN 'RFC 4523' ) +attributeTypes: ( 2.5.4.39 + NAME 'certificateRevocationList' + DESC 'X.509 certificate revocation list' + EQUALITY certificateListExactMatch + SYNTAX 1.3.6.1.4.1.1466.115.121.1.9 + X-ORIGIN 'RFC 4523' ) +attributeTypes: ( 2.5.4.38 + NAME 'authorityRevocationList' + DESC 'X.509 authority revocation list' + EQUALITY certificateListExactMatch + SYNTAX 1.3.6.1.4.1.1466.115.121.1.9 + X-ORIGIN 'RFC 4523' ) +attributeTypes: ( 2.5.4.53 + NAME 'deltaRevocationList' + DESC 'X.509 delta revocation list' + EQUALITY certificateListExactMatch + SYNTAX 1.3.6.1.4.1.1466.115.121.1.9 + X-ORIGIN 'RFC 4523' ) +attributeTypes: ( 2.5.4.52 + NAME 'supportedAlgorithms' + DESC 'X.509 supported algorithms' + EQUALITY algorithmIdentifierMatch + SYNTAX 1.3.6.1.4.1.1466.115.121.1.49 + X-ORIGIN 'RFC 4523' ) +attributeTypes: ( 0.9.2342.19200300.100.1.37 + NAME 'associatedDomain' + EQUALITY caseIgnoreIA5Match + SUBSTR caseIgnoreIA5SubstringsMatch + SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 + X-ORIGIN 'RFC 4524' ) +attributeTypes: ( 0.9.2342.19200300.100.1.38 + NAME 'associatedName' + EQUALITY distinguishedNameMatch + SYNTAX 1.3.6.1.4.1.1466.115.121.1.12 + X-ORIGIN 'RFC 4524' ) +attributeTypes: ( 0.9.2342.19200300.100.1.48 + NAME 'buildingName' + EQUALITY caseIgnoreMatch + SUBSTR caseIgnoreSubstringsMatch + SYNTAX 1.3.6.1.4.1.1466.115.121.1.15{256} + X-ORIGIN 'RFC 4524' ) +attributeTypes: ( 0.9.2342.19200300.100.1.43 + NAME 'co' + EQUALITY caseIgnoreMatch + SUBSTR caseIgnoreSubstringsMatch + SYNTAX 1.3.6.1.4.1.1466.115.121.1.15 + X-ORIGIN 'RFC 4524' ) +attributeTypes: ( 0.9.2342.19200300.100.1.14 + NAME 'documentAuthor' + EQUALITY distinguishedNameMatch + SYNTAX 1.3.6.1.4.1.1466.115.121.1.12 + X-ORIGIN 'RFC 4524' ) +attributeTypes: ( 0.9.2342.19200300.100.1.11 + NAME 'documentIdentifier' + EQUALITY caseIgnoreMatch + SUBSTR caseIgnoreSubstringsMatch + SYNTAX 1.3.6.1.4.1.1466.115.121.1.15{256} + X-ORIGIN 'RFC 4524' ) +attributeTypes: ( 0.9.2342.19200300.100.1.15 + NAME 'documentLocation' + EQUALITY caseIgnoreMatch + SUBSTR caseIgnoreSubstringsMatch + SYNTAX 1.3.6.1.4.1.1466.115.121.1.15{256} + X-ORIGIN 'RFC 4524' ) +attributeTypes: ( 0.9.2342.19200300.100.1.56 + NAME 'documentPublisher' + EQUALITY caseIgnoreMatch + SUBSTR caseIgnoreSubstringsMatch + SYNTAX 1.3.6.1.4.1.1466.115.121.1.15 + X-ORIGIN 'RFC 4524' ) +attributeTypes: ( 0.9.2342.19200300.100.1.12 + NAME 'documentTitle' + EQUALITY caseIgnoreMatch + SUBSTR caseIgnoreSubstringsMatch + SYNTAX 1.3.6.1.4.1.1466.115.121.1.15{256} + X-ORIGIN 'RFC 4524' ) +attributeTypes: ( 0.9.2342.19200300.100.1.13 + NAME 'documentVersion' + EQUALITY caseIgnoreMatch + SUBSTR caseIgnoreSubstringsMatch + SYNTAX 1.3.6.1.4.1.1466.115.121.1.15{256} + X-ORIGIN 'RFC 4524' ) +attributeTypes: ( 0.9.2342.19200300.100.1.5 + NAME 'drink' + EQUALITY caseIgnoreMatch + SUBSTR caseIgnoreSubstringsMatch + SYNTAX 1.3.6.1.4.1.1466.115.121.1.15{256} + X-ORIGIN 'RFC 4524' ) +attributeTypes: ( 0.9.2342.19200300.100.1.20 + NAME 'homePhone' + EQUALITY telephoneNumberMatch + SUBSTR telephoneNumberSubstringsMatch + SYNTAX 1.3.6.1.4.1.1466.115.121.1.50 + X-ORIGIN 'RFC 4524' ) +attributeTypes: ( 0.9.2342.19200300.100.1.39 + NAME 'homePostalAddress' + EQUALITY caseIgnoreListMatch + SUBSTR caseIgnoreListSubstringsMatch + SYNTAX 1.3.6.1.4.1.1466.115.121.1.41 + X-ORIGIN 'RFC 4524' ) +attributeTypes: ( 0.9.2342.19200300.100.1.9 + NAME 'host' + EQUALITY caseIgnoreMatch + SUBSTR caseIgnoreSubstringsMatch + SYNTAX 1.3.6.1.4.1.1466.115.121.1.15{256} + X-ORIGIN 'RFC 4524' ) +attributeTypes: ( 0.9.2342.19200300.100.1.4 + NAME 'info' + EQUALITY caseIgnoreMatch + SUBSTR caseIgnoreSubstringsMatch + SYNTAX 1.3.6.1.4.1.1466.115.121.1.15{2048} + X-ORIGIN 'RFC 4524' ) +attributeTypes: ( 0.9.2342.19200300.100.1.3 + NAME 'mail' + EQUALITY caseIgnoreIA5Match + SUBSTR caseIgnoreIA5SubstringsMatch + SYNTAX 1.3.6.1.4.1.1466.115.121.1.26{256} + X-ORIGIN 'RFC 4524' ) +attributeTypes: ( 0.9.2342.19200300.100.1.10 + NAME 'manager' + EQUALITY distinguishedNameMatch + SYNTAX 1.3.6.1.4.1.1466.115.121.1.12 + X-ORIGIN 'RFC 4524' ) +attributeTypes: ( 0.9.2342.19200300.100.1.41 + NAME 'mobile' + EQUALITY telephoneNumberMatch + SUBSTR telephoneNumberSubstringsMatch + SYNTAX 1.3.6.1.4.1.1466.115.121.1.50 + X-ORIGIN 'RFC 4524' ) +attributeTypes: ( 0.9.2342.19200300.100.1.45 + NAME 'organizationalStatus' + EQUALITY caseIgnoreMatch + SUBSTR caseIgnoreSubstringsMatch + SYNTAX 1.3.6.1.4.1.1466.115.121.1.15{256} + X-ORIGIN 'RFC 4524' ) +attributeTypes: ( 0.9.2342.19200300.100.1.42 + NAME 'pager' + EQUALITY telephoneNumberMatch + SUBSTR telephoneNumberSubstringsMatch + SYNTAX 1.3.6.1.4.1.1466.115.121.1.50 + X-ORIGIN 'RFC 4524' ) +attributeTypes: ( 0.9.2342.19200300.100.1.40 + NAME 'personalTitle' + EQUALITY caseIgnoreMatch + SUBSTR caseIgnoreSubstringsMatch + SYNTAX 1.3.6.1.4.1.1466.115.121.1.15{256} + X-ORIGIN 'RFC 4524' ) +attributeTypes: ( 0.9.2342.19200300.100.1.6 + NAME 'roomNumber' + EQUALITY caseIgnoreMatch + SUBSTR caseIgnoreSubstringsMatch + SYNTAX 1.3.6.1.4.1.1466.115.121.1.15{256} + X-ORIGIN 'RFC 4524' ) +attributeTypes: ( 0.9.2342.19200300.100.1.21 + NAME 'secretary' + EQUALITY distinguishedNameMatch + SYNTAX 1.3.6.1.4.1.1466.115.121.1.12 + X-ORIGIN 'RFC 4524' ) +attributeTypes: ( 0.9.2342.19200300.100.1.44 + NAME 'uniqueIdentifier' + EQUALITY caseIgnoreMatch + SUBSTR caseIgnoreSubstringsMatch + SYNTAX 1.3.6.1.4.1.1466.115.121.1.15{256} + X-ORIGIN 'RFC 4524' ) +attributeTypes: ( 0.9.2342.19200300.100.1.8 + NAME 'userClass' + EQUALITY caseIgnoreMatch + SUBSTR caseIgnoreSubstringsMatch + SYNTAX 1.3.6.1.4.1.1466.115.121.1.15{256} + X-ORIGIN 'RFC 4524' ) +attributeTypes: ( 0.9.2342.19200300.100.1.55 + NAME 'audio' + EQUALITY octetStringMatch + SYNTAX 1.3.6.1.4.1.1466.115.121.1.40{250000} + X-ORIGIN 'RFC 2798' ) +attributeTypes: ( 0.9.2342.19200300.100.1.7 + NAME 'photo' + X-ORIGIN 'RFC 2798' ) +attributeTypes: ( 1.3.6.1.4.1.250.1.57 + NAME 'labeledURI' + EQUALITY caseExactMatch + SUBSTR caseExactSubstringsMatch + SYNTAX 1.3.6.1.4.1.1466.115.121.1.15 + X-ORIGIN 'RFC 2798' ) +attributeTypes: ( 1.3.6.1.1.20 + NAME 'entryDN' + DESC 'DN of the entry' + EQUALITY distinguishedNameMatch + SYNTAX 1.3.6.1.4.1.1466.115.121.1.12 + SINGLE-VALUE + NO-USER-MODIFICATION + USAGE directoryOperation + X-ORIGIN 'RFC 5020' ) +attributeTypes: ( 2.16.840.1.113730.3.1.34 + NAME 'ref' + DESC 'named reference - a labeledURI' + EQUALITY caseExactMatch + SYNTAX 1.3.6.1.4.1.1466.115.121.1.15 + USAGE distributedOperation + X-ORIGIN 'RFC 3296' ) +attributeTypes: ( 1.3.6.1.1.4 + NAME 'vendorName' + EQUALITY 1.3.6.1.4.1.1466.109.114.1 + SYNTAX 1.3.6.1.4.1.1466.115.121.1.15 + SINGLE-VALUE + NO-USER-MODIFICATION + USAGE dSAOperation + X-ORIGIN 'RFC 3045' ) +attributeTypes: ( 1.3.6.1.1.5 + NAME 'vendorVersion' + EQUALITY 1.3.6.1.4.1.1466.109.114.1 + SYNTAX 1.3.6.1.4.1.1466.115.121.1.15 + SINGLE-VALUE + NO-USER-MODIFICATION + USAGE dSAOperation + X-ORIGIN 'RFC 3045' ) +attributeTypes: ( 1.3.6.1.1.16.4 + NAME 'entryUUID' + DESC 'UUID of the entry' + EQUALITY uuidMatch + ORDERING uuidOrderingMatch + SYNTAX 1.3.6.1.1.16.1 + SINGLE-VALUE + NO-USER-MODIFICATION + USAGE directoryOperation + X-ORIGIN 'RFC 4530' ) +attributeTypes: ( 1.3.6.1.4.1.453.16.2.103 + NAME 'numSubordinates' + DESC 'count of immediate subordinates' + EQUALITY integerMatch + ORDERING integerOrderingMatch + SYNTAX 1.3.6.1.4.1.453.16.2.103 + SINGLE-VALUE + NO-USER-MODIFICATION + USAGE directoryOperation + X-ORIGIN 'draft-ietf-boreham-numsubordinates' ) +attributeTypes: ( 1.3.6.1.4.1.7628.5.4.1 + NAME 'inheritable' + SYNTAX BOOLEAN + SINGLE-VALUE + NO-USER-MODIFICATION + USAGE dSAOperation + X-ORIGIN 'draft-ietf-ldup-subentry' ) +attributeTypes: ( 1.3.6.1.4.1.7628.5.4.2 + NAME 'blockInheritance' + SYNTAX BOOLEAN + SINGLE-VALUE + NO-USER-MODIFICATION + USAGE dSAOperation + X-ORIGIN 'draft-ietf-ldup-subentry' ) +attributeTypes: ( 2.16.840.1.113730.3.1.5 + NAME 'changeNumber' + DESC 'a number which uniquely identifies a change made to a directory entry' + SYNTAX 1.3.6.1.4.1.1466.115.121.1.27 + EQUALITY integerMatch + ORDERING integerOrderingMatch + SINGLE-VALUE + X-ORIGIN 'draft-good-ldap-changelog' ) +attributeTypes: ( 2.16.840.1.113730.3.1.6 + NAME 'targetDN' + DESC 'the DN of the entry which was modified' + EQUALITY distinguishedNameMatch + SYNTAX 1.3.6.1.4.1.1466.115.121.1.12 + SINGLE-VALUE + X-ORIGIN 'draft-good-ldap-changelog' ) +attributeTypes: ( 2.16.840.1.113730.3.1.7 + NAME 'changeType' + DESC 'the type of change made to an entry' + EQUALITY caseIgnoreMatch + SYNTAX 1.3.6.1.4.1.1466.115.121.1.15 + SINGLE-VALUE + X-ORIGIN 'draft-good-ldap-changelog' ) +attributeTypes: ( 2.16.840.1.113730.3.1.8 + NAME 'changes' + DESC 'a set of changes to apply to an entry' + SYNTAX 1.3.6.1.4.1.1466.115.121.1.40 + X-ORIGIN 'draft-good-ldap-changelog' ) +attributeTypes: ( 2.16.840.1.113730.3.1.9 + NAME 'newRDN' + DESC 'the new RDN of an entry which is the target of a modrdn operation' + EQUALITY distinguishedNameMatch + SYNTAX 1.3.6.1.4.1.1466.115.121.1.12 + SINGLE-VALUE + X-ORIGIN 'draft-good-ldap-changelog' ) +attributeTypes: ( 2.16.840.1.113730.3.1.10 + NAME 'deleteOldRDN' + DESC 'a flag which indicates if the old RDN should be retained as an + attribute of the entry' + EQUALITY booleanMatch + SYNTAX 1.3.6.1.4.1.1466.115.121.1.7 + SINGLE-VALUE + X-ORIGIN 'draft-good-ldap-changelog' ) +attributeTypes: ( 2.16.840.1.113730.3.1.11 + NAME 'newSuperior' + DESC 'the new parent of an entry which is the target of a moddn operation' + EQUALITY distinguishedNameMatch + SYNTAX 1.3.6.1.4.1.1466.115.121.1.12 + SINGLE-VALUE + X-ORIGIN 'draft-good-ldap-changelog' ) +attributeTypes: ( 2.16.840.1.113730.3.1.35 + NAME 'changelog' + DESC 'the distinguished name of the entry which contains the set of entries + comprising the server changelog' + EQUALITY distinguishedNameMatch + SYNTAX 1.3.6.1.4.1.1466.115.121.1.12 + X-ORIGIN 'draft-good-ldap-changelog' ) +attributeTypes: ( 1.3.6.1.4.1.4203.1.3.3 + NAME 'supportedAuthPasswordSchemes' + DESC 'supported password storage schemes' + EQUALITY caseExactIA5Match + SYNTAX 1.3.6.1.4.1.1466.115.121.1.26{32} + USAGE dSAOperation + X-ORIGIN 'RFC 3112' ) +attributeTypes: ( 1.3.6.1.4.1.4203.1.3.4 + NAME 'authPassword' + DESC 'password authentication information' + EQUALITY 1.3.6.1.4.1.4203.1.2.2 + SYNTAX 1.3.6.1.4.1.4203.1.1.2 + X-ORIGIN 'RFC 3112' ) +attributeTypes: ( 2.16.840.1.113730.3.1.55 + NAME 'aci' + SYNTAX 1.3.6.1.4.1.1466.115.121.1.15 + USAGE directoryOperation + X-ORIGIN 'De facto standard' ) +objectClasses: ( 2.5.6.0 + NAME 'top' + ABSTRACT + MUST objectClass + X-ORIGIN 'RFC 4512' ) +objectClasses: ( 2.5.6.1 + NAME 'alias' + SUP top + STRUCTURAL + MUST aliasedObjectName + X-ORIGIN 'RFC 4512' ) +objectClasses: ( 1.3.6.1.4.1.1466.101.120.111 + NAME 'extensibleObject' + SUP top + AUXILIARY + X-ORIGIN 'RFC 4512' ) +objectClasses: ( 2.5.20.1 + NAME 'subschema' + AUXILIARY + MAY ( dITStructureRules $ + nameForms $ + ditContentRules $ + objectClasses $ + attributeTypes $ + matchingRules $ + matchingRuleUse ) + X-ORIGIN 'RFC 4512' ) +objectClasses: ( 2.5.6.11 + NAME 'applicationProcess' + SUP top + STRUCTURAL + MUST cn + MAY ( seeAlso $ + ou $ + l $ + description ) + X-ORIGIN 'RFC 4519' ) +objectClasses: ( 2.5.6.2 + NAME 'country' + SUP top + STRUCTURAL + MUST c + MAY ( searchGuide $ + description ) + X-ORIGIN 'RFC 4519' ) +objectClasses: ( 1.3.6.1.4.1.1466.344 + NAME 'dcObject' + SUP top + AUXILIARY + MUST dc + X-ORIGIN 'RFC 4519' ) +objectClasses: ( 2.5.6.14 + NAME 'device' + SUP top + STRUCTURAL + MUST cn + MAY ( serialNumber $ + seeAlso $ + owner $ + ou $ + o $ + l $ + description ) + X-ORIGIN 'RFC 4519' ) +objectClasses: ( 2.5.6.9 + NAME 'groupOfNames' + SUP top + STRUCTURAL + MUST cn + MAY ( member $ + businessCategory $ + seeAlso $ + owner $ + ou $ + o $ + description ) + X-ORIGIN 'RFC 4519' ) +objectClasses: ( 2.5.6.17 + NAME 'groupOfUniqueNames' + SUP top + STRUCTURAL + MUST cn + MAY ( uniqueMember $ + businessCategory $ + seeAlso $ + owner $ + ou $ + o $ + description ) + X-ORIGIN 'RFC 4519' ) +objectClasses: ( 2.5.6.3 + NAME 'locality' + SUP top + STRUCTURAL + MAY ( street $ + seeAlso $ + searchGuide $ + st $ + l $ + description ) + X-ORIGIN 'RFC 4519' ) +objectClasses: ( 2.5.6.4 + NAME 'organization' + SUP top + STRUCTURAL + MUST o + MAY ( userPassword $ + searchGuide $ + seeAlso $ + businessCategory $ + x121Address $ + registeredAddress $ + destinationIndicator $ + preferredDeliveryMethod $ + telexNumber $ + teletexTerminalIdentifier $ + telephoneNumber $ + internationalISDNNumber $ + facsimileTelephoneNumber $ + street $ + postOfficeBox $ + postalCode $ + postalAddress $ + physicalDeliveryOfficeName $ + st $ + l $ + description ) + X-ORIGIN 'RFC 4519' ) +objectClasses: ( 2.5.6.6 + NAME 'person' + SUP top + STRUCTURAL + MUST ( sn $ + cn ) + MAY ( userPassword $ + telephoneNumber $ + seeAlso $ + description ) + X-ORIGIN 'RFC 4519' ) +objectClasses: ( 2.5.6.7 + NAME 'organizationalPerson' + SUP person + STRUCTURAL + MAY ( title $ + x121Address $ + registeredAddress $ + destinationIndicator $ + preferredDeliveryMethod $ + telexNumber $ + teletexTerminalIdentifier $ + telephoneNumber $ + internationalISDNNumber $ + facsimileTelephoneNumber $ + street $ + postOfficeBox $ + postalCode $ + postalAddress $ + physicalDeliveryOfficeName $ + ou $ + st $ + l ) + X-ORIGIN 'RFC 4519' ) +objectClasses: ( 2.5.6.8 + NAME 'organizationalRole' + SUP top + STRUCTURAL + MUST cn + MAY ( x121Address $ + registeredAddress $ + destinationIndicator $ + preferredDeliveryMethod $ + telexNumber $ + teletexTerminalIdentifier $ + telephoneNumber $ + internationalISDNNumber $ + facsimileTelephoneNumber $ + seeAlso $ + roleOccupant $ + preferredDeliveryMethod $ + street $ + postOfficeBox $ + postalCode $ + postalAddress $ + physicalDeliveryOfficeName $ + ou $ + st $ + l $ + description ) + X-ORIGIN 'RFC 4519' ) +objectClasses: ( 2.5.6.5 + NAME 'organizationalUnit' + SUP top + STRUCTURAL + MUST ou + MAY ( businessCategory $ + description $ + destinationIndicator $ + facsimileTelephoneNumber $ + internationalISDNNumber $ + l $ + physicalDeliveryOfficeName $ + postalAddress $ + postalCode $ + postOfficeBox $ + preferredDeliveryMethod $ + registeredAddress $ + searchGuide $ + seeAlso $ + st $ + street $ + telephoneNumber $ + teletexTerminalIdentifier $ + telexNumber $ + userPassword $ + x121Address ) + X-ORIGIN 'RFC 4519' ) +objectClasses: ( 2.5.6.10 + NAME 'residentialPerson' + SUP person + STRUCTURAL + MUST l + MAY ( businessCategory $ + x121Address $ + registeredAddress $ + destinationIndicator $ + preferredDeliveryMethod $ + telexNumber $ + teletexTerminalIdentifier $ + telephoneNumber $ + internationalISDNNumber $ + facsimileTelephoneNumber $ + preferredDeliveryMethod $ + street $ + postOfficeBox $ + postalCode $ + postalAddress $ + physicalDeliveryOfficeName $ + st $ + l ) + X-ORIGIN 'RFC 4519' ) +objectClasses: ( 1.3.6.1.1.3.1 + NAME 'uidObject' + SUP top + AUXILIARY + MUST uid + X-ORIGIN 'RFC 4519' ) +objectClasses: ( 2.16.840.1.113730.3.2.2 + NAME 'inetOrgPerson' + SUP organizationalPerson + STRUCTURAL + MAY ( audio $ + businessCategory $ + carLicense $ + departmentNumber $ + displayName $ + employeeNumber $ + employeeType $ + givenName $ + homePhone $ + homePostalAddress $ + initials $ + jpegPhoto $ + labeledURI $ + mail $ + manager $ + mobile $ + o $ + pager $ + photo $ + roomNumber $ + secretary $ + uid $ + userCertificate $ + x500uniqueIdentifier $ + preferredLanguage $ + userSMIMECertificate $ + userPKCS12 ) + X-ORIGIN 'RFC 2798' ) +objectClasses: ( 2.5.6.21 + NAME 'pkiUser' + DESC 'X.509 PKI User' + SUP top AUXILIARY + MAY userCertificate + X-ORIGIN 'RFC 4523' ) +objectClasses: ( 2.5.6.22 + NAME 'pkiCA' + DESC 'X.509 PKI Certificate Authority' + SUP top + AUXILIARY + MAY ( cACertificate $ + certificateRevocationList $ + authorityRevocationList $ + crossCertificatePair ) + X-ORIGIN 'RFC 4523' ) +objectClasses: ( 2.5.6.19 + NAME 'cRLDistributionPoint' + DESC 'X.509 CRL distribution point' + SUP top + STRUCTURAL + MUST cn + MAY ( certificateRevocationList $ + authorityRevocationList $ + deltaRevocationList ) + X-ORIGIN 'RFC 4523' ) +objectClasses: ( 2.5.6.23 + NAME 'deltaCRL' + DESC 'X.509 delta CRL' + SUP top + AUXILIARY + MAY deltaRevocationList + X-ORIGIN 'RFC 4523' ) +objectClasses: ( 2.5.6.15 + NAME 'strongAuthenticationUser' + DESC 'X.521 strong authentication user' + SUP top + AUXILIARY + MUST userCertificate + X-ORIGIN 'RFC 4523' ) +objectClasses: ( 2.5.6.18 + NAME 'userSecurityInformation' + DESC 'X.521 user security information' + SUP top + AUXILIARY + MAY ( supportedAlgorithms ) + X-ORIGIN 'RFC 4523' ) +objectClasses: ( 2.5.6.16 + NAME 'certificationAuthority' + DESC 'X.509 certificate authority' + SUP top + AUXILIARY + MUST ( authorityRevocationList $ + certificateRevocationList $ + cACertificate ) + MAY crossCertificatePair + X-ORIGIN 'RFC 4523' ) +objectClasses: ( 2.5.6.16.2 + NAME 'certificationAuthority-V2' + DESC 'X.509 certificate authority, version 2' + SUP certificationAuthority + AUXILIARY + MAY deltaRevocationList + X-ORIGIN 'RFC 4523' ) +objectClasses: ( 0.9.2342.19200300.100.4.5 + NAME 'account' + SUP top STRUCTURAL + MUST uid + MAY ( description $ + seeAlso $ + l $ + o $ + ou $ + host ) + X-ORIGIN 'RFC 4524' ) +objectClasses: ( 0.9.2342.19200300.100.4.6 + NAME 'document' + SUP top STRUCTURAL + MUST documentIdentifier + MAY ( cn $ + description $ + seeAlso $ + l $ + o $ + ou $ + documentTitle $ + documentVersion $ + documentAuthor $ + documentLocation $ + documentPublisher ) + X-ORIGIN 'RFC 4524' ) +objectClasses: ( 0.9.2342.19200300.100.4.9 + NAME 'documentSeries' + SUP top STRUCTURAL + MUST cn + MAY ( description $ + l $ + o $ + ou $ + seeAlso $ + telephonenumber ) + X-ORIGIN 'RFC 4524' ) +objectClasses: ( 0.9.2342.19200300.100.4.13 + NAME 'domain' + SUP top + STRUCTURAL + MUST dc + MAY ( userPassword $ + searchGuide $ + seeAlso $ + businessCategory $ + x121Address $ + registeredAddress $ + destinationIndicator $ + preferredDeliveryMethod $ + telexNumber $ + teletexTerminalIdentifier $ + telephoneNumber $ + internationaliSDNNumber $ + facsimileTelephoneNumber $ + street $ + postOfficeBox $ + postalCode $ + postalAddress $ + physicalDeliveryOfficeName $ + st $ + l $ + description $ + o $ + associatedName ) + X-ORIGIN 'RFC 4524' ) +objectClasses: ( 0.9.2342.19200300.100.4.17 + NAME 'domainRelatedObject' + SUP top + AUXILIARY + MUST associatedDomain + X-ORIGIN 'RFC 4524' ) +objectClasses: ( 0.9.2342.19200300.100.4.18 + NAME 'friendlyCountry' + SUP country + STRUCTURAL + MUST co + X-ORIGIN 'RFC 4524' ) +objectClasses: ( 0.9.2342.19200300.100.4.14 + NAME 'rFC822localPart' + SUP domain + STRUCTURAL + MAY ( cn $ + description $ + destinationIndicator $ + facsimileTelephoneNumber $ + internationaliSDNNumber $ + physicalDeliveryOfficeName $ + postalAddress $ + postalCode $ + postOfficeBox $ + preferredDeliveryMethod $ + registeredAddress $ + seeAlso $ + sn $ + street $ + telephoneNumber $ + teletexTerminalIdentifier $ + telexNumber $ + x121Address ) + X-ORIGIN 'RFC 4524' ) +objectClasses: ( 0.9.2342.19200300.100.4.7 + NAME 'room' + SUP top + STRUCTURAL + MUST cn + MAY ( roomNumber $ + description $ + seeAlso $ + telephoneNumber ) + X-ORIGIN 'RFC 4524' ) +objectClasses: ( 0.9.2342.19200300.100.4.19 + NAME 'simpleSecurityObject' + SUP top + AUXILIARY + MUST userPassword + X-ORIGIN 'RFC 4524' ) +objectClasses: ( 2.16.840.1.113730.3.2.6 + NAME 'referral' + DESC 'named subordinate reference object' + STRUCTURAL + MUST ref + X-ORIGIN 'RFC 3296' ) +objectClasses: ( 1.3.6.1.4.1.5322.13.1.1 + NAME 'namedObject' + SUP top + STRUCTURAL MAY cn + X-ORIGIN 'draft-howard-namedobject' ) +objectClasses: ( 2.16.840.1.113719.2.142.6.1.1 + NAME 'ldapSubEntry' + DESC 'LDAP Subentry class, version 1' + SUP top + STRUCTURAL + MAY ( cn ) + X-ORIGIN 'draft-ietf-ldup-subentry' ) +objectClasses: ( 1.3.6.1.4.1.7628.5.6.1.1 + NAME 'inheritableLDAPSubEntry' + DESC 'Inheritable LDAP Subentry class, version 1' + SUP ldapSubEntry + STRUCTURAL + MUST ( inheritable ) + MAY ( blockInheritance ) + X-ORIGIN 'draft-ietf-ldup-subentry' ) +objectClasses: ( 2.16.840.1.113730.3.2.1 + NAME 'changeLogEntry' + SUP top + STRUCTURAL + MUST ( changeNumber $ + targetDN $ + changeType ) + MAY ( changes $ + newRDN $ + deleteOldRDN $ + newSuperior ) + X-ORIGIN 'draft-good-ldap-changelog' ) +objectClasses: ( 1.3.6.1.4.1.4203.1.4.7 + NAME 'authPasswordObject' + DESC 'authentication password mix in class' + AUXILIARY + MAY authPassword + X-ORIGIN 'RFC 3112' ) + diff --git a/embedded-ldap-junit5/pom.xml b/embedded-ldap-junit5/pom.xml new file mode 100644 index 0000000..b366ad8 --- /dev/null +++ b/embedded-ldap-junit5/pom.xml @@ -0,0 +1,35 @@ + + + + embedded-ldap-parent + org.zapodot + 0.9-SNAPSHOT + + 4.0.0 + + embedded-ldap-junit5 + + + + org.zapodot + embedded-ldap-core + ${project.version} + + + + org.junit.jupiter + junit-jupiter-api + ${junit5.version} + + + + + org.junit.jupiter + junit-jupiter-engine + ${junit5.version} + test + + + diff --git a/embedded-ldap-junit5/src/main/java/org/zapodot/junit/ldap/internal/EmbeddedLdapExtensionImpl.java b/embedded-ldap-junit5/src/main/java/org/zapodot/junit/ldap/internal/EmbeddedLdapExtensionImpl.java new file mode 100644 index 0000000..66dd274 --- /dev/null +++ b/embedded-ldap-junit5/src/main/java/org/zapodot/junit/ldap/internal/EmbeddedLdapExtensionImpl.java @@ -0,0 +1,56 @@ +package org.zapodot.junit.ldap.internal; + +import com.unboundid.ldap.listener.InMemoryDirectoryServer; +import com.unboundid.ldap.listener.InMemoryDirectoryServerConfig; +import com.unboundid.ldap.sdk.LDAPException; +import org.junit.jupiter.api.extension.ExtensionContext; +import org.zapodot.junit.ldap.junit5.EmbeddedLdapExtension; + +import javax.net.ssl.SSLSocketFactory; +import java.util.List; + +public class EmbeddedLdapExtensionImpl extends EmbeddedLdapServerImpl implements EmbeddedLdapExtension { + + public static EmbeddedLdapExtension createForConfiguration(final InMemoryDirectoryServerConfig inMemoryDirectoryServerConfig, + final AuthenticationConfiguration authenticationConfiguration, + final List ldifs, boolean useTls, SSLSocketFactory socketFactory) { + try { + return new EmbeddedLdapExtensionImpl(createServer(inMemoryDirectoryServerConfig, ldifs), + authenticationConfiguration, useTls, socketFactory); + } catch (LDAPException e) { + throw new IllegalStateException("Can not initiate in-memory LDAP server due to an exception", e); + } + } + + private boolean isStartedBeforeAll = false; + + public EmbeddedLdapExtensionImpl(InMemoryDirectoryServer inMemoryDirectoryServer, AuthenticationConfiguration authenticationConfiguration1, + boolean useTls, SSLSocketFactory socketFactory) { + super(inMemoryDirectoryServer, authenticationConfiguration1, useTls, socketFactory); + } + + @Override + public void beforeAll(ExtensionContext extensionContext) throws Exception { + isStartedBeforeAll = true; + startEmbeddedLdapServer(); + } + + @Override + public void afterAll(ExtensionContext extensionContext) { + takeDownEmbeddedLdapServer(); + } + + @Override + public void beforeEach(ExtensionContext extensionContext) throws Exception { + if (!isStartedBeforeAll) { + startEmbeddedLdapServer(); + } + } + + @Override + public void afterEach(ExtensionContext extensionContext) { + if (!isStartedBeforeAll) { + takeDownEmbeddedLdapServer(); + } + } +} diff --git a/embedded-ldap-junit5/src/main/java/org/zapodot/junit/ldap/junit5/EmbeddedLdapExtension.java b/embedded-ldap-junit5/src/main/java/org/zapodot/junit/ldap/junit5/EmbeddedLdapExtension.java new file mode 100644 index 0000000..10ccbf3 --- /dev/null +++ b/embedded-ldap-junit5/src/main/java/org/zapodot/junit/ldap/junit5/EmbeddedLdapExtension.java @@ -0,0 +1,14 @@ +package org.zapodot.junit.ldap.junit5; + +import org.junit.jupiter.api.extension.*; +import org.zapodot.junit.ldap.EmbeddedLdapServer; + +/** + * A JUnit 5 extension that can be registered with @{@link RegisterExtension} + * (supports both {@code static} and instance fields). + */ +public interface EmbeddedLdapExtension extends EmbeddedLdapServer, Extension, + BeforeEachCallback, AfterEachCallback, + BeforeAllCallback, AfterAllCallback { + +} diff --git a/embedded-ldap-junit5/src/main/java/org/zapodot/junit/ldap/junit5/EmbeddedLdapExtensionBuilder.java b/embedded-ldap-junit5/src/main/java/org/zapodot/junit/ldap/junit5/EmbeddedLdapExtensionBuilder.java new file mode 100644 index 0000000..dc37aaa --- /dev/null +++ b/embedded-ldap-junit5/src/main/java/org/zapodot/junit/ldap/junit5/EmbeddedLdapExtensionBuilder.java @@ -0,0 +1,42 @@ +package org.zapodot.junit.ldap.junit5; + +import org.zapodot.junit.ldap.internal.AbstractEmbeddedLdapBuilder; +import org.zapodot.junit.ldap.internal.EmbeddedLdapExtensionImpl; + +import java.util.Objects; + +/** + * A builder providing a fluent way of defining {@link EmbeddedLdapExtension} instances. + */ +public class EmbeddedLdapExtensionBuilder extends AbstractEmbeddedLdapBuilder { + + /** + * Creates a new builder + * + * @return a new EmbeddedLdapExtensionBuilder instance + */ + public static EmbeddedLdapExtensionBuilder newInstance() { + return new EmbeddedLdapExtensionBuilder(); + } + + /** + * Creates a new extension based on the information that was previously provided + * + * @return a new EmbeddedLdapExtension instance + */ + public EmbeddedLdapExtension build() { + Objects.requireNonNull(bindDSN, "\"bindDSN\" can not be null"); + return EmbeddedLdapExtensionImpl.createForConfiguration( + createInMemoryServerConfiguration(), + authenticationConfiguration, + ldifsToImport, + useTls, + socketFactory + ); + } + + @Override + protected EmbeddedLdapExtensionBuilder getThis() { + return this; + } +} diff --git a/embedded-ldap-junit5/src/test/java/org/zapodot/junit/ldap/junit5/EmbeddedLdapExtensionBuilderTest.java b/embedded-ldap-junit5/src/test/java/org/zapodot/junit/ldap/junit5/EmbeddedLdapExtensionBuilderTest.java new file mode 100644 index 0000000..bb8c546 --- /dev/null +++ b/embedded-ldap-junit5/src/test/java/org/zapodot/junit/ldap/junit5/EmbeddedLdapExtensionBuilderTest.java @@ -0,0 +1,99 @@ +package org.zapodot.junit.ldap.junit5; + +import org.junit.jupiter.api.Test; + +import static org.junit.jupiter.api.Assertions.assertNotNull; +import static org.junit.jupiter.api.Assertions.assertThrows; + +class EmbeddedLdapExtensionBuilderTest { + + @Test + void bindingToLegalPort() { + assertNotNull(EmbeddedLdapExtensionBuilder.newInstance().bindingToPort(9999)); + } + + @Test + void testPrematureLdapConnection() { + assertThrows(IllegalStateException.class, () -> + EmbeddedLdapExtensionBuilder.newInstance().build().ldapConnection() + ); + } + + @Test + void testPrematureContext() { + assertThrows(IllegalStateException.class, () -> + EmbeddedLdapExtensionBuilder.newInstance().build().context() + ); + } + + @Test + void testUnknownLDIF() { + assertThrows(IllegalArgumentException.class, () -> + EmbeddedLdapExtensionBuilder.newInstance().importingLdifs("nonExisting.ldif").build() + ); + } + + @Test + void testNullLDIF() { + assertNotNull(EmbeddedLdapExtensionBuilder.newInstance().importingLdifs(null).build()); + + } + + @Test + void testIllegalDSN() { + assertThrows(IllegalStateException.class, () -> + EmbeddedLdapExtensionBuilder.newInstance().usingBindDSN("bindDsn").build() + ); + } + + @Test + void testIllegalPort() { + assertThrows(IllegalArgumentException.class, () -> + EmbeddedLdapExtensionBuilder.newInstance().bindingToPort(Integer.MIN_VALUE).build() + ); + } + + @Test + void testSchemaNotFound() { + assertThrows(IllegalArgumentException.class, () -> + EmbeddedLdapExtensionBuilder.newInstance().withSchema("non-existing-schema.ldif").build() + ); + } + + @Test + void testSchemaIsNotAFile() { + assertThrows(IllegalArgumentException.class, () -> + EmbeddedLdapExtensionBuilder.newInstance().withSchema("folder").build() + ); + } + + @Test + void testSchemaIsInvalid() { + assertThrows(IllegalArgumentException.class, () -> + EmbeddedLdapExtensionBuilder.newInstance().withSchema("invalid.ldif").build() + ); + } + + @Test + void testSchemaFileUnsupportedIsInvalid() { + assertThrows(IllegalArgumentException.class, () -> + EmbeddedLdapExtensionBuilder.newInstance().withSchema("\"#%¤&&%/¤##¤¤").build() + ); + } + + @Test + void testInvalidPort() { + assertThrows(IllegalArgumentException.class, () -> + EmbeddedLdapExtensionBuilder.newInstance().bindingToPort(Integer.MAX_VALUE) + ); + } + + @Test + void testInvalidBindAddress() { + assertThrows(IllegalArgumentException.class, () -> + EmbeddedLdapExtensionBuilder.newInstance().bindingToAddress("åpsldfåpl") + ); + } + + +} diff --git a/embedded-ldap-junit5/src/test/java/org/zapodot/junit/ldap/junit5/EmbeddedLdapExtensionStaticTest.java b/embedded-ldap-junit5/src/test/java/org/zapodot/junit/ldap/junit5/EmbeddedLdapExtensionStaticTest.java new file mode 100644 index 0000000..5fa054f --- /dev/null +++ b/embedded-ldap-junit5/src/test/java/org/zapodot/junit/ldap/junit5/EmbeddedLdapExtensionStaticTest.java @@ -0,0 +1,28 @@ +package org.zapodot.junit.ldap.junit5; + +import com.unboundid.ldap.sdk.LDAPInterface; +import com.unboundid.ldap.sdk.SearchScope; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.extension.RegisterExtension; + +import static org.junit.jupiter.api.Assertions.assertEquals; + +class EmbeddedLdapExtensionStaticTest { + public static final String DOMAIN_DSN = "dc=zapodot,dc=org"; + + @RegisterExtension + public static EmbeddedLdapExtension embeddedLdapExtension = EmbeddedLdapExtensionBuilder + .newInstance() + .usingDomainDsn(DOMAIN_DSN) + .usingBindDSN("cn=Directory manager") + .usingBindCredentials("testPass") + .importingLdifs("example.ldif") + .build(); + + @Test + void testCheck() throws Exception { + final LDAPInterface ldapConnection = embeddedLdapExtension.ldapConnection(); + assertEquals(4, ldapConnection.search(DOMAIN_DSN, SearchScope.SUB, "(objectClass=*)").getEntryCount()); + + } +} diff --git a/embedded-ldap-junit5/src/test/java/org/zapodot/junit/ldap/junit5/EmbeddedLdapExtensionTest.java b/embedded-ldap-junit5/src/test/java/org/zapodot/junit/ldap/junit5/EmbeddedLdapExtensionTest.java new file mode 100644 index 0000000..d2e40f7 --- /dev/null +++ b/embedded-ldap-junit5/src/test/java/org/zapodot/junit/ldap/junit5/EmbeddedLdapExtensionTest.java @@ -0,0 +1,94 @@ +package org.zapodot.junit.ldap.junit5; + +import com.google.common.collect.Iterators; +import com.unboundid.ldap.sdk.*; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.extension.RegisterExtension; + +import javax.naming.Context; +import javax.naming.NamingEnumeration; +import javax.naming.directory.DirContext; +import javax.naming.directory.SearchControls; +import java.util.Arrays; + +import static org.junit.jupiter.api.Assertions.*; + +class EmbeddedLdapExtensionTest { + + public static final String DOMAIN_DSN = "dc=zapodot,dc=org"; + + @RegisterExtension + public EmbeddedLdapExtension embeddedLdapExtension = EmbeddedLdapExtensionBuilder + .newInstance() + .usingDomainDsn(DOMAIN_DSN) + .importingLdifs("example.ldif") + .build(); + + @Test + void testLdapConnection() throws Exception { + final LDAPInterface ldapConnection = embeddedLdapExtension.ldapConnection(); + final SearchResult searchResult = ldapConnection.search(DOMAIN_DSN, SearchScope.SUB, "(objectClass=person)"); + assertEquals(1, searchResult.getEntryCount()); + } + + @Test + void testRawLdapConnection() throws Exception { + final String commonName = "Test person"; + final String dn = String.format( + "cn=%s,ou=people,dc=zapodot,dc=org", + commonName); + LDAPConnection ldapConnection = embeddedLdapExtension.unsharedLdapConnection(); + try { + ldapConnection.add(new AddRequest(dn, Arrays.asList( + new Attribute("objectclass", "top", "person", "organizationalPerson", "inetOrgPerson"), + new Attribute("cn", commonName), new Attribute("sn", "Person"), new Attribute("uid", "test")))); + } finally { + // Forces the LDAP connection to be closed. This is not necessary as the rule will usually close it for you. + ldapConnection.close(); + } + ldapConnection = embeddedLdapExtension.unsharedLdapConnection(); + final SearchResultEntry entry = ldapConnection.searchForEntry(new SearchRequest(dn, + SearchScope.BASE, + "(objectClass=person)")); + assertNotNull(entry); + } + + @Test + void testDirContext() throws Exception { + final DirContext dirContext = embeddedLdapExtension.dirContext(); + final SearchControls searchControls = new SearchControls(); + searchControls.setSearchScope(SearchControls.SUBTREE_SCOPE); + final NamingEnumeration resultNamingEnumeration = + dirContext.search(DOMAIN_DSN, "(objectClass=person)", searchControls); + assertEquals(1, Iterators.size(Iterators.forEnumeration(resultNamingEnumeration))); + } + + @Test + void testContext() throws Exception { + final Context context = embeddedLdapExtension.context(); + final Object user = context.lookup("cn=Sondre Eikanger Kvalo,ou=people,dc=zapodot,dc=org"); + assertNotNull(user); + } + + @Test + void testContextClose() throws Exception { + final Context context = embeddedLdapExtension.context(); + context.close(); + assertNotNull(context.getNameInNamespace()); + + } + + @Test + void testEmbeddedServerPort() { + assertTrue(embeddedLdapExtension.embeddedServerPort() > 0); + + } + + @Test + void testNoPortAssignedYet() { + final EmbeddedLdapExtension embeddedLdapRule = new EmbeddedLdapExtensionBuilder().build(); + + assertThrows(IllegalStateException.class, embeddedLdapRule::embeddedServerPort); + + } +} diff --git a/embedded-ldap-junit5/src/test/resources/example.ldif b/embedded-ldap-junit5/src/test/resources/example.ldif new file mode 100644 index 0000000..5eb286a --- /dev/null +++ b/embedded-ldap-junit5/src/test/resources/example.ldif @@ -0,0 +1,28 @@ +version: 1 + +dn: dc=zapodot,dc=org +objectClass: domain +objectClass: top +dc: zapodot + +dn: ou=groups,dc=zapodot,dc=org +objectclass: top +objectclass: organizationalUnit +ou: groups + +dn: ou=people,dc=zapodot,dc=org +objectclass: top +objectclass: organizationalUnit +ou: people + +dn: cn=Sondre Eikanger Kvalo,ou=people,dc=zapodot,dc=org +objectclass: top +objectclass: person +objectclass: organizationalPerson +objectclass: inetOrgPerson +uid: zapodot +userPassword: password +cn: Sondre Eikanger Kvalo +cn:: U29uZHJlIEVpa2FuZ2VyIEt2YWzDuA== +sn: Person +description: Developer \ No newline at end of file diff --git a/pom.xml b/pom.xml index 1278128..cda93fa 100644 --- a/pom.xml +++ b/pom.xml @@ -5,10 +5,17 @@ 4.0.0 org.zapodot - embedded-ldap-junit + embedded-ldap-parent + pom 0.9.1-SNAPSHOT + + + embedded-ldap-core + embedded-ldap-junit + embedded-ldap-junit5 + ${project.artifactId} - Library that provides a JUnit rule for setting up an in-memory LDAP server by using the glorious Unboundid LDAP SDK + Library that provides a JUnit rule and extension for setting up an in-memory LDAP server by using the glorious Unboundid LDAP SDK https://github.com/zapodot/embedded-ldap-junit 2015 @@ -24,6 +31,7 @@ 4.13.2 + 5.7.0 6.0.6 1.7.36 31.1-jre @@ -40,51 +48,7 @@ 8 0.8.8 - - - com.unboundid - unboundid-ldapsdk - ${unboundid-ldapsdk.version} - - - junit - junit - ${junit.version} - - - com.google.guava - guava - ${guava.version} - - - net.bytebuddy - byte-buddy - ${byte-buddy.version} - - - org.slf4j - slf4j-api - ${slf4j.version} - - - ch.qos.logback - logback-classic - ${logback.version} - test - - - org.bouncycastle - bcprov-jdk15on - ${bouncycastle.version} - test - - - org.bouncycastle - bcpkix-jdk15on - ${bouncycastle.version} - test - - + @@ -189,6 +153,10 @@ ${java.version} + + maven-surefire-plugin + 2.22.2 + @@ -270,4 +238,5 @@ - \ No newline at end of file + +