package redis.clients.jedis.tests.commands; import java.io.IOException; import java.net.UnknownHostException; import java.util.ArrayList; import java.util.Arrays; import java.util.List; import java.util.Set; import org.junit.Before; import org.junit.Test; import redis.clients.jedis.Jedis; import redis.clients.jedis.Pipeline; import redis.clients.jedis.Protocol.Keyword; import redis.clients.jedis.Response; import redis.clients.jedis.Transaction; import redis.clients.jedis.exceptions.JedisDataException; public class TransactionCommandsTest extends JedisCommandTestBase { final byte[] bfoo = { 0x01, 0x02, 0x03, 0x04 }; final byte[] bbar = { 0x05, 0x06, 0x07, 0x08 }; final byte[] ba = { 0x0A }; final byte[] bb = { 0x0B }; final byte[] bmykey = { 0x42, 0x02, 0x03, 0x04 }; Jedis nj; @Before public void setUp() throws Exception { super.setUp(); nj = new Jedis(hnp.getHost(), hnp.getPort(), 500); nj.connect(); nj.auth("foobared"); nj.flushAll(); } @Test public void multi() { Transaction trans = jedis.multi(); trans.sadd("foo", "a"); trans.sadd("foo", "b"); trans.scard("foo"); List<Object> response = trans.exec(); List<Object> expected = new ArrayList<Object>(); expected.add(1L); expected.add(1L); expected.add(2L); assertEquals(expected, response); // Binary trans = jedis.multi(); trans.sadd(bfoo, ba); trans.sadd(bfoo, bb); trans.scard(bfoo); response = trans.exec(); expected = new ArrayList<Object>(); expected.add(1L); expected.add(1L); expected.add(2L); assertEquals(expected, response); } @Test public void watch() throws UnknownHostException, IOException { jedis.watch("mykey", "somekey"); Transaction t = jedis.multi(); nj.connect(); nj.auth("foobared"); nj.set("mykey", "bar"); nj.disconnect(); t.set("mykey", "foo"); List<Object> resp = t.exec(); assertEquals(null, resp); assertEquals("bar", jedis.get("mykey")); // Binary jedis.watch(bmykey, "foobar".getBytes()); t = jedis.multi(); nj.connect(); nj.auth("foobared"); nj.set(bmykey, bbar); nj.disconnect(); t.set(bmykey, bfoo); resp = t.exec(); assertEquals(null, resp); assertTrue(Arrays.equals(bbar, jedis.get(bmykey))); } @Test public void unwatch() throws UnknownHostException, IOException { jedis.watch("mykey"); String val = jedis.get("mykey"); val = "foo"; String status = jedis.unwatch(); assertEquals("OK", status); Transaction t = jedis.multi(); nj.connect(); nj.auth("foobared"); nj.set("mykey", "bar"); nj.disconnect(); t.set("mykey", val); List<Object> resp = t.exec(); assertEquals(1, resp.size()); assertEquals("OK", resp.get(0)); // Binary jedis.watch(bmykey); byte[] bval = jedis.get(bmykey); bval = bfoo; status = jedis.unwatch(); assertEquals(Keyword.OK.name(), status); t = jedis.multi(); nj.connect(); nj.auth("foobared"); nj.set(bmykey, bbar); nj.disconnect(); t.set(bmykey, bval); resp = t.exec(); assertEquals(1, resp.size()); assertEquals("OK", resp.get(0)); } @Test(expected = JedisDataException.class) public void validateWhenInMulti() { jedis.multi(); jedis.ping(); } @Test public void discard() { Transaction t = jedis.multi(); String status = t.discard(); assertEquals("OK", status); } @Test public void transactionResponse() { jedis.set("string", "foo"); jedis.lpush("list", "foo"); jedis.hset("hash", "foo", "bar"); jedis.zadd("zset", 1, "foo"); jedis.sadd("set", "foo"); Transaction t = jedis.multi(); Response<String> string = t.get("string"); Response<String> list = t.lpop("list"); Response<String> hash = t.hget("hash", "foo"); Response<Set<String>> zset = t.zrange("zset", 0, -1); Response<String> set = t.spop("set"); t.exec(); assertEquals("foo", string.get()); assertEquals("foo", list.get()); assertEquals("bar", hash.get()); assertEquals("foo", zset.get().iterator().next()); assertEquals("foo", set.get()); } @Test public void transactionResponseBinary() { jedis.set("string", "foo"); jedis.lpush("list", "foo"); jedis.hset("hash", "foo", "bar"); jedis.zadd("zset", 1, "foo"); jedis.sadd("set", "foo"); Transaction t = jedis.multi(); Response<byte[]> string = t.get("string".getBytes()); Response<byte[]> list = t.lpop("list".getBytes()); Response<byte[]> hash = t.hget("hash".getBytes(), "foo".getBytes()); Response<Set<byte[]>> zset = t.zrange("zset".getBytes(), 0, -1); Response<byte[]> set = t.spop("set".getBytes()); t.exec(); assertArrayEquals("foo".getBytes(), string.get()); assertArrayEquals("foo".getBytes(), list.get()); assertArrayEquals("bar".getBytes(), hash.get()); assertArrayEquals("foo".getBytes(), zset.get().iterator().next()); assertArrayEquals("foo".getBytes(), set.get()); } @Test(expected = JedisDataException.class) public void transactionResponseWithinPipeline() { jedis.set("string", "foo"); Transaction t = jedis.multi(); Response<String> string = t.get("string"); string.get(); t.exec(); } @Test public void transactionResponseWithError() { Transaction t = jedis.multi(); t.set("foo", "bar"); Response<Set<String>> error = t.smembers("foo"); Response<String> r = t.get("foo"); List<Object> l = t.exec(); assertEquals(JedisDataException.class, l.get(1).getClass()); try { error.get(); fail("We expect exception here!"); } catch (JedisDataException e) { // that is fine we should be here } assertEquals(r.get(), "bar"); } @Test public void execGetResponse() { Transaction t = jedis.multi(); t.set("foo", "bar"); t.smembers("foo"); t.get("foo"); List<Response<?>> lr = t.execGetResponse(); try { lr.get(1).get(); fail("We expect exception here!"); } catch (JedisDataException e) { // that is fine we should be here } assertEquals("bar", lr.get(2).get()); } @Test public void select() { jedis.select(1); jedis.set("foo", "bar"); jedis.watch("foo"); Transaction t = jedis.multi(); t.select(0); t.set("bar", "foo"); Jedis jedis2 = createJedis(); jedis2.select(1); jedis2.set("foo", "bar2"); List<Object> results = t.exec(); assertNull(results); } @Test public void testResetStateWhenInMulti() { jedis.auth("foobared"); Transaction t = jedis.multi(); t.set("foooo", "barrr"); jedis.resetState(); assertEquals(null, jedis.get("foooo")); } @Test public void testResetStateWhenInMultiWithinPipeline() { jedis.auth("foobared"); Pipeline p = jedis.pipelined(); p.multi(); p.set("foooo", "barrr"); jedis.resetState(); assertEquals(null, jedis.get("foooo")); } @Test public void testResetStateWhenInWatch() { jedis.watch("mykey", "somekey"); // state reset : unwatch jedis.resetState(); Transaction t = jedis.multi(); nj.connect(); nj.auth("foobared"); nj.set("mykey", "bar"); nj.disconnect(); t.set("mykey", "foo"); List<Object> resp = t.exec(); assertNotNull(resp); assertEquals(1, resp.size()); assertEquals("foo", jedis.get("mykey")); } @Test public void testResetStateWithFullyExecutedTransaction() { Jedis jedis2 = new Jedis(jedis.getClient().getHost(), jedis.getClient().getPort()); jedis2.auth("foobared"); Transaction t = jedis2.multi(); t.set("mykey", "foo"); t.get("mykey"); List<Object> resp = t.exec(); assertNotNull(resp); assertEquals(2, resp.size()); jedis2.resetState(); jedis2.close(); } @Test public void testCloseable() throws IOException { // we need to test with fresh instance of Jedis Jedis jedis2 = new Jedis(hnp.getHost(), hnp.getPort(), 500); jedis2.auth("foobared"); Transaction transaction = jedis2.multi(); transaction.set("a", "1"); transaction.set("b", "2"); transaction.close(); try { transaction.exec(); fail("close should discard transaction"); } catch (JedisDataException e) { assertTrue(e.getMessage().contains("EXEC without MULTI")); // pass } } }