/*
 * Copyright (C) 2014-2026 CZ.NIC
 *
 * This program is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
 *
 * In addition, as a special exception, the copyright holders give
 * permission to link the code of portions of this program with the
 * OpenSSL library under certain conditions as described in each
 * individual source file, and distribute linked combinations including
 * the two.
 */

#include <QByteArray>
#include <QDateTime>
#include <QFile>
#include <QString>
#include <QtTest/QtTest>
#include <QObject>

#include "src/datovka_shared/json/basic.h"
#include "src/datovka_shared/log/log.h"
#include "src/datovka_shared/records_management/json/entry_error.h"
#include "src/datovka_shared/records_management/json/service_info.h"
#include "src/datovka_shared/records_management/json/stored_files.h"
#include "src/datovka_shared/records_management/json/upload_account_status.h"
#include "src/datovka_shared/records_management/json/upload_file.h"
#include "src/datovka_shared/records_management/json/upload_hierarchy.h"
#include "src/global.h"
#include "src/records_management/content/automatic_upload_target.h"
#include "tests/test_records_management.h"

class TestRecordsManagement : public QObject {
	Q_OBJECT

public:
	TestRecordsManagement(void);

private slots:
	void initTestCase(void);

	void cleanupTestCase(void);

	void errorEntry(void);

	void errorEntryCompare(void);

	void errorEntryConstructor(void);

	void errorEntryCopy(void);

	void errorEntrySetValues(void);

	void errorEntryJsonConversion(void);

	void serviceInfoResp(void);

	void serviceInfoRespCompare(void);

	void serviceInfoRespConstructor(void);

	void serviceInfoRespCopy(void);

	void serviceInfoRespValues(void);

	void serviceInfoRespJsonConversion(void);

	void storedFilesReq(void);

	void storedFilesReqCompare(void);

	void storedFilesReqConstructor(void);

	void storedFilesReqCopy(void);

	void storedFilesReqValues(void);

	void storedFilesReqJsonConversion(void);

	void dmEntry(void);

	void dmEntryCompare(void);

	void dmEntryConstructor(void);

	void dmEntryCopy(void);

	void dmEntryValues(void);

	void dmEntryJsonConversion(void);

	void dmEntryListJsonConversion(void);

	void diEntry(void);

	void diEntryCompare(void);

	void diEntryConstructor(void);

	void diEntryCopy(void);

	void diEntryValues(void);

	void diEntryJsonConversion(void);

	void diEntryListJsonConversion(void);

	void storedFilesResp(void);

	void storedFilesRespCompare(void);

	void storedFilesRespConstructor(void);

	void storedFilesRespCopy(void);

	void storedFilesRespValues(void);

	void storedFilesRespJsonConversion(void);

	void uploadAccountStatusReq(void);

	void uploadAccountStatusReqCompare(void);

	void uploadAccountStatusReqConstructor(void);

	void uploadAccountStatusReqCopy(void);

	void uploadAccountStatusReqValues(void);

	void uploadAccountStatusReqJsonConversion(void);

	void uploadAccountStatusResp(void);

	void uploadAccountStatusRespCompare(void);

	void uploadAccountStatusRespConstructor(void);

	void uploadAccountStatusRespCopy(void);

	void uploadAccountStatusRespValues(void);

	void uploadAccountStatusRespJsonConversion(void);

	void uploadFileReq(void);

	void uploadFileReqCompare(void);

	void uploadFileReqConstructor(void);

	void uploadFileReqCopy(void);

	void uploadFileReqValues(void);

	void uploadFileReqJsonConversion(void);

	void uploadFileResp(void);

	void uploadFileRespCompare(void);

	void uploadFileRespConstructor(void);

	void uploadFileRespCopy(void);

	void uploadFileRespValues(void);

	void uploadFileRespJsonConversion(void);

	void uploadHierarchyResp(void);

	void uploadHierarchyRespConstructor(void);

	void uploadHierarchyRespCopy(void);

	void uploadHierarchyRespJsonConversion(void);

	void automaticUploadTarget(void);

	void automaticUploadTargetConstructor(void);

	void automaticUploadTargetCopy(void);

	void automaticUploadTargetInteraction(void);
};

TestRecordsManagement::TestRecordsManagement(void)
{
}

void TestRecordsManagement::initTestCase(void)
{
	QVERIFY(GlobInstcs::logPtr == Q_NULLPTR);
	GlobInstcs::logPtr = new (::std::nothrow) LogDevice;
	QVERIFY(GlobInstcs::logPtr != Q_NULLPTR);
}

void TestRecordsManagement::cleanupTestCase(void)
{
	delete GlobInstcs::logPtr; GlobInstcs::logPtr = Q_NULLPTR;
}

void TestRecordsManagement::errorEntry(void)
{
	RecMgmt::ErrorEntry ee1, ee2;
	const enum RecMgmt::ErrorEntry::Code code = RecMgmt::ErrorEntry::ERR_MALFORMED_REQUEST;
	const QString description("description");

	/* Must be null. */
	QVERIFY(ee1.code() == RecMgmt::ErrorEntry::ERR_NO_ERROR);
	QVERIFY(ee1.description().isNull());
	QVERIFY(ee2.code() == RecMgmt::ErrorEntry::ERR_NO_ERROR);
	QVERIFY(ee2.description().isNull());

	QVERIFY(ee1.isNull());
	QVERIFY(ee2.isNull());
	QVERIFY(ee1 == ee2);

	/* Check whether values are not cross-linked. */
	ee1.setCode(code);
	ee1.setDescription(description);

	QVERIFY(ee1.code() == code);
	QVERIFY(ee1.description() == description);

	QVERIFY(!ee1.isNull());
	QVERIFY(ee2.isNull());
	QVERIFY(ee1 != ee2);

	/* Check value copying. */
	ee2 = ee1;

	QVERIFY(ee2.code() == code);
	QVERIFY(ee2.description() == description);

	QVERIFY(!ee1.isNull());
	QVERIFY(!ee2.isNull());
	QVERIFY(ee1 == ee2);

	/* Clear value. */
	ee1 = RecMgmt::ErrorEntry();

	QVERIFY(ee1.code() == RecMgmt::ErrorEntry::ERR_NO_ERROR);
	QVERIFY(ee1.description().isNull());
	QVERIFY(ee2.code() == code);
	QVERIFY(ee2.description() == description);

	QVERIFY(ee1.isNull());
	QVERIFY(!ee2.isNull());
	QVERIFY(ee1 != ee2);
}

void TestRecordsManagement::errorEntryCompare(void)
{
	RecMgmt::ErrorEntry ee1, ee2;
	const enum RecMgmt::ErrorEntry::Code code = RecMgmt::ErrorEntry::ERR_MALFORMED_REQUEST;
	const QString description("description");

	ee1.setCode(code);
	ee1.setDescription(description);
	ee2.setCode(code);
	ee2.setDescription(description);

	QVERIFY(ee1 == ee2);

	ee2.setCode(RecMgmt::ErrorEntry::ERR_MISSING_IDENTIFIER);
	QVERIFY(ee1 != ee2);
	ee2.setCode(code);
	QVERIFY(ee1 == ee2);

	ee2.setDescription("");
	QVERIFY(ee1 != ee2);
	ee2.setDescription(description);
	QVERIFY(ee1 == ee2);
}

void TestRecordsManagement::errorEntryConstructor(void)
{
	const enum RecMgmt::ErrorEntry::Code cCode = RecMgmt::ErrorEntry::ERR_MALFORMED_REQUEST;
	const QString cDescription("description");

	{
		RecMgmt::ErrorEntry ee;

		QVERIFY(ee.isNull());

		QVERIFY(ee.code() == RecMgmt::ErrorEntry::ERR_NO_ERROR);
		QVERIFY(ee.description().isNull());
	}

	{
		enum RecMgmt::ErrorEntry::Code code = cCode;
		QString description(cDescription);

		RecMgmt::ErrorEntry ee(code, description);

		QVERIFY(!ee.isNull());

		QVERIFY(ee.code() == cCode);
		QVERIFY(ee.description() == cDescription);

		QVERIFY(code == cCode);
		QVERIFY(description == cDescription);
	}

#ifdef Q_COMPILER_RVALUE_REFS
	{
		enum RecMgmt::ErrorEntry::Code code = cCode;
		QString description(cDescription);

		RecMgmt::ErrorEntry ee(code, ::std::move(description));

		QVERIFY(!ee.isNull());

		QVERIFY(ee.code() == cCode);
		QVERIFY(ee.description() == cDescription);

		QVERIFY(code == cCode);
		QVERIFY(description != cDescription);
		QVERIFY(description.isNull());
	}
#endif /* Q_COMPILER_RVALUE_REFS */
}

void TestRecordsManagement::errorEntryCopy(void)
{
	RecMgmt::ErrorEntry ee1;
	const enum RecMgmt::ErrorEntry::Code code = RecMgmt::ErrorEntry::ERR_MALFORMED_REQUEST;
	const QString description("description");

	ee1.setCode(code);
	ee1.setDescription(description);

	/* Constructor. */
	{
		RecMgmt::ErrorEntry ee2(ee1);

		QVERIFY(!ee1.isNull());
		QVERIFY(!ee2.isNull());
		QVERIFY(ee1 == ee2);

#ifdef Q_COMPILER_RVALUE_REFS
		/* Move. */
		RecMgmt::ErrorEntry ee3(::std::move(ee2));

		QVERIFY(ee2.isNull());
		QVERIFY(ee1 != ee2);

		QVERIFY(!ee1.isNull());
		QVERIFY(!ee3.isNull());
		QVERIFY(ee1 == ee3);
#endif /* Q_COMPILER_RVALUE_REFS */
	}

	/* Assignment operator. */
	{
		RecMgmt::ErrorEntry ee2;

		QVERIFY(ee2.isNull());

		ee2 = ee1;

		QVERIFY(!ee1.isNull());
		QVERIFY(!ee2.isNull());
		QVERIFY(ee1 == ee2);

#ifdef Q_COMPILER_RVALUE_REFS
		/* Move. */
		RecMgmt::ErrorEntry ee3;

		QVERIFY(ee3.isNull());

		ee3 = ::std::move(ee2);

		QVERIFY(ee2.isNull());
		QVERIFY(ee1 != ee2);

		QVERIFY(!ee1.isNull());
		QVERIFY(!ee3.isNull());
		QVERIFY(ee1 == ee3);
#endif /* Q_COMPILER_RVALUE_REFS */
	}
}

void TestRecordsManagement::errorEntrySetValues(void)
{
	const enum RecMgmt::ErrorEntry::Code cCode = RecMgmt::ErrorEntry::ERR_MALFORMED_REQUEST;
	const QString cDescription("description");

	RecMgmt::ErrorEntry ee;
	enum RecMgmt::ErrorEntry::Code code = cCode;
	QString description(cDescription);

	QVERIFY(ee.code() == RecMgmt::ErrorEntry::ERR_NO_ERROR);
	ee.setCode(code);
	QVERIFY(ee.code() == cCode);
	QVERIFY(code == cCode);

	QVERIFY(ee.description().isNull());
	ee.setDescription(description);
	QVERIFY(ee.description() == cDescription);
	QVERIFY(description == cDescription);
#ifdef Q_COMPILER_RVALUE_REFS
	ee.setDescription("other_description");
	QVERIFY(ee.description() != cDescription);
	ee.setDescription(::std::move(description));
	QVERIFY(ee.description() == cDescription);
	QVERIFY(description != cDescription);
#endif /* Q_COMPILER_RVALUE_REFS */
}

void TestRecordsManagement::errorEntryJsonConversion(void)
{
	RecMgmt::ErrorEntry ee1, ee2;
	const enum RecMgmt::ErrorEntry::Code code = RecMgmt::ErrorEntry::ERR_MALFORMED_REQUEST;
	const QString description("description");

	bool iOk = false;
	QJsonValue jsonVal;

	QVERIFY(ee1.isNull());
	QVERIFY(ee2.isNull());
	QVERIFY(ee1 == ee2);

	ee1.setCode(code);
	ee1.setDescription(description);

	QVERIFY(!ee1.isNull());
	QVERIFY(ee2.isNull());
	QVERIFY(ee1 != ee2);

	/* Null value converts onto null object. */
	iOk = false;
	ee2 = RecMgmt::ErrorEntry::fromJsonVal(QJsonValue(), &iOk);
	QVERIFY(iOk == true);
	QVERIFY(ee2.isNull());

	/* Null object converts onto null value. */
	iOk = false;
	iOk = ee2.toJsonVal(jsonVal);
	QVERIFY(iOk == true);
	QVERIFY(jsonVal.isNull());

	iOk = false;
	iOk = ee1.toJsonVal(jsonVal);
	QVERIFY(iOk == true);
	QVERIFY(!jsonVal.isNull());

	iOk = false;
	ee2 = RecMgmt::ErrorEntry::fromJsonVal(jsonVal, &iOk);
	QVERIFY(iOk == true);
	QVERIFY(!ee2.isNull());

	QVERIFY(ee2.code() == code);
	QVERIFY(ee2.description() == description);

	QVERIFY(!ee1.isNull());
	QVERIFY(!ee2.isNull());
	QVERIFY(ee1 == ee2);
}

void TestRecordsManagement::serviceInfoResp(void)
{
	RecMgmt::ServiceInfoResp sir1, sir2;
	const QByteArray logoSvg("data");
	const QString name("name");
	const QString tokenName("token_name");

	/* Must be null. */
	QVERIFY(sir1.logoSvg().isNull());
	QVERIFY(sir1.name().isNull());
	QVERIFY(sir1.tokenName().isNull());
	QVERIFY(sir2.logoSvg().isNull());
	QVERIFY(sir2.name().isNull());
	QVERIFY(sir2.tokenName().isNull());

	QVERIFY(sir1.isNull());
	QVERIFY(sir2.isNull());
	QVERIFY(sir1 == sir2);

	/* Check whether values are not cross-linked. */
	sir1.setLogoSvg(logoSvg);
	sir1.setName(name);
	sir1.setTokenName(tokenName);

	QVERIFY(sir1.logoSvg() == logoSvg);
	QVERIFY(sir1.name() == name);
	QVERIFY(sir1.tokenName() == tokenName);

	QVERIFY(!sir1.isNull());
	QVERIFY(sir2.isNull());
	QVERIFY(sir1 != sir2);

	/* Check value copying. */
	sir2 = sir1;

	QVERIFY(sir2.logoSvg() == logoSvg);
	QVERIFY(sir2.name() == name);
	QVERIFY(sir2.tokenName() == tokenName);

	QVERIFY(!sir1.isNull());
	QVERIFY(!sir2.isNull());
	QVERIFY(sir1 == sir2);

	/* Clear value. */
	sir1 = RecMgmt::ServiceInfoResp();

	QVERIFY(sir1.logoSvg().isNull());
	QVERIFY(sir1.name().isNull());
	QVERIFY(sir1.tokenName().isNull());

	QVERIFY(sir1.isNull());
	QVERIFY(!sir2.isNull());
	QVERIFY(sir1 != sir2);
}

void TestRecordsManagement::serviceInfoRespCompare(void)
{
	RecMgmt::ServiceInfoResp sir1, sir2;
	const QByteArray logoSvg("data");
	const QString name("name");
	const QString tokenName("token_name");

	sir1.setLogoSvg(logoSvg);
	sir1.setName(name);
	sir1.setTokenName(tokenName);
	sir2.setLogoSvg(logoSvg);
	sir2.setName(name);
	sir2.setTokenName(tokenName);

	QVERIFY(sir1 == sir2);

	sir2.setLogoSvg("");
	QVERIFY(sir1 != sir2);
	sir2.setLogoSvg(logoSvg);
	QVERIFY(sir1 == sir2);

	sir2.setName("");
	QVERIFY(sir1 != sir2);
	sir2.setName(name);
	sir2.setLogoSvg(logoSvg);

	sir2.setTokenName("");
	QVERIFY(sir1 != sir2);
	sir2.setTokenName(tokenName);
	sir2.setLogoSvg(logoSvg);
}

void TestRecordsManagement::serviceInfoRespConstructor(void)
{
	const QByteArray cLogoSvg("data");
	const QString cName("name");
	const QString cTokenName("token_name");

	{
		RecMgmt::ServiceInfoResp sir;

		QVERIFY(sir.isNull());
		QVERIFY(!sir.isValid());

		QVERIFY(sir.logoSvg().isNull());
		QVERIFY(sir.name().isNull());
		QVERIFY(sir.tokenName().isNull());
	}

	{
		QByteArray logoSvg(cLogoSvg);
		QString name(cName);
		QString tokenName(cTokenName);
		RecMgmt::ServiceInfoResp sir(logoSvg, name, tokenName);

		QVERIFY(!sir.isNull());
		QVERIFY(sir.isValid());

		QVERIFY(sir.logoSvg() == cLogoSvg);
		QVERIFY(sir.name() == cName);
		QVERIFY(sir.tokenName() == cTokenName);

		QVERIFY(logoSvg == cLogoSvg);
		QVERIFY(name == cName);
		QVERIFY(tokenName == cTokenName);
	}

#ifdef Q_COMPILER_RVALUE_REFS
	{
		QByteArray logoSvg(cLogoSvg);
		QString name(cName);
		QString tokenName(cTokenName);
		RecMgmt::ServiceInfoResp sir(::std::move(logoSvg),
		    ::std::move(name), ::std::move(tokenName));

		QVERIFY(!sir.isNull());
		QVERIFY(sir.isValid());

		QVERIFY(sir.logoSvg() == cLogoSvg);
		QVERIFY(sir.name() == cName);
		QVERIFY(sir.tokenName() == cTokenName);

		QVERIFY(logoSvg != cLogoSvg);
		QVERIFY(logoSvg.isNull());
		QVERIFY(name != cName);
		QVERIFY(name.isNull());
		QVERIFY(tokenName != cTokenName);
		QVERIFY(tokenName.isNull());
	}
#endif /* Q_COMPILER_RVALUE_REFS */
}

void TestRecordsManagement::serviceInfoRespCopy(void)
{
	RecMgmt::ServiceInfoResp sir1;
	const QByteArray logoSvg("data");
	const QString name("name");
	const QString tokenName("token_name");

	sir1.setLogoSvg(logoSvg);
	sir1.setName(name);
	sir1.setTokenName(tokenName);

	/* Constructor. */
	{
		RecMgmt::ServiceInfoResp sir2(sir1);

		QVERIFY(!sir1.isNull());
		QVERIFY(!sir2.isNull());
		QVERIFY(sir1 == sir2);

#ifdef Q_COMPILER_RVALUE_REFS
		/* Move. */
		RecMgmt::ServiceInfoResp sir3(::std::move(sir2));

		QVERIFY(sir2.isNull());
		QVERIFY(sir1 != sir2);

		QVERIFY(!sir1.isNull());
		QVERIFY(!sir3.isNull());
		QVERIFY(sir1 == sir3);
#endif /* Q_COMPILER_RVALUE_REFS */
	}

	/* Assignment operator. */
	{
		RecMgmt::ServiceInfoResp sir2;

		QVERIFY(sir2.isNull());

		sir2 = sir1;

		QVERIFY(!sir1.isNull());
		QVERIFY(!sir2.isNull());
		QVERIFY(sir1 == sir2);

#ifdef Q_COMPILER_RVALUE_REFS
		/* Move. */
		RecMgmt::ServiceInfoResp sir3;

		QVERIFY(sir3.isNull());

		sir3 = ::std::move(sir2);

		QVERIFY(sir2.isNull());
		QVERIFY(sir1 != sir2);

		QVERIFY(!sir1.isNull());
		QVERIFY(!sir3.isNull());
		QVERIFY(sir1 == sir3);
#endif /* Q_COMPILER_RVALUE_REFS */
	}
}

void TestRecordsManagement::serviceInfoRespValues(void)
{
	const QByteArray cLogoSvg("data");
	const QString cName("name");
	const QString cTokenName("token_name");

	RecMgmt::ServiceInfoResp sir;
	QByteArray logoSvg(cLogoSvg);
	QString name(cName);
	QString tokenName(cTokenName);

	QVERIFY(sir.logoSvg().isNull());
	sir.setLogoSvg(logoSvg);
	QVERIFY(sir.logoSvg() == cLogoSvg);
	QVERIFY(logoSvg == cLogoSvg);
#ifdef Q_COMPILER_RVALUE_REFS
	sir.setLogoSvg("other_data");
	QVERIFY(sir.logoSvg() != cLogoSvg);
	sir.setLogoSvg(::std::move(logoSvg));
	QVERIFY(sir.logoSvg() == cLogoSvg);
	QVERIFY(logoSvg != cLogoSvg);
#endif /* Q_COMPILER_RVALUE_REFS */

	QVERIFY(sir.name().isNull());
	sir.setName(name);
	QVERIFY(sir.name() == cName);
	QVERIFY(name == cName);
#ifdef Q_COMPILER_RVALUE_REFS
	sir.setName("other_name");
	QVERIFY(sir.name() != cName);
	sir.setName(::std::move(name));
	QVERIFY(sir.name() == cName);
	QVERIFY(name != cName);
#endif /* Q_COMPILER_RVALUE_REFS */

	QVERIFY(sir.tokenName().isNull());
	sir.setTokenName(tokenName);
	QVERIFY(sir.tokenName() == cTokenName);
	QVERIFY(tokenName == cTokenName);
#ifdef Q_COMPILER_RVALUE_REFS
	sir.setTokenName("other_token_name");
	QVERIFY(sir.tokenName() != cTokenName);
	sir.setTokenName(::std::move(tokenName));
	QVERIFY(sir.tokenName() == cTokenName);
	QVERIFY(tokenName != cTokenName);
#endif /* Q_COMPILER_RVALUE_REFS */
}

void TestRecordsManagement::serviceInfoRespJsonConversion(void)
{
	RecMgmt::ServiceInfoResp sir1, sir2;
	const QByteArray logoSvg("data");
	const QString name("name");
	const QString tokenName("token_name");

	bool iOk = false;
	QByteArray jsonData;
	QJsonValue jsonVal;

	QVERIFY(sir1.isNull());
	QVERIFY(sir2.isNull());
	QVERIFY(sir1 == sir2);

	sir1.setLogoSvg(logoSvg);
	sir1.setName(name);
	sir1.setTokenName(tokenName);

	QVERIFY(!sir1.isNull());
	QVERIFY(sir2.isNull());
	QVERIFY(sir1 != sir2);

	/* Empty data cause error. */
	iOk = true;
	sir2 = RecMgmt::ServiceInfoResp::fromJson(QByteArray(), &iOk);
	QVERIFY(iOk == false);
	QVERIFY(sir2.isNull());

	/* Null value causes error. */
	iOk = true;
	sir2 = RecMgmt::ServiceInfoResp::fromJsonVal(QJsonValue(), &iOk);
	QVERIFY(iOk == false);
	QVERIFY(sir2.isNull());

	/* Null object converts onto non-null value. */
	iOk = false;
	iOk = sir2.toJsonVal(jsonVal);
	QVERIFY(iOk == true);
	QVERIFY(!jsonVal.isNull());

	jsonData = sir1.toJsonData();
	QVERIFY(!jsonData.isEmpty());

	iOk = false;
	sir2 = RecMgmt::ServiceInfoResp::fromJson(jsonData, &iOk);
	QVERIFY(iOk == true);
	QVERIFY(!sir2.isNull());

	QVERIFY(!sir1.isNull());
	QVERIFY(!sir2.isNull());
	QVERIFY(sir1 == sir2);
}

void TestRecordsManagement::storedFilesReq(void)
{
	RecMgmt::StoredFilesReq sfr1, sfr2;
	const Json::Int64StringList dmIds({0, 1});
	const Json::Int64StringList diIds({2, 3});

	/* Must be null. */
	QVERIFY(sfr1.dmIds().isEmpty());
	QVERIFY(sfr1.diIds().isEmpty());
	QVERIFY(sfr2.dmIds().isEmpty());
	QVERIFY(sfr2.diIds().isEmpty());

	QVERIFY(sfr1.isNull());
	QVERIFY(sfr2.isNull());
	QVERIFY(sfr1 == sfr2);

	/* Check whether values are not cross-linked. */
	sfr1.setDmIds(dmIds);
	sfr1.setDiIds(diIds);

	QVERIFY(sfr1.dmIds() == dmIds);
	QVERIFY(sfr1.diIds() == diIds);

	QVERIFY(!sfr1.isNull());
	QVERIFY(sfr2.isNull());
	QVERIFY(sfr1 != sfr2);

	/* Check value copying. */
	sfr2 = sfr1;

	QVERIFY(sfr2.dmIds() == dmIds);
	QVERIFY(sfr2.diIds() == diIds);

	QVERIFY(!sfr1.isNull());
	QVERIFY(!sfr2.isNull());
	QVERIFY(sfr1 == sfr2);

	/* Clear value. */
	sfr1 = RecMgmt::StoredFilesReq();

	QVERIFY(sfr1.dmIds().isEmpty());
	QVERIFY(sfr1.diIds().isEmpty());

	QVERIFY(sfr1.isNull());
	QVERIFY(!sfr2.isNull());
	QVERIFY(sfr1 != sfr2);
}

void TestRecordsManagement::storedFilesReqCompare(void)
{
	RecMgmt::StoredFilesReq sfr1, sfr2;
	const Json::Int64StringList dmIds({0, 1});
	const Json::Int64StringList diIds({2, 3});

	sfr1.setDmIds(dmIds);
	sfr1.setDiIds(diIds);
	sfr2.setDmIds(dmIds);
	sfr2.setDiIds(diIds);

	QVERIFY(sfr1 == sfr2);

	sfr1.setDmIds(Json::Int64StringList({4}));
	QVERIFY(sfr1 != sfr2);
	sfr1.setDmIds(dmIds);
	QVERIFY(sfr1 == sfr2);

	sfr1.setDiIds(Json::Int64StringList({4}));
	QVERIFY(sfr1 != sfr2);
	sfr1.setDiIds(diIds);
	QVERIFY(sfr1 == sfr2);
}

void TestRecordsManagement::storedFilesReqConstructor(void)
{
	const Json::Int64StringList cDmIds({0, 1});
	const Json::Int64StringList cDiIds({2, 3});

	{
		RecMgmt::StoredFilesReq sfr;

		QVERIFY(sfr.isNull());
		QVERIFY(!sfr.isValid());

		QVERIFY(sfr.dmIds().isEmpty());
		QVERIFY(sfr.diIds().isEmpty());
	}

	{
		Json::Int64StringList dmIds(cDmIds);
		Json::Int64StringList diIds(cDiIds);

		RecMgmt::StoredFilesReq sfr(dmIds, diIds);

		QVERIFY(!sfr.isNull());
		QVERIFY(sfr.isValid());

		QVERIFY(sfr.dmIds() == cDmIds);
		QVERIFY(sfr.diIds() == cDiIds);

		QVERIFY(dmIds == cDmIds);
		QVERIFY(diIds == cDiIds);
	}

#ifdef Q_COMPILER_RVALUE_REFS
	{
		Json::Int64StringList dmIds(cDmIds);
		Json::Int64StringList diIds(cDiIds);

		RecMgmt::StoredFilesReq sfr(::std::move(dmIds), ::std::move(diIds));

		QVERIFY(!sfr.isNull());
		QVERIFY(sfr.isValid());

		QVERIFY(sfr.dmIds() == cDmIds);
		QVERIFY(sfr.diIds() == cDiIds);

		QVERIFY(dmIds != cDmIds);
		QVERIFY(dmIds.isEmpty());
		QVERIFY(diIds != cDiIds);
		QVERIFY(diIds.isEmpty());
	}
#endif /* Q_COMPILER_RVALUE_REFS */
}

void TestRecordsManagement::storedFilesReqCopy(void)
{
	RecMgmt::StoredFilesReq sfr1;
	const Json::Int64StringList dmIds({0, 1});
	const Json::Int64StringList diIds({2, 3});

	sfr1.setDmIds(dmIds);
	sfr1.setDiIds(diIds);

	/* Constructor. */
	{
		RecMgmt::StoredFilesReq sfr2(sfr1);

		QVERIFY(!sfr1.isNull());
		QVERIFY(!sfr2.isNull());
		QVERIFY(sfr1 == sfr2);

#ifdef Q_COMPILER_RVALUE_REFS
		/* Move. */
		RecMgmt::StoredFilesReq sfr3(::std::move(sfr2));

		QVERIFY(sfr2.isNull());
		QVERIFY(sfr1 != sfr2);

		QVERIFY(!sfr1.isNull());
		QVERIFY(!sfr3.isNull());
		QVERIFY(sfr1 == sfr3);
#endif /* Q_COMPILER_RVALUE_REFS */
	}

	/* Assignment operator. */
	{
		RecMgmt::StoredFilesReq sfr2;

		QVERIFY(sfr2.isNull());

		sfr2 = sfr1;

		QVERIFY(!sfr1.isNull());
		QVERIFY(!sfr2.isNull());
		QVERIFY(sfr1 == sfr2);

#ifdef Q_COMPILER_RVALUE_REFS
		/* Move. */
		RecMgmt::StoredFilesReq sfr3;

		QVERIFY(sfr3.isNull());

		sfr3 = ::std::move(sfr2);

		QVERIFY(sfr2.isNull());
		QVERIFY(sfr1 != sfr2);

		QVERIFY(!sfr1.isNull());
		QVERIFY(!sfr3.isNull());
		QVERIFY(sfr1 == sfr3);
#endif /* Q_COMPILER_RVALUE_REFS */
	}
}

void TestRecordsManagement::storedFilesReqValues(void)
{
	const Json::Int64StringList cDmIds({0, 1});
	const Json::Int64StringList cDiIds({2, 3});

	RecMgmt::StoredFilesReq sfr;
	Json::Int64StringList dmIds(cDmIds);
	Json::Int64StringList diIds(cDiIds);

	QVERIFY(sfr.dmIds().isEmpty());
	sfr.setDmIds(dmIds);
	QVERIFY(sfr.dmIds() == cDmIds);
	QVERIFY(dmIds == cDmIds);
#ifdef Q_COMPILER_RVALUE_REFS
	sfr.setDmIds(Json::Int64StringList({4}));
	QVERIFY(sfr.dmIds() != cDmIds);
	sfr.setDmIds(::std::move(dmIds));
	QVERIFY(sfr.dmIds() == cDmIds);
	QVERIFY(dmIds != cDmIds);
#endif /* Q_COMPILER_RVALUE_REFS */

	QVERIFY(sfr.diIds().isEmpty());
	sfr.setDiIds(diIds);
	QVERIFY(sfr.diIds() == cDiIds);
	QVERIFY(diIds == cDiIds);
#ifdef Q_COMPILER_RVALUE_REFS
	sfr.setDiIds(Json::Int64StringList({4}));
	QVERIFY(sfr.diIds() != cDiIds);
	sfr.setDiIds(::std::move(diIds));
	QVERIFY(sfr.diIds() == cDiIds);
	QVERIFY(diIds != cDiIds);
#endif /* Q_COMPILER_RVALUE_REFS */
}

void TestRecordsManagement::storedFilesReqJsonConversion(void)
{
	RecMgmt::StoredFilesReq sfr1, sfr2;
	const Json::Int64StringList dmIds({0, 1});
	const Json::Int64StringList diIds({2, 3});

	bool iOk = false;
	QByteArray jsonData;
	QJsonValue jsonVal;

	QVERIFY(sfr1.isNull());
	QVERIFY(sfr2.isNull());
	QVERIFY(sfr1 == sfr2);

	sfr1.setDmIds(dmIds);
	sfr1.setDiIds(diIds);

	QVERIFY(!sfr1.isNull());
	QVERIFY(sfr2.isNull());
	QVERIFY(sfr1 != sfr2);

	/* Empty data cause error. */
	iOk = true;
	sfr2 = RecMgmt::StoredFilesReq::fromJson(QByteArray(), &iOk);
	QVERIFY(iOk == false);
	QVERIFY(sfr2.isNull());

	/* Null value causes error. */
	iOk = true;
	sfr2 = RecMgmt::StoredFilesReq::fromJsonVal(QJsonValue(), &iOk);
	QVERIFY(iOk == false);
	QVERIFY(sfr2.isNull());

	/* Null object converts onto non-null value. */
	iOk = false;
	iOk = sfr2.toJsonVal(jsonVal);
	QVERIFY(iOk == true);
	QVERIFY(!jsonVal.isNull());

	jsonData = sfr1.toJsonData();
	QVERIFY(!jsonData.isEmpty());

	iOk = false;
	sfr2 = RecMgmt::StoredFilesReq::fromJson(jsonData, &iOk);
	QVERIFY(iOk == true);
	QVERIFY(!sfr2.isNull());

	QVERIFY(!sfr1.isNull());
	QVERIFY(!sfr2.isNull());
	QVERIFY(sfr1 == sfr2);
}

void TestRecordsManagement::dmEntry(void)
{
	RecMgmt::DmEntry e1, e2;
	const qint64 dmId(1);
	const QStringList locations({"location1", "location2"});

	/* Must be null. */
	QVERIFY(e1.dmId() == -1);
	QVERIFY(e1.locations().isEmpty());
	QVERIFY(e2.dmId() == -1);
	QVERIFY(e2.locations().isEmpty());

	QVERIFY(e1.isNull());
	QVERIFY(e2.isNull());
	QVERIFY(e1 == e2);

	/* Check whether values are not cross-linked. */
	e1.setDmId(dmId);
	e1.setLocations(locations);

	QVERIFY(e1.dmId() == 1);
	QVERIFY(e1.locations() == locations);

	QVERIFY(!e1.isNull());
	QVERIFY(e2.isNull());
	QVERIFY(e1 != e2);

	/* Check value copying. */
	e2 = e1;

	QVERIFY(e2.dmId() == 1);
	QVERIFY(e2.locations() == locations);

	QVERIFY(!e1.isNull());
	QVERIFY(!e2.isNull());
	QVERIFY(e1 == e2);

	/* Clear value. */
	e1 = RecMgmt::DmEntry();

	QVERIFY(e1.dmId() == -1);
	QVERIFY(e1.locations().isEmpty());

	QVERIFY(e1.isNull());
	QVERIFY(!e2.isNull());
	QVERIFY(e1 != e2);
}

void TestRecordsManagement::dmEntryCompare(void)
{
	RecMgmt::DmEntry e1, e2;
	const qint64 dmId(1);
	const QStringList locations({"location1", "location2"});

	e1.setDmId(dmId);
	e1.setLocations(locations);
	e2.setDmId(dmId);
	e2.setLocations(locations);

	QVERIFY(e1 == e2);

	e1.setDmId(0);
	QVERIFY(e1 != e2);
	e1.setDmId(dmId);
	QVERIFY(e1 == e2);

	e1.setLocations(QStringList({"location3"}));
	QVERIFY(e1 != e2);
	e1.setLocations(locations);
	QVERIFY(e1 == e2);
}

void TestRecordsManagement::dmEntryConstructor(void)
{
	const qint64 cDmId(1);
	const QStringList cLocations({"location1", "location2"});

	{
		RecMgmt::DmEntry e;

		QVERIFY(e.isNull());
		QVERIFY(!e.isValid());

		QVERIFY(e.dmId() == -1);
		QVERIFY(e.locations().isEmpty());
	}

	{
		qint64 dmId(cDmId);
		QStringList locations(cLocations);

		RecMgmt::DmEntry e(dmId, locations);

		QVERIFY(!e.isNull());
		QVERIFY(e.isValid());

		QVERIFY(e.dmId() == cDmId);
		QVERIFY(e.locations() == cLocations);

		QVERIFY(dmId == cDmId);
		QVERIFY(locations == cLocations);
	}

#ifdef Q_COMPILER_RVALUE_REFS
	{
		qint64 dmId(cDmId);
		QStringList locations(cLocations);

		RecMgmt::DmEntry e(dmId, ::std::move(locations));

		QVERIFY(!e.isNull());
		QVERIFY(e.isValid());

		QVERIFY(e.dmId() == cDmId);
		QVERIFY(e.locations() == cLocations);

		QVERIFY(dmId == cDmId);
#  if (QT_VERSION >= QT_VERSION_CHECK(5, 4, 0))
		QVERIFY(locations != cLocations);
		QVERIFY(locations.isEmpty());
#  endif /* >= Qt-5.4 */
	}
#endif /* Q_COMPILER_RVALUE_REFS */
}

void TestRecordsManagement::dmEntryCopy(void)
{
	RecMgmt::DmEntry e1;
	const qint64 dmId(1);
	const QStringList locations({"location1", "location2"});

	e1.setDmId(dmId);
	e1.setLocations(locations);

	/* Constructor. */
	{
		RecMgmt::DmEntry e2(e1);

		QVERIFY(!e1.isNull());
		QVERIFY(!e2.isNull());
		QVERIFY(e1 == e2);

#ifdef Q_COMPILER_RVALUE_REFS
		/* Move. */
		RecMgmt::DmEntry e3(::std::move(e2));

		QVERIFY(e2.isNull());
		QVERIFY(e1 != e2);

		QVERIFY(!e1.isNull());
		QVERIFY(!e3.isNull());
		QVERIFY(e1 == e3);
#endif /* Q_COMPILER_RVALUE_REFS */
	}

	/* Assignment operator. */
	{
		RecMgmt::DmEntry e2;

		QVERIFY(e2.isNull());

		e2 = e1;

		QVERIFY(!e1.isNull());
		QVERIFY(!e2.isNull());
		QVERIFY(e1 == e2);

#ifdef Q_COMPILER_RVALUE_REFS
		/* Move. */
		RecMgmt::DmEntry e3;

		QVERIFY(e3.isNull());

		e3 = ::std::move(e2);

		QVERIFY(e2.isNull());
		QVERIFY(e1 != e2);

		QVERIFY(!e1.isNull());
		QVERIFY(!e3.isNull());
		QVERIFY(e1 == e3);
#endif /* Q_COMPILER_RVALUE_REFS */
	}
}

void TestRecordsManagement::dmEntryValues(void)
{
	const qint64 cDmId(1);
	const QStringList cLocations({"location1", "location2"});

	RecMgmt::DmEntry e;
	qint64 dmId(cDmId);
	QStringList locations(cLocations);

	QVERIFY(e.dmId() == -1);
	e.setDmId(dmId);
	QVERIFY(e.dmId() == cDmId);
	QVERIFY(dmId == cDmId);

	QVERIFY(e.locations().isEmpty());
	e.setLocations(locations);
	QVERIFY(e.locations() == cLocations);
	QVERIFY(locations == cLocations);
#ifdef Q_COMPILER_RVALUE_REFS
	e.setLocations(QStringList({"location2"}));
	QVERIFY(e.locations() != cLocations);
	e.setLocations(::std::move(locations));
	QVERIFY(e.locations() == cLocations);
#  if (QT_VERSION >= QT_VERSION_CHECK(5, 4, 0))
	QVERIFY(locations != cLocations);
#  endif /* >= Qt-5.4 */
#endif /* Q_COMPILER_RVALUE_REFS */
}

void TestRecordsManagement::dmEntryJsonConversion(void)
{
	RecMgmt::DmEntry e1, e2;
	const qint64 dmId(1);
	const QStringList locations({"location1", "location2"});

	bool iOk = false;
	QByteArray jsonData;
	QJsonValue jsonVal;

	QVERIFY(e1.isNull());
	QVERIFY(e2.isNull());
	QVERIFY(e1 == e2);

	e1.setDmId(dmId);
	e1.setLocations(locations);

	QVERIFY(!e1.isNull());
	QVERIFY(e2.isNull());
	QVERIFY(e1 != e2);

	/* Empty data cause error. */
	iOk = true;
	e2 = RecMgmt::DmEntry::fromJson(QByteArray(), &iOk);
	QVERIFY(iOk == false);
	QVERIFY(e2.isNull());

	/* Null value causes error. */
	iOk = true;
	e2 = RecMgmt::DmEntry::fromJsonVal(QJsonValue(), &iOk);
	QVERIFY(iOk == false);
	QVERIFY(e2.isNull());

	/* Null object converts onto non-null value. */
	iOk = false;
	iOk = e2.toJsonVal(jsonVal);
	QVERIFY(iOk == true);
	QVERIFY(!jsonVal.isNull());

	jsonData = e1.toJsonData();
	QVERIFY(!jsonData.isEmpty());

	iOk = false;
	e2 = RecMgmt::DmEntry::fromJson(jsonData, &iOk);
	QVERIFY(iOk == true);
	QVERIFY(!e2.isNull());

	QVERIFY(!e1.isNull());
	QVERIFY(!e2.isNull());
	QVERIFY(e1 == e2);
}

void TestRecordsManagement::dmEntryListJsonConversion(void)
{
	RecMgmt::DmEntryList el1, el2;
	const qint64 dmId(1);
	const QStringList locations({"location1", "location2"});

	bool iOk = false;
	QByteArray jsonData;
	QJsonValue jsonVal;

	QVERIFY(el1.isEmpty());
	QVERIFY(el2.isEmpty());
	QVERIFY(el1 == el2);

	el1.append(RecMgmt::DmEntry(dmId, locations));

	QVERIFY(!el1.isEmpty());
	QVERIFY(el2.isEmpty());
	QVERIFY(el1 != el2);

	/* Empty data cause error. */
	iOk = true;
	el2 = RecMgmt::DmEntryList::fromJson(QByteArray(), &iOk);
	QVERIFY(iOk == false);
	QVERIFY(el2.isEmpty());

	/* Null value causes error. */
	iOk = true;
	el2 = RecMgmt::DmEntryList::fromJsonVal(QJsonValue(), &iOk);
	QVERIFY(iOk == false);
	QVERIFY(el2.isEmpty());

	/* Null object converts onto non-null value. */
	iOk = false;
	iOk = el2.toJsonVal(jsonVal);
	QVERIFY(iOk == true);
	QVERIFY(!jsonVal.isNull());

	jsonData = el1.toJsonData();
	QVERIFY(!jsonData.isEmpty());

	iOk = false;
	el2 = RecMgmt::DmEntryList::fromJson(jsonData, &iOk);
	QVERIFY(iOk == true);
	QVERIFY(!el2.isEmpty());

	QVERIFY(!el1.isEmpty());
	QVERIFY(!el2.isEmpty());
	QVERIFY(el1 == el2);
}

void TestRecordsManagement::diEntry(void)
{
	RecMgmt::DiEntry e1, e2;
	const qint64 diId(1);
	const QStringList locations({"location1", "location2"});

	/* Must be null. */
	QVERIFY(e1.diId() == -1);
	QVERIFY(e1.locations().isEmpty());
	QVERIFY(e2.diId() == -1);
	QVERIFY(e2.locations().isEmpty());

	QVERIFY(e1.isNull());
	QVERIFY(e2.isNull());
	QVERIFY(e1 == e2);

	/* Check whether values are not cross-linked. */
	e1.setDiId(diId);
	e1.setLocations(locations);

	QVERIFY(e1.diId() == 1);
	QVERIFY(e1.locations() == locations);

	QVERIFY(!e1.isNull());
	QVERIFY(e2.isNull());
	QVERIFY(e1 != e2);

	/* Check value copying. */
	e2 = e1;

	QVERIFY(e2.diId() == 1);
	QVERIFY(e2.locations() == locations);

	QVERIFY(!e1.isNull());
	QVERIFY(!e2.isNull());
	QVERIFY(e1 == e2);

	/* Clear value. */
	e1 = RecMgmt::DiEntry();

	QVERIFY(e1.diId() == -1);
	QVERIFY(e1.locations().isEmpty());

	QVERIFY(e1.isNull());
	QVERIFY(!e2.isNull());
	QVERIFY(e1 != e2);
}

void TestRecordsManagement::diEntryCompare(void)
{
	RecMgmt::DiEntry e1, e2;
	const qint64 diId(1);
	const QStringList locations({"location1", "location2"});

	e1.setDiId(diId);
	e1.setLocations(locations);
	e2.setDiId(diId);
	e2.setLocations(locations);

	QVERIFY(e1 == e2);

	e1.setDiId(0);
	QVERIFY(e1 != e2);
	e1.setDiId(diId);
	QVERIFY(e1 == e2);

	e1.setLocations(QStringList({"location3"}));
	QVERIFY(e1 != e2);
	e1.setLocations(locations);
	QVERIFY(e1 == e2);
}

void TestRecordsManagement::diEntryConstructor(void)
{
	const qint64 cDiId(1);
	const QStringList cLocations({"location1", "location2"});

	{
		RecMgmt::DiEntry e;

		QVERIFY(e.isNull());
		QVERIFY(!e.isValid());

		QVERIFY(e.diId() == -1);
		QVERIFY(e.locations().isEmpty());
	}

	{
		qint64 diId(cDiId);
		QStringList locations(cLocations);

		RecMgmt::DiEntry e(diId, locations);

		QVERIFY(!e.isNull());
		QVERIFY(e.isValid());

		QVERIFY(e.diId() == cDiId);
		QVERIFY(e.locations() == cLocations);

		QVERIFY(diId == cDiId);
		QVERIFY(locations == cLocations);
	}

#ifdef Q_COMPILER_RVALUE_REFS
	{
		qint64 diId(cDiId);
		QStringList locations(cLocations);

		RecMgmt::DiEntry e(diId, ::std::move(locations));

		QVERIFY(!e.isNull());
		QVERIFY(e.isValid());

		QVERIFY(e.diId() == cDiId);
		QVERIFY(e.locations() == cLocations);

		QVERIFY(diId == cDiId);
#  if (QT_VERSION >= QT_VERSION_CHECK(5, 4, 0))
		QVERIFY(locations != cLocations);
		QVERIFY(locations.isEmpty());
#  endif /* >= Qt-5.4 */
	}
#endif /* Q_COMPILER_RVALUE_REFS */
}

void TestRecordsManagement::diEntryCopy(void)
{
	RecMgmt::DiEntry e1;
	const qint64 diId(1);
	const QStringList locations({"location1", "location2"});

	e1.setDiId(diId);
	e1.setLocations(locations);

	/* Constructor. */
	{
		RecMgmt::DiEntry e2(e1);

		QVERIFY(!e1.isNull());
		QVERIFY(!e2.isNull());
		QVERIFY(e1 == e2);

#ifdef Q_COMPILER_RVALUE_REFS
		/* Move. */
		RecMgmt::DiEntry e3(::std::move(e2));

		QVERIFY(e2.isNull());
		QVERIFY(e1 != e2);

		QVERIFY(!e1.isNull());
		QVERIFY(!e3.isNull());
		QVERIFY(e1 == e3);
#endif /* Q_COMPILER_RVALUE_REFS */
	}

	/* Assignment operator. */
	{
		RecMgmt::DiEntry e2;

		QVERIFY(e2.isNull());

		e2 = e1;

		QVERIFY(!e1.isNull());
		QVERIFY(!e2.isNull());
		QVERIFY(e1 == e2);

#ifdef Q_COMPILER_RVALUE_REFS
		/* Move. */
		RecMgmt::DiEntry e3;

		QVERIFY(e3.isNull());

		e3 = ::std::move(e2);

		QVERIFY(e2.isNull());
		QVERIFY(e1 != e2);

		QVERIFY(!e1.isNull());
		QVERIFY(!e3.isNull());
		QVERIFY(e1 == e3);
#endif /* Q_COMPILER_RVALUE_REFS */
	}
}

void TestRecordsManagement::diEntryValues(void)
{
	const qint64 cDiId(1);
	const QStringList cLocations({"location1", "location2"});

	RecMgmt::DiEntry e;
	qint64 diId(cDiId);
	QStringList locations(cLocations);

	QVERIFY(e.diId() == -1);
	e.setDiId(diId);
	QVERIFY(e.diId() == cDiId);
	QVERIFY(diId == cDiId);

	QVERIFY(e.locations().isEmpty());
	e.setLocations(locations);
	QVERIFY(e.locations() == cLocations);
	QVERIFY(locations == cLocations);
#ifdef Q_COMPILER_RVALUE_REFS
	e.setLocations(QStringList({"location2"}));
	QVERIFY(e.locations() != cLocations);
	e.setLocations(::std::move(locations));
	QVERIFY(e.locations() == cLocations);
#  if (QT_VERSION >= QT_VERSION_CHECK(5, 4, 0))
	QVERIFY(locations != cLocations);
#  endif /* >= Qt-5.4 */
#endif /* Q_COMPILER_RVALUE_REFS */
}

void TestRecordsManagement::diEntryJsonConversion(void)
{
	RecMgmt::DiEntry e1, e2;
	const qint64 diId(1);
	const QStringList locations({"location1", "location2"});

	bool iOk = false;
	QByteArray jsonData;
	QJsonValue jsonVal;

	QVERIFY(e1.isNull());
	QVERIFY(e2.isNull());
	QVERIFY(e1 == e2);

	e1.setDiId(diId);
	e1.setLocations(locations);

	QVERIFY(!e1.isNull());
	QVERIFY(e2.isNull());
	QVERIFY(e1 != e2);

	/* Empty data cause error. */
	iOk = true;
	e2 = RecMgmt::DiEntry::fromJson(QByteArray(), &iOk);
	QVERIFY(iOk == false);
	QVERIFY(e2.isNull());

	/* Null value causes error. */
	iOk = true;
	e2 = RecMgmt::DiEntry::fromJsonVal(QJsonValue(), &iOk);
	QVERIFY(iOk == false);
	QVERIFY(e2.isNull());

	/* Null object converts onto non-null value. */
	iOk = false;
	iOk = e2.toJsonVal(jsonVal);
	QVERIFY(iOk == true);
	QVERIFY(!jsonVal.isNull());

	jsonData = e1.toJsonData();
	QVERIFY(!jsonData.isEmpty());

	iOk = false;
	e2 = RecMgmt::DiEntry::fromJson(jsonData, &iOk);
	QVERIFY(iOk == true);
	QVERIFY(!e2.isNull());

	QVERIFY(!e1.isNull());
	QVERIFY(!e2.isNull());
	QVERIFY(e1 == e2);
}

void TestRecordsManagement::diEntryListJsonConversion(void)
{
	RecMgmt::DiEntryList el1, el2;
	const qint64 diId(1);
	const QStringList locations({"location1", "location2"});

	bool iOk = false;
	QByteArray jsonData;
	QJsonValue jsonVal;

	QVERIFY(el1.isEmpty());
	QVERIFY(el2.isEmpty());
	QVERIFY(el1 == el2);

	el1.append(RecMgmt::DiEntry(diId, locations));

	QVERIFY(!el1.isEmpty());
	QVERIFY(el2.isEmpty());
	QVERIFY(el1 != el2);

	/* Empty data cause error. */
	iOk = true;
	el2 = RecMgmt::DiEntryList::fromJson(QByteArray(), &iOk);
	QVERIFY(iOk == false);
	QVERIFY(el2.isEmpty());

	/* Null value causes error. */
	iOk = true;
	el2 = RecMgmt::DiEntryList::fromJsonVal(QJsonValue(), &iOk);
	QVERIFY(iOk == false);
	QVERIFY(el2.isEmpty());

	/* Null object converts onto non-null value. */
	iOk = false;
	iOk = el2.toJsonVal(jsonVal);
	QVERIFY(iOk == true);
	QVERIFY(!jsonVal.isNull());

	jsonData = el1.toJsonData();
	QVERIFY(!jsonData.isEmpty());

	iOk = false;
	el2 = RecMgmt::DiEntryList::fromJson(jsonData, &iOk);
	QVERIFY(iOk == true);
	QVERIFY(!el2.isEmpty());

	QVERIFY(!el1.isEmpty());
	QVERIFY(!el2.isEmpty());
	QVERIFY(el1 == el2);
}

void TestRecordsManagement::storedFilesResp(void)
{
	RecMgmt::StoredFilesResp sfr1, sfr2;
	const RecMgmt::DmEntryList dms(
	    {RecMgmt::DmEntry(1, QStringList({"location1", "location2"}))});
	const RecMgmt::DiEntryList dis(
	    {RecMgmt::DiEntry(2, QStringList({"location3", "location4"}))});
	const int limit(1);
	const RecMgmt::ErrorEntry error(
	    RecMgmt::ErrorEntry::ERR_MALFORMED_REQUEST, "description");

	/* Must be null. */
	QVERIFY(sfr1.dms().isEmpty());
	QVERIFY(sfr1.dis().isEmpty());
	QVERIFY(sfr1.limit() == -1);
	QVERIFY(sfr1.error().isNull());
	QVERIFY(sfr2.dms().isEmpty());
	QVERIFY(sfr2.dis().isEmpty());
	QVERIFY(sfr2.limit() == -1);
	QVERIFY(sfr2.error().isNull());

	QVERIFY(sfr1.isNull());
	QVERIFY(sfr2.isNull());
	QVERIFY(sfr1 == sfr2);

	/* Check whether values are not cross-linked. */
	sfr1.setDms(dms);
	sfr1.setDis(dis);
	sfr1.setLimit(limit);
	sfr1.setError(error);

	QVERIFY(sfr1.dms() == dms);
	QVERIFY(sfr1.dis() == dis);
	QVERIFY(sfr1.limit() == limit);
	QVERIFY(sfr1.error() == error);

	QVERIFY(!sfr1.isNull());
	QVERIFY(sfr2.isNull());
	QVERIFY(sfr1 != sfr2);

	/* Check value copying. */
	sfr2 = sfr1;

	QVERIFY(sfr2.dms() == dms);
	QVERIFY(sfr2.dis() == dis);
	QVERIFY(sfr2.limit() == limit);
	QVERIFY(sfr2.error() == error);

	QVERIFY(!sfr1.isNull());
	QVERIFY(!sfr2.isNull());
	QVERIFY(sfr1 == sfr2);

	/* Clear value. */
	sfr1 = RecMgmt::StoredFilesResp();

	QVERIFY(sfr1.dms().isEmpty());
	QVERIFY(sfr1.dis().isEmpty());
	QVERIFY(sfr1.limit() == -1);
	QVERIFY(sfr1.error().isNull());

	QVERIFY(sfr1.isNull());
	QVERIFY(!sfr2.isNull());
	QVERIFY(sfr1 != sfr2);
}

void TestRecordsManagement::storedFilesRespCompare(void)
{
	RecMgmt::StoredFilesResp sfr1, sfr2;
	const RecMgmt::DmEntryList dms(
	    {RecMgmt::DmEntry(1, QStringList({"location1", "location2"}))});
	const RecMgmt::DiEntryList dis(
	    {RecMgmt::DiEntry(2, QStringList({"location3", "location4"}))});
	const int limit(1);
	const RecMgmt::ErrorEntry error(
	    RecMgmt::ErrorEntry::ERR_MALFORMED_REQUEST, "description");

	sfr1.setDms(dms);
	sfr1.setDis(dis);
	sfr1.setLimit(limit);
	sfr1.setError(error);
	sfr2.setDms(dms);
	sfr2.setDis(dis);
	sfr2.setLimit(limit);
	sfr2.setError(error);

	QVERIFY(sfr1 == sfr2);

	sfr1.setDms(RecMgmt::DmEntryList(
	    {RecMgmt::DmEntry(3, QStringList({"location5"}))}));
	QVERIFY(sfr1 != sfr2);
	sfr1.setDms(dms);
	QVERIFY(sfr1 == sfr2);

	sfr1.setDis(RecMgmt::DiEntryList(
	    {RecMgmt::DiEntry(3, QStringList({"location5"}))}));
	QVERIFY(sfr1 != sfr2);
	sfr1.setDis(dis);
	QVERIFY(sfr1 == sfr2);

	sfr1.setLimit(2);
	QVERIFY(sfr1 != sfr2);
	sfr1.setLimit(limit);
	QVERIFY(sfr1 == sfr2);

	sfr1.setError(RecMgmt::ErrorEntry(
	    RecMgmt::ErrorEntry::ERR_MISSING_IDENTIFIER, "description2"));
	QVERIFY(sfr1 != sfr2);
	sfr1.setError(error);
	QVERIFY(sfr1 == sfr2);
}

void TestRecordsManagement::storedFilesRespConstructor(void)
{
	const RecMgmt::DmEntryList cDms(
	    {RecMgmt::DmEntry(1, QStringList({"location1", "location2"}))});
	const RecMgmt::DiEntryList cDis(
	    {RecMgmt::DiEntry(2, QStringList({"location3", "location4"}))});
	const int cLimit(1);
	const RecMgmt::ErrorEntry cError(
	    RecMgmt::ErrorEntry::ERR_MALFORMED_REQUEST, "description");

	{
		RecMgmt::StoredFilesResp sfr;

		QVERIFY(sfr.isNull());
		QVERIFY(!sfr.isValid());

		QVERIFY(sfr.dms().isEmpty());
		QVERIFY(sfr.dis().isEmpty());
		QVERIFY(sfr.limit() == -1);
		QVERIFY(sfr.error().isNull());
	}

	{
		RecMgmt::DmEntryList dms(cDms);
		RecMgmt::DiEntryList dis(cDis);
		int limit(cLimit);
		RecMgmt::ErrorEntry error(cError);

		RecMgmt::StoredFilesResp sfr(dms, dis, limit, error);

		QVERIFY(!sfr.isNull());
		QVERIFY(sfr.isValid());

		QVERIFY(sfr.dms() == cDms);
		QVERIFY(sfr.dis() == cDis);
		QVERIFY(sfr.limit() == cLimit);
		QVERIFY(sfr.error() == cError);

		QVERIFY(dms == cDms);
		QVERIFY(dis == cDis);
		QVERIFY(limit == cLimit);
		QVERIFY(error == cError);
	}

#ifdef Q_COMPILER_RVALUE_REFS
	{
		RecMgmt::DmEntryList dms(cDms);
		RecMgmt::DiEntryList dis(cDis);
		int limit(cLimit);
		RecMgmt::ErrorEntry error(cError);

		RecMgmt::StoredFilesResp sfr(::std::move(dms), ::std::move(dis),
		    limit, ::std::move(error));

		QVERIFY(!sfr.isNull());
		QVERIFY(sfr.isValid());

		QVERIFY(sfr.dms() == cDms);
		QVERIFY(sfr.dis() == cDis);
		QVERIFY(sfr.limit() == cLimit);
		QVERIFY(sfr.error() == cError);

		QVERIFY(dms != cDms);
		QVERIFY(dms.isEmpty());
		QVERIFY(dis != cDis);
		QVERIFY(dis.isEmpty());
		QVERIFY(limit == cLimit);
		QVERIFY(error != cError);
		QVERIFY(error.isNull());
	}
#endif /* Q_COMPILER_RVALUE_REFS */
}

void TestRecordsManagement::storedFilesRespCopy(void)
{
	RecMgmt::StoredFilesResp sfr1;
	const RecMgmt::DmEntryList dms(
	    {RecMgmt::DmEntry(1, QStringList({"location1", "location2"}))});
	const RecMgmt::DiEntryList dis(
	    {RecMgmt::DiEntry(2, QStringList({"location3", "location4"}))});
	const int limit(1);
	const RecMgmt::ErrorEntry error(
	    RecMgmt::ErrorEntry::ERR_MALFORMED_REQUEST, "description");

	sfr1.setDms(dms);
	sfr1.setDis(dis);
	sfr1.setLimit(limit);
	sfr1.setError(error);

	/* Constructor. */
	{
		RecMgmt::StoredFilesResp sfr2(sfr1);

		QVERIFY(!sfr1.isNull());
		QVERIFY(!sfr2.isNull());
		QVERIFY(sfr1 == sfr2);

#ifdef Q_COMPILER_RVALUE_REFS
		/* Move. */
		RecMgmt::StoredFilesResp sfr3(::std::move(sfr2));

		QVERIFY(sfr2.isNull());
		QVERIFY(sfr1 != sfr2);

		QVERIFY(!sfr1.isNull());
		QVERIFY(!sfr3.isNull());
		QVERIFY(sfr1 == sfr3);
#endif /* Q_COMPILER_RVALUE_REFS */
	}

	/* Assignment operator. */
	{
		RecMgmt::StoredFilesResp sfr2;

		QVERIFY(sfr2.isNull());

		sfr2 = sfr1;

		QVERIFY(!sfr1.isNull());
		QVERIFY(!sfr2.isNull());
		QVERIFY(sfr1 == sfr2);

#ifdef Q_COMPILER_RVALUE_REFS
		/* Move. */
		RecMgmt::StoredFilesResp sfr3;

		QVERIFY(sfr3.isNull());

		sfr3 = ::std::move(sfr2);

		QVERIFY(sfr2.isNull());
		QVERIFY(sfr1 != sfr2);

		QVERIFY(!sfr1.isNull());
		QVERIFY(!sfr3.isNull());
		QVERIFY(sfr1 == sfr3);
#endif /* Q_COMPILER_RVALUE_REFS */
	}
}

void TestRecordsManagement::storedFilesRespValues(void)
{
	const RecMgmt::DmEntryList cDms(
	    {RecMgmt::DmEntry(1, QStringList({"location1", "location2"}))});
	const RecMgmt::DiEntryList cDis(
	    {RecMgmt::DiEntry(2, QStringList({"location3", "location4"}))});
	const int cLimit(1);
	const RecMgmt::ErrorEntry cError(
	    RecMgmt::ErrorEntry::ERR_MALFORMED_REQUEST, "description");

	RecMgmt::StoredFilesResp sfr;
	RecMgmt::DmEntryList dms(cDms);
	RecMgmt::DiEntryList dis(cDis);
	int limit(cLimit);
	RecMgmt::ErrorEntry error(cError);

	QVERIFY(sfr.dms().isEmpty());
	sfr.setDms(dms);
	QVERIFY(sfr.dms() == cDms);
	QVERIFY(dms == cDms);
#ifdef Q_COMPILER_RVALUE_REFS
	sfr.setDms(RecMgmt::DmEntryList(
	    {RecMgmt::DmEntry(3, QStringList({"location5"}))}));
	QVERIFY(sfr.dms() != cDms);
	sfr.setDms(::std::move(dms));
	QVERIFY(sfr.dms() == cDms);
	QVERIFY(dms != cDms);
#endif /* Q_COMPILER_RVALUE_REFS */

	QVERIFY(sfr.dis().isEmpty());
	sfr.setDis(dis);
	QVERIFY(sfr.dis() == cDis);
	QVERIFY(dis == cDis);
#ifdef Q_COMPILER_RVALUE_REFS
	sfr.setDis(RecMgmt::DiEntryList(
	    {RecMgmt::DiEntry(3, QStringList({"location5"}))}));
	QVERIFY(sfr.dis() != cDis);
	sfr.setDis(::std::move(dis));
	QVERIFY(sfr.dis() == cDis);
	QVERIFY(dis != cDis);
#endif /* Q_COMPILER_RVALUE_REFS */

	QVERIFY(sfr.limit() == -1);
	sfr.setLimit(limit);
	QVERIFY(sfr.limit() == cLimit);
	QVERIFY(limit == cLimit);

	QVERIFY(sfr.error().isNull());
	sfr.setError(error);
	QVERIFY(sfr.error() == cError);
	QVERIFY(error == cError);
#ifdef Q_COMPILER_RVALUE_REFS
	sfr.setError(RecMgmt::ErrorEntry(
	    RecMgmt::ErrorEntry::ERR_MISSING_IDENTIFIER, "description2"));
	QVERIFY(sfr.error() != cError);
	sfr.setError(::std::move(error));
	QVERIFY(sfr.error() == cError);
	QVERIFY(error != cError);
#endif /* Q_COMPILER_RVALUE_REFS */
}

void TestRecordsManagement::storedFilesRespJsonConversion(void)
{
	RecMgmt::StoredFilesResp sfr1, sfr2;
	const RecMgmt::DmEntryList dms(
	    {RecMgmt::DmEntry(1, QStringList({"location1", "location2"}))});
	const RecMgmt::DiEntryList dis(
	    {RecMgmt::DiEntry(2, QStringList({"location3", "location4"}))});
	const int limit(1);
	const RecMgmt::ErrorEntry error(
	    RecMgmt::ErrorEntry::ERR_MALFORMED_REQUEST, "description");

	bool iOk = false;
	QByteArray jsonData;
	QJsonValue jsonVal;

	QVERIFY(sfr1.dms().isEmpty());
	QVERIFY(sfr1.dis().isEmpty());
	QVERIFY(sfr1.limit() == -1);
	QVERIFY(sfr1.error().isNull());

	sfr1.setDms(dms);
	sfr1.setDis(dis);
	sfr1.setLimit(limit);
	sfr1.setError(error);

	QVERIFY(!sfr1.isNull());
	QVERIFY(sfr2.isNull());
	QVERIFY(sfr1 != sfr2);

	/* Empty data cause error. */
	iOk = true;
	sfr2 = RecMgmt::StoredFilesResp::fromJson(QByteArray(), &iOk);
	QVERIFY(iOk == false);
	QVERIFY(sfr2.isNull());

	/* Null value causes error. */
	iOk = true;
	sfr2 = RecMgmt::StoredFilesResp::fromJsonVal(QJsonValue(), &iOk);
	QVERIFY(iOk == false);
	QVERIFY(sfr2.isNull());

	/* Null object converts onto non-null value. */
	iOk = false;
	iOk = sfr2.toJsonVal(jsonVal);
	QVERIFY(iOk == true);
	QVERIFY(!jsonVal.isNull());

	jsonData = sfr1.toJsonData();
	QVERIFY(!jsonData.isEmpty());

	iOk = false;
	sfr2 = RecMgmt::StoredFilesResp::fromJson(jsonData, &iOk);
	QVERIFY(iOk == true);
	QVERIFY(!sfr2.isNull());

	QVERIFY(!sfr1.isNull());
	QVERIFY(!sfr2.isNull());
	QVERIFY(sfr1 == sfr2);
}

void TestRecordsManagement::uploadAccountStatusReq(void)
{
	RecMgmt::UploadAccountStatusReq uasr1, uasr2;
	const QString boxId("box_id");
	const QString userId("user_id");
	const QDateTime time(QDate(2014, 1, 31), QTime(0, 0, 0, 0), Qt::UTC);
	const int rcvdNotAccepted(1);
	const int sntNotAccepted(2);
	const int rcvdNotInRecMgmt(3);
	const int sntNotInRecMgmt(4);
	const QString userAccountName("user_account_name");

	/* Must be null. */
	QVERIFY(uasr1.boxId().isNull());
	QVERIFY(uasr1.userId().isNull());
	QVERIFY(uasr1.time().isNull());
	QVERIFY(uasr1.rcvdNotAccepted() == -1);
	QVERIFY(uasr1.sntNotAccepted() == -1);
	QVERIFY(uasr1.rcvdNotInRecMgmt() == -1);
	QVERIFY(uasr1.sntNotInRecMgmt() == -1);
	QVERIFY(uasr1.userAccountName().isNull());
	QVERIFY(uasr2.boxId().isNull());
	QVERIFY(uasr2.userId().isNull());
	QVERIFY(uasr2.time().isNull());
	QVERIFY(uasr2.rcvdNotAccepted() == -1);
	QVERIFY(uasr2.sntNotAccepted() == -1);
	QVERIFY(uasr2.rcvdNotInRecMgmt() == -1);
	QVERIFY(uasr2.sntNotInRecMgmt() == -1);
	QVERIFY(uasr2.userAccountName().isNull());

	QVERIFY(uasr1.isNull());
	QVERIFY(uasr2.isNull());
	QVERIFY(uasr1 == uasr2);

	/* Check whether values are not cross-linked. */
	uasr1.setBoxId(boxId);
	uasr1.setUserId(userId);
	uasr1.setTime(time);
	uasr1.setRcvdNotAccepted(rcvdNotAccepted);
	uasr1.setSntNotAccepted(sntNotAccepted);
	uasr1.setRcvdNotInRecMgmt(rcvdNotInRecMgmt);
	uasr1.setSntNotInRecMgmt(sntNotInRecMgmt);
	uasr1.setUserAccountName(userAccountName);

	QVERIFY(uasr1.boxId() == boxId);
	QVERIFY(uasr1.userId() == userId);
	QVERIFY(uasr1.time() == time);
	QVERIFY(uasr1.rcvdNotAccepted() == rcvdNotAccepted);
	QVERIFY(uasr1.sntNotAccepted() == sntNotAccepted);
	QVERIFY(uasr1.rcvdNotInRecMgmt() == rcvdNotInRecMgmt);
	QVERIFY(uasr1.sntNotInRecMgmt() == sntNotInRecMgmt);
	QVERIFY(uasr1.userAccountName() == userAccountName);

	QVERIFY(!uasr1.isNull());
	QVERIFY(uasr2.isNull());
	QVERIFY(uasr1 != uasr2);

	/* Check value copying. */
	uasr2 = uasr1;

	QVERIFY(uasr2.boxId() == boxId);
	QVERIFY(uasr2.userId() == userId);
	QVERIFY(uasr2.time() == time);
	QVERIFY(uasr2.rcvdNotAccepted() == rcvdNotAccepted);
	QVERIFY(uasr2.sntNotAccepted() == sntNotAccepted);
	QVERIFY(uasr2.rcvdNotInRecMgmt() == rcvdNotInRecMgmt);
	QVERIFY(uasr2.sntNotInRecMgmt() == sntNotInRecMgmt);
	QVERIFY(uasr2.userAccountName() == userAccountName);

	QVERIFY(!uasr1.isNull());
	QVERIFY(!uasr2.isNull());
	QVERIFY(uasr1 == uasr2);

	/* Clear value. */
	uasr1 = RecMgmt::UploadAccountStatusReq();

	QVERIFY(uasr1.boxId().isNull());
	QVERIFY(uasr1.userId().isNull());
	QVERIFY(uasr1.time().isNull());
	QVERIFY(uasr1.rcvdNotAccepted() == -1);
	QVERIFY(uasr1.sntNotAccepted() == -1);
	QVERIFY(uasr1.rcvdNotInRecMgmt() == -1);
	QVERIFY(uasr1.sntNotInRecMgmt() == -1);
	QVERIFY(uasr1.userAccountName().isNull());

	QVERIFY(uasr1.isNull());
	QVERIFY(!uasr2.isNull());
	QVERIFY(uasr1 != uasr2);
}

void TestRecordsManagement::uploadAccountStatusReqCompare(void)
{
	RecMgmt::UploadAccountStatusReq uasr1, uasr2;
	const QString boxId("box_id");
	const QString userId("user_id");
	const QDateTime time(QDate(2014, 1, 31), QTime(0, 0, 0, 0), Qt::UTC);
	const int rcvdNotAccepted(1);
	const int sntNotAccepted(2);
	const int rcvdNotInRecMgmt(3);
	const int sntNotInRecMgmt(4);
	const QString userAccountName("user_account_name");

	uasr1.setBoxId(boxId);
	uasr1.setUserId(userId);
	uasr1.setTime(time);
	uasr1.setRcvdNotAccepted(rcvdNotAccepted);
	uasr1.setSntNotAccepted(sntNotAccepted);
	uasr1.setRcvdNotInRecMgmt(rcvdNotInRecMgmt);
	uasr1.setSntNotInRecMgmt(sntNotInRecMgmt);
	uasr1.setUserAccountName(userAccountName);
	uasr2.setBoxId(boxId);
	uasr2.setUserId(userId);
	uasr2.setTime(time);
	uasr2.setRcvdNotAccepted(rcvdNotAccepted);
	uasr2.setSntNotAccepted(sntNotAccepted);
	uasr2.setRcvdNotInRecMgmt(rcvdNotInRecMgmt);
	uasr2.setSntNotInRecMgmt(sntNotInRecMgmt);
	uasr2.setUserAccountName(userAccountName);

	QVERIFY(uasr1 == uasr2);

	uasr1.setBoxId("other_box_id");
	QVERIFY(uasr1 != uasr2);
	uasr1.setBoxId(boxId);
	QVERIFY(uasr1 == uasr2);

	uasr1.setUserId("other_user_id");
	QVERIFY(uasr1 != uasr2);
	uasr1.setUserId(userId);
	QVERIFY(uasr1 == uasr2);

	uasr1.setTime(QDateTime(QDate(2014, 2, 1), QTime(0, 0, 0, 0), Qt::UTC));
	QVERIFY(uasr1 != uasr2);
	uasr1.setTime(time);
	QVERIFY(uasr1 == uasr2);

	uasr1.setRcvdNotAccepted(5);
	QVERIFY(uasr1 != uasr2);
	uasr1.setRcvdNotAccepted(rcvdNotAccepted);
	QVERIFY(uasr1 == uasr2);

	uasr1.setSntNotAccepted(6);
	QVERIFY(uasr1 != uasr2);
	uasr1.setSntNotAccepted(sntNotAccepted);
	QVERIFY(uasr1 == uasr2);

	uasr1.setRcvdNotInRecMgmt(7);
	QVERIFY(uasr1 != uasr2);
	uasr1.setRcvdNotInRecMgmt(rcvdNotInRecMgmt);
	QVERIFY(uasr1 == uasr2);

	uasr1.setSntNotInRecMgmt(8);
	QVERIFY(uasr1 != uasr2);
	uasr1.setSntNotInRecMgmt(sntNotInRecMgmt);
	QVERIFY(uasr1 == uasr2);

	uasr1.setUserAccountName("other_user_account_name");
	QVERIFY(uasr1 != uasr2);
	uasr1.setUserAccountName(userAccountName);
	QVERIFY(uasr1 == uasr2);
}

void TestRecordsManagement::uploadAccountStatusReqConstructor(void)
{
	const QString cBoxId("box_id");
	const QString cUserId("user_id");
	const QDateTime cTime(QDate(2014, 1, 31), QTime(0, 0, 0, 0), Qt::UTC);
	const int cRcvdNotAccepted(1);
	const int cSntNotAccepted(2);
	const int cRcvdNotInRecMgmt(3);
	const int cSntNotInRecMgmt(4);
	const QString cUserAccountName("user_account_name");

	{
		RecMgmt::UploadAccountStatusReq uasr;

		QVERIFY(uasr.isNull());
		QVERIFY(!uasr.isValid());

		QVERIFY(uasr.boxId().isNull());
		QVERIFY(uasr.userId().isNull());
		QVERIFY(uasr.time().isNull());
		QVERIFY(uasr.rcvdNotAccepted() == -1);
		QVERIFY(uasr.sntNotAccepted() == -1);
		QVERIFY(uasr.rcvdNotInRecMgmt() == -1);
		QVERIFY(uasr.sntNotInRecMgmt() == -1);
		QVERIFY(uasr.userAccountName().isNull());
	}

	{
		QString boxId(cBoxId);
		QString userId(cUserId);
		QDateTime time(cTime);
		int rcvdNotAccepted(cRcvdNotAccepted);
		int sntNotAccepted(cSntNotAccepted);
		int rcvdNotInRecMgmt(cRcvdNotInRecMgmt);
		int sntNotInRecMgmt(cSntNotInRecMgmt);
		QString userAccountName(cUserAccountName);

		RecMgmt::UploadAccountStatusReq uasr(boxId, userId, time,
		    rcvdNotAccepted, sntNotAccepted, rcvdNotInRecMgmt,
		    sntNotInRecMgmt, userAccountName);

		QVERIFY(!uasr.isNull());
		QVERIFY(uasr.isValid());

		QVERIFY(uasr.boxId() == cBoxId);
		QVERIFY(uasr.userId() == cUserId);
		QVERIFY(uasr.time() == cTime);
		QVERIFY(uasr.rcvdNotAccepted() == cRcvdNotAccepted);
		QVERIFY(uasr.sntNotAccepted() == cSntNotAccepted);
		QVERIFY(uasr.rcvdNotInRecMgmt() == cRcvdNotInRecMgmt);
		QVERIFY(uasr.sntNotInRecMgmt() == cSntNotInRecMgmt);
		QVERIFY(uasr.userAccountName() == cUserAccountName);

		QVERIFY(boxId == cBoxId);
		QVERIFY(userId == cUserId);
		QVERIFY(time == cTime);
		QVERIFY(rcvdNotAccepted == cRcvdNotAccepted);
		QVERIFY(sntNotAccepted == cSntNotAccepted);
		QVERIFY(rcvdNotInRecMgmt == cRcvdNotInRecMgmt);
		QVERIFY(sntNotInRecMgmt == cSntNotInRecMgmt);
		QVERIFY(userAccountName == cUserAccountName);
	}

#ifdef Q_COMPILER_RVALUE_REFS
	{
		QString boxId(cBoxId);
		QString userId(cUserId);
		QDateTime time(cTime);
		int rcvdNotAccepted(cRcvdNotAccepted);
		int sntNotAccepted(cSntNotAccepted);
		int rcvdNotInRecMgmt(cRcvdNotInRecMgmt);
		int sntNotInRecMgmt(cSntNotInRecMgmt);
		QString userAccountName(cUserAccountName);

		RecMgmt::UploadAccountStatusReq uasr(::std::move(boxId),
		    ::std::move(userId), ::std::move(time),
		    rcvdNotAccepted, sntNotAccepted, rcvdNotInRecMgmt,
		    sntNotInRecMgmt, ::std::move(userAccountName));

		QVERIFY(!uasr.isNull());
		QVERIFY(uasr.isValid());

		QVERIFY(uasr.boxId() == cBoxId);
		QVERIFY(uasr.userId() == cUserId);
		QVERIFY(uasr.time() == cTime);
		QVERIFY(uasr.rcvdNotAccepted() == cRcvdNotAccepted);
		QVERIFY(uasr.sntNotAccepted() == cSntNotAccepted);
		QVERIFY(uasr.rcvdNotInRecMgmt() == cRcvdNotInRecMgmt);
		QVERIFY(uasr.sntNotInRecMgmt() == cSntNotInRecMgmt);
		QVERIFY(uasr.userAccountName() == cUserAccountName);

		QVERIFY(boxId != cBoxId);
		QVERIFY(boxId.isNull());
		QVERIFY(userId != cUserId);
		QVERIFY(userId.isNull());
#  if (QT_VERSION >= QT_VERSION_CHECK(5, 8, 0))
		QVERIFY(time != cTime);
		QVERIFY(time.isNull());
#  endif /* >= Qt-5.8 */
		QVERIFY(rcvdNotAccepted == cRcvdNotAccepted);
		QVERIFY(sntNotAccepted == cSntNotAccepted);
		QVERIFY(rcvdNotInRecMgmt == cRcvdNotInRecMgmt);
		QVERIFY(sntNotInRecMgmt == cSntNotInRecMgmt);
		QVERIFY(userAccountName != cUserAccountName);
		QVERIFY(userAccountName.isNull());
	}
#endif /* Q_COMPILER_RVALUE_REFS */
}

void TestRecordsManagement::uploadAccountStatusReqCopy(void)
{
	RecMgmt::UploadAccountStatusReq uasr1;
	const QString boxId("box_id");
	const QString userId("user_id");
	const QDateTime time(QDate(2014, 1, 31), QTime(0, 0, 0, 0), Qt::UTC);
	const int rcvdNotAccepted(1);
	const int sntNotAccepted(2);
	const int rcvdNotInRecMgmt(3);
	const int sntNotInRecMgmt(4);
	const QString userAccountName("user_account_name");

	uasr1.setBoxId(boxId);
	uasr1.setUserId(userId);
	uasr1.setTime(time);
	uasr1.setRcvdNotAccepted(rcvdNotAccepted);
	uasr1.setSntNotAccepted(sntNotAccepted);
	uasr1.setRcvdNotInRecMgmt(rcvdNotInRecMgmt);
	uasr1.setSntNotInRecMgmt(sntNotInRecMgmt);
	uasr1.setUserAccountName(userAccountName);

	/* Constructor. */
	{
		RecMgmt::UploadAccountStatusReq uasr2(uasr1);

		QVERIFY(!uasr1.isNull());
		QVERIFY(!uasr2.isNull());
		QVERIFY(uasr1 == uasr2);

#ifdef Q_COMPILER_RVALUE_REFS
		/* Move. */
		RecMgmt::UploadAccountStatusReq uasr3(::std::move(uasr2));

		QVERIFY(uasr2.isNull());
		QVERIFY(uasr1 != uasr2);

		QVERIFY(!uasr1.isNull());
		QVERIFY(!uasr3.isNull());
		QVERIFY(uasr1 == uasr3);
#endif /* Q_COMPILER_RVALUE_REFS */
	}

	/* Assignment operator. */
	{
		RecMgmt::UploadAccountStatusReq uasr2;

		QVERIFY(uasr2.isNull());

		uasr2 = uasr1;

		QVERIFY(!uasr1.isNull());
		QVERIFY(!uasr2.isNull());
		QVERIFY(uasr1 == uasr2);

#ifdef Q_COMPILER_RVALUE_REFS
		/* Move. */
		RecMgmt::UploadAccountStatusReq uasr3;

		QVERIFY(uasr3.isNull());

		uasr3 = ::std::move(uasr2);

		QVERIFY(uasr2.isNull());
		QVERIFY(uasr1 != uasr2);

		QVERIFY(!uasr1.isNull());
		QVERIFY(!uasr3.isNull());
		QVERIFY(uasr1 == uasr3);
#endif /* Q_COMPILER_RVALUE_REFS */
	}
}

void TestRecordsManagement::uploadAccountStatusReqValues(void)
{
	const QString cBoxId("box_id");
	const QString cUserId("user_id");
	const QDateTime cTime(QDate(2014, 1, 31), QTime(0, 0, 0, 0), Qt::UTC);
	const int cRcvdNotAccepted(1);
	const int cSntNotAccepted(2);
	const int cRcvdNotInRecMgmt(3);
	const int cSntNotInRecMgmt(4);
	const QString cUserAccountName("user_account_name");

	RecMgmt::UploadAccountStatusReq uasr;
	QString boxId(cBoxId);
	QString userId(cUserId);
	QDateTime time(cTime);
	int rcvdNotAccepted(cRcvdNotAccepted);
	int sntNotAccepted(cSntNotAccepted);
	int rcvdNotInRecMgmt(cRcvdNotInRecMgmt);
	int sntNotInRecMgmt(cSntNotInRecMgmt);
	QString userAccountName(cUserAccountName);

	QVERIFY(uasr.boxId().isNull());
	uasr.setBoxId(boxId);
	QVERIFY(uasr.boxId() == cBoxId);
	QVERIFY(boxId == cBoxId);
#ifdef Q_COMPILER_RVALUE_REFS
	uasr.setBoxId("other_box_id");
	QVERIFY(uasr.boxId() != cBoxId);
	uasr.setBoxId(::std::move(boxId));
	QVERIFY(uasr.boxId() == cBoxId);
	QVERIFY(boxId != cBoxId);
#endif /* Q_COMPILER_RVALUE_REFS */

	QVERIFY(uasr.userId().isNull());
	uasr.setUserId(userId);
	QVERIFY(uasr.userId() == cUserId);
	QVERIFY(userId == cUserId);
#ifdef Q_COMPILER_RVALUE_REFS
	uasr.setUserId("other_user_id");
	QVERIFY(uasr.userId() != cUserId);
	uasr.setUserId(::std::move(userId));
	QVERIFY(uasr.userId() == cUserId);
	QVERIFY(userId != cUserId);
#endif /* Q_COMPILER_RVALUE_REFS */

	QVERIFY(uasr.time().isNull());
	uasr.setTime(time);
	QVERIFY(uasr.time() == cTime);
	QVERIFY(time == cTime);
#ifdef Q_COMPILER_RVALUE_REFS
	uasr.setTime(QDateTime(QDate(2014, 2, 1), QTime(0, 0, 0, 0), Qt::UTC));
	QVERIFY(uasr.time() != cTime);
	uasr.setTime(::std::move(time));
	QVERIFY(uasr.time() == cTime);
#  if (QT_VERSION >= QT_VERSION_CHECK(5, 8, 0))
	QVERIFY(time != cTime);
#  endif /* >= Qt-5.8 */
#endif /* Q_COMPILER_RVALUE_REFS */

	QVERIFY(uasr.rcvdNotAccepted() == -1);
	uasr.setRcvdNotAccepted(rcvdNotAccepted);
	QVERIFY(uasr.rcvdNotAccepted() == cRcvdNotAccepted);
	QVERIFY(rcvdNotAccepted == cRcvdNotAccepted);

	QVERIFY(uasr.sntNotAccepted() == -1);
	uasr.setSntNotAccepted(sntNotAccepted);
	QVERIFY(uasr.sntNotAccepted() == cSntNotAccepted);
	QVERIFY(sntNotAccepted == cSntNotAccepted);

	QVERIFY(uasr.rcvdNotInRecMgmt() == -1);
	uasr.setRcvdNotInRecMgmt(rcvdNotInRecMgmt);
	QVERIFY(uasr.rcvdNotInRecMgmt() == cRcvdNotInRecMgmt);
	QVERIFY(rcvdNotInRecMgmt == cRcvdNotInRecMgmt);

	QVERIFY(uasr.sntNotInRecMgmt() == -1);
	uasr.setSntNotInRecMgmt(sntNotInRecMgmt);
	QVERIFY(uasr.sntNotInRecMgmt() == cSntNotInRecMgmt);
	QVERIFY(sntNotInRecMgmt == cSntNotInRecMgmt);

	QVERIFY(uasr.userAccountName().isNull());
	uasr.setUserAccountName(userAccountName);
	QVERIFY(uasr.userAccountName() == cUserAccountName);
	QVERIFY(userAccountName == cUserAccountName);
#ifdef Q_COMPILER_RVALUE_REFS
	uasr.setUserAccountName("other_user_account_name");
	QVERIFY(uasr.userAccountName() != cUserAccountName);
	uasr.setUserAccountName(::std::move(userAccountName));
	QVERIFY(uasr.userAccountName() == cUserAccountName);
	QVERIFY(userAccountName != cUserAccountName);
#endif /* Q_COMPILER_RVALUE_REFS */
}

static
QDateTime currentTimeWithoutMsec(void)
{
	QDateTime dateTime = QDateTime::currentDateTime();
	QTime time = dateTime.time();
	if (time.msec() > 0) {
		/* Subtract the milliseconds. */
		time = time.addMSecs(- time.msec());
		dateTime.setTime(time);
	}
	return dateTime;
}

void TestRecordsManagement::uploadAccountStatusReqJsonConversion(void)
{
	RecMgmt::UploadAccountStatusReq uasr1, uasr2;
	const QString boxId("box_id");
	const QString userId("user_id");
	const QDateTime time(currentTimeWithoutMsec());
	const int rcvdNotAccepted(1);
	const int sntNotAccepted(2);
	const int rcvdNotInRecMgmt(3);
	const int sntNotInRecMgmt(4);
	const QString userAccountName("user_account_name");

	bool iOk = false;
	QByteArray jsonData;
	QJsonValue jsonVal;

	QVERIFY(uasr1.boxId().isNull());
	QVERIFY(uasr1.userId().isNull());
	QVERIFY(uasr1.time().isNull());
	QVERIFY(uasr1.rcvdNotAccepted() == -1);
	QVERIFY(uasr1.sntNotAccepted() == -1);
	QVERIFY(uasr1.rcvdNotInRecMgmt() == -1);
	QVERIFY(uasr1.sntNotInRecMgmt() == -1);
	QVERIFY(uasr1.userAccountName().isNull());

	uasr1.setBoxId(boxId);
	uasr1.setUserId(userId);
	uasr1.setTime(time);
	uasr1.setRcvdNotAccepted(rcvdNotAccepted);
	uasr1.setSntNotAccepted(sntNotAccepted);
	uasr1.setRcvdNotInRecMgmt(rcvdNotInRecMgmt);
	uasr1.setSntNotInRecMgmt(sntNotInRecMgmt);
	uasr1.setUserAccountName(userAccountName);

	QVERIFY(!uasr1.isNull());
	QVERIFY(uasr2.isNull());
	QVERIFY(uasr1 != uasr2);

	/* Empty data cause error. */
	iOk = true;
	uasr2 = RecMgmt::UploadAccountStatusReq::fromJson(QByteArray(), &iOk);
	QVERIFY(iOk == false);
	QVERIFY(uasr2.isNull());

	/* Null value causes error. */
	iOk = true;
	uasr2 = RecMgmt::UploadAccountStatusReq::fromJsonVal(QJsonValue(), &iOk);
	QVERIFY(iOk == false);
	QVERIFY(uasr2.isNull());

	/* Null object converts onto non-null value. */
	iOk = false;
	iOk = uasr2.toJsonVal(jsonVal);
	QVERIFY(iOk == true);
	QVERIFY(!jsonVal.isNull());

	jsonData = uasr1.toJsonData();
	QVERIFY(!jsonData.isEmpty());

	iOk = false;
	uasr2 = RecMgmt::UploadAccountStatusReq::fromJson(jsonData, &iOk);
	QVERIFY(iOk == true);
	QVERIFY(!uasr2.isNull());

	QVERIFY(!uasr1.isNull());
	QVERIFY(!uasr2.isNull());
	QVERIFY(uasr1 == uasr2);
}

void TestRecordsManagement::uploadAccountStatusResp(void)
{
	RecMgmt::UploadAccountStatusResp uasr1, uasr2;
	const RecMgmt::ErrorEntry error(
	    RecMgmt::ErrorEntry::ERR_MALFORMED_REQUEST, "description");

	/* Must be null. */
	QVERIFY(uasr1.error().isNull());
	QVERIFY(uasr2.error().isNull());

	QVERIFY(uasr1.isNull());
	QVERIFY(uasr2.isNull());
	QVERIFY(uasr1 == uasr2);

	/* Check whether values are not cross-linked. */
	uasr1.setError(error);

	QVERIFY(uasr1.error() == error);

	QVERIFY(!uasr1.isNull());
	QVERIFY(uasr2.isNull());
	QVERIFY(uasr1 != uasr2);

	/* Check value copying. */
	uasr2 = uasr1;

	QVERIFY(uasr2.error() == error);

	QVERIFY(!uasr1.isNull());
	QVERIFY(!uasr2.isNull());
	QVERIFY(uasr1 == uasr2);

	/* Clear value. */
	uasr1 = RecMgmt::UploadAccountStatusResp();

	QVERIFY(uasr1.error().isNull());

	QVERIFY(uasr1.isNull());
	QVERIFY(!uasr2.isNull());
	QVERIFY(uasr1 != uasr2);
}

void TestRecordsManagement::uploadAccountStatusRespCompare(void)
{
	RecMgmt::UploadAccountStatusResp uasr1, uasr2;
	const RecMgmt::ErrorEntry error(
	    RecMgmt::ErrorEntry::ERR_MALFORMED_REQUEST, "description");

	uasr1.setError(error);
	uasr2.setError(error);

	QVERIFY(uasr1 == uasr2);

	uasr1.setError(RecMgmt::ErrorEntry(
	    RecMgmt::ErrorEntry::ERR_MISSING_IDENTIFIER, "other_description"));
	QVERIFY(uasr1 != uasr2);
	uasr1.setError(error);
	QVERIFY(uasr1 == uasr2);
}

void TestRecordsManagement::uploadAccountStatusRespConstructor(void)
{
	const RecMgmt::ErrorEntry cError(
	    RecMgmt::ErrorEntry::ERR_MALFORMED_REQUEST, "description");

	{
		RecMgmt::UploadAccountStatusResp uasr;

		QVERIFY(uasr.isNull());
		QVERIFY(uasr.isValid());

		QVERIFY(uasr.error().isNull());
	}

	{
		RecMgmt::ErrorEntry error(cError);

		RecMgmt::UploadAccountStatusResp uasr(error);

		QVERIFY(!uasr.isNull());
		QVERIFY(uasr.isValid());

		QVERIFY(uasr.error() == cError);

		QVERIFY(error == cError);
	}

#ifdef Q_COMPILER_RVALUE_REFS
	{
		RecMgmt::ErrorEntry error(cError);

		RecMgmt::UploadAccountStatusResp uasr(::std::move(error));

		QVERIFY(!uasr.isNull());
		QVERIFY(uasr.isValid());

		QVERIFY(uasr.error() == cError);

		QVERIFY(error != cError);
		QVERIFY(error.isNull());
	}
#endif /* Q_COMPILER_RVALUE_REFS */
}

void TestRecordsManagement::uploadAccountStatusRespCopy(void)
{
	RecMgmt::UploadAccountStatusResp uasr1;
	const RecMgmt::ErrorEntry error(
	    RecMgmt::ErrorEntry::ERR_MALFORMED_REQUEST, "description");

	uasr1.setError(error);

	/* Constructor. */
	{
		RecMgmt::UploadAccountStatusResp uasr2(uasr1);

		QVERIFY(!uasr1.isNull());
		QVERIFY(!uasr2.isNull());
		QVERIFY(uasr1 == uasr2);

#ifdef Q_COMPILER_RVALUE_REFS
		/* Move. */
		RecMgmt::UploadAccountStatusResp uasr3(::std::move(uasr2));

		QVERIFY(uasr2.isNull());
		QVERIFY(uasr1 != uasr2);

		QVERIFY(!uasr1.isNull());
		QVERIFY(!uasr3.isNull());
		QVERIFY(uasr1 == uasr3);
#endif /* Q_COMPILER_RVALUE_REFS */
	}

	/* Assignment operator. */
	{
		RecMgmt::UploadAccountStatusResp uasr2;

		QVERIFY(uasr2.isNull());

		uasr2 = uasr1;

		QVERIFY(!uasr1.isNull());
		QVERIFY(!uasr2.isNull());
		QVERIFY(uasr1 == uasr2);

#ifdef Q_COMPILER_RVALUE_REFS
		/* Move. */
		RecMgmt::UploadAccountStatusResp uasr3;

		QVERIFY(uasr3.isNull());

		uasr3 = ::std::move(uasr2);

		QVERIFY(uasr2.isNull());
		QVERIFY(uasr1 != uasr2);

		QVERIFY(!uasr1.isNull());
		QVERIFY(!uasr3.isNull());
		QVERIFY(uasr1 == uasr3);
#endif /* Q_COMPILER_RVALUE_REFS */
	}
}

void TestRecordsManagement::uploadAccountStatusRespValues(void)
{
	const RecMgmt::ErrorEntry cError(
	    RecMgmt::ErrorEntry::ERR_MALFORMED_REQUEST, "description");

	RecMgmt::UploadAccountStatusResp uasr;
	RecMgmt::ErrorEntry error(cError);

	QVERIFY(uasr.error().isNull());
	uasr.setError(error);
	QVERIFY(uasr.error() == cError);
	QVERIFY(error == cError);
#ifdef Q_COMPILER_RVALUE_REFS
	uasr.setError(RecMgmt::ErrorEntry(
	    RecMgmt::ErrorEntry::ERR_MISSING_IDENTIFIER, "other_description"));
	QVERIFY(uasr.error() != cError);
	uasr.setError(::std::move(error));
	QVERIFY(uasr.error() == cError);
	QVERIFY(error != cError);
#endif /* Q_COMPILER_RVALUE_REFS */
}

void TestRecordsManagement::uploadAccountStatusRespJsonConversion(void)
{
	RecMgmt::UploadAccountStatusResp uasr1, uasr2;
	const RecMgmt::ErrorEntry error(
	    RecMgmt::ErrorEntry::ERR_MALFORMED_REQUEST, "description");

	bool iOk = false;
	QByteArray jsonData;
	QJsonValue jsonVal;

	QVERIFY(uasr1.error().isNull());
	QVERIFY(uasr2.error().isNull());

	uasr1.setError(error);

	QVERIFY(!uasr1.isNull());
	QVERIFY(uasr2.isNull());
	QVERIFY(uasr1 != uasr2);

	/* Empty data cause error. */
	iOk = true;
	uasr2 = RecMgmt::UploadAccountStatusResp::fromJson(QByteArray(), &iOk);
	QVERIFY(iOk == false);
	QVERIFY(uasr2.isNull());

	/* Null value causes error. */
	iOk = true;
	uasr2 = RecMgmt::UploadAccountStatusResp::fromJsonVal(QJsonValue(), &iOk);
	QVERIFY(iOk == false);
	QVERIFY(uasr2.isNull());

	/* Null object converts onto non-null value. */
	iOk = false;
	iOk = uasr2.toJsonVal(jsonVal);
	QVERIFY(iOk == true);
	QVERIFY(!jsonVal.isNull());

	jsonData = uasr1.toJsonData();
	QVERIFY(!jsonData.isEmpty());

	iOk = false;
	uasr2 = RecMgmt::UploadAccountStatusResp::fromJson(jsonData, &iOk);
	QVERIFY(iOk == true);
	QVERIFY(!uasr2.isNull());

	QVERIFY(!uasr1.isNull());
	QVERIFY(!uasr2.isNull());
	QVERIFY(uasr1 == uasr2);
}

void TestRecordsManagement::uploadFileReq(void)
{
	RecMgmt::UploadFileReq ufr1, ufr2;
	const QStringList ids({"aa", "ab"});
	const QString fileName("file_name");
	const QByteArray fileContent("file_content");

	/* Must be null. */
	QVERIFY(ufr1.ids().isEmpty());
	QVERIFY(ufr1.fileName().isNull());
	QVERIFY(ufr1.fileContent().isNull());
	QVERIFY(ufr2.ids().isEmpty());
	QVERIFY(ufr2.fileName().isNull());
	QVERIFY(ufr2.fileContent().isNull());

	QVERIFY(ufr1.isNull());
	QVERIFY(ufr2.isNull());
	QVERIFY(ufr1 == ufr2);

	/* Check whether values are not cross-linked. */
	ufr1.setIds(ids);
	ufr1.setFileName(fileName);
	ufr1.setFileContent(fileContent);

	QVERIFY(ufr1.ids() == ids);
	QVERIFY(ufr1.fileName() == fileName);
	QVERIFY(ufr1.fileContent() == fileContent);

	QVERIFY(!ufr1.isNull());
	QVERIFY(ufr2.isNull());
	QVERIFY(ufr1 != ufr2);

	/* Check value copying. */
	ufr2 = ufr1;

	QVERIFY(ufr2.ids() == ids);
	QVERIFY(ufr2.fileName() == fileName);
	QVERIFY(ufr2.fileContent() == fileContent);

	QVERIFY(!ufr1.isNull());
	QVERIFY(!ufr2.isNull());
	QVERIFY(ufr1 == ufr2);

	/* Clear value. */
	ufr1 = RecMgmt::UploadFileReq();

	QVERIFY(ufr1.ids().isEmpty());
	QVERIFY(ufr1.fileName().isNull());
	QVERIFY(ufr1.fileContent().isNull());

	QVERIFY(ufr1.isNull());
	QVERIFY(!ufr2.isNull());
	QVERIFY(ufr1 != ufr2);
}

void TestRecordsManagement::uploadFileReqCompare(void)
{
	RecMgmt::UploadFileReq ufr1, ufr2;
	const QStringList ids({"aa", "ab"});
	const QString fileName("file_name");
	const QByteArray fileContent("file_content");

	ufr1.setIds(ids);
	ufr1.setFileName(fileName);
	ufr1.setFileContent(fileContent);
	ufr2.setIds(ids);
	ufr2.setFileName(fileName);
	ufr2.setFileContent(fileContent);

	QVERIFY(ufr1 == ufr2);

	ufr1.setIds(QStringList({"ba", "bb"}));
	QVERIFY(ufr1 != ufr2);
	ufr1.setIds(ids);
	QVERIFY(ufr1 == ufr2);

	ufr1.setFileName("other_file_name");
	QVERIFY(ufr1 != ufr2);
	ufr1.setFileName(fileName);
	QVERIFY(ufr1 == ufr2);

	ufr1.setFileContent("other_file_content");
	QVERIFY(ufr1 != ufr2);
	ufr1.setFileContent(fileContent);
	QVERIFY(ufr1 == ufr2);
}

void TestRecordsManagement::uploadFileReqConstructor(void)
{
	const QStringList cIds({"aa", "ab"});
	const QString cFileName("file_name");
	const QByteArray cFileContent("file_content");

	{
		RecMgmt::UploadFileReq ufr;

		QVERIFY(ufr.isNull());
		QVERIFY(!ufr.isValid());

		QVERIFY(ufr.ids().isEmpty());
		QVERIFY(ufr.fileName().isNull());
		QVERIFY(ufr.fileContent().isNull());
	}

	{
		QStringList ids(cIds);
		QString fileName(cFileName);
		QByteArray fileContent(cFileContent);

		RecMgmt::UploadFileReq ufr(ids, fileName, fileContent);

		QVERIFY(!ufr.isNull());
		QVERIFY(ufr.isValid());

		QVERIFY(ufr.ids() == cIds);
		QVERIFY(ufr.fileName() == cFileName);
		QVERIFY(ufr.fileContent() == cFileContent);

		QVERIFY(ids == cIds);
		QVERIFY(fileName == cFileName);
		QVERIFY(fileContent == cFileContent);
	}

#ifdef Q_COMPILER_RVALUE_REFS
	{
		QStringList ids(cIds);
		QString fileName(cFileName);
		QByteArray fileContent(cFileContent);

		RecMgmt::UploadFileReq ufr(::std::move(ids),
		    ::std::move(fileName), ::std::move(fileContent));

		QVERIFY(!ufr.isNull());
		QVERIFY(ufr.isValid());

		QVERIFY(ufr.ids() == cIds);
		QVERIFY(ufr.fileName() == cFileName);
		QVERIFY(ufr.fileContent() == cFileContent);

#  if (QT_VERSION >= QT_VERSION_CHECK(5, 4, 0))
		QVERIFY(ids != cIds);
		QVERIFY(ids.isEmpty());
#  endif /* >= Qt-5.4 */
		QVERIFY(fileName != cFileName);
		QVERIFY(fileName.isNull());
		QVERIFY(fileContent != cFileContent);
		QVERIFY(fileContent.isNull());
	}
#endif /* Q_COMPILER_RVALUE_REFS */
}

void TestRecordsManagement::uploadFileReqCopy(void)
{
	RecMgmt::UploadFileReq ufr1;
	const QStringList ids({"aa", "ab"});
	const QString fileName("file_name");
	const QByteArray fileContent("file_content");

	ufr1.setIds(ids);
	ufr1.setFileName(fileName);
	ufr1.setFileContent(fileContent);

	/* Constructor. */
	{
		RecMgmt::UploadFileReq ufr2(ufr1);

		QVERIFY(!ufr1.isNull());
		QVERIFY(!ufr2.isNull());
		QVERIFY(ufr1 == ufr2);

#ifdef Q_COMPILER_RVALUE_REFS
		/* Move. */
		RecMgmt::UploadFileReq ufr3(::std::move(ufr2));

		QVERIFY(ufr2.isNull());
		QVERIFY(ufr1 != ufr2);

		QVERIFY(!ufr1.isNull());
		QVERIFY(!ufr3.isNull());
		QVERIFY(ufr1 == ufr3);
#endif /* Q_COMPILER_RVALUE_REFS */
	}

	/* Assignment operator. */
	{
		RecMgmt::UploadFileReq ufr2;

		QVERIFY(ufr2.isNull());

		ufr2 = ufr1;

		QVERIFY(!ufr1.isNull());
		QVERIFY(!ufr2.isNull());
		QVERIFY(ufr1 == ufr2);

#ifdef Q_COMPILER_RVALUE_REFS
		/* Move. */
		RecMgmt::UploadFileReq ufr3;

		QVERIFY(ufr3.isNull());

		ufr3 = ::std::move(ufr2);

		QVERIFY(ufr2.isNull());
		QVERIFY(ufr1 != ufr2);

		QVERIFY(!ufr1.isNull());
		QVERIFY(!ufr3.isNull());
		QVERIFY(ufr1 == ufr3);
#endif /* Q_COMPILER_RVALUE_REFS */
	}
}

void TestRecordsManagement::uploadFileReqValues(void)
{
	const QStringList cIds({"aa", "ab"});
	const QString cFileName("file_name");
	const QByteArray cFileContent("file_content");

	RecMgmt::UploadFileReq ufr;
	QStringList ids(cIds);
	QString fileName(cFileName);
	QByteArray fileContent(cFileContent);

	QVERIFY(ufr.ids().isEmpty());
	ufr.setIds(ids);
	QVERIFY(ufr.ids() == cIds);
	QVERIFY(ids == cIds);
#ifdef Q_COMPILER_RVALUE_REFS
	ufr.setIds(QStringList({"ba", "bb"}));
	QVERIFY(ufr.ids() != cIds);
	ufr.setIds(::std::move(ids));
	QVERIFY(ufr.ids() == cIds);
#  if (QT_VERSION >= QT_VERSION_CHECK(5, 4, 0))
	QVERIFY(ids != cIds);
#  endif /* >= Qt-5.4 */
#endif /* Q_COMPILER_RVALUE_REFS */

	QVERIFY(ufr.fileName().isNull());
	ufr.setFileName(fileName);
	QVERIFY(ufr.fileName() == cFileName);
	QVERIFY(fileName == cFileName);
#ifdef Q_COMPILER_RVALUE_REFS
	ufr.setFileName("other_file_name");
	QVERIFY(ufr.fileName() != cFileName);
	ufr.setFileName(::std::move(fileName));
	QVERIFY(ufr.fileName() == cFileName);
	QVERIFY(fileName != cFileName);
#endif /* Q_COMPILER_RVALUE_REFS */

	QVERIFY(ufr.fileContent().isNull());
	ufr.setFileContent(fileContent);
	QVERIFY(ufr.fileContent() == cFileContent);
	QVERIFY(fileContent == cFileContent);
#ifdef Q_COMPILER_RVALUE_REFS
	ufr.setFileContent("other_file_content");
	QVERIFY(ufr.fileContent() != cFileContent);
	ufr.setFileContent(::std::move(fileContent));
	QVERIFY(ufr.fileContent() == cFileContent);
	QVERIFY(fileContent != cFileContent);
#endif /* Q_COMPILER_RVALUE_REFS */
}

void TestRecordsManagement::uploadFileReqJsonConversion(void)
{
	RecMgmt::UploadFileReq ufr1, ufr2;
	const QStringList ids({"aa", "ab"});
	const QString fileName("file_name");
	const QByteArray fileContent("file_content");

	bool iOk = false;
	QByteArray jsonData;
	QJsonValue jsonVal;

	QVERIFY(ufr1.ids().isEmpty());
	QVERIFY(ufr1.fileName().isNull());
	QVERIFY(ufr1.fileContent().isNull());

	ufr1.setIds(ids);
	ufr1.setFileName(fileName);
	ufr1.setFileContent(fileContent);

	QVERIFY(ufr1.ids() == ids);
	QVERIFY(ufr1.fileName() == fileName);
	QVERIFY(ufr1.fileContent() == fileContent);

	QVERIFY(!ufr1.isNull());
	QVERIFY(ufr2.isNull());
	QVERIFY(ufr1 != ufr2);

	/* Empty data cause error. */
	iOk = true;
	ufr2 = RecMgmt::UploadFileReq::fromJson(QByteArray(), &iOk);
	QVERIFY(iOk == false);
	QVERIFY(ufr2.isNull());

	/* Null value causes error. */
	iOk = true;
	ufr2 = RecMgmt::UploadFileReq::fromJsonVal(QJsonValue(), &iOk);
	QVERIFY(iOk == false);
	QVERIFY(ufr2.isNull());

	/* Null object converts onto non-null value. */
	iOk = false;
	iOk = ufr2.toJsonVal(jsonVal);
	QVERIFY(iOk == true);
	QVERIFY(!jsonVal.isNull());

	jsonData = ufr1.toJsonData();
	QVERIFY(!jsonData.isEmpty());

	iOk = false;
	ufr2 = RecMgmt::UploadFileReq::fromJson(jsonData, &iOk);
	QVERIFY(iOk == true);
	QVERIFY(!ufr2.isNull());

	QVERIFY(!ufr1.isNull());
	QVERIFY(!ufr2.isNull());
	QVERIFY(ufr1 == ufr2);
}

void TestRecordsManagement::uploadFileResp(void)
{
	RecMgmt::UploadFileResp ufr1, ufr2;
	const QString id("id");
	const RecMgmt:: ErrorEntry error(
	    RecMgmt::ErrorEntry::ERR_MALFORMED_REQUEST, "description");
	const QStringList locations({"location1, location2"});

	/* Must be null. */
	QVERIFY(ufr1.id().isNull());
	QVERIFY(ufr1.error().isNull());
	QVERIFY(ufr1.locations().isEmpty());
	QVERIFY(ufr2.id().isNull());
	QVERIFY(ufr2.error().isNull());
	QVERIFY(ufr2.locations().isEmpty());

	QVERIFY(ufr1.isNull());
	QVERIFY(ufr2.isNull());
	QVERIFY(ufr1 == ufr2);

	/* Check whether values are not cross-linked. */
	ufr1.setId(id);
	ufr1.setError(error);
	ufr1.setLocations(locations);

	QVERIFY(ufr1.id() == id);
	QVERIFY(ufr1.error() == error);
	QVERIFY(ufr1.locations() == locations);

	QVERIFY(!ufr1.isNull());
	QVERIFY(ufr2.isNull());
	QVERIFY(ufr1 != ufr2);

	/* Check value copying. */
	ufr2 = ufr1;

	QVERIFY(ufr2.id() == id);
	QVERIFY(ufr2.error() == error);
	QVERIFY(ufr2.locations() == locations);

	QVERIFY(!ufr1.isNull());
	QVERIFY(!ufr2.isNull());
	QVERIFY(ufr1 == ufr2);

	/* Clear value. */
	ufr1 = RecMgmt::UploadFileResp();

	QVERIFY(ufr1.id().isNull());
	QVERIFY(ufr1.error().isNull());
	QVERIFY(ufr1.locations().isEmpty());

	QVERIFY(ufr1.isNull());
	QVERIFY(!ufr2.isNull());
	QVERIFY(ufr1 != ufr2);
}

void TestRecordsManagement::uploadFileRespCompare(void)
{
	RecMgmt::UploadFileResp ufr1, ufr2;
	const QString id("id");
	const RecMgmt:: ErrorEntry error(
	    RecMgmt::ErrorEntry::ERR_MALFORMED_REQUEST, "description");
	const QStringList locations({"location1, location2"});

	ufr1.setId(id);
	ufr1.setError(error);
	ufr1.setLocations(locations);
	ufr2.setId(id);
	ufr2.setError(error);
	ufr2.setLocations(locations);

	QVERIFY(ufr1 == ufr2);

	ufr1.setId("other_id");
	QVERIFY(ufr1 != ufr2);
	ufr1.setId(id);
	QVERIFY(ufr1 == ufr2);

	ufr1.setError(RecMgmt::ErrorEntry(
	    RecMgmt::ErrorEntry::ERR_MISSING_IDENTIFIER, "other_description"));
	QVERIFY(ufr1 != ufr2);
	ufr1.setError(error);
	QVERIFY(ufr1 == ufr2);

	ufr1.setLocations(QStringList({"location3, location4"}));
	QVERIFY(ufr1 != ufr2);
	ufr1.setLocations(locations);
	QVERIFY(ufr1 == ufr2);
}

void TestRecordsManagement::uploadFileRespConstructor(void)
{
	const QString cId("id");
	const RecMgmt:: ErrorEntry cError(
	    RecMgmt::ErrorEntry::ERR_MALFORMED_REQUEST, "description");
	const QStringList cLocations({"location1, location2"});

	{
		RecMgmt::UploadFileResp ufr;

		QVERIFY(ufr.isNull());
		QVERIFY(!ufr.isValid());

		QVERIFY(ufr.id().isNull());
		QVERIFY(ufr.error().isNull());
		QVERIFY(ufr.locations().isEmpty());
	}

	{
		QString id(cId);
		RecMgmt:: ErrorEntry error(cError);
		QStringList locations(cLocations);

		RecMgmt::UploadFileResp ufr(id, error, locations);

		QVERIFY(!ufr.isNull());
		QVERIFY(ufr.isValid());

		QVERIFY(ufr.id() == cId);
		QVERIFY(ufr.error() == cError);
		QVERIFY(ufr.locations() == cLocations);

		QVERIFY(id == cId);
		QVERIFY(error == cError);
		QVERIFY(locations == cLocations);
	}

#ifdef Q_COMPILER_RVALUE_REFS
	{
		QString id(cId);
		RecMgmt:: ErrorEntry error(cError);
		QStringList locations(cLocations);

		RecMgmt::UploadFileResp ufr(::std::move(id),
		    ::std::move(error), ::std::move(locations));

		QVERIFY(!ufr.isNull());
		QVERIFY(ufr.isValid());

		QVERIFY(ufr.id() == cId);
		QVERIFY(ufr.error() == cError);
		QVERIFY(ufr.locations() == cLocations);

		QVERIFY(id != cId);
		QVERIFY(id.isNull());
		QVERIFY(error != cError);
		QVERIFY(error.isNull());
#  if (QT_VERSION >= QT_VERSION_CHECK(5, 4, 0))
		QVERIFY(locations != cLocations);
		QVERIFY(locations.isEmpty());
#  endif /* >= Qt-5.4 */
	}
#endif /* Q_COMPILER_RVALUE_REFS */
}

void TestRecordsManagement::uploadFileRespCopy(void)
{
	RecMgmt::UploadFileResp ufr1;
	const QString id("id");
	const RecMgmt:: ErrorEntry error(
	    RecMgmt::ErrorEntry::ERR_MALFORMED_REQUEST, "description");
	const QStringList locations({"location1, location2"});

	ufr1.setId(id);
	ufr1.setError(error);
	ufr1.setLocations(locations);

	/* Constructor. */
	{
		RecMgmt::UploadFileResp ufr2(ufr1);

		QVERIFY(!ufr1.isNull());
		QVERIFY(!ufr2.isNull());
		QVERIFY(ufr1 == ufr2);

#ifdef Q_COMPILER_RVALUE_REFS
		/* Move. */
		RecMgmt::UploadFileResp ufr3(::std::move(ufr2));

		QVERIFY(ufr2.isNull());
		QVERIFY(ufr1 != ufr2);

		QVERIFY(!ufr1.isNull());
		QVERIFY(!ufr3.isNull());
		QVERIFY(ufr1 == ufr3);
#endif /* Q_COMPILER_RVALUE_REFS */
	}

	/* Assignment operator. */
	{
		RecMgmt::UploadFileResp ufr2;

		QVERIFY(ufr2.isNull());

		ufr2 = ufr1;

		QVERIFY(!ufr1.isNull());
		QVERIFY(!ufr2.isNull());
		QVERIFY(ufr1 == ufr2);

#ifdef Q_COMPILER_RVALUE_REFS
		/* Move. */
		RecMgmt::UploadFileResp ufr3;

		QVERIFY(ufr3.isNull());

		ufr3 = ::std::move(ufr2);

		QVERIFY(ufr2.isNull());
		QVERIFY(ufr1 != ufr2);

		QVERIFY(!ufr1.isNull());
		QVERIFY(!ufr3.isNull());
		QVERIFY(ufr1 == ufr3);
#endif /* Q_COMPILER_RVALUE_REFS */
	}
}

void TestRecordsManagement::uploadFileRespValues(void)
{
	const QString cId("id");
	const RecMgmt:: ErrorEntry cError(
	    RecMgmt::ErrorEntry::ERR_MALFORMED_REQUEST, "description");
	const QStringList cLocations({"location1, location2"});

	RecMgmt::UploadFileResp ufr;
	QString id(cId);
	RecMgmt:: ErrorEntry error(cError);
	QStringList locations(cLocations);

	QVERIFY(ufr.id().isNull());
	ufr.setId(id);
	QVERIFY(ufr.id() == cId);
	QVERIFY(id == cId);
#ifdef Q_COMPILER_RVALUE_REFS
	ufr.setId("other_id");
	QVERIFY(ufr.id() != cId);
	ufr.setId(::std::move(id));
	QVERIFY(ufr.id() == cId);
	QVERIFY(id != cId);
#endif /* Q_COMPILER_RVALUE_REFS */

	QVERIFY(ufr.error().isNull());
	ufr.setError(error);
	QVERIFY(ufr.error() == cError);
	QVERIFY(error == cError);
#ifdef Q_COMPILER_RVALUE_REFS
	ufr.setError(RecMgmt::ErrorEntry(
	    RecMgmt::ErrorEntry::ERR_MISSING_IDENTIFIER, "other_description"));
	QVERIFY(ufr.error() != cError);
	ufr.setError(::std::move(error));
	QVERIFY(ufr.error() == cError);
	QVERIFY(error != cError);
#endif /* Q_COMPILER_RVALUE_REFS */

	QVERIFY(ufr.locations().isEmpty());
	ufr.setLocations(locations);
	QVERIFY(ufr.locations() == cLocations);
	QVERIFY(locations == cLocations);
#ifdef Q_COMPILER_RVALUE_REFS
	ufr.setLocations(QStringList({"location3, location4"}));
	QVERIFY(ufr.locations() != cLocations);
	ufr.setLocations(::std::move(locations));
	QVERIFY(ufr.locations() == cLocations);
#  if (QT_VERSION >= QT_VERSION_CHECK(5, 4, 0))
	QVERIFY(locations != cLocations);
#  endif /* >= Qt-5.4 */
#endif /* Q_COMPILER_RVALUE_REFS */
}

void TestRecordsManagement::uploadFileRespJsonConversion(void)
{
	RecMgmt::UploadFileResp ufr1, ufr2;
	const QString id("id");
	const RecMgmt:: ErrorEntry error(
	    RecMgmt::ErrorEntry::ERR_MALFORMED_REQUEST, "description");
	const QStringList locations({"location1, location2"});

	bool iOk = false;
	QByteArray jsonData;
	QJsonValue jsonVal;

	QVERIFY(ufr1.id().isNull());
	QVERIFY(ufr1.error().isNull());
	QVERIFY(ufr1.locations().isEmpty());

	ufr1.setId(id);
	ufr1.setError(error);
	ufr1.setLocations(locations);

	QVERIFY(ufr1.id() == id);
	QVERIFY(ufr1.error() == error);
	QVERIFY(ufr1.locations() == locations);

	QVERIFY(!ufr1.isNull());
	QVERIFY(ufr2.isNull());
	QVERIFY(ufr1 != ufr2);

	/* Empty data cause error. */
	iOk = true;
	ufr2 = RecMgmt::UploadFileResp::fromJson(QByteArray(), &iOk);
	QVERIFY(iOk == false);
	QVERIFY(ufr2.isNull());

	/* Null value causes error. */
	iOk = true;
	ufr2 = RecMgmt::UploadFileResp::fromJsonVal(QJsonValue(), &iOk);
	QVERIFY(iOk == false);
	QVERIFY(ufr2.isNull());

	/* Null object converts onto non-null value. */
	iOk = false;
	iOk = ufr2.toJsonVal(jsonVal);
	QVERIFY(iOk == true);
	QVERIFY(!jsonVal.isNull());

	jsonData = ufr1.toJsonData();
	QVERIFY(!jsonData.isEmpty());

	iOk = false;
	ufr2 = RecMgmt::UploadFileResp::fromJson(jsonData, &iOk);
	QVERIFY(iOk == true);
	QVERIFY(!ufr2.isNull());

	QVERIFY(!ufr1.isNull());
	QVERIFY(!ufr2.isNull());
	QVERIFY(ufr1 == ufr2);
}

/*!
 * @brief Read whole file content.
 *
 * @param[in] fileName File path.
 */
static
QByteArray readFileData(const QString &fileName)
{
	if (Q_UNLIKELY(fileName.isEmpty())) {
		return QByteArray();
	}

	QFile file(fileName);
	if (!file.exists() || !file.open(QIODevice::ReadOnly)) {
		return QByteArray();
	}

	QByteArray data = file.readAll();
	file.close();

	return data;
}

void TestRecordsManagement::uploadHierarchyResp(void)
{
	RecMgmt::UploadHierarchyResp uhr1, uhr2;

	/* Must be null. */
	QVERIFY(uhr1.root() == Q_NULLPTR);
	QVERIFY(uhr2.root() == Q_NULLPTR);

	/* Check whether values are not cross-linked. */
	{
		const QByteArray jsonData = readFileData(
		    "data/records_management_upload_hierarchy_reply_001.json");
		QVERIFY(!jsonData.isEmpty());

		uhr1 = RecMgmt::UploadHierarchyResp::fromJson(jsonData);
	}

	QVERIFY(uhr1.root() != Q_NULLPTR);
	QVERIFY(uhr2.root() == Q_NULLPTR);

	/* Check value copying. */
	uhr2 = uhr1;

	QVERIFY(uhr1.root() != Q_NULLPTR);
	QVERIFY(uhr2.root() != Q_NULLPTR);
	QVERIFY(uhr1.root() != uhr2.root());

	/* Clear value. */
	uhr1 = RecMgmt::UploadHierarchyResp();

	QVERIFY(uhr1.root() == Q_NULLPTR);
	QVERIFY(uhr2.root() != Q_NULLPTR);
}

void TestRecordsManagement::uploadHierarchyRespConstructor(void)
{
	{
		RecMgmt::UploadHierarchyResp uhr;

		QVERIFY(!uhr.isValid());

		QVERIFY(uhr.root() == Q_NULLPTR);
	}
}

void TestRecordsManagement::uploadHierarchyRespCopy(void)
{
	RecMgmt::UploadHierarchyResp uhr1;

	{
		const QByteArray jsonData = readFileData(
		    "data/records_management_upload_hierarchy_reply_001.json");
		QVERIFY(!jsonData.isEmpty());

		uhr1 = RecMgmt::UploadHierarchyResp::fromJson(jsonData);
	}

	/* Constructor. */
	{
		RecMgmt::UploadHierarchyResp uhr2(uhr1);

		QVERIFY(uhr1.root() != Q_NULLPTR);
		QVERIFY(uhr2.root() != Q_NULLPTR);
		QVERIFY(uhr1.root() != uhr2.root());

#ifdef Q_COMPILER_RVALUE_REFS
		/* Move. */
		RecMgmt::UploadHierarchyResp uhr3(::std::move(uhr2));

		QVERIFY(uhr2.root() == Q_NULLPTR);

		QVERIFY(uhr1.root() != Q_NULLPTR);
		QVERIFY(uhr3.root() != Q_NULLPTR);
		QVERIFY(uhr1.root() != uhr3.root());
#endif /* Q_COMPILER_RVALUE_REFS */
	}

	/* Assignment operator. */
	{
		RecMgmt::UploadHierarchyResp uhr2;

		QVERIFY(uhr2.root() == Q_NULLPTR);

		uhr2 = uhr1;

		QVERIFY(uhr1.root() != Q_NULLPTR);
		QVERIFY(uhr2.root() != Q_NULLPTR);
		QVERIFY(uhr1.root() != uhr2.root());

#ifdef Q_COMPILER_RVALUE_REFS
		/* Move. */
		RecMgmt::UploadHierarchyResp uhr3;

		QVERIFY(uhr3.root() == Q_NULLPTR);

		uhr3 = ::std::move(uhr2);

		QVERIFY(uhr2.root() == Q_NULLPTR);

		QVERIFY(uhr1.root() != Q_NULLPTR);
		QVERIFY(uhr3.root() != Q_NULLPTR);
		QVERIFY(uhr1.root() != uhr3.root());
#endif /* Q_COMPILER_RVALUE_REFS */
	}
}

void TestRecordsManagement::uploadHierarchyRespJsonConversion(void)
{
	RecMgmt::UploadHierarchyResp uhr1, uhr2;

	bool iOk = false;
	QByteArray jsonData;
	QJsonValue jsonVal;

	QVERIFY(uhr1.root() == Q_NULLPTR);

	{
		const QByteArray jsonData = readFileData(
		    "data/records_management_upload_hierarchy_reply_001.json");
		QVERIFY(!jsonData.isEmpty());

		uhr1 = RecMgmt::UploadHierarchyResp::fromJson(jsonData);
	}

	QVERIFY(uhr1.root() != Q_NULLPTR);
	QVERIFY(uhr2.root() == Q_NULLPTR);

	/* Empty data cause error. */
	iOk = true;
	uhr2 = RecMgmt::UploadHierarchyResp::fromJson(QByteArray(), &iOk);
	QVERIFY(iOk == false);
	QVERIFY(uhr2.root() == Q_NULLPTR);

	/* Null value causes error. */
	iOk = true;
	uhr2 = RecMgmt::UploadHierarchyResp::fromJsonVal(QJsonValue(), &iOk);
	QVERIFY(iOk == false);
	QVERIFY(uhr2.root() == Q_NULLPTR);

	/* Null object converts onto non-null value. */
	iOk = false;
	iOk = uhr2.toJsonVal(jsonVal);
	QVERIFY(iOk == true);
	QVERIFY(!jsonVal.isNull());

	jsonData = uhr1.toJsonData();
	QVERIFY(!jsonData.isEmpty());

	iOk = false;
	uhr2 = RecMgmt::UploadHierarchyResp::fromJson(jsonData, &iOk);
	QVERIFY(iOk == true);
	QVERIFY(uhr2.root() != Q_NULLPTR);

	QVERIFY(uhr1.root() != Q_NULLPTR);
	QVERIFY(uhr2.root() != Q_NULLPTR);
	QVERIFY(uhr1.root() != uhr2.root());
}

void TestRecordsManagement::automaticUploadTarget(void)
{
	RecMgmt::AutomaticUploadTarget aut1, aut2;

	/* Must be null. */
	QVERIFY(aut1.isNull());
	QVERIFY(aut2.isNull());

	/* Check whether values are not cross-linked. */
	{
		QByteArray jsonData = readFileData(
		    "data/records_management_upload_hierarchy_reply_001.json");
		QVERIFY(!jsonData.isEmpty());

		RecMgmt::UploadHierarchyResp uhr =
		    RecMgmt::UploadHierarchyResp::fromJson(jsonData);
		QVERIFY(uhr.isValid());

		aut1 = RecMgmt::AutomaticUploadTarget::getUnambiguousTargets(uhr);
	}

	QVERIFY(!aut1.isNull());
	QVERIFY(aut2.isNull());

	/* Check value copying. */
	aut2 = aut1;

	QVERIFY(!aut1.isNull());
	QVERIFY(!aut2.isNull());

	/* Clear value. */
	aut1 = RecMgmt::AutomaticUploadTarget();

	QVERIFY(aut1.isNull());
	QVERIFY(!aut2.isNull());
}

void TestRecordsManagement::automaticUploadTargetConstructor(void)
{
	{
		RecMgmt::AutomaticUploadTarget aut;

		QVERIFY(aut.isNull());

		QVERIFY(aut.dumpCaseIdMapping().isEmpty());
		QVERIFY(aut.dumpCourtCaseIdMapping().isEmpty());
	}
}

void TestRecordsManagement::automaticUploadTargetCopy(void)
{
	RecMgmt::AutomaticUploadTarget aut1;

	{
		QByteArray jsonData = readFileData(
		    "data/records_management_upload_hierarchy_reply_001.json");
		QVERIFY(!jsonData.isEmpty());

		RecMgmt::UploadHierarchyResp uhr =
		    RecMgmt::UploadHierarchyResp::fromJson(jsonData);
		QVERIFY(uhr.isValid());

		aut1 = RecMgmt::AutomaticUploadTarget::getUnambiguousTargets(uhr);
	}

	/* Constructor. */
	{
		RecMgmt::AutomaticUploadTarget aut2(aut1);

		QVERIFY(!aut1.isNull());
		QVERIFY(!aut2.isNull());

#ifdef Q_COMPILER_RVALUE_REFS
		/* Move. */
		RecMgmt::AutomaticUploadTarget aut3(::std::move(aut2));

		QVERIFY(aut2.isNull());

		QVERIFY(!aut1.isNull());
		QVERIFY(!aut3.isNull());
#endif /* Q_COMPILER_RVALUE_REFS */
	}

	/* Assignment operator. */
	{
		RecMgmt::AutomaticUploadTarget aut2;

		QVERIFY(aut2.isNull());

		aut2 = aut1;

		QVERIFY(!aut1.isNull());
		QVERIFY(!aut2.isNull());

#ifdef Q_COMPILER_RVALUE_REFS
		/* Move. */
		RecMgmt::AutomaticUploadTarget aut3;

		QVERIFY(aut3.isNull());

		aut3 = ::std::move(aut2);

		QVERIFY(aut2.isNull());

		QVERIFY(!aut1.isNull());
		QVERIFY(!aut3.isNull());
#endif /* Q_COMPILER_RVALUE_REFS */
	}
}

void TestRecordsManagement::automaticUploadTargetInteraction(void)
{
	RecMgmt::AutomaticUploadTarget aut;
	{
		QByteArray json = readFileData(
		    "data/records_management_upload_hierarchy_reply.json");
		QVERIFY(!json.isEmpty());

		RecMgmt::UploadHierarchyResp uhr =
		    RecMgmt::UploadHierarchyResp::fromJson(json);
		QVERIFY(uhr.isValid());

		aut = RecMgmt::AutomaticUploadTarget::getUnambiguousTargets(uhr);
		QVERIFY(!aut.isNull());
	}

	QVERIFY(!aut.haveCaseId(QString()));
	QVERIFY(!aut.haveCaseId(""));
	QVERIFY(aut.haveCaseId("SC-0001"));
	QVERIFY(!aut.haveCaseId("SC-0002"));

	QVERIFY(!aut.haveAmbiguousCaseId(QString()));
	QVERIFY(!aut.haveAmbiguousCaseId(""));
	QVERIFY(!aut.haveAmbiguousCaseId("SC-0001"));
	QVERIFY(aut.haveAmbiguousCaseId("SC-0002"));

	QVERIFY(!aut.haveCourtCaseId(QString()));
	QVERIFY(!aut.haveCourtCaseId(""));
	QVERIFY(!aut.haveCourtCaseId("2020"));
	QVERIFY(aut.haveCourtCaseId("2021"));

	QVERIFY(!aut.haveAmbiguousCourtCaseId(QString()));
	QVERIFY(!aut.haveAmbiguousCourtCaseId(""));
	QVERIFY(aut.haveAmbiguousCourtCaseId("2020"));
	QVERIFY(!aut.haveAmbiguousCourtCaseId("2021"));
}

QObject *newTestRecordsManagement(void)
{
	return new (::std::nothrow) TestRecordsManagement();
}

//QTEST_MAIN(TestRecordsManagement)
#include "test_records_management.moc"
