Add support for RandomGenerator in Java 17 #19
This commit is contained in:
parent
3b6a135fd3
commit
f80eb4029c
|
@ -6,6 +6,10 @@ All notable changes to this project will be documented in this file.
|
||||||
|
|
||||||
Nothing unreleased.
|
Nothing unreleased.
|
||||||
|
|
||||||
|
## [5.0.0] - 2022-07-09
|
||||||
|
|
||||||
|
Add support for RandomGenerator in Java 17. #19
|
||||||
|
|
||||||
## [4.2.1] - 2022-04-21
|
## [4.2.1] - 2022-04-21
|
||||||
|
|
||||||
Handle clock drift. #18
|
Handle clock drift. #18
|
||||||
|
@ -286,7 +290,8 @@ Project created as an alternative Java implementation of [ULID spec](https://git
|
||||||
- Added `LICENSE`
|
- Added `LICENSE`
|
||||||
- Added test cases
|
- 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.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.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
|
[4.1.2]: https://github.com/f4b6a3/ulid-creator/compare/ulid-creator-4.1.1...ulid-creator-4.1.2
|
||||||
|
|
34
README.md
34
README.md
|
@ -39,7 +39,7 @@ Add these lines to your `pom.xml`.
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>com.github.f4b6a3</groupId>
|
<groupId>com.github.f4b6a3</groupId>
|
||||||
<artifactId>ulid-creator</artifactId>
|
<artifactId>ulid-creator</artifactId>
|
||||||
<version>4.2.1</version>
|
<version>5.0.0</version>
|
||||||
</dependency>
|
</dependency>
|
||||||
```
|
```
|
||||||
See more options in [maven.org](https://search.maven.org/artifact/com.github.f4b6a3/ulid-creator).
|
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<byte[]>`:
|
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
|
```java
|
||||||
// use a random supplier that returns an array of 10 bytes
|
// use a random supplier that returns an array of 10 bytes
|
||||||
UlidFactory factory = UlidFactory.newInstance(() -> {
|
UlidFactory factory = UlidFactory.newInstance((length) -> {
|
||||||
final byte[] bytes = new byte[Ulid.RANDOM_BYTES];
|
final byte[] bytes = new byte[length];
|
||||||
ThreadLocalRandom.current().nextBytes(bytes);
|
ThreadLocalRandom.current().nextBytes(bytes);
|
||||||
return bytes;
|
return bytes;
|
||||||
});
|
});
|
||||||
|
|
|
@ -27,8 +27,9 @@ package com.github.f4b6a3.ulid;
|
||||||
import java.security.SecureRandom;
|
import java.security.SecureRandom;
|
||||||
import java.time.Clock;
|
import java.time.Clock;
|
||||||
import java.util.Random;
|
import java.util.Random;
|
||||||
|
import java.util.function.IntFunction;
|
||||||
import java.util.function.LongFunction;
|
import java.util.function.LongFunction;
|
||||||
import java.util.function.Supplier;
|
import java.util.function.LongSupplier;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Factory that generates ULIDs.
|
* Factory that generates ULIDs.
|
||||||
|
@ -47,7 +48,7 @@ public final class UlidFactory {
|
||||||
private final LongFunction<Ulid> ulidFunction;
|
private final LongFunction<Ulid> ulidFunction;
|
||||||
|
|
||||||
public UlidFactory() {
|
public UlidFactory() {
|
||||||
this(new UlidFunction(getRandomSupplier(null)));
|
this(new UlidFunction());
|
||||||
}
|
}
|
||||||
|
|
||||||
private UlidFactory(LongFunction<Ulid> ulidFunction) {
|
private UlidFactory(LongFunction<Ulid> ulidFunction) {
|
||||||
|
@ -67,7 +68,7 @@ public final class UlidFactory {
|
||||||
* @return {@link UlidFactory}
|
* @return {@link UlidFactory}
|
||||||
*/
|
*/
|
||||||
public static UlidFactory newInstance() {
|
public static UlidFactory newInstance() {
|
||||||
return newInstance(getRandomSupplier(null));
|
return new UlidFactory(new UlidFunction());
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -77,19 +78,31 @@ public final class UlidFactory {
|
||||||
* @return {@link UlidFactory}
|
* @return {@link UlidFactory}
|
||||||
*/
|
*/
|
||||||
public static UlidFactory newInstance(Random random) {
|
public static UlidFactory newInstance(Random random) {
|
||||||
return newInstance(getRandomSupplier(random));
|
return new UlidFactory(new UlidFunction(random));
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns a new factory.
|
* 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}
|
* @return {@link UlidFactory}
|
||||||
*/
|
*/
|
||||||
public static UlidFactory newInstance(Supplier<byte[]> randomSupplier) {
|
public static UlidFactory newInstance(LongSupplier randomFunction) {
|
||||||
return new UlidFactory(new UlidFunction(randomSupplier));
|
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<byte[]> randomFunction) {
|
||||||
|
return new UlidFactory(new UlidFunction(randomFunction));
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -98,7 +111,7 @@ public final class UlidFactory {
|
||||||
* @return {@link UlidFactory}
|
* @return {@link UlidFactory}
|
||||||
*/
|
*/
|
||||||
public static UlidFactory newMonotonicInstance() {
|
public static UlidFactory newMonotonicInstance() {
|
||||||
return newMonotonicInstance(getRandomSupplier(null));
|
return new UlidFactory(new MonotonicFunction());
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -108,32 +121,57 @@ public final class UlidFactory {
|
||||||
* @return {@link UlidFactory}
|
* @return {@link UlidFactory}
|
||||||
*/
|
*/
|
||||||
public static UlidFactory newMonotonicInstance(Random random) {
|
public static UlidFactory newMonotonicInstance(Random random) {
|
||||||
return newMonotonicInstance(getRandomSupplier(random));
|
return new UlidFactory(new MonotonicFunction(random));
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns a new monotonic factory.
|
* 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}
|
* @return {@link UlidFactory}
|
||||||
*/
|
*/
|
||||||
public static UlidFactory newMonotonicInstance(Supplier<byte[]> randomSupplier) {
|
public static UlidFactory newMonotonicInstance(LongSupplier randomFunction) {
|
||||||
return new UlidFactory(new MonotonicFunction(randomSupplier));
|
return new UlidFactory(new MonotonicFunction(randomFunction));
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns a new monotonic factory.
|
* 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<byte[]> 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
|
* @param clock a custom clock instance for tests
|
||||||
* @return {@link UlidFactory}
|
* @return {@link UlidFactory}
|
||||||
*/
|
*/
|
||||||
protected static UlidFactory newMonotonicInstance(Supplier<byte[]> randomSupplier, Clock clock) {
|
protected static UlidFactory newMonotonicInstance(LongSupplier randomFunction, Clock clock) {
|
||||||
return new UlidFactory(new MonotonicFunction(randomSupplier), 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<byte[]> randomFunction, Clock clock) {
|
||||||
|
return new UlidFactory(new MonotonicFunction(randomFunction), clock);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -141,8 +179,8 @@ public final class UlidFactory {
|
||||||
*
|
*
|
||||||
* @return a ULID
|
* @return a ULID
|
||||||
*/
|
*/
|
||||||
public Ulid create() {
|
public synchronized Ulid create() {
|
||||||
return create(clock.millis());
|
return this.ulidFunction.apply(clock.millis());
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -153,7 +191,7 @@ public final class UlidFactory {
|
||||||
* @param time a given time
|
* @param time a given time
|
||||||
* @return a ULID
|
* @return a ULID
|
||||||
*/
|
*/
|
||||||
public Ulid create(final long time) {
|
public synchronized Ulid create(final long time) {
|
||||||
return this.ulidFunction.apply(time);
|
return this.ulidFunction.apply(time);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -162,16 +200,33 @@ public final class UlidFactory {
|
||||||
*/
|
*/
|
||||||
protected static final class UlidFunction implements LongFunction<Ulid> {
|
protected static final class UlidFunction implements LongFunction<Ulid> {
|
||||||
|
|
||||||
// it must return an array of 10 bytes
|
private final IRandom random;
|
||||||
private Supplier<byte[]> randomSupplier;
|
|
||||||
|
|
||||||
public UlidFunction(Supplier<byte[]> randomSupplier) {
|
public UlidFunction() {
|
||||||
this.randomSupplier = randomSupplier;
|
this.random = new ByteRandom();
|
||||||
|
}
|
||||||
|
|
||||||
|
public UlidFunction(Random random) {
|
||||||
|
this.random = IRandom.newInstance(random);
|
||||||
|
}
|
||||||
|
|
||||||
|
public UlidFunction(IntFunction<byte[]> randomFunction) {
|
||||||
|
this.random = new ByteRandom(randomFunction);
|
||||||
|
}
|
||||||
|
|
||||||
|
public UlidFunction(LongSupplier randomFunction) {
|
||||||
|
this.random = new LongRandom(randomFunction);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Ulid apply(final long time) {
|
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 long lastTime;
|
||||||
private Ulid lastUlid;
|
private Ulid lastUlid;
|
||||||
|
|
||||||
|
private final IRandom random;
|
||||||
|
|
||||||
// Used to preserve monotonicity when the system clock is
|
// Used to preserve monotonicity when the system clock is
|
||||||
// adjusted by NTP after a small clock drift or when the
|
// adjusted by NTP after a small clock drift or when the
|
||||||
// system clock jumps back by 1 second due to leap second.
|
// system clock jumps back by 1 second due to leap second.
|
||||||
protected static final int CLOCK_DRIFT_TOLERANCE = 10_000;
|
protected static final int CLOCK_DRIFT_TOLERANCE = 10_000;
|
||||||
|
|
||||||
// it must return an array of 10 bytes
|
public MonotonicFunction() {
|
||||||
private Supplier<byte[]> randomSupplier;
|
this(new ByteRandom());
|
||||||
|
}
|
||||||
|
|
||||||
public MonotonicFunction(Supplier<byte[]> randomSupplier) {
|
public MonotonicFunction(Random random) {
|
||||||
this.randomSupplier = randomSupplier;
|
this(IRandom.newInstance(random));
|
||||||
|
}
|
||||||
|
|
||||||
|
public MonotonicFunction(IntFunction<byte[]> randomFunction) {
|
||||||
|
this(new ByteRandom(randomFunction));
|
||||||
|
}
|
||||||
|
|
||||||
|
public MonotonicFunction(LongSupplier randomFunction) {
|
||||||
|
this(new LongRandom(randomFunction));
|
||||||
|
}
|
||||||
|
|
||||||
|
private MonotonicFunction(IRandom random) {
|
||||||
|
this.random = random;
|
||||||
|
|
||||||
// initialize internal state
|
// initialize internal state
|
||||||
this.lastTime = Clock.systemUTC().millis();
|
this.lastTime = Clock.systemUTC().millis();
|
||||||
this.lastUlid = new Ulid(lastTime, randomSupplier.get());
|
this.lastUlid = new Ulid(lastTime, random.nextBytes(Ulid.RANDOM_BYTES));
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -209,26 +279,122 @@ public final class UlidFactory {
|
||||||
this.lastUlid = lastUlid.increment();
|
this.lastUlid = lastUlid.increment();
|
||||||
} else {
|
} else {
|
||||||
this.lastTime = time;
|
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);
|
return new Ulid(this.lastUlid);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
protected static interface IRandom {
|
||||||
* It instantiates a supplier that returns an array of 10 bytes.
|
|
||||||
*
|
public long nextLong();
|
||||||
* @param random a {@link Random} generator
|
|
||||||
* @return a random supplier that returns 10 bytes
|
public byte[] nextBytes(int length);
|
||||||
*/
|
|
||||||
protected static Supplier<byte[]> getRandomSupplier(Random random) {
|
static IRandom newInstance(Random random) {
|
||||||
Random entropy = random != null ? random : new SecureRandom();
|
if (random == null) {
|
||||||
return () -> {
|
return new ByteRandom();
|
||||||
byte[] payload = new byte[Ulid.RANDOM_BYTES];
|
} else {
|
||||||
entropy.nextBytes(payload);
|
if (random instanceof SecureRandom) {
|
||||||
return payload;
|
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<byte[]> randomFunction;
|
||||||
|
|
||||||
|
public ByteRandom() {
|
||||||
|
this(newRandomFunction(null));
|
||||||
|
}
|
||||||
|
|
||||||
|
public ByteRandom(Random random) {
|
||||||
|
this(newRandomFunction(random));
|
||||||
|
}
|
||||||
|
|
||||||
|
public ByteRandom(IntFunction<byte[]> 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<byte[]> 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;
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -2,13 +2,16 @@ package com.github.f4b6a3.ulid;
|
||||||
|
|
||||||
import org.junit.Test;
|
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 static org.junit.Assert.*;
|
||||||
|
|
||||||
|
import java.nio.ByteBuffer;
|
||||||
|
import java.security.SecureRandom;
|
||||||
|
import java.util.Arrays;
|
||||||
import java.util.Random;
|
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 {
|
public class UlidFactoryDefaultfTest extends UlidFactoryTest {
|
||||||
|
|
||||||
|
@ -59,4 +62,188 @@ public class UlidFactoryDefaultfTest extends UlidFactoryTest {
|
||||||
assertEquals(time, ulid.getTime());
|
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<byte[]> 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<byte[]>) 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)));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -2,10 +2,6 @@ package com.github.f4b6a3.ulid;
|
||||||
|
|
||||||
import org.junit.Test;
|
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 static org.junit.Assert.*;
|
||||||
|
|
||||||
import java.time.Clock;
|
import java.time.Clock;
|
||||||
|
@ -13,7 +9,10 @@ import java.time.Instant;
|
||||||
import java.time.ZoneId;
|
import java.time.ZoneId;
|
||||||
import java.util.Arrays;
|
import java.util.Arrays;
|
||||||
import java.util.Random;
|
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 {
|
public class UlidFactoryMonotonicTest extends UlidFactoryTest {
|
||||||
|
|
||||||
|
@ -66,7 +65,7 @@ public class UlidFactoryMonotonicTest extends UlidFactoryTest {
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
Supplier<byte[]> randomSupplier = UlidFactory.getRandomSupplier(new Random());
|
IntFunction<byte[]> randomSupplier = UlidFactory.ByteRandom.newRandomFunction(new Random());
|
||||||
UlidFactory factory = UlidFactory.newMonotonicInstance(randomSupplier, clock);
|
UlidFactory factory = UlidFactory.newMonotonicInstance(randomSupplier, clock);
|
||||||
|
|
||||||
long ms1 = factory.create().getTime(); // time
|
long ms1 = factory.create().getTime(); // time
|
||||||
|
@ -115,7 +114,7 @@ public class UlidFactoryMonotonicTest extends UlidFactoryTest {
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
Supplier<byte[]> randomSupplier = UlidFactory.getRandomSupplier(new Random());
|
IntFunction<byte[]> randomSupplier = UlidFactory.ByteRandom.newRandomFunction(new Random());
|
||||||
UlidFactory factory = UlidFactory.newMonotonicInstance(randomSupplier, clock);
|
UlidFactory factory = UlidFactory.newMonotonicInstance(randomSupplier, clock);
|
||||||
|
|
||||||
long ms1 = factory.create().getTime(); // second
|
long ms1 = factory.create().getTime(); // second
|
||||||
|
@ -163,4 +162,63 @@ public class UlidFactoryMonotonicTest extends UlidFactoryTest {
|
||||||
assertEquals(time, ulid.getTime());
|
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<byte[]> function = (length) -> {
|
||||||
|
byte[] bytes = new byte[length];
|
||||||
|
ThreadLocalRandom.current().nextBytes(bytes);
|
||||||
|
return bytes;
|
||||||
|
};
|
||||||
|
UlidFactory factory = UlidFactory.newMonotonicInstance(function);
|
||||||
|
assertNotNull(factory.create());
|
||||||
|
}
|
||||||
|
{
|
||||||
|
IntFunction<byte[]> 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<byte[]>) null);
|
||||||
|
assertNotNull(factory.create());
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -9,8 +9,6 @@ import java.util.Random;
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
import java.util.UUID;
|
import java.util.UUID;
|
||||||
|
|
||||||
import com.github.f4b6a3.ulid.UlidFactory;
|
|
||||||
|
|
||||||
public abstract class UlidFactoryTest {
|
public abstract class UlidFactoryTest {
|
||||||
|
|
||||||
protected static final int DEFAULT_LOOP_MAX = 10_000;
|
protected static final int DEFAULT_LOOP_MAX = 10_000;
|
||||||
|
|
|
@ -15,8 +15,6 @@ import java.util.UUID;
|
||||||
|
|
||||||
import org.junit.Test;
|
import org.junit.Test;
|
||||||
|
|
||||||
import com.github.f4b6a3.ulid.Ulid;
|
|
||||||
|
|
||||||
public class UlidTest {
|
public class UlidTest {
|
||||||
|
|
||||||
private static final int DEFAULT_LOOP_MAX = 1_000;
|
private static final int DEFAULT_LOOP_MAX = 1_000;
|
||||||
|
|
|
@ -1,8 +1,12 @@
|
||||||
package com.github.f4b6a3.ulid;
|
package com.github.f4b6a3.ulid.uniq;
|
||||||
|
|
||||||
import java.util.HashSet;
|
import java.util.HashSet;
|
||||||
import java.util.Random;
|
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
|
* This test starts many threads that keep requesting thousands of ULIDs to a
|
Loading…
Reference in New Issue