TEST(WideToUtf8, InvalidData)
{
	int32_t errors = UTF8_ERR_NONE;

	EXPECT_EQ(0, widetoutf8(nullptr, sizeof(wchar_t), nullptr, 1, &errors));
	EXPECT_ERROREQ(UTF8_ERR_INVALID_DATA, errors);
}
TEST(CaseMappingInitialize, Initialize)
{
	CaseMappingState state;
	const char* i = "Greetings";
	size_t is = strlen(i);
	char o[256] = { 0 };
	size_t os = 255;
	int32_t errors = UTF8_ERR_NONE;

	EXPECT_TRUE(casemapping_initialize(&state, i, is, o, os, TitlecaseIndex1Ptr, TitlecaseIndex2Ptr, TitlecaseDataPtr, QuickCheckCaseMapped_Titlecase, UTF8_LOCALE_DEFAULT, &errors));
	EXPECT_ERROREQ(UTF8_ERR_NONE, errors);
	EXPECT_EQ(i, state.src);
	EXPECT_EQ(is, state.src_size);
	EXPECT_EQ(o, state.dst);
	EXPECT_EQ(os, state.dst_size);
	EXPECT_EQ(TitlecaseIndex1Ptr, state.property_index1);
	EXPECT_EQ(TitlecaseIndex2Ptr, state.property_index2);
	EXPECT_EQ(TitlecaseDataPtr, state.property_data);
	EXPECT_LOCALE_EQ(UTF8_LOCALE_DEFAULT, state.locale);
	EXPECT_EQ(QuickCheckCaseMapped_Titlecase, state.quickcheck_flags);
	EXPECT_EQ(0, state.total_bytes_needed);
	EXPECT_EQ(0, state.last_code_point);
	EXPECT_EQ(0, state.last_code_point_size);
	EXPECT_EQ(0, state.last_general_category);
	EXPECT_EQ(0, state.last_canonical_combining_class);
}
TEST(WideToUtf8, OverlappingParametersFits)
{
	int32_t errors = UTF8_ERR_NONE;

	uint8_t data[128] = { 0 };
	data[0 * sizeof(wchar_t)] = 'o';
	data[1 * sizeof(wchar_t)] = 'f';
	data[2 * sizeof(wchar_t)] = 'f';
	data[3 * sizeof(wchar_t)] = 's';
	data[4 * sizeof(wchar_t)] = 'e';
	data[5 * sizeof(wchar_t)] = 't';

	const wchar_t* i = (const wchar_t*)data;
	size_t is = 6 * sizeof(wchar_t);
	char* o = (char*)(data + is);
	size_t os = 6;

	EXPECT_EQ(6, widetoutf8(i, is, o, os, &errors));
#if UTF8_WCHAR_UTF32
	EXPECT_MEMEQ("o\0\0\0f\0\0\0f\0\0\0s\0\0\0e\0\0\0t\0\0\0offset", (const char*)data, 30);
#else
	EXPECT_MEMEQ("o\0f\0f\0s\0e\0t\0offset", (const char*)data, 18);
#endif
	EXPECT_ERROREQ(UTF8_ERR_NONE, errors);
}
TEST_F(Utf8ToLowerTurkish, SingleCapitalLetterIAmountOfBytes)
{
	const char* c = "I";
	int32_t errors = UTF8_ERR_NONE;

	EXPECT_EQ(2, utf8tolower(c, strlen(c), nullptr, 0, &errors));
	EXPECT_ERROREQ(UTF8_ERR_NONE, errors);
}
TEST_F(Utf8ToLowerGreek, SentenceSmallLetterSigmaAmountOfBytes)
{
	const char* c = "\xCE\xB5\xCE\xBD\xCE\xB8\xCF\x83 \xCF\x85\xCF\x84";
	int32_t errors = UTF8_ERR_NONE;

	EXPECT_EQ(13, utf8tolower(c, strlen(c), nullptr, 0, &errors));
	EXPECT_ERROREQ(UTF8_ERR_NONE, errors);
}
TEST_F(Utf8ToTitleTurkish, SingleCapitalLetterIAndDotAboveAmountOfBytes)
{
	const char* c = "I\xCC\x87";
	int32_t errors = UTF8_ERR_NONE;

	EXPECT_EQ(3, utf8totitle(c, strlen(c), nullptr, 0, &errors));
	EXPECT_ERROREQ(UTF8_ERR_NONE, errors);
}
TEST_F(Utf8ToLowerGreek, SentenceSmallLetterFinalSigmaAmountOfBytes)
{
	const char* c = "\xCE\xB5\xCE\xB6\xCF\x82 \xCE\xBE\xCE\xBE\xCE\xAB\xCE\xAD";
	int32_t errors = UTF8_ERR_NONE;

	EXPECT_EQ(15, utf8tolower(c, strlen(c), nullptr, 0, &errors));
	EXPECT_ERROREQ(UTF8_ERR_NONE, errors);
}
TEST_F(Utf8ToLowerTurkish, SingleSmallLetterDotlessIAmountOfBytes)
{
	const char* c = "\xC4\xB1";
	int32_t errors = UTF8_ERR_NONE;

	EXPECT_EQ(2, utf8tolower(c, strlen(c), nullptr, 0, &errors));
	EXPECT_ERROREQ(UTF8_ERR_NONE, errors);
}
TEST_F(Utf8ToLowerGreek, SingleSmallLetterSigmaAmountOfBytes)
{
	const char* c = "\xCF\x83";
	int32_t errors = UTF8_ERR_NONE;

	EXPECT_EQ(2, utf8tolower(c, strlen(c), nullptr, 0, &errors));
	EXPECT_ERROREQ(UTF8_ERR_NONE, errors);
}
TEST_F(Utf8ToLowerGreek, SentenceCapitalLetterSigmaAmountOfBytes)
{
	const char* c = "\xCE\xA3\xCE\x97\xCE\xA3 \xCE\x98\xCE\x9F\xCE\xA4\xCE\xA3";
	int32_t errors = UTF8_ERR_NONE;

	EXPECT_EQ(15, utf8tolower(c, strlen(c), nullptr, 0, &errors));
	EXPECT_ERROREQ(UTF8_ERR_NONE, errors);
}
TEST_F(Utf8ToLowerGreek, WordSmallLetterFinalSigmaAmountOfBytes)
{
	const char* c = "\xCE\xBF\xCF\x80\xCF\x82";
	int32_t errors = UTF8_ERR_NONE;

	EXPECT_EQ(6, utf8tolower(c, strlen(c), nullptr, 0, &errors));
	EXPECT_ERROREQ(UTF8_ERR_NONE, errors);
}
TEST_F(Utf8ToTitleTurkish, SingleSmallLetterIAmountOfBytes)
{
	const char* c = "i";
	int32_t errors = UTF8_ERR_NONE;

	EXPECT_EQ(2, utf8totitle(c, strlen(c), nullptr, 0, &errors));
	EXPECT_ERROREQ(UTF8_ERR_NONE, errors);
}
TEST_F(Utf8ToLowerGreek, WordCapitalLetterSigmaAtEndAmountOfBytes)
{
	const char* c = "\xCE\x88\xCE\x93\xCE\xA3";
	int32_t errors = UTF8_ERR_NONE;

	EXPECT_EQ(6, utf8tolower(c, strlen(c), nullptr, 0, &errors));
	EXPECT_ERROREQ(UTF8_ERR_NONE, errors);
}
TEST_F(Utf8ToTitleTurkish, SingleSmallLetterDotlessIWithDotAboveAmountOfBytes)
{
	const char* c = "\xC4\xB1\xCC\x87";
	int32_t errors = UTF8_ERR_NONE;

	EXPECT_EQ(3, utf8totitle(c, strlen(c), nullptr, 0, &errors));
	EXPECT_ERROREQ(UTF8_ERR_NONE, errors);
}
TEST_F(Utf8ToLowerTurkish, SingleSmallLetterIWithDotAboveAmountOfBytes)
{
	const char* c = "i\xCC\x87";
	int32_t errors = UTF8_ERR_NONE;

	EXPECT_EQ(3, utf8tolower(c, strlen(c), nullptr, 0, &errors));
	EXPECT_ERROREQ(UTF8_ERR_NONE, errors);
}
TEST(WideToUtf8, BasicLatinAmountOfBytes)
{
	wchar_t i[] = { '$', ' ', '4', '.', '3', '3' };
	size_t is = sizeof(i);
	int32_t errors = UTF8_ERR_NONE;

	EXPECT_EQ(6, widetoutf8(i, is, nullptr, 0, &errors));
	EXPECT_ERROREQ(UTF8_ERR_NONE, errors);
}
TEST(WideToUtf8, SurrogatePairAmountOfBytes)
{
	const wchar_t i[] = { 0xDAAD, 0xDC12, 0xDB01, 0xDC45 };
	size_t is = sizeof(i);
	int32_t errors = UTF8_ERR_NONE;

	EXPECT_EQ(8, widetoutf8(i, is, nullptr, 0, &errors));
	EXPECT_ERROREQ(UTF8_ERR_NONE, errors);
}
TEST(Utf8Normalize, InvalidFlagAndInvalidData)
{
	char o[256] = { 0 };
	size_t os = 255;
	int32_t errors = UTF8_ERR_NONE;

	EXPECT_EQ(0, utf8normalize(nullptr, 166, o, os, 0x00001B28, &errors));
	EXPECT_UTF8EQ("", o);
	EXPECT_ERROREQ(UTF8_ERR_INVALID_FLAG, errors);
}
TEST(Utf8Normalize, InvalidData)
{
	char o[256] = { 0 };
	size_t os = 255;
	int32_t errors = UTF8_ERR_NONE;

	EXPECT_EQ(0, utf8normalize(nullptr, 7, o, os, UTF8_NORMALIZE_COMPOSE, &errors));
	EXPECT_UTF8EQ("", o);
	EXPECT_ERROREQ(UTF8_ERR_INVALID_DATA, errors);
}
TEST_F(Utf8ToTitleTurkish, SingleCapitalLetterIAndDotAboveNotEnoughSpace)
{
	const char* c = "I\xCC\x87";
	const size_t s = 2;
	char b[256] = { 0 };
	int32_t errors = UTF8_ERR_NONE;

	EXPECT_EQ(1, utf8totitle(c, strlen(c), b, s, &errors));
	EXPECT_UTF8EQ("I", b);
	EXPECT_ERROREQ(UTF8_ERR_NOT_ENOUGH_SPACE, errors);
}
TEST_F(Utf8ToLowerGreek, SingleSmallLetterSigmaNotEnoughSpace)
{
	const char* c = "\xCF\x83";
	const size_t s = 1;
	char b[256] = { 0 };
	int32_t errors = UTF8_ERR_NONE;

	EXPECT_EQ(0, utf8tolower(c, strlen(c), b, s, &errors));
	EXPECT_UTF8EQ("", b);
	EXPECT_ERROREQ(UTF8_ERR_NOT_ENOUGH_SPACE, errors);
}
TEST_F(Utf8ToTitleTurkish, SingleSmallLetterDotlessINotEnoughSpace)
{
	const char* c = "\xC4\xB1";
	const size_t s = 0;
	char b[256] = { 0 };
	int32_t errors = UTF8_ERR_NONE;

	EXPECT_EQ(0, utf8totitle(c, strlen(c), b, s, &errors));
	EXPECT_UTF8EQ("", b);
	EXPECT_ERROREQ(UTF8_ERR_NOT_ENOUGH_SPACE, errors);
}
TEST_F(Utf8ToLowerGreek, WordCapitalLetterSigmaAtEndNotEnoughSpace)
{
	const char* c = "\xCE\x88\xCE\x93\xCE\xA3";
	const size_t s = 2;
	char b[256] = { 0 };
	int32_t errors = UTF8_ERR_NONE;

	EXPECT_EQ(2, utf8tolower(c, strlen(c), b, s, &errors));
	EXPECT_UTF8EQ("\xCE\xAD", b);
	EXPECT_ERROREQ(UTF8_ERR_NOT_ENOUGH_SPACE, errors);
}
TEST_F(Utf8ToLowerTurkish, SingleSmallLetterDotlessIWithDotAboveNotEnoughSpace)
{
	const char* c = "\xC4\xB1\xCC\x87";
	const size_t s = 1;
	char b[256] = { 0 };
	int32_t errors = UTF8_ERR_NONE;

	EXPECT_EQ(0, utf8tolower(c, strlen(c), b, s, &errors));
	EXPECT_UTF8EQ("", b);
	EXPECT_ERROREQ(UTF8_ERR_NOT_ENOUGH_SPACE, errors);
}
TEST_F(Utf8ToLowerGreek, WordSmallLetterFinalSigmaNotEnoughSpace)
{
	const char* c = "\xCE\xBF\xCF\x80\xCF\x82";
	const size_t s = 3;
	char b[256] = { 0 };
	int32_t errors = UTF8_ERR_NONE;

	EXPECT_EQ(2, utf8tolower(c, strlen(c), b, s, &errors));
	EXPECT_UTF8EQ("\xCE\xBF", b);
	EXPECT_ERROREQ(UTF8_ERR_NOT_ENOUGH_SPACE, errors);
}
TEST_F(Utf8ToLowerTurkish, SingleCapitalLetterINotEnoughSpace)
{
	const char* c = "I";
	const size_t s = 1;
	char b[256] = { 0 };
	int32_t errors = UTF8_ERR_NONE;

	EXPECT_EQ(0, utf8tolower(c, strlen(c), b, s, &errors));
	EXPECT_UTF8EQ("", b);
	EXPECT_ERROREQ(UTF8_ERR_NOT_ENOUGH_SPACE, errors);
}
TEST_F(Utf8ToLowerGreek, SentenceCapitalLetterSigmaNotEnoughSpace)
{
	const char* c = "\xCE\xA3\xCE\x97\xCE\xA3 \xCE\x98\xCE\x9F\xCE\xA4\xCE\xA3";
	const size_t s = 6;
	char b[256] = { 0 };
	int32_t errors = UTF8_ERR_NONE;

	EXPECT_EQ(6, utf8tolower(c, strlen(c), b, s, &errors));
	EXPECT_UTF8EQ("\xCF\x83\xCE\xB7\xCF\x82", b);
	EXPECT_ERROREQ(UTF8_ERR_NOT_ENOUGH_SPACE, errors);
}
TEST_F(Utf8ToLowerGreek, SentenceSmallLetterSigmaNotEnoughSpace)
{
	const char* c = "\xCE\xB5\xCE\xBD\xCE\xB8\xCF\x83 \xCF\x85\xCF\x84";
	const size_t s = 7;
	char b[256] = { 0 };
	int32_t errors = UTF8_ERR_NONE;

	EXPECT_EQ(6, utf8tolower(c, strlen(c), b, s, &errors));
	EXPECT_UTF8EQ("\xCE\xB5\xCE\xBD\xCE\xB8", b);
	EXPECT_ERROREQ(UTF8_ERR_NOT_ENOUGH_SPACE, errors);
}
TEST_F(Utf8ToLowerGreek, SentenceSmallLetterFinalSigmaNotEnoughSpace)
{
	const char* c = "\xCE\xB5\xCE\xB6\xCF\x82 \xCE\xBE\xCE\xBE\xCE\xAB\xCE\xAD";
	const size_t s = 5;
	char b[256] = { 0 };
	int32_t errors = UTF8_ERR_NONE;

	EXPECT_EQ(4, utf8tolower(c, strlen(c), b, s, &errors));
	EXPECT_UTF8EQ("\xCE\xB5\xCE\xB6", b);
	EXPECT_ERROREQ(UTF8_ERR_NOT_ENOUGH_SPACE, errors);
}
TEST(WideToUtf8, BasicLatin)
{
	wchar_t i[] = { 'c', 'o', 'n', 'n', 'e', 'c', 't' };
	size_t is = sizeof(i);
	char o[256] = { 0 };
	size_t os = 255;
	int32_t errors = UTF8_ERR_NONE;

	EXPECT_EQ(7, widetoutf8(i, is, o, os, &errors));
	EXPECT_UTF8EQ("connect", o);
	EXPECT_ERROREQ(UTF8_ERR_NONE, errors);
}