From def3f38de70ccc3337f944232201bd39173c06bd Mon Sep 17 00:00:00 2001 From: Jonathan Leibiusky Date: Sat, 12 Jun 2010 00:29:46 -0300 Subject: [PATCH] Added commands operating on all kind of values --- README.md | 21 +- pom.xml | 2 +- src/main/java/redis/clients/jedis/Client.java | 12 +- src/main/java/redis/clients/jedis/Jedis.java | 80 +++++- .../redis/clients/jedis/JedisException.java | 12 + .../java/redis/clients/jedis/Protocol.java | 78 ++++-- .../clients/jedis/tests/ProtocolTest.java | 11 +- .../commands/AllKindOfValuesCommandsTest.java | 248 ++++++++++++++++++ .../ConnectionHandlingCommandsTest.java | 37 +++ .../StringValuesCommandsTest.java} | 18 +- 10 files changed, 467 insertions(+), 52 deletions(-) create mode 100644 src/main/java/redis/clients/jedis/JedisException.java create mode 100644 src/test/java/redis/clients/jedis/tests/commands/AllKindOfValuesCommandsTest.java create mode 100644 src/test/java/redis/clients/jedis/tests/commands/ConnectionHandlingCommandsTest.java rename src/test/java/redis/clients/jedis/tests/{JedisTest.java => commands/StringValuesCommandsTest.java} (59%) diff --git a/README.md b/README.md index a29cf97..b400bee 100644 --- a/README.md +++ b/README.md @@ -7,12 +7,29 @@ Jedis was conceived to be EASY to use and FULLY COMPATIBLE with the latest versi Jedis is a WORK IN PROGRESS. ## What's still missing? -Right now almost everything. You can just PING, GET and SET. But stay close because whenever I have a couple of free hours it will support almost everything! +- Commands operating on string values +- Commands operating on lists +- Commands operating on sets +- Commands operating on sorted sets +- Commands operating on hashes +- Sorting +- Transactions +- Publish/Subscribe +- Persistence control commands +- Remote server control commands +- And the AUTH command + +But stay close because things are going fast and all this will be implemented soon! + +## Ok.. so what's already done? +- Connection handling (not AUTH) +- Commands operating on all the kind of values +- Commands operating on string values (just GET and SET) ## How do I use it? You can download the latests build at: - http://github.com/downloads/xetorthio/jedis/jedis-0.0.1-SNAPSHOT.jar + http://github.com/downloads/xetorthio/jedis/jedis-0.0.2.jar To use it just: diff --git a/pom.xml b/pom.xml index 2cc762e..85c54aa 100644 --- a/pom.xml +++ b/pom.xml @@ -2,7 +2,7 @@ 4.0.0 redis.clients jedis - 0.0.1-SNAPSHOT + 0.0.2 junit diff --git a/src/main/java/redis/clients/jedis/Client.java b/src/main/java/redis/clients/jedis/Client.java index d362a94..6114595 100644 --- a/src/main/java/redis/clients/jedis/Client.java +++ b/src/main/java/redis/clients/jedis/Client.java @@ -5,6 +5,7 @@ import java.io.InputStream; import java.io.OutputStream; import java.net.Socket; import java.net.UnknownHostException; +import java.util.List; public class Client { private String host; @@ -74,12 +75,19 @@ public class Client { return connected; } - protected String getSingleLineReply() { + protected String getStatusCodeReply() throws JedisException { return protocol.getSingleLineReply(inputStream); } - public String getBulkReply() { + public String getBulkReply() throws JedisException { return protocol.getBulkReply(inputStream); } + public int getIntegerReply() throws JedisException { + return protocol.getIntegerReply(inputStream); + } + + public List getMultiBulkReply() throws JedisException { + return protocol.getMultiBulkReply(inputStream); + } } \ No newline at end of file diff --git a/src/main/java/redis/clients/jedis/Jedis.java b/src/main/java/redis/clients/jedis/Jedis.java index 89f3c9a..59ce924 100644 --- a/src/main/java/redis/clients/jedis/Jedis.java +++ b/src/main/java/redis/clients/jedis/Jedis.java @@ -1,21 +1,89 @@ package redis.clients.jedis; +import java.util.List; + public class Jedis extends Client { public Jedis(String host) { super(host); } - public String ping() { - return sendCommand("PING").getSingleLineReply(); + public String ping() throws JedisException { + return sendCommand("PING").getStatusCodeReply(); } - public String set(String key, String value) { - return sendCommand("SET", key, value).getSingleLineReply(); - + public String set(String key, String value) throws JedisException { + return sendCommand("SET", key, value).getStatusCodeReply(); } - public String get(String key) { + public String get(String key) throws JedisException { return sendCommand("GET", key).getBulkReply(); } + public void quit() { + sendCommand("QUIT"); + } + + public int exists(String key) throws JedisException { + return sendCommand("EXISTS", key).getIntegerReply(); + } + + public int del(String... keys) throws JedisException { + return sendCommand("DEL", keys).getIntegerReply(); + } + + public String type(String key) throws JedisException { + return sendCommand("TYPE", key).getStatusCodeReply(); + } + + public String flushDB() throws JedisException { + return sendCommand("FLUSHDB").getStatusCodeReply(); + } + + public List keys(String pattern) throws JedisException { + return sendCommand("KEYS", pattern).getMultiBulkReply(); + } + + public String randomKey() throws JedisException { + return sendCommand("RANDOMKEY").getStatusCodeReply(); + } + + public String rename(String oldkey, String newkey) throws JedisException { + return sendCommand("RENAME", oldkey, newkey).getStatusCodeReply(); + } + + public int renamenx(String oldkey, String newkey) throws JedisException { + return sendCommand("RENAMENX", oldkey, newkey).getIntegerReply(); + } + + public int dbSize() throws JedisException { + return sendCommand("DBSIZE").getIntegerReply(); + } + + public int expire(String key, int seconds) throws JedisException { + return sendCommand("EXPIRE", key, String.valueOf(seconds)) + .getIntegerReply(); + } + + public int expireAt(String key, long unixTime) throws JedisException { + return sendCommand("EXPIREAT", key, String.valueOf(unixTime)) + .getIntegerReply(); + } + + public int ttl(String key) throws JedisException { + return sendCommand("TTL", key).getIntegerReply(); + } + + public String select(int index) throws JedisException { + return sendCommand("SELECT", String.valueOf(index)) + .getStatusCodeReply(); + } + + public int move(String key, int dbIndex) throws JedisException { + return sendCommand("MOVE", key, String.valueOf(dbIndex)) + .getIntegerReply(); + } + + public String flushAll() throws JedisException { + return sendCommand("FLUSHALL").getStatusCodeReply(); + } } diff --git a/src/main/java/redis/clients/jedis/JedisException.java b/src/main/java/redis/clients/jedis/JedisException.java new file mode 100644 index 0000000..e69cbac --- /dev/null +++ b/src/main/java/redis/clients/jedis/JedisException.java @@ -0,0 +1,12 @@ +package redis.clients.jedis; + +public class JedisException extends Exception { + /** + * + */ + private static final long serialVersionUID = -2946266495682282677L; + + public JedisException(String message) { + super(message); + } +} diff --git a/src/main/java/redis/clients/jedis/Protocol.java b/src/main/java/redis/clients/jedis/Protocol.java index 8f00084..39c1ebe 100644 --- a/src/main/java/redis/clients/jedis/Protocol.java +++ b/src/main/java/redis/clients/jedis/Protocol.java @@ -10,6 +10,7 @@ public class Protocol { public static final String DOLLAR = "$"; public static final String ASTERISK = "*"; public static final String PLUS = "+"; + public static final String MINUS = "-"; public static final String COLON = ":"; public static final String COMMAND_DELIMITER = "\r\n"; public static final int DEFAULT_PORT = 6379; @@ -17,6 +18,7 @@ public class Protocol { public static final byte DOLLAR_BYTE = DOLLAR.getBytes()[0]; public static final byte ASTERISK_BYTE = ASTERISK.getBytes()[0]; public static final byte PLUS_BYTE = PLUS.getBytes()[0]; + public static final byte MINUS_BYTE = MINUS.getBytes()[0]; public static final byte COLON_BYTE = COLON.getBytes()[0]; public void sendCommand(OutputStream os, String name, String... args) { @@ -36,10 +38,40 @@ public class Protocol { } } - public String getBulkReply(InputStream is) { + public void processError(InputStream is) throws JedisException { + String message = readLine(is); + throw new JedisException(message); + } + + private String readLine(InputStream is) { + byte b; + StringBuilder sb = new StringBuilder(); + + try { + while ((b = (byte) is.read()) != -1) { + if (b == '\r') { + b = (byte) is.read(); + if (b == '\n') { + break; + } + } + sb.append((char) b); + } + } catch (IOException e) { + // TODO Dont know what to do here! + } + return sb.toString(); + } + + public String getBulkReply(InputStream is) throws JedisException { String ret = null; try { - if ((byte) is.read() == DOLLAR_BYTE) { + byte b = (byte) is.read(); + if (b == MINUS_BYTE) { + processError(is); + } + + if (b == DOLLAR_BYTE) { int len = Integer.parseInt(readLine(is)); if (len == -1) { return null; @@ -60,26 +92,15 @@ public class Protocol { return ret; } - private String readLine(InputStream is) throws IOException { - byte b; - StringBuilder sb = new StringBuilder(); - - while ((b = (byte) is.read()) != -1) { - if (b == '\r') { - b = (byte) is.read(); - if (b == '\n') { - break; - } - } - sb.append((char) b); - } - return sb.toString(); - } - - public String getSingleLineReply(InputStream is) { + public String getSingleLineReply(InputStream is) throws JedisException { String ret = null; try { - if ((byte) is.read() == PLUS_BYTE) { + byte b = (byte) is.read(); + if (b == MINUS_BYTE) { + processError(is); + } + + if (b == PLUS_BYTE) { ret = readLine(is); } } catch (IOException e) { @@ -89,24 +110,33 @@ public class Protocol { return ret; } - public int getIntegerReply(InputStream is) { + public int getIntegerReply(InputStream is) throws JedisException { int ret = 0; try { - if ((byte) is.read() == COLON_BYTE) { + byte b = (byte) is.read(); + if (b == MINUS_BYTE) { + processError(is); + } + if (b == COLON_BYTE) { String num = readLine(is); ret = Integer.parseInt(num); } } catch (IOException e) { // TODO Not sure that I should return 0 + e.printStackTrace(); return 0; } return ret; } - public List getMultiBulkReply(InputStream is) { + public List getMultiBulkReply(InputStream is) throws JedisException { List ret = new ArrayList(); try { - if ((byte) is.read() == ASTERISK_BYTE) { + byte b = (byte) is.read(); + if (b == MINUS_BYTE) { + processError(is); + } + if (b == ASTERISK_BYTE) { int num = Integer.parseInt(readLine(is)); for (int i = 0; i < num; i++) { ret.add(getBulkReply(is)); diff --git a/src/test/java/redis/clients/jedis/tests/ProtocolTest.java b/src/test/java/redis/clients/jedis/tests/ProtocolTest.java index 5098fad..d0266f4 100644 --- a/src/test/java/redis/clients/jedis/tests/ProtocolTest.java +++ b/src/test/java/redis/clients/jedis/tests/ProtocolTest.java @@ -13,6 +13,7 @@ import junit.framework.Assert; import org.junit.Test; +import redis.clients.jedis.JedisException; import redis.clients.jedis.Protocol; public class ProtocolTest extends Assert { @@ -38,7 +39,7 @@ public class ProtocolTest extends Assert { } @Test - public void bulkReply() { + public void bulkReply() throws JedisException { InputStream is = new ByteArrayInputStream("$6\r\nfoobar\r\n".getBytes()); Protocol protocol = new Protocol(); String response = protocol.getBulkReply(is); @@ -46,7 +47,7 @@ public class ProtocolTest extends Assert { } @Test - public void nullBulkReply() { + public void nullBulkReply() throws JedisException { InputStream is = new ByteArrayInputStream("$-1\r\n".getBytes()); Protocol protocol = new Protocol(); String response = protocol.getBulkReply(is); @@ -54,7 +55,7 @@ public class ProtocolTest extends Assert { } @Test - public void singleLineReply() { + public void singleLineReply() throws JedisException { InputStream is = new ByteArrayInputStream("+OK\r\n".getBytes()); Protocol protocol = new Protocol(); String response = protocol.getSingleLineReply(is); @@ -62,7 +63,7 @@ public class ProtocolTest extends Assert { } @Test - public void integerReply() { + public void integerReply() throws JedisException { InputStream is = new ByteArrayInputStream(":123\r\n".getBytes()); Protocol protocol = new Protocol(); int response = protocol.getIntegerReply(is); @@ -70,7 +71,7 @@ public class ProtocolTest extends Assert { } @Test - public void multiBulkReply() { + public void multiBulkReply() throws JedisException { InputStream is = new ByteArrayInputStream( "*4\r\n$3\r\nfoo\r\n$3\r\nbar\r\n$5\r\nHello\r\n$5\r\nWorld\r\n" .getBytes()); diff --git a/src/test/java/redis/clients/jedis/tests/commands/AllKindOfValuesCommandsTest.java b/src/test/java/redis/clients/jedis/tests/commands/AllKindOfValuesCommandsTest.java new file mode 100644 index 0000000..283f776 --- /dev/null +++ b/src/test/java/redis/clients/jedis/tests/commands/AllKindOfValuesCommandsTest.java @@ -0,0 +1,248 @@ +package redis.clients.jedis.tests.commands; + +import java.util.ArrayList; +import java.util.List; + +import junit.framework.Assert; + +import org.junit.After; +import org.junit.Before; +import org.junit.Test; + +import redis.clients.jedis.Jedis; +import redis.clients.jedis.JedisException; + +public class AllKindOfValuesCommandsTest extends Assert { + private Jedis jedis; + + @Before + public void setUp() throws Exception { + jedis = new Jedis("localhost"); + jedis.connect(); + } + + @After + public void tearDown() throws Exception { + jedis.flushDB(); + jedis.disconnect(); + } + + @Test + public void ping() throws JedisException { + String status = jedis.ping(); + assertEquals("PONG", status); + } + + @Test + public void exists() throws JedisException { + String status = jedis.set("foo", "bar"); + assertEquals("OK", status); + + int reply = jedis.exists("foo"); + assertEquals(1, reply); + + reply = jedis.del("foo"); + assertEquals(1, reply); + + reply = jedis.exists("foo"); + assertEquals(0, reply); + } + + @Test + public void del() throws JedisException { + jedis.set("foo1", "bar1"); + jedis.set("foo2", "bar2"); + jedis.set("foo3", "bar3"); + + int reply = jedis.del("foo1", "foo2", "foo3"); + assertEquals(3, reply); + + reply = jedis.exists("foo1"); + assertEquals(0, reply); + reply = jedis.exists("foo2"); + assertEquals(0, reply); + reply = jedis.exists("foo3"); + assertEquals(0, reply); + + jedis.set("foo1", "bar1"); + + reply = jedis.del("foo1", "foo2"); + assertEquals(1, reply); + + reply = jedis.del("foo1", "foo2"); + assertEquals(0, reply); + } + + @Test + public void type() throws JedisException { + jedis.set("foo", "bar"); + String status = jedis.type("foo"); + assertEquals("string", status); + } + + @Test + public void keys() throws JedisException { + jedis.set("foo", "bar"); + jedis.set("foobar", "bar"); + + List keys = jedis.keys("foo*"); + List expected = new ArrayList(); + expected.add("foo"); + expected.add("foobar"); + assertEquals(expected, keys); + + expected = new ArrayList(); + keys = jedis.keys("bar*"); + + assertEquals(expected, keys); + } + + @Test + public void randomKey() throws JedisException { + assertEquals("", jedis.randomKey()); + + jedis.set("foo", "bar"); + + assertEquals("foo", jedis.randomKey()); + + jedis.set("bar", "foo"); + + String randomkey = jedis.randomKey(); + assertTrue(randomkey.equals("foo") || randomkey.equals("bar")); + } + + @Test + public void rename() throws JedisException { + jedis.set("foo", "bar"); + String status = jedis.rename("foo", "bar"); + assertEquals("OK", status); + + String value = jedis.get("foo"); + assertEquals(null, value); + + value = jedis.get("bar"); + assertEquals("bar", value); + } + + @Test(expected = JedisException.class) + public void renameOldAndNewAreTheSame() throws JedisException { + jedis.set("foo", "bar"); + jedis.rename("foo", "foo"); + } + + @Test + public void renamenx() throws JedisException { + jedis.set("foo", "bar"); + int status = jedis.renamenx("foo", "bar"); + assertEquals(1, status); + + jedis.set("foo", "bar"); + status = jedis.renamenx("foo", "bar"); + assertEquals(0, status); + } + + @Test + public void dbSize() throws JedisException { + int size = jedis.dbSize(); + assertEquals(0, size); + + jedis.set("foo", "bar"); + size = jedis.dbSize(); + assertEquals(1, size); + } + + @Test + public void expire() throws JedisException { + int status = jedis.expire("foo", 20); + assertEquals(0, status); + + jedis.set("foo", "bar"); + status = jedis.expire("foo", 20); + assertEquals(1, status); + + status = jedis.expire("foo", 20); + assertEquals(0, status); + } + + @Test + public void expireAt() throws JedisException { + long unixTime = (System.currentTimeMillis() / 1000L) + 20; + + int status = jedis.expireAt("foo", unixTime); + assertEquals(0, status); + + jedis.set("foo", "bar"); + unixTime = (System.currentTimeMillis() / 1000L) + 20; + status = jedis.expireAt("foo", unixTime); + assertEquals(1, status); + + unixTime = (System.currentTimeMillis() / 1000L) + 20; + status = jedis.expireAt("foo", unixTime); + assertEquals(0, status); + } + + @Test + public void ttl() throws JedisException { + int ttl = jedis.ttl("foo"); + assertEquals(-1, ttl); + + jedis.set("foo", "bar"); + ttl = jedis.ttl("foo"); + assertEquals(-1, ttl); + + jedis.expire("foo", 20); + ttl = jedis.ttl("foo"); + assertTrue(ttl >= 0 && ttl <= 20); + } + + @Test + public void select() throws JedisException { + jedis.set("foo", "bar"); + String status = jedis.select(1); + assertEquals("OK", status); + assertEquals(null, jedis.get("foo")); + status = jedis.select(0); + assertEquals("OK", status); + assertEquals("bar", jedis.get("foo")); + } + + @Test + public void move() throws JedisException { + int status = jedis.move("foo", 1); + assertEquals(0, status); + + jedis.set("foo", "bar"); + status = jedis.move("foo", 1); + assertEquals(1, status); + assertEquals(null, jedis.get("foo")); + + jedis.select(1); + assertEquals("bar", jedis.get("foo")); + } + + @Test + public void flushDB() throws JedisException { + jedis.set("foo", "bar"); + assertEquals(1, jedis.dbSize()); + jedis.set("bar", "foo"); + jedis.move("bar", 1); + String status = jedis.flushDB(); + assertEquals("OK", status); + assertEquals(0, jedis.dbSize()); + jedis.select(1); + assertEquals(1, jedis.dbSize()); + } + + @Test + public void flushAll() throws JedisException { + jedis.set("foo", "bar"); + assertEquals(1, jedis.dbSize()); + jedis.set("bar", "foo"); + jedis.move("bar", 1); + String status = jedis.flushAll(); + assertEquals("OK", status); + assertEquals(0, jedis.dbSize()); + jedis.select(1); + assertEquals(0, jedis.dbSize()); + } +} \ No newline at end of file diff --git a/src/test/java/redis/clients/jedis/tests/commands/ConnectionHandlingCommandsTest.java b/src/test/java/redis/clients/jedis/tests/commands/ConnectionHandlingCommandsTest.java new file mode 100644 index 0000000..4d41dbe --- /dev/null +++ b/src/test/java/redis/clients/jedis/tests/commands/ConnectionHandlingCommandsTest.java @@ -0,0 +1,37 @@ +package redis.clients.jedis.tests.commands; + +import junit.framework.Assert; + +import org.junit.After; +import org.junit.Before; +import org.junit.Ignore; +import org.junit.Test; + +import redis.clients.jedis.Jedis; + +public class ConnectionHandlingCommandsTest extends Assert { + private Jedis jedis; + + @Before + public void setUp() throws Exception { + jedis = new Jedis("localhost"); + jedis.connect(); + } + + @After + public void tearDown() throws Exception { + jedis.flushDB(); + jedis.disconnect(); + } + + @Test + public void quit() { + jedis.quit(); + } + + @Test + @Ignore(value = "Need to implement!") + public void auth() { + + } +} \ No newline at end of file diff --git a/src/test/java/redis/clients/jedis/tests/JedisTest.java b/src/test/java/redis/clients/jedis/tests/commands/StringValuesCommandsTest.java similarity index 59% rename from src/test/java/redis/clients/jedis/tests/JedisTest.java rename to src/test/java/redis/clients/jedis/tests/commands/StringValuesCommandsTest.java index b2793ea..1ad66fc 100644 --- a/src/test/java/redis/clients/jedis/tests/JedisTest.java +++ b/src/test/java/redis/clients/jedis/tests/commands/StringValuesCommandsTest.java @@ -1,7 +1,4 @@ -package redis.clients.jedis.tests; - -import java.io.IOException; -import java.net.UnknownHostException; +package redis.clients.jedis.tests.commands; import junit.framework.Assert; @@ -10,8 +7,9 @@ import org.junit.Before; import org.junit.Test; import redis.clients.jedis.Jedis; +import redis.clients.jedis.JedisException; -public class JedisTest extends Assert { +public class StringValuesCommandsTest extends Assert { private Jedis jedis; @Before @@ -22,21 +20,17 @@ public class JedisTest extends Assert { @After public void tearDown() throws Exception { + jedis.flushDB(); jedis.disconnect(); } @Test - public void ping() throws UnknownHostException, IOException { - String status = jedis.ping(); - assertEquals("PONG", status); - } - - @Test - public void setAndGet() throws UnknownHostException, IOException { + public void setAndGet() throws JedisException { String status = jedis.set("foo", "bar"); assertEquals("OK", status); String value = jedis.get("foo"); assertEquals("bar", value); } + }