/* xoreos-tools - Tools to help with xoreos development
 *
 * xoreos-tools is the legal property of its developers, whose names
 * can be found in the AUTHORS file distributed with this source
 * distribution.
 *
 * xoreos-tools 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.
 *
 * xoreos-tools 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 xoreos-tools. If not, see <http://www.gnu.org/licenses/>.
 */

/** @file
 *  Unit tests for our GDA file reader class.
 */

#include "gtest/gtest.h"

#include "src/common/util.h"
#include "src/common/error.h"
#include "src/common/encoding.h"
#include "src/common/hash.h"
#include "src/common/memreadstream.h"
#include "src/aurora/gff4file.h"
#include "src/aurora/gff4fields.h"

#include "src/aurora/gdafile.h"

static const byte kGDAFile[] = {
	0x47,0x46,0x46,0x20,0x56,0x34,0x2E,0x30,0x50,0x43,0x20,0x20,0x47,0x32,0x44,0x41,
	0x56,0x30,0x2E,0x31,0x03,0x00,0x00,0x00,0xC4,0x00,0x00,0x00,0x67,0x74,0x6F,0x70,
	0x02,0x00,0x00,0x00,0x4C,0x00,0x00,0x00,0x08,0x00,0x00,0x00,0x63,0x6F,0x6C,0x6D,
	0x02,0x00,0x00,0x00,0x64,0x00,0x00,0x00,0x05,0x00,0x00,0x00,0x72,0x6F,0x77,0x73,
	0x06,0x00,0x00,0x00,0x7C,0x00,0x00,0x00,0x15,0x00,0x00,0x00,0x12,0x27,0x00,0x00,
	0x01,0x00,0x00,0xC0,0x00,0x00,0x00,0x00,0x13,0x27,0x00,0x00,0x02,0x00,0x00,0xC0,
	0x04,0x00,0x00,0x00,0x11,0x27,0x00,0x00,0x04,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
	0xF7,0x2A,0x00,0x00,0x00,0x00,0x00,0x00,0x04,0x00,0x00,0x00,0x15,0x27,0x00,0x00,
	0x05,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x16,0x27,0x00,0x00,0x0E,0x00,0x00,0x00,
	0x04,0x00,0x00,0x00,0x17,0x27,0x00,0x00,0x05,0x00,0x00,0x00,0x08,0x00,0x00,0x00,
	0x18,0x27,0x00,0x00,0x08,0x00,0x00,0x00,0x0C,0x00,0x00,0x00,0x19,0x27,0x00,0x00,
	0x00,0x00,0x00,0x00,0x10,0x00,0x00,0x00,0x1A,0x27,0x00,0x00,0x0E,0x00,0x00,0x00,
	0x11,0x00,0x00,0x00,0x08,0x00,0x00,0x00,0x2A,0x00,0x00,0x00,0x06,0x00,0x00,0x00,
	0x36,0xC9,0xFB,0x66,0x01,0xAF,0x21,0x19,0x14,0x00,0xB9,0xFD,0xC0,0xB4,0x01,0xE1,
	0x2C,0xBE,0x02,0x02,0xE2,0xC9,0xF5,0x19,0x03,0x91,0xD7,0x45,0x03,0x04,0x03,0x00,
	0x00,0x00,0x01,0x00,0x00,0x00,0x6D,0x00,0x00,0x00,0xE9,0xFF,0xFF,0xFF,0x00,0x00,
	0x28,0x42,0x00,0x7D,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x8F,0x00,0x00,0x00,0xE8,
	0xFF,0xFF,0xFF,0x66,0x66,0x28,0x42,0x00,0x9F,0x00,0x00,0x00,0x03,0x00,0x00,0x00,
	0xB1,0x00,0x00,0x00,0xE7,0xFF,0xFF,0xFF,0xCD,0xCC,0x28,0x42,0x01,0xC1,0x00,0x00,
	0x00,0x06,0x00,0x00,0x00,0x46,0x00,0x6F,0x00,0x6F,0x00,0x62,0x00,0x61,0x00,0x72,
	0x00,0x07,0x00,0x00,0x00,0x66,0x00,0x6F,0x00,0x6F,0x00,0x2E,0x00,0x62,0x00,0x61,
	0x00,0x72,0x00,0x06,0x00,0x00,0x00,0x42,0x00,0x61,0x00,0x72,0x00,0x66,0x00,0x6F,
	0x00,0x6F,0x00,0x07,0x00,0x00,0x00,0x62,0x00,0x61,0x00,0x72,0x00,0x2E,0x00,0x66,
	0x00,0x6F,0x00,0x6F,0x00,0x06,0x00,0x00,0x00,0x51,0x00,0x75,0x00,0x75,0x00,0x75,
	0x00,0x75,0x00,0x78,0x00,0x07,0x00,0x00,0x00,0x71,0x00,0x75,0x00,0x78,0x00,0x2E,
	0x00,0x71,0x00,0x75,0x00,0x78,0x00
};

static const size_t kColumnCount = 6;

static const char * const kHeaders[kColumnCount] = {
	"ID", "StringValue", "IntValue", "FloatValue", "BoolValue", "ResourceValue"
};

static const char * const kHeadersLow[kColumnCount] = {
	"id", "stringvalue", "intvalue", "floatvalue", "boolvalue", "resourcevalue"
};

static const uint32 kFields[kColumnCount] = {
	Aurora::kGFF4G2DAColumn1, Aurora::kGFF4G2DAColumn2, Aurora::kGFF4G2DAColumn3,
	Aurora::kGFF4G2DAColumn4, Aurora::kGFF4G2DAColumn5, Aurora::kGFF4G2DAColumn6
};

static const size_t kRowCount = 3;

static const int32        kDataID      [kRowCount] = { 1        , 0        , 3         };
static const char * const kDataString  [kRowCount] = { "Foobar" , "Barfoo" , "Quuuux"  };
static const int32        kDataInt     [kRowCount] = { -23      , -24      , -25       };
static const float        kDataFloat   [kRowCount] = { 42.0f    , 42.1f    , 42.2f     };
static const int32        kDataBool    [kRowCount] = { 0        , 0        , 1         };
static const char * const kDataResource[kRowCount] = { "foo.bar", "bar.foo", "qux.qux" };

GTEST_TEST(GDAFile, getColumnCount) {
	const Aurora::GDAFile gda(new Common::MemoryReadStream(kGDAFile));

	EXPECT_EQ(gda.getColumnCount(), kColumnCount);
}

GTEST_TEST(GDAFile, getRowCount) {
	const Aurora::GDAFile gda(new Common::MemoryReadStream(kGDAFile));

	EXPECT_EQ(gda.getRowCount(), kRowCount);
}

GTEST_TEST(GDAFile, hasRow) {
	const Aurora::GDAFile gda(new Common::MemoryReadStream(kGDAFile));

	for (size_t i = 0; i < kRowCount; i++)
		EXPECT_TRUE(gda.hasRow(i));

	EXPECT_FALSE(gda.hasRow(kRowCount + 1));
}

GTEST_TEST(GDAFile, getRow) {
	const Aurora::GDAFile gda(new Common::MemoryReadStream(kGDAFile));

	for (size_t i = 0; i < kRowCount; i++) {
		const Aurora::GFF4Struct *row = gda.getRow(i);
		ASSERT_NE(row, static_cast<Aurora::GFF4Struct *>(0));

		EXPECT_EQ(row->getLabel(), MKTAG('r', 'o', 'w', 's'));
		EXPECT_EQ(row->getSint(kFields[0]), kDataID[i]);
	}

	EXPECT_EQ(gda.getRow(kRowCount + 1), static_cast<Aurora::GFF4Struct *>(0));
}

GTEST_TEST(GDAFile, findRow) {
	const Aurora::GDAFile gda(new Common::MemoryReadStream(kGDAFile));

	for (size_t i = 0; i < kRowCount; i++)
		EXPECT_EQ(gda.findRow(kDataID[i]), i);

	EXPECT_EQ(gda.findRow(9999), Aurora::GDAFile::kInvalidRow);
}

GTEST_TEST(GDAFile, findColumnName) {
	const Aurora::GDAFile gda(new Common::MemoryReadStream(kGDAFile));

	for (size_t i = 0; i < kColumnCount; i++)
		EXPECT_EQ(gda.findColumn(kHeaders[i]), kFields[i]);

	EXPECT_EQ(gda.findColumn("NOPE"), Aurora::GDAFile::kInvalidColumn);
}

GTEST_TEST(GDAFile, findColumnHash) {
	const Aurora::GDAFile gda(new Common::MemoryReadStream(kGDAFile));

	for (size_t i = 0; i < kColumnCount; i++)
		EXPECT_EQ(gda.findColumn(Common::hashStringCRC32(kHeadersLow[i], Common::kEncodingUTF16LE)), kFields[i]);

	EXPECT_EQ(gda.findColumn(9999), Aurora::GDAFile::kInvalidColumn);
}

GTEST_TEST(GDAFile, getStringName) {
	const Aurora::GDAFile gda(new Common::MemoryReadStream(kGDAFile));

	for (size_t i = 0; i < kRowCount; i++) {
		EXPECT_STREQ(gda.getString(i, kHeaders[1]).c_str(), kDataString[i]);
		EXPECT_STREQ(gda.getString(i, kHeaders[5]).c_str(), kDataResource[i]);
	}

	EXPECT_STREQ(gda.getString(9999, kHeaders[1]).c_str(), "");
	EXPECT_STREQ(gda.getString(   0, "NOPE"     ).c_str(), "");
	EXPECT_STREQ(gda.getString(9999, "NOPE"     ).c_str(), "");

	EXPECT_STREQ(gda.getString(9999, "NOPE", "nope").c_str(), "nope");

	EXPECT_THROW(gda.getString(0, kHeaders[0]), Common::Exception);
}

GTEST_TEST(GDAFile, getStringHash) {
	const Aurora::GDAFile gda(new Common::MemoryReadStream(kGDAFile));

	const uint32 hash0 = Common::hashStringCRC32(kHeadersLow[0], Common::kEncodingUTF16LE);
	const uint32 hash1 = Common::hashStringCRC32(kHeadersLow[1], Common::kEncodingUTF16LE);
	const uint32 hash5 = Common::hashStringCRC32(kHeadersLow[5], Common::kEncodingUTF16LE);

	for (size_t i = 0; i < kRowCount; i++) {
		EXPECT_STREQ(gda.getString(i, hash1).c_str(), kDataString[i]);
		EXPECT_STREQ(gda.getString(i, hash5).c_str(), kDataResource[i]);
	}

	EXPECT_STREQ(gda.getString(9999, hash1).c_str(), "");
	EXPECT_STREQ(gda.getString(   0, 99999).c_str(), "");
	EXPECT_STREQ(gda.getString(9999, 99999).c_str(), "");

	EXPECT_STREQ(gda.getString(9999, 99999, "nope").c_str(), "nope");

	EXPECT_THROW(gda.getString(0, hash0), Common::Exception);
}

GTEST_TEST(GDAFile, getIntName) {
	const Aurora::GDAFile gda(new Common::MemoryReadStream(kGDAFile));

	for (size_t i = 0; i < kRowCount; i++) {
		EXPECT_EQ(gda.getInt(i, kHeaders[0]), kDataID[i]);
		EXPECT_EQ(gda.getInt(i, kHeaders[2]), kDataInt[i]);
		EXPECT_EQ(gda.getInt(i, kHeaders[4]), kDataBool[i]);
	}

	EXPECT_EQ(gda.getInt(9999, kHeaders[0]), 0);
	EXPECT_EQ(gda.getInt(   0, "NOPE"     ), 0);
	EXPECT_EQ(gda.getInt(9999, "NOPE"     ), 0);

	EXPECT_EQ(gda.getInt(9999, "NOPE", 9999), 9999);

	EXPECT_THROW(gda.getInt(0, kHeaders[1]), Common::Exception);
}

GTEST_TEST(GDAFile, getIntHash) {
	const Aurora::GDAFile gda(new Common::MemoryReadStream(kGDAFile));

	const uint32 hash0 = Common::hashStringCRC32(kHeadersLow[0], Common::kEncodingUTF16LE);
	const uint32 hash1 = Common::hashStringCRC32(kHeadersLow[1], Common::kEncodingUTF16LE);
	const uint32 hash2 = Common::hashStringCRC32(kHeadersLow[2], Common::kEncodingUTF16LE);
	const uint32 hash4 = Common::hashStringCRC32(kHeadersLow[4], Common::kEncodingUTF16LE);

	for (size_t i = 0; i < kRowCount; i++) {
		EXPECT_EQ(gda.getInt(i, hash0), kDataID[i]);
		EXPECT_EQ(gda.getInt(i, hash2), kDataInt[i]);
		EXPECT_EQ(gda.getInt(i, hash4), kDataBool[i]);
	}

	EXPECT_EQ(gda.getInt(9999, hash0), 0);
	EXPECT_EQ(gda.getInt(   0, 99999), 0);
	EXPECT_EQ(gda.getInt(9999, 99999), 0);

	EXPECT_EQ(gda.getInt(9999, 99999, 9999), 9999);

	EXPECT_THROW(gda.getInt(0, hash1), Common::Exception);
}

GTEST_TEST(GDAFile, getFloatName) {
	const Aurora::GDAFile gda(new Common::MemoryReadStream(kGDAFile));

	for (size_t i = 0; i < kRowCount; i++)
		EXPECT_FLOAT_EQ(gda.getFloat(i, kHeaders[3]), kDataFloat[i]);

	EXPECT_FLOAT_EQ(gda.getFloat(9999, kHeaders[0]), 0.0f);
	EXPECT_FLOAT_EQ(gda.getFloat(   0, "NOPE"     ), 0.0f);
	EXPECT_FLOAT_EQ(gda.getFloat(9999, "NOPE"     ), 0.0f);

	EXPECT_FLOAT_EQ(gda.getFloat(9999, "NOPE", 9999.0f), 9999.0f);

	EXPECT_THROW(gda.getFloat(0, kHeaders[1]), Common::Exception);
}

GTEST_TEST(GDAFile, getFloatHash) {
	const Aurora::GDAFile gda(new Common::MemoryReadStream(kGDAFile));

	const uint32 hash1 = Common::hashStringCRC32(kHeadersLow[1], Common::kEncodingUTF16LE);
	const uint32 hash3 = Common::hashStringCRC32(kHeadersLow[3], Common::kEncodingUTF16LE);

	for (size_t i = 0; i < kRowCount; i++)
		EXPECT_FLOAT_EQ(gda.getFloat(i, hash3), kDataFloat[i]);

	EXPECT_FLOAT_EQ(gda.getFloat(9999, hash3), 0.0f);
	EXPECT_FLOAT_EQ(gda.getFloat(   0, 99999), 0.0f);
	EXPECT_FLOAT_EQ(gda.getFloat(9999, 99999), 0.0f);

	EXPECT_FLOAT_EQ(gda.getFloat(9999, 99999, 9999.0f), 9999.0f);

	EXPECT_THROW(gda.getFloat(0, hash1), Common::Exception);
}

GTEST_TEST(GDAFile, v02) {
	static const byte kGDAv02[] = {
		0x47,0x46,0x46,0x20,0x56,0x34,0x2E,0x30,0x50,0x43,0x20,0x20,0x47,0x32,0x44,0x41,
		0x56,0x30,0x2E,0x32,0x03,0x00,0x00,0x00,0xC4,0x00,0x00,0x00,0x67,0x74,0x6F,0x70,
		0x02,0x00,0x00,0x00,0x4C,0x00,0x00,0x00,0x08,0x00,0x00,0x00,0x63,0x6F,0x6C,0x6D,
		0x02,0x00,0x00,0x00,0x64,0x00,0x00,0x00,0x05,0x00,0x00,0x00,0x72,0x6F,0x77,0x73,
		0x06,0x00,0x00,0x00,0x7C,0x00,0x00,0x00,0x15,0x00,0x00,0x00,0x12,0x27,0x00,0x00,
		0x01,0x00,0x00,0xC0,0x00,0x00,0x00,0x00,0x13,0x27,0x00,0x00,0x02,0x00,0x00,0xC0,
		0x04,0x00,0x00,0x00,0x11,0x27,0x00,0x00,0x04,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
		0xF7,0x2A,0x00,0x00,0x00,0x00,0x00,0x00,0x04,0x00,0x00,0x00,0x15,0x27,0x00,0x00,
		0x05,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x16,0x27,0x00,0x00,0x0E,0x00,0x00,0x00,
		0x04,0x00,0x00,0x00,0x17,0x27,0x00,0x00,0x05,0x00,0x00,0x00,0x08,0x00,0x00,0x00,
		0x18,0x27,0x00,0x00,0x08,0x00,0x00,0x00,0x0C,0x00,0x00,0x00,0x19,0x27,0x00,0x00,
		0x00,0x00,0x00,0x00,0x10,0x00,0x00,0x00,0x1A,0x27,0x00,0x00,0x0E,0x00,0x00,0x00,
		0x11,0x00,0x00,0x00,0x08,0x00,0x00,0x00,0x2A,0x00,0x00,0x00,0x06,0x00,0x00,0x00,
		0x36,0xC9,0xFB,0x66,0x01,0xAF,0x21,0x19,0x14,0x00,0xB9,0xFD,0xC0,0xB4,0x01,0xE1,
		0x2C,0xBE,0x02,0x02,0xE2,0xC9,0xF5,0x19,0x03,0x91,0xD7,0x45,0x03,0x04,0x03,0x00,
		0x00,0x00,0x01,0x00,0x00,0x00,0x6D,0x00,0x00,0x00,0xE9,0xFF,0xFF,0xFF,0x00,0x00,
		0x28,0x42,0x00,0x7D,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x8F,0x00,0x00,0x00,0xE8,
		0xFF,0xFF,0xFF,0x66,0x66,0x28,0x42,0x00,0x9F,0x00,0x00,0x00,0x03,0x00,0x00,0x00,
		0xB1,0x00,0x00,0x00,0xE7,0xFF,0xFF,0xFF,0xCD,0xCC,0x28,0x42,0x01,0xC1,0x00,0x00,
		0x00,0x06,0x00,0x00,0x00,0x46,0x00,0x6F,0x00,0x6F,0x00,0x62,0x00,0x61,0x00,0x72,
		0x00,0x07,0x00,0x00,0x00,0x66,0x00,0x6F,0x00,0x6F,0x00,0x2E,0x00,0x62,0x00,0x61,
		0x00,0x72,0x00,0x06,0x00,0x00,0x00,0x42,0x00,0x61,0x00,0x72,0x00,0x66,0x00,0x6F,
		0x00,0x6F,0x00,0x07,0x00,0x00,0x00,0x62,0x00,0x61,0x00,0x72,0x00,0x2E,0x00,0x66,
		0x00,0x6F,0x00,0x6F,0x00,0x06,0x00,0x00,0x00,0x51,0x00,0x75,0x00,0x75,0x00,0x75,
		0x00,0x75,0x00,0x78,0x00,0x07,0x00,0x00,0x00,0x71,0x00,0x75,0x00,0x78,0x00,0x2E,
		0x00,0x71,0x00,0x75,0x00,0x78,0x00
	};

	const Aurora::GDAFile gda(new Common::MemoryReadStream(kGDAv02));

	EXPECT_EQ(gda.getColumnCount(), kColumnCount);
	EXPECT_EQ(gda.getRowCount(), kRowCount);

	for (size_t i = 0; i < kRowCount; i++) {
		const Aurora::GFF4Struct *row = gda.getRow(i);
		ASSERT_NE(row, static_cast<Aurora::GFF4Struct *>(0));

		EXPECT_EQ(row->getLabel(), MKTAG('r', 'o', 'w', 's'));
		EXPECT_EQ(row->getSint(kFields[0]), kDataID[i]);
	}
}

GTEST_TEST(GDAFile, add) {
	static const byte kMGDA1[] = {
		0x47,0x46,0x46,0x20,0x56,0x34,0x2E,0x30,0x50,0x43,0x20,0x20,0x47,0x32,0x44,0x41,
		0x56,0x30,0x2E,0x31,0x03,0x00,0x00,0x00,0x94,0x00,0x00,0x00,0x67,0x74,0x6F,0x70,
		0x02,0x00,0x00,0x00,0x4C,0x00,0x00,0x00,0x08,0x00,0x00,0x00,0x63,0x6F,0x6C,0x6D,
		0x02,0x00,0x00,0x00,0x64,0x00,0x00,0x00,0x05,0x00,0x00,0x00,0x72,0x6F,0x77,0x73,
		0x02,0x00,0x00,0x00,0x7C,0x00,0x00,0x00,0x08,0x00,0x00,0x00,0x12,0x27,0x00,0x00,
		0x01,0x00,0x00,0xC0,0x00,0x00,0x00,0x00,0x13,0x27,0x00,0x00,0x02,0x00,0x00,0xC0,
		0x04,0x00,0x00,0x00,0x11,0x27,0x00,0x00,0x04,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
		0xF7,0x2A,0x00,0x00,0x00,0x00,0x00,0x00,0x04,0x00,0x00,0x00,0x15,0x27,0x00,0x00,
		0x05,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x16,0x27,0x00,0x00,0x05,0x00,0x00,0x00,
		0x04,0x00,0x00,0x00,0x08,0x00,0x00,0x00,0x16,0x00,0x00,0x00,0x02,0x00,0x00,0x00,
		0x36,0xC9,0xFB,0x66,0x01,0xE1,0x3D,0xC1,0x3F,0x01,0x03,0x00,0x00,0x00,0x00,0x00,
		0x00,0x00,0x00,0x00,0x00,0x00,0x01,0x00,0x00,0x00,0x01,0x00,0x00,0x00,0x02,0x00,
		0x00,0x00,0x02,0x00,0x00,0x00
	};
	static const byte kMGDA2[] = {
		0x47,0x46,0x46,0x20,0x56,0x34,0x2E,0x30,0x50,0x43,0x20,0x20,0x47,0x32,0x44,0x41,
		0x56,0x30,0x2E,0x31,0x03,0x00,0x00,0x00,0x94,0x00,0x00,0x00,0x67,0x74,0x6F,0x70,
		0x02,0x00,0x00,0x00,0x4C,0x00,0x00,0x00,0x08,0x00,0x00,0x00,0x63,0x6F,0x6C,0x6D,
		0x02,0x00,0x00,0x00,0x64,0x00,0x00,0x00,0x05,0x00,0x00,0x00,0x72,0x6F,0x77,0x73,
		0x02,0x00,0x00,0x00,0x7C,0x00,0x00,0x00,0x08,0x00,0x00,0x00,0x12,0x27,0x00,0x00,
		0x01,0x00,0x00,0xC0,0x00,0x00,0x00,0x00,0x13,0x27,0x00,0x00,0x02,0x00,0x00,0xC0,
		0x04,0x00,0x00,0x00,0x11,0x27,0x00,0x00,0x04,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
		0xF7,0x2A,0x00,0x00,0x00,0x00,0x00,0x00,0x04,0x00,0x00,0x00,0x15,0x27,0x00,0x00,
		0x05,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x16,0x27,0x00,0x00,0x05,0x00,0x00,0x00,
		0x04,0x00,0x00,0x00,0x08,0x00,0x00,0x00,0x16,0x00,0x00,0x00,0x02,0x00,0x00,0x00,
		0x36,0xC9,0xFB,0x66,0x01,0xE1,0x3D,0xC1,0x3F,0x01,0x03,0x00,0x00,0x00,0x0A,0x00,
		0x00,0x00,0x0A,0x00,0x00,0x00,0x0B,0x00,0x00,0x00,0x0B,0x00,0x00,0x00,0x0C,0x00,
		0x00,0x00,0x0C,0x00,0x00,0x00
	};
	static const byte kMGDA3[] = {
		0x47,0x46,0x46,0x20,0x56,0x34,0x2E,0x30,0x50,0x43,0x20,0x20,0x47,0x32,0x44,0x41,
		0x56,0x30,0x2E,0x31,0x03,0x00,0x00,0x00,0x94,0x00,0x00,0x00,0x67,0x74,0x6F,0x70,
		0x02,0x00,0x00,0x00,0x4C,0x00,0x00,0x00,0x08,0x00,0x00,0x00,0x63,0x6F,0x6C,0x6D,
		0x02,0x00,0x00,0x00,0x64,0x00,0x00,0x00,0x05,0x00,0x00,0x00,0x72,0x6F,0x77,0x73,
		0x02,0x00,0x00,0x00,0x7C,0x00,0x00,0x00,0x08,0x00,0x00,0x00,0x12,0x27,0x00,0x00,
		0x01,0x00,0x00,0xC0,0x00,0x00,0x00,0x00,0x13,0x27,0x00,0x00,0x02,0x00,0x00,0xC0,
		0x04,0x00,0x00,0x00,0x11,0x27,0x00,0x00,0x04,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
		0xF7,0x2A,0x00,0x00,0x00,0x00,0x00,0x00,0x04,0x00,0x00,0x00,0x15,0x27,0x00,0x00,
		0x05,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x16,0x27,0x00,0x00,0x05,0x00,0x00,0x00,
		0x04,0x00,0x00,0x00,0x08,0x00,0x00,0x00,0x16,0x00,0x00,0x00,0x02,0x00,0x00,0x00,
		0x36,0xC9,0xFB,0x66,0x01,0xE1,0x3D,0xC1,0x3F,0x01,0x03,0x00,0x00,0x00,0x14,0x00,
		0x00,0x00,0x14,0x00,0x00,0x00,0x15,0x00,0x00,0x00,0x15,0x00,0x00,0x00,0x16,0x00,
		0x00,0x00,0x16,0x00,0x00,0x00
	};

	static const int32 kIDs[9] = { 0, 1, 2, 10, 11, 12, 20, 21, 22 };

	Aurora::GDAFile gda(new Common::MemoryReadStream(kMGDA1));

	gda.add(new Common::MemoryReadStream(kMGDA3));
	gda.add(new Common::MemoryReadStream(kMGDA2));

	EXPECT_EQ(gda.getColumnCount(), 2);
	EXPECT_EQ(gda.getRowCount(), ARRAYSIZE(kIDs));

	for (size_t i = 0; i < ARRAYSIZE(kIDs); i++) {
		const size_t index = gda.findRow(kIDs[i]);
		ASSERT_NE(index, Aurora::GDAFile::kInvalidRow);

		EXPECT_EQ(gda.getInt(index, "Value"), kIDs[i]);
	}
}
