diff --git a/README.md b/README.md
index e37a5c2..88517e0 100755
--- a/README.md
+++ b/README.md
@@ -1,7 +1,7 @@
# embedded-ldap-junit
[![Build Status](https://travis-ci.org/zapodot/embedded-ldap-junit.svg?branch=master)](https://travis-ci.org/zapodot/embedded-ldap-junit) [![Coverage Status](https://coveralls.io/repos/zapodot/embedded-ldap-junit/badge.svg)](https://coveralls.io/r/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
@@ -46,7 +46,9 @@ Java 8 or higher is required. It has proven pretty useful for several users and
libraryDependencies += "org.zapodot" % "embedded-ldap-junit" % "0.8.1"
```
-### Add to Junit test
+### Add to JUnit test
+
+#### JUnit 4
```java
import com.unboundid.ldap.sdk.LDAPInterface;
import javax.naming.Context;
@@ -96,3 +98,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/pom.xml b/pom.xml
index 6b05250..6182969 100644
--- a/pom.xml
+++ b/pom.xml
@@ -24,6 +24,7 @@
4.13
+ 5.7.0
5.0.1
1.7.30
29.0-jre
@@ -52,6 +53,12 @@
junit
${junit.version}
+
+ org.junit.jupiter
+ junit-jupiter-api
+ ${junit5.version}
+ true
+
com.google.guava
guava
@@ -264,4 +271,4 @@
-
\ No newline at end of file
+
diff --git a/src/main/java/org/zapodot/junit/ldap/EmbeddedLdapRule.java b/src/main/java/org/zapodot/junit/ldap/EmbeddedLdapRule.java
index 0b742b4..4aa70d4 100755
--- a/src/main/java/org/zapodot/junit/ldap/EmbeddedLdapRule.java
+++ b/src/main/java/org/zapodot/junit/ldap/EmbeddedLdapRule.java
@@ -1,65 +1,10 @@
package org.zapodot.junit.ldap;
-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 {
-
- /**
- * For tests depending on the UnboundID LDAP SDK. Returns a proxied version of an Unboundid interface that will be
- * closed when the test(s) have been invoked
- *
- * @return a shared LDAPConnection
- * @throws LDAPException if a connection can not be opened
- */
- LDAPInterface ldapConnection() throws LDAPException;
-
- /**
- * For tests depending on the UnboundID LDAP SDK that needs access to an ${link LDAPConnection} object
- * rather than the interface. If your code does not close the connection for you it will be closed on teardown
- *
- * @return a LDAPConnection connected to the embedded LDAP server
- * @throws LDAPException if an exception occurred while establishing the connection
- */
- LDAPConnection unsharedLdapConnection() throws LDAPException;
-
- /**
- * For tests depending on the standard Java JNDI API
- *
- * @return a shared Context connected to the in-memory LDAP server
- * @throws NamingException if context can not be created
- */
- Context context() throws NamingException;
-
- /**
- * Like {@link #context()}, but returns a DirContext
- *
- * @return a DirContext connected to the in-memory LDAP server
- * @throws NamingException if a LDAP failure happens during DirContext creation
- */
- DirContext dirContext() throws NamingException;
-
- /**
- * Gives access to the listening port for the currently running embedded LDAP server.
- * This will make it easier to use other integration mechanisms
- *
- * Note: the embedded LDAP server is by default configured to listen only on the loopback address
- * (i.e localhost/127.0.0.1) unless another address has been provided to the builder when the rule was built
- *
- *
- * @return the port number that the embedded server is listening to
- * @see org.zapodot.junit.ldap.EmbeddedLdapRuleBuilder#bindingToAddress(String)
- */
- int embeddedServerPort();
-
+public interface EmbeddedLdapRule extends EmbeddedLdapServer, TestRule {
}
diff --git a/src/main/java/org/zapodot/junit/ldap/EmbeddedLdapRuleBuilder.java b/src/main/java/org/zapodot/junit/ldap/EmbeddedLdapRuleBuilder.java
index 05ef238..b00771e 100755
--- a/src/main/java/org/zapodot/junit/ldap/EmbeddedLdapRuleBuilder.java
+++ b/src/main/java/org/zapodot/junit/ldap/EmbeddedLdapRuleBuilder.java
@@ -1,60 +1,14 @@
package org.zapodot.junit.ldap;
-import com.google.common.base.Function;
-import com.google.common.base.Optional;
-import com.google.common.collect.Lists;
-import com.google.common.io.Resources;
-import com.unboundid.ldap.listener.InMemoryDirectoryServerConfig;
-import com.unboundid.ldap.listener.InMemoryListenerConfig;
-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.AbstractEmbeddedLdapBuilder;
import org.zapodot.junit.ldap.internal.EmbeddedLdapRuleImpl;
-import java.io.File;
-import java.io.IOException;
-import java.net.InetAddress;
-import java.net.URISyntaxException;
-import java.net.UnknownHostException;
-import java.util.Arrays;
-import java.util.LinkedList;
-import java.util.List;
import java.util.Objects;
/**
* A builder providing a fluent way of defining EmbeddedLdapRule instances
*/
-public class EmbeddedLdapRuleBuilder {
-
- public static final String DEFAULT_DOMAIN = "dc=example,dc=com";
- public static final String DEFAULT_BIND_DSN = "cn=Directory manager";
- public static final String DEFAULT_BIND_CREDENTIALS = "password";
- public static final String LDAP_SERVER_LISTENER_NAME = "test-listener";
- public static final int MIN_PORT_EXCLUSIVE = 0;
- public static final int MAX_PORT_EXCLUSIVE = 65535;
- private List domainDsn = new LinkedList<>();
-
- private String bindDSN = DEFAULT_BIND_DSN;
-
- private String bindCredentials = DEFAULT_BIND_CREDENTIALS;
-
- private List ldifsToImport = new LinkedList<>();
-
- private List schemaLdifs = new LinkedList<>();
-
- private boolean addDefaultSchema = true;
-
- private Integer bindPort = 0;
-
- private InetAddress bindAddress = InetAddress.getLoopbackAddress();
-
- private AuthenticationConfiguration authenticationConfiguration;
-
- private InMemoryListenerConfig listenerConfig = null;
-
- public EmbeddedLdapRuleBuilder() {
- }
+public class EmbeddedLdapRuleBuilder extends AbstractEmbeddedLdapBuilder {
/**
* Creates a new builder
@@ -65,109 +19,8 @@ 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
- */
- public EmbeddedLdapRuleBuilder usingDomainDsn(final String domainDsn) {
- this.domainDsn.add(domainDsn);
- return this;
- }
-
- /**
- * 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
- */
- public EmbeddedLdapRuleBuilder usingBindDSN(final String bindDSN) {
- this.bindDSN = bindDSN;
- return this;
- }
-
- /**
- * 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
- */
- public EmbeddedLdapRuleBuilder usingBindCredentials(final String bindCredentials) {
- this.bindCredentials = bindCredentials;
- return this;
- }
-
- /**
- * 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
- * @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) {
- 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;
- }
-
- /**
- * 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
- * @throws IllegalArgumentException if the value provided for \"address\" is invalid
- */
- public EmbeddedLdapRuleBuilder bindingToAddress(final String address) {
- Objects.requireNonNull(address);
- try {
- final InetAddress addressByName = InetAddress.getByName(address);
- this.bindAddress = addressByName;
- } catch (UnknownHostException e) {
- throw new IllegalArgumentException(String.format("Unknown host address \"%s\"", address), e);
- }
- return this;
- }
-
- /**
- * 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
- */
- public EmbeddedLdapRuleBuilder withoutDefaultSchema() {
- this.addDefaultSchema = false;
- return this;
- }
-
- /**
- * 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.
- */
- public EmbeddedLdapRuleBuilder withSchema(final String... ldifSchemaFiles) {
- this.schemaLdifs.addAll(Arrays.asList(ldifSchemaFiles));
- return this;
- }
-
- /**
- * 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
- */
- public EmbeddedLdapRuleBuilder importingLdifs(final String... ldifFiles) {
- if (ldifFiles != null) {
- ldifsToImport.addAll(Arrays.asList(ldifFiles));
- }
- return this;
- }
-
- public EmbeddedLdapRuleBuilder withListener(InMemoryListenerConfig listenerConfig) {
- this.listenerConfig = listenerConfig;
+ @Override
+ protected EmbeddedLdapRuleBuilder getThis() {
return this;
}
@@ -183,82 +36,4 @@ public EmbeddedLdapRule build() {
ldifsToImport);
}
- private InMemoryDirectoryServerConfig createInMemoryServerConfiguration() {
- try {
- final InMemoryDirectoryServerConfig inMemoryDirectoryServerConfig =
- new InMemoryDirectoryServerConfig(domainDsnArray());
-
- if (bindCredentials != null) {
- this.authenticationConfiguration = new AuthenticationConfiguration(bindDSN, bindCredentials);
- inMemoryDirectoryServerConfig.addAdditionalBindCredentials(bindDSN, bindCredentials);
- }
-
- if (listenerConfig == null) {
- listenerConfig = InMemoryListenerConfig.createLDAPConfig(
- LDAP_SERVER_LISTENER_NAME,
- bindAddress,
- bindPort,
- null);
- }
- inMemoryDirectoryServerConfig.setListenerConfigs(listenerConfig);
- inMemoryDirectoryServerConfig.setSchema(customSchema());
- return inMemoryDirectoryServerConfig;
- } catch (LDAPException e) {
- throw new IllegalStateException(
- "Could not create configuration for the in-memory LDAP instance due to an exception",
- e);
- }
- }
-
- private String[] domainDsnArray() {
- if (domainDsn.size() == 0) {
- return new String[]{DEFAULT_DOMAIN};
- } else {
- return domainDsn.toArray(new String[]{});
- }
- }
-
- private Schema customSchema() {
- final List schemaFiles = schemaFiles();
-
- try {
- final Schema initialSchema = (addDefaultSchema ? Schema.getDefaultStandardSchema() : null);
- if (!schemaFiles.isEmpty()) {
- final Schema customSchema = initialSchema == null
- ? Schema.getSchema(schemaFiles)
- : Schema.mergeSchemas(initialSchema, Schema.getSchema(schemaFiles));
- return customSchema;
- } else {
- return null;
- }
-
- } catch (IOException | LDIFException | LDAPException e) {
- throw new IllegalArgumentException(
- "Could not create custom LDAP schema due, probably caused by an incorrectly formatted schema",
- e);
- }
- }
-
- private List schemaFiles() {
- return Lists.newArrayList(Lists.transform(this.schemaLdifs, new Function() {
- @Override
- public File apply(final String input) {
- try {
- final File file = new File(Resources.getResource(input).toURI());
- if (!file.isFile()) {
- throw new IllegalArgumentException(String.format(
- "The resource named \"%s\" can not be found or is not a file",
- input));
- }
- return file;
- } catch (URISyntaxException e) {
- throw new IllegalArgumentException(String.format(
- "The resource named \"%s\" is not a valid file reference",
- input), e);
- }
- }
- }));
- }
-
-
}
diff --git a/src/main/java/org/zapodot/junit/ldap/EmbeddedLdapServer.java b/src/main/java/org/zapodot/junit/ldap/EmbeddedLdapServer.java
new file mode 100644
index 0000000..45191d9
--- /dev/null
+++ b/src/main/java/org/zapodot/junit/ldap/EmbeddedLdapServer.java
@@ -0,0 +1,60 @@
+package org.zapodot.junit.ldap;
+
+import com.unboundid.ldap.sdk.LDAPConnection;
+import com.unboundid.ldap.sdk.LDAPException;
+import com.unboundid.ldap.sdk.LDAPInterface;
+
+import javax.naming.Context;
+import javax.naming.NamingException;
+import javax.naming.directory.DirContext;
+
+public interface EmbeddedLdapServer {
+
+ /**
+ * For tests depending on the UnboundID LDAP SDK. Returns a proxied version of an Unboundid interface that will be
+ * closed when the test(s) have been invoked
+ *
+ * @return a shared LDAPConnection
+ * @throws LDAPException if a connection can not be opened
+ */
+ LDAPInterface ldapConnection() throws LDAPException;
+
+ /**
+ * For tests depending on the UnboundID LDAP SDK that needs access to an ${link LDAPConnection} object
+ * rather than the interface. If your code does not close the connection for you it will be closed on teardown
+ *
+ * @return a LDAPConnection connected to the embedded LDAP server
+ * @throws LDAPException if an exception occurred while establishing the connection
+ */
+ LDAPConnection unsharedLdapConnection() throws LDAPException;
+
+ /**
+ * For tests depending on the standard Java JNDI API
+ *
+ * @return a shared Context connected to the in-memory LDAP server
+ * @throws NamingException if context can not be created
+ */
+ Context context() throws NamingException;
+
+ /**
+ * Like {@link #context()}, but returns a DirContext
+ *
+ * @return a DirContext connected to the in-memory LDAP server
+ * @throws NamingException if a LDAP failure happens during DirContext creation
+ */
+ DirContext dirContext() throws NamingException;
+
+ /**
+ * Gives access to the listening port for the currently running embedded LDAP server.
+ * This will make it easier to use other integration mechanisms
+ *
+ * Note: the embedded LDAP server is by default configured to listen only on the loopback address
+ * (i.e localhost/127.0.0.1) unless another address has been provided to the builder when the rule was built
+ *
+ *
+ * @return the port number that the embedded server is listening to
+ * @see org.zapodot.junit.ldap.EmbeddedLdapRuleBuilder#bindingToAddress(String)
+ */
+ int embeddedServerPort();
+
+}
diff --git a/src/main/java/org/zapodot/junit/ldap/internal/AbstractEmbeddedLdapBuilder.java b/src/main/java/org/zapodot/junit/ldap/internal/AbstractEmbeddedLdapBuilder.java
new file mode 100644
index 0000000..e5326ea
--- /dev/null
+++ b/src/main/java/org/zapodot/junit/ldap/internal/AbstractEmbeddedLdapBuilder.java
@@ -0,0 +1,240 @@
+package org.zapodot.junit.ldap.internal;
+
+import com.google.common.base.Function;
+import com.google.common.collect.Lists;
+import com.google.common.io.Resources;
+import com.unboundid.ldap.listener.InMemoryDirectoryServerConfig;
+import com.unboundid.ldap.listener.InMemoryListenerConfig;
+import com.unboundid.ldap.sdk.LDAPException;
+import com.unboundid.ldap.sdk.schema.Schema;
+import com.unboundid.ldif.LDIFException;
+
+import java.io.File;
+import java.io.IOException;
+import java.net.InetAddress;
+import java.net.URISyntaxException;
+import java.net.UnknownHostException;
+import java.util.Arrays;
+import java.util.LinkedList;
+import java.util.List;
+import java.util.Objects;
+
+/**
+ * A builder providing a fluent way of defining {@link org.zapodot.junit.ldap.EmbeddedLdapRule}
+ * or {@link org.zapodot.junit.ldap.junit5.EmbeddedLdapExtension} instances.
+ */
+public abstract class AbstractEmbeddedLdapBuilder> {
+
+ public static final String DEFAULT_DOMAIN = "dc=example,dc=com";
+ public static final String DEFAULT_BIND_DSN = "cn=Directory manager";
+ public static final String DEFAULT_BIND_CREDENTIALS = "password";
+ public static final String LDAP_SERVER_LISTENER_NAME = "test-listener";
+ public static final int MIN_PORT_EXCLUSIVE = 0;
+ public static final int MAX_PORT_EXCLUSIVE = 65535;
+ private List domainDsn = new LinkedList<>();
+
+ protected String bindDSN = DEFAULT_BIND_DSN;
+
+ private String bindCredentials = DEFAULT_BIND_CREDENTIALS;
+
+ protected List ldifsToImport = new LinkedList<>();
+
+ private List schemaLdifs = new LinkedList<>();
+
+ private boolean addDefaultSchema = true;
+
+ private Integer bindPort = 0;
+
+ private InetAddress bindAddress = InetAddress.getLoopbackAddress();
+
+ protected AuthenticationConfiguration authenticationConfiguration;
+
+ private InMemoryListenerConfig listenerConfig = null;
+
+ /**
+ * 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 builder instance with the domainDsn field set
+ */
+ public Self usingDomainDsn(final String domainDsn) {
+ this.domainDsn.add(domainDsn);
+ 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 builder instance with the bindDSN field set
+ */
+ public Self usingBindDSN(final String bindDSN) {
+ this.bindDSN = bindDSN;
+ 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 builder instance with the bindCredentials field set
+ */
+ public Self usingBindCredentials(final String bindCredentials) {
+ this.bindCredentials = bindCredentials;
+ 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 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 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 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 builder instance with the bindAddress field set
+ * @throws IllegalArgumentException if the value provided for \"address\" is invalid
+ */
+ public Self bindingToAddress(final String address) {
+ Objects.requireNonNull(address);
+ try {
+ final InetAddress addressByName = InetAddress.getByName(address);
+ this.bindAddress = addressByName;
+ } catch (UnknownHostException e) {
+ throw new IllegalArgumentException(String.format("Unknown host address \"%s\"", address), e);
+ }
+ return getThis();
+ }
+
+ /**
+ * Avoid adding UnboundID's default schema that contains the most common LDAP elements defined through various RFC's.
+ *
+ * @return same builder instance with the withoutDefaultSchema field set to FALSE
+ */
+ public Self withoutDefaultSchema() {
+ this.addDefaultSchema = false;
+ 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 builder with the given LDIF-files added to the internal schema file collection.
+ */
+ public Self withSchema(final String... ldifSchemaFiles) {
+ this.schemaLdifs.addAll(Arrays.asList(ldifSchemaFiles));
+ return getThis();
+ }
+
+ /**
+ * Specify one or more LDIF resources to be imported on startup.
+ *
+ * @param ldifFiles LDIF-files to import
+ * @return same builder instance with the provided ldifFiles added to the list of LDIF files to import
+ */
+ public Self importingLdifs(final String... ldifFiles) {
+ if (ldifFiles != null) {
+ ldifsToImport.addAll(Arrays.asList(ldifFiles));
+ }
+ return getThis();
+ }
+
+ public Self withListener(InMemoryListenerConfig listenerConfig) {
+ this.listenerConfig = listenerConfig;
+ return getThis();
+ }
+
+ protected abstract Self getThis();
+
+ protected InMemoryDirectoryServerConfig createInMemoryServerConfiguration() {
+ try {
+ final InMemoryDirectoryServerConfig inMemoryDirectoryServerConfig =
+ new InMemoryDirectoryServerConfig(domainDsnArray());
+
+ if (bindCredentials != null) {
+ this.authenticationConfiguration = new AuthenticationConfiguration(bindDSN, bindCredentials);
+ inMemoryDirectoryServerConfig.addAdditionalBindCredentials(bindDSN, bindCredentials);
+ }
+
+ if (listenerConfig == null) {
+ listenerConfig = InMemoryListenerConfig.createLDAPConfig(
+ LDAP_SERVER_LISTENER_NAME,
+ bindAddress,
+ bindPort,
+ null);
+ }
+ inMemoryDirectoryServerConfig.setListenerConfigs(listenerConfig);
+ inMemoryDirectoryServerConfig.setSchema(customSchema());
+ return inMemoryDirectoryServerConfig;
+ } catch (LDAPException e) {
+ throw new IllegalStateException(
+ "Could not create configuration for the in-memory LDAP instance due to an exception",
+ e);
+ }
+ }
+
+ private String[] domainDsnArray() {
+ if (domainDsn.size() == 0) {
+ return new String[]{DEFAULT_DOMAIN};
+ } else {
+ return domainDsn.toArray(new String[]{});
+ }
+ }
+
+ private Schema customSchema() {
+ final List schemaFiles = schemaFiles();
+
+ try {
+ final Schema initialSchema = (addDefaultSchema ? Schema.getDefaultStandardSchema() : null);
+ if (!schemaFiles.isEmpty()) {
+ final Schema customSchema = initialSchema == null
+ ? Schema.getSchema(schemaFiles)
+ : Schema.mergeSchemas(initialSchema, Schema.getSchema(schemaFiles));
+ return customSchema;
+ } else {
+ return null;
+ }
+
+ } catch (IOException | LDIFException | LDAPException e) {
+ throw new IllegalArgumentException(
+ "Could not create custom LDAP schema due, probably caused by an incorrectly formatted schema",
+ e);
+ }
+ }
+
+ private List schemaFiles() {
+ return Lists.newArrayList(Lists.transform(this.schemaLdifs, new Function() {
+ @Override
+ public File apply(final String input) {
+ try {
+ final File file = new File(Resources.getResource(input).toURI());
+ if (!file.isFile()) {
+ throw new IllegalArgumentException(String.format(
+ "The resource named \"%s\" can not be found or is not a file",
+ input));
+ }
+ return file;
+ } catch (URISyntaxException e) {
+ throw new IllegalArgumentException(String.format(
+ "The resource named \"%s\" is not a valid file reference",
+ input), e);
+ }
+ }
+ }));
+ }
+
+
+}
diff --git a/src/main/java/org/zapodot/junit/ldap/internal/EmbeddedLdapExtensionImpl.java b/src/main/java/org/zapodot/junit/ldap/internal/EmbeddedLdapExtensionImpl.java
new file mode 100644
index 0000000..1daf1ab
--- /dev/null
+++ b/src/main/java/org/zapodot/junit/ldap/internal/EmbeddedLdapExtensionImpl.java
@@ -0,0 +1,54 @@
+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 java.util.List;
+
+public class EmbeddedLdapExtensionImpl extends EmbeddedLdapServerImpl implements EmbeddedLdapExtension {
+
+ public static EmbeddedLdapExtension createForConfiguration(final InMemoryDirectoryServerConfig inMemoryDirectoryServerConfig,
+ final AuthenticationConfiguration authenticationConfiguration,
+ final List ldifs) {
+ try {
+ return new EmbeddedLdapExtensionImpl(createServer(inMemoryDirectoryServerConfig, ldifs),
+ authenticationConfiguration);
+ } 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) {
+ super(inMemoryDirectoryServer, authenticationConfiguration1);
+ }
+
+ @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/src/main/java/org/zapodot/junit/ldap/internal/EmbeddedLdapRuleImpl.java b/src/main/java/org/zapodot/junit/ldap/internal/EmbeddedLdapRuleImpl.java
index baaca0c..9f33d28 100755
--- a/src/main/java/org/zapodot/junit/ldap/internal/EmbeddedLdapRuleImpl.java
+++ b/src/main/java/org/zapodot/junit/ldap/internal/EmbeddedLdapRuleImpl.java
@@ -1,49 +1,15 @@
package org.zapodot.junit.ldap.internal;
-import com.google.common.base.Charsets;
-import com.google.common.io.Resources;
import com.unboundid.ldap.listener.InMemoryDirectoryServer;
import com.unboundid.ldap.listener.InMemoryDirectoryServerConfig;
-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 org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
import org.zapodot.junit.ldap.EmbeddedLdapRule;
-import org.zapodot.junit.ldap.internal.jndi.ContextProxyFactory;
-import org.zapodot.junit.ldap.internal.unboundid.LDAPInterfaceProxyFactory;
-import javax.naming.Context;
-import javax.naming.NamingException;
-import javax.naming.directory.DirContext;
-import javax.naming.directory.InitialDirContext;
-import javax.naming.ldap.LdapContext;
-import java.io.UnsupportedEncodingException;
-import java.net.URLDecoder;
-import java.util.Hashtable;
import java.util.List;
-public class EmbeddedLdapRuleImpl implements EmbeddedLdapRule {
-
- 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 final InMemoryDirectoryServer inMemoryDirectoryServer;
- private final AuthenticationConfiguration authenticationConfiguration;
- private LDAPConnection ldapConnection;
- private InitialDirContext initialDirContext;
- private boolean isStarted = false;
-
-
- private EmbeddedLdapRuleImpl(final InMemoryDirectoryServer inMemoryDirectoryServer,
- final AuthenticationConfiguration authenticationConfiguration1) {
- this.inMemoryDirectoryServer = inMemoryDirectoryServer;
- this.authenticationConfiguration = authenticationConfiguration1;
- }
+public class EmbeddedLdapRuleImpl extends EmbeddedLdapServerImpl implements EmbeddedLdapRule {
public static EmbeddedLdapRule createForConfiguration(final InMemoryDirectoryServerConfig inMemoryDirectoryServerConfig,
final AuthenticationConfiguration authenticationConfiguration,
@@ -56,89 +22,10 @@ public static EmbeddedLdapRule createForConfiguration(final InMemoryDirectorySer
}
}
- private static InMemoryDirectoryServer createServer(final InMemoryDirectoryServerConfig inMemoryDirectoryServerConfig,
- final List ldifs) throws LDAPException {
- final InMemoryDirectoryServer ldapServer =
- new InMemoryDirectoryServer(inMemoryDirectoryServerConfig);
- if (ldifs != null && !ldifs.isEmpty()) {
- for (final String ldif : ldifs) {
- try {
- ldapServer.importFromLDIF(false, URLDecoder.decode(Resources.getResource(ldif).getPath(),
- Charsets.UTF_8.name()));
- } catch (UnsupportedEncodingException e) {
- throw new IllegalStateException("Can not URL decode path:" + Resources.getResource(ldif).getPath(),
- e);
- }
- }
- }
- return ldapServer;
- }
-
- @Override
- public LDAPInterface ldapConnection() throws LDAPException {
- return LDAPInterfaceProxyFactory.createProxy(createOrGetLdapConnection());
- }
-
- @Override
- public LDAPConnection unsharedLdapConnection() throws LDAPException {
- return createOrGetLdapConnection();
- }
-
- private LDAPConnection createOrGetLdapConnection() throws LDAPException {
- if (isStarted) {
- if (ldapConnection == null || ! ldapConnection.isConnected()) {
- ldapConnection = inMemoryDirectoryServer.getConnection();
- }
- return ldapConnection;
- } else {
- throw new IllegalStateException(
- "Can not get a LdapConnection before the embedded LDAP server has been started");
- }
- }
-
- @Override
- public Context context() throws NamingException {
- return ContextProxyFactory.asDelegatingContext(createOrGetInitialDirContext());
- }
-
- @Override
- public DirContext dirContext() throws NamingException {
- return ContextProxyFactory.asDelegatingDirContext(createOrGetInitialDirContext());
- }
-
- @Override
- public int embeddedServerPort() {
- if(isStarted) {
- return inMemoryDirectoryServer.getListenPort();
- } else {
- throw new IllegalStateException("The embedded server must be started prior to accessing the listening port");
- }
- }
-
- private InitialDirContext createOrGetInitialDirContext() throws NamingException {
- if (isStarted) {
- if (initialDirContext == null) {
- initialDirContext = new InitialDirContext(createLdapEnvironment());
- }
- return initialDirContext;
- } else {
- throw new IllegalStateException(
- "Can not get an InitialDirContext before the embedded LDAP server has been started");
- }
+ public EmbeddedLdapRuleImpl(InMemoryDirectoryServer inMemoryDirectoryServer, AuthenticationConfiguration authenticationConfiguration1) {
+ super(inMemoryDirectoryServer, authenticationConfiguration1);
}
- private Hashtable createLdapEnvironment() {
- final Hashtable environment = new Hashtable<>();
- environment.put(LdapContext.CONTROL_FACTORIES, JAVA_RT_CONTROL_FACTORY);
- environment.put(Context.PROVIDER_URL, String.format("ldap://%s:%s",
- inMemoryDirectoryServer.getListenAddress().getHostName(),
- embeddedServerPort()));
- environment.put(Context.INITIAL_CONTEXT_FACTORY, JAVA_RT_CONTEXT_FACTORY);
- if (authenticationConfiguration != null) {
- environment.putAll(authenticationConfiguration.toAuthenticationEnvironment());
- }
- return environment;
- }
@Override
public Statement apply(final Statement base, final Description description) {
@@ -159,26 +46,4 @@ public void evaluate() throws Throwable {
};
}
- private void startEmbeddedLdapServer() throws LDAPException {
- inMemoryDirectoryServer.startListening();
- isStarted = true;
- }
-
- private void takeDownEmbeddedLdapServer() {
- try {
- if (ldapConnection != null && ldapConnection.isConnected()) {
- ldapConnection.close();
- }
- if (initialDirContext != null) {
- initialDirContext.close();
- }
- } catch (NamingException e) {
- logger.info("Could not close initial context, forcing server shutdown anyway", e);
- } finally {
- inMemoryDirectoryServer.shutDown(true);
- }
-
- }
-
-
}
diff --git a/src/main/java/org/zapodot/junit/ldap/internal/EmbeddedLdapServerImpl.java b/src/main/java/org/zapodot/junit/ldap/internal/EmbeddedLdapServerImpl.java
new file mode 100644
index 0000000..161ee12
--- /dev/null
+++ b/src/main/java/org/zapodot/junit/ldap/internal/EmbeddedLdapServerImpl.java
@@ -0,0 +1,148 @@
+package org.zapodot.junit.ldap.internal;
+
+import com.google.common.base.Charsets;
+import com.google.common.io.Resources;
+import com.unboundid.ldap.listener.InMemoryDirectoryServer;
+import com.unboundid.ldap.listener.InMemoryDirectoryServerConfig;
+import com.unboundid.ldap.sdk.LDAPConnection;
+import com.unboundid.ldap.sdk.LDAPException;
+import com.unboundid.ldap.sdk.LDAPInterface;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.zapodot.junit.ldap.EmbeddedLdapServer;
+import org.zapodot.junit.ldap.internal.jndi.ContextProxyFactory;
+import org.zapodot.junit.ldap.internal.unboundid.LDAPInterfaceProxyFactory;
+
+import javax.naming.Context;
+import javax.naming.NamingException;
+import javax.naming.directory.DirContext;
+import javax.naming.directory.InitialDirContext;
+import javax.naming.ldap.LdapContext;
+import java.io.UnsupportedEncodingException;
+import java.net.URLDecoder;
+import java.util.Hashtable;
+import java.util.List;
+
+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(EmbeddedLdapExtensionImpl.class);
+ private final InMemoryDirectoryServer inMemoryDirectoryServer;
+ private final AuthenticationConfiguration authenticationConfiguration;
+ private LDAPConnection ldapConnection;
+ private InitialDirContext initialDirContext;
+ private boolean isStarted = false;
+
+ public EmbeddedLdapServerImpl(final InMemoryDirectoryServer inMemoryDirectoryServer,
+ final AuthenticationConfiguration authenticationConfiguration1) {
+ this.inMemoryDirectoryServer = inMemoryDirectoryServer;
+ this.authenticationConfiguration = authenticationConfiguration1;
+ }
+
+ protected static InMemoryDirectoryServer createServer(final InMemoryDirectoryServerConfig inMemoryDirectoryServerConfig,
+ final List ldifs) throws LDAPException {
+ final InMemoryDirectoryServer ldapServer =
+ new InMemoryDirectoryServer(inMemoryDirectoryServerConfig);
+ if (ldifs != null && !ldifs.isEmpty()) {
+ for (final String ldif : ldifs) {
+ try {
+ ldapServer.importFromLDIF(false, URLDecoder.decode(Resources.getResource(ldif).getPath(),
+ Charsets.UTF_8.name()));
+ } catch (UnsupportedEncodingException e) {
+ throw new IllegalStateException("Can not URL decode path:" + Resources.getResource(ldif).getPath(),
+ e);
+ }
+ }
+ }
+ return ldapServer;
+ }
+
+ @Override
+ public LDAPInterface ldapConnection() throws LDAPException {
+ return LDAPInterfaceProxyFactory.createProxy(createOrGetLdapConnection());
+ }
+
+ @Override
+ public LDAPConnection unsharedLdapConnection() throws LDAPException {
+ return createOrGetLdapConnection();
+ }
+
+ private LDAPConnection createOrGetLdapConnection() throws LDAPException {
+ if (isStarted) {
+ if (ldapConnection == null || ! ldapConnection.isConnected()) {
+ ldapConnection = inMemoryDirectoryServer.getConnection();
+ }
+ return ldapConnection;
+ } else {
+ throw new IllegalStateException(
+ "Can not get a LdapConnection before the embedded LDAP server has been started");
+ }
+ }
+
+ @Override
+ public Context context() throws NamingException {
+ return ContextProxyFactory.asDelegatingContext(createOrGetInitialDirContext());
+ }
+
+ @Override
+ public DirContext dirContext() throws NamingException {
+ return ContextProxyFactory.asDelegatingDirContext(createOrGetInitialDirContext());
+ }
+
+ @Override
+ public int embeddedServerPort() {
+ if(isStarted) {
+ return inMemoryDirectoryServer.getListenPort();
+ } else {
+ throw new IllegalStateException("The embedded server must be started prior to accessing the listening port");
+ }
+ }
+
+ private InitialDirContext createOrGetInitialDirContext() throws NamingException {
+ if (isStarted) {
+ if (initialDirContext == null) {
+ initialDirContext = new InitialDirContext(createLdapEnvironment());
+ }
+ return initialDirContext;
+ } else {
+ throw new IllegalStateException(
+ "Can not get an InitialDirContext before the embedded LDAP server has been started");
+ }
+ }
+
+ private Hashtable createLdapEnvironment() {
+ final Hashtable environment = new Hashtable<>();
+ environment.put(LdapContext.CONTROL_FACTORIES, JAVA_RT_CONTROL_FACTORY);
+ environment.put(Context.PROVIDER_URL, String.format("ldap://%s:%s",
+ inMemoryDirectoryServer.getListenAddress().getHostName(),
+ embeddedServerPort()));
+ environment.put(Context.INITIAL_CONTEXT_FACTORY, JAVA_RT_CONTEXT_FACTORY);
+ if (authenticationConfiguration != null) {
+ environment.putAll(authenticationConfiguration.toAuthenticationEnvironment());
+ }
+ return environment;
+ }
+
+ protected void startEmbeddedLdapServer() throws LDAPException {
+ inMemoryDirectoryServer.startListening();
+ isStarted = true;
+ }
+
+ protected void takeDownEmbeddedLdapServer() {
+ try {
+ if (ldapConnection != null && ldapConnection.isConnected()) {
+ ldapConnection.close();
+ }
+ if (initialDirContext != null) {
+ initialDirContext.close();
+ }
+ } catch (NamingException e) {
+ logger.info("Could not close initial context, forcing server shutdown anyway", e);
+ } finally {
+ inMemoryDirectoryServer.shutDown(true);
+ }
+
+ }
+}
diff --git a/src/main/java/org/zapodot/junit/ldap/junit5/EmbeddedLdapExtension.java b/src/main/java/org/zapodot/junit/ldap/junit5/EmbeddedLdapExtension.java
new file mode 100644
index 0000000..10ccbf3
--- /dev/null
+++ b/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/src/main/java/org/zapodot/junit/ldap/junit5/EmbeddedLdapExtensionBuilder.java b/src/main/java/org/zapodot/junit/ldap/junit5/EmbeddedLdapExtensionBuilder.java
new file mode 100644
index 0000000..3bee8b7
--- /dev/null
+++ b/src/main/java/org/zapodot/junit/ldap/junit5/EmbeddedLdapExtensionBuilder.java
@@ -0,0 +1,38 @@
+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);
+ }
+
+ @Override
+ protected EmbeddedLdapExtensionBuilder getThis() {
+ return this;
+ }
+}
diff --git a/src/test/java/org/zapodot/junit/ldap/junit5/EmbeddedLdapExtensionBuilderTest.java b/src/test/java/org/zapodot/junit/ldap/junit5/EmbeddedLdapExtensionBuilderTest.java
new file mode 100644
index 0000000..77d0d1e
--- /dev/null
+++ b/src/test/java/org/zapodot/junit/ldap/junit5/EmbeddedLdapExtensionBuilderTest.java
@@ -0,0 +1,87 @@
+package org.zapodot.junit.ldap.junit5;
+
+import org.junit.Test;
+
+import static org.junit.Assert.assertNotNull;
+
+public class EmbeddedLdapExtensionBuilderTest {
+
+ @Test
+ public void bindingToLegalPort() {
+ assertNotNull(EmbeddedLdapExtensionBuilder.newInstance().bindingToPort(9999));
+ }
+
+ @Test(expected = IllegalStateException.class)
+ public void testPrematureLdapConnection() throws Exception {
+ EmbeddedLdapExtensionBuilder.newInstance().build().ldapConnection();
+
+ }
+
+ @Test(expected = IllegalStateException.class)
+ public void testPrematureContext() throws Exception {
+ EmbeddedLdapExtensionBuilder.newInstance().build().context();
+
+ }
+
+ @Test(expected = IllegalArgumentException.class)
+ public void testUnknownLDIF() {
+ EmbeddedLdapExtensionBuilder.newInstance().importingLdifs("nonExisting.ldif").build();
+
+ }
+
+ @Test
+ public void testNullLDIF() {
+ assertNotNull(EmbeddedLdapExtensionBuilder.newInstance().importingLdifs(null).build());
+
+ }
+
+ @Test(expected = IllegalStateException.class)
+ public void testIllegalDSN() {
+ EmbeddedLdapExtensionBuilder.newInstance().usingBindDSN("bindDsn").build();
+
+ }
+
+ @Test(expected = IllegalArgumentException.class)
+ public void testIllegalPort() {
+ EmbeddedLdapExtensionBuilder.newInstance().bindingToPort(Integer.MIN_VALUE).build();
+
+ }
+
+ @Test(expected = IllegalArgumentException.class)
+ public void testSchemaNotFound() {
+ EmbeddedLdapExtensionBuilder.newInstance().withSchema("non-existing-schema.ldif").build();
+
+ }
+
+ @Test(expected = IllegalArgumentException.class)
+ public void testSchemaIsNotAFile() {
+ EmbeddedLdapExtensionBuilder.newInstance().withSchema("folder").build();
+
+ }
+
+ @Test(expected = IllegalArgumentException.class)
+ public void testSchemaIsInvalid() {
+ EmbeddedLdapExtensionBuilder.newInstance().withSchema("invalid.ldif").build();
+
+ }
+
+ @Test(expected = IllegalArgumentException.class)
+ public void testSchemaFileUnsupportedIsInvalid() {
+ EmbeddedLdapExtensionBuilder.newInstance().withSchema("\"#%¤&&%/¤##¤¤").build();
+
+ }
+
+ @Test(expected = IllegalArgumentException.class)
+ public void testInvalidPort() {
+ EmbeddedLdapExtensionBuilder.newInstance().bindingToPort(Integer.MAX_VALUE);
+
+ }
+
+ @Test(expected = IllegalArgumentException.class)
+ public void testInvalidBindAddress() {
+ EmbeddedLdapExtensionBuilder.newInstance().bindingToAddress("åpsldfåpl");
+
+ }
+
+
+}
diff --git a/src/test/java/org/zapodot/junit/ldap/junit5/EmbeddedLdapExtensionStaticTest.java b/src/test/java/org/zapodot/junit/ldap/junit5/EmbeddedLdapExtensionStaticTest.java
new file mode 100644
index 0000000..5fa054f
--- /dev/null
+++ b/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/src/test/java/org/zapodot/junit/ldap/junit5/EmbeddedLdapExtensionTest.java b/src/test/java/org/zapodot/junit/ldap/junit5/EmbeddedLdapExtensionTest.java
new file mode 100644
index 0000000..d2e40f7
--- /dev/null
+++ b/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);
+
+ }
+}