package org.bench4q.master.integrated;

import static org.junit.Assert.*;

import java.util.List;
import java.util.Map;
import java.util.UUID;

import org.bench4q.master.domain.RunningAgentInterface;
import org.bench4q.master.domain.entity.RunningAgentDB;
import org.bench4q.master.domain.entity.TestPlan;
import org.bench4q.master.domain.entity.TestPlanScript;
import org.bench4q.master.unitTest.TestBase_MakeUpTestPlan;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;

@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(locations = { "classpath:service-test-context.xml" })
public class Test_HighAvailableWithActualMessenger extends
		TestBase_MakeUpTestPlan {

	@Before
	public void prepare() {
	}

	@After
	public void cleanUp() {
	}

	@Test
	public void testSubstituteOnBoard() throws InterruptedException {
		submitATestPlanWithOneScript();
		prepareForTestPlanRunning();
		assertEquals(Long.valueOf(1000), this.getHaPool().getMaxAvailableLoad());
		assertEquals(1000, this.getHaPool().getCurrentAvailableLoad());

		this.getTestPlanEngine().doRunTestPlan(getTestPlanRunIdUuid());

		assertEquals(Long.valueOf(1000), this.getHaPool().getMaxAvailableLoad());
		assertEquals(500, this.getHaPool().getCurrentAvailableLoad());
		TestPlan testPlan = this.getTestPlanRepository().getRunningTestPlanBy(
				getTestPlanRunIdUuid());
		TestPlanScript testPlanScriptBeforeSubmit = testPlan
				.extracSpecifiedScript(getScriptId());
		Map<UUID, RunningAgentInterface> agentRunBlottersBeforeKill = this
				.getHaPool().getAgentRunBlotters();
		assertEquals(1, this.getHaPool().blotterSize());
		assertEquals(1, testPlanScriptBeforeSubmit.getSampler()
				.getRunningAgents().size());
		this.getHaPool().checkAllHeartBeat();
		for (RunningAgentInterface runingAgent : agentRunBlottersBeforeKill
				.values()) {
			while (this.getAgentMessenger().getStatus(runingAgent.getAgent()) != null) {
				System.out.println("This need agent "
						+ runingAgent.getAgent().getHostName()
						+ " to be killed");
				Thread.sleep(1000);
			}
		}
		this.getHaPool().checkAllHeartBeat();
		TestPlan testPlanAfterSubstitute = this.getTestPlanRepository()
				.getRunningTestPlanBy(getTestPlanRunIdUuid());
		TestPlanScript extracSpecifiedScript = testPlanAfterSubstitute
				.extracSpecifiedScript(getScriptId());
		for (RunningAgentDB runningAgentDB : extracSpecifiedScript
				.getRunningAgentsDB()) {
			if (runningAgentDB.isBreakDown()) {
			} else {
				assertEquals(runningAgentDB.getAgent().getMaxLoad()
						- EACH_SCRIPT_LOAD_SMALLSCALE, runningAgentDB
						.getAgent().getRemainLoad());
			}
		}
		assertEquals(Long.valueOf(500), this.getHaPool().getMaxAvailableLoad());
		assertEquals(0, this.getHaPool().getCurrentAvailableLoad());
		this.getHaPool().checkAllHeartBeat();
		assertEquals(2, agentRunBlottersBeforeKill.size());

		assertEquals(2, extracSpecifiedScript.getRunningAgentsDB().size());
		assertEquals(2, extracSpecifiedScript.getSampler().getRunningAgents()
				.size());
		cleanUpForTestPlanRunning();
	}

	@Test
	public void testCurrentAvailableLoad() {
		this.getHaPool().checkAllHeartBeat();
		assertTrue(this.getHaPool().getCurrentAvailableLoad() >= 0);
	}

	@Test
	public void test_applyFor() {
		this.getHaPool().checkAllHeartBeat();
		assertTrue(this.getHaPool().getCurrentAvailableLoad() > EACH_SCRIPT_LOAD_SMALLSCALE);
		synchronized (this.getHaPool()) {
			List<RunningAgentInterface> result = this.getHaPool().applyFor(
					EACH_SCRIPT_LOAD_SMALLSCALE);
			assertEquals(1, result.size());
			assertEquals(EACH_SCRIPT_LOAD_SMALLSCALE, result.get(0)
					.getLoadInUse());
			UUID runId = result.get(0).getAgentRunId();
			assertNotNull(runId);
			assertNull(result.get(0).getRunningScript());
			assertEquals(1, this.getHaPool().getAgentRunBlotters().size());
			assertEquals(result.get(0), this.getHaPool().getAgentRunBlotters()
					.get(runId));
			for (RunningAgentInterface runningAgent : result) {
				assertTrue(runningAgent.stop());
			}
		}

	}
}
