diff --git a/CHANGELOG.md b/CHANGELOG.md
index 984fad2..79ac9d6 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -6,6 +6,10 @@ All notable changes to this project will be documented in this file.
Nothing unreleased.
+## [5.0.0] - 2022-07-09
+
+Add support for RandomGenerator in Java 17. #19
+
## [4.2.1] - 2022-04-21
Handle clock drift. #18
@@ -286,7 +290,8 @@ Project created as an alternative Java implementation of [ULID spec](https://git
- Added `LICENSE`
- Added test cases
-[unreleased]: https://github.com/f4b6a3/ulid-creator/compare/ulid-creator-4.2.1...HEAD
+[unreleased]: https://github.com/f4b6a3/ulid-creator/compare/ulid-creator-5.0.0...HEAD
+[5.0.0]: https://github.com/f4b6a3/ulid-creator/compare/ulid-creator-4.2.1...ulid-creator-5.0.0
[4.2.1]: https://github.com/f4b6a3/ulid-creator/compare/ulid-creator-4.2.0...ulid-creator-4.2.1
[4.2.0]: https://github.com/f4b6a3/ulid-creator/compare/ulid-creator-4.1.2...ulid-creator-4.2.0
[4.1.2]: https://github.com/f4b6a3/ulid-creator/compare/ulid-creator-4.1.1...ulid-creator-4.1.2
diff --git a/README.md b/README.md
index 9a3e647..512903f 100644
--- a/README.md
+++ b/README.md
@@ -39,7 +39,7 @@ Add these lines to your `pom.xml`.
com.github.f4b6a3
ulid-creator
- 4.2.1
+ 5.0.0
```
See more options in [maven.org](https://search.maven.org/artifact/com.github.f4b6a3/ulid-creator).
@@ -198,12 +198,38 @@ Ulid ulid = factory.create();
---
-A `UlidFactory` with `ThreadLocalRandom` inside of a `Supplier`:
+A `UlidFactory` with `SplittableRandom`:
+
+```java
+// use a random function that returns a long value
+SplittableRandom random = new SplittableRandom();
+UlidFactory factory = UlidFactory.newInstance(() -> random.nextLong());
+
+// use the factory
+Ulid ulid = factory.create();
+```
+
+---
+
+A `UlidFactory` with `RandomGenerator` (JDK 17+):
+
+```java
+// use a random function that returns a long value
+RandomGenerator random = RandomGenerator.getDefault();
+UlidFactory factory = UlidFactory.newInstance(() -> random.nextLong());
+
+// use the factory
+Ulid ulid = factory.create();
+```
+
+---
+
+A `UlidFactory` with `ThreadLocalRandom`:
```java
// use a random supplier that returns an array of 10 bytes
-UlidFactory factory = UlidFactory.newInstance(() -> {
- final byte[] bytes = new byte[Ulid.RANDOM_BYTES];
+UlidFactory factory = UlidFactory.newInstance((length) -> {
+ final byte[] bytes = new byte[length];
ThreadLocalRandom.current().nextBytes(bytes);
return bytes;
});
diff --git a/src/main/java/com/github/f4b6a3/ulid/UlidFactory.java b/src/main/java/com/github/f4b6a3/ulid/UlidFactory.java
index 4aaef93..8aa53f6 100644
--- a/src/main/java/com/github/f4b6a3/ulid/UlidFactory.java
+++ b/src/main/java/com/github/f4b6a3/ulid/UlidFactory.java
@@ -27,8 +27,9 @@ package com.github.f4b6a3.ulid;
import java.security.SecureRandom;
import java.time.Clock;
import java.util.Random;
+import java.util.function.IntFunction;
import java.util.function.LongFunction;
-import java.util.function.Supplier;
+import java.util.function.LongSupplier;
/**
* Factory that generates ULIDs.
@@ -47,7 +48,7 @@ public final class UlidFactory {
private final LongFunction ulidFunction;
public UlidFactory() {
- this(new UlidFunction(getRandomSupplier(null)));
+ this(new UlidFunction());
}
private UlidFactory(LongFunction ulidFunction) {
@@ -67,7 +68,7 @@ public final class UlidFactory {
* @return {@link UlidFactory}
*/
public static UlidFactory newInstance() {
- return newInstance(getRandomSupplier(null));
+ return new UlidFactory(new UlidFunction());
}
/**
@@ -77,19 +78,31 @@ public final class UlidFactory {
* @return {@link UlidFactory}
*/
public static UlidFactory newInstance(Random random) {
- return newInstance(getRandomSupplier(random));
+ return new UlidFactory(new UlidFunction(random));
}
/**
* Returns a new factory.
*
- * The given random supplier must return an array of 10 bytes.
+ * The given random function must return a long value.
*
- * @param randomSupplier a random supplier that returns 10 bytes
+ * @param randomFunction a random function that returns a long value
* @return {@link UlidFactory}
*/
- public static UlidFactory newInstance(Supplier randomSupplier) {
- return new UlidFactory(new UlidFunction(randomSupplier));
+ public static UlidFactory newInstance(LongSupplier randomFunction) {
+ return new UlidFactory(new UlidFunction(randomFunction));
+ }
+
+ /**
+ * Returns a new factory.
+ *
+ * The given random function must return a byte array.
+ *
+ * @param randomFunction a random function that returns a byte array
+ * @return {@link UlidFactory}
+ */
+ public static UlidFactory newInstance(IntFunction randomFunction) {
+ return new UlidFactory(new UlidFunction(randomFunction));
}
/**
@@ -98,7 +111,7 @@ public final class UlidFactory {
* @return {@link UlidFactory}
*/
public static UlidFactory newMonotonicInstance() {
- return newMonotonicInstance(getRandomSupplier(null));
+ return new UlidFactory(new MonotonicFunction());
}
/**
@@ -108,32 +121,57 @@ public final class UlidFactory {
* @return {@link UlidFactory}
*/
public static UlidFactory newMonotonicInstance(Random random) {
- return newMonotonicInstance(getRandomSupplier(random));
+ return new UlidFactory(new MonotonicFunction(random));
}
/**
* Returns a new monotonic factory.
*
- * The given random supplier must return an array of 10 bytes.
+ * The given random function must return a long value.
*
- * @param randomSupplier a random supplier that returns 10 bytes
+ * @param randomFunction a random function that returns a long value
* @return {@link UlidFactory}
*/
- public static UlidFactory newMonotonicInstance(Supplier randomSupplier) {
- return new UlidFactory(new MonotonicFunction(randomSupplier));
+ public static UlidFactory newMonotonicInstance(LongSupplier randomFunction) {
+ return new UlidFactory(new MonotonicFunction(randomFunction));
}
/**
* Returns a new monotonic factory.
*
- * The given random supplier must return an array of 10 bytes.
+ * The given random function must return a byte array.
*
- * @param randomSupplier a random supplier that returns 10 bytes
+ * @param randomFunction a random function that returns a byte array
+ * @return {@link UlidFactory}
+ */
+ public static UlidFactory newMonotonicInstance(IntFunction randomFunction) {
+ return new UlidFactory(new MonotonicFunction(randomFunction));
+ }
+
+ /**
+ * Returns a new monotonic factory.
+ *
+ * The given random function must return a long value.
+ *
+ * @param randomFunction a random function that returns a long value
* @param clock a custom clock instance for tests
* @return {@link UlidFactory}
*/
- protected static UlidFactory newMonotonicInstance(Supplier randomSupplier, Clock clock) {
- return new UlidFactory(new MonotonicFunction(randomSupplier), clock);
+ protected static UlidFactory newMonotonicInstance(LongSupplier randomFunction, Clock clock) {
+ return new UlidFactory(new MonotonicFunction(randomFunction), clock);
+ }
+
+ /**
+ * Returns a new monotonic factory.
+ *
+ * The given random function must return a byte array.
+ *
+ * @param randomFunction a random function that returns a byte array
+ * @param clock a custom clock instance for tests
+ * @return {@link UlidFactory}
+ */
+ protected static UlidFactory newMonotonicInstance(IntFunction randomFunction, Clock clock) {
+ return new UlidFactory(new MonotonicFunction(randomFunction), clock);
}
/**
@@ -141,8 +179,8 @@ public final class UlidFactory {
*
* @return a ULID
*/
- public Ulid create() {
- return create(clock.millis());
+ public synchronized Ulid create() {
+ return this.ulidFunction.apply(clock.millis());
}
/**
@@ -153,7 +191,7 @@ public final class UlidFactory {
* @param time a given time
* @return a ULID
*/
- public Ulid create(final long time) {
+ public synchronized Ulid create(final long time) {
return this.ulidFunction.apply(time);
}
@@ -162,16 +200,33 @@ public final class UlidFactory {
*/
protected static final class UlidFunction implements LongFunction {
- // it must return an array of 10 bytes
- private Supplier randomSupplier;
+ private final IRandom random;
- public UlidFunction(Supplier randomSupplier) {
- this.randomSupplier = randomSupplier;
+ public UlidFunction() {
+ this.random = new ByteRandom();
+ }
+
+ public UlidFunction(Random random) {
+ this.random = IRandom.newInstance(random);
+ }
+
+ public UlidFunction(IntFunction randomFunction) {
+ this.random = new ByteRandom(randomFunction);
+ }
+
+ public UlidFunction(LongSupplier randomFunction) {
+ this.random = new LongRandom(randomFunction);
}
@Override
public Ulid apply(final long time) {
- return new Ulid(time, this.randomSupplier.get());
+ if (this.random instanceof ByteRandom) {
+ return new Ulid(time, this.random.nextBytes(Ulid.RANDOM_BYTES));
+ } else {
+ final long msb = (time << 16) | (this.random.nextLong() & 0xffffL);
+ final long lsb = this.random.nextLong();
+ return new Ulid(msb, lsb);
+ }
}
}
@@ -183,20 +238,35 @@ public final class UlidFactory {
private long lastTime;
private Ulid lastUlid;
+ private final IRandom random;
+
// Used to preserve monotonicity when the system clock is
// adjusted by NTP after a small clock drift or when the
// system clock jumps back by 1 second due to leap second.
protected static final int CLOCK_DRIFT_TOLERANCE = 10_000;
- // it must return an array of 10 bytes
- private Supplier randomSupplier;
+ public MonotonicFunction() {
+ this(new ByteRandom());
+ }
- public MonotonicFunction(Supplier randomSupplier) {
- this.randomSupplier = randomSupplier;
+ public MonotonicFunction(Random random) {
+ this(IRandom.newInstance(random));
+ }
+
+ public MonotonicFunction(IntFunction randomFunction) {
+ this(new ByteRandom(randomFunction));
+ }
+
+ public MonotonicFunction(LongSupplier randomFunction) {
+ this(new LongRandom(randomFunction));
+ }
+
+ private MonotonicFunction(IRandom random) {
+ this.random = random;
// initialize internal state
this.lastTime = Clock.systemUTC().millis();
- this.lastUlid = new Ulid(lastTime, randomSupplier.get());
+ this.lastUlid = new Ulid(lastTime, random.nextBytes(Ulid.RANDOM_BYTES));
}
@Override
@@ -209,26 +279,122 @@ public final class UlidFactory {
this.lastUlid = lastUlid.increment();
} else {
this.lastTime = time;
- this.lastUlid = new Ulid(time, this.randomSupplier.get());
+ if (this.random instanceof ByteRandom) {
+ this.lastUlid = new Ulid(time, this.random.nextBytes(Ulid.RANDOM_BYTES));
+ } else {
+ final long msb = (time << 16) | (this.random.nextLong() & 0xffffL);
+ final long lsb = this.random.nextLong();
+ this.lastUlid = new Ulid(msb, lsb);
+ }
}
return new Ulid(this.lastUlid);
}
}
- /**
- * It instantiates a supplier that returns an array of 10 bytes.
- *
- * @param random a {@link Random} generator
- * @return a random supplier that returns 10 bytes
- */
- protected static Supplier getRandomSupplier(Random random) {
- Random entropy = random != null ? random : new SecureRandom();
- return () -> {
- byte[] payload = new byte[Ulid.RANDOM_BYTES];
- entropy.nextBytes(payload);
- return payload;
- };
+ protected static interface IRandom {
+
+ public long nextLong();
+
+ public byte[] nextBytes(int length);
+
+ static IRandom newInstance(Random random) {
+ if (random == null) {
+ return new ByteRandom();
+ } else {
+ if (random instanceof SecureRandom) {
+ return new ByteRandom(random);
+ } else {
+ return new LongRandom(random);
+ }
+ }
+ }
}
+ protected static class LongRandom implements IRandom {
+
+ private final LongSupplier randomFunction;
+
+ public LongRandom() {
+ this(newRandomFunction(null));
+ }
+
+ public LongRandom(Random random) {
+ this(newRandomFunction(random));
+ }
+
+ public LongRandom(LongSupplier randomFunction) {
+ this.randomFunction = randomFunction != null ? randomFunction : newRandomFunction(null);
+ }
+
+ @Override
+ public long nextLong() {
+ return randomFunction.getAsLong();
+ }
+
+ @Override
+ public byte[] nextBytes(int length) {
+
+ int shift = 0;
+ long random = 0;
+ final byte[] bytes = new byte[length];
+
+ for (int i = 0; i < length; i++) {
+ if (shift < Byte.SIZE) {
+ shift = Long.SIZE;
+ random = randomFunction.getAsLong();
+ }
+ shift -= Byte.SIZE; // 56, 48, 42...
+ bytes[i] = (byte) (random >>> shift);
+ }
+
+ return bytes;
+ }
+
+ protected static LongSupplier newRandomFunction(Random random) {
+ final Random entropy = random != null ? random : new SecureRandom();
+ return entropy::nextLong;
+ }
+ }
+
+ protected static class ByteRandom implements IRandom {
+
+ private final IntFunction randomFunction;
+
+ public ByteRandom() {
+ this(newRandomFunction(null));
+ }
+
+ public ByteRandom(Random random) {
+ this(newRandomFunction(random));
+ }
+
+ public ByteRandom(IntFunction randomFunction) {
+ this.randomFunction = randomFunction != null ? randomFunction : newRandomFunction(null);
+ }
+
+ @Override
+ public long nextLong() {
+ long number = 0;
+ byte[] bytes = this.randomFunction.apply(Long.BYTES);
+ for (int i = 0; i < Long.BYTES; i++) {
+ number = (number << 8) | (bytes[i] & 0xff);
+ }
+ return number;
+ }
+
+ @Override
+ public byte[] nextBytes(int length) {
+ return this.randomFunction.apply(length);
+ }
+
+ protected static IntFunction newRandomFunction(Random random) {
+ final Random entropy = random != null ? random : new SecureRandom();
+ return (final int length) -> {
+ final byte[] bytes = new byte[length];
+ entropy.nextBytes(bytes);
+ return bytes;
+ };
+ }
+ }
}
diff --git a/src/test/java/com/github/f4b6a3/ulid/UlidFactoryDefaultfTest.java b/src/test/java/com/github/f4b6a3/ulid/UlidFactoryDefaultfTest.java
index eca2121..d946d44 100644
--- a/src/test/java/com/github/f4b6a3/ulid/UlidFactoryDefaultfTest.java
+++ b/src/test/java/com/github/f4b6a3/ulid/UlidFactoryDefaultfTest.java
@@ -2,13 +2,16 @@ package com.github.f4b6a3.ulid;
import org.junit.Test;
-import com.github.f4b6a3.ulid.Ulid;
-import com.github.f4b6a3.ulid.UlidCreator;
-import com.github.f4b6a3.ulid.UlidFactory;
-
import static org.junit.Assert.*;
+import java.nio.ByteBuffer;
+import java.security.SecureRandom;
+import java.util.Arrays;
import java.util.Random;
+import java.util.SplittableRandom;
+import java.util.concurrent.ThreadLocalRandom;
+import java.util.function.IntFunction;
+import java.util.function.LongSupplier;
public class UlidFactoryDefaultfTest extends UlidFactoryTest {
@@ -59,4 +62,188 @@ public class UlidFactoryDefaultfTest extends UlidFactoryTest {
assertEquals(time, ulid.getTime());
}
}
+
+ @Test
+ public void testDefault() {
+ UlidFactory factory = new UlidFactory();
+ assertNotNull(factory.create());
+ }
+
+ @Test
+ public void testWithRandom() {
+ {
+ Random random = new Random();
+ UlidFactory factory = UlidFactory.newInstance(random);
+ assertNotNull(factory.create());
+ }
+ {
+ SecureRandom random = new SecureRandom();
+ UlidFactory factory = UlidFactory.newInstance(random);
+ assertNotNull(factory.create());
+ }
+ }
+
+ @Test
+ public void testWithRandomNull() {
+ UlidFactory factory = UlidFactory.newInstance((Random) null);
+ assertNotNull(factory.create());
+ }
+
+ @Test
+ public void testWithRandomFunction() {
+ {
+ SplittableRandom random = new SplittableRandom();
+ LongSupplier function = () -> random.nextLong();
+ UlidFactory factory = UlidFactory.newInstance(function);
+ assertNotNull(factory.create());
+ }
+ {
+ IntFunction function = (length) -> {
+ byte[] bytes = new byte[length];
+ ThreadLocalRandom.current().nextBytes(bytes);
+ return bytes;
+ };
+ UlidFactory factory = UlidFactory.newInstance(function);
+ assertNotNull(factory.create());
+ }
+ }
+
+ @Test
+ public void testWithRandomFunctionNull() {
+ {
+ UlidFactory factory = UlidFactory.newInstance((LongSupplier) null);
+ assertNotNull(factory.create());
+ }
+ {
+ UlidFactory factory = UlidFactory.newInstance((IntFunction) null);
+ assertNotNull(factory.create());
+ }
+ }
+
+ @Test
+ public void testByteRandomNextLong() {
+
+ for (int i = 0; i < 10; i++) {
+ byte[] bytes = new byte[Long.BYTES];
+ (new Random()).nextBytes(bytes);
+ long number = ByteBuffer.wrap(bytes).getLong();
+ UlidFactory.IRandom random = new UlidFactory.ByteRandom((x) -> bytes);
+ assertEquals(number, random.nextLong());
+ }
+
+ for (int i = 0; i < 10; i++) {
+
+ int longs = 10;
+ int size = Long.BYTES * longs;
+
+ byte[] bytes = new byte[size];
+ (new Random()).nextBytes(bytes);
+ ByteBuffer buffer1 = ByteBuffer.wrap(bytes);
+ ByteBuffer buffer2 = ByteBuffer.wrap(bytes);
+
+ UlidFactory.IRandom random = new UlidFactory.ByteRandom((x) -> {
+ byte[] octects = new byte[x];
+ buffer1.get(octects);
+ return octects;
+ });
+
+ for (int j = 0; j < longs; j++) {
+ assertEquals(buffer2.getLong(), random.nextLong());
+ }
+ }
+ }
+
+ @Test
+ public void testByteRandomNextBytes() {
+
+ for (int i = 0; i < 10; i++) {
+ byte[] bytes = new byte[Long.BYTES];
+ (new Random()).nextBytes(bytes);
+ UlidFactory.IRandom random = new UlidFactory.ByteRandom((x) -> bytes);
+ assertEquals(Arrays.toString(bytes), Arrays.toString(random.nextBytes(Long.BYTES)));
+ }
+
+ for (int i = 0; i < 10; i++) {
+
+ int ints = 10;
+ int size = Long.BYTES * ints;
+
+ byte[] bytes = new byte[size];
+ (new Random()).nextBytes(bytes);
+ ByteBuffer buffer1 = ByteBuffer.wrap(bytes);
+ ByteBuffer buffer2 = ByteBuffer.wrap(bytes);
+
+ UlidFactory.IRandom random = new UlidFactory.ByteRandom((x) -> {
+ byte[] octects = new byte[x];
+ buffer1.get(octects);
+ return octects;
+ });
+
+ for (int j = 0; j < ints; j++) {
+ byte[] octects = new byte[Long.BYTES];
+ buffer2.get(octects);
+ assertEquals(Arrays.toString(octects), Arrays.toString(random.nextBytes(Long.BYTES)));
+ }
+ }
+ }
+
+ @Test
+ public void testLogRandomNextLong() {
+
+ for (int i = 0; i < 10; i++) {
+ byte[] bytes = new byte[Long.BYTES];
+ (new Random()).nextBytes(bytes);
+ long number = ByteBuffer.wrap(bytes).getLong();
+ UlidFactory.IRandom random = new UlidFactory.LongRandom(() -> number);
+ assertEquals(number, random.nextLong());
+ }
+
+ for (int i = 0; i < 10; i++) {
+
+ int ints = 10;
+ int size = Long.BYTES * ints;
+
+ byte[] bytes = new byte[size];
+ (new Random()).nextBytes(bytes);
+ ByteBuffer buffer1 = ByteBuffer.wrap(bytes);
+ ByteBuffer buffer2 = ByteBuffer.wrap(bytes);
+
+ UlidFactory.IRandom random = new UlidFactory.LongRandom(() -> buffer1.getLong());
+
+ for (int j = 0; j < ints; j++) {
+ assertEquals(buffer2.getLong(), random.nextLong());
+ }
+ }
+ }
+
+ @Test
+ public void testLogRandomNextBytes() {
+
+ for (int i = 0; i < 10; i++) {
+ byte[] bytes = new byte[Long.BYTES];
+ (new Random()).nextBytes(bytes);
+ long number = ByteBuffer.wrap(bytes).getLong();
+ UlidFactory.IRandom random = new UlidFactory.LongRandom(() -> number);
+ assertEquals(Arrays.toString(bytes), Arrays.toString(random.nextBytes(Long.BYTES)));
+ }
+
+ for (int i = 0; i < 10; i++) {
+
+ int ints = 10;
+ int size = Long.BYTES * ints;
+
+ byte[] bytes = new byte[size];
+ (new Random()).nextBytes(bytes);
+ ByteBuffer buffer1 = ByteBuffer.wrap(bytes);
+ ByteBuffer buffer2 = ByteBuffer.wrap(bytes);
+
+ UlidFactory.IRandom random = new UlidFactory.LongRandom(() -> buffer1.getLong());
+
+ for (int j = 0; j < ints; j++) {
+ byte[] octects = new byte[Long.BYTES];
+ buffer2.get(octects);
+ assertEquals(Arrays.toString(octects), Arrays.toString(random.nextBytes(Long.BYTES)));
+ }
+ }
+ }
}
diff --git a/src/test/java/com/github/f4b6a3/ulid/UlidFactoryMonotonicTest.java b/src/test/java/com/github/f4b6a3/ulid/UlidFactoryMonotonicTest.java
index 1f6f06c..495621f 100644
--- a/src/test/java/com/github/f4b6a3/ulid/UlidFactoryMonotonicTest.java
+++ b/src/test/java/com/github/f4b6a3/ulid/UlidFactoryMonotonicTest.java
@@ -2,10 +2,6 @@ package com.github.f4b6a3.ulid;
import org.junit.Test;
-import com.github.f4b6a3.ulid.Ulid;
-import com.github.f4b6a3.ulid.UlidCreator;
-import com.github.f4b6a3.ulid.UlidFactory;
-
import static org.junit.Assert.*;
import java.time.Clock;
@@ -13,7 +9,10 @@ import java.time.Instant;
import java.time.ZoneId;
import java.util.Arrays;
import java.util.Random;
-import java.util.function.Supplier;
+import java.util.SplittableRandom;
+import java.util.concurrent.ThreadLocalRandom;
+import java.util.function.IntFunction;
+import java.util.function.LongSupplier;
public class UlidFactoryMonotonicTest extends UlidFactoryTest {
@@ -66,7 +65,7 @@ public class UlidFactoryMonotonicTest extends UlidFactoryTest {
}
};
- Supplier randomSupplier = UlidFactory.getRandomSupplier(new Random());
+ IntFunction randomSupplier = UlidFactory.ByteRandom.newRandomFunction(new Random());
UlidFactory factory = UlidFactory.newMonotonicInstance(randomSupplier, clock);
long ms1 = factory.create().getTime(); // time
@@ -115,7 +114,7 @@ public class UlidFactoryMonotonicTest extends UlidFactoryTest {
}
};
- Supplier randomSupplier = UlidFactory.getRandomSupplier(new Random());
+ IntFunction randomSupplier = UlidFactory.ByteRandom.newRandomFunction(new Random());
UlidFactory factory = UlidFactory.newMonotonicInstance(randomSupplier, clock);
long ms1 = factory.create().getTime(); // second
@@ -163,4 +162,63 @@ public class UlidFactoryMonotonicTest extends UlidFactoryTest {
assertEquals(time, ulid.getTime());
}
}
+
+ @Test
+ public void testWithRandom() {
+ Random random = new Random();
+ UlidFactory factory = UlidFactory.newMonotonicInstance(random);
+ assertNotNull(factory.create());
+ }
+
+ @Test
+ public void testWithRandomNull() {
+ UlidFactory factory = UlidFactory.newMonotonicInstance((Random) null);
+ assertNotNull(factory.create());
+ }
+
+ @Test
+ public void testWithRandomFunction() {
+ {
+ SplittableRandom random = new SplittableRandom();
+ LongSupplier function = () -> random.nextLong();
+ UlidFactory factory = UlidFactory.newMonotonicInstance(function);
+ assertNotNull(factory.create());
+ }
+ {
+ SplittableRandom random = new SplittableRandom();
+ LongSupplier function = () -> random.nextLong();
+ UlidFactory factory = UlidFactory.newMonotonicInstance(function, Clock.systemDefaultZone());
+ assertNotNull(factory.create());
+ }
+ {
+ IntFunction function = (length) -> {
+ byte[] bytes = new byte[length];
+ ThreadLocalRandom.current().nextBytes(bytes);
+ return bytes;
+ };
+ UlidFactory factory = UlidFactory.newMonotonicInstance(function);
+ assertNotNull(factory.create());
+ }
+ {
+ IntFunction function = (length) -> {
+ byte[] bytes = new byte[length];
+ ThreadLocalRandom.current().nextBytes(bytes);
+ return bytes;
+ };
+ UlidFactory factory = UlidFactory.newMonotonicInstance(function, Clock.systemDefaultZone());
+ assertNotNull(factory.create());
+ }
+ }
+
+ @Test
+ public void testWithRandomFunctionNull() {
+ {
+ UlidFactory factory = UlidFactory.newMonotonicInstance((LongSupplier) null);
+ assertNotNull(factory.create());
+ }
+ {
+ UlidFactory factory = UlidFactory.newMonotonicInstance((IntFunction) null);
+ assertNotNull(factory.create());
+ }
+ }
}
diff --git a/src/test/java/com/github/f4b6a3/ulid/UlidFactoryTest.java b/src/test/java/com/github/f4b6a3/ulid/UlidFactoryTest.java
index e36863b..bf2296b 100644
--- a/src/test/java/com/github/f4b6a3/ulid/UlidFactoryTest.java
+++ b/src/test/java/com/github/f4b6a3/ulid/UlidFactoryTest.java
@@ -9,8 +9,6 @@ import java.util.Random;
import java.util.Set;
import java.util.UUID;
-import com.github.f4b6a3.ulid.UlidFactory;
-
public abstract class UlidFactoryTest {
protected static final int DEFAULT_LOOP_MAX = 10_000;
diff --git a/src/test/java/com/github/f4b6a3/ulid/UlidTest.java b/src/test/java/com/github/f4b6a3/ulid/UlidTest.java
index a45c784..97a3afa 100644
--- a/src/test/java/com/github/f4b6a3/ulid/UlidTest.java
+++ b/src/test/java/com/github/f4b6a3/ulid/UlidTest.java
@@ -15,8 +15,6 @@ import java.util.UUID;
import org.junit.Test;
-import com.github.f4b6a3.ulid.Ulid;
-
public class UlidTest {
private static final int DEFAULT_LOOP_MAX = 1_000;
diff --git a/src/test/java/com/github/f4b6a3/ulid/UniquenessTest.java b/src/test/java/com/github/f4b6a3/ulid/uniq/UniquenessTest.java
similarity index 95%
rename from src/test/java/com/github/f4b6a3/ulid/UniquenessTest.java
rename to src/test/java/com/github/f4b6a3/ulid/uniq/UniquenessTest.java
index 106ce1d..9333d1c 100644
--- a/src/test/java/com/github/f4b6a3/ulid/UniquenessTest.java
+++ b/src/test/java/com/github/f4b6a3/ulid/uniq/UniquenessTest.java
@@ -1,8 +1,12 @@
-package com.github.f4b6a3.ulid;
+package com.github.f4b6a3.ulid.uniq;
import java.util.HashSet;
import java.util.Random;
+import com.github.f4b6a3.ulid.TestSuite;
+import com.github.f4b6a3.ulid.Ulid;
+import com.github.f4b6a3.ulid.UlidFactory;
+
/**
*
* This test starts many threads that keep requesting thousands of ULIDs to a