/**
* Copyright 2008 the original author or authors.
*
* 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.
*/
package net.sf.katta.master;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertTrue;
import static org.mockito.Matchers.any;
import static org.mockito.Matchers.eq;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.times;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;
import java.util.Arrays;
import java.util.List;
import net.sf.katta.AbstractTest;
import net.sf.katta.operation.master.CheckIndicesOperation;
import net.sf.katta.operation.master.MasterOperation;
import net.sf.katta.operation.master.RemoveObsoleteShardsOperation;
import net.sf.katta.protocol.IAddRemoveListener;
import net.sf.katta.protocol.InteractionProtocol;
import net.sf.katta.protocol.MasterQueue;
import net.sf.katta.testutil.TestUtil;
import net.sf.katta.testutil.mockito.SleepingAnswer;
import net.sf.katta.util.KattaException;
import net.sf.katta.util.ZkConfiguration;
import net.sf.katta.util.ZkConfiguration.PathDef;
import org.I0Itec.zkclient.ZkClient;
import org.I0Itec.zkclient.ZkServer;
import org.junit.Before;
import org.junit.Test;
import org.mockito.ArgumentCaptor;
public class MasterMockTest extends AbstractTest {
private InteractionProtocol _protocol = mock(InteractionProtocol.class);
@Before
public void setUp() {
when(_protocol.getZkConfiguration()).thenReturn(new ZkConfiguration());
ZkClient mock = mock(ZkClient.class);
when(_protocol.getZkClient()).thenReturn(mock);
}
@Test
public void testBecomeMaster() throws Exception {
final Master master = new Master(_protocol, false);
MasterQueue masterQueue = mockBlockingOperationQueue();
when(_protocol.publishMaster(master)).thenReturn(masterQueue);
when(_protocol.getLiveNodes()).thenReturn(Arrays.asList("node1"));
master.start();
assertTrue(master.isMaster());
master.shutdown();
assertFalse(master.isMaster());
}
@Test
public void testBecomeSecMaster() throws Exception {
final Master master = new Master(_protocol, false);
when(_protocol.publishMaster(master)).thenReturn(null);
when(_protocol.getLiveNodes()).thenReturn(Arrays.asList("node1"));
master.start();
assertFalse(master.isMaster());
master.shutdown();
}
@Test
public void testDisconnectReconnect() throws Exception {
final Master master = new Master(_protocol, false);
MasterQueue masterQueue = mockBlockingOperationQueue();
when(_protocol.publishMaster(master)).thenReturn(masterQueue);
when(_protocol.getLiveNodes()).thenReturn(Arrays.asList("node1"));
master.start();
assertTrue(master.isMaster());
master.disconnect();
assertFalse(master.isMaster());
master.reconnect();
assertTrue(master.isMaster());
master.shutdown();
}
@Test
public void testGracefulStartupShutdown() throws Exception {
boolean shutdownClient = false;
checkStartStop(shutdownClient, null);
}
@Test
public void testGracefulStartupShutdownWithShutdownClient() throws Exception {
boolean shutdownClient = true;
checkStartStop(shutdownClient, null);
}
@Test
public void testGracefulStartupShutdownWithZkServer() throws Exception {
ZkServer zkServer = mock(ZkServer.class);
checkStartStop(false, zkServer);
}
@Test
public void testRemoveOldNodeShards() throws Exception {
final Master master = new Master(_protocol, false);
String nodeName = "node1";
MasterQueue masterQueue = mockBlockingOperationQueue();
when(_protocol.publishMaster(master)).thenReturn(masterQueue);
when(_protocol.getLiveNodes()).thenReturn(Arrays.asList(nodeName));
when(_protocol.registerChildListener(eq(master), eq(PathDef.NODES_LIVE), any(IAddRemoveListener.class)))
.thenReturn(Arrays.asList(nodeName));
List<String> shards = Arrays.asList("shard1", "shard2");
when(_protocol.getNodeShards(nodeName)).thenReturn(shards);
master.start();
assertTrue(master.isMaster());
TestUtil.waitUntilLeaveSafeMode(master);
ArgumentCaptor<MasterOperation> argument = ArgumentCaptor.forClass(MasterOperation.class);
verify(_protocol, times(2)).addMasterOperation(argument.capture());
assertTrue(argument.getAllValues().get(0) instanceof CheckIndicesOperation);
assertTrue(argument.getAllValues().get(1) instanceof RemoveObsoleteShardsOperation);
assertEquals(nodeName, ((RemoveObsoleteShardsOperation) argument.getAllValues().get(1)).getNodeName());
master.shutdown();
}
private void checkStartStop(boolean shutdownClient, ZkServer zkServer) throws KattaException, InterruptedException,
Exception {
final Master master;
if (zkServer != null) {
master = new Master(_protocol, zkServer);
} else {
master = new Master(_protocol, shutdownClient);
}
MasterQueue masterQueue = mockBlockingOperationQueue();
when(_protocol.publishMaster(master)).thenReturn(masterQueue);
when(_protocol.getLiveNodes()).thenReturn(Arrays.asList("node1"));
master.start();
TestUtil.waitUntilLeaveSafeMode(master);
// stop agin
master.shutdown();
verify(_protocol).unregisterComponent(master);
if (shutdownClient) {
verify(_protocol).disconnect();
}
if (zkServer != null) {
verify(zkServer).shutdown();
}
}
private MasterQueue mockBlockingOperationQueue() throws InterruptedException {
MasterQueue queue = mock(MasterQueue.class);
when(queue.peek()).thenAnswer(new SleepingAnswer());
return queue;
}
}