diff --git a/pom.xml b/pom.xml index a2bc239..22406ee 100644 --- a/pom.xml +++ b/pom.xml @@ -48,7 +48,7 @@ 4.4.5 5.3.1 2.0.4 - 1.4.11 + 1.3.11 4.13.2 1.7.0 diff --git a/src/main/java/io/github/grrolland/hcshm/ShmService.java b/src/main/java/io/github/grrolland/hcshm/ShmService.java index ba3c837..f89c55a 100644 --- a/src/main/java/io/github/grrolland/hcshm/ShmService.java +++ b/src/main/java/io/github/grrolland/hcshm/ShmService.java @@ -73,11 +73,11 @@ public String get(String key) { * @param value * the value as string * @param expire - * the expiration in seconds + * the expiration in milliseconds * @return the value set */ - public String set(String key, String value, int expire) { - getMap(key).set(key, new ShmValue(value, expire), expire, TimeUnit.SECONDS); + public String set(String key, String value, long expire) { + getMap(key).set(key, new ShmValue(value, expire), expire, TimeUnit.MILLISECONDS); return value; } @@ -89,12 +89,12 @@ public String set(String key, String value, int expire) { * @param value * the value as long * @param expire - * the expiration in seconds + * the expiration in milliseconds * @return the value set as string representation */ - public String set(String key, long value, int expire) { + public String set(String key, long value, long expire) { String r = Long.toString(value); - getMap(key).set(key, new ShmValue(r, expire), expire, TimeUnit.SECONDS); + getMap(key).set(key, new ShmValue(r, expire), expire, TimeUnit.MILLISECONDS); return r; } @@ -104,9 +104,9 @@ public String set(String key, long value, int expire) { * @param key * the key * @param expire - * the expiration in seconds + * the expiration in milliseconds */ - public void touch(String key, int expire) { + public void touch(String key, long expire) { getMap(key).executeOnKey(key, new TouchProcessor(expire)); } @@ -123,7 +123,7 @@ public void touch(String key, int expire) { * the initial expiration * @return the new value as string representation */ - public String incr(String key, int value, int init, int initialExpire) { + public String incr(String key, int value, int init, long initialExpire) { return (String) getMap(key).executeOnKey(key, new IncrProcessor(value, init, initialExpire)); } diff --git a/src/main/java/io/github/grrolland/hcshm/ShmValue.java b/src/main/java/io/github/grrolland/hcshm/ShmValue.java index 60bac5e..e9a2e97 100644 --- a/src/main/java/io/github/grrolland/hcshm/ShmValue.java +++ b/src/main/java/io/github/grrolland/hcshm/ShmValue.java @@ -1,23 +1,22 @@ /** * ngx-distributed-shm * Copyright (C) 2018 Flu.Tech - * + *

* This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. - * + *

* This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. - * + *

* You should have received a copy of the GNU General Public License * along with this program. If not, see . */ package io.github.grrolland.hcshm; - import java.io.Serializable; /** @@ -28,77 +27,75 @@ public class ShmValue implements Serializable { /** * The value */ - private String value = null; + private final String value; + /** * The expiration deadline */ private long deadline = 0; + /** * Indicate if the value expire */ private boolean doExpire = false; - /** - * Constructor - * - * @param newval the new value - * @param expire the expiration in second - */ - public ShmValue(String newval, int expire) { - value = newval; - if (expire != 0) { - deadline = System.currentTimeMillis() + expire * 1000; - doExpire = true; - } - } - /** * Get the value + * * @return the value */ public String getValue() { return value; } - /** - * Expire the value - * @param sectime expiration in second - */ - public void expire(int sectime) { - if (sectime != 0) { - deadline = System.currentTimeMillis() + sectime * 1000; - doExpire = true; - } - else - { - doExpire = false; - } - } - /** * Get le lasting time for the value - * - * When the time to the expiration deadline is lower than 1, return -1. - * + *

+ * When the time to the expiration deadline is lower than 1000, return -1. + *

* tha mean the value should expire immediately * * @return the time to the expiration deadline */ - public int getLastingTime() { + public long getLastingTime() { if (doExpire) { - final double lt = (deadline - System.currentTimeMillis()) / 1000d; - if (lt < 1.0) { + final long lt = deadline - System.currentTimeMillis(); + if (lt < 1000) { return -1; + } else { + return lt; } - else { - return (int) lt; - } - } - else - { + } else { return 0; } } + /** + * Constructor + * + * @param newval + * the new value + * @param expire + * the expiration in milliseconds + */ + public ShmValue(String newval, long expire) { + value = newval; + this.expire(expire); + } + + /** + * Expire the value + * + * @param sectime + * expiration in milliseconds + */ + public void expire(long sectime) { + if (sectime != 0) { + deadline = System.currentTimeMillis() + sectime; + doExpire = true; + } else { + doExpire = false; + } + } } diff --git a/src/main/java/io/github/grrolland/hcshm/commands/Command.java b/src/main/java/io/github/grrolland/hcshm/commands/Command.java index e24ee32..f26065b 100644 --- a/src/main/java/io/github/grrolland/hcshm/commands/Command.java +++ b/src/main/java/io/github/grrolland/hcshm/commands/Command.java @@ -1,17 +1,17 @@ /** * ngx-distributed-shm * Copyright (C) 2018 Flu.Tech - * + *

* This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. - * + *

* This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. - * + *

* You should have received a copy of the GNU General Public License * along with this program. If not, see . */ @@ -26,30 +26,31 @@ */ public abstract class Command { - /** - * Protocol Encoding - */ - protected static final String PROTOCOL_ENCODING = "UTF-8"; /** * Protocol response : DONE */ protected static final String DONE = "DONE"; + /** * Protocol response : DONE */ protected static final String LEN = "LEN "; + /** * Protocol response : DONE */ protected static final String RESPONSE_LINE_DELIMITER = "\r\n"; + /** * Protocol response : Error malformed resuqest */ protected static final String ERROR_MALFORMED_REQUEST = "ERROR malformed_request"; + /** * Protocol response : Error malformed request */ protected static final String ERROR_UNEXPECTED_DATA = "ERROR unexpected_data"; + /** * Protocol response : Error Not Found */ @@ -58,92 +59,113 @@ public abstract class Command { /** * SHM Service */ - private ShmService service = null; - - /** - * Package private constructor for factory only - * @param service th SHM Service - */ - Command(ShmService service) { - this.service = service; - } + private final ShmService service; /** * Get the SHM service + * * @return the service */ protected ShmService getService() { return service; } + /** + * Get if this command is a termination command and the socket must be closed after the execution + * + * @return true if this is a termination command + */ + public boolean isTerminationCommand() { + return false; + } + + /** + * Get the size of the data part if needed + * + * @return the size of the data part if needed + */ + public int getDataPartSize() { + return 0; // NOSONAR + } + + /** + * Package private constructor for factory only + * + * @param service + * th SHM Service + */ + Command(ShmService service) { + this.service = service; + } + /** * Execute the command - * @param comandTokens the protocol tokens argument of the command + * + * @param comandTokens + * the protocol tokens argument of the command * @return the result of the command 'protocol encoded' */ public abstract String execute(String[] comandTokens); /** * Execute the command - * @param buffer the data buffer + * + * @param buffer + * the data buffer * @return the result of the command 'protocol encoded' */ public String executeDataPart(String buffer) { return ERROR_UNEXPECTED_DATA + RESPONSE_LINE_DELIMITER; } - /** - * Get if this command is a termination command and the socket must be closed after the execution - * @return true if this is a termination command - */ - public boolean isTerminationCommand() { - return false; - } - /** * Get if this command need a data part + * * @return true if this command need a data part */ public boolean needsDataPart() { return false; } - /** - * Get the size of the data part if needed - * @return the size of the data part if needed - */ - public int getDataPartSize() { - return 0; // NOSONAR - } - /** * Assert command tokens contains expected token number - * @param commandTokens the command tokens - * @param expectedTokens the expected token numbers - * @throws ProtocolException if the command token numbers is different from expected + * + * @param commandTokens + * the command tokens + * @param expectedTokens + * the expected token numbers + * @throws ProtocolException + * if the command token numbers is different from expected */ protected void assertTokens(String[] commandTokens, int expectedTokens) throws ProtocolException { - if(commandTokens.length != expectedTokens) { - throw new ProtocolException(); + if (commandTokens.length != expectedTokens) { + throw new ProtocolException(); } } /** * Assert command tokens contains expected token number - * @param commandTokens the command tokens - * @param minToken the min expected token numbers - * @param maxToken the max expected token numbers - * @throws ProtocolException if the command token numbers is different from expected + * + * @param commandTokens + * the command tokens + * @param minToken + * the min expected token numbers + * @param maxToken + * the max expected token numbers + * @throws ProtocolException + * if the command token numbers is different from expected */ protected void assertTokens(String[] commandTokens, int minToken, int maxToken) throws ProtocolException { - if(commandTokens.length < minToken || commandTokens.length > maxToken) { - throw new ProtocolException(); + if (commandTokens.length < minToken || commandTokens.length > maxToken) { + throw new ProtocolException(); } } /** * Get the key from command token - * @param commandToken the command token + * + * @param commandToken + * the command token * @return the key */ protected String getKey(String commandToken) { @@ -152,101 +174,117 @@ protected String getKey(String commandToken) { /** * Get the expire value form command token - * @param commandToken the command token - * @return the expire value - * @throws ProtocolException if unable to get the expire value from command token - */ - protected int getExpire(String commandToken) throws ProtocolException { - try - { - final int l_expire = Integer.parseInt(commandToken); - if (l_expire < 0) { + * + * @param commandToken + * the command token + * @return the expire value in milliseconds + * @throws ProtocolException + * if unable to get the expire value from command token + */ + protected long getExpire(String commandToken) throws ProtocolException { + try { + final int expire = Integer.parseInt(commandToken); + if (expire < 0) { throw new ProtocolException(); } - return l_expire; - } - catch(NumberFormatException e) - { + return expire * 1000L; + } catch (NumberFormatException e) { throw new ProtocolException(); } } /** * get the incr value from command token - * @param commandToken the command token + * + * @param commandToken + * the command token * @return the incr value - * @throws ProtocolException if unable to get the incr value frame from command token + * @throws ProtocolException + * if unable to get the incr value frame from command token */ protected int getIncrValue(String commandToken) throws ProtocolException { - try - { + try { return Integer.parseInt(commandToken); - } - catch(NumberFormatException e) - { + } catch (NumberFormatException e) { throw new ProtocolException(); } } /** * get the size of data from command token - * @param commandToken the command token + * + * @param commandToken + * the command token * @return the size of the data frame - * @throws ProtocolException if unable to get the size of the data frame from command token + * @throws ProtocolException + * if unable to get the size of the data frame from command token */ protected int getSize(String commandToken) throws ProtocolException { - try - { + try { final int size = Integer.parseInt(commandToken); if (size <= 0) { throw new ProtocolException(); } return size; - } - catch(NumberFormatException e) - { + } catch (NumberFormatException e) { throw new ProtocolException(); } } /** * Write the LEN protocol line - * @param response the constructing response - * @param value the value which the length to write. + * + * @param response + * the constructing response + * @param value + * the value which the length to write. */ protected void writeLen(StringBuilder response, String value) { response.append(LEN); response.append(value.length()); response.append(RESPONSE_LINE_DELIMITER); } + /** * Write the LEN protocol line - * @param response the constructing response - * @param value the value + * + * @param response + * the constructing response + * @param value + * the value */ protected void writeValue(StringBuilder response, String value) { response.append(value); response.append(RESPONSE_LINE_DELIMITER); } + /** * Write the LEN protocol line - * @param response the constructing response + * + * @param response + * the constructing response */ protected void writeDone(StringBuilder response) { response.append(DONE); response.append(RESPONSE_LINE_DELIMITER); } + /** * Write the LEN protocol line - * @param response the constructing response + * + * @param response + * the constructing response */ protected void writeMalformedRequest(StringBuilder response) { response.append(ERROR_MALFORMED_REQUEST); response.append(RESPONSE_LINE_DELIMITER); } + /** * Write the LEN protocol line - * @param response the constructing response + * + * @param response + * the constructing response */ protected void writeNotFound(StringBuilder response) { response.append(ERROR_NOT_FOUND); diff --git a/src/main/java/io/github/grrolland/hcshm/commands/IncrCommand.java b/src/main/java/io/github/grrolland/hcshm/commands/IncrCommand.java index d5ae9b2..71f494e 100644 --- a/src/main/java/io/github/grrolland/hcshm/commands/IncrCommand.java +++ b/src/main/java/io/github/grrolland/hcshm/commands/IncrCommand.java @@ -49,7 +49,7 @@ public String execute(String[] commandTokens) { String key = getKey(commandTokens[1]); int incr = getIncrValue(commandTokens[2]); int initial = getIncrValue(commandTokens[3]); - int initialExpire = commandTokens.length == 5 ? getExpire(commandTokens[4]) : 0; + long initialExpire = commandTokens.length == 5 ? getExpire(commandTokens[4]) : 0; String value = getService().incr(key, incr, initial, initialExpire); writeLen(response, value); writeValue(response, value); diff --git a/src/main/java/io/github/grrolland/hcshm/commands/SetCommand.java b/src/main/java/io/github/grrolland/hcshm/commands/SetCommand.java index 680ca4b..4f8dd56 100644 --- a/src/main/java/io/github/grrolland/hcshm/commands/SetCommand.java +++ b/src/main/java/io/github/grrolland/hcshm/commands/SetCommand.java @@ -1,17 +1,17 @@ /** * ngx-distributed-shm * Copyright (C) 2018 Flu.Tech - * + *

* This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. - * + *

* This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. - * + *

* You should have received a copy of the GNU General Public License * along with this program. If not, see . */ @@ -29,38 +29,25 @@ public class SetCommand extends Command { * The key */ private String key = null; + /** - * The expiration + * The expiration in milliseconds */ - private int expire = 0; + private long expire = 0; + /** * The length */ private int length = 0; + /** * Need a data part ? */ private boolean needsDataPart = false; - /** - * Default Constructor - * @param service the shm service - */ - SetCommand(ShmService service) { - super(service); - } - - /** - * Get if this command need a data part - * @return true if this command need a data part - */ - @Override - public boolean needsDataPart() { - return needsDataPart; - } - /** * Get the size of the data part if needed + * * @return the size of the data part if needed */ @Override @@ -70,21 +57,20 @@ public int getDataPartSize() { /** * Execute the command - * @param commandTokens the protocol tokens argument of the command + * + * @param commandTokens + * the protocol tokens argument of the command * @return the result of the command 'protocol encoded' */ public String execute(String[] commandTokens) { final StringBuilder response = new StringBuilder(); - try - { + try { assertTokens(commandTokens, 4); key = getKey(commandTokens[1]); expire = getExpire(commandTokens[2]); length = getSize(commandTokens[3]); needsDataPart = true; - } - catch (ProtocolException e) - { + } catch (ProtocolException e) { writeMalformedRequest(response); } return response.toString(); @@ -92,19 +78,18 @@ public String execute(String[] commandTokens) { /** * Execute the command - * @param buffer the data buffer + * + * @param buffer + * the data buffer * @return the result of the command 'protocol encoded' */ @Override public String executeDataPart(String buffer) { final StringBuilder response = new StringBuilder(); String value; - try - { + try { value = getService().set(key, Long.parseLong(buffer), expire); - } - catch (NumberFormatException e) - { + } catch (NumberFormatException e) { value = getService().set(key, buffer, expire); } writeLen(response, value); @@ -114,4 +99,25 @@ public String executeDataPart(String buffer) { length = 0; return response.toString(); } + + /** + * Get if this command need a data part + * + * @return true if this command need a data part + */ + @Override + public boolean needsDataPart() { + return needsDataPart; + } + + /** + * Default Constructor + * + * @param service + * the shm service + */ + SetCommand(ShmService service) { + super(service); + } + } diff --git a/src/main/java/io/github/grrolland/hcshm/commands/TouchCommand.java b/src/main/java/io/github/grrolland/hcshm/commands/TouchCommand.java index a87d8b5..17b3c67 100644 --- a/src/main/java/io/github/grrolland/hcshm/commands/TouchCommand.java +++ b/src/main/java/io/github/grrolland/hcshm/commands/TouchCommand.java @@ -1,17 +1,17 @@ /** * ngx-distributed-shm * Copyright (C) 2018 Flu.Tech - * + *

* This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. - * + *

* This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. - * + *

* You should have received a copy of the GNU General Public License * along with this program. If not, see . */ @@ -40,16 +40,13 @@ public class TouchCommand extends Command { */ public String execute(String[] commandTokens) { final StringBuilder response = new StringBuilder(); - try - { + try { assertTokens(commandTokens, 3); String key = getKey(commandTokens[1]); - int expire = getExpire(commandTokens[2]); + long expire = getExpire(commandTokens[2]); getService().touch(key, expire); writeDone(response); - } - catch (ProtocolException e) - { + } catch (ProtocolException e) { writeMalformedRequest(response); } return response.toString(); diff --git a/src/main/java/io/github/grrolland/hcshm/processor/IncrProcessor.java b/src/main/java/io/github/grrolland/hcshm/processor/IncrProcessor.java index c0c084e..2b440dc 100644 --- a/src/main/java/io/github/grrolland/hcshm/processor/IncrProcessor.java +++ b/src/main/java/io/github/grrolland/hcshm/processor/IncrProcessor.java @@ -40,9 +40,9 @@ public class IncrProcessor implements EntryProcessor, private final int init; /** - * Initial TTL value + * Initial TTL value in milliseconds */ - private final int initialExpire; + private final long initialExpire; /** * Constructor @@ -52,9 +52,9 @@ public class IncrProcessor implements EntryProcessor, * @param init * initial value * @param initialExpire - * the initial expiration + * the initial expiration in milliseconds */ - public IncrProcessor(long value, int init, int initialExpire) { + public IncrProcessor(long value, int init, long initialExpire) { this.value = value; this.init = init; this.initialExpire = initialExpire; @@ -72,7 +72,7 @@ public Object process(Map.Entry entry) { final ShmValue r = entry.getValue(); String newval; - int expire; + long expire; ExtendedMapEntry extendedMapEntry = (ExtendedMapEntry) entry; if (null != r) { try { @@ -86,7 +86,7 @@ public Object process(Map.Entry entry) { expire = this.initialExpire; } if (expire >= 0) { - extendedMapEntry.setValue(new ShmValue(newval, expire), expire, TimeUnit.SECONDS); + extendedMapEntry.setValue(new ShmValue(newval, expire), expire, TimeUnit.MILLISECONDS); } else { extendedMapEntry.setValue(null); } diff --git a/src/main/java/io/github/grrolland/hcshm/processor/TouchProcessor.java b/src/main/java/io/github/grrolland/hcshm/processor/TouchProcessor.java index 43c03cc..cb0a038 100644 --- a/src/main/java/io/github/grrolland/hcshm/processor/TouchProcessor.java +++ b/src/main/java/io/github/grrolland/hcshm/processor/TouchProcessor.java @@ -1,30 +1,29 @@ /** * ngx-distributed-shm * Copyright (C) 2018 Flu.Tech - * + *

* This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. - * + *

* This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. - * + *

* You should have received a copy of the GNU General Public License * along with this program. If not, see . */ package io.github.grrolland.hcshm.processor; -import java.util.Map; -import java.util.concurrent.TimeUnit; - import com.hazelcast.map.EntryProcessor; import com.hazelcast.map.ExtendedMapEntry; - import io.github.grrolland.hcshm.ShmValue; +import java.util.Map; +import java.util.concurrent.TimeUnit; + /** * Entry processor for the touch command */ @@ -32,19 +31,23 @@ public class TouchProcessor implements EntryProcessor /** * Touch expiration */ - private int expire = 0; - + private final long expire; + /** * constructor - * @param expire touch expiration + * + * @param expire + * touch expiration */ - public TouchProcessor(int expire) { + public TouchProcessor(long expire) { this.expire = expire; } /** * Touch process - * @param entry the entry to touch + * + * @param entry + * the entry to touch * @return nothing */ @Override @@ -52,7 +55,7 @@ public Object process(Map.Entry entry) { final ShmValue r = entry.getValue(); if (null != r) { r.expire(expire); - ((ExtendedMapEntry) entry).setValue(r, expire, TimeUnit.SECONDS); + ((ExtendedMapEntry) entry).setValue(r, expire, TimeUnit.MILLISECONDS); } return null; } diff --git a/src/test/java/io/github/grrolland/hcshm/AbstractHCSHMGetTestCase.java b/src/test/java/io/github/grrolland/hcshm/AbstractHCSHMGetTestCase.java index 313ef21..91809f0 100644 --- a/src/test/java/io/github/grrolland/hcshm/AbstractHCSHMGetTestCase.java +++ b/src/test/java/io/github/grrolland/hcshm/AbstractHCSHMGetTestCase.java @@ -69,7 +69,7 @@ protected BufferedWriter getWriter() { } /** - * get Retry + * Get Retry * * @return the retry */ @@ -99,10 +99,20 @@ private static Retry getRetry() { * Wait (2000 ms) * * @throws InterruptedException - * exception when trying to sleep the current thread + * exception when trying to sleep the current thread */ public static void pause() throws InterruptedException { - Thread.sleep(2000); // NOSONAR + pause(2000); + } + + /*** + * Pause the test during duration milliseconds + * @param duration the duration time in milliseconds + * @throws InterruptedException + * exception when trying to sleep the current thread + */ + public static void pause(long duration) throws InterruptedException { + Thread.sleep(duration); // NOSONAR } /** @@ -206,6 +216,7 @@ public void assertResponseMalFormedRequest() throws IOException { * Assert response is DONE * * @throws IOException + * I/O Exception */ public void assertResponseDone() throws IOException { String res = getReader().readLine(); diff --git a/src/test/java/io/github/grrolland/hcshm/IncrTestCase.java b/src/test/java/io/github/grrolland/hcshm/IncrTestCase.java index 1f577d4..08101c0 100644 --- a/src/test/java/io/github/grrolland/hcshm/IncrTestCase.java +++ b/src/test/java/io/github/grrolland/hcshm/IncrTestCase.java @@ -17,8 +17,11 @@ */ package io.github.grrolland.hcshm; +import ch.qos.logback.classic.Level; +import ch.qos.logback.classic.Logger; import org.junit.Assert; import org.junit.Test; +import org.slf4j.LoggerFactory; import java.io.IOException; @@ -86,23 +89,75 @@ public void testIncrExpire() { * Test Incrementation */ @Test - public void testMultiIncrExpire() { + public void testMultiIncrExpireLoad() throws IOException { + Logger logger = (Logger) LoggerFactory.getLogger(IncrTestCase.class); + logger.setLevel(Level.INFO); + // Increment key + for (int i = 1; i <= 200; i++) { + getWriter().write("INCR key 1 0 60\r\n"); + getWriter().flush(); + logger.info("Expect value {}", i); + assertResponseGetValue(String.valueOf(i)); + } + } + + /** + * Test Incrementation + */ + @Test + public void testMultiIncr() { try { + //Delete KEY + getWriter().write("DELETE key\r\n"); + getWriter().flush(); + assertResponseDone(); + // Increment key - getWriter().write("INCR key -1 10 3\r\n"); + getWriter().write("INCR key -1 10 4\r\n"); getWriter().flush(); assertResponseGetValue("9"); // Pause - pause(); + pause(2000); + + getWriter().write("INCR key -1 10\r\n"); + getWriter().flush(); + assertResponseGetValue("8"); + + // Pause + pause(5000); + getWriter().write("GET key\r\n"); + getWriter().flush(); + assertResponseNotFound(); + } catch (IOException | InterruptedException e) { + Assert.fail(e.getMessage()); + } + + } + + /** + * Test Incrementation + */ + @Test + public void testMultiIncrExpire() { + + try { + // Increment key getWriter().write("INCR key -1 10 4\r\n"); getWriter().flush(); + assertResponseGetValue("9"); + + // Pause + pause(2000); + + getWriter().write("INCR key -1 10 60\r\n"); + getWriter().flush(); assertResponseGetValue("8"); // Pause - pause(); + pause(4000); getWriter().write("GET key\r\n"); getWriter().flush(); assertResponseNotFound(); @@ -120,6 +175,11 @@ public void testMultiIncrExpire() { public void testIncrExistingWithoutExpire() { try { + // Prepare test + getWriter().write("DELETE key\r\n"); + getWriter().flush(); + assertResponseDone(); + // SET key without expire getWriter().write("SET key 0 2\r\n"); getWriter().write("10");