From b2d41060785a3c8f1adf86b94cf8f2f80b94b4dc Mon Sep 17 00:00:00 2001 From: Martin Blomberg Date: Sun, 12 Feb 2023 21:59:24 +0100 Subject: [PATCH 01/27] Add HazeIT.java Integration tests that starts the server on a random free port. Tests for the following commands: PING - PONG SETNX SET - GET DELETE EXISTS Error for not implemented command --- pom.xml | 6 ++ src/test/java/org/fungover/haze/HazeIT.java | 104 ++++++++++++++++++++ 2 files changed, 110 insertions(+) create mode 100644 src/test/java/org/fungover/haze/HazeIT.java diff --git a/pom.xml b/pom.xml index 1ee02c72..52e2f823 100644 --- a/pom.xml +++ b/pom.xml @@ -48,6 +48,12 @@ log4j-core 2.19.0 + + redis.clients + jedis + 4.3.1 + test + diff --git a/src/test/java/org/fungover/haze/HazeIT.java b/src/test/java/org/fungover/haze/HazeIT.java new file mode 100644 index 00000000..f0655988 --- /dev/null +++ b/src/test/java/org/fungover/haze/HazeIT.java @@ -0,0 +1,104 @@ +package org.fungover.haze; + +import org.junit.jupiter.api.AfterAll; +import org.junit.jupiter.api.BeforeAll; +import org.junit.jupiter.api.Test; +import redis.clients.jedis.JedisPooled; +import redis.clients.jedis.Protocol; +import redis.clients.jedis.util.SafeEncoder; + +import java.io.BufferedReader; +import java.io.IOException; +import java.io.InputStreamReader; +import java.net.ServerSocket; +import java.net.Socket; +import java.nio.charset.StandardCharsets; + +import static org.assertj.core.api.Assertions.assertThat; + +public class HazeIT { + + static Process pro; + static JedisPooled pool; + static int port; + + @BeforeAll + static void startServer() throws IOException { + port = findFreePort(); + System.out.println(port); + String[] command = {"java", "--enable-preview", "-cp", "target/classes", "org.fungover.haze.Main", "--port", String.valueOf(port)}; + pro = Runtime.getRuntime().exec(command); + pool = new JedisPooled("localhost", port); + } + + @AfterAll + static void stopServer() throws InterruptedException { + pool.close(); + pro.destroy(); + pro.waitFor(); + System.out.println("exitValue() " + pro.exitValue()); + } + + @Test + void pingPong() { + //Simple PING command with no message should return PONG as simple string + var result = pool.sendCommand(Protocol.Command.PING); + assertThat(SafeEncoder.encode((byte[]) result)).isEqualTo("PONG"); + //PING with message argument should return bulk string with the argument + result = pool.sendCommand(Protocol.Command.PING, "HELLO"); + assertThat(SafeEncoder.encode((byte[]) result)).isEqualTo("HELLO"); + //PING with message argument containing space should return bulk string with the argument + result = pool.sendCommand(Protocol.Command.PING, "HELLO\r\n There"); + assertThat(SafeEncoder.encode((byte[]) result)).isEqualTo("HELLO\r\n There"); + } + + @Test + void setNx() { + //Remove keys before trying this + pool.del("test", "test1"); + assertThat(pool.setnx("test", "test")).isEqualTo(1); + assertThat(pool.setnx("test1", "test")).isEqualTo(1); + //Key test already exists so should not be set + assertThat(pool.setnx("test", "test1")).isEqualTo(0); + } + + @Test + void setGet() { + assertThat(pool.set("test", "test")).isEqualTo("OK"); + assertThat(pool.get("test")).isEqualTo("test"); + } + + @Test + void exists() { + assertThat(pool.set("test", "test")).isEqualTo("OK"); + assertThat(pool.exists("test")).isTrue(); + pool.del("notused"); + assertThat(pool.exists("notused")).isFalse(); + } + + @Test + void unknownCommand() { + try (Socket socket = new Socket("localhost", port)) { + socket.setSoTimeout(3000); + socket.getOutputStream().write("helloworld key value\r\n".getBytes(StandardCharsets.UTF_8)); + BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(socket.getInputStream())); + assertThat(bufferedReader.readLine()).isEqualTo("-ERR unknown command 'helloworld', with args beginning with: 'key' 'value' "); + } catch (IOException e) { + throw new RuntimeException(e); + } + } + + private static int findFreePort() { + int port = 0; + try (ServerSocket socket = new ServerSocket(0)) { + // Disable timeout and reuse address after closing the socket. + socket.setReuseAddress(true); + port = socket.getLocalPort(); + } catch (IOException ignored) { + } + if (port > 0) { + return port; + } + throw new RuntimeException("Could not find a free port"); + } +} From aeed8ab8e3d3f97af5262dd21c5169b890918303 Mon Sep 17 00:00:00 2001 From: Martin Blomberg Date: Mon, 13 Feb 2023 17:03:55 +0100 Subject: [PATCH 02/27] Update findFreePort method Change initialization of ServerSocket setReuseAddress true to happen before binding. Otherwise, the reuse address option doesn't work. --- pom.xml | 6 +++++ src/test/java/org/fungover/haze/HazeIT.java | 29 +++++++++++++++++---- 2 files changed, 30 insertions(+), 5 deletions(-) diff --git a/pom.xml b/pom.xml index 52e2f823..3c7f27c5 100644 --- a/pom.xml +++ b/pom.xml @@ -54,6 +54,12 @@ 4.3.1 test + + org.awaitility + awaitility + 4.2.0 + test + diff --git a/src/test/java/org/fungover/haze/HazeIT.java b/src/test/java/org/fungover/haze/HazeIT.java index f0655988..0d22ca5e 100644 --- a/src/test/java/org/fungover/haze/HazeIT.java +++ b/src/test/java/org/fungover/haze/HazeIT.java @@ -10,13 +10,17 @@ import java.io.BufferedReader; import java.io.IOException; import java.io.InputStreamReader; +import java.net.InetSocketAddress; import java.net.ServerSocket; import java.net.Socket; import java.nio.charset.StandardCharsets; +import java.util.concurrent.Callable; +import static java.util.concurrent.TimeUnit.SECONDS; import static org.assertj.core.api.Assertions.assertThat; +import static org.awaitility.Awaitility.await; -public class HazeIT { +class HazeIT { static Process pro; static JedisPooled pool; @@ -24,13 +28,27 @@ public class HazeIT { @BeforeAll static void startServer() throws IOException { + var pathSep = System.getProperty("path.separator"); port = findFreePort(); System.out.println(port); - String[] command = {"java", "--enable-preview", "-cp", "target/classes", "org.fungover.haze.Main", "--port", String.valueOf(port)}; + String[] command = {"java", "--enable-preview", "-cp", "target/classes" + pathSep + "target/dependency/*", "org.fungover.haze.Main", "--port", String.valueOf(port)}; pro = Runtime.getRuntime().exec(command); + + await().atMost(10, SECONDS).until(serverIsUp()); + pool = new JedisPooled("localhost", port); } + private static Callable serverIsUp() { + return () -> { + try (Socket socket = new Socket("localhost", port)) { + return true; + } catch (IOException e) { + return false; + } + }; // The condition that must be fulfilled + } + @AfterAll static void stopServer() throws InterruptedException { pool.close(); @@ -59,7 +77,7 @@ void setNx() { assertThat(pool.setnx("test", "test")).isEqualTo(1); assertThat(pool.setnx("test1", "test")).isEqualTo(1); //Key test already exists so should not be set - assertThat(pool.setnx("test", "test1")).isEqualTo(0); + assertThat(pool.setnx("test", "test1")).isZero(); } @Test @@ -90,9 +108,10 @@ void unknownCommand() { private static int findFreePort() { int port = 0; - try (ServerSocket socket = new ServerSocket(0)) { - // Disable timeout and reuse address after closing the socket. + try (ServerSocket socket = new ServerSocket()) { + // Allow direct reuse of port after closing the socket. socket.setReuseAddress(true); + socket.bind(new InetSocketAddress("localhost", 0)); port = socket.getLocalPort(); } catch (IOException ignored) { } From 7afd6e2234d0bf1905c729891ebfac4002c65a4e Mon Sep 17 00:00:00 2001 From: Martin Blomberg Date: Sat, 18 Feb 2023 09:47:59 +0100 Subject: [PATCH 03/27] Remove IT testcode not working with current server impl. --- src/test/java/org/fungover/haze/HazeIT.java | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/src/test/java/org/fungover/haze/HazeIT.java b/src/test/java/org/fungover/haze/HazeIT.java index 0d22ca5e..8af9de08 100644 --- a/src/test/java/org/fungover/haze/HazeIT.java +++ b/src/test/java/org/fungover/haze/HazeIT.java @@ -66,14 +66,12 @@ void pingPong() { result = pool.sendCommand(Protocol.Command.PING, "HELLO"); assertThat(SafeEncoder.encode((byte[]) result)).isEqualTo("HELLO"); //PING with message argument containing space should return bulk string with the argument - result = pool.sendCommand(Protocol.Command.PING, "HELLO\r\n There"); - assertThat(SafeEncoder.encode((byte[]) result)).isEqualTo("HELLO\r\n There"); + // result = pool.sendCommand(Protocol.Command.PING, "HELLO\r\n There"); + // assertThat(SafeEncoder.encode((byte[]) result)).isEqualTo("HELLO\r\n There"); } @Test void setNx() { - //Remove keys before trying this - pool.del("test", "test1"); assertThat(pool.setnx("test", "test")).isEqualTo(1); assertThat(pool.setnx("test1", "test")).isEqualTo(1); //Key test already exists so should not be set @@ -84,6 +82,7 @@ void setNx() { void setGet() { assertThat(pool.set("test", "test")).isEqualTo("OK"); assertThat(pool.get("test")).isEqualTo("test"); + pool.del("test"); } @Test @@ -100,7 +99,8 @@ void unknownCommand() { socket.setSoTimeout(3000); socket.getOutputStream().write("helloworld key value\r\n".getBytes(StandardCharsets.UTF_8)); BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(socket.getInputStream())); - assertThat(bufferedReader.readLine()).isEqualTo("-ERR unknown command 'helloworld', with args beginning with: 'key' 'value' "); +// assertThat(bufferedReader.readLine()).isEqualTo("-ERR unknown command 'helloworld', with args beginning with: 'key' 'value' "); + assertThat(bufferedReader.readLine()).isEqualTo("-ERR unknown command"); } catch (IOException e) { throw new RuntimeException(e); } From e7a32ac78ac75a7d3120b589ed849e59f650f8ea Mon Sep 17 00:00:00 2001 From: Martin Blomberg Date: Tue, 21 Feb 2023 21:23:13 +0100 Subject: [PATCH 04/27] Add Integration test for list --- src/test/java/org/fungover/haze/HazeIT.java | 18 ++++++++++++++++-- 1 file changed, 16 insertions(+), 2 deletions(-) diff --git a/src/test/java/org/fungover/haze/HazeIT.java b/src/test/java/org/fungover/haze/HazeIT.java index 8af9de08..75dbadb7 100644 --- a/src/test/java/org/fungover/haze/HazeIT.java +++ b/src/test/java/org/fungover/haze/HazeIT.java @@ -66,8 +66,8 @@ void pingPong() { result = pool.sendCommand(Protocol.Command.PING, "HELLO"); assertThat(SafeEncoder.encode((byte[]) result)).isEqualTo("HELLO"); //PING with message argument containing space should return bulk string with the argument - // result = pool.sendCommand(Protocol.Command.PING, "HELLO\r\n There"); - // assertThat(SafeEncoder.encode((byte[]) result)).isEqualTo("HELLO\r\n There"); + // result = pool.sendCommand(Protocol.Command.PING, "HELLO\r\n There"); + // assertThat(SafeEncoder.encode((byte[]) result)).isEqualTo("HELLO\r\n There"); } @Test @@ -106,6 +106,20 @@ void unknownCommand() { } } + @Test + void listMethods() { + assertThat(pool.lpush("mylist", "third")).isEqualTo(1); + assertThat(pool.llen("mylist")).isEqualTo(1); + assertThat(pool.lpush("mylist", "second","first")).isEqualTo(3); + assertThat(pool.llen("mylist")).isEqualTo(3); + assertThat(pool.lpop("mylist")).isEqualTo("first"); + assertThat(pool.llen("mylist")).isEqualTo(2); + assertThat(pool.rpush("mylist", "last")).isEqualTo(3); + assertThat(pool.rpop("mylist")).isEqualTo("last"); + assertThat(pool.lset("mylist",0, "test")).isEqualTo("OK"); + assertThat(pool.del("mylist")).isEqualTo(1); + } + private static int findFreePort() { int port = 0; try (ServerSocket socket = new ServerSocket()) { From 70402c30cb97c095124f5dd4370ce93bba7309fb Mon Sep 17 00:00:00 2001 From: Martin Blomberg Date: Wed, 22 Feb 2023 20:28:42 +0100 Subject: [PATCH 05/27] Change HazeIT to use testcontainers --- pom.xml | 12 ++ src/main/java/org/fungover/haze/Main.java | 22 +--- src/test/java/org/fungover/haze/HazeIT.java | 138 +++++++++----------- 3 files changed, 83 insertions(+), 89 deletions(-) diff --git a/pom.xml b/pom.xml index 3c7f27c5..210fa7bb 100644 --- a/pom.xml +++ b/pom.xml @@ -60,6 +60,18 @@ 4.2.0 test + + org.testcontainers + testcontainers + 1.17.6 + test + + + org.testcontainers + junit-jupiter + 1.17.6 + test + diff --git a/src/main/java/org/fungover/haze/Main.java b/src/main/java/org/fungover/haze/Main.java index 2abc5b51..05a9344e 100644 --- a/src/main/java/org/fungover/haze/Main.java +++ b/src/main/java/org/fungover/haze/Main.java @@ -9,6 +9,7 @@ import java.net.InetSocketAddress; import java.net.ServerSocket; import java.net.Socket; +import java.nio.charset.StandardCharsets; import java.util.ArrayList; import java.util.Arrays; import java.util.List; @@ -35,7 +36,6 @@ public static void main(String[] args) { serverSocket.bind(new InetSocketAddress(initialize.getPort())); while (serverOpen) { var client = serverSocket.accept(); - logger.info("Application started: serverSocket.accept()"); Runnable newThread = () -> { try { @@ -45,19 +45,16 @@ public static void main(String[] args) { List inputList = new ArrayList<>(); String firstReading = input.readLine(); + logger.debug(firstReading); readInputStream(input, inputList, firstReading); clientAuthenticated = authenticateClient(auth, isPasswordSet, client, inputList, clientAuthenticated); - client.getOutputStream().write(executeCommand(hazeDatabase, inputList, hazeList).getBytes()); - - inputList.forEach(System.out::println); // For checking incoming message - - printThreadDebug(); + client.getOutputStream().write(executeCommand(hazeDatabase, inputList, hazeList).getBytes(StandardCharsets.UTF_8)); + client.getOutputStream().flush(); inputList.clear(); } - } catch (IOException e) { logger.error(e); } @@ -75,14 +72,9 @@ private static void shutdown(HazeDatabase hazeDatabase) { logger.info("Shutting down...."); } - private static void printThreadDebug() { - logger.debug("ThreadID {}", () -> Thread.currentThread().threadId()); // Only for Debug - logger.debug("Is virtual Thread {}", () -> Thread.currentThread().isVirtual()); // Only for Debug - } - public static String executeCommand(HazeDatabase hazeDatabase, List inputList, HazeList hazeList) { if (inputList.isEmpty() || inputList.get(0).isEmpty()) { - return "-ERR no command provided\r\n"; + return "-ERR unknown command\r\n"; } logger.debug("executeCommand: {} {} ", () -> hazeDatabase, () -> inputList); @@ -107,7 +99,7 @@ public static String executeCommand(HazeDatabase hazeDatabase, List inpu case RPUSH -> hazeList.rPush(inputList); case LPUSH -> hazeList.lPush(inputList); case LPOP -> hazeList.callLPop(inputList); - case RPOP -> hazeList.callRpop(inputList); + case RPOP -> hazeList.callRPop(inputList); case LLEN -> hazeList.lLen(inputList); case LMOVE -> hazeList.lMove(inputList); case LTRIM -> hazeList.callLtrim(inputList); @@ -118,7 +110,7 @@ public static String executeCommand(HazeDatabase hazeDatabase, List inpu private static void readInputStream(BufferedReader input, List inputList, String firstReading) throws IOException { - logger.debug("readInputStream: {} {} {}", () -> input, () -> inputList, () -> firstReading); + logger.debug("readInputStream: {} {}", () -> inputList, () -> firstReading); int size; if (firstReading.startsWith("*")) { size = Integer.parseInt(firstReading.substring(1)) * 2; diff --git a/src/test/java/org/fungover/haze/HazeIT.java b/src/test/java/org/fungover/haze/HazeIT.java index 75dbadb7..ae930553 100644 --- a/src/test/java/org/fungover/haze/HazeIT.java +++ b/src/test/java/org/fungover/haze/HazeIT.java @@ -1,60 +1,41 @@ package org.fungover.haze; -import org.junit.jupiter.api.AfterAll; -import org.junit.jupiter.api.BeforeAll; +import org.junit.jupiter.api.AfterEach; +import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; +import org.testcontainers.containers.GenericContainer; +import org.testcontainers.images.builder.ImageFromDockerfile; +import org.testcontainers.junit.jupiter.Container; +import org.testcontainers.junit.jupiter.Testcontainers; import redis.clients.jedis.JedisPooled; import redis.clients.jedis.Protocol; import redis.clients.jedis.util.SafeEncoder; -import java.io.BufferedReader; -import java.io.IOException; -import java.io.InputStreamReader; -import java.net.InetSocketAddress; -import java.net.ServerSocket; -import java.net.Socket; -import java.nio.charset.StandardCharsets; -import java.util.concurrent.Callable; +import java.nio.file.Path; -import static java.util.concurrent.TimeUnit.SECONDS; import static org.assertj.core.api.Assertions.assertThat; -import static org.awaitility.Awaitility.await; -class HazeIT { - static Process pro; - static JedisPooled pool; - static int port; +@Testcontainers +class HazeIT { - @BeforeAll - static void startServer() throws IOException { - var pathSep = System.getProperty("path.separator"); - port = findFreePort(); - System.out.println(port); - String[] command = {"java", "--enable-preview", "-cp", "target/classes" + pathSep + "target/dependency/*", "org.fungover.haze.Main", "--port", String.valueOf(port)}; - pro = Runtime.getRuntime().exec(command); + @Container + public GenericContainer haze = new GenericContainer(new ImageFromDockerfile() + .withDockerfile(Path.of("./Dockerfile"))) + .withExposedPorts(6379); - await().atMost(10, SECONDS).until(serverIsUp()); + JedisPooled pool; - pool = new JedisPooled("localhost", port); + @BeforeEach + void createPool() { + String address = haze.getHost(); + Integer port = haze.getFirstMappedPort(); + pool = new JedisPooled(address, port); } - private static Callable serverIsUp() { - return () -> { - try (Socket socket = new Socket("localhost", port)) { - return true; - } catch (IOException e) { - return false; - } - }; // The condition that must be fulfilled - } - - @AfterAll - static void stopServer() throws InterruptedException { + @AfterEach + void closePool() { pool.close(); - pro.destroy(); - pro.waitFor(); - System.out.println("exitValue() " + pro.exitValue()); } @Test @@ -72,10 +53,14 @@ void pingPong() { @Test void setNx() { + pool.del("test"); + pool.del("test1"); assertThat(pool.setnx("test", "test")).isEqualTo(1); assertThat(pool.setnx("test1", "test")).isEqualTo(1); //Key test already exists so should not be set assertThat(pool.setnx("test", "test1")).isZero(); + pool.del("test"); + pool.del("test1"); } @Test @@ -94,44 +79,49 @@ void exists() { } @Test - void unknownCommand() { - try (Socket socket = new Socket("localhost", port)) { - socket.setSoTimeout(3000); - socket.getOutputStream().write("helloworld key value\r\n".getBytes(StandardCharsets.UTF_8)); - BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(socket.getInputStream())); -// assertThat(bufferedReader.readLine()).isEqualTo("-ERR unknown command 'helloworld', with args beginning with: 'key' 'value' "); - assertThat(bufferedReader.readLine()).isEqualTo("-ERR unknown command"); - } catch (IOException e) { - throw new RuntimeException(e); - } + void listLPushLPop() { + assertThat(pool.lpush("left", "first")).isEqualTo(1); + assertThat(pool.llen("left")).isEqualTo(1); + assertThat(pool.lpop("left")).isEqualTo("first"); + assertThat(pool.llen("left")).isZero(); + pool.del("left"); + assertThat(pool.exists("left")).isFalse(); } @Test - void listMethods() { - assertThat(pool.lpush("mylist", "third")).isEqualTo(1); - assertThat(pool.llen("mylist")).isEqualTo(1); - assertThat(pool.lpush("mylist", "second","first")).isEqualTo(3); - assertThat(pool.llen("mylist")).isEqualTo(3); - assertThat(pool.lpop("mylist")).isEqualTo("first"); - assertThat(pool.llen("mylist")).isEqualTo(2); - assertThat(pool.rpush("mylist", "last")).isEqualTo(3); - assertThat(pool.rpop("mylist")).isEqualTo("last"); - assertThat(pool.lset("mylist",0, "test")).isEqualTo("OK"); - assertThat(pool.del("mylist")).isEqualTo(1); + void listRPushRPop() { + assertThat(pool.rpush("right", "first")).isEqualTo(1); + assertThat(pool.llen("right")).isEqualTo(1); + assertThat(pool.rpop("right")).isEqualTo("first"); + assertThat(pool.llen("right")).isZero(); + pool.del("right"); + assertThat(pool.exists("right")).isFalse(); } - private static int findFreePort() { - int port = 0; - try (ServerSocket socket = new ServerSocket()) { - // Allow direct reuse of port after closing the socket. - socket.setReuseAddress(true); - socket.bind(new InetSocketAddress("localhost", 0)); - port = socket.getLocalPort(); - } catch (IOException ignored) { - } - if (port > 0) { - return port; - } - throw new RuntimeException("Could not find a free port"); + @Test + void listKeyWithMultipleValues() { + assertThat(pool.lpush("test", "first")).isEqualTo(1); + assertThat(pool.lpush("test", "second")).isEqualTo(1); //This is wrong + assertThat(pool.llen("test")).isEqualTo(2); + assertThat(pool.lpush("test", "third", "fourth")).isEqualTo(2); + assertThat(pool.llen("test")).isEqualTo(4); + assertThat(pool.rpush("test", "fifth", "sixth")).isEqualTo(2); + assertThat(pool.llen("test")).isEqualTo(6); + + pool.del("test"); + assertThat(pool.exists("right")).isFalse(); } + +// @Test +// void unknownCommand() { +// try (Socket socket = new Socket("localhost", port)) { +// // socket.setSoTimeout(3000); +// socket.getOutputStream().write("helloworld key value\r\n".getBytes(StandardCharsets.UTF_8)); +// BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(socket.getInputStream())); +//// assertThat(bufferedReader.readLine()).isEqualTo("-ERR unknown command 'helloworld', with args beginning with: 'key' 'value' "); +// assertThat(bufferedReader.readLine()).isEqualTo("-ERR unknown command"); +// } catch (IOException e) { +// throw new RuntimeException(e); +// } +// } } From fd999ebd274906d8b19da942255029df748d73c8 Mon Sep 17 00:00:00 2001 From: Martin Blomberg Date: Fri, 24 Feb 2023 15:11:32 +0100 Subject: [PATCH 06/27] Create HazeExtension for running integration tests --- pom.xml | 3 +- .../haze/integration/HazeExtension.java | 55 +++++++++++++++++++ .../haze/{ => integration}/HazeIT.java | 35 ++---------- .../org/fungover/haze/integration/Pool.java | 9 +++ 4 files changed, 72 insertions(+), 30 deletions(-) create mode 100644 src/test/java/org/fungover/haze/integration/HazeExtension.java rename src/test/java/org/fungover/haze/{ => integration}/HazeIT.java (81%) create mode 100644 src/test/java/org/fungover/haze/integration/Pool.java diff --git a/pom.xml b/pom.xml index 210fa7bb..6e14f700 100644 --- a/pom.xml +++ b/pom.xml @@ -194,7 +194,8 @@ copy-dependencies - test + + pre-integration-test copy-dependencies diff --git a/src/test/java/org/fungover/haze/integration/HazeExtension.java b/src/test/java/org/fungover/haze/integration/HazeExtension.java new file mode 100644 index 00000000..88a45c30 --- /dev/null +++ b/src/test/java/org/fungover/haze/integration/HazeExtension.java @@ -0,0 +1,55 @@ +package org.fungover.haze.integration; + +import org.junit.jupiter.api.extension.AfterAllCallback; +import org.junit.jupiter.api.extension.BeforeAllCallback; +import org.junit.jupiter.api.extension.BeforeEachCallback; +import org.junit.jupiter.api.extension.ExtensionContext; +import org.testcontainers.containers.GenericContainer; +import org.testcontainers.images.builder.ImageFromDockerfile; +import redis.clients.jedis.JedisPooled; + +import java.lang.reflect.Field; +import java.nio.file.Path; +import java.util.List; + +public class HazeExtension implements BeforeAllCallback, AfterAllCallback, BeforeEachCallback { + + private GenericContainer haze; + private JedisPooled pool; + + @Override + public void beforeAll(ExtensionContext extensionContext) throws Exception { + haze = new GenericContainer<>(new ImageFromDockerfile() + .withDockerfile(Path.of("./Dockerfile"))) + .withExposedPorts(6379); + haze.start(); + pool = new JedisPooled(haze.getHost(), haze.getFirstMappedPort()); + } + + @Override + public void afterAll(ExtensionContext context) { + // do nothing, Testcontainers handles container shutdown + if (pool != null) + pool.close(); + } + + @Override + public void beforeEach(ExtensionContext extensionContext) throws Exception { + + // Get the list of test instances (instances of test classes) + final List testInstances = + extensionContext.getRequiredTestInstances().getAllInstances(); + + testInstances.forEach((ti) -> { + for (Field field : ti.getClass().getDeclaredFields()) { + if (field.isAnnotationPresent(Pool.class)) { + try { + field.set(ti, pool); + } catch (IllegalAccessException e) { + throw new RuntimeException(e); + } + } + } + }); + } +} diff --git a/src/test/java/org/fungover/haze/HazeIT.java b/src/test/java/org/fungover/haze/integration/HazeIT.java similarity index 81% rename from src/test/java/org/fungover/haze/HazeIT.java rename to src/test/java/org/fungover/haze/integration/HazeIT.java index ae930553..aab6be54 100644 --- a/src/test/java/org/fungover/haze/HazeIT.java +++ b/src/test/java/org/fungover/haze/integration/HazeIT.java @@ -1,43 +1,19 @@ -package org.fungover.haze; +package org.fungover.haze.integration; -import org.junit.jupiter.api.AfterEach; -import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; -import org.testcontainers.containers.GenericContainer; -import org.testcontainers.images.builder.ImageFromDockerfile; -import org.testcontainers.junit.jupiter.Container; -import org.testcontainers.junit.jupiter.Testcontainers; +import org.junit.jupiter.api.extension.ExtendWith; import redis.clients.jedis.JedisPooled; import redis.clients.jedis.Protocol; import redis.clients.jedis.util.SafeEncoder; -import java.nio.file.Path; - import static org.assertj.core.api.Assertions.assertThat; +@ExtendWith(HazeExtension.class) +public class HazeIT { -@Testcontainers -class HazeIT { - - @Container - public GenericContainer haze = new GenericContainer(new ImageFromDockerfile() - .withDockerfile(Path.of("./Dockerfile"))) - .withExposedPorts(6379); - + @Pool JedisPooled pool; - @BeforeEach - void createPool() { - String address = haze.getHost(); - Integer port = haze.getFirstMappedPort(); - pool = new JedisPooled(address, port); - } - - @AfterEach - void closePool() { - pool.close(); - } - @Test void pingPong() { //Simple PING command with no message should return PONG as simple string @@ -112,6 +88,7 @@ void listKeyWithMultipleValues() { assertThat(pool.exists("right")).isFalse(); } + // @Test // void unknownCommand() { // try (Socket socket = new Socket("localhost", port)) { diff --git a/src/test/java/org/fungover/haze/integration/Pool.java b/src/test/java/org/fungover/haze/integration/Pool.java new file mode 100644 index 00000000..f264d017 --- /dev/null +++ b/src/test/java/org/fungover/haze/integration/Pool.java @@ -0,0 +1,9 @@ +package org.fungover.haze.integration; + +import java.lang.annotation.*; + +@Documented +@Target(ElementType.FIELD) +@Retention(RetentionPolicy.RUNTIME) +public @interface Pool { +} From 03f94b0bf9610a69b042e48b8eb2c8554733954c Mon Sep 17 00:00:00 2001 From: Martin Blomberg Date: Fri, 24 Feb 2023 16:32:28 +0100 Subject: [PATCH 07/27] Add dependency for slf4j-nop When running tests testcontainers uses slf4j to do logging. Without an implementation an error message will be printed. --- pom.xml | 12 ++++++------ .../java/org/fungover/haze/integration/HazeIT.java | 7 +++---- 2 files changed, 9 insertions(+), 10 deletions(-) diff --git a/pom.xml b/pom.xml index 6e14f700..a7ef82e2 100644 --- a/pom.xml +++ b/pom.xml @@ -54,12 +54,6 @@ 4.3.1 test - - org.awaitility - awaitility - 4.2.0 - test - org.testcontainers testcontainers @@ -72,6 +66,12 @@ 1.17.6 test + + org.slf4j + slf4j-nop + 1.7.36 + test + diff --git a/src/test/java/org/fungover/haze/integration/HazeIT.java b/src/test/java/org/fungover/haze/integration/HazeIT.java index aab6be54..5107a969 100644 --- a/src/test/java/org/fungover/haze/integration/HazeIT.java +++ b/src/test/java/org/fungover/haze/integration/HazeIT.java @@ -77,18 +77,17 @@ void listRPushRPop() { @Test void listKeyWithMultipleValues() { assertThat(pool.lpush("test", "first")).isEqualTo(1); - assertThat(pool.lpush("test", "second")).isEqualTo(1); //This is wrong + assertThat(pool.lpush("test", "second")).isEqualTo(2); assertThat(pool.llen("test")).isEqualTo(2); - assertThat(pool.lpush("test", "third", "fourth")).isEqualTo(2); + assertThat(pool.lpush("test", "third", "fourth")).isEqualTo(4); assertThat(pool.llen("test")).isEqualTo(4); - assertThat(pool.rpush("test", "fifth", "sixth")).isEqualTo(2); + assertThat(pool.rpush("test", "fifth", "sixth")).isEqualTo(6); assertThat(pool.llen("test")).isEqualTo(6); pool.del("test"); assertThat(pool.exists("right")).isFalse(); } - // @Test // void unknownCommand() { // try (Socket socket = new Socket("localhost", port)) { From fee0107f2d591b5c9486db5cc522c945529a3da1 Mon Sep 17 00:00:00 2001 From: Martin Blomberg Date: Sat, 25 Feb 2023 19:55:03 +0100 Subject: [PATCH 08/27] Update Dockerfile to download dependencies from internet --- Dockerfile | 16 +++++-- pom.xml | 46 +++++++++++-------- .../org/fungover/haze/integration/HazeIT.java | 2 + 3 files changed, 41 insertions(+), 23 deletions(-) diff --git a/Dockerfile b/Dockerfile index ba38162e..8adf8db4 100644 --- a/Dockerfile +++ b/Dockerfile @@ -1,6 +1,16 @@ FROM eclipse-temurin:19-jre-jammy -COPY target/dependency /lib -COPY target/classes /app +#COPY target/dependency /lib WORKDIR /app +ARG USERNAME=hazeuser +ARG USER_UID=1000 +ARG USER_GID=$USER_UID +RUN groupadd --gid $USER_GID $USERNAME && \ + useradd --uid $USER_UID --gid $USER_GID -m $USERNAME +ADD https://repo1.maven.org/maven2/org/apache/logging/log4j/log4j-core/2.20.0/log4j-core-2.20.0.jar ./lib/ +ADD https://repo1.maven.org/maven2/org/apache/logging/log4j/log4j-api/2.20.0/log4j-api-2.20.0.jar ./lib/ +#RUN chmod --recursive 440 ./lib/ +COPY target/classes . +RUN chown --recursive $USERNAME:$USERNAME . +USER $USERNAME EXPOSE 6379 -ENTRYPOINT ["java","-cp" , "/app:/lib/*", "--enable-preview", "org.fungover.haze.Main"] +ENTRYPOINT ["java","-cp","/app:/app/lib/*","--enable-preview","org.fungover.haze.Main"] diff --git a/pom.xml b/pom.xml index a7ef82e2..e749a7ab 100644 --- a/pom.xml +++ b/pom.xml @@ -41,12 +41,12 @@ org.apache.logging.log4j log4j-api - 2.19.0 + 2.20.0 org.apache.logging.log4j log4j-core - 2.19.0 + 2.20.0 redis.clients @@ -72,6 +72,12 @@ 1.7.36 test + + + + + + @@ -187,24 +193,24 @@ @{argLine} --enable-preview - - org.apache.maven.plugins - maven-dependency-plugin - 3.5.0 - - - copy-dependencies - - pre-integration-test - - copy-dependencies - - - runtime - - - - + + + + + + + + + + + + + + + + + + diff --git a/src/test/java/org/fungover/haze/integration/HazeIT.java b/src/test/java/org/fungover/haze/integration/HazeIT.java index 5107a969..5b261876 100644 --- a/src/test/java/org/fungover/haze/integration/HazeIT.java +++ b/src/test/java/org/fungover/haze/integration/HazeIT.java @@ -1,5 +1,6 @@ package org.fungover.haze.integration; +import org.junit.jupiter.api.Disabled; import org.junit.jupiter.api.Test; import org.junit.jupiter.api.extension.ExtendWith; import redis.clients.jedis.JedisPooled; @@ -75,6 +76,7 @@ void listRPushRPop() { } @Test + @Disabled void listKeyWithMultipleValues() { assertThat(pool.lpush("test", "first")).isEqualTo(1); assertThat(pool.lpush("test", "second")).isEqualTo(2); From f3117c8f82538af2a1c53bc3793ee36090cc1d79 Mon Sep 17 00:00:00 2001 From: Martin Blomberg Date: Sat, 4 Mar 2023 15:32:48 +0100 Subject: [PATCH 09/27] Update tests to work with the latest code --- src/test/java/org/fungover/haze/MainTest.java | 2 +- src/test/java/org/fungover/haze/integration/HazeIT.java | 2 -- 2 files changed, 1 insertion(+), 3 deletions(-) diff --git a/src/test/java/org/fungover/haze/MainTest.java b/src/test/java/org/fungover/haze/MainTest.java index 67933883..a8dd8e7d 100644 --- a/src/test/java/org/fungover/haze/MainTest.java +++ b/src/test/java/org/fungover/haze/MainTest.java @@ -21,7 +21,7 @@ void callingExecuteCommandWithValidNonExistingInputReturnsColonOne() { @Test void callingExecuteCommandWithInvalidInputStringReturnsErrorMessage() { - assertThat(Main.executeCommand(database, List.of(""), hazeList)).isEqualTo("-ERR no command provided\r\n"); + assertThat(Main.executeCommand(database, List.of(""), hazeList)).isEqualTo("-ERR unknown command\r\n"); } diff --git a/src/test/java/org/fungover/haze/integration/HazeIT.java b/src/test/java/org/fungover/haze/integration/HazeIT.java index 5b261876..5107a969 100644 --- a/src/test/java/org/fungover/haze/integration/HazeIT.java +++ b/src/test/java/org/fungover/haze/integration/HazeIT.java @@ -1,6 +1,5 @@ package org.fungover.haze.integration; -import org.junit.jupiter.api.Disabled; import org.junit.jupiter.api.Test; import org.junit.jupiter.api.extension.ExtendWith; import redis.clients.jedis.JedisPooled; @@ -76,7 +75,6 @@ void listRPushRPop() { } @Test - @Disabled void listKeyWithMultipleValues() { assertThat(pool.lpush("test", "first")).isEqualTo(1); assertThat(pool.lpush("test", "second")).isEqualTo(2); From 736579f975705965a16dabe520bb4e36a85c0745 Mon Sep 17 00:00:00 2001 From: Martin Blomberg Date: Sat, 4 Mar 2023 16:01:29 +0100 Subject: [PATCH 10/27] Disable generation of jar file, not needed. --- pom.xml | 28 ++++++++++------------------ 1 file changed, 10 insertions(+), 18 deletions(-) diff --git a/pom.xml b/pom.xml index e749a7ab..477480bf 100644 --- a/pom.xml +++ b/pom.xml @@ -125,6 +125,16 @@ org.apache.maven.plugins maven-jar-plugin 3.3.0 + + + default-jar + none + + unwanted + unwanted + + + org.apache.maven.plugins @@ -193,24 +203,6 @@ @{argLine} --enable-preview - - - - - - - - - - - - - - - - - - From d8e3c2436e0eac1c60427230bb2b39d584bc3881 Mon Sep 17 00:00:00 2001 From: Martin Blomberg Date: Sat, 4 Mar 2023 16:10:56 +0100 Subject: [PATCH 11/27] Update release.yml to run Integration tests Before building new docker images during release integration tests will be run. The command is now mvn -B verify. --- .github/workflows/release.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 1ec9e9e8..b0963335 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -26,7 +26,7 @@ jobs: cache: maven - name: Compile and test with Maven - run: mvn -B test --file pom.xml + run: mvn -B verify --file pom.xml - name: Set up QEMU uses: docker/setup-qemu-action@v2 From 6a0375eeb084fde0cacac6f0b91630b8de49c3c5 Mon Sep 17 00:00:00 2001 From: Martin Blomberg Date: Sat, 4 Mar 2023 16:42:10 +0100 Subject: [PATCH 12/27] Fix code smells. --- pom.xml | 6 ------ .../org/fungover/haze/integration/HazeIT.java | 15 +-------------- 2 files changed, 1 insertion(+), 20 deletions(-) diff --git a/pom.xml b/pom.xml index 2ca44640..2e534243 100644 --- a/pom.xml +++ b/pom.xml @@ -72,12 +72,6 @@ 1.7.36 test - - - - - - diff --git a/src/test/java/org/fungover/haze/integration/HazeIT.java b/src/test/java/org/fungover/haze/integration/HazeIT.java index 5107a969..c5bae8b0 100644 --- a/src/test/java/org/fungover/haze/integration/HazeIT.java +++ b/src/test/java/org/fungover/haze/integration/HazeIT.java @@ -9,7 +9,7 @@ import static org.assertj.core.api.Assertions.assertThat; @ExtendWith(HazeExtension.class) -public class HazeIT { +class HazeIT { @Pool JedisPooled pool; @@ -87,17 +87,4 @@ void listKeyWithMultipleValues() { pool.del("test"); assertThat(pool.exists("right")).isFalse(); } - -// @Test -// void unknownCommand() { -// try (Socket socket = new Socket("localhost", port)) { -// // socket.setSoTimeout(3000); -// socket.getOutputStream().write("helloworld key value\r\n".getBytes(StandardCharsets.UTF_8)); -// BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(socket.getInputStream())); -//// assertThat(bufferedReader.readLine()).isEqualTo("-ERR unknown command 'helloworld', with args beginning with: 'key' 'value' "); -// assertThat(bufferedReader.readLine()).isEqualTo("-ERR unknown command"); -// } catch (IOException e) { -// throw new RuntimeException(e); -// } -// } } From 8d52331fc8c43c55e525c72dcba695ea6f651749 Mon Sep 17 00:00:00 2001 From: Martin Blomberg Date: Sun, 12 Feb 2023 21:59:24 +0100 Subject: [PATCH 13/27] Add HazeIT.java Integration tests that starts the server on a random free port. Tests for the following commands: PING - PONG SETNX SET - GET DELETE EXISTS Error for not implemented command --- pom.xml | 6 ++ src/test/java/org/fungover/haze/HazeIT.java | 104 ++++++++++++++++++++ 2 files changed, 110 insertions(+) create mode 100644 src/test/java/org/fungover/haze/HazeIT.java diff --git a/pom.xml b/pom.xml index fb2f65de..5e95c742 100644 --- a/pom.xml +++ b/pom.xml @@ -48,6 +48,12 @@ log4j-core 2.20.0 + + redis.clients + jedis + 4.3.1 + test + diff --git a/src/test/java/org/fungover/haze/HazeIT.java b/src/test/java/org/fungover/haze/HazeIT.java new file mode 100644 index 00000000..f0655988 --- /dev/null +++ b/src/test/java/org/fungover/haze/HazeIT.java @@ -0,0 +1,104 @@ +package org.fungover.haze; + +import org.junit.jupiter.api.AfterAll; +import org.junit.jupiter.api.BeforeAll; +import org.junit.jupiter.api.Test; +import redis.clients.jedis.JedisPooled; +import redis.clients.jedis.Protocol; +import redis.clients.jedis.util.SafeEncoder; + +import java.io.BufferedReader; +import java.io.IOException; +import java.io.InputStreamReader; +import java.net.ServerSocket; +import java.net.Socket; +import java.nio.charset.StandardCharsets; + +import static org.assertj.core.api.Assertions.assertThat; + +public class HazeIT { + + static Process pro; + static JedisPooled pool; + static int port; + + @BeforeAll + static void startServer() throws IOException { + port = findFreePort(); + System.out.println(port); + String[] command = {"java", "--enable-preview", "-cp", "target/classes", "org.fungover.haze.Main", "--port", String.valueOf(port)}; + pro = Runtime.getRuntime().exec(command); + pool = new JedisPooled("localhost", port); + } + + @AfterAll + static void stopServer() throws InterruptedException { + pool.close(); + pro.destroy(); + pro.waitFor(); + System.out.println("exitValue() " + pro.exitValue()); + } + + @Test + void pingPong() { + //Simple PING command with no message should return PONG as simple string + var result = pool.sendCommand(Protocol.Command.PING); + assertThat(SafeEncoder.encode((byte[]) result)).isEqualTo("PONG"); + //PING with message argument should return bulk string with the argument + result = pool.sendCommand(Protocol.Command.PING, "HELLO"); + assertThat(SafeEncoder.encode((byte[]) result)).isEqualTo("HELLO"); + //PING with message argument containing space should return bulk string with the argument + result = pool.sendCommand(Protocol.Command.PING, "HELLO\r\n There"); + assertThat(SafeEncoder.encode((byte[]) result)).isEqualTo("HELLO\r\n There"); + } + + @Test + void setNx() { + //Remove keys before trying this + pool.del("test", "test1"); + assertThat(pool.setnx("test", "test")).isEqualTo(1); + assertThat(pool.setnx("test1", "test")).isEqualTo(1); + //Key test already exists so should not be set + assertThat(pool.setnx("test", "test1")).isEqualTo(0); + } + + @Test + void setGet() { + assertThat(pool.set("test", "test")).isEqualTo("OK"); + assertThat(pool.get("test")).isEqualTo("test"); + } + + @Test + void exists() { + assertThat(pool.set("test", "test")).isEqualTo("OK"); + assertThat(pool.exists("test")).isTrue(); + pool.del("notused"); + assertThat(pool.exists("notused")).isFalse(); + } + + @Test + void unknownCommand() { + try (Socket socket = new Socket("localhost", port)) { + socket.setSoTimeout(3000); + socket.getOutputStream().write("helloworld key value\r\n".getBytes(StandardCharsets.UTF_8)); + BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(socket.getInputStream())); + assertThat(bufferedReader.readLine()).isEqualTo("-ERR unknown command 'helloworld', with args beginning with: 'key' 'value' "); + } catch (IOException e) { + throw new RuntimeException(e); + } + } + + private static int findFreePort() { + int port = 0; + try (ServerSocket socket = new ServerSocket(0)) { + // Disable timeout and reuse address after closing the socket. + socket.setReuseAddress(true); + port = socket.getLocalPort(); + } catch (IOException ignored) { + } + if (port > 0) { + return port; + } + throw new RuntimeException("Could not find a free port"); + } +} From 565f7565e25250ccfcd0b0f3ebf9edc2ddd825e9 Mon Sep 17 00:00:00 2001 From: Martin Blomberg Date: Mon, 13 Feb 2023 17:03:55 +0100 Subject: [PATCH 14/27] Update findFreePort method Change initialization of ServerSocket setReuseAddress true to happen before binding. Otherwise, the reuse address option doesn't work. --- pom.xml | 6 +++++ src/test/java/org/fungover/haze/HazeIT.java | 29 +++++++++++++++++---- 2 files changed, 30 insertions(+), 5 deletions(-) diff --git a/pom.xml b/pom.xml index 5e95c742..08b73d5f 100644 --- a/pom.xml +++ b/pom.xml @@ -54,6 +54,12 @@ 4.3.1 test + + org.awaitility + awaitility + 4.2.0 + test + diff --git a/src/test/java/org/fungover/haze/HazeIT.java b/src/test/java/org/fungover/haze/HazeIT.java index f0655988..0d22ca5e 100644 --- a/src/test/java/org/fungover/haze/HazeIT.java +++ b/src/test/java/org/fungover/haze/HazeIT.java @@ -10,13 +10,17 @@ import java.io.BufferedReader; import java.io.IOException; import java.io.InputStreamReader; +import java.net.InetSocketAddress; import java.net.ServerSocket; import java.net.Socket; import java.nio.charset.StandardCharsets; +import java.util.concurrent.Callable; +import static java.util.concurrent.TimeUnit.SECONDS; import static org.assertj.core.api.Assertions.assertThat; +import static org.awaitility.Awaitility.await; -public class HazeIT { +class HazeIT { static Process pro; static JedisPooled pool; @@ -24,13 +28,27 @@ public class HazeIT { @BeforeAll static void startServer() throws IOException { + var pathSep = System.getProperty("path.separator"); port = findFreePort(); System.out.println(port); - String[] command = {"java", "--enable-preview", "-cp", "target/classes", "org.fungover.haze.Main", "--port", String.valueOf(port)}; + String[] command = {"java", "--enable-preview", "-cp", "target/classes" + pathSep + "target/dependency/*", "org.fungover.haze.Main", "--port", String.valueOf(port)}; pro = Runtime.getRuntime().exec(command); + + await().atMost(10, SECONDS).until(serverIsUp()); + pool = new JedisPooled("localhost", port); } + private static Callable serverIsUp() { + return () -> { + try (Socket socket = new Socket("localhost", port)) { + return true; + } catch (IOException e) { + return false; + } + }; // The condition that must be fulfilled + } + @AfterAll static void stopServer() throws InterruptedException { pool.close(); @@ -59,7 +77,7 @@ void setNx() { assertThat(pool.setnx("test", "test")).isEqualTo(1); assertThat(pool.setnx("test1", "test")).isEqualTo(1); //Key test already exists so should not be set - assertThat(pool.setnx("test", "test1")).isEqualTo(0); + assertThat(pool.setnx("test", "test1")).isZero(); } @Test @@ -90,9 +108,10 @@ void unknownCommand() { private static int findFreePort() { int port = 0; - try (ServerSocket socket = new ServerSocket(0)) { - // Disable timeout and reuse address after closing the socket. + try (ServerSocket socket = new ServerSocket()) { + // Allow direct reuse of port after closing the socket. socket.setReuseAddress(true); + socket.bind(new InetSocketAddress("localhost", 0)); port = socket.getLocalPort(); } catch (IOException ignored) { } From 47efedaa964442b4167183dca19b5e44ca86bb50 Mon Sep 17 00:00:00 2001 From: Martin Blomberg Date: Sat, 18 Feb 2023 09:47:59 +0100 Subject: [PATCH 15/27] Remove IT testcode not working with current server impl. --- src/test/java/org/fungover/haze/HazeIT.java | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/src/test/java/org/fungover/haze/HazeIT.java b/src/test/java/org/fungover/haze/HazeIT.java index 0d22ca5e..8af9de08 100644 --- a/src/test/java/org/fungover/haze/HazeIT.java +++ b/src/test/java/org/fungover/haze/HazeIT.java @@ -66,14 +66,12 @@ void pingPong() { result = pool.sendCommand(Protocol.Command.PING, "HELLO"); assertThat(SafeEncoder.encode((byte[]) result)).isEqualTo("HELLO"); //PING with message argument containing space should return bulk string with the argument - result = pool.sendCommand(Protocol.Command.PING, "HELLO\r\n There"); - assertThat(SafeEncoder.encode((byte[]) result)).isEqualTo("HELLO\r\n There"); + // result = pool.sendCommand(Protocol.Command.PING, "HELLO\r\n There"); + // assertThat(SafeEncoder.encode((byte[]) result)).isEqualTo("HELLO\r\n There"); } @Test void setNx() { - //Remove keys before trying this - pool.del("test", "test1"); assertThat(pool.setnx("test", "test")).isEqualTo(1); assertThat(pool.setnx("test1", "test")).isEqualTo(1); //Key test already exists so should not be set @@ -84,6 +82,7 @@ void setNx() { void setGet() { assertThat(pool.set("test", "test")).isEqualTo("OK"); assertThat(pool.get("test")).isEqualTo("test"); + pool.del("test"); } @Test @@ -100,7 +99,8 @@ void unknownCommand() { socket.setSoTimeout(3000); socket.getOutputStream().write("helloworld key value\r\n".getBytes(StandardCharsets.UTF_8)); BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(socket.getInputStream())); - assertThat(bufferedReader.readLine()).isEqualTo("-ERR unknown command 'helloworld', with args beginning with: 'key' 'value' "); +// assertThat(bufferedReader.readLine()).isEqualTo("-ERR unknown command 'helloworld', with args beginning with: 'key' 'value' "); + assertThat(bufferedReader.readLine()).isEqualTo("-ERR unknown command"); } catch (IOException e) { throw new RuntimeException(e); } From b4499c9a959a6b109bb16140d40095d28dea8f85 Mon Sep 17 00:00:00 2001 From: Martin Blomberg Date: Tue, 21 Feb 2023 21:23:13 +0100 Subject: [PATCH 16/27] Add Integration test for list --- src/test/java/org/fungover/haze/HazeIT.java | 18 ++++++++++++++++-- 1 file changed, 16 insertions(+), 2 deletions(-) diff --git a/src/test/java/org/fungover/haze/HazeIT.java b/src/test/java/org/fungover/haze/HazeIT.java index 8af9de08..75dbadb7 100644 --- a/src/test/java/org/fungover/haze/HazeIT.java +++ b/src/test/java/org/fungover/haze/HazeIT.java @@ -66,8 +66,8 @@ void pingPong() { result = pool.sendCommand(Protocol.Command.PING, "HELLO"); assertThat(SafeEncoder.encode((byte[]) result)).isEqualTo("HELLO"); //PING with message argument containing space should return bulk string with the argument - // result = pool.sendCommand(Protocol.Command.PING, "HELLO\r\n There"); - // assertThat(SafeEncoder.encode((byte[]) result)).isEqualTo("HELLO\r\n There"); + // result = pool.sendCommand(Protocol.Command.PING, "HELLO\r\n There"); + // assertThat(SafeEncoder.encode((byte[]) result)).isEqualTo("HELLO\r\n There"); } @Test @@ -106,6 +106,20 @@ void unknownCommand() { } } + @Test + void listMethods() { + assertThat(pool.lpush("mylist", "third")).isEqualTo(1); + assertThat(pool.llen("mylist")).isEqualTo(1); + assertThat(pool.lpush("mylist", "second","first")).isEqualTo(3); + assertThat(pool.llen("mylist")).isEqualTo(3); + assertThat(pool.lpop("mylist")).isEqualTo("first"); + assertThat(pool.llen("mylist")).isEqualTo(2); + assertThat(pool.rpush("mylist", "last")).isEqualTo(3); + assertThat(pool.rpop("mylist")).isEqualTo("last"); + assertThat(pool.lset("mylist",0, "test")).isEqualTo("OK"); + assertThat(pool.del("mylist")).isEqualTo(1); + } + private static int findFreePort() { int port = 0; try (ServerSocket socket = new ServerSocket()) { From da4b919958838c4d02c0459338c3a820a38f8f77 Mon Sep 17 00:00:00 2001 From: Martin Blomberg Date: Wed, 22 Feb 2023 20:28:42 +0100 Subject: [PATCH 17/27] Change HazeIT to use testcontainers --- pom.xml | 12 ++ src/main/java/org/fungover/haze/Main.java | 20 +-- src/test/java/org/fungover/haze/HazeIT.java | 138 +++++++++----------- 3 files changed, 82 insertions(+), 88 deletions(-) diff --git a/pom.xml b/pom.xml index 08b73d5f..cd1bbd04 100644 --- a/pom.xml +++ b/pom.xml @@ -60,6 +60,18 @@ 4.2.0 test + + org.testcontainers + testcontainers + 1.17.6 + test + + + org.testcontainers + junit-jupiter + 1.17.6 + test + diff --git a/src/main/java/org/fungover/haze/Main.java b/src/main/java/org/fungover/haze/Main.java index d52c2446..05a9344e 100644 --- a/src/main/java/org/fungover/haze/Main.java +++ b/src/main/java/org/fungover/haze/Main.java @@ -9,6 +9,7 @@ import java.net.InetSocketAddress; import java.net.ServerSocket; import java.net.Socket; +import java.nio.charset.StandardCharsets; import java.util.ArrayList; import java.util.Arrays; import java.util.List; @@ -35,7 +36,6 @@ public static void main(String[] args) { serverSocket.bind(new InetSocketAddress(initialize.getPort())); while (serverOpen) { var client = serverSocket.accept(); - logger.info("Application started: serverSocket.accept()"); Runnable newThread = () -> { try { @@ -45,19 +45,16 @@ public static void main(String[] args) { List inputList = new ArrayList<>(); String firstReading = input.readLine(); + logger.debug(firstReading); readInputStream(input, inputList, firstReading); clientAuthenticated = authenticateClient(auth, isPasswordSet, client, inputList, clientAuthenticated); - client.getOutputStream().write(executeCommand(hazeDatabase, inputList, hazeList).getBytes()); - - inputList.forEach(System.out::println); // For checking incoming message - - printThreadDebug(); + client.getOutputStream().write(executeCommand(hazeDatabase, inputList, hazeList).getBytes(StandardCharsets.UTF_8)); + client.getOutputStream().flush(); inputList.clear(); } - } catch (IOException e) { logger.error(e); } @@ -75,14 +72,9 @@ private static void shutdown(HazeDatabase hazeDatabase) { logger.info("Shutting down...."); } - private static void printThreadDebug() { - logger.debug("ThreadID {}", () -> Thread.currentThread().threadId()); // Only for Debug - logger.debug("Is virtual Thread {}", () -> Thread.currentThread().isVirtual()); // Only for Debug - } - public static String executeCommand(HazeDatabase hazeDatabase, List inputList, HazeList hazeList) { if (inputList.isEmpty() || inputList.get(0).isEmpty()) { - return "-ERR no command provided\r\n"; + return "-ERR unknown command\r\n"; } logger.debug("executeCommand: {} {} ", () -> hazeDatabase, () -> inputList); @@ -118,7 +110,7 @@ public static String executeCommand(HazeDatabase hazeDatabase, List inpu private static void readInputStream(BufferedReader input, List inputList, String firstReading) throws IOException { - logger.debug("readInputStream: {} {} {}", () -> input, () -> inputList, () -> firstReading); + logger.debug("readInputStream: {} {}", () -> inputList, () -> firstReading); int size; if (firstReading.startsWith("*")) { size = Integer.parseInt(firstReading.substring(1)) * 2; diff --git a/src/test/java/org/fungover/haze/HazeIT.java b/src/test/java/org/fungover/haze/HazeIT.java index 75dbadb7..ae930553 100644 --- a/src/test/java/org/fungover/haze/HazeIT.java +++ b/src/test/java/org/fungover/haze/HazeIT.java @@ -1,60 +1,41 @@ package org.fungover.haze; -import org.junit.jupiter.api.AfterAll; -import org.junit.jupiter.api.BeforeAll; +import org.junit.jupiter.api.AfterEach; +import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; +import org.testcontainers.containers.GenericContainer; +import org.testcontainers.images.builder.ImageFromDockerfile; +import org.testcontainers.junit.jupiter.Container; +import org.testcontainers.junit.jupiter.Testcontainers; import redis.clients.jedis.JedisPooled; import redis.clients.jedis.Protocol; import redis.clients.jedis.util.SafeEncoder; -import java.io.BufferedReader; -import java.io.IOException; -import java.io.InputStreamReader; -import java.net.InetSocketAddress; -import java.net.ServerSocket; -import java.net.Socket; -import java.nio.charset.StandardCharsets; -import java.util.concurrent.Callable; +import java.nio.file.Path; -import static java.util.concurrent.TimeUnit.SECONDS; import static org.assertj.core.api.Assertions.assertThat; -import static org.awaitility.Awaitility.await; -class HazeIT { - static Process pro; - static JedisPooled pool; - static int port; +@Testcontainers +class HazeIT { - @BeforeAll - static void startServer() throws IOException { - var pathSep = System.getProperty("path.separator"); - port = findFreePort(); - System.out.println(port); - String[] command = {"java", "--enable-preview", "-cp", "target/classes" + pathSep + "target/dependency/*", "org.fungover.haze.Main", "--port", String.valueOf(port)}; - pro = Runtime.getRuntime().exec(command); + @Container + public GenericContainer haze = new GenericContainer(new ImageFromDockerfile() + .withDockerfile(Path.of("./Dockerfile"))) + .withExposedPorts(6379); - await().atMost(10, SECONDS).until(serverIsUp()); + JedisPooled pool; - pool = new JedisPooled("localhost", port); + @BeforeEach + void createPool() { + String address = haze.getHost(); + Integer port = haze.getFirstMappedPort(); + pool = new JedisPooled(address, port); } - private static Callable serverIsUp() { - return () -> { - try (Socket socket = new Socket("localhost", port)) { - return true; - } catch (IOException e) { - return false; - } - }; // The condition that must be fulfilled - } - - @AfterAll - static void stopServer() throws InterruptedException { + @AfterEach + void closePool() { pool.close(); - pro.destroy(); - pro.waitFor(); - System.out.println("exitValue() " + pro.exitValue()); } @Test @@ -72,10 +53,14 @@ void pingPong() { @Test void setNx() { + pool.del("test"); + pool.del("test1"); assertThat(pool.setnx("test", "test")).isEqualTo(1); assertThat(pool.setnx("test1", "test")).isEqualTo(1); //Key test already exists so should not be set assertThat(pool.setnx("test", "test1")).isZero(); + pool.del("test"); + pool.del("test1"); } @Test @@ -94,44 +79,49 @@ void exists() { } @Test - void unknownCommand() { - try (Socket socket = new Socket("localhost", port)) { - socket.setSoTimeout(3000); - socket.getOutputStream().write("helloworld key value\r\n".getBytes(StandardCharsets.UTF_8)); - BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(socket.getInputStream())); -// assertThat(bufferedReader.readLine()).isEqualTo("-ERR unknown command 'helloworld', with args beginning with: 'key' 'value' "); - assertThat(bufferedReader.readLine()).isEqualTo("-ERR unknown command"); - } catch (IOException e) { - throw new RuntimeException(e); - } + void listLPushLPop() { + assertThat(pool.lpush("left", "first")).isEqualTo(1); + assertThat(pool.llen("left")).isEqualTo(1); + assertThat(pool.lpop("left")).isEqualTo("first"); + assertThat(pool.llen("left")).isZero(); + pool.del("left"); + assertThat(pool.exists("left")).isFalse(); } @Test - void listMethods() { - assertThat(pool.lpush("mylist", "third")).isEqualTo(1); - assertThat(pool.llen("mylist")).isEqualTo(1); - assertThat(pool.lpush("mylist", "second","first")).isEqualTo(3); - assertThat(pool.llen("mylist")).isEqualTo(3); - assertThat(pool.lpop("mylist")).isEqualTo("first"); - assertThat(pool.llen("mylist")).isEqualTo(2); - assertThat(pool.rpush("mylist", "last")).isEqualTo(3); - assertThat(pool.rpop("mylist")).isEqualTo("last"); - assertThat(pool.lset("mylist",0, "test")).isEqualTo("OK"); - assertThat(pool.del("mylist")).isEqualTo(1); + void listRPushRPop() { + assertThat(pool.rpush("right", "first")).isEqualTo(1); + assertThat(pool.llen("right")).isEqualTo(1); + assertThat(pool.rpop("right")).isEqualTo("first"); + assertThat(pool.llen("right")).isZero(); + pool.del("right"); + assertThat(pool.exists("right")).isFalse(); } - private static int findFreePort() { - int port = 0; - try (ServerSocket socket = new ServerSocket()) { - // Allow direct reuse of port after closing the socket. - socket.setReuseAddress(true); - socket.bind(new InetSocketAddress("localhost", 0)); - port = socket.getLocalPort(); - } catch (IOException ignored) { - } - if (port > 0) { - return port; - } - throw new RuntimeException("Could not find a free port"); + @Test + void listKeyWithMultipleValues() { + assertThat(pool.lpush("test", "first")).isEqualTo(1); + assertThat(pool.lpush("test", "second")).isEqualTo(1); //This is wrong + assertThat(pool.llen("test")).isEqualTo(2); + assertThat(pool.lpush("test", "third", "fourth")).isEqualTo(2); + assertThat(pool.llen("test")).isEqualTo(4); + assertThat(pool.rpush("test", "fifth", "sixth")).isEqualTo(2); + assertThat(pool.llen("test")).isEqualTo(6); + + pool.del("test"); + assertThat(pool.exists("right")).isFalse(); } + +// @Test +// void unknownCommand() { +// try (Socket socket = new Socket("localhost", port)) { +// // socket.setSoTimeout(3000); +// socket.getOutputStream().write("helloworld key value\r\n".getBytes(StandardCharsets.UTF_8)); +// BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(socket.getInputStream())); +//// assertThat(bufferedReader.readLine()).isEqualTo("-ERR unknown command 'helloworld', with args beginning with: 'key' 'value' "); +// assertThat(bufferedReader.readLine()).isEqualTo("-ERR unknown command"); +// } catch (IOException e) { +// throw new RuntimeException(e); +// } +// } } From 2378d657baca1c561c882a0dcb02e2a8d72a3870 Mon Sep 17 00:00:00 2001 From: Martin Blomberg Date: Fri, 24 Feb 2023 15:11:32 +0100 Subject: [PATCH 18/27] Create HazeExtension for running integration tests --- pom.xml | 3 +- .../haze/integration/HazeExtension.java | 55 +++++++++++++++++++ .../haze/{ => integration}/HazeIT.java | 35 ++---------- .../org/fungover/haze/integration/Pool.java | 9 +++ 4 files changed, 72 insertions(+), 30 deletions(-) create mode 100644 src/test/java/org/fungover/haze/integration/HazeExtension.java rename src/test/java/org/fungover/haze/{ => integration}/HazeIT.java (81%) create mode 100644 src/test/java/org/fungover/haze/integration/Pool.java diff --git a/pom.xml b/pom.xml index cd1bbd04..27063ea2 100644 --- a/pom.xml +++ b/pom.xml @@ -194,7 +194,8 @@ copy-dependencies - test + + pre-integration-test copy-dependencies diff --git a/src/test/java/org/fungover/haze/integration/HazeExtension.java b/src/test/java/org/fungover/haze/integration/HazeExtension.java new file mode 100644 index 00000000..88a45c30 --- /dev/null +++ b/src/test/java/org/fungover/haze/integration/HazeExtension.java @@ -0,0 +1,55 @@ +package org.fungover.haze.integration; + +import org.junit.jupiter.api.extension.AfterAllCallback; +import org.junit.jupiter.api.extension.BeforeAllCallback; +import org.junit.jupiter.api.extension.BeforeEachCallback; +import org.junit.jupiter.api.extension.ExtensionContext; +import org.testcontainers.containers.GenericContainer; +import org.testcontainers.images.builder.ImageFromDockerfile; +import redis.clients.jedis.JedisPooled; + +import java.lang.reflect.Field; +import java.nio.file.Path; +import java.util.List; + +public class HazeExtension implements BeforeAllCallback, AfterAllCallback, BeforeEachCallback { + + private GenericContainer haze; + private JedisPooled pool; + + @Override + public void beforeAll(ExtensionContext extensionContext) throws Exception { + haze = new GenericContainer<>(new ImageFromDockerfile() + .withDockerfile(Path.of("./Dockerfile"))) + .withExposedPorts(6379); + haze.start(); + pool = new JedisPooled(haze.getHost(), haze.getFirstMappedPort()); + } + + @Override + public void afterAll(ExtensionContext context) { + // do nothing, Testcontainers handles container shutdown + if (pool != null) + pool.close(); + } + + @Override + public void beforeEach(ExtensionContext extensionContext) throws Exception { + + // Get the list of test instances (instances of test classes) + final List testInstances = + extensionContext.getRequiredTestInstances().getAllInstances(); + + testInstances.forEach((ti) -> { + for (Field field : ti.getClass().getDeclaredFields()) { + if (field.isAnnotationPresent(Pool.class)) { + try { + field.set(ti, pool); + } catch (IllegalAccessException e) { + throw new RuntimeException(e); + } + } + } + }); + } +} diff --git a/src/test/java/org/fungover/haze/HazeIT.java b/src/test/java/org/fungover/haze/integration/HazeIT.java similarity index 81% rename from src/test/java/org/fungover/haze/HazeIT.java rename to src/test/java/org/fungover/haze/integration/HazeIT.java index ae930553..aab6be54 100644 --- a/src/test/java/org/fungover/haze/HazeIT.java +++ b/src/test/java/org/fungover/haze/integration/HazeIT.java @@ -1,43 +1,19 @@ -package org.fungover.haze; +package org.fungover.haze.integration; -import org.junit.jupiter.api.AfterEach; -import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; -import org.testcontainers.containers.GenericContainer; -import org.testcontainers.images.builder.ImageFromDockerfile; -import org.testcontainers.junit.jupiter.Container; -import org.testcontainers.junit.jupiter.Testcontainers; +import org.junit.jupiter.api.extension.ExtendWith; import redis.clients.jedis.JedisPooled; import redis.clients.jedis.Protocol; import redis.clients.jedis.util.SafeEncoder; -import java.nio.file.Path; - import static org.assertj.core.api.Assertions.assertThat; +@ExtendWith(HazeExtension.class) +public class HazeIT { -@Testcontainers -class HazeIT { - - @Container - public GenericContainer haze = new GenericContainer(new ImageFromDockerfile() - .withDockerfile(Path.of("./Dockerfile"))) - .withExposedPorts(6379); - + @Pool JedisPooled pool; - @BeforeEach - void createPool() { - String address = haze.getHost(); - Integer port = haze.getFirstMappedPort(); - pool = new JedisPooled(address, port); - } - - @AfterEach - void closePool() { - pool.close(); - } - @Test void pingPong() { //Simple PING command with no message should return PONG as simple string @@ -112,6 +88,7 @@ void listKeyWithMultipleValues() { assertThat(pool.exists("right")).isFalse(); } + // @Test // void unknownCommand() { // try (Socket socket = new Socket("localhost", port)) { diff --git a/src/test/java/org/fungover/haze/integration/Pool.java b/src/test/java/org/fungover/haze/integration/Pool.java new file mode 100644 index 00000000..f264d017 --- /dev/null +++ b/src/test/java/org/fungover/haze/integration/Pool.java @@ -0,0 +1,9 @@ +package org.fungover.haze.integration; + +import java.lang.annotation.*; + +@Documented +@Target(ElementType.FIELD) +@Retention(RetentionPolicy.RUNTIME) +public @interface Pool { +} From 77de081c252da6a0e8d4e605f63a7f158c1e9c3d Mon Sep 17 00:00:00 2001 From: Martin Blomberg Date: Fri, 24 Feb 2023 16:32:28 +0100 Subject: [PATCH 19/27] Add dependency for slf4j-nop When running tests testcontainers uses slf4j to do logging. Without an implementation an error message will be printed. --- pom.xml | 12 ++++++------ .../java/org/fungover/haze/integration/HazeIT.java | 7 +++---- 2 files changed, 9 insertions(+), 10 deletions(-) diff --git a/pom.xml b/pom.xml index 27063ea2..69c15f51 100644 --- a/pom.xml +++ b/pom.xml @@ -54,12 +54,6 @@ 4.3.1 test - - org.awaitility - awaitility - 4.2.0 - test - org.testcontainers testcontainers @@ -72,6 +66,12 @@ 1.17.6 test + + org.slf4j + slf4j-nop + 1.7.36 + test + diff --git a/src/test/java/org/fungover/haze/integration/HazeIT.java b/src/test/java/org/fungover/haze/integration/HazeIT.java index aab6be54..5107a969 100644 --- a/src/test/java/org/fungover/haze/integration/HazeIT.java +++ b/src/test/java/org/fungover/haze/integration/HazeIT.java @@ -77,18 +77,17 @@ void listRPushRPop() { @Test void listKeyWithMultipleValues() { assertThat(pool.lpush("test", "first")).isEqualTo(1); - assertThat(pool.lpush("test", "second")).isEqualTo(1); //This is wrong + assertThat(pool.lpush("test", "second")).isEqualTo(2); assertThat(pool.llen("test")).isEqualTo(2); - assertThat(pool.lpush("test", "third", "fourth")).isEqualTo(2); + assertThat(pool.lpush("test", "third", "fourth")).isEqualTo(4); assertThat(pool.llen("test")).isEqualTo(4); - assertThat(pool.rpush("test", "fifth", "sixth")).isEqualTo(2); + assertThat(pool.rpush("test", "fifth", "sixth")).isEqualTo(6); assertThat(pool.llen("test")).isEqualTo(6); pool.del("test"); assertThat(pool.exists("right")).isFalse(); } - // @Test // void unknownCommand() { // try (Socket socket = new Socket("localhost", port)) { From becb206fd628af6055851f5b6ea1d7831bc807bb Mon Sep 17 00:00:00 2001 From: Martin Blomberg Date: Sat, 25 Feb 2023 19:55:03 +0100 Subject: [PATCH 20/27] Update Dockerfile to download dependencies from internet --- Dockerfile | 16 +++++-- pom.xml | 42 +++++++++++-------- .../org/fungover/haze/integration/HazeIT.java | 2 + 3 files changed, 39 insertions(+), 21 deletions(-) diff --git a/Dockerfile b/Dockerfile index ba38162e..8adf8db4 100644 --- a/Dockerfile +++ b/Dockerfile @@ -1,6 +1,16 @@ FROM eclipse-temurin:19-jre-jammy -COPY target/dependency /lib -COPY target/classes /app +#COPY target/dependency /lib WORKDIR /app +ARG USERNAME=hazeuser +ARG USER_UID=1000 +ARG USER_GID=$USER_UID +RUN groupadd --gid $USER_GID $USERNAME && \ + useradd --uid $USER_UID --gid $USER_GID -m $USERNAME +ADD https://repo1.maven.org/maven2/org/apache/logging/log4j/log4j-core/2.20.0/log4j-core-2.20.0.jar ./lib/ +ADD https://repo1.maven.org/maven2/org/apache/logging/log4j/log4j-api/2.20.0/log4j-api-2.20.0.jar ./lib/ +#RUN chmod --recursive 440 ./lib/ +COPY target/classes . +RUN chown --recursive $USERNAME:$USERNAME . +USER $USERNAME EXPOSE 6379 -ENTRYPOINT ["java","-cp" , "/app:/lib/*", "--enable-preview", "org.fungover.haze.Main"] +ENTRYPOINT ["java","-cp","/app:/app/lib/*","--enable-preview","org.fungover.haze.Main"] diff --git a/pom.xml b/pom.xml index 69c15f51..965f3848 100644 --- a/pom.xml +++ b/pom.xml @@ -72,6 +72,12 @@ 1.7.36 test + + + + + + @@ -187,24 +193,24 @@ @{argLine} --enable-preview - - org.apache.maven.plugins - maven-dependency-plugin - 3.5.0 - - - copy-dependencies - - pre-integration-test - - copy-dependencies - - - runtime - - - - + + + + + + + + + + + + + + + + + + diff --git a/src/test/java/org/fungover/haze/integration/HazeIT.java b/src/test/java/org/fungover/haze/integration/HazeIT.java index 5107a969..5b261876 100644 --- a/src/test/java/org/fungover/haze/integration/HazeIT.java +++ b/src/test/java/org/fungover/haze/integration/HazeIT.java @@ -1,5 +1,6 @@ package org.fungover.haze.integration; +import org.junit.jupiter.api.Disabled; import org.junit.jupiter.api.Test; import org.junit.jupiter.api.extension.ExtendWith; import redis.clients.jedis.JedisPooled; @@ -75,6 +76,7 @@ void listRPushRPop() { } @Test + @Disabled void listKeyWithMultipleValues() { assertThat(pool.lpush("test", "first")).isEqualTo(1); assertThat(pool.lpush("test", "second")).isEqualTo(2); From 7cbc3c85c7d7d07aff46668fea3a0f3421eff7f1 Mon Sep 17 00:00:00 2001 From: Martin Blomberg Date: Sat, 4 Mar 2023 15:32:48 +0100 Subject: [PATCH 21/27] Update tests to work with the latest code --- src/test/java/org/fungover/haze/MainTest.java | 2 +- src/test/java/org/fungover/haze/integration/HazeIT.java | 2 -- 2 files changed, 1 insertion(+), 3 deletions(-) diff --git a/src/test/java/org/fungover/haze/MainTest.java b/src/test/java/org/fungover/haze/MainTest.java index 67933883..a8dd8e7d 100644 --- a/src/test/java/org/fungover/haze/MainTest.java +++ b/src/test/java/org/fungover/haze/MainTest.java @@ -21,7 +21,7 @@ void callingExecuteCommandWithValidNonExistingInputReturnsColonOne() { @Test void callingExecuteCommandWithInvalidInputStringReturnsErrorMessage() { - assertThat(Main.executeCommand(database, List.of(""), hazeList)).isEqualTo("-ERR no command provided\r\n"); + assertThat(Main.executeCommand(database, List.of(""), hazeList)).isEqualTo("-ERR unknown command\r\n"); } diff --git a/src/test/java/org/fungover/haze/integration/HazeIT.java b/src/test/java/org/fungover/haze/integration/HazeIT.java index 5b261876..5107a969 100644 --- a/src/test/java/org/fungover/haze/integration/HazeIT.java +++ b/src/test/java/org/fungover/haze/integration/HazeIT.java @@ -1,6 +1,5 @@ package org.fungover.haze.integration; -import org.junit.jupiter.api.Disabled; import org.junit.jupiter.api.Test; import org.junit.jupiter.api.extension.ExtendWith; import redis.clients.jedis.JedisPooled; @@ -76,7 +75,6 @@ void listRPushRPop() { } @Test - @Disabled void listKeyWithMultipleValues() { assertThat(pool.lpush("test", "first")).isEqualTo(1); assertThat(pool.lpush("test", "second")).isEqualTo(2); From f4f96ddfc2c8758aea54294d7e19e0d6739252af Mon Sep 17 00:00:00 2001 From: Martin Blomberg Date: Sat, 4 Mar 2023 16:01:29 +0100 Subject: [PATCH 22/27] Disable generation of jar file, not needed. --- pom.xml | 28 ++++++++++------------------ 1 file changed, 10 insertions(+), 18 deletions(-) diff --git a/pom.xml b/pom.xml index 965f3848..a3ea1395 100644 --- a/pom.xml +++ b/pom.xml @@ -125,6 +125,16 @@ org.apache.maven.plugins maven-jar-plugin 3.3.0 + + + default-jar + none + + unwanted + unwanted + + + org.apache.maven.plugins @@ -193,24 +203,6 @@ @{argLine} --enable-preview - - - - - - - - - - - - - - - - - - From 058b92504a961a002951da69a460162ee125714b Mon Sep 17 00:00:00 2001 From: Martin Blomberg Date: Sat, 4 Mar 2023 16:10:56 +0100 Subject: [PATCH 23/27] Update release.yml to run Integration tests Before building new docker images during release integration tests will be run. The command is now mvn -B verify. --- .github/workflows/release.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 1ec9e9e8..b0963335 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -26,7 +26,7 @@ jobs: cache: maven - name: Compile and test with Maven - run: mvn -B test --file pom.xml + run: mvn -B verify --file pom.xml - name: Set up QEMU uses: docker/setup-qemu-action@v2 From 4b412fec10854fa72fa3fb66d67f4e01be1047c9 Mon Sep 17 00:00:00 2001 From: Martin Blomberg Date: Sat, 4 Mar 2023 16:42:10 +0100 Subject: [PATCH 24/27] Fix code smells. --- pom.xml | 6 ------ .../org/fungover/haze/integration/HazeIT.java | 15 +-------------- 2 files changed, 1 insertion(+), 20 deletions(-) diff --git a/pom.xml b/pom.xml index a3ea1395..38fd1979 100644 --- a/pom.xml +++ b/pom.xml @@ -72,12 +72,6 @@ 1.7.36 test - - - - - - diff --git a/src/test/java/org/fungover/haze/integration/HazeIT.java b/src/test/java/org/fungover/haze/integration/HazeIT.java index 5107a969..c5bae8b0 100644 --- a/src/test/java/org/fungover/haze/integration/HazeIT.java +++ b/src/test/java/org/fungover/haze/integration/HazeIT.java @@ -9,7 +9,7 @@ import static org.assertj.core.api.Assertions.assertThat; @ExtendWith(HazeExtension.class) -public class HazeIT { +class HazeIT { @Pool JedisPooled pool; @@ -87,17 +87,4 @@ void listKeyWithMultipleValues() { pool.del("test"); assertThat(pool.exists("right")).isFalse(); } - -// @Test -// void unknownCommand() { -// try (Socket socket = new Socket("localhost", port)) { -// // socket.setSoTimeout(3000); -// socket.getOutputStream().write("helloworld key value\r\n".getBytes(StandardCharsets.UTF_8)); -// BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(socket.getInputStream())); -//// assertThat(bufferedReader.readLine()).isEqualTo("-ERR unknown command 'helloworld', with args beginning with: 'key' 'value' "); -// assertThat(bufferedReader.readLine()).isEqualTo("-ERR unknown command"); -// } catch (IOException e) { -// throw new RuntimeException(e); -// } -// } } From 98afabaf9c7667b4ada875d11d77d5db693e08bd Mon Sep 17 00:00:00 2001 From: Martin Blomberg Date: Sun, 4 Feb 2024 10:13:50 +0100 Subject: [PATCH 25/27] Update versions for java and plugins --- Dockerfile | 4 ++-- pom.xml | 21 ++++++--------------- 2 files changed, 8 insertions(+), 17 deletions(-) diff --git a/Dockerfile b/Dockerfile index 8adf8db4..80526bdc 100644 --- a/Dockerfile +++ b/Dockerfile @@ -1,4 +1,4 @@ -FROM eclipse-temurin:19-jre-jammy +FROM eclipse-temurin:21-jre-jammy #COPY target/dependency /lib WORKDIR /app ARG USERNAME=hazeuser @@ -13,4 +13,4 @@ COPY target/classes . RUN chown --recursive $USERNAME:$USERNAME . USER $USERNAME EXPOSE 6379 -ENTRYPOINT ["java","-cp","/app:/app/lib/*","--enable-preview","org.fungover.haze.Main"] +ENTRYPOINT ["java","-cp","/app:/app/lib/*","org.fungover.haze.Main"] diff --git a/pom.xml b/pom.xml index 38fd1979..8712790d 100644 --- a/pom.xml +++ b/pom.xml @@ -8,7 +8,7 @@ haze 2.0.1-SNAPSHOT - 19 + 21 UTF-8 fungover https://sonarcloud.io @@ -51,13 +51,13 @@ redis.clients jedis - 4.3.1 + 5.1.0 test org.testcontainers testcontainers - 1.17.6 + 1.19.4 test @@ -79,11 +79,6 @@ org.apache.maven.plugins maven-compiler-plugin 3.11.0 - - - --enable-preview - - org.apache.maven.plugins @@ -148,7 +143,7 @@ org.apache.maven.plugins maven-failsafe-plugin - 3.0.0-M9 + 3.2.1 @@ -157,14 +152,11 @@ - - @{argLine} --enable-preview - org.jacoco jacoco-maven-plugin - 0.8.8 + 0.8.11 prepare-agent @@ -188,13 +180,12 @@ org.apache.maven.plugins maven-surefire-plugin - 3.0.0-M9 + 3.2.5 6380 12345 - @{argLine} --enable-preview From 247a5b4b9f6f6f33f2e81a4adc6bcae9cbbc0ae5 Mon Sep 17 00:00:00 2001 From: Martin Blomberg Date: Tue, 6 Feb 2024 11:57:42 +0100 Subject: [PATCH 26/27] Revert MaintTest.java --- src/test/java/org/fungover/haze/MainTest.java | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/src/test/java/org/fungover/haze/MainTest.java b/src/test/java/org/fungover/haze/MainTest.java index 686be38d..4e9c2c29 100644 --- a/src/test/java/org/fungover/haze/MainTest.java +++ b/src/test/java/org/fungover/haze/MainTest.java @@ -7,12 +7,11 @@ import java.io.ByteArrayOutputStream; import java.io.PrintStream; -import java.util.ArrayList; import java.util.List; import static org.assertj.core.api.Assertions.assertThat; import static org.fungover.haze.Main.printThreadDebug; -import static org.junit.jupiter.api.Assertions.*; +import static org.junit.jupiter.api.Assertions.assertFalse; class MainTest { @@ -27,7 +26,7 @@ void callingExecuteCommandWithValidNonExistingInputReturnsColonOne() { @Test void callingExecuteCommandWithInvalidInputStringReturnsErrorMessage() { - assertThat(Main.executeCommand(database, List.of(""), hazeList)).isEqualTo("-ERR unknown command\r\n"); + assertThat(Main.executeCommand(database, List.of(""), hazeList)).isEqualTo("-ERR no command provided\r\n"); } From 73dc9b4124beae801982908139c952ff54b5d878 Mon Sep 17 00:00:00 2001 From: Martin Blomberg Date: Tue, 6 Feb 2024 12:04:49 +0100 Subject: [PATCH 27/27] Clean up Dockerfile --- Dockerfile | 3 --- 1 file changed, 3 deletions(-) diff --git a/Dockerfile b/Dockerfile index f4f30242..89f9b6d0 100644 --- a/Dockerfile +++ b/Dockerfile @@ -1,6 +1,4 @@ FROM eclipse-temurin:21-jre-jammy -COPY target/dependency /lib -COPY target/classes /app WORKDIR /app ARG USERNAME=hazeuser ARG USER_UID=1000 @@ -9,7 +7,6 @@ RUN groupadd --gid $USER_GID $USERNAME && \ useradd --uid $USER_UID --gid $USER_GID -m $USERNAME ADD https://repo1.maven.org/maven2/org/apache/logging/log4j/log4j-core/2.20.0/log4j-core-2.20.0.jar ./lib/ ADD https://repo1.maven.org/maven2/org/apache/logging/log4j/log4j-api/2.20.0/log4j-api-2.20.0.jar ./lib/ -#RUN chmod --recursive 440 ./lib/ COPY target/classes . RUN chown --recursive $USERNAME:$USERNAME . USER $USERNAME