package com.linkedin.databus.bootstrap.server; /* * * 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 junit.framework.Assert; import org.easymock.EasyMock; import org.testng.annotations.Test; import com.linkedin.databus.bootstrap.api.BootstrapEventCallback; import com.linkedin.databus.bootstrap.api.BootstrapEventProcessResult; import com.linkedin.databus.core.Checkpoint; public class TestBootstrapProcessor { @Test public void testIsPhaseCompletedFlag() throws Exception { BootstrapProcessor bp = new BootstrapProcessor(); long processedRowCount = 1; // order of args : processedRowCount, isLimitExceeded, isDropped, isError BootstrapEventProcessResult result_ok = new BootstrapEventProcessResult(processedRowCount, false, false, false); BootstrapEventProcessResult result_err = new BootstrapEventProcessResult(processedRowCount, false, false, true); BootstrapEventProcessResult result_ile = new BootstrapEventProcessResult(processedRowCount, true, false, false); Checkpoint ckpt_ss = 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}"); ckpt_ss.assertCheckpoint(); Checkpoint ckpt_cu = 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}"); ckpt_cu.assertCheckpoint(); long numRowsReadFromDb = 1; long maxRowsPerFetch = 2; long windowScn = 1; // result is null, phaseCompleted == false ( irrespective of snapshot / catchup phase ) numRowsReadFromDb = 0; boolean pc = bp.computeIsPhaseCompleted(null, ckpt_ss, numRowsReadFromDb, maxRowsPerFetch, windowScn); Assert.assertTrue(pc); pc = bp.computeIsPhaseCompleted(null, ckpt_cu, numRowsReadFromDb, maxRowsPerFetch, windowScn); Assert.assertTrue(pc); numRowsReadFromDb = 1; // numRowsReadFromDb < maxRowsPerFetch, in SNAPSHOT mode pc = bp.computeIsPhaseCompleted(result_ok, ckpt_ss, numRowsReadFromDb, maxRowsPerFetch, windowScn); Assert.assertTrue(pc); // Same as above, but result.isError == true ( overrides all other conditions ) pc = bp.computeIsPhaseCompleted(result_err, ckpt_ss, numRowsReadFromDb, maxRowsPerFetch, windowScn); Assert.assertFalse(pc); // Same as above, but result.isLimitExceeded == true ( overrides all other conditions ) pc = bp.computeIsPhaseCompleted(result_ile, ckpt_ss, numRowsReadFromDb, maxRowsPerFetch, windowScn); Assert.assertFalse(pc); // numRowsReadFromDb == maxRowsPerFetch, in SNAPSHOT mode numRowsReadFromDb = 2; pc = bp.computeIsPhaseCompleted(result_ok, ckpt_ss, numRowsReadFromDb, maxRowsPerFetch, windowScn); Assert.assertFalse(pc); // Same as above, but result.isError == true pc = bp.computeIsPhaseCompleted(result_err, ckpt_ss, numRowsReadFromDb, maxRowsPerFetch, windowScn); Assert.assertFalse(pc); // Same as above, but result.isLimitExceeded == true pc = bp.computeIsPhaseCompleted(result_ile, ckpt_ss, numRowsReadFromDb, maxRowsPerFetch, windowScn); Assert.assertFalse(pc); numRowsReadFromDb = 1; // numRowsReadFromDb < maxRowsPerFetch, in CATCHUP mode, windowScn != bootstrap_target_scn pc = bp.computeIsPhaseCompleted(result_ok, ckpt_ss, numRowsReadFromDb, maxRowsPerFetch, windowScn); Assert.assertTrue(pc); windowScn = ckpt_cu.getBootstrapTargetScn(); pc = bp.computeIsPhaseCompleted(result_ok, ckpt_cu, numRowsReadFromDb, maxRowsPerFetch, windowScn); Assert.assertTrue(pc); // Same as above, but result.isError == true ( overrides all other conditions ) pc = bp.computeIsPhaseCompleted(result_err, ckpt_ss, numRowsReadFromDb, maxRowsPerFetch, windowScn); Assert.assertFalse(pc); // Same as above, but result.isLimitExceeded == true ( overrides result being null ) pc = bp.computeIsPhaseCompleted(result_ile, ckpt_ss, numRowsReadFromDb, maxRowsPerFetch, windowScn); Assert.assertFalse(pc); // numRowsReadFromDb == maxRowsPerFetch, in CATCHUP mode numRowsReadFromDb = 2; windowScn = 10; // not equal to bootstrap_target_scn pc = bp.computeIsPhaseCompleted(result_ok, ckpt_cu, numRowsReadFromDb, maxRowsPerFetch, windowScn); Assert.assertFalse(pc); windowScn = ckpt_cu.getBootstrapTargetScn(); // equal to bootstrap_target_scn, but does not matter still pc = bp.computeIsPhaseCompleted(result_ok, ckpt_cu, numRowsReadFromDb, maxRowsPerFetch, windowScn); Assert.assertFalse(pc); // Same as above, but result.isError == true pc = bp.computeIsPhaseCompleted(result_err, ckpt_cu, numRowsReadFromDb, maxRowsPerFetch, windowScn); Assert.assertFalse(pc); // Same as above, but result.isLimitExceeded == true pc = bp.computeIsPhaseCompleted(result_ile, ckpt_cu, numRowsReadFromDb, maxRowsPerFetch, windowScn); Assert.assertFalse(pc); } @Test public void testCkptWriteLogic() throws Exception { BootstrapProcessor bp = new BootstrapProcessor(); long processedRowCount = 1; // order of args : processedRowCount, isLimitExceeded, isDropped, isError BootstrapEventProcessResult result_ok = new BootstrapEventProcessResult(processedRowCount, false, false, false); BootstrapEventProcessResult result_zero_ok = new BootstrapEventProcessResult(0, false, false, false); BootstrapEventProcessResult result_err = new BootstrapEventProcessResult(processedRowCount, false, false, true); BootstrapEventProcessResult result_zero_ile = new BootstrapEventProcessResult(0, true, false, false); Checkpoint ckpt_ss = 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}"); ckpt_ss.assertCheckpoint(); long numRowsReadFromDb = 1; BootstrapEventCallback callback1 = EasyMock.createMock(BootstrapEventCallback.class); EasyMock.replay(callback1); BootstrapEventCallback callback2 = EasyMock.createMock(BootstrapEventCallback.class); callback2.onCheckpointEvent(ckpt_ss, null); EasyMock.replay(callback2); BootstrapEventCallback callback3 = EasyMock.createMock(BootstrapEventCallback.class); callback3.onCheckpointEvent(ckpt_ss, null); EasyMock.replay(callback3); // No checkpoint when result is null bp.writeCkptIfAppropriate(null, callback1, numRowsReadFromDb, ckpt_ss, "test"); // No checkpoint when result is error bp.writeCkptIfAppropriate(result_err, callback1, numRowsReadFromDb, ckpt_ss, "test"); // numRowsWritten == 1, must checkpoint bp.writeCkptIfAppropriate(result_ok, callback2, numRowsReadFromDb, ckpt_ss, "test"); // numRowsWritten == 0, must checkpoint as numRowsReadFromDb > 0 bp.writeCkptIfAppropriate(result_zero_ok, callback3, numRowsReadFromDb, ckpt_ss, "test"); // numRowsWritten == 0, must have checkpointed as numRowsReadFromDb > 0. However result is client buffer exceeded // So .. sorry to disappoint but no checkpoint as we want that pending_event_header bp.writeCkptIfAppropriate(result_zero_ile, callback1, numRowsReadFromDb, ckpt_ss, "test"); // result != null, numRowsWritten == 0, numRowsReadFromDb == 0. We expect a RuntimeException here try { bp.writeCkptIfAppropriate(result_zero_ok, callback2, 0, ckpt_ss, "test"); Assert.fail(); } catch (RuntimeException e) { } } }