package com.linkedin.databus.core; /* * * Copyright 2013 LinkedIn Corp. All rights reserved * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. * */ import static org.testng.AssertJUnit.assertEquals; import static org.testng.AssertJUnit.fail; import java.io.ByteArrayOutputStream; import java.io.IOException; import org.apache.log4j.Level; import org.apache.log4j.Logger; import org.codehaus.jackson.JsonParseException; import org.codehaus.jackson.map.JsonMappingException; import org.testng.Assert; import org.testng.annotations.BeforeClass; import org.testng.annotations.Test; import com.linkedin.databus2.test.TestUtil; public class TestCheckpoint { @BeforeClass public void setUpClass() { TestUtil.setupLogging(true, null, Level.ERROR); } @Test public void testCheckpoint() { try { Checkpoint cp = new Checkpoint("{\"scn\":1234, \"scnMessageOffset\":34}"); Assert.assertEquals(cp.getConsumptionMode(), DbusClientMode.INIT); } catch (JsonParseException e) { fail("Should not throw JSON parse exception"); } catch (JsonMappingException e) { fail("Should not throw JSON parse exception"); } catch (IOException e) { fail("Should not throw JSON parse exception"); } } //@Test public void testSetScn() { fail("Not yet implemented"); } //@Test public void testSetScnMessageOffset() { fail("Not yet implemented"); } //@Test public void testGetScn() { fail("Not yet implemented"); } //@Test public void testGetScnMessageOffset() { fail("Not yet implemented"); } @Test public void testInit() { Checkpoint cp = new Checkpoint(); assertEquals(cp.getInit(), true); cp.setWindowScn(1234L); cp.setWindowOffset(123); cp.setConsumptionMode(DbusClientMode.ONLINE_CONSUMPTION); assertEquals(cp.getInit(), false); cp.init(); assertEquals(cp.getInit(), true); } @Test public void testSerialize() throws JsonParseException, JsonMappingException, IOException { Checkpoint cp = Checkpoint.createOnlineConsumptionCheckpoint(1234L); cp.setWindowOffset(5677); cp.setPrevScn(1233L); ByteArrayOutputStream baos = new ByteArrayOutputStream(); cp.serialize(baos); //System.out.println("Serialized String="+ baos.toString()); Checkpoint newCp = new Checkpoint(baos.toString()); Assert.assertTrue(newCp.assertCheckpoint()); assertEquals(cp, newCp); Assert.assertEquals(cp.hashCode(), newCp.hashCode()); } @Test public void testLargeOffsets() throws JsonParseException, JsonMappingException, IOException { Checkpoint cp = new Checkpoint(); cp.setConsumptionMode(DbusClientMode.BOOTSTRAP_SNAPSHOT); cp.setWindowScn(1234L); cp.setWindowOffset(Long.MAX_VALUE-1); cp.onSnapshotEvent(Long.MAX_VALUE-2); cp.setBootstrapStartScn(100L); cp.bootstrapCheckPoint(); String cpString = cp.toString(); Checkpoint cp2 = new Checkpoint(cpString); assertEquals("Checkpoint with large bootstrap offsets",cp, cp2); } @Test public void testCreateOnlineCheckpoints() { Checkpoint cp = Checkpoint.createFlexibleCheckpoint(); Assert.assertEquals(cp.getConsumptionMode(), DbusClientMode.ONLINE_CONSUMPTION); Assert.assertTrue(cp.getFlexible()); Assert.assertFalse(cp.equals(null)); //please don't crash Assert.assertEquals(cp, cp); //duh final long scn = 1L + Integer.MAX_VALUE; cp = Checkpoint.createOnlineConsumptionCheckpoint(scn); Assert.assertEquals(cp, cp); //duh Assert.assertEquals(cp.getConsumptionMode(), DbusClientMode.ONLINE_CONSUMPTION); Assert.assertEquals(cp.getWindowOffset(), Checkpoint.FULLY_CONSUMED_WINDOW_OFFSET); Assert.assertEquals(cp.getWindowScn(), scn); Assert.assertEquals(cp.getPrevScn(), scn); Assert.assertFalse(cp.getFlexible()); Assert.assertEquals(cp.getTsNsecs(), Checkpoint.UNSET_TS_NSECS); } @Test public void testToFromString() throws JsonParseException, JsonMappingException, IOException { Checkpoint cp = Checkpoint.createFlexibleCheckpoint(); Checkpoint newCp = new Checkpoint(cp.toString()); Assert.assertTrue(newCp.assertCheckpoint()); Assert.assertEquals(newCp, cp); Assert.assertEquals(cp.hashCode(), newCp.hashCode()); cp = Checkpoint.createOnlineConsumptionCheckpoint(99999999999L); newCp = new Checkpoint(cp.toString()); Assert.assertTrue(newCp.assertCheckpoint()); Assert.assertEquals(newCp, cp); Assert.assertEquals(cp.hashCode(), newCp.hashCode()); cp = Checkpoint.createOnlineConsumptionCheckpoint(1); newCp = new Checkpoint(cp.toString()); Assert.assertTrue(newCp.assertCheckpoint()); Assert.assertEquals(newCp, cp); Assert.assertEquals(cp.hashCode(), newCp.hashCode()); cp = new Checkpoint(); cp.setBootstrapSinceScn(0L); cp.setConsumptionMode(DbusClientMode.BOOTSTRAP_SNAPSHOT); cp.setBootstrapStartScn(1000L); cp.setBootstrapSnapshotSourceIndex(2); cp.setSnapshotOffset(0xABCDEF0123456L); cp.setBootstrapCatchupSourceIndex(0); cp.setWindowScn(123L); cp.setWindowOffset(Checkpoint.FULLY_CONSUMED_WINDOW_OFFSET); Assert.assertEquals(cp, cp); //duh newCp = new Checkpoint(cp.toString()); Assert.assertTrue(newCp.assertCheckpoint()); Assert.assertEquals(newCp, cp); Assert.assertEquals(cp.hashCode(), newCp.hashCode()); cp = new Checkpoint(); cp.setBootstrapSinceScn(0L); cp.setConsumptionMode(DbusClientMode.BOOTSTRAP_SNAPSHOT); cp.setBootstrapSnapshotSourceIndex(1); cp.setBootstrapStartScn(1000L); cp.setBootstrapTargetScn(2000L); cp.setSnapshotOffset(-1); cp.setConsumptionMode(DbusClientMode.BOOTSTRAP_CATCHUP); cp.setBootstrapCatchupSourceIndex(1); cp.setWindowScn(123L); cp.setWindowOffset(0xABCDEFL); Assert.assertEquals(cp, cp); //duh newCp = new Checkpoint(cp.toString()); Assert.assertTrue(newCp.assertCheckpoint()); Assert.assertEquals(newCp, cp); Assert.assertEquals(cp.hashCode(), newCp.hashCode()); } @Test public void testOnlineCheckpointAsserts() throws JsonParseException, JsonMappingException, IOException { Checkpoint newCp = null; try { newCp = Checkpoint.createOnlineConsumptionCheckpoint(-1); Assert.fail("InvalidCheckpointException expected"); } catch (InvalidCheckpointException e) { //ok } try { newCp = Checkpoint.createOnlineConsumptionCheckpoint(1000000L); newCp.setPrevScn(10L); newCp.assertCheckpoint(); Assert.fail("InvalidCheckpointException expected"); } catch (InvalidCheckpointException e) { //ok } try { newCp = new Checkpoint("{\"windowScn\":10, \"prevScn\": 5, \"windowOffset\":-1, \"consumption_mode\":\"ONLINE_CONSUMPTION\"}"); newCp.assertCheckpoint(); Assert.fail("InvalidCheckpointException expected"); } catch (InvalidCheckpointException e) { //ok } try { newCp = Checkpoint.createOnlineConsumptionCheckpoint(1000000L); newCp.setWindowOffset(1000); newCp.setPrevScn(1000001L); newCp.assertCheckpoint(); Assert.fail("InvalidCheckpointException expected"); } catch (InvalidCheckpointException e) { //ok } try { newCp = Checkpoint.createOnlineConsumptionCheckpoint(1000000L); newCp.setWindowOffset(-101); newCp.assertCheckpoint(); Assert.fail("InvalidCheckpointException expected"); } catch (InvalidCheckpointException e) { //ok } try { newCp = Checkpoint.createFlexibleCheckpoint(); newCp.setTsNsecs(1L); newCp.assertCheckpoint(); Assert.fail("InvalidCheckpointException expected"); } catch (InvalidCheckpointException e) { // ok } } @Test public void testSnapshotCheckpointAsserts() { Checkpoint cp = null; try { cp = new Checkpoint(); cp.setConsumptionMode(DbusClientMode.BOOTSTRAP_SNAPSHOT); cp.assertCheckpoint(); Assert.fail("InvalidCheckpointException expected"); } catch (InvalidCheckpointException e) { //ok } try { cp.setBootstrapSinceScn(0L); cp.assertCheckpoint(); Assert.fail("InvalidCheckpointException expected"); } catch (InvalidCheckpointException e) { //ok } try { cp.setBootstrapSnapshotSourceIndex(1); cp.assertCheckpoint(); Assert.fail("InvalidCheckpointException expected"); } catch (InvalidCheckpointException e) { //ok } try { cp.setSnapshotOffset(-1); cp.setBootstrapCatchupSourceIndex(2); cp.assertCheckpoint(); Assert.fail("InvalidCheckpointException expected"); } catch (InvalidCheckpointException e) { //ok } try { cp.setSnapshotOffset(1000); cp.setBootstrapCatchupSourceIndex(1); cp.assertCheckpoint(); Assert.fail("InvalidCheckpointException expected"); } catch (InvalidCheckpointException e) { //ok } try { cp.setSnapshotOffset(1000); cp.setBootstrapCatchupSourceIndex(0); cp.assertCheckpoint(); Assert.fail("InvalidCheckpointException expected"); } catch (InvalidCheckpointException e) { //ok } } @Test public void testCatchupCheckpointAsserts() throws JsonParseException, JsonMappingException, IOException { final Logger log = Logger.getLogger("TestCheckpoint.testCatchupCheckpointAsserts"); Checkpoint cp = null; try { cp = new Checkpoint("{\"consumption_mode\":\"BOOTSTRAP_CATCHUP\"}"); cp.assertCheckpoint(); Assert.fail("InvalidCheckpointException expected"); } catch (InvalidCheckpointException e) { //ok -- bootstrap_since_scn must be set log.debug("exception thrown: " + e); } try { cp = new Checkpoint("{\"consumption_mode\":\"BOOTSTRAP_CATCHUP\", \"bootstrap_since_scn\":0}"); cp.assertCheckpoint(); Assert.fail("InvalidCheckpointException expected"); } catch (InvalidCheckpointException e) { //ok -- bootstrap_start_scn must be set log.debug("exception thrown: " + e); } try { cp = new Checkpoint("{\"consumption_mode\":\"BOOTSTRAP_CATCHUP\", \"bootstrap_since_scn\":0," + "\"bootstrap_start_scn\":1000}"); cp.assertCheckpoint(); Assert.fail("InvalidCheckpointException expected"); } catch (InvalidCheckpointException e) { //ok -- bootstrap_target_scn must be set log.debug("exception thrown: " + e); } try { cp = new Checkpoint("{\"consumption_mode\":\"BOOTSTRAP_CATCHUP\", \"bootstrap_since_scn\":0," + "\"bootstrap_start_scn\":1000,\"bootstrap_target_scn\":900}"); cp.setBootstrapTargetScn(900L); cp.assertCheckpoint(); Assert.fail("InvalidCheckpointException expected"); } catch (InvalidCheckpointException e) { //ok -- bootstrap_target_scn < bootstrap_start_scn log.debug("exception thrown: " + e); } try { cp = new Checkpoint("{\"consumption_mode\":\"BOOTSTRAP_CATCHUP\", \"bootstrap_since_scn\":0," + "\"bootstrap_start_scn\":1000,\"bootstrap_target_scn\":2000}"); cp.setBootstrapTargetScn(2000L); cp.setBootstrapSnapshotSourceIndex(-1); cp.assertCheckpoint(); Assert.fail("InvalidCheckpointException expected"); } catch (InvalidCheckpointException e) { //ok - missing bootstrap_catchup_source_index log.debug("exception thrown: " + e); } try { cp = new Checkpoint("{\"consumption_mode\":\"BOOTSTRAP_CATCHUP\", \"bootstrap_since_scn\":0," + "\"bootstrap_start_scn\":1000,\"bootstrap_target_scn\":2000,\"bootstrap_catchup_source_index\":1}"); cp.setBootstrapCatchupSourceIndex(1); cp.assertCheckpoint(); Assert.fail("InvalidCheckpointException expected"); } catch (InvalidCheckpointException e) { //ok -- bootstrap_catchup_snapshot index must be set log.debug("exception thrown: " + e); } try { cp = new Checkpoint("{\"consumption_mode\":\"BOOTSTRAP_CATCHUP\", \"bootstrap_since_scn\":0," + "\"bootstrap_start_scn\":1000,\"bootstrap_target_scn\":2000,\"bootstrap_catchup_source_index\":1," + "\"bootstrap_snapshot_source_index\":1, \"snapshot_offset\":1}"); cp.assertCheckpoint(); Assert.fail("InvalidCheckpointException expected"); } catch (InvalidCheckpointException e) { //ok - bootstrap_offset must be -1 log.debug("exception thrown: " + e); } try { cp = new Checkpoint("{\"consumption_mode\":\"BOOTSTRAP_CATCHUP\", \"bootstrap_since_scn\":0," + "\"bootstrap_start_scn\":1000,\"bootstrap_target_scn\":2000,\"bootstrap_catchup_source_index\":1," + "\"bootstrap_snapshot_source_index\":0}"); cp.assertCheckpoint(); Assert.fail("InvalidCheckpointException expected"); } catch (InvalidCheckpointException e) { //ok - bootstrap_catchup_source_index > bootstrap_catchup_snapshot index log.debug("exception thrown: " + e); } cp = new Checkpoint("{\"consumption_mode\":\"BOOTSTRAP_CATCHUP\", \"bootstrap_since_scn\":0," + "\"bootstrap_start_scn\":1000,\"bootstrap_target_scn\":2000,\"bootstrap_catchup_source_index\":1," + "\"bootstrap_snapshot_source_index\":1}"); cp.assertCheckpoint(); } @Test public void testV3Checkpoint() throws JsonParseException, JsonMappingException, IOException { Checkpoint cp = null; // Happy path, Add V3 bootstrap parameters for bootstrap SNAPSHOT checkpoint cp = new Checkpoint("{\"consumption_mode\":\"BOOTSTRAP_SNAPSHOT\", \"bootstrap_since_scn\":0," + "\"bootstrap_start_scn\":1000,\"bootstrap_target_scn\":2000,\"bootstrap_catchup_source_index\":0," + "\"bootstrap_snapshot_source_index\":1,"+"\"storage_cluster_name\":\"testCluster\","+ "\"bootstrap_snapshot_file_record_offset\":1000}"); cp.assertCheckpoint(); // Happy path, Add V3 bootstrap parameters for bootstrap CATCHUP checkpoint cp = new Checkpoint("{\"consumption_mode\":\"BOOTSTRAP_CATCHUP\", \"bootstrap_since_scn\":0," + "\"bootstrap_start_scn\":1000,\"bootstrap_target_scn\":2000,\"bootstrap_catchup_source_index\":1," + "\"bootstrap_snapshot_source_index\":1,"+"\"storage_cluster_name\":\"testCluster\","+ "\"bootstrap_snapshot_file_record_offset\":1000}"); cp.assertCheckpoint(); // Unhappy path; V3 bootstrap parameter file_record_offset set, but not cluster name - SNAPSHOT try { cp = new Checkpoint("{\"consumption_mode\":\"BOOTSTRAP_SNAPSHOT\", \"bootstrap_since_scn\":0," + "\"bootstrap_start_scn\":1000,\"bootstrap_target_scn\":2000,\"bootstrap_catchup_source_index\":0," + "\"bootstrap_snapshot_source_index\":1,"+"\"storage_cluster_name\":\"\","+ "\"bootstrap_snapshot_file_record_offset\":1000}"); cp.assertCheckpoint(); Assert.fail("The above checkpoint " + cp + " is invalid"); } catch (InvalidCheckpointException e) { } // Unhappy path; V3 bootstrap parameter file_record_offset set, but not cluster name - CATCHUP try { cp = new Checkpoint("{\"consumption_mode\":\"BOOTSTRAP_CATCHUP\", \"bootstrap_since_scn\":0," + "\"bootstrap_start_scn\":1000,\"bootstrap_target_scn\":2000,\"bootstrap_catchup_source_index\":2," + "\"bootstrap_snapshot_source_index\":1,"+"\"storage_cluster_name\":\"\","+ "\"bootstrap_snapshot_file_record_offset\":1000}"); cp.assertCheckpoint(); Assert.fail("The above checkpoint " + cp + " is invalid"); } catch (InvalidCheckpointException e) { } } @Test public void testCopyBootstrapSnapshotCheckpoint() throws JsonParseException, JsonMappingException, IOException { Checkpoint cp = null; // Happy path, Add V3 bootstrap parameters for bootstrap SNAPSHOT checkpoint cp = new Checkpoint("{\"consumption_mode\":\"BOOTSTRAP_SNAPSHOT\", \"bootstrap_since_scn\":0," + "\"bootstrap_start_scn\":1000,\"bootstrap_target_scn\":2000,\"bootstrap_catchup_source_index\":0," + "\"bootstrap_snapshot_source_index\":1,"+"\"storage_cluster_name\":\"testCluster\","+ "\"bootstrap_snapshot_file_record_offset\":1000}"); cp.assertCheckpoint(); Checkpoint cp2 = new Checkpoint("{\"consumption_mode\":\"BOOTSTRAP_SNAPSHOT\", \"bootstrap_since_scn\":0," + "\"bootstrap_start_scn\":1000,\"bootstrap_target_scn\":2000,\"bootstrap_catchup_source_index\":0," + "\"bootstrap_snapshot_source_index\":1,"+"\"storage_cluster_name\":\"testCluster\","+ "\"bootstrap_snapshot_file_record_offset\":2000}"); cp2.copyBootstrapSnapshotCheckpoint(cp); Assert.assertEquals(cp2.getSnapshotFileRecordOffset(), cp.getSnapshotFileRecordOffset()); } @Test public void testCopyBootstrapCatchupCheckpoint() throws JsonParseException, JsonMappingException, IOException { Checkpoint cp = null; // Happy path, Add V3 bootstrap parameters for bootstrap SNAPSHOT checkpoint cp = new Checkpoint("{\"consumption_mode\":\"BOOTSTRAP_CATCHUP\", \"bootstrap_since_scn\":0," + "\"bootstrap_start_scn\":1000,\"bootstrap_target_scn\":2000,\"bootstrap_catchup_source_index\":1," + "\"bootstrap_snapshot_source_index\":1,"+"\"storage_cluster_name\":\"testCluster\","+ "\"bootstrap_snapshot_file_record_offset\":1000}"); cp.assertCheckpoint(); Checkpoint cp2 = new Checkpoint("{\"consumption_mode\":\"BOOTSTRAP_CATCHUP\", \"bootstrap_since_scn\":0," + "\"bootstrap_start_scn\":1000,\"bootstrap_target_scn\":2000,\"bootstrap_catchup_source_index\":1," + "\"bootstrap_snapshot_source_index\":1,"+"\"storage_cluster_name\":\"testCluster\","+ "\"bootstrap_snapshot_file_record_offset\":2000}"); cp2.copyBootstrapCatchupCheckpoint(cp); Assert.assertEquals(cp2.getSnapshotFileRecordOffset(), cp.getSnapshotFileRecordOffset()); } @Test public void testEqualsHashCodeForV3Bootstrap() throws JsonParseException, JsonMappingException, IOException { Checkpoint cp = null; cp = new Checkpoint("{\"consumption_mode\":\"BOOTSTRAP_CATCHUP\", \"bootstrap_since_scn\":0," + "\"bootstrap_start_scn\":1000,\"bootstrap_target_scn\":2000,\"bootstrap_catchup_source_index\":1," + "\"bootstrap_snapshot_source_index\":1,"+"\"storage_cluster_name\":\"testCluster\","+ "\"bootstrap_snapshot_file_record_offset\":1000}"); // Reflexive Assert.assertEquals(cp, cp); Checkpoint cp2 = new Checkpoint("{\"consumption_mode\":\"BOOTSTRAP_CATCHUP\", \"bootstrap_since_scn\":0," + "\"bootstrap_start_scn\":1000,\"bootstrap_target_scn\":2000,\"bootstrap_catchup_source_index\":1," + "\"bootstrap_snapshot_source_index\":1,"+"\"storage_cluster_name\":\"testCluster\","+ "\"bootstrap_snapshot_file_record_offset\":1000}"); // Symmetric Assert.assertEquals(cp2, cp); Checkpoint cp3 = cp2.clone(); Assert.assertEquals(cp3, cp2); Assert.assertEquals(cp, cp3); } @Test public void testEqualsHashCodeForV3BootstrapBackwardCompat() throws JsonParseException, JsonMappingException, IOException { Checkpoint cp = null; cp = new Checkpoint("{\"consumption_mode\":\"BOOTSTRAP_CATCHUP\", \"bootstrap_since_scn\":0," + "\"bootstrap_start_scn\":1000,\"bootstrap_target_scn\":2000,\"bootstrap_catchup_source_index\":1," + "\"bootstrap_snapshot_source_index\":1,"+"\"storage_cluster_name\":\"\","+ "\"bootstrap_snapshot_file_record_offset\":-1}"); Checkpoint cp2 = new Checkpoint("{\"consumption_mode\":\"BOOTSTRAP_CATCHUP\", \"bootstrap_since_scn\":0," + "\"bootstrap_start_scn\":1000,\"bootstrap_target_scn\":2000,\"bootstrap_catchup_source_index\":1," + "\"bootstrap_snapshot_source_index\":1}"); Assert.assertTrue(cp2.equals(cp)); // The new checkpoint with default values and the old checkpoint without these fields are different. // But because we are not using the V3 checkpoints for bootstrap this is ok. Assert.assertFalse(cp.equals(cp2)); } // Test the case where a manual checkpoint is created with scn set to 0 but timestamp is non-zero. @Test public void testTimestampBasedCheckpoint() throws Exception { final long ts = 23534677L; Checkpoint cp = Checkpoint.createOnlineConsumptionCheckpoint(0L); cp.setTsNsecs(ts); Assert.assertTrue(cp.assertCheckpoint()); String serCp = cp.toString(); Checkpoint newCp = new Checkpoint(serCp); Assert.assertTrue(newCp.assertCheckpoint()); Assert.assertEquals(newCp.getTsNsecs(), ts); } }