// 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 Instrument Manager: Parameters

#include <thread>
#include <chrono>
#include <iostream>

#include <QtTest>
#include <QSignalSpy>

#include "CTHM1176InstrumentManager.h"

using namespace MTL;

#define THM1176_PROMPT_TIME         10      // s
#define THM1176_BOOT_N_SCAN_TIME	15000   // ms
#define THM1176_CONNECT_TIME		5000    // ms
#define THM1176_CHANGE_PARM_TIME	1000    // ms
#define THM1176_RESET_TIME			1000    // ms
#define THM1176_MEASURE_TIME		2000    // ms

static CTHM1176InstrumentManager	Manager;

//----------------------------------------------------------------------//
//	Utility functions													//
//----------------------------------------------------------------------//
static void PromptAndWait(std::string Prompt)
{
    std::string l_Space     = ("" == Prompt) ? "" : " ";
    std::string l_Message   = ">>> " + Prompt + l_Space + "(Will continue in " + std::to_string(THM1176_PROMPT_TIME) + " seconds) <<<";
    QWARN(" ");
    QWARN(l_Message.c_str());
    QThread::currentThread()->sleep(THM1176_PROMPT_TIME);
}

//----------------------------------------------------------------------//
//	Test class definition                                               //
//----------------------------------------------------------------------//
class THM1176IM_Test03_Parameters: public QObject
{
    Q_OBJECT

public:
    THM1176IM_Test03_Parameters();
    ~THM1176IM_Test03_Parameters();

private:
    // Qt argument variant
    QList<QVariant>					m_Arguments;

    //	Basic instrument control:
    CResourceList					m_ResourceList;
    tResourceName					m_THM1176Selected;
    eTHM1176OperatingMode			m_OperatingMode;
    CMeasurement					m_Measurement;
    CErrorList						m_LatestErrors;

    //	Instrument information and parameter bounds:
    sIdentifier						m_Identification;
    CFluxList						m_RangeList;
    CTHM1176UnitsList				m_UnitsList;
    CDivisorList					m_DivisorList;
    sAveraging<sBoundedParm>		m_AveragingBounds;
    sInputTrigger<sBoundedParm>		m_TriggerBounds;
    sRange<sBoundedParm>			m_RangeBounds;

    // Parameters:
    sAveraging<uParm>				m_AveragingParms;
    sInputTrigger<uParm>			m_Trigger;
    sArbitraryMeasurements			m_OutputSelect;
    bool							m_SleepParm;
    eTHM1176Units					m_Units;
    bool							m_UseCalibration;
    sRange<uParm>					m_RangeParms;
    eCommunicationFormat			m_CommFormat;

private slots:

    /// \brief Test case initialization.
    void initTestCase(void);

    /// \brief Test case cleanup.
    void cleanupTestCase(void);

    /// \brief Test to verify that Get...() == initial Notify...().
    void TestGetEqualsInitialNotify(void);

    /// \brief Test to verify that Set...() == Notify...() == Get...().
    void TestSetEqualsNotifyAndGet(void);

    /// \brief Test to verify that Notify...() == Get...() == default after reset.
    void TestNotifyAndGetAfterReset(void);

    /// \brief Test to verify that Get...() == unchanged after error.
    void TestGetAfterSetError(void);

    /// \brief Test to verify that SetTrigger() fails during continuous measurement.
    void TestSetTriggerDuringContinuousMeasurement(void);

    /// \brief Test to verify that Set...() returns error when THM disconnected.
    void TestSetAndGetAfterDisconnect(void);

};

//----------------------------------------------------------------------//
//	Test case constructor and destructor								//
//----------------------------------------------------------------------//
THM1176IM_Test03_Parameters::THM1176IM_Test03_Parameters()
{

}

THM1176IM_Test03_Parameters::~THM1176IM_Test03_Parameters()
{

}

//----------------------------------------------------------------------//
//	Test case initialization and cleanup								//
//----------------------------------------------------------------------//
void THM1176IM_Test03_Parameters::initTestCase(void)
{
	QList<QVariant>					m_Arguments;

	// Start the Instrument Manager.
	Manager.Start();

	// Create Signal Spies to retrieve instrument list, instrument info, parameters, and possible errors.
	QSignalSpy	l_NotifyInstrumentListSpy(&Manager, SIGNAL(NotifyInstrumentList(CResourceList)));
	QSignalSpy	l_NotifyCurrentInstrumentSpy(&Manager, SIGNAL(NotifyCurrentInstrument(tResourceName)));

	QSignalSpy	l_NotifyIdentificationSpy(&Manager, SIGNAL(NotifyIdentification(sIdentifier)));
	QSignalSpy	l_NotifyRangeListSpy(&Manager, SIGNAL(NotifyRangeList(CFluxList)));
    QSignalSpy	l_NotifyUnitsListSpy(&Manager, SIGNAL(NotifyUnitsList(CTHM1176UnitsList)));
	QSignalSpy	l_NotifyDivisorListSpy(&Manager, SIGNAL(NotifyDivisorList(CDivisorList)));
	QSignalSpy	l_NotifyAveragingParmBoundsSpy(&Manager, SIGNAL(NotifyAveragingParmBounds(sAveraging<sBoundedParm>)));
	QSignalSpy	l_NotifyTriggerParmBoundsSpy(&Manager, SIGNAL(NotifyTriggerParmBounds(sInputTrigger<sBoundedParm>)));
	QSignalSpy	l_NotifyRangeParmBoundsSpy(&Manager, SIGNAL(NotifyRangeParmBounds(sRange<sBoundedParm>)));

	QSignalSpy	l_NotifyAveragingParmsSpy(&Manager, SIGNAL(NotifyAveragingParms(sAveraging<uParm>)));
	QSignalSpy	l_NotifyTriggerParmsSpy(&Manager, SIGNAL(NotifyTriggerParms(sInputTrigger<uParm>)));
	QSignalSpy	l_NotifyOutputSelectSpy(&Manager, SIGNAL(NotifyOutputSelect(sArbitraryMeasurements)));
	QSignalSpy	l_NotifySleepParmSpy(&Manager, SIGNAL(NotifySleepParm(bool)));
    QSignalSpy	l_NotifyUnitsSpy(&Manager, SIGNAL(NotifyUnits(eTHM1176Units)));
	QSignalSpy	l_NotifyRangeParmsSpy(&Manager, SIGNAL(NotifyRangeParms(sRange<uParm>)));
	QSignalSpy	l_NotifyCommFormatSpy(&Manager, SIGNAL(NotifyCommFormat(eCommunicationFormat)));

	QSignalSpy	l_NotifyOperatingModeSpy(&Manager, SIGNAL(NotifyOperatingMode(eTHM1176OperatingMode)));
	QSignalSpy	l_NotifyErrorListSpy(&Manager, SIGNAL(NotifyErrorList(CErrorList)));

	// Plug in the THM.
	PromptAndWait("Please plug in a THM");
	l_NotifyInstrumentListSpy.wait(THM1176_BOOT_N_SCAN_TIME);
	QCOMPARE(l_NotifyInstrumentListSpy.count(), 1);
	m_Arguments = l_NotifyInstrumentListSpy.takeFirst();
	m_ResourceList = qvariant_cast<CResourceList>(m_Arguments.at(0));
	QCOMPARE(m_ResourceList.size(), 1ul);

	// Select the THM.
	Manager.SetCurrentInstrument(m_ResourceList[0]);

	// The last thing to happen should be setting the Operating Mode to Idle.
	l_NotifyOperatingModeSpy.wait(THM1176_CONNECT_TIME);
	QCOMPARE(l_NotifyOperatingModeSpy.count(), 1);
	m_Arguments = l_NotifyOperatingModeSpy.takeFirst();
	m_OperatingMode = qvariant_cast<eTHM1176OperatingMode>(m_Arguments.at(0));
	QCOMPARE(m_OperatingMode, kTHM1176Idle);

	// Retrieve current instrument.
	QCOMPARE(l_NotifyCurrentInstrumentSpy.count(), 1);
	m_Arguments = l_NotifyCurrentInstrumentSpy.takeFirst();
	m_THM1176Selected = qvariant_cast<tResourceName>(m_Arguments.at(0));
	QCOMPARE(m_THM1176Selected, m_ResourceList[0]);

	// Retrieve instrument information and parameter bounds for this THM.
	QCOMPARE(l_NotifyIdentificationSpy.count(), 1);
	m_Arguments = l_NotifyIdentificationSpy.takeFirst();
	m_Identification = qvariant_cast<sIdentifier>(m_Arguments.at(0));
	QVERIFY(!m_Identification.Manufacturer.empty() && !m_Identification.Model.empty() && m_Identification.SerialNumber != 0);

	QCOMPARE(l_NotifyRangeListSpy.count(), 1);
	m_Arguments = l_NotifyRangeListSpy.takeFirst();
	m_RangeList = qvariant_cast<CFluxList>(m_Arguments.at(0));
	QVERIFY(!m_RangeList.empty());

	QCOMPARE(l_NotifyUnitsListSpy.count(), 1);
	m_Arguments		= l_NotifyUnitsListSpy.takeFirst();
    m_UnitsList		= qvariant_cast<CTHM1176UnitsList>(m_Arguments.at(0));
	QVERIFY(!m_UnitsList.empty());

	QCOMPARE(l_NotifyDivisorListSpy.count(), 1);
	m_Arguments		= l_NotifyDivisorListSpy.takeFirst();
	m_DivisorList	= qvariant_cast<CDivisorList>(m_Arguments.at(0));
	QVERIFY(!m_DivisorList.empty());

	QCOMPARE(l_NotifyAveragingParmBoundsSpy.count(), 1);
	m_Arguments = l_NotifyAveragingParmBoundsSpy.takeFirst();
	m_AveragingBounds = qvariant_cast<sAveraging<sBoundedParm>>(m_Arguments.at(0));
	QVERIFY(m_AveragingBounds.NoPoints.Val != 0 && m_AveragingBounds.NoPoints.Min != 0 &&
			m_AveragingBounds.NoPoints.Max != 0 && m_AveragingBounds.NoPoints.Def != 0);

	QCOMPARE(l_NotifyTriggerParmBoundsSpy.count(), 1);
	m_Arguments = l_NotifyTriggerParmBoundsSpy.takeFirst();
	m_TriggerBounds = qvariant_cast<sInputTrigger<sBoundedParm>>(m_Arguments.at(0));
	QVERIFY(m_TriggerBounds.Period_s.Val != 0 && m_TriggerBounds.Period_s.Min != 0 &&
			m_TriggerBounds.Period_s.Max != 0 && m_TriggerBounds.Period_s.Def != 0 &&
			m_TriggerBounds.Count.Val != 0 && m_TriggerBounds.Count.Min != 0 &&
			m_TriggerBounds.Count.Max != 0 && m_TriggerBounds.Count.Def != 0);

	QCOMPARE(l_NotifyRangeParmBoundsSpy.count(), 1);
	m_Arguments = l_NotifyRangeParmBoundsSpy.takeFirst();
	m_RangeBounds = qvariant_cast<sRange<sBoundedParm>>(m_Arguments.at(0));
	QVERIFY(m_RangeBounds.Range.Val != 0 && m_RangeBounds.Range.Min != 0 &&
			m_RangeBounds.Range.Max != 0 && m_RangeBounds.Range.Def != 0);

	// Retrieve the current parameters for this instrument.
	QCOMPARE(l_NotifyAveragingParmsSpy.count(), 1);
	m_Arguments = l_NotifyAveragingParmsSpy.takeFirst();
	m_AveragingParms = qvariant_cast<sAveraging<uParm>>(m_Arguments.at(0));
	QVERIFY(m_AveragingParms.NoPoints > 0);

	QCOMPARE(l_NotifyTriggerParmsSpy.count(), 1);
	m_Arguments = l_NotifyTriggerParmsSpy.takeFirst();
	m_Trigger = qvariant_cast<sInputTrigger<uParm>>(m_Arguments.at(0));
	QVERIFY(m_Trigger.Period_s > 0. && m_Trigger.Count > 0);

	QCOMPARE(l_NotifyOutputSelectSpy.count(), 1);
	m_Arguments = l_NotifyOutputSelectSpy.takeFirst();
	m_OutputSelect = qvariant_cast<sArbitraryMeasurements>(m_Arguments.at(0));

	QCOMPARE(l_NotifySleepParmSpy.count(), 1);
	m_Arguments = l_NotifySleepParmSpy.takeFirst();
	m_SleepParm = qvariant_cast<bool>(m_Arguments.at(0));

	QCOMPARE(l_NotifyUnitsSpy.count(), 1);
	m_Arguments = l_NotifyUnitsSpy.takeFirst();
    m_Units = qvariant_cast<eTHM1176Units>(m_Arguments.at(0));

	QCOMPARE(l_NotifyRangeParmsSpy.count(), 1);
	m_Arguments = l_NotifyRangeParmsSpy.takeFirst();
	m_RangeParms = qvariant_cast<sRange<uParm>>(m_Arguments.at(0));

	QCOMPARE(l_NotifyCommFormatSpy.count(), 1);
	m_Arguments = l_NotifyCommFormatSpy.takeFirst();
	m_CommFormat = qvariant_cast<eCommunicationFormat>(m_Arguments.at(0));

	QCOMPARE(l_NotifyErrorListSpy.count(), 0);

    std::cout << "- Connected to " << m_Identification.Model << ", S/N " << m_Identification.SerialNumber << std::endl;

} // THM1176IM_Test03_Parameters::initTestCase

void THM1176IM_Test03_Parameters::cleanupTestCase(void)
{
	Manager.Stop();
}

//////////////////////////////////////////////////////////////////////////
/// \test   Test THM1176 Instrument Manager: Test to verify that Get...() == initial Notify...()
void THM1176IM_Test03_Parameters::TestGetEqualsInitialNotify(void)
{
	//	Basic instrument control:
	CResourceList					l_ResourceList_temp				= Manager.GetInstrumentList();
	QVERIFY(l_ResourceList_temp		== m_ResourceList);
	tResourceName					l_THM1176Selected_temp			= Manager.GetCurrentInstrument();
	QVERIFY(l_THM1176Selected_temp	== m_THM1176Selected);
	eTHM1176OperatingMode			l_OperatingMode_temp			= Manager.GetOperatingMode();
	QVERIFY(l_OperatingMode_temp	== m_OperatingMode);
	CMeasurement					l_Measurement_temp				= Manager.GetMeasurement();
	QVERIFY(l_Measurement_temp		== m_Measurement);
	CErrorList						l_LatestErrors_temp				= Manager.GetErrorList();
	QVERIFY(l_LatestErrors_temp		== m_LatestErrors);

	//	Instrument information and parameter bounds:
	sIdentifier						l_Identification_temp			= Manager.GetIdentification();
	QVERIFY(l_Identification_temp	== m_Identification);
	CFluxList						l_RangeList_temp				= Manager.GetRangeList();
	QVERIFY(l_RangeList_temp		== m_RangeList);
    CTHM1176UnitsList				l_UnitsList_temp				= Manager.GetUnitsList();
	QVERIFY(l_UnitsList_temp		== m_UnitsList);
	CDivisorList					l_DivisorList_temp				= Manager.GetDivisorList();
	QVERIFY(l_DivisorList_temp		== m_DivisorList);
	sAveraging<sBoundedParm>		l_AveragingBounds_temp			= Manager.GetAveragingParmBounds();
	QVERIFY(l_AveragingBounds_temp	== m_AveragingBounds);
	sInputTrigger<sBoundedParm>		l_TriggerBounds_temp			= Manager.GetTriggerParmBounds();
	QVERIFY(l_TriggerBounds_temp	== m_TriggerBounds);
	sRange<sBoundedParm>			l_RangeBounds_temp				= Manager.GetRangeParmBounds();
	QVERIFY(l_RangeBounds_temp		== m_RangeBounds);

	// Parameters:
	sAveraging<uParm>				l_AveragingParms_temp			= Manager.GetAveragingParms();
	QVERIFY(l_AveragingParms_temp	== m_AveragingParms);
	sInputTrigger<uParm>			l_Trigger_temp					= Manager.GetTriggerParms();
	QVERIFY(l_Trigger_temp			== m_Trigger);
	sArbitraryMeasurements			l_OutputSelect_temp				= Manager.GetOutputSelect();
	QVERIFY(l_OutputSelect_temp		== m_OutputSelect);
	bool							l_SleepParm_temp				= Manager.GetSleepParm();
	QVERIFY(l_SleepParm_temp		== m_SleepParm);
    eTHM1176Units					l_Units_temp					= Manager.GetUnits();
	QVERIFY(l_Units_temp			== m_Units);
	sRange<uParm>					l_RangeParms_temp				= Manager.GetRangeParms();
	QVERIFY(l_RangeParms_temp		== m_RangeParms);
	eCommunicationFormat			l_CommFormat_temp				= Manager.GetCommFormat();
	QVERIFY(l_CommFormat_temp		== m_CommFormat);

} // THM1176IM_Test03_Parameters::TestGetEqualsInitialNotify

//////////////////////////////////////////////////////////////////////////
/// \test   Test THM1176 Instrument Manager: Test to verify that Set...() == Notify...() == Get...()
void THM1176IM_Test03_Parameters::TestSetEqualsNotifyAndGet(void)
{
	// Create Signal Spies to reset and retrieve parameters and possible errors.
	QSignalSpy	l_NotifyOperatingModeSpy(&Manager, SIGNAL(NotifyOperatingMode(eTHM1176OperatingMode)));

	QSignalSpy	l_NotifyAveragingParmsSpy(&Manager, SIGNAL(NotifyAveragingParms(sAveraging<uParm>)));
	QSignalSpy	l_NotifyTriggerParmsSpy(&Manager, SIGNAL(NotifyTriggerParms(sInputTrigger<uParm>)));
	QSignalSpy	l_NotifyOutputSelectSpy(&Manager, SIGNAL(NotifyOutputSelect(sArbitraryMeasurements)));
	QSignalSpy	l_NotifySleepParmSpy(&Manager, SIGNAL(NotifySleepParm(bool)));
    QSignalSpy	l_NotifyUnitsSpy(&Manager, SIGNAL(NotifyUnits(eTHM1176Units)));
	QSignalSpy	l_NotifyRangeParmsSpy(&Manager, SIGNAL(NotifyRangeParms(sRange<uParm>)));
	QSignalSpy	l_NotifyCommFormatSpy(&Manager, SIGNAL(NotifyCommFormat(eCommunicationFormat)));

	QSignalSpy	l_NotifyErrorListSpy(&Manager, SIGNAL(NotifyErrorList(CErrorList)));

	// Perform reset to guarantee a known state.
	Manager.SetOperatingMode(kTHM1176Reset);

	l_NotifyOperatingModeSpy.wait(THM1176_RESET_TIME);
	QVERIFY(l_NotifyOperatingModeSpy.count() > 0);
	m_Arguments = l_NotifyOperatingModeSpy.takeFirst();
	m_OperatingMode = qvariant_cast<eTHM1176OperatingMode>(m_Arguments.at(0));
	QCOMPARE(m_OperatingMode, kTHM1176Reset);
	if (l_NotifyOperatingModeSpy.count() <= 0)
	{
		l_NotifyOperatingModeSpy.wait(THM1176_RESET_TIME);
		QCOMPARE(l_NotifyOperatingModeSpy.count(), 1);
	}
	m_Arguments = l_NotifyOperatingModeSpy.takeFirst();
	m_OperatingMode = qvariant_cast<eTHM1176OperatingMode>(m_Arguments.at(0));
	QCOMPARE(m_OperatingMode, kTHM1176Idle);

	// Ignore any notifications.
	l_NotifyAveragingParmsSpy.clear();
	l_NotifyTriggerParmsSpy.clear();
	l_NotifyOutputSelectSpy.clear();
	l_NotifySleepParmSpy.clear();
	l_NotifyUnitsSpy.clear();
	l_NotifyRangeParmsSpy.clear();
	l_NotifyCommFormatSpy.clear();

	// Averaging parameters.
	sAveraging<uParm>				l_AveragingParms_temp			= { 123 };
	Manager.SetAveragingParms(l_AveragingParms_temp);

	l_NotifyAveragingParmsSpy.wait(THM1176_CHANGE_PARM_TIME);
	QCOMPARE(l_NotifyAveragingParmsSpy.count(), 1);
	m_Arguments						= l_NotifyAveragingParmsSpy.takeFirst();
	m_AveragingParms				= qvariant_cast<sAveraging<uParm>>(m_Arguments.at(0));
	QVERIFY(l_AveragingParms_temp	== m_AveragingParms);

	l_AveragingParms_temp			= Manager.GetAveragingParms();
	QVERIFY(l_AveragingParms_temp	== m_AveragingParms);

	QCOMPARE(l_NotifyErrorListSpy.count(), 0);

	// Trigger parameters.
	sInputTrigger<uParm>			l_Trigger_temp					= { kInputTrigSrcTimer, 0.123, 123 };
	Manager.SetTriggerParms(l_Trigger_temp);

	l_NotifyTriggerParmsSpy.wait(THM1176_CHANGE_PARM_TIME);
	QCOMPARE(l_NotifyTriggerParmsSpy.count(), 1);
	m_Arguments						= l_NotifyTriggerParmsSpy.takeFirst();
	m_Trigger						= qvariant_cast<sInputTrigger<uParm>>(m_Arguments.at(0));
	QVERIFY(l_Trigger_temp			== m_Trigger);

	l_Trigger_temp					= Manager.GetTriggerParms();
	QVERIFY(l_Trigger_temp			== m_Trigger);

	QCOMPARE(l_NotifyErrorListSpy.count(), 0);

	// Output selection parameters.
	sArbitraryMeasurements			l_OutputSelect_temp				= { false, true, false, true, false, 123 };
	Manager.SetOutputSelect(l_OutputSelect_temp);

	l_NotifyOutputSelectSpy.wait(THM1176_CHANGE_PARM_TIME);
	QCOMPARE(l_NotifyOutputSelectSpy.count(), 1);
	m_Arguments						= l_NotifyOutputSelectSpy.takeFirst();
	m_OutputSelect					= qvariant_cast<sArbitraryMeasurements>(m_Arguments.at(0));
	QVERIFY(l_OutputSelect_temp		== m_OutputSelect);

	l_OutputSelect_temp				= Manager.GetOutputSelect();
	QVERIFY(l_OutputSelect_temp		== m_OutputSelect);

	QCOMPARE(l_NotifyErrorListSpy.count(), 0);

	// Sleep parameter.
	bool							l_SleepParm_temp				= !m_SleepParm;
	Manager.SetSleepParm(l_SleepParm_temp);

	l_NotifySleepParmSpy.wait(THM1176_CHANGE_PARM_TIME);
	QCOMPARE(l_NotifySleepParmSpy.count(), 1);
	m_Arguments						= l_NotifySleepParmSpy.takeFirst();
	m_SleepParm						= qvariant_cast<bool>(m_Arguments.at(0));
	QVERIFY(l_SleepParm_temp		== m_SleepParm);

	l_SleepParm_temp				= Manager.GetSleepParm();
	QVERIFY(l_SleepParm_temp		== m_SleepParm);

	QCOMPARE(l_NotifyErrorListSpy.count(), 0);

	// Units.
    eTHM1176Units					l_Units_temp					= m_UnitsList.back();
	Manager.SetUnits(l_Units_temp);

	l_NotifyUnitsSpy.wait(THM1176_CHANGE_PARM_TIME);
	QCOMPARE(l_NotifyUnitsSpy.count(), 1);
	m_Arguments						= l_NotifyUnitsSpy.takeFirst();
    m_Units							= qvariant_cast<eTHM1176Units>(m_Arguments.at(0));
	QVERIFY(l_Units_temp			== m_Units);

	l_Units_temp					= Manager.GetUnits();
	QVERIFY(l_Units_temp			== m_Units);

	QCOMPARE(l_NotifyErrorListSpy.count(), 0);

	// Range parameters.
	sRange<uParm>					l_RangeParms_temp				= { !m_RangeParms.Auto, m_RangeList.front()};
	Manager.SetRangeParms(l_RangeParms_temp);

	l_NotifyRangeParmsSpy.wait(THM1176_CHANGE_PARM_TIME);
	QCOMPARE(l_NotifyRangeParmsSpy.count(), 1);
	m_Arguments						= l_NotifyRangeParmsSpy.takeFirst();
	m_RangeParms					= qvariant_cast<sRange<uParm>>(m_Arguments.at(0));
	QVERIFY(l_RangeParms_temp		== m_RangeParms);

	l_RangeParms_temp				= Manager.GetRangeParms();
	QVERIFY(l_RangeParms_temp		== m_RangeParms);

	QCOMPARE(l_NotifyErrorListSpy.count(), 0);

	// Communication Format parameter.
	eCommunicationFormat			l_CommFormat_temp				= kComFormatPacked1Byte;
	Manager.SetCommFormat(l_CommFormat_temp);

	l_NotifyCommFormatSpy.wait(THM1176_CHANGE_PARM_TIME);
	QCOMPARE(l_NotifyCommFormatSpy.count(), 1);
	m_Arguments						= l_NotifyCommFormatSpy.takeFirst();
	m_CommFormat					= qvariant_cast<eCommunicationFormat>(m_Arguments.at(0));
	QVERIFY(l_CommFormat_temp		== m_CommFormat);

	l_CommFormat_temp				= Manager.GetCommFormat();
	QVERIFY(l_CommFormat_temp		== m_CommFormat);

	QCOMPARE(l_NotifyErrorListSpy.count(), 0);

} // THM1176IM_Test03_Parameters::TestSetEqualsNotifyAndGet

//////////////////////////////////////////////////////////////////////////
/// \test   Test THM1176 Instrument Manager: Test to verify that Notify...() == Get...() == default after reset
void THM1176IM_Test03_Parameters::TestNotifyAndGetAfterReset(void)
{
	// Create Signal Spies to reset and retrieve parameters and possible errors.
	QSignalSpy	l_NotifyOperatingModeSpy(&Manager, SIGNAL(NotifyOperatingMode(eTHM1176OperatingMode)));

	QSignalSpy	l_NotifyAveragingParmsSpy(&Manager, SIGNAL(NotifyAveragingParms(sAveraging<uParm>)));
	QSignalSpy	l_NotifyTriggerParmsSpy(&Manager, SIGNAL(NotifyTriggerParms(sInputTrigger<uParm>)));
	QSignalSpy	l_NotifyOutputSelectSpy(&Manager, SIGNAL(NotifyOutputSelect(sArbitraryMeasurements)));
	QSignalSpy	l_NotifySleepParmSpy(&Manager, SIGNAL(NotifySleepParm(bool)));
    QSignalSpy	l_NotifyUnitsSpy(&Manager, SIGNAL(NotifyUnits(eTHM1176Units)));
	QSignalSpy	l_NotifyRangeParmsSpy(&Manager, SIGNAL(NotifyRangeParms(sRange<uParm>)));
	QSignalSpy	l_NotifyCommFormatSpy(&Manager, SIGNAL(NotifyCommFormat(eCommunicationFormat)));

	QSignalSpy	l_NotifyErrorListSpy(&Manager, SIGNAL(NotifyErrorList(CErrorList)));

	// Perform reset.
	Manager.SetOperatingMode(kTHM1176Reset);

	l_NotifyOperatingModeSpy.wait(THM1176_RESET_TIME);
	QVERIFY(l_NotifyOperatingModeSpy.count() > 0);
	m_Arguments = l_NotifyOperatingModeSpy.takeFirst();
	m_OperatingMode = qvariant_cast<eTHM1176OperatingMode>(m_Arguments.at(0));
	QCOMPARE(m_OperatingMode, kTHM1176Reset);
	if (l_NotifyOperatingModeSpy.count() <= 0)
	{
		l_NotifyOperatingModeSpy.wait(THM1176_RESET_TIME);
		QCOMPARE(l_NotifyOperatingModeSpy.count(), 1);
	}
	m_Arguments = l_NotifyOperatingModeSpy.takeFirst();
	m_OperatingMode = qvariant_cast<eTHM1176OperatingMode>(m_Arguments.at(0));
	QCOMPARE(m_OperatingMode, kTHM1176Idle);

	// Should have no errors.
	QCOMPARE(l_NotifyErrorListSpy.count(), 0);

	// Averaging parameters.
	sAveraging<uParm>				l_AveragingParms_temp			= { 1 };
	if (l_AveragingParms_temp		!= m_AveragingParms)
	{
		QCOMPARE(l_NotifyAveragingParmsSpy.count(), 1);
		m_Arguments						= l_NotifyAveragingParmsSpy.takeFirst();
		m_AveragingParms				= qvariant_cast<sAveraging<uParm>>(m_Arguments.at(0));
		QVERIFY(l_AveragingParms_temp	== m_AveragingParms);
	}
	l_AveragingParms_temp			= Manager.GetAveragingParms();
	QVERIFY(l_AveragingParms_temp	== m_AveragingParms);

	// Trigger parameters.
	sInputTrigger<uParm>			l_Trigger_temp					= { kInputTrigSrcImmediate, 0.1, 1 };
	if (l_Trigger_temp				!= m_Trigger)
	{
		QCOMPARE(l_NotifyTriggerParmsSpy.count(), 1);
		m_Arguments						= l_NotifyTriggerParmsSpy.takeFirst();
		m_Trigger						= qvariant_cast<sInputTrigger<uParm>>(m_Arguments.at(0));
		QVERIFY(l_Trigger_temp			== m_Trigger);
	}
	l_Trigger_temp					= Manager.GetTriggerParms();
	QVERIFY(l_Trigger_temp			== m_Trigger);

	// Output selection parameters.
	sArbitraryMeasurements			l_OutputSelect_temp				= { true, true, true, true, true, 1 };
	if (l_OutputSelect_temp			!= m_OutputSelect)
	{
		QCOMPARE(l_NotifyOutputSelectSpy.count(), 1);
		m_Arguments						= l_NotifyOutputSelectSpy.takeFirst();
		m_OutputSelect					= qvariant_cast<sArbitraryMeasurements>(m_Arguments.at(0));
		QVERIFY(l_OutputSelect_temp		== m_OutputSelect);
	}
	l_OutputSelect_temp				= Manager.GetOutputSelect();
	QVERIFY(l_OutputSelect_temp		== m_OutputSelect);

	// Sleep parameter.
	bool							l_SleepParm_temp				= false;
	if (l_SleepParm_temp			!= m_SleepParm)
	{
		QCOMPARE(l_NotifySleepParmSpy.count(), 1);
		m_Arguments						= l_NotifySleepParmSpy.takeFirst();
		m_SleepParm						= qvariant_cast<bool>(m_Arguments.at(0));
		QVERIFY(l_SleepParm_temp		== m_SleepParm);
	}
	l_SleepParm_temp				= Manager.GetSleepParm();
	QVERIFY(l_SleepParm_temp		== m_SleepParm);

	// Units.
    eTHM1176Units					l_Units_temp					= MTL::kT;
	if (l_Units_temp				!= m_Units)
	{
		QCOMPARE(l_NotifyUnitsSpy.count(), 1);
		m_Arguments						= l_NotifyUnitsSpy.takeFirst();
        m_Units							= qvariant_cast<eTHM1176Units>(m_Arguments.at(0));
		QVERIFY(l_Units_temp			== m_Units);
	}
	l_Units_temp					= Manager.GetUnits();
	QVERIFY(l_Units_temp			== m_Units);

	// Range parameters.
	sRange<uParm>					l_RangeParms_temp				= { true, m_RangeList.back()};
	if (l_RangeParms_temp			!= m_RangeParms)
	{
		QCOMPARE(l_NotifyRangeParmsSpy.count(), 1);
		m_Arguments						= l_NotifyRangeParmsSpy.takeFirst();
		m_RangeParms					= qvariant_cast<sRange<uParm>>(m_Arguments.at(0));
		QVERIFY(l_RangeParms_temp		== m_RangeParms);
	}
	l_RangeParms_temp				= Manager.GetRangeParms();
	QVERIFY(l_RangeParms_temp		== m_RangeParms);

	// Communication Format parameter.
	eCommunicationFormat			l_CommFormat_temp				= kComFormatAscii;
	if (l_CommFormat_temp			!= m_CommFormat)
	{
		QCOMPARE(l_NotifyCommFormatSpy.count(), 1);
		m_Arguments						= l_NotifyCommFormatSpy.takeFirst();
		m_CommFormat					= qvariant_cast<eCommunicationFormat>(m_Arguments.at(0));
		QVERIFY(l_CommFormat_temp		== m_CommFormat);
	}
	l_CommFormat_temp				= Manager.GetCommFormat();
	QVERIFY(l_CommFormat_temp		== m_CommFormat);

} // THM1176IM_Test03_Parameters::TestNotifyAndGetAfterReset

//////////////////////////////////////////////////////////////////////////
/// \test   Test THM1176 Instrument Manager: Test to verify that Get...() == unchanged after error
void THM1176IM_Test03_Parameters::TestGetAfterSetError(void)
{
	// Create Signal Spies to reset and retrieve parameters and possible errors.
	QSignalSpy	l_NotifyOperatingModeSpy(&Manager, SIGNAL(NotifyOperatingMode(eTHM1176OperatingMode)));

	QSignalSpy	l_NotifyAveragingParmsSpy(&Manager, SIGNAL(NotifyAveragingParms(sAveraging<uParm>)));
	QSignalSpy	l_NotifyTriggerParmsSpy(&Manager, SIGNAL(NotifyTriggerParms(sInputTrigger<uParm>)));
	QSignalSpy	l_NotifyOutputSelectSpy(&Manager, SIGNAL(NotifyOutputSelect(sArbitraryMeasurements)));
	QSignalSpy	l_NotifySleepParmSpy(&Manager, SIGNAL(NotifySleepParm(bool)));
    QSignalSpy	l_NotifyUnitsSpy(&Manager, SIGNAL(NotifyUnits(eTHM1176Units)));
	QSignalSpy	l_NotifyRangeParmsSpy(&Manager, SIGNAL(NotifyRangeParms(sRange<uParm>)));
	QSignalSpy	l_NotifyCommFormatSpy(&Manager, SIGNAL(NotifyCommFormat(eCommunicationFormat)));

	QSignalSpy	l_NotifyErrorListSpy(&Manager, SIGNAL(NotifyErrorList(CErrorList)));

	// Perform reset to guarantee a known state.
	Manager.SetOperatingMode(kTHM1176Reset);

	l_NotifyOperatingModeSpy.wait(THM1176_RESET_TIME);
	QVERIFY(l_NotifyOperatingModeSpy.count() > 0);
	m_Arguments = l_NotifyOperatingModeSpy.takeFirst();
	m_OperatingMode = qvariant_cast<eTHM1176OperatingMode>(m_Arguments.at(0));
	QCOMPARE(m_OperatingMode, kTHM1176Reset);
	if (l_NotifyOperatingModeSpy.count() <= 0)
	{
		l_NotifyOperatingModeSpy.wait(THM1176_RESET_TIME);
		QCOMPARE(l_NotifyOperatingModeSpy.count(), 1);
	}
	m_Arguments = l_NotifyOperatingModeSpy.takeFirst();
	m_OperatingMode = qvariant_cast<eTHM1176OperatingMode>(m_Arguments.at(0));
	QCOMPARE(m_OperatingMode, kTHM1176Idle);

	// Ignore any notifications.
	l_NotifyAveragingParmsSpy.clear();
	l_NotifyTriggerParmsSpy.clear();
	l_NotifyOutputSelectSpy.clear();
	l_NotifySleepParmSpy.clear();
	l_NotifyUnitsSpy.clear();
	l_NotifyRangeParmsSpy.clear();
	l_NotifyCommFormatSpy.clear();
	l_NotifyErrorListSpy.clear();

	// Retrieve the parameter values via Get...
	m_AveragingParms		= Manager.GetAveragingParms();
	m_Trigger				= Manager.GetTriggerParms();
	m_OutputSelect			= Manager.GetOutputSelect();
	m_SleepParm				= Manager.GetSleepParm();
	m_Units					= Manager.GetUnits();
	m_RangeParms			= Manager.GetRangeParms();
	m_CommFormat			= Manager.GetCommFormat();

	// Averaging parameters: too low.
	sAveraging<uParm>				l_AveragingParms_temp			= { 0 };
	Manager.SetAveragingParms(l_AveragingParms_temp);
	l_NotifyErrorListSpy.wait(THM1176_CHANGE_PARM_TIME);
	QCOMPARE(l_NotifyErrorListSpy.count(), 1);
	l_NotifyErrorListSpy.clear();
	QCOMPARE(l_NotifyAveragingParmsSpy.count(), 0);
	l_AveragingParms_temp			= Manager.GetAveragingParms();
	QVERIFY(l_AveragingParms_temp	== m_AveragingParms);

	// Averaging parameters: too high.
	l_AveragingParms_temp			= { static_cast<U16>(m_AveragingBounds.NoPoints.Max + 1) };
	Manager.SetAveragingParms(l_AveragingParms_temp);
	l_NotifyErrorListSpy.wait(THM1176_CHANGE_PARM_TIME);
	QCOMPARE(l_NotifyErrorListSpy.count(), 1);
	l_NotifyErrorListSpy.clear();
	QCOMPARE(l_NotifyAveragingParmsSpy.count(), 0);
	l_AveragingParms_temp			= Manager.GetAveragingParms();
	QVERIFY(l_AveragingParms_temp	== m_AveragingParms);

	// Trigger parameters: count too low.
	sInputTrigger<uParm>			l_Trigger_temp					= { kInputTrigSrcTimer, 0.1, 0 };
	Manager.SetTriggerParms(l_Trigger_temp);
	l_NotifyErrorListSpy.wait(THM1176_CHANGE_PARM_TIME);
	QCOMPARE(l_NotifyErrorListSpy.count(), 1);
	l_NotifyErrorListSpy.clear();
	QCOMPARE(l_NotifyTriggerParmsSpy.count(), 0);
	l_Trigger_temp					= Manager.GetTriggerParms();
	QVERIFY(l_Trigger_temp			== m_Trigger);

	// Trigger parameters: count too high.
	l_Trigger_temp					= { kInputTrigSrcTimer, 0.1, static_cast<U16>(m_TriggerBounds.Count.Max + 1) };
	Manager.SetTriggerParms(l_Trigger_temp);
	l_NotifyErrorListSpy.wait(THM1176_CHANGE_PARM_TIME);
	QCOMPARE(l_NotifyErrorListSpy.count(), 1);
	l_NotifyErrorListSpy.clear();
	QCOMPARE(l_NotifyTriggerParmsSpy.count(), 0);
	l_Trigger_temp					= Manager.GetTriggerParms();
	QVERIFY(l_Trigger_temp			== m_Trigger);

	// Trigger parameters: period too low.
	l_Trigger_temp					= { kInputTrigSrcTimer, 0, 1 };
	Manager.SetTriggerParms(l_Trigger_temp);
	l_NotifyErrorListSpy.wait(THM1176_CHANGE_PARM_TIME);
	QCOMPARE(l_NotifyErrorListSpy.count(), 1);
	l_NotifyErrorListSpy.clear();
	QCOMPARE(l_NotifyTriggerParmsSpy.count(), 0);
	l_Trigger_temp					= Manager.GetTriggerParms();
	QVERIFY(l_Trigger_temp			== m_Trigger);

	// Trigger parameters: period too high.
	l_Trigger_temp					= { kInputTrigSrcTimer, 2. * m_TriggerBounds.Period_s.Max, 1 };
	Manager.SetTriggerParms(l_Trigger_temp);
	l_NotifyErrorListSpy.wait(THM1176_CHANGE_PARM_TIME);
	QCOMPARE(l_NotifyErrorListSpy.count(), 1);
	l_NotifyErrorListSpy.clear();
	QCOMPARE(l_NotifyTriggerParmsSpy.count(), 0);
	l_Trigger_temp					= Manager.GetTriggerParms();
	QVERIFY(l_Trigger_temp			== m_Trigger);

	// Output selection parameters: count too low.
	sArbitraryMeasurements			l_OutputSelect_temp				= { false, true, false, true, false, 0 };
	Manager.SetOutputSelect(l_OutputSelect_temp);
	l_NotifyErrorListSpy.wait(THM1176_CHANGE_PARM_TIME);
	QCOMPARE(l_NotifyErrorListSpy.count(), 1);
	l_NotifyErrorListSpy.clear();
	QCOMPARE(l_NotifyOutputSelectSpy.count(), 0);
	l_OutputSelect_temp				= Manager.GetOutputSelect();
	QVERIFY(l_OutputSelect_temp		== m_OutputSelect);

	// Output selection parameters: count too high.
	l_OutputSelect_temp				= { false, true, false, true, false, 2 };
	Manager.SetOutputSelect(l_OutputSelect_temp);
	l_NotifyErrorListSpy.wait(THM1176_CHANGE_PARM_TIME);
	QCOMPARE(l_NotifyErrorListSpy.count(), 1);
	l_NotifyErrorListSpy.clear();
	QCOMPARE(l_NotifyOutputSelectSpy.count(), 0);
	l_OutputSelect_temp				= Manager.GetOutputSelect();
	QVERIFY(l_OutputSelect_temp		== m_OutputSelect);

	// Units: not supported by this instrument.
    eTHM1176Units					l_Units_temp					= MTL::kT;
    std::set<eTHM1176Units>			l_SupportedUnits;
	for (auto l_pUnits = m_UnitsList.begin(); l_pUnits < m_UnitsList.end(); l_pUnits++)
		l_SupportedUnits.insert(*l_pUnits);
    for (int i = MTL::kT; i <= MTL::kMHzp; i++)
	{
        eTHM1176Units m_Units = static_cast<eTHM1176Units>(i);
		if (l_SupportedUnits.count(m_Units) == 0)
			l_Units_temp = m_Units;
	}
	Manager.SetUnits(l_Units_temp);
	l_NotifyErrorListSpy.wait(THM1176_CHANGE_PARM_TIME);
	QCOMPARE(l_NotifyErrorListSpy.count(), 1);
	l_NotifyErrorListSpy.clear();
	QCOMPARE(l_NotifyUnitsSpy.count(), 0);
	l_Units_temp					= Manager.GetUnits();
	QVERIFY(l_Units_temp			== m_Units);

	// Range parameters: invalid range.
	sRange<uParm>					l_RangeParms_temp				= { false, 0.};
	Manager.SetRangeParms(l_RangeParms_temp);
	l_NotifyErrorListSpy.wait(THM1176_CHANGE_PARM_TIME);
	QCOMPARE(l_NotifyErrorListSpy.count(), 1);
	l_NotifyErrorListSpy.clear();
	QCOMPARE(l_NotifyRangeParmsSpy.count(), 0);
	l_RangeParms_temp				= Manager.GetRangeParms();
	QVERIFY(l_RangeParms_temp		== m_RangeParms);

} // THM1176IM_Test03_Parameters::TestGetAfterSetError

//////////////////////////////////////////////////////////////////////////
/// \test   Test THM1176 Instrument Manager: Test to verify that SetTrigger() fails during continuous measurement
void THM1176IM_Test03_Parameters::TestSetTriggerDuringContinuousMeasurement(void)
{
	// Create  Signal Spies to retrieve measurement result, operating mode, and possible errors.
	QSignalSpy	l_NotifyMeasurementSpy(&Manager, SIGNAL(NotifyMeasurement(CMeasurement)));
	QSignalSpy	l_NotifyOperatingModeSpy(&Manager, SIGNAL(NotifyOperatingMode(eTHM1176OperatingMode)));
	QSignalSpy	l_NotifyTriggerParmsSpy(&Manager, SIGNAL(NotifyTriggerParms(sInputTrigger<uParm>)));
	QSignalSpy	l_NotifyErrorListSpy(&Manager, SIGNAL(NotifyErrorList(CErrorList)));

	//	Reset the instrument. This sets Trigger Parms to Immediate,1.
	Manager.SetOperatingMode(kTHM1176Reset);

	l_NotifyOperatingModeSpy.wait(THM1176_RESET_TIME);
	QVERIFY(l_NotifyOperatingModeSpy.count() > 0);
	m_Arguments = l_NotifyOperatingModeSpy.takeFirst();
	m_OperatingMode = qvariant_cast<eTHM1176OperatingMode>(m_Arguments.at(0));
	QCOMPARE(m_OperatingMode, kTHM1176Reset);
	if (l_NotifyOperatingModeSpy.count() <= 0)
	{
		l_NotifyOperatingModeSpy.wait(THM1176_RESET_TIME);
		QCOMPARE(l_NotifyOperatingModeSpy.count(), 1);
	}
	m_Arguments = l_NotifyOperatingModeSpy.takeFirst();
	m_OperatingMode = qvariant_cast<eTHM1176OperatingMode>(m_Arguments.at(0));
	QCOMPARE(m_OperatingMode, kTHM1176Idle);

	// Set SetTriggerParms to Bus,1: should receive a notification.
	sInputTrigger<uParm>			l_Trigger_temp					= { kInputTrigSrcBus, 0.1, 1 };
	Manager.SetTriggerParms(l_Trigger_temp);

	l_NotifyTriggerParmsSpy.wait(THM1176_CHANGE_PARM_TIME);
	QCOMPARE(l_NotifyTriggerParmsSpy.count(), 1);
	m_Arguments = l_NotifyTriggerParmsSpy.takeFirst();
	m_Trigger						= qvariant_cast<sInputTrigger<uParm>>(m_Arguments.at(0));
	QVERIFY(l_Trigger_temp			== m_Trigger);
	QCOMPARE(l_NotifyErrorListSpy.count(), 0);

	// Set Operating Mode to Measure,Continuous.
	Manager.SetOperatingMode(kTHM1176MeasureContinuously);

	l_NotifyOperatingModeSpy.wait(THM1176_MEASURE_TIME);
	QCOMPARE(l_NotifyOperatingModeSpy.count(), 1);
	m_Arguments = l_NotifyOperatingModeSpy.takeFirst();
	m_OperatingMode = qvariant_cast<eTHM1176OperatingMode>(m_Arguments.at(0));
	QCOMPARE(m_OperatingMode, kTHM1176MeasureContinuously);

	// Set SetTriggerParms to Bus,1: should succeed (even though it doesn't do anything).
	Manager.SetTriggerParms(l_Trigger_temp);

	l_NotifyTriggerParmsSpy.wait(THM1176_CHANGE_PARM_TIME);
	QCOMPARE(l_NotifyTriggerParmsSpy.count(), 0);
	QCOMPARE(l_NotifyErrorListSpy.count(), 0);

	// Try to set SetTriggerParms to Timer,0.1,1: should fail.
	l_Trigger_temp					= { kInputTrigSrcTimer, 0.1, 1 };
	Manager.SetTriggerParms(l_Trigger_temp);

	l_NotifyErrorListSpy.wait(THM1176_CHANGE_PARM_TIME);
	QCOMPARE(l_NotifyErrorListSpy.count(), 1);
	l_NotifyErrorListSpy.clear();
	QCOMPARE(l_NotifyTriggerParmsSpy.count(), 0);
	l_Trigger_temp					= Manager.GetTriggerParms();
	QVERIFY(l_Trigger_temp			== m_Trigger);

	// Set Operating Mode to Idle.
	Manager.SetOperatingMode(kTHM1176Idle);

	l_NotifyOperatingModeSpy.wait(THM1176_MEASURE_TIME);
	QCOMPARE(l_NotifyOperatingModeSpy.count(), 1);
	m_Arguments = l_NotifyOperatingModeSpy.takeFirst();
	m_OperatingMode = qvariant_cast<eTHM1176OperatingMode>(m_Arguments.at(0));
	QCOMPARE(m_OperatingMode, kTHM1176Idle);

	QCOMPARE(l_NotifyErrorListSpy.count(), 0);

} // THM1176IM_Test03_Parameters::TestSetTriggerDuringContinuousMeasurement

//////////////////////////////////////////////////////////////////////////
/// \test   Test THM1176 Instrument Manager: Test to verify that Set...() returns error when THM disconnected
void THM1176IM_Test03_Parameters::TestSetAndGetAfterDisconnect(void)
{
	// Create Signal Spies to reset and retrieve parameters and possible errors.
	QSignalSpy	l_NotifyCurrentInstrumentSpy(&Manager, SIGNAL(NotifyCurrentInstrument(tResourceName)));
	QSignalSpy	l_NotifyOperatingModeSpy(&Manager, SIGNAL(NotifyOperatingMode(eTHM1176OperatingMode)));

	QSignalSpy	l_NotifyIdentificationSpy(&Manager, SIGNAL(NotifyIdentification(sIdentifier)));
	QSignalSpy	l_NotifyRangeListSpy(&Manager, SIGNAL(NotifyRangeList(CFluxList)));
    QSignalSpy	l_NotifyUnitsListSpy(&Manager, SIGNAL(NotifyUnitsList(CTHM1176UnitsList)));
	QSignalSpy	l_NotifyDivisorListSpy(&Manager, SIGNAL(NotifyDivisorList(CDivisorList)));
	QSignalSpy	l_NotifyAveragingParmBoundsSpy(&Manager, SIGNAL(NotifyAveragingParmBounds(sAveraging<sBoundedParm>)));
	QSignalSpy	l_NotifyTriggerParmBoundsSpy(&Manager, SIGNAL(NotifyTriggerParmBounds(sInputTrigger<sBoundedParm>)));
	QSignalSpy	l_NotifyRangeParmBoundsSpy(&Manager, SIGNAL(NotifyRangeParmBounds(sRange<sBoundedParm>)));

	QSignalSpy	l_NotifyAveragingParmsSpy(&Manager, SIGNAL(NotifyAveragingParms(sAveraging<uParm>)));
	QSignalSpy	l_NotifyTriggerParmsSpy(&Manager, SIGNAL(NotifyTriggerParms(sInputTrigger<uParm>)));
	QSignalSpy	l_NotifyOutputSelectSpy(&Manager, SIGNAL(NotifyOutputSelect(sArbitraryMeasurements)));
	QSignalSpy	l_NotifySleepParmSpy(&Manager, SIGNAL(NotifySleepParm(bool)));
    QSignalSpy	l_NotifyUnitsSpy(&Manager, SIGNAL(NotifyUnits(eTHM1176Units)));
	QSignalSpy	l_NotifyRangeParmsSpy(&Manager, SIGNAL(NotifyRangeParms(sRange<uParm>)));
	QSignalSpy	l_NotifyCommFormatSpy(&Manager, SIGNAL(NotifyCommFormat(eCommunicationFormat)));

	QSignalSpy	l_NotifyErrorListSpy(&Manager, SIGNAL(NotifyErrorList(CErrorList)));

	// Disconnect the THM.
	// Note: this test needs to run last!
	Manager.SetOperatingMode(kTHM1176NotConnected);

	// Wait for NotifyCommFormat, which should be the last Notify signal.
	l_NotifyCommFormatSpy.wait(THM1176_CONNECT_TIME);
	QCOMPARE(l_NotifyCommFormatSpy.count(), 1);
	m_Arguments = l_NotifyCommFormatSpy.takeFirst();
	m_CommFormat = qvariant_cast<eCommunicationFormat>(m_Arguments.at(0));
	QCOMPARE(m_CommFormat, kComFormatAscii);

	// Retrieve all the other notifications.
	QCOMPARE(l_NotifyCurrentInstrumentSpy.count(), 1);
	m_Arguments = l_NotifyCurrentInstrumentSpy.takeFirst();
	m_THM1176Selected = qvariant_cast<tResourceName>(m_Arguments.at(0));
	QVERIFY(m_THM1176Selected.empty());

	QCOMPARE(l_NotifyOperatingModeSpy.count(), 1);
	m_Arguments = l_NotifyOperatingModeSpy.takeFirst();
	m_OperatingMode = qvariant_cast<eTHM1176OperatingMode>(m_Arguments.at(0));
	QCOMPARE(m_OperatingMode, kTHM1176NotConnected);

	QCOMPARE(l_NotifyIdentificationSpy.count(), 1);
	m_Arguments = l_NotifyIdentificationSpy.takeFirst();
	m_Identification = qvariant_cast<sIdentifier>(m_Arguments.at(0));
	QVERIFY(m_Identification.Manufacturer.empty() && m_Identification.Model.empty() && m_Identification.SerialNumber == 0);

	QCOMPARE(l_NotifyRangeListSpy.count(), 1);
	m_Arguments = l_NotifyRangeListSpy.takeFirst();
	m_RangeList = qvariant_cast<CFluxList>(m_Arguments.at(0));
	QVERIFY(m_RangeList.empty());

	QCOMPARE(l_NotifyUnitsListSpy.count(), 1);
	m_Arguments		= l_NotifyUnitsListSpy.takeFirst();
    m_UnitsList		= qvariant_cast<CTHM1176UnitsList>(m_Arguments.at(0));
	QVERIFY(m_UnitsList.empty());

	QCOMPARE(l_NotifyDivisorListSpy.count(), 1);
	m_Arguments		= l_NotifyDivisorListSpy.takeFirst();
	m_DivisorList	= qvariant_cast<CDivisorList>(m_Arguments.at(0));
	QVERIFY(m_DivisorList.empty());

	QCOMPARE(l_NotifyAveragingParmBoundsSpy.count(), 1);
	m_Arguments = l_NotifyAveragingParmBoundsSpy.takeFirst();
	m_AveragingBounds = qvariant_cast<sAveraging<sBoundedParm>>(m_Arguments.at(0));
	QVERIFY(m_AveragingBounds.NoPoints.Val == 0 && m_AveragingBounds.NoPoints.Min == 0 &&
			m_AveragingBounds.NoPoints.Max == 0 && m_AveragingBounds.NoPoints.Def == 0);

	QCOMPARE(l_NotifyTriggerParmBoundsSpy.count(), 1);
	m_Arguments = l_NotifyTriggerParmBoundsSpy.takeFirst();
	m_TriggerBounds = qvariant_cast<sInputTrigger<sBoundedParm>>(m_Arguments.at(0));
	QVERIFY(m_TriggerBounds.Period_s.Val == 0 && m_TriggerBounds.Period_s.Min == 0 &&
			m_TriggerBounds.Period_s.Max == 0 && m_TriggerBounds.Period_s.Def == 0 &&
			m_TriggerBounds.Count.Val == 0 && m_TriggerBounds.Count.Min == 0 &&
			m_TriggerBounds.Count.Max == 0 && m_TriggerBounds.Count.Def == 0);

	QCOMPARE(l_NotifyRangeParmBoundsSpy.count(), 1);
	m_Arguments = l_NotifyRangeParmBoundsSpy.takeFirst();
	m_RangeBounds = qvariant_cast<sRange<sBoundedParm>>(m_Arguments.at(0));
	QVERIFY(m_RangeBounds.Range.Val == 0 && m_RangeBounds.Range.Min == 0 &&
			m_RangeBounds.Range.Max == 0 && m_RangeBounds.Range.Def == 0);

	QCOMPARE(l_NotifyAveragingParmsSpy.count(), 1);
	m_Arguments = l_NotifyAveragingParmsSpy.takeFirst();
	m_AveragingParms = qvariant_cast<sAveraging<uParm>>(m_Arguments.at(0));
	QVERIFY(m_AveragingParms.NoPoints == 0);

	QCOMPARE(l_NotifyTriggerParmsSpy.count(), 1);
	m_Arguments = l_NotifyTriggerParmsSpy.takeFirst();
	m_Trigger = qvariant_cast<sInputTrigger<uParm>>(m_Arguments.at(0));
	QVERIFY(m_Trigger.Period_s == 0. && m_Trigger.Count == 0);

	QCOMPARE(l_NotifyOutputSelectSpy.count(), 1);
	m_Arguments = l_NotifyOutputSelectSpy.takeFirst();
	m_OutputSelect = qvariant_cast<sArbitraryMeasurements>(m_Arguments.at(0));
	QVERIFY(m_OutputSelect.Bx && m_OutputSelect.By && m_OutputSelect.Bz &&
			m_OutputSelect.Temperature && m_OutputSelect.Timestamp &&
			m_OutputSelect.NoMeasurements == 1);

	QCOMPARE(l_NotifySleepParmSpy.count(), 1);
	m_Arguments = l_NotifySleepParmSpy.takeFirst();
	m_SleepParm = qvariant_cast<bool>(m_Arguments.at(0));
	QVERIFY(!m_SleepParm);

	QCOMPARE(l_NotifyUnitsSpy.count(), 1);
	m_Arguments = l_NotifyUnitsSpy.takeFirst();
    m_Units = qvariant_cast<eTHM1176Units>(m_Arguments.at(0));
    QVERIFY(m_Units == MTL::kT);

	QCOMPARE(l_NotifyRangeParmsSpy.count(), 1);
	m_Arguments = l_NotifyRangeParmsSpy.takeFirst();
	m_RangeParms = qvariant_cast<sRange<uParm>>(m_Arguments.at(0));
	QVERIFY(!m_RangeParms.Auto && m_RangeParms.Range == 0.f);

	// Try to Get the currently selected instrument: should succeed, but be empty.
	tResourceName					l_THM1176Selected_temp			= Manager.GetCurrentInstrument();
	l_NotifyErrorListSpy.wait(THM1176_CHANGE_PARM_TIME);
	QCOMPARE(l_NotifyErrorListSpy.count(), 0);
	QVERIFY(l_THM1176Selected_temp.empty());

	// Try to Get the Operating Mode, should succeed, but be Not Connected.
	eTHM1176OperatingMode			l_OperatingMode_temp			= Manager.GetOperatingMode();
	l_NotifyErrorListSpy.wait(THM1176_CHANGE_PARM_TIME);
	QCOMPARE(l_NotifyErrorListSpy.count(), 0);
	QCOMPARE(l_OperatingMode_temp, kTHM1176NotConnected);

	// Try to Get Measurement: should fail, returning an empty measurement.
	CMeasurement					l_Measurement_temp				= Manager.GetMeasurement();
	l_NotifyErrorListSpy.wait(THM1176_CHANGE_PARM_TIME);
	QCOMPARE(l_NotifyErrorListSpy.count(), 1);
	l_NotifyErrorListSpy.clear();
	QCOMPARE(m_Measurement.Bx.size(), 0ul);
	QCOMPARE(m_Measurement.By.size(), 0ul);
	QCOMPARE(m_Measurement.Bz.size(), 0ul);
    QCOMPARE(m_Measurement.Units, MTL::kT);
	QVERIFY(m_Measurement.Temp == 0);
	QCOMPARE(m_Measurement.TimestampList.size(), 0ul);
	QCOMPARE(m_Measurement.Warnings.size(), 0ul);

	// Try to Get Error List: should succeed, with last "Instrument not connected" error message.
	CErrorList						l_LatestErrors_temp				= Manager.GetErrorList();
	l_NotifyErrorListSpy.wait(THM1176_CHANGE_PARM_TIME);
	QCOMPARE(l_NotifyErrorListSpy.count(), 0);
	QCOMPARE(l_LatestErrors_temp.size(), 1ul);

	//Try to Get Instrument Identification: should fail, returning an empty structure.
	sIdentifier						l_Identification_temp			= Manager.GetIdentification();
	l_NotifyErrorListSpy.wait(THM1176_CHANGE_PARM_TIME);
	QCOMPARE(l_NotifyErrorListSpy.count(), 1);
	l_NotifyErrorListSpy.clear();
	QVERIFY(l_Identification_temp	== m_Identification);

	// Try to Get Range List: should fail, returning an empty list.
	CFluxList						l_RangeList_temp				= Manager.GetRangeList();
	l_NotifyErrorListSpy.wait(THM1176_CHANGE_PARM_TIME);
	QCOMPARE(l_NotifyErrorListSpy.count(), 1);
	l_NotifyErrorListSpy.clear();
	QVERIFY(l_RangeList_temp		== m_RangeList);

	// Try to Get Units List: should fail, returning an empty list.
    CTHM1176UnitsList				l_UnitsList_temp				= Manager.GetUnitsList();
	l_NotifyErrorListSpy.wait(THM1176_CHANGE_PARM_TIME);
	QCOMPARE(l_NotifyErrorListSpy.count(), 1);
	l_NotifyErrorListSpy.clear();
	QVERIFY(l_UnitsList_temp		== m_UnitsList);

	// Try to Get Divisor List: should fail, returning an empty list.
	CDivisorList					l_DivisorList_temp				= Manager.GetDivisorList();
	l_NotifyErrorListSpy.wait(THM1176_CHANGE_PARM_TIME);
	QCOMPARE(l_NotifyErrorListSpy.count(), 1);
	l_NotifyErrorListSpy.clear();
	QVERIFY(l_DivisorList_temp		== m_DivisorList);

	// Try to get Averaging Parameter Bounds: should fail, returning an empty structure.
	sAveraging<sBoundedParm>		l_AveragingBounds_temp			= Manager.GetAveragingParmBounds();
	l_NotifyErrorListSpy.wait(THM1176_CHANGE_PARM_TIME);
	QCOMPARE(l_NotifyErrorListSpy.count(), 1);
	l_NotifyErrorListSpy.clear();
	QVERIFY(l_AveragingBounds_temp	== m_AveragingBounds);

	// Try to Get Trigger Parameter Bounds: should fail, returning an empty structure.
	sInputTrigger<sBoundedParm>		l_TriggerBounds_temp			= Manager.GetTriggerParmBounds();
	l_NotifyErrorListSpy.wait(THM1176_CHANGE_PARM_TIME);
	QCOMPARE(l_NotifyErrorListSpy.count(), 1);
	l_NotifyErrorListSpy.clear();
	QVERIFY(l_TriggerBounds_temp	== m_TriggerBounds);

	// Try to Get Range Parameter Bounds: should fail, returning an empty structure.
	sRange<sBoundedParm>			l_RangeBounds_temp				= Manager.GetRangeParmBounds();
	l_NotifyErrorListSpy.wait(THM1176_CHANGE_PARM_TIME);
	QCOMPARE(l_NotifyErrorListSpy.count(), 1);
	l_NotifyErrorListSpy.clear();
	QVERIFY(l_RangeBounds_temp		== m_RangeBounds);

	// Try to Set and Get Averaging parameters: should fail, with Get returning an empty structure.
	sAveraging<uParm>				l_AveragingParms_temp			= { 1 };
	Manager.SetAveragingParms(l_AveragingParms_temp);
	l_NotifyErrorListSpy.wait(THM1176_CHANGE_PARM_TIME);
	QCOMPARE(l_NotifyErrorListSpy.count(), 1);
	l_NotifyErrorListSpy.clear();
	QCOMPARE(l_NotifyAveragingParmsSpy.count(), 0);

	l_AveragingParms_temp											= Manager.GetAveragingParms();
	l_NotifyErrorListSpy.wait(THM1176_CHANGE_PARM_TIME);
	QCOMPARE(l_NotifyErrorListSpy.count(), 1);
	l_NotifyErrorListSpy.clear();
	QVERIFY(l_AveragingParms_temp	== m_AveragingParms);

	// Try to Set and Get Trigger parameters: should fail, with Get returning an empty structure.
	sInputTrigger<uParm>			l_Trigger_temp					= { kInputTrigSrcImmediate, 0.1, 1 };
	Manager.SetTriggerParms(l_Trigger_temp);
	l_NotifyErrorListSpy.wait(THM1176_CHANGE_PARM_TIME);
	QCOMPARE(l_NotifyErrorListSpy.count(), 1);
	l_NotifyErrorListSpy.clear();
	QCOMPARE(l_NotifyTriggerParmsSpy.count(), 0);

	l_Trigger_temp													= Manager.GetTriggerParms();
	l_NotifyErrorListSpy.wait(THM1176_CHANGE_PARM_TIME);
	QCOMPARE(l_NotifyErrorListSpy.count(), 1);
	l_NotifyErrorListSpy.clear();
	QVERIFY(l_Trigger_temp			== m_Trigger);

	// Try to Set and Get Output Selection parameters: should fail, with Get returning an empty structure.
	sArbitraryMeasurements			l_OutputSelect_temp				= { true, true, true, true, true, 1 };
	Manager.SetOutputSelect(l_OutputSelect_temp);
	l_NotifyErrorListSpy.wait(THM1176_CHANGE_PARM_TIME);
	QCOMPARE(l_NotifyErrorListSpy.count(), 1);
	l_NotifyErrorListSpy.clear();
	QCOMPARE(l_NotifyOutputSelectSpy.count(), 0);

	l_OutputSelect_temp												= Manager.GetOutputSelect();
	l_NotifyErrorListSpy.wait(THM1176_CHANGE_PARM_TIME);
	QCOMPARE(l_NotifyErrorListSpy.count(), 1);
	l_NotifyErrorListSpy.clear();
	QVERIFY(l_OutputSelect_temp		== m_OutputSelect);

	// Try to Set and Get Sleep parameter: should fail, with Get returning an empty structure.
	bool							l_SleepParm_temp				= !m_SleepParm;
	Manager.SetSleepParm(l_SleepParm_temp);
	l_NotifyErrorListSpy.wait(THM1176_CHANGE_PARM_TIME);
	QCOMPARE(l_NotifyErrorListSpy.count(), 1);
	l_NotifyErrorListSpy.clear();
	QCOMPARE(l_NotifySleepParmSpy.count(), 0);

	l_SleepParm_temp												= Manager.GetSleepParm();
	l_NotifyErrorListSpy.wait(THM1176_CHANGE_PARM_TIME);
	QCOMPARE(l_NotifyErrorListSpy.count(), 1);
	l_NotifyErrorListSpy.clear();
	QVERIFY(l_SleepParm_temp		== m_SleepParm);

	// Try to Set and Get Units: should fail, with Get returning an empty structure.
    eTHM1176Units							l_Units_temp					= MTL::kT;
	Manager.SetUnits(l_Units_temp);
	l_NotifyErrorListSpy.wait(THM1176_CHANGE_PARM_TIME);
	QCOMPARE(l_NotifyErrorListSpy.count(), 1);
	l_NotifyErrorListSpy.clear();
	QCOMPARE(l_NotifyUnitsSpy.count(), 0);

	l_Units_temp													= Manager.GetUnits();
	l_NotifyErrorListSpy.wait(THM1176_CHANGE_PARM_TIME);
	QCOMPARE(l_NotifyErrorListSpy.count(), 1);
	l_NotifyErrorListSpy.clear();
	QVERIFY(l_Units_temp			== m_Units);

	// Try to Set and Get Range parameters: should fail, with Get returning an empty structure.
	sRange<uParm>					l_RangeParms_temp				= { true, 0};
	Manager.SetRangeParms(l_RangeParms_temp);
	l_NotifyErrorListSpy.wait(THM1176_CHANGE_PARM_TIME);
	QCOMPARE(l_NotifyErrorListSpy.count(), 1);
	l_NotifyErrorListSpy.clear();
	QCOMPARE(l_NotifyRangeParmsSpy.count(), 0);

	l_RangeParms_temp												= Manager.GetRangeParms();
	l_NotifyErrorListSpy.wait(THM1176_CHANGE_PARM_TIME);
	QCOMPARE(l_NotifyErrorListSpy.count(), 1);
	l_NotifyErrorListSpy.clear();
	QVERIFY(l_RangeParms_temp		== m_RangeParms);

	// Try to Set and Get Communication Format parameter: should fail, with Get returning an empty structure.
	eCommunicationFormat			l_CommFormat_temp				= kComFormatPacked1Byte;
	Manager.SetCommFormat(l_CommFormat_temp);
	l_NotifyErrorListSpy.wait(THM1176_CHANGE_PARM_TIME);
	QCOMPARE(l_NotifyErrorListSpy.count(), 1);
	l_NotifyErrorListSpy.clear();
	QCOMPARE(l_NotifyCommFormatSpy.count(), 0);

	l_CommFormat_temp												= Manager.GetCommFormat();
	l_NotifyErrorListSpy.wait(THM1176_CHANGE_PARM_TIME);
	QCOMPARE(l_NotifyErrorListSpy.count(), 1);
	l_NotifyErrorListSpy.clear();
	QVERIFY(l_CommFormat_temp		== m_CommFormat);

} // THM1176IM_Test03_Parameters::TestSetAndGetAfterDisconnect

//----------------------------------------------------------------------//
//	main()																//
//----------------------------------------------------------------------//
QTEST_MAIN(THM1176IM_Test03_Parameters)

#include "THM1176IM_Test03_Parameters.moc"
