// Copyright (c) 2020 Metrolab Technology S.A., Geneva, Switzerland (www.metrolab.com)
// See the included file LICENSE.txt for the licensing conditions.

//////////////////////////////////////////////////////////////////////////
/// \file
/// \brief Test THM1176 API: Initiate, Abort, Bus Trigger

#include "gtest/gtest.h"
#include "THM1176TestUtilities.h"
#include <ctime>

using namespace MTL::Instrument;
using namespace MTL::Instrument::THM1176Types;

/// \brief Test THM1176 API: Initiate, Abort, Bus Trigger
class CTHM1176InitiateTest : public ::testing::Test
{
protected:
	static THM1176_TEST_RESOURCE_MANAGER_CLASS * pResourceManager;
	static CTHM1176Instrument<THM1176_TEST_INSTRUMENT_CLASS, THM1176_TEST_RESOURCE_MANAGER_CLASS> * pTHM1176;

	static void SetUpTestCase()
	{
		ASSERT_EQ(true, ConnectToTHM1176(pResourceManager, pTHM1176));
		ASSERT_NE(nullptr, pResourceManager);
		ASSERT_NE(nullptr, pTHM1176);
		ASSERT_EQ(true, pTHM1176->IsOpen());
		ASSERT_EQ(true, pTHM1176->Reset());
	}
	
	static void TearDownTestCase()
	{
		delete pTHM1176;
		pTHM1176 = nullptr;
		delete pResourceManager;
		pResourceManager = nullptr;
	}
	
	virtual void SetUp()
	{
		ASSERT_NE(pTHM1176, nullptr);
		ASSERT_EQ(true, pTHM1176->Reset());
	}
};
THM1176_TEST_RESOURCE_MANAGER_CLASS * CTHM1176InitiateTest::pResourceManager = nullptr;
CTHM1176Instrument<THM1176_TEST_INSTRUMENT_CLASS, THM1176_TEST_RESOURCE_MANAGER_CLASS> * CTHM1176InitiateTest::pTHM1176 = nullptr;

/// \test Test Initiate method to perform a single measurement.
TEST_F(CTHM1176InitiateTest, InitiateSingle)
{
	// Set timed trigger with default count, default period.
	sInputTrigger<sBoundedParm> l_TrigBounds;
	ASSERT_EQ(true, pTHM1176->ParmTriggerInputGet(l_TrigBounds));
	sInputTrigger<uParm> l_Trig;
	l_Trig.Source	= kInputTrigSrcTimer;
	l_Trig.Count	= l_TrigBounds.Count.Def;
	l_Trig.Period_s	= l_TrigBounds.Period_s.Def;
	ASSERT_EQ(true, pTHM1176->ParmTriggerInputSet(l_Trig));

	// Initiate once.
	ASSERT_EQ(true, pTHM1176->Initiate());
	
	// Check that we measured.
	uOPERation l_OperationStatus;
	ASSERT_EQ(true, pTHM1176->StatusGet(sStatusRegister(kStatusOperationStatusRegister, kStatusEvent), l_OperationStatus.RawOPER));
	EXPECT_EQ(1, l_OperationStatus.OPERation.MEASuring);
	
	// Check that we are no longer measuring.
	ASSERT_EQ(true, pTHM1176->StatusGet(sStatusRegister(kStatusOperationStatusRegister, kStatusCondition), l_OperationStatus.RawOPER));
	EXPECT_EQ(0, l_OperationStatus.OPERation.MEASuring);
}

/// \test Test Initiate method to perform continuous measurements.
TEST_F(CTHM1176InitiateTest, InitiateContinuous)
{
	// Set timed trigger with default count, default period.
	sInputTrigger<sBoundedParm> l_TrigBounds;
	ASSERT_EQ(true, pTHM1176->ParmTriggerInputGet(l_TrigBounds));
	sInputTrigger<uParm> l_Trig;
	l_Trig.Source	= kInputTrigSrcTimer;
	l_Trig.Count		= l_TrigBounds.Count.Def;
	l_Trig.Period_s	= l_TrigBounds.Period_s.Def;
	ASSERT_EQ(true, pTHM1176->ParmTriggerInputSet(l_Trig));
	
	// Initiate continuously.
	ASSERT_EQ(true, pTHM1176->Initiate(true));
	
	// Check that we measured.
	uOPERation l_OperationStatus;
	ASSERT_EQ(true, pTHM1176->StatusGet(sStatusRegister(kStatusOperationStatusRegister, kStatusEvent), l_OperationStatus.RawOPER));
	EXPECT_EQ(1, l_OperationStatus.OPERation.MEASuring);
	
	// Check that we are still measuring.
	ASSERT_EQ(true, pTHM1176->StatusGet(sStatusRegister(kStatusOperationStatusRegister, kStatusCondition), l_OperationStatus.RawOPER));
	EXPECT_EQ(1, l_OperationStatus.OPERation.MEASuring);
}

/// \test Test Abort method.
TEST_F(CTHM1176InitiateTest, Abort)
{
	// Set bus trigger.
	sInputTrigger<sBoundedParm> l_TrigBounds;
	ASSERT_EQ(true, pTHM1176->ParmTriggerInputGet(l_TrigBounds));
	sInputTrigger<uParm> l_Trig;
	l_Trig.Source	= kInputTrigSrcBus;
	l_Trig.Count		= 1;
	ASSERT_EQ(true, pTHM1176->ParmTriggerInputSet(l_Trig));
	
	// Initiate once.
	ASSERT_EQ(true, pTHM1176->Initiate());
	
	// Check that we are waiting for trigger.
	uOPERation l_OperationStatus;
	ASSERT_EQ(true, pTHM1176->StatusGet(sStatusRegister(kStatusOperationStatusRegister, kStatusCondition), l_OperationStatus.RawOPER));
	EXPECT_EQ(1, l_OperationStatus.OPERation.WaitingForTRIGger);
	
	// Abort the measurement.
	ASSERT_EQ(true, pTHM1176->Abort());
	
	// Check that we are no longer waiting for trigger.
	ASSERT_EQ(true, pTHM1176->StatusGet(sStatusRegister(kStatusOperationStatusRegister, kStatusCondition), l_OperationStatus.RawOPER));
	EXPECT_EQ(0, l_OperationStatus.OPERation.WaitingForTRIGger);
	
	// Set timed trigger.
	l_Trig.Source	= kInputTrigSrcTimer;
	l_Trig.Count		= l_TrigBounds.Count.Max;
	l_Trig.Period_s	= l_TrigBounds.Period_s.Min;
	ASSERT_EQ(true, pTHM1176->ParmTriggerInputSet(l_Trig));
	
	// Initiate continuously.
	ASSERT_EQ(true, pTHM1176->Initiate(true));
	
	// Check that we are measuring.
	ASSERT_EQ(true, pTHM1176->StatusGet(sStatusRegister(kStatusOperationStatusRegister, kStatusCondition), l_OperationStatus.RawOPER));
	EXPECT_EQ(1, l_OperationStatus.OPERation.MEASuring);
	
	// Abort the measurement.
	ASSERT_EQ(true, pTHM1176->Abort());
	
	// Check that we are no longer measuring.
	ASSERT_EQ(true, pTHM1176->StatusGet(sStatusRegister(kStatusOperationStatusRegister, kStatusCondition), l_OperationStatus.RawOPER));
	EXPECT_EQ(0, l_OperationStatus.OPERation.MEASuring);
}

/// \test Test SendBusTrigger method.
TEST_F(CTHM1176InitiateTest, SendBusTrigger)
{
	// Set bus trigger.
	sInputTrigger<sBoundedParm> l_TrigBounds;
	ASSERT_EQ(true, pTHM1176->ParmTriggerInputGet(l_TrigBounds));
	sInputTrigger<uParm> l_Trig;
	l_Trig.Source	= kInputTrigSrcBus;
	l_Trig.Count		= 1;
	ASSERT_EQ(true, pTHM1176->ParmTriggerInputSet(l_Trig));
	
	// Initiate once.
	ASSERT_EQ(true, pTHM1176->Initiate());
	
	// Check that we are waiting for trigger.
	uOPERation l_OperationStatus;
	ASSERT_EQ(true, pTHM1176->StatusGet(sStatusRegister(kStatusOperationStatusRegister, kStatusCondition), l_OperationStatus.RawOPER));
	EXPECT_EQ(1, l_OperationStatus.OPERation.WaitingForTRIGger);
	
	// Generate a trigger.
	ASSERT_EQ(true, pTHM1176->SendBusTrigger());
	
	// Check that we are no longer waiting for trigger.
	ASSERT_EQ(true, pTHM1176->StatusGet(sStatusRegister(kStatusOperationStatusRegister, kStatusCondition), l_OperationStatus.RawOPER));
	EXPECT_EQ(0, l_OperationStatus.OPERation.WaitingForTRIGger);
}
