// Copyright 2005-2019 The Mumble Developers. All rights reserved.
// Use of this source code is governed by a BSD-style license
// that can be found in the LICENSE file at the root of the
// Mumble source tree or at <https://www.mumble.info/LICENSE>.

#include <QtCore>
#include <QtNetwork>
#include <QtTest>
#include <QObject>
#include "PacketDataStream.h"
#include "Message.h"

class TestPacketDataStream : public QObject {
		Q_OBJECT
	private slots:
		void integer();
		void integer_data();
		void string();
		void string_data();
		void space();
		void floating();
		void floating_data();
		void undersize();
};

void TestPacketDataStream::floating_data() {
	QTest::addColumn<double>("value");
	for (int i=1;i<256;i++) {
		double v = 1.0L / (1.0L * i);
		QTest::newRow("Positive") << v;
		QTest::newRow("Negative") << -v;
	}
}

void TestPacketDataStream::floating() {
	QFETCH(double, value);

	char buff[256];
	double d;

	PacketDataStream out(buff, 256);
	out << value;
	PacketDataStream in(buff, out.size());
	in >> d;
	QCOMPARE(value, d);
	QVERIFY(in.isValid());
	QVERIFY(in.left() == 0);
}

void TestPacketDataStream::undersize() {
	QByteArray qba(32, 'Z');
	char buff[256];

	for (unsigned int i=0;i<32;i++) {
		PacketDataStream out(buff, i);
		out << qba;
		QCOMPARE(33-i, out.undersize());
		QVERIFY(! out.isValid());
		QVERIFY(out.left() == 0);
	}
	PacketDataStream out(buff, 33);
	out << qba;
	QCOMPARE(out.undersize(), 0U);
	QVERIFY(out.isValid());
	QVERIFY(out.left() == 0);
}

void TestPacketDataStream::integer_data() {
	QTest::addColumn<quint64>("value");
	for (int i=0;i<64;i++) {
		quint64 v = 1ULL << i;
		QTest::newRow("Integer") << v;
		QTest::newRow("~Integer") << ~v;
	}
}

void TestPacketDataStream::integer() {
	QFETCH(quint64, value);

	char buff[256];
	quint64 v;
	PacketDataStream out(buff, 256);
	out << value;
	PacketDataStream in(buff, out.size());
	in >> v;

	QCOMPARE(value, v);
	QVERIFY(in.isValid());
	QVERIFY(in.left() == 0);
}

void TestPacketDataStream::string_data() {
	QTest::addColumn<QString>("string");
	QTest::newRow("Empty") << QString("");
	QTest::newRow("Null") << QString();
	QTest::newRow("Bærtur") << QString("Bærtur");
}

void TestPacketDataStream::string() {
	QFETCH(QString, string);

	char buff[256];
	QString v;

	PacketDataStream out(buff, 256);
	out << string;
	PacketDataStream in(buff, out.size());
	in >> v;
	QCOMPARE(string, v);
	QVERIFY(in.isValid());
	QVERIFY(in.left() == 0);
}

void TestPacketDataStream::space() {
	char buff[256];
	for (int i=0;i<256;i++)
		buff[i]= 0x55;

	PacketDataStream out(buff, 1);

	char val = -2;

	out << val;
	QVERIFY(out.isValid());
	QVERIFY(out.size() == 1);
	QVERIFY(out.left() == 0);
	QVERIFY(buff[1] == 0x55);

	out << val;

	QVERIFY(! out.isValid());
	QVERIFY(out.size() == 1);
	QVERIFY(out.left() == 0);
	QVERIFY(buff[1] == 0x55);

	PacketDataStream in(buff, 1);

	char v;

	in >> v;
	QCOMPARE(v, val);
	QVERIFY(in.isValid());
	QVERIFY(in.size() == 1);
	QVERIFY(in.left() == 0);

	in >> v;
	QVERIFY(! in.isValid());
	QVERIFY(in.size() == 1);
	QVERIFY(in.left() == 0);
}

QTEST_MAIN(TestPacketDataStream)
#include "TestPacketDataStream.moc"
