diff --git a/src/main/java/com/github/msemys/esjc/util/UUIDConverter.java b/src/main/java/com/github/msemys/esjc/util/UUIDConverter.java index 1c0f4cc0..0c54b955 100644 --- a/src/main/java/com/github/msemys/esjc/util/UUIDConverter.java +++ b/src/main/java/com/github/msemys/esjc/util/UUIDConverter.java @@ -9,14 +9,32 @@ public static byte[] toBytes(UUID uuid) { ByteBuffer bb = ByteBuffer.allocate(16); bb.putLong(uuid.getMostSignificantBits()); bb.putLong(uuid.getLeastSignificantBits()); - return bb.array(); + return adaptEndianness(bb.array()); } public static UUID toUUID(byte[] bytes) { - ByteBuffer bb = ByteBuffer.wrap(bytes); + ByteBuffer bb = ByteBuffer.wrap(adaptEndianness(bytes)); long mostSignificantBits = bb.getLong(); long leastSignificantBits = bb.getLong(); return new UUID(mostSignificantBits, leastSignificantBits); } + /* + * Adapt between mixed-endian UUID encoding (C#/EventStore) and big-endian (Java). + * https://stackoverflow.com/questions/45671415/c-sharp-why-does-system-guid-flip-the-bytes-in-a-byte-array + */ + private static byte[] adaptEndianness(byte[] bytes) { + switchBytes(bytes, 0, 3); + switchBytes(bytes, 1, 2); + switchBytes(bytes, 4, 5); + switchBytes(bytes, 6, 7); + return bytes; + } + + private static void switchBytes(byte[] bytes, int i, int j) { + byte b = bytes[i]; + bytes[i] = bytes[j]; + bytes[j] = b; + } + } diff --git a/src/test/java/com/github/msemys/esjc/AbstractEventStoreTest.java b/src/test/java/com/github/msemys/esjc/AbstractEventStoreTest.java index 0ebcd8ad..5a870c6e 100644 --- a/src/test/java/com/github/msemys/esjc/AbstractEventStoreTest.java +++ b/src/test/java/com/github/msemys/esjc/AbstractEventStoreTest.java @@ -1,6 +1,11 @@ package com.github.msemys.esjc; + import com.github.msemys.esjc.runner.EventStoreRunnerWithParametersFactory; +import com.github.msemys.esjc.http.HttpClient; +import com.github.msemys.esjc.util.Throwables; +import org.junit.After; +import org.junit.Before; import org.junit.Rule; import org.junit.rules.TestName; import org.junit.runner.RunWith; @@ -38,6 +43,12 @@ public static Object[] parameters() { }; } + protected static final HttpClient httpClient = HttpClient.newBuilder() + .address("127.0.0.1", 2113) + .build(); + + protected static final UserCredentials eventstoreCredentials = new UserCredentials("admin", "changeit"); + protected final EventStore eventstore; @Rule diff --git a/src/test/java/com/github/msemys/esjc/ITReadEvent.java b/src/test/java/com/github/msemys/esjc/ITReadEvent.java index dec025a9..9bf49651 100644 --- a/src/test/java/com/github/msemys/esjc/ITReadEvent.java +++ b/src/test/java/com/github/msemys/esjc/ITReadEvent.java @@ -1,9 +1,14 @@ package com.github.msemys.esjc; +import io.netty.handler.codec.http.FullHttpRequest; import org.junit.Test; import java.util.List; +import java.util.UUID; +import java.util.concurrent.ExecutionException; +import static com.github.msemys.esjc.http.HttpClient.newRequest; +import static io.netty.handler.codec.http.HttpMethod.POST; import static java.util.Arrays.asList; import static org.junit.Assert.*; @@ -93,6 +98,26 @@ public void returnsExistingEvent() { assertNotNull(result.event.originalEvent().created); } + @Test + public void returnsCorrectEventId() throws ExecutionException, InterruptedException { + final String stream = generateStreamName(); + final UUID eventId = UUID.randomUUID(); + + // write event via http API + String uri = "/streams/" + stream; + FullHttpRequest request = newRequest(POST, uri, "{}", "application/json", eventstoreCredentials); + request.headers().set("ES-EventId", eventId.toString()); + request.headers().set("ES-EventType", "event0"); + httpClient.send(request).get(); + + // read event via tcp + EventReadResult result = eventstore.readEvent(stream, 0, true).join(); + + // compare event IDs + assertEquals(EventReadStatus.Success, result.status); + assertEquals(eventId, result.event.originalEvent().eventId); + } + @Test public void retrievesJsonFlagProperly() { final String stream = generateStreamName(); diff --git a/src/test/java/com/github/msemys/esjc/tcp/TcpPackageTest.java b/src/test/java/com/github/msemys/esjc/tcp/TcpPackageTest.java index 9dc82204..86a13171 100644 --- a/src/test/java/com/github/msemys/esjc/tcp/TcpPackageTest.java +++ b/src/test/java/com/github/msemys/esjc/tcp/TcpPackageTest.java @@ -84,7 +84,7 @@ public void createsNonAuthorizedTcpPackageFromByteArray() { assertEquals(TcpCommand.HeartbeatRequestCommand, tcpPackage.command); assertEquals(TcpFlag.None, tcpPackage.flag); - assertEquals("0dc092bd-aeb3-4ad4-a6cf-4448e4ca50cb", tcpPackage.correlationId.toString()); + assertEquals("bd92c00d-b3ae-d44a-a6cf-4448e4ca50cb", tcpPackage.correlationId.toString()); assertNull(tcpPackage.login); assertNull(tcpPackage.password); assertEquals(DATA, new String(tcpPackage.data, UTF_8)); @@ -100,7 +100,7 @@ public void createsAuthorizedTcpPackageFromByteArray() { assertEquals(TcpCommand.HeartbeatRequestCommand, tcpPackage.command); assertEquals(TcpFlag.Authenticated, tcpPackage.flag); - assertEquals("beca0c9b-4d2d-4c10-9bd8-d518da5ccf00", tcpPackage.correlationId.toString()); + assertEquals("9b0ccabe-2d4d-104c-9bd8-d518da5ccf00", tcpPackage.correlationId.toString()); assertEquals("admin", tcpPackage.login); assertEquals("secret", tcpPackage.password); assertEquals(DATA, new String(tcpPackage.data, UTF_8)); diff --git a/src/test/java/com/github/msemys/esjc/util/UUIDConverterTest.java b/src/test/java/com/github/msemys/esjc/util/UUIDConverterTest.java new file mode 100644 index 00000000..2c66c5f1 --- /dev/null +++ b/src/test/java/com/github/msemys/esjc/util/UUIDConverterTest.java @@ -0,0 +1,49 @@ +package com.github.msemys.esjc.util; + +import org.junit.Test; + +import java.util.UUID; + +import static org.junit.Assert.assertArrayEquals; +import static org.junit.Assert.assertEquals; + +/** + * Guid: 35918bc9-196d-40ea-9779-889d79b753f0 + * C9 8B 91 35 6D 19 EA 40 97 79 88 9D 79 B7 53 F0 + * example from https://docs.microsoft.com/en-us/dotnet/api/system.guid.tobytearray?view=netframework-4.7 + */ +public class UUIDConverterTest { + + @Test + public void toUUID() { + byte[] uuidBytes = toByteArray("C9 8B 91 35 6D 19 EA 40 97 79 88 9D 79 B7 53 F0"); + + UUID uuid = UUIDConverter.toUUID(uuidBytes); + + assertEquals(UUID.fromString("35918bc9-196d-40ea-9779-889d79b753f0"), uuid); + } + + @Test + public void toBytes() { + UUID uuid = UUID.fromString("35918bc9-196d-40ea-9779-889d79b753f0"); + + byte[] uuidBytes = UUIDConverter.toBytes(uuid); + + assertArrayEquals(toByteArray("C9 8B 91 35 6D 19 EA 40 97 79 88 9D 79 B7 53 F0"), uuidBytes); + } + + private byte[] toByteArray(String hexString) { + String[] hexArray = hexString.split(" "); + byte[] bytes = new byte[hexArray.length]; + for (int i = 0; i