package com.ctrip.xpipe.redis.integratedtest.keeper;

import com.ctrip.xpipe.redis.core.entity.RedisMeta;
import com.ctrip.xpipe.redis.core.metaserver.MetaServerConsoleService.PrimaryDcChangeMessage;
import com.ctrip.xpipe.redis.core.protocal.pojo.MasterInfo;
import com.ctrip.xpipe.redis.keeper.config.KeeperConfig;
import com.ctrip.xpipe.redis.keeper.config.TestKeeperConfig;
import com.ctrip.xpipe.redis.meta.server.dcchange.ExecutionLog;
import com.ctrip.xpipe.redis.meta.server.dcchange.OffsetWaiter;
import com.ctrip.xpipe.redis.meta.server.dcchange.SentinelManager;
import com.ctrip.xpipe.redis.meta.server.dcchange.impl.BecomeBackupAction;
import com.ctrip.xpipe.redis.meta.server.dcchange.impl.BecomePrimaryAction;
import com.ctrip.xpipe.redis.meta.server.dcchange.impl.FirstNewMasterChooser;
import com.ctrip.xpipe.redis.meta.server.meta.CurrentMetaManager;
import com.ctrip.xpipe.redis.meta.server.meta.DcMetaCache;
import com.ctrip.xpipe.redis.meta.server.multidc.MultiDcService;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.Mock;
import org.mockito.junit.MockitoJUnitRunner;

import java.util.List;

import static org.mockito.Mockito.when;

/**
 * @author wenchao.meng
 *
 * Aug 17, 2016
 */
@RunWith(MockitoJUnitRunner.class)
public class KeeperMultiDcChangePrimary extends AbstractKeeperIntegratedMultiDc{
	
	@Mock
	public DcMetaCache dcMetaCache;

	@Mock
	public CurrentMetaManager currentMetaManager;
	
	@Mock 
	private SentinelManager sentinelManager;
	
	@Mock
	private MultiDcService multiDcService;

	@Mock
	private OffsetWaiter offsetWaiter;
	
	private FirstNewMasterChooser newMasterChooser;
	
	@Before
	public void beforeKeeperMultiDcChangePrimary() throws Exception{
		
		newMasterChooser = new FirstNewMasterChooser(getXpipeNettyClientKeyedObjectPool(), scheduled, executors);
		
	}

	@Test
	public void testChangePrimary() throws Exception{
		
		String primaryDc = getPrimaryDc();
		String backupDc = getBackupDc();
		//change backup to primary
		
		when(dcMetaCache.getShardRedises(getClusterDbId(), getShardDbId())).thenReturn(getDcRedises(backupDc, getClusterId(), getShardId()));
		when(currentMetaManager.getSurviveKeepers(getClusterDbId(), getShardDbId())).thenReturn(getDcKeepers(backupDc, getClusterId(), getShardId()));
		
		logger.info(remarkableMessage("[make dc primary]change dc primary to:" + backupDc));
		BecomePrimaryAction becomePrimaryAction = new BecomePrimaryAction(getClusterDbId(), getShardDbId(), dcMetaCache,
				currentMetaManager, sentinelManager, offsetWaiter, new ExecutionLog(currentTestName()),
				getXpipeNettyClientKeyedObjectPool(), newMasterChooser, scheduled, executors);
		PrimaryDcChangeMessage message = becomePrimaryAction.changePrimaryDc(getClusterDbId(), getShardDbId(), backupDc, new MasterInfo());
		logger.info("{}", message);

		sleep(2000);
		
		logger.info(remarkableMessage("[make dc backup]change dc primary to:" + backupDc));
		when(dcMetaCache.getPrimaryDc(getClusterDbId(), getShardDbId())).thenReturn(backupDc);
		when(multiDcService.getActiveKeeper(backupDc, getClusterDbId(), getShardDbId())).thenReturn(getDcKeepers(backupDc, getClusterId(), getShardId()).get(0));
		
		when(dcMetaCache.getShardRedises(getClusterDbId(), getShardDbId())).thenReturn(getDcRedises(primaryDc, getClusterId(), getShardId()));
		when(currentMetaManager.getKeeperActive(getClusterDbId(), getShardDbId())).thenReturn(getKeeperActive(primaryDc));
		when(currentMetaManager.getSurviveKeepers(getClusterDbId(), getShardDbId())).thenReturn(getDcKeepers(primaryDc, getClusterId(), getShardId()));
		
		BecomeBackupAction becomeBackupAction = new BecomeBackupAction(getClusterDbId(), getShardDbId(), dcMetaCache,
				currentMetaManager, sentinelManager, new ExecutionLog(currentTestName()),
				getXpipeNettyClientKeyedObjectPool(), multiDcService, scheduled, executors);
		message = becomeBackupAction.changePrimaryDc(getClusterDbId(), getShardDbId(), backupDc, new MasterInfo());
		logger.info("{}", message);

		sleep(2000);
		
		RedisMeta newRedisMaster = newMasterChooser.getLastChoosenMaster();
		List<RedisMeta> allRedises = getRedises(primaryDc);
		allRedises.addAll(getRedises(backupDc));
		allRedises.remove(newRedisMaster);

		logger.info("{}\n{}", newRedisMaster, allRedises);
		sendMesssageToMasterAndTest(newRedisMaster, allRedises);
	}

	@Override
	protected KeeperConfig getKeeperConfig() {
		return new TestKeeperConfig(1 << 20, 100, 100 * (1 << 20), 2000);
	}


}

@@ -43,24 +43,78 @@
 st.keeper;%0A%0A
+import com.ctrip.xpipe.redis.core.entity.ClusterMeta;%0A
 import com.c
@@ -149,24 +149,24 @@
 .RedisMeta;%0A
-
 import com.c
@@ -1215,16 +1215,56 @@
 .List;%0A%0A
+import static org.mockito.Mockito.mock;%0A
 import s
@@ -2397,18 +2397,212 @@
 Id()));%0A
+%0A
 %09%09
+ClusterMeta clusterMeta = mock(ClusterMeta.class);%0A%09%09when(clusterMeta.getActiveDc()).thenReturn(primaryDc);%0A%09%09when(currentMetaManager.getClusterMeta(getClusterDbId())).thenReturn(clusterMeta);%0A
 %0A%09%09logge

fix NPE