|
@@ -45,6 +45,7 @@ import org.apache.zookeeper.PortAssignment;
|
|
|
import org.apache.zookeeper.ZooDefs.Ids;
|
|
|
import org.apache.zookeeper.ZooDefs.OpCode;
|
|
|
import org.apache.zookeeper.data.Id;
|
|
|
+import org.apache.zookeeper.data.Stat;
|
|
|
import org.apache.zookeeper.proto.CreateRequest;
|
|
|
import org.apache.zookeeper.proto.ReconfigRequest;
|
|
|
import org.apache.zookeeper.proto.RequestHeader;
|
|
@@ -59,6 +60,7 @@ import org.apache.zookeeper.server.quorum.QuorumPeerConfig;
|
|
|
import org.apache.zookeeper.server.quorum.flexible.QuorumVerifier;
|
|
|
import org.apache.zookeeper.test.ClientBase;
|
|
|
import org.apache.zookeeper.txn.ErrorTxn;
|
|
|
+import org.apache.zookeeper.txn.SetDataTxn;
|
|
|
import org.junit.jupiter.api.AfterEach;
|
|
|
import org.junit.jupiter.api.BeforeEach;
|
|
|
import org.junit.jupiter.api.Test;
|
|
@@ -391,4 +393,110 @@ public class PrepRequestProcessorTest extends ClientBase {
|
|
|
return Collections.emptySet();
|
|
|
}
|
|
|
}
|
|
|
+
|
|
|
+ @Test
|
|
|
+ public void testCheckAndIncVersion() throws Exception {
|
|
|
+ zks.getZKDatabase().dataTree.createNode("/foo", new byte[0], Ids.OPEN_ACL_UNSAFE, 0, 0, 0, 0);
|
|
|
+ pLatch = new CountDownLatch(1);
|
|
|
+ processor = new PrepRequestProcessor(zks, new MyRequestProcessor());
|
|
|
+
|
|
|
+ SetDataRequest record = new SetDataRequest("/foo", new byte[0], 0);
|
|
|
+ Request req = createRequest(record, OpCode.setData, false);
|
|
|
+ processor.pRequest(req);
|
|
|
+ pLatch.await();
|
|
|
+ assertEquals(OpCode.setData, outcome.getHdr().getType());
|
|
|
+ assertTrue(outcome.getTxn() instanceof SetDataTxn);
|
|
|
+ SetDataTxn setDataTxn = (SetDataTxn) outcome.getTxn();
|
|
|
+ assertEquals(1, setDataTxn.getVersion());
|
|
|
+ }
|
|
|
+
|
|
|
+ @Test
|
|
|
+ public void testCheckAndIncVersionOverflow() throws Exception {
|
|
|
+ Stat customStat = new Stat();
|
|
|
+ customStat.setVersion(Integer.MAX_VALUE);
|
|
|
+ zks.getZKDatabase().dataTree.createNode("/foo", new byte[0], Ids.OPEN_ACL_UNSAFE, 0, 0, 0, 0);
|
|
|
+ DataNode node = zks.getZKDatabase().dataTree.getNode("/foo");
|
|
|
+ node.stat = DataTree.createStat(Integer.MAX_VALUE);
|
|
|
+
|
|
|
+ pLatch = new CountDownLatch(1);
|
|
|
+ processor = new PrepRequestProcessor(zks, new MyRequestProcessor());
|
|
|
+
|
|
|
+ SetDataRequest record = new SetDataRequest("/foo", new byte[0], Integer.MAX_VALUE);
|
|
|
+ Request req = createRequest(record, OpCode.setData, false);
|
|
|
+ processor.pRequest(req);
|
|
|
+ pLatch.await();
|
|
|
+ assertEquals(OpCode.setData, outcome.getHdr().getType());
|
|
|
+ assertTrue(outcome.getTxn() instanceof SetDataTxn);
|
|
|
+ SetDataTxn setDataTxn = (SetDataTxn) outcome.getTxn();
|
|
|
+ assertEquals(Integer.MIN_VALUE, setDataTxn.getVersion());
|
|
|
+ }
|
|
|
+ @Test
|
|
|
+ public void testCheckAndIncVersionWithNegativeNumber() throws Exception {
|
|
|
+ zks.getZKDatabase().dataTree.createNode("/foo", new byte[0], Ids.OPEN_ACL_UNSAFE, 0, 0, 0, 0);
|
|
|
+ DataNode node = zks.getZKDatabase().dataTree.getNode("/foo");
|
|
|
+ node.stat = DataTree.createStat(Integer.MIN_VALUE);
|
|
|
+
|
|
|
+ pLatch = new CountDownLatch(1);
|
|
|
+ processor = new PrepRequestProcessor(zks, new MyRequestProcessor());
|
|
|
+
|
|
|
+ SetDataRequest record = new SetDataRequest("/foo", new byte[0], Integer.MIN_VALUE);
|
|
|
+ Request req = createRequest(record, OpCode.setData, false);
|
|
|
+ processor.pRequest(req);
|
|
|
+ pLatch.await();
|
|
|
+ assertEquals(OpCode.setData, outcome.getHdr().getType());
|
|
|
+ assertTrue(outcome.getTxn() instanceof SetDataTxn);
|
|
|
+ SetDataTxn setDataTxn = (SetDataTxn) outcome.getTxn();
|
|
|
+ assertEquals(Integer.MIN_VALUE + 1, setDataTxn.getVersion());
|
|
|
+ }
|
|
|
+
|
|
|
+ @Test
|
|
|
+ public void testCheckAndIncToZeroFromNegativeTwo() throws Exception {
|
|
|
+ zks.getZKDatabase().dataTree.createNode("/foo", new byte[0], Ids.OPEN_ACL_UNSAFE, 0, 0, 0, 0);
|
|
|
+ DataNode node = zks.getZKDatabase().dataTree.getNode("/foo");
|
|
|
+ node.stat = DataTree.createStat(-2);
|
|
|
+
|
|
|
+ pLatch = new CountDownLatch(1);
|
|
|
+ processor = new PrepRequestProcessor(zks, new MyRequestProcessor());
|
|
|
+
|
|
|
+ SetDataRequest record = new SetDataRequest("/foo", new byte[0], -2);
|
|
|
+ Request req = createRequest(record, OpCode.setData, false);
|
|
|
+ processor.pRequest(req);
|
|
|
+ pLatch.await();
|
|
|
+ assertEquals(OpCode.setData, outcome.getHdr().getType());
|
|
|
+ assertTrue(outcome.getTxn() instanceof SetDataTxn);
|
|
|
+ SetDataTxn setDataTxn = (SetDataTxn) outcome.getTxn();
|
|
|
+ assertEquals(0, setDataTxn.getVersion());
|
|
|
+ }
|
|
|
+
|
|
|
+ @Test
|
|
|
+ public void testCheckAndIncSkipEqualityCheck() throws Exception {
|
|
|
+ zks.getZKDatabase().dataTree.createNode("/foo", new byte[0], Ids.OPEN_ACL_UNSAFE, 0, 0, 0, 0);
|
|
|
+ DataNode node = zks.getZKDatabase().dataTree.getNode("/foo");
|
|
|
+
|
|
|
+ pLatch = new CountDownLatch(1);
|
|
|
+ processor = new PrepRequestProcessor(zks, new MyRequestProcessor());
|
|
|
+
|
|
|
+ SetDataRequest record = new SetDataRequest("/foo", new byte[0], -1);
|
|
|
+ Request req = createRequest(record, OpCode.setData, false);
|
|
|
+ processor.pRequest(req);
|
|
|
+ pLatch.await();
|
|
|
+ assertEquals(OpCode.setData, outcome.getHdr().getType());
|
|
|
+ assertTrue(outcome.getTxn() instanceof SetDataTxn);
|
|
|
+ SetDataTxn setDataTxn = (SetDataTxn) outcome.getTxn();
|
|
|
+ assertEquals(1, setDataTxn.getVersion());
|
|
|
+ }
|
|
|
+
|
|
|
+ @Test
|
|
|
+ public void testCheckAndIncWithBadVersion() throws Exception {
|
|
|
+ zks.getZKDatabase().dataTree.createNode("/foo", new byte[0], Ids.OPEN_ACL_UNSAFE, 0, 0, 0, 0);
|
|
|
+ pLatch = new CountDownLatch(1);
|
|
|
+ processor = new PrepRequestProcessor(zks, new MyRequestProcessor());
|
|
|
+
|
|
|
+ SetDataRequest record = new SetDataRequest("/foo", new byte[0], 1);
|
|
|
+ Request req = createRequest(record, OpCode.setData, false);
|
|
|
+ processor.pRequest(req);
|
|
|
+ pLatch.await();
|
|
|
+ assertEquals(OpCode.error, outcome.getHdr().getType());
|
|
|
+ assertEquals(KeeperException.Code.BADVERSION, outcome.getException().code());
|
|
|
+ }
|
|
|
}
|