public final class FailoverServiceTest { @Mock private JobNodeStorage jobNodeStorage; @Mock private LocalHostService localHostService; @Mock private ServerService serverService; @Mock private ShardingService shardingService; @Mock private JobScheduleController jobScheduleController; private final JobConfiguration jobConfig = JobConfigurationFactory.createSimpleJobConfigurationBuilder( "testJob", TestJob.class, 3, "0/1 * * * * ?") .overwrite(true) .build(); private final FailoverService failoverService = new FailoverService(null, jobConfig); @Before public void setUp() throws NoSuchFieldException { MockitoAnnotations.initMocks(this); ReflectionUtils.setFieldValue(failoverService, "jobNodeStorage", jobNodeStorage); ReflectionUtils.setFieldValue(failoverService, "localHostService", localHostService); ReflectionUtils.setFieldValue(failoverService, "serverService", serverService); ReflectionUtils.setFieldValue(failoverService, "shardingService", shardingService); when(localHostService.getIp()).thenReturn("mockedIP"); when(localHostService.getHostName()).thenReturn("mockedHostName"); when(jobNodeStorage.getJobConfiguration()).thenReturn(jobConfig); } @Test public void assertSetCrashedFailoverFlagWhenItemIsNotAssigned() { when(jobNodeStorage.isJobNodeExisted("execution/0/failover")).thenReturn(true); failoverService.setCrashedFailoverFlag(0); verify(jobNodeStorage).isJobNodeExisted("execution/0/failover"); verify(jobNodeStorage, times(0)).createJobNodeIfNeeded("leader/failover/items/0"); } @Test public void assertSetCrashedFailoverFlagWhenItemIsAssigned() { when(jobNodeStorage.isJobNodeExisted("execution/0/failover")).thenReturn(false); failoverService.setCrashedFailoverFlag(0); verify(jobNodeStorage).isJobNodeExisted("execution/0/failover"); verify(jobNodeStorage).createJobNodeIfNeeded("leader/failover/items/0"); } @Test public void assertFailoverIfUnnecessaryWhenItemsRootNodeNotExisted() { when(jobNodeStorage.isJobNodeExisted("leader/failover/items")).thenReturn(false); failoverService.failoverIfNecessary(); verify(jobNodeStorage).isJobNodeExisted("leader/failover/items"); verify(jobNodeStorage, times(0)) .executeInLeader( eq("leader/failover/latch"), Matchers.<FailoverLeaderExecutionCallback>any()); } @Test public void assertFailoverIfUnnecessaryWhenItemsRootNodeIsEmpty() { when(jobNodeStorage.isJobNodeExisted("leader/failover/items")).thenReturn(true); when(jobNodeStorage.getJobNodeChildrenKeys("leader/failover/items")) .thenReturn(Collections.<String>emptyList()); failoverService.failoverIfNecessary(); verify(jobNodeStorage).isJobNodeExisted("leader/failover/items"); verify(jobNodeStorage).getJobNodeChildrenKeys("leader/failover/items"); verify(jobNodeStorage, times(0)) .executeInLeader( eq("leader/failover/latch"), Matchers.<FailoverLeaderExecutionCallback>any()); } @Test public void assertFailoverIfUnnecessaryWhenServerIsNotReady() { when(jobNodeStorage.isJobNodeExisted("leader/failover/items")).thenReturn(true); when(jobNodeStorage.getJobNodeChildrenKeys("leader/failover/items")) .thenReturn(Arrays.asList("0", "1", "2")); when(serverService.isLocalhostServerReady()).thenReturn(false); failoverService.failoverIfNecessary(); verify(jobNodeStorage).isJobNodeExisted("leader/failover/items"); verify(jobNodeStorage).getJobNodeChildrenKeys("leader/failover/items"); verify(serverService).isLocalhostServerReady(); verify(jobNodeStorage, times(0)) .executeInLeader( eq("leader/failover/latch"), Matchers.<FailoverLeaderExecutionCallback>any()); } @Test public void assertFailoverIfNecessary() { when(jobNodeStorage.isJobNodeExisted("leader/failover/items")).thenReturn(true); when(jobNodeStorage.getJobNodeChildrenKeys("leader/failover/items")) .thenReturn(Arrays.asList("0", "1", "2")); when(serverService.isLocalhostServerReady()).thenReturn(true); failoverService.failoverIfNecessary(); verify(jobNodeStorage).isJobNodeExisted("leader/failover/items"); verify(jobNodeStorage).getJobNodeChildrenKeys("leader/failover/items"); verify(serverService).isLocalhostServerReady(); verify(jobNodeStorage) .executeInLeader( eq("leader/failover/latch"), Matchers.<FailoverLeaderExecutionCallback>any()); } @Test public void assertFailoverLeaderExecutionCallbackIfNotNecessary() { when(jobNodeStorage.isJobNodeExisted("leader/failover/items")).thenReturn(false); failoverService.new FailoverLeaderExecutionCallback().execute(); verify(jobNodeStorage).isJobNodeExisted("leader/failover/items"); verify(jobNodeStorage, times(0)).getJobNodeChildrenKeys("leader/failover/items"); } @Test public void assertFailoverLeaderExecutionCallbackIfNecessary() { when(jobNodeStorage.isJobNodeExisted("leader/failover/items")).thenReturn(true); when(jobNodeStorage.getJobNodeChildrenKeys("leader/failover/items")) .thenReturn(Arrays.asList("0", "1", "2")); when(serverService.isLocalhostServerReady()).thenReturn(true); JobRegistry.getInstance().addJobScheduleController("testJob", jobScheduleController); failoverService.new FailoverLeaderExecutionCallback().execute(); verify(jobNodeStorage).isJobNodeExisted("leader/failover/items"); verify(jobNodeStorage, times(2)).getJobNodeChildrenKeys("leader/failover/items"); verify(serverService).isLocalhostServerReady(); verify(jobNodeStorage).fillEphemeralJobNode("execution/0/failover", "mockedIP"); verify(jobNodeStorage).removeJobNodeIfExisted("leader/failover/items/0"); verify(jobScheduleController).triggerJob(); } @Test public void assertUpdateFailoverComplete() { failoverService.updateFailoverComplete(Arrays.asList(0, 1)); verify(jobNodeStorage).removeJobNodeIfExisted("execution/0/failover"); verify(jobNodeStorage).removeJobNodeIfExisted("execution/1/failover"); } @Test public void assertGetLocalHostFailoverItems() { when(jobNodeStorage.getJobNodeChildrenKeys("execution")) .thenReturn(Arrays.asList("0", "1", "2")); when(jobNodeStorage.isJobNodeExisted("execution/0/failover")).thenReturn(true); when(jobNodeStorage.isJobNodeExisted("execution/1/failover")).thenReturn(true); when(jobNodeStorage.isJobNodeExisted("execution/2/failover")).thenReturn(false); when(jobNodeStorage.getJobNodeDataDirectly("execution/0/failover")).thenReturn("mockedIP"); when(jobNodeStorage.getJobNodeDataDirectly("execution/1/failover")).thenReturn("otherIP"); assertThat(failoverService.getLocalHostFailoverItems(), is(Collections.singletonList(0))); verify(jobNodeStorage).getJobNodeChildrenKeys("execution"); verify(localHostService).getIp(); verify(jobNodeStorage).isJobNodeExisted("execution/0/failover"); verify(jobNodeStorage).isJobNodeExisted("execution/1/failover"); verify(jobNodeStorage).getJobNodeDataDirectly("execution/0/failover"); verify(jobNodeStorage).getJobNodeDataDirectly("execution/1/failover"); } @Test public void assertGetLocalHostTakeOffItems() { when(shardingService.getLocalHostShardingItems()).thenReturn(Arrays.asList(0, 1, 2)); when(jobNodeStorage.isJobNodeExisted("execution/0/failover")).thenReturn(true); when(jobNodeStorage.isJobNodeExisted("execution/1/failover")).thenReturn(true); when(jobNodeStorage.isJobNodeExisted("execution/2/failover")).thenReturn(false); assertThat(failoverService.getLocalHostTakeOffItems(), is(Arrays.asList(0, 1))); verify(shardingService).getLocalHostShardingItems(); verify(jobNodeStorage).isJobNodeExisted("execution/0/failover"); verify(jobNodeStorage).isJobNodeExisted("execution/1/failover"); verify(jobNodeStorage).isJobNodeExisted("execution/2/failover"); } @Test public void assertRemoveFailoverInfo() { when(jobNodeStorage.getJobNodeChildrenKeys("execution")) .thenReturn(Arrays.asList("0", "1", "2")); failoverService.removeFailoverInfo(); verify(jobNodeStorage).getJobNodeChildrenKeys("execution"); verify(jobNodeStorage).removeJobNodeIfExisted("execution/0/failover"); verify(jobNodeStorage).removeJobNodeIfExisted("execution/1/failover"); verify(jobNodeStorage).removeJobNodeIfExisted("execution/2/failover"); } }
public final class JobNodeStorageTest { @Mock private CoordinatorRegistryCenter coordinatorRegistryCenter; private SimpleJobConfiguration jobConfig = JobConfigurationFactory.createSimpleJobConfigurationBuilder( "testJob", TestJob.class, 3, "0/1 * * * * ?") .overwrite(false) .build(); private JobNodeStorage jobNodeStorage = new JobNodeStorage(coordinatorRegistryCenter, jobConfig); @Before public void initMocks() throws NoSuchFieldException { MockitoAnnotations.initMocks(this); ReflectionUtils.setFieldValue( jobNodeStorage, "coordinatorRegistryCenter", coordinatorRegistryCenter); } @Before public void reset() { JobConfigurationFieldUtil.setSuperFieldValue(jobConfig, "overwrite", false); } @Test public void assertIsJobNodeExisted() { when(coordinatorRegistryCenter.isExisted("/testJob/config")).thenReturn(true); assertTrue(jobNodeStorage.isJobNodeExisted("config")); verify(coordinatorRegistryCenter).isExisted("/testJob/config"); } @Test public void assertGetJobNodeData() { when(coordinatorRegistryCenter.get("/testJob/config/cron")).thenReturn("0/1 * * * * ?"); assertThat(jobNodeStorage.getJobNodeData("config/cron"), is("0/1 * * * * ?")); verify(coordinatorRegistryCenter).get("/testJob/config/cron"); } @Test public void assertGetJobNodeDataDirectly() { when(coordinatorRegistryCenter.getDirectly("/testJob/config/cron")).thenReturn("0/1 * * * * ?"); assertThat(jobNodeStorage.getJobNodeDataDirectly("config/cron"), is("0/1 * * * * ?")); verify(coordinatorRegistryCenter).getDirectly("/testJob/config/cron"); } @Test public void assertGetJobNodeChildrenKeys() { when(coordinatorRegistryCenter.getChildrenKeys("/testJob/servers")) .thenReturn(Arrays.asList("host0", "host1")); assertThat( jobNodeStorage.getJobNodeChildrenKeys("servers"), is(Arrays.asList("host0", "host1"))); verify(coordinatorRegistryCenter).getChildrenKeys("/testJob/servers"); } @Test public void assertCreateJobNodeIfNeeded() { when(coordinatorRegistryCenter.isExisted("/testJob")).thenReturn(true); when(coordinatorRegistryCenter.isExisted("/testJob/config")).thenReturn(false); jobNodeStorage.createJobNodeIfNeeded("config"); verify(coordinatorRegistryCenter).isExisted("/testJob"); verify(coordinatorRegistryCenter).isExisted("/testJob/config"); verify(coordinatorRegistryCenter).persist("/testJob/config", ""); } @Test public void assertCreateJobNodeIfRootJobNodeIsNotExist() { when(coordinatorRegistryCenter.isExisted("/testJob")).thenReturn(false); when(coordinatorRegistryCenter.isExisted("/testJob/config")).thenReturn(true); jobNodeStorage.createJobNodeIfNeeded("config"); verify(coordinatorRegistryCenter).isExisted("/testJob"); verify(coordinatorRegistryCenter, times(0)).isExisted("/testJob/config"); verify(coordinatorRegistryCenter, times(0)).persist("/testJob/config", ""); } @Test public void assertCreateJobNodeIfNotNeeded() { when(coordinatorRegistryCenter.isExisted("/testJob")).thenReturn(true); when(coordinatorRegistryCenter.isExisted("/testJob/config")).thenReturn(true); jobNodeStorage.createJobNodeIfNeeded("config"); verify(coordinatorRegistryCenter).isExisted("/testJob"); verify(coordinatorRegistryCenter).isExisted("/testJob/config"); verify(coordinatorRegistryCenter, times(0)).persist("/testJob/config", ""); } @Test public void assertRemoveJobNodeIfNeeded() { when(coordinatorRegistryCenter.isExisted("/testJob/config")).thenReturn(true); jobNodeStorage.removeJobNodeIfExisted("config"); verify(coordinatorRegistryCenter).isExisted("/testJob/config"); verify(coordinatorRegistryCenter).remove("/testJob/config"); } @Test public void assertRemoveJobNodeIfNotNeeded() { when(coordinatorRegistryCenter.isExisted("/testJob/config")).thenReturn(false); jobNodeStorage.removeJobNodeIfExisted("config"); verify(coordinatorRegistryCenter).isExisted("/testJob/config"); verify(coordinatorRegistryCenter, times(0)).remove("/testJob/config"); } @Test public void assertFillJobNodeIfNotNullAndOverwriteDisabled() { when(coordinatorRegistryCenter.isExisted("/testJob/config/cron")).thenReturn(true); jobNodeStorage.fillJobNodeIfNullOrOverwrite("config/cron", "0/1 * * * * ?"); verify(coordinatorRegistryCenter).isExisted("/testJob/config/cron"); verify(coordinatorRegistryCenter, times(0)).persist("/testJob/config/cron", "0/1 * * * * ?"); } @Test public void assertFillJobNodeIfNotNullAndOverwriteEnabledButValueSame() throws NoSuchFieldException { when(coordinatorRegistryCenter.isExisted("/testJob/config/cron")).thenReturn(true); when(coordinatorRegistryCenter.getDirectly("/testJob/config/cron")).thenReturn("0/1 * * * * ?"); JobConfigurationFieldUtil.setSuperFieldValue(jobConfig, "overwrite", true); jobNodeStorage.fillJobNodeIfNullOrOverwrite("config/cron", "0/1 * * * * ?"); verify(coordinatorRegistryCenter).isExisted("/testJob/config/cron"); verify(coordinatorRegistryCenter).getDirectly("/testJob/config/cron"); verify(coordinatorRegistryCenter, times(0)).persist("/testJob/config", "0/1 * * * * ?"); } @Test public void assertFillJobNodeIfNotNullAndOverwriteEnabledAndValueDifferent() throws NoSuchFieldException { when(coordinatorRegistryCenter.isExisted("/testJob/config/cron")).thenReturn(true); when(coordinatorRegistryCenter.getDirectly("/testJob/config/cron")).thenReturn("0/1 * * * * ?"); JobConfigurationFieldUtil.setSuperFieldValue(jobConfig, "overwrite", true); jobNodeStorage.fillJobNodeIfNullOrOverwrite("config/cron", "0/2 * * * * ?"); verify(coordinatorRegistryCenter).isExisted("/testJob/config/cron"); verify(coordinatorRegistryCenter).getDirectly("/testJob/config/cron"); verify(coordinatorRegistryCenter).persist("/testJob/config/cron", "0/2 * * * * ?"); } @Test public void assertFillJobNodeIfNull() { when(coordinatorRegistryCenter.isExisted("/testJob/config/cron")).thenReturn(false); jobNodeStorage.fillJobNodeIfNullOrOverwrite("config/cron", "0/2 * * * * ?"); verify(coordinatorRegistryCenter).isExisted("/testJob/config/cron"); verify(coordinatorRegistryCenter).persist("/testJob/config/cron", "0/2 * * * * ?"); } @Test public void assertFillEphemeralJobNode() { jobNodeStorage.fillEphemeralJobNode("config/cron", "0/1 * * * * ?"); verify(coordinatorRegistryCenter).persistEphemeral("/testJob/config/cron", "0/1 * * * * ?"); } @Test public void assertUpdateJobNode() { jobNodeStorage.updateJobNode("config/cron", "0/1 * * * * ?"); verify(coordinatorRegistryCenter).update("/testJob/config/cron", "0/1 * * * * ?"); } @Test public void assertReplaceJobNode() { jobNodeStorage.replaceJobNode("config/cron", "0/1 * * * * ?"); verify(coordinatorRegistryCenter).persist("/testJob/config/cron", "0/1 * * * * ?"); } @Test public void assertExecuteInTransactionSuccess() throws Exception { CuratorFramework client = mock(CuratorFramework.class); CuratorTransaction curatorTransaction = mock(CuratorTransaction.class); TransactionCheckBuilder transactionCheckBuilder = mock(TransactionCheckBuilder.class); CuratorTransactionBridge curatorTransactionBridge = mock(CuratorTransactionBridge.class); CuratorTransactionFinal curatorTransactionFinal = mock(CuratorTransactionFinal.class); when(coordinatorRegistryCenter.getRawClient()).thenReturn(client); when(client.inTransaction()).thenReturn(curatorTransaction); when(curatorTransaction.check()).thenReturn(transactionCheckBuilder); when(transactionCheckBuilder.forPath("/")).thenReturn(curatorTransactionBridge); when(curatorTransactionBridge.and()).thenReturn(curatorTransactionFinal); TransactionCreateBuilder transactionCreateBuilder = mock(TransactionCreateBuilder.class); when(curatorTransactionFinal.create()).thenReturn(transactionCreateBuilder); when(transactionCreateBuilder.forPath("/test_transaction")) .thenReturn(curatorTransactionBridge); when(curatorTransactionBridge.and()).thenReturn(curatorTransactionFinal); jobNodeStorage.executeInTransaction( new TransactionExecutionCallback() { @Override public void execute(final CuratorTransactionFinal curatorTransactionFinal) throws Exception { curatorTransactionFinal.create().forPath("/test_transaction").and(); } }); verify(coordinatorRegistryCenter).getRawClient(); verify(client).inTransaction(); verify(curatorTransaction).check(); verify(transactionCheckBuilder).forPath("/"); verify(curatorTransactionBridge, times(2)).and(); verify(curatorTransactionFinal).create(); verify(transactionCreateBuilder).forPath("/test_transaction"); verify(curatorTransactionFinal).commit(); } @Test(expected = RuntimeException.class) public void assertExecuteInTransactionFailure() throws Exception { CuratorFramework client = mock(CuratorFramework.class); CuratorTransaction curatorTransaction = mock(CuratorTransaction.class); TransactionCheckBuilder transactionCheckBuilder = mock(TransactionCheckBuilder.class); CuratorTransactionBridge curatorTransactionBridge = mock(CuratorTransactionBridge.class); CuratorTransactionFinal curatorTransactionFinal = mock(CuratorTransactionFinal.class); when(coordinatorRegistryCenter.getRawClient()).thenReturn(client); when(client.inTransaction()).thenReturn(curatorTransaction); when(curatorTransaction.check()).thenReturn(transactionCheckBuilder); when(transactionCheckBuilder.forPath("/")).thenReturn(curatorTransactionBridge); when(curatorTransactionBridge.and()).thenReturn(curatorTransactionFinal); TransactionCreateBuilder transactionCreateBuilder = mock(TransactionCreateBuilder.class); when(curatorTransactionFinal.create()).thenReturn(transactionCreateBuilder); when(transactionCreateBuilder.forPath("/test_transaction")) .thenReturn(curatorTransactionBridge); when(curatorTransactionBridge.and()).thenThrow(new RuntimeException()); jobNodeStorage.executeInTransaction( new TransactionExecutionCallback() { @Override public void execute(final CuratorTransactionFinal curatorTransactionFinal) throws Exception { curatorTransactionFinal.create().forPath("/test_transaction").and(); } }); verify(coordinatorRegistryCenter).getRawClient(); verify(client).inTransaction(); verify(curatorTransaction).check(); verify(transactionCheckBuilder).forPath("/"); verify(curatorTransactionBridge, times(2)).and(); verify(curatorTransactionFinal).create(); verify(transactionCreateBuilder).forPath("/test_transaction"); verify(curatorTransactionFinal, times(0)).commit(); } @Test public void assertAddConnectionStateListener() { CuratorFramework client = mock(CuratorFramework.class); @SuppressWarnings("unchecked") Listenable<ConnectionStateListener> listeners = mock(Listenable.class); ConnectionStateListener listener = mock(ConnectionStateListener.class); when(client.getConnectionStateListenable()).thenReturn(listeners); when(coordinatorRegistryCenter.getRawClient()).thenReturn(client); jobNodeStorage.addConnectionStateListener(listener); verify(listeners).addListener(listener); } @Test public void assertAddDataListener() { TreeCache treeCache = mock(TreeCache.class); @SuppressWarnings("unchecked") Listenable<TreeCacheListener> listeners = mock(Listenable.class); TreeCacheListener listener = mock(TreeCacheListener.class); when(treeCache.getListenable()).thenReturn(listeners); when(coordinatorRegistryCenter.getRawCache("/testJob")).thenReturn(treeCache); jobNodeStorage.addDataListener(listener); verify(listeners).addListener(listener); } @Test public void assertGetRegistryCenterTime() { when(coordinatorRegistryCenter.getRegistryCenterTime("/testJob/systemTime/current")) .thenReturn(0L); assertThat(jobNodeStorage.getRegistryCenterTime(), is(0L)); verify(coordinatorRegistryCenter).getRegistryCenterTime("/testJob/systemTime/current"); } @Test public void assertGetJobConfiguration() { assertThat(jobNodeStorage.getJobConfiguration(), is((JobConfiguration) jobConfig)); } }