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

//////////////////////////////////////////////////////////////////////////
/// \file
/// \brief Implementation for SCPI QtTest object.

// Personal includes
#include "TestSCPIParsing.h"
#include "SCPIParsing.h"
#include "VISAInstrumentBuffer.h"

// Standard includes
#include <cstddef>

using namespace MTL::SCPI;

// Local Utilities
void l_PromptUser(std::string S)
{
	std::cout << "PROMPT : " << S << std::endl;
	std::cin.ignore();
}

// Mandatory methods
void TestSCPIParsing::initTestCase()
{
}
void TestSCPIParsing::cleanupTestCase()
{
	l_PromptUser("Press Enter to quit");
}

/// \test Test arbitrary-block functions.
void TestSCPIParsing::ArbitraryBlock()
{
	//----------------------------------------------------------------------//
	//							Arbitrary Blocks							//
	//----------------------------------------------------------------------//
	#define NOT_ARBITRARY_BLOCK					"DUMMY"
	#define ARBITRARY_BLOCK_INFINITE			"#0abcd\0efgh1234#'?@~."
	#define ARBITRARY_BLOCK_DEFINITE1			"#219abcd\0efgh1234#'?@~.NOTINBLOCK"
	#define ARBITRARY_BLOCK_DEFINITE2			"#6000019abcd\0efgh1234#'?@~.NOTINBLOCK"
	#define ARBITRARY_BLOCK_DEFINITE_TOO_SHORT	"#6000019abcd\0efgh1234#'?@~"
	size_t l_Offset, l_Len;
	//----------------------------------------------------------------------//
	// IsArbitraryBlock
	MTL::Instrument::CVISABuffer l_ArbBlockBuff;
	l_ArbBlockBuff.assign(NOT_ARBITRARY_BLOCK, sizeof(NOT_ARBITRARY_BLOCK) - 1);
	QVERIFY(!IsArbitraryBlock(l_ArbBlockBuff.begin(), l_ArbBlockBuff.end(), l_Offset, l_Len));
	l_ArbBlockBuff.assign(ARBITRARY_BLOCK_INFINITE, sizeof(ARBITRARY_BLOCK_INFINITE) - 1);
	QVERIFY(IsArbitraryBlock(l_ArbBlockBuff.begin(), l_ArbBlockBuff.end(), l_Offset, l_Len) && l_Offset == 2 && l_Len == 19);
	l_ArbBlockBuff.assign(ARBITRARY_BLOCK_DEFINITE1, sizeof(ARBITRARY_BLOCK_DEFINITE1) - 1);
	QVERIFY(IsArbitraryBlock(l_ArbBlockBuff.begin(), l_ArbBlockBuff.end(), l_Offset, l_Len) && l_Offset == 4 && l_Len == 19);
	l_ArbBlockBuff.assign(ARBITRARY_BLOCK_DEFINITE2, sizeof(ARBITRARY_BLOCK_DEFINITE2) - 1);
	QVERIFY(IsArbitraryBlock(l_ArbBlockBuff.begin(), l_ArbBlockBuff.end(), l_Offset, l_Len) && l_Offset == 8 && l_Len == 19);
	l_ArbBlockBuff.assign(ARBITRARY_BLOCK_DEFINITE_TOO_SHORT, sizeof(ARBITRARY_BLOCK_DEFINITE_TOO_SHORT) - 1);
	QVERIFY(!IsArbitraryBlock(l_ArbBlockBuff.begin(), l_ArbBlockBuff.end(), l_Offset, l_Len));
	//----------------------------------------------------------------------//
	// ToArbitraryBlock
	#define RAW_DATA_BLOCK				"abcd\0efgh1234#'?@~."
	#define ARBITRARY_BLOCK_DEFINITE	"#219abcd\0efgh1234#'?@~."
	std::string l_RawData, l_sArbBlock;
	l_RawData.assign(RAW_DATA_BLOCK, sizeof(RAW_DATA_BLOCK) - 1);
	ToArbitraryBlock(l_RawData, l_sArbBlock, true);
	QVERIFY(memcmp(l_sArbBlock.data(), ARBITRARY_BLOCK_INFINITE, sizeof(ARBITRARY_BLOCK_INFINITE) - 1) == 0);
	ToArbitraryBlock(l_RawData, l_sArbBlock, false);
	QVERIFY(memcmp(l_sArbBlock.data(), ARBITRARY_BLOCK_DEFINITE, sizeof(ARBITRARY_BLOCK_DEFINITE) - 1) == 0);
}
/// \test Test string channel list functions.
void TestSCPIParsing::StringChannelList()
{
	//----------------------------------------------------------------------//
	//							String Channel Lists						//
	//----------------------------------------------------------------------//
	#define NOT_CHANNEL				"(1!2)"
	#define CHANNEL_EMPTY			"(@)"
	#define CHANNEL_1PORT			"(@1)"
	#define CHANNEL_MULTIPORTS		"(@1!2!255!18)"
	#define CHANNEL_MULTIPORTS2		"(@1!2!255!18,3!8,7)"
	//----------------------------------------------------------------------//
	// FromStringChannelList
	tChannelList l_ChanList;
	std::string l_sChanlist;
	l_sChanlist.assign(NOT_CHANNEL, sizeof(NOT_CHANNEL) - 1);
	FromStringChannelList(l_sChanlist.begin(), l_sChanlist.end(), l_ChanList);
	QVERIFY(l_ChanList.empty());
	l_sChanlist.assign(CHANNEL_EMPTY, sizeof(CHANNEL_EMPTY) - 1);
	FromStringChannelList(l_sChanlist.begin(), l_sChanlist.end(), l_ChanList);
	QVERIFY(l_ChanList.empty());
	l_sChanlist.assign(CHANNEL_1PORT, sizeof(CHANNEL_1PORT) - 1);
	FromStringChannelList(l_sChanlist.begin(), l_sChanlist.end(), l_ChanList);
	tChannelList ExpectedChanList = { { 1 } };
	QVERIFY(l_ChanList == ExpectedChanList);
	l_sChanlist.assign(CHANNEL_MULTIPORTS, sizeof(CHANNEL_MULTIPORTS) - 1);
	FromStringChannelList(l_sChanlist.begin(), l_sChanlist.end(), l_ChanList);
	ExpectedChanList = { { 1,2,255,18 } };
	QVERIFY(l_ChanList == ExpectedChanList);
	l_sChanlist.assign(CHANNEL_MULTIPORTS2, sizeof(CHANNEL_MULTIPORTS2) - 1);
	FromStringChannelList(l_sChanlist.begin(), l_sChanlist.end(), l_ChanList);
	ExpectedChanList = { { 1,2,255,18 },{ 3,8 },{ 7 } };
	QVERIFY(l_ChanList == ExpectedChanList);
	//----------------------------------------------------------------------//
	// ToStringChannelList
	std::string l_StrChanList;
	l_ChanList = { {} };
	ToStringChannelList(l_ChanList, l_StrChanList);
	QVERIFY(l_StrChanList == std::string(CHANNEL_EMPTY, sizeof(CHANNEL_EMPTY) - 1));
	l_ChanList = { { 1 } };
	ToStringChannelList(l_ChanList, l_StrChanList);
	QVERIFY(l_StrChanList == std::string(CHANNEL_1PORT, sizeof(CHANNEL_1PORT) - 1));
	l_ChanList = { { 1,2,255,18 } };
	ToStringChannelList(l_ChanList, l_StrChanList);
	QVERIFY(l_StrChanList == std::string(CHANNEL_MULTIPORTS, sizeof(CHANNEL_MULTIPORTS) - 1));
	l_ChanList = { { 1,2,255,18 },{ 3,8 },{ 7 } };
	ToStringChannelList(l_ChanList, l_StrChanList);
	QVERIFY(l_StrChanList == std::string(CHANNEL_MULTIPORTS2, sizeof(CHANNEL_MULTIPORTS2) - 1));
}
/// \test Test binary channel list functions.
void TestSCPIParsing::BinaryChannelList()
{
	//----------------------------------------------------------------------//
	//							Binary Channel Lists						//
	//----------------------------------------------------------------------//
	#define BINARY_CHANNELLIST_EMPTY	{}
	#define BINARY_CHANNELLIST_1PORT	{1}
	#define BINARY_CHANNELLIST_MULTI	{1,2,255,18}
	#define BINARY_CHANNELLIST_MULTI2	{1,2,255,18,0,3,8,0,7}
	//----------------------------------------------------------------------//
	// FromBinaryChannelList
	tChannelList l_ChanList;
	std::vector<unsigned char> l_BinaryChanList;
	l_BinaryChanList = BINARY_CHANNELLIST_EMPTY;
	FromBinaryChannelList((char*)l_BinaryChanList.data(), l_BinaryChanList.size(), l_ChanList);
	QVERIFY(l_ChanList.empty());
	l_BinaryChanList = BINARY_CHANNELLIST_1PORT;
	tChannelList ExpectedChanList = { { 1 } };
	FromBinaryChannelList((char*)l_BinaryChanList.data(), l_BinaryChanList.size(), l_ChanList);
	QVERIFY(l_ChanList == ExpectedChanList);
	l_BinaryChanList = BINARY_CHANNELLIST_MULTI;
	ExpectedChanList = { { 1,2,255,18 } };
	FromBinaryChannelList((char*)l_BinaryChanList.data(), l_BinaryChanList.size(), l_ChanList);
	QVERIFY(l_ChanList == ExpectedChanList);
	l_BinaryChanList = BINARY_CHANNELLIST_MULTI2;
	ExpectedChanList = { { 1,2,255,18 },{ 3,8 },{ 7 } };
	FromBinaryChannelList((char*)l_BinaryChanList.data(), l_BinaryChanList.size(), l_ChanList);
	QVERIFY(l_ChanList == ExpectedChanList);
	//----------------------------------------------------------------------//
	// ToBinaryChannelList
	std::vector<unsigned char> l_ExpectedBinaryChanList;
	std::vector<char> l_ObtainedBinaryChanList;
	l_ChanList = {};
	l_ExpectedBinaryChanList = BINARY_CHANNELLIST_EMPTY;
	ToBinaryChannelList(l_ChanList, l_ObtainedBinaryChanList);
	QVERIFY(memcmp(l_ObtainedBinaryChanList.data(), l_ExpectedBinaryChanList.data(), l_ObtainedBinaryChanList.size()) == 0);
	l_ChanList = { { 1 } };
	l_ExpectedBinaryChanList = BINARY_CHANNELLIST_1PORT;
	ToBinaryChannelList(l_ChanList, l_ObtainedBinaryChanList);
	QVERIFY(memcmp(l_ObtainedBinaryChanList.data(), l_ExpectedBinaryChanList.data(), l_ObtainedBinaryChanList.size()) == 0);
	l_ChanList = { { 1,2,255,18 } };
	l_ExpectedBinaryChanList = BINARY_CHANNELLIST_MULTI;
	ToBinaryChannelList(l_ChanList, l_ObtainedBinaryChanList);
	QVERIFY(memcmp(l_ObtainedBinaryChanList.data(), l_ExpectedBinaryChanList.data(), l_ObtainedBinaryChanList.size()) == 0);
	l_ChanList = { { 1,2,255,18 },{ 3,8 },{ 7 } };
	l_ExpectedBinaryChanList = BINARY_CHANNELLIST_MULTI2;
	ToBinaryChannelList(l_ChanList, l_ObtainedBinaryChanList);
	QVERIFY(memcmp(l_ObtainedBinaryChanList.data(), l_ExpectedBinaryChanList.data(), l_ObtainedBinaryChanList.size()) == 0);
}

// Test main
QTEST_MAIN(TestSCPIParsing)
