package org.bench4q.master.integrated;

import static org.junit.Assert.*;

import java.util.ArrayList;
import java.util.Date;
import java.util.List;

import org.bench4q.master.domain.entity.Monitor;
import org.bench4q.master.domain.entity.TestPlan;
import org.bench4q.master.domain.entity.TestPlanScript;
import org.bench4q.master.domain.factory.TestPlanFactory;
import org.bench4q.master.domain.service.TestResultSave;
import org.bench4q.master.domain.valueobject.datastatistics.TestMonitorSampler;
import org.bench4q.master.unitTest.TestBase_MakeUpTestPlan;
import org.bench4q.share.enums.master.TestPlanStatus;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
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_TestResultSave extends TestBase_MakeUpTestPlan {
	private TestResultSave testResultSave;

	private TestPlanFactory testPlanFactory;

	private TestMonitorSampler testMonitorSampler;

	public TestResultSave getTestResultSave() {
		return testResultSave;
	}

	@Autowired
	public void setTestResultSave(TestResultSave testResultSave) {
		this.testResultSave = testResultSave;
	}

	public TestPlanFactory getTestPlanFactory() {
		return testPlanFactory;
	}

	@Autowired
	public void setTestPlanFactory(TestPlanFactory testPlanFactory) {
		this.testPlanFactory = testPlanFactory;
	}

	public TestMonitorSampler getTestMonitorSampler() {
		return testMonitorSampler;
	}

	@Autowired
	public void setTestMonitorSampler(TestMonitorSampler testMonitorSampler) {
		this.testMonitorSampler = testMonitorSampler;
	}

	@Before
	public void setUp() {
		this.prepareForTestPlanRunning();
		this.submitATestPlanWithOneScript();
	}

	@After
	public void cleanUp() {
		cleanUpForTestPlanRunning();
	}

	@Test
	public void testDoSaveMonitorResult() {

		TestPlan testPlanFromRepo = this.getTestPlanRepository()
				.getTestPlanInDomainBy(this.getTestPlanRunIdUuid());
		int beforeInsertCount = getMonitorResultSize(getOneMonitor(
				testPlanFromRepo, Monitor_Host_Name));
		assertTrue(beforeInsertCount == 0);
		TestPlan testPlan = this.getTestPlanFactory().convertToDomain(
				testPlanFromRepo);
		List<Object> resultList = new ArrayList<Object>();
		resultList.addAll(getOneMonitor(testPlan, Monitor_Host_Name)
				.doAfterRun(new Date()));
		this.getTestResultSave().update(testPlan, resultList);
		testPlanFromRepo = this.getTestPlanRepository().getTestPlanInDomainBy(
				this.getTestPlanRunIdUuid());
		int afterInsertCount = getMonitorResultSize(getOneMonitor(
				testPlanFromRepo, Monitor_Host_Name));
		assertEquals(beforeInsertCount + 5, afterInsertCount);

	}

	@Test
	public void testDoSaveTestPlanScriptResult() {

		TestPlan testPlanFromRepo = this.getTestPlanRepository()
				.getTestPlanInDomainBy(this.getTestPlanRunIdUuid());
		TestPlanScript testPlanScript = getOneTestPlanScript(testPlanFromRepo);
		int beforeInsertCount = getTestPlanScriptResultSize(testPlanScript);
		assertTrue(beforeInsertCount == 0);
		TestPlan testPlan = this.getTestPlanFactory().convertToDomain(
				testPlanFromRepo);
		testPlan.run();
		assertEquals(TestPlanStatus.InRunning.name(),
				testPlan.getCurrentStatus());
		testPlanScript = getOneTestPlanScript(testPlan);
		List<Object> resultList = new ArrayList<Object>();
		resultList.addAll(testPlanScript.doAfterRun(new Date()));
		this.getTestResultSave().update(testPlan, resultList);
		testPlanFromRepo = this.getTestPlanRepository().getTestPlanInDomainBy(
				this.getTestPlanRunIdUuid());
		int afterInsertCount = getTestPlanScriptResultSize(testPlanScript);
		assertEquals(beforeInsertCount + 3, afterInsertCount);
	}

	private Monitor getOneMonitor(TestPlan testPlan, String hostName) {
		for (Monitor monitor : testPlan.getMonitors()) {
			if (monitor.getHostName().equals(hostName))
				return testPlan.getMonitors().iterator().next();
		}
		return null;

	}

	private int getMonitorResultSize(Monitor monitor) {
		return this.getTestPlanRepository().getMonitorResultsByMonitor(monitor)
				.size();
	}

	private int getTestPlanScriptResultSize(TestPlanScript testPlanScript) {
		return this.getTestPlanRepository()
				.getScriptResultsByTestPlanScript(testPlanScript).size();
	}

	private TestPlanScript getOneTestPlanScript(TestPlan testPlan) {
		return testPlan.getTestPlanScripts().iterator().next();
	}
}
