#include <gtest/gtest.h>

#include <base/system.h>

TEST(Str, Dist)
{
	EXPECT_EQ(str_utf8_dist("aaa", "aaa"), 0);
	EXPECT_EQ(str_utf8_dist("123", "123"), 0);
	EXPECT_EQ(str_utf8_dist("", ""), 0);
	EXPECT_EQ(str_utf8_dist("a", "b"), 1);
	EXPECT_EQ(str_utf8_dist("", "aaa"), 3);
	EXPECT_EQ(str_utf8_dist("123", ""), 3);
	EXPECT_EQ(str_utf8_dist("ä", ""), 1);
	EXPECT_EQ(str_utf8_dist("Hëllö", "Hello"), 2);
	// https://en.wikipedia.org/w/index.php?title=Levenshtein_distance&oldid=828480025#Example
	EXPECT_EQ(str_utf8_dist("kitten", "sitting"), 3);
	EXPECT_EQ(str_utf8_dist("flaw", "lawn"), 2);
	EXPECT_EQ(str_utf8_dist("saturday", "sunday"), 3);
}

TEST(Str, Utf8Isspace)
{
	EXPECT_TRUE(str_utf8_isspace(0x200b)); // Zero-width space
	EXPECT_TRUE(str_utf8_isspace(' '));
	EXPECT_FALSE(str_utf8_isspace('a'));
	// Control characters.
	for(char c = 0; c < 0x20; c++)
	{
		EXPECT_TRUE(str_utf8_isspace(c));
	}
}

TEST(Str, Utf8SkipWhitespaces)
{
	EXPECT_STREQ(str_utf8_skip_whitespaces("abc"), "abc");
	EXPECT_STREQ(str_utf8_skip_whitespaces("abc   "), "abc   ");
	EXPECT_STREQ(str_utf8_skip_whitespaces("    abc"), "abc");
	EXPECT_STREQ(str_utf8_skip_whitespaces("\xe2\x80\x8b abc"), "abc");
}

TEST(Str, Utf8TrimRight)
{
	char A1[] = "abc";
	str_utf8_trim_right(A1);
	EXPECT_STREQ(A1, "abc");
	char A2[] = "   abc";
	str_utf8_trim_right(A2);
	EXPECT_STREQ(A2, "   abc");
	char A3[] = "abc   ";
	str_utf8_trim_right(A3);
	EXPECT_STREQ(A3, "abc");
	char A4[] = "abc \xe2\x80\x8b";
	str_utf8_trim_right(A4);
	EXPECT_STREQ(A4, "abc");
}

TEST(Str, Utf8CompConfusables)
{
	EXPECT_TRUE(str_utf8_comp_confusable("abc", "abc") == 0);
	EXPECT_TRUE(str_utf8_comp_confusable("rn", "m") == 0);
	EXPECT_TRUE(str_utf8_comp_confusable("l", "ӏ") == 0); // CYRILLIC SMALL LETTER PALOCHKA
	EXPECT_TRUE(str_utf8_comp_confusable("i", "¡") == 0); // INVERTED EXCLAMATION MARK
	EXPECT_FALSE(str_utf8_comp_confusable("o", "x") == 0);
	EXPECT_TRUE(str_utf8_comp_confusable("aceiou", "ąçęįǫų") == 0);
}

TEST(Str, Utf8ToLower)
{
	EXPECT_TRUE(str_utf8_tolower('A') == 'a');
	EXPECT_TRUE(str_utf8_tolower('z') == 'z');
	EXPECT_TRUE(str_utf8_tolower(192) == 224); // À -> à
	EXPECT_TRUE(str_utf8_tolower(7882) == 7883); // Ị -> ị

	EXPECT_TRUE(str_utf8_comp_nocase("ÖlÜ", "ölü") == 0);
	EXPECT_TRUE(str_utf8_comp_nocase("ÜlÖ", "ölü") > 0); // ü > ö
	EXPECT_TRUE(str_utf8_comp_nocase("ÖlÜ", "ölüa") < 0); // NULL < a
	EXPECT_TRUE(str_utf8_comp_nocase("ölüa", "ÖlÜ") > 0); // a < NULL

#if(CHAR_MIN < 0)
	const char a[2] = {CHAR_MIN, 0};
	const char b[2] = {0, 0};
	EXPECT_TRUE(str_utf8_comp_nocase(a, b) > 0);
	EXPECT_TRUE(str_utf8_comp_nocase(b, a) < 0);
#endif

	EXPECT_TRUE(str_utf8_comp_nocase_num("ÖlÜ", "ölüa", 5) == 0);
	EXPECT_TRUE(str_utf8_comp_nocase_num("ÖlÜ", "ölüa", 6) != 0);
	EXPECT_TRUE(str_utf8_comp_nocase_num("a", "z", 0) == 0);
	EXPECT_TRUE(str_utf8_comp_nocase_num("a", "z", 1) != 0);

	const char str[] = "ÄÖÜ";
	EXPECT_TRUE(str_utf8_find_nocase(str, "ä") == str);
	EXPECT_TRUE(str_utf8_find_nocase(str, "ö") == str + 2);
	EXPECT_TRUE(str_utf8_find_nocase(str, "ü") == str + 4);
	EXPECT_TRUE(str_utf8_find_nocase(str, "z") == NULL);
}

TEST(Str, Utf8FixTruncation)
{
	char aaBuf[][32] = {
		"",
		"\xff",
		"abc",
		"abc\xff",
		"blub\xffxyz",
		"привет Наташа\xff",
		"до свидания\xffОлег",
	};
	const char *apExpected[] = {
		"",
		"",
		"abc",
		"abc",
		"blub\xffxyz",
		"привет Наташа",
		"до свидания\xffОлег",
	};
	for(unsigned i = 0; i < std::size(aaBuf); i++)
	{
		EXPECT_EQ(str_utf8_fix_truncation(aaBuf[i]), str_length(apExpected[i]));
		EXPECT_STREQ(aaBuf[i], apExpected[i]);
	}
}

TEST(Str, Startswith)
{
	EXPECT_TRUE(str_startswith("abcdef", "abc"));
	EXPECT_FALSE(str_startswith("abc", "abcdef"));

	EXPECT_TRUE(str_startswith("xyz", ""));
	EXPECT_FALSE(str_startswith("", "xyz"));

	EXPECT_FALSE(str_startswith("house", "home"));
	EXPECT_FALSE(str_startswith("blackboard", "board"));

	EXPECT_TRUE(str_startswith("поплавать", "по"));
	EXPECT_FALSE(str_startswith("плавать", "по"));

	static const char ABCDEFG[] = "abcdefg";
	static const char ABC[] = "abc";
	EXPECT_EQ(str_startswith(ABCDEFG, ABC) - ABCDEFG, str_length(ABC));
}

TEST(Str, StartswithNocase)
{
	EXPECT_TRUE(str_startswith_nocase("Abcdef", "abc"));
	EXPECT_FALSE(str_startswith_nocase("aBc", "abcdef"));

	EXPECT_TRUE(str_startswith_nocase("xYz", ""));
	EXPECT_FALSE(str_startswith_nocase("", "xYz"));

	EXPECT_FALSE(str_startswith_nocase("house", "home"));
	EXPECT_FALSE(str_startswith_nocase("Blackboard", "board"));

	EXPECT_TRUE(str_startswith_nocase("поплавать", "по"));
	EXPECT_FALSE(str_startswith_nocase("плавать", "по"));

	static const char ABCDEFG[] = "aBcdefg";
	static const char ABC[] = "abc";
	EXPECT_EQ(str_startswith_nocase(ABCDEFG, ABC) - ABCDEFG, str_length(ABC));
}

TEST(Str, Endswith)
{
	EXPECT_TRUE(str_endswith("abcdef", "def"));
	EXPECT_FALSE(str_endswith("def", "abcdef"));

	EXPECT_TRUE(str_endswith("xyz", ""));
	EXPECT_FALSE(str_endswith("", "xyz"));

	EXPECT_FALSE(str_endswith("rhyme", "mine"));
	EXPECT_FALSE(str_endswith("blackboard", "black"));

	EXPECT_TRUE(str_endswith("люди", "юди"));
	EXPECT_FALSE(str_endswith("люди", "любовь"));

	static const char ABCDEFG[] = "abcdefg";
	static const char DEFG[] = "defg";
	EXPECT_EQ(str_endswith(ABCDEFG, DEFG) - ABCDEFG,
		str_length(ABCDEFG) - str_length(DEFG));
}

TEST(Str, EndswithNocase)
{
	EXPECT_TRUE(str_endswith_nocase("abcdef", "deF"));
	EXPECT_FALSE(str_endswith_nocase("def", "abcdef"));

	EXPECT_TRUE(str_endswith_nocase("xyz", ""));
	EXPECT_FALSE(str_endswith_nocase("", "xyz"));

	EXPECT_FALSE(str_endswith_nocase("rhyme", "minE"));
	EXPECT_FALSE(str_endswith_nocase("blackboard", "black"));

	EXPECT_TRUE(str_endswith_nocase("люди", "юди"));
	EXPECT_FALSE(str_endswith_nocase("люди", "любовь"));

	static const char ABCDEFG[] = "abcdefG";
	static const char DEFG[] = "defg";
	EXPECT_EQ(str_endswith_nocase(ABCDEFG, DEFG) - ABCDEFG,
		str_length(ABCDEFG) - str_length(DEFG));
}

TEST(Str, HexDecode)
{
	char aOut[5] = {'a', 'b', 'c', 'd', 0};
	EXPECT_EQ(str_hex_decode(aOut, 0, ""), 0);
	EXPECT_STREQ(aOut, "abcd");
	EXPECT_EQ(str_hex_decode(aOut, 0, " "), 2);
	EXPECT_STREQ(aOut, "abcd");
	EXPECT_EQ(str_hex_decode(aOut, 1, "1"), 2);
	EXPECT_STREQ(aOut + 1, "bcd");
	EXPECT_EQ(str_hex_decode(aOut, 1, "41"), 0);
	EXPECT_STREQ(aOut, "Abcd");
	EXPECT_EQ(str_hex_decode(aOut, 1, "4x"), 1);
	EXPECT_STREQ(aOut + 1, "bcd");
	EXPECT_EQ(str_hex_decode(aOut, 1, "x1"), 1);
	EXPECT_STREQ(aOut + 1, "bcd");
	EXPECT_EQ(str_hex_decode(aOut, 1, "411"), 2);
	EXPECT_STREQ(aOut + 1, "bcd");
	EXPECT_EQ(str_hex_decode(aOut, 4, "41424344"), 0);
	EXPECT_STREQ(aOut, "ABCD");
}

void StrBase64Str(char *pBuffer, int BufferSize, const char *pString)
{
	str_base64(pBuffer, BufferSize, pString, str_length(pString));
}

TEST(Str, Base64)
{
	char aBuf[128];
	str_base64(aBuf, sizeof(aBuf), "\0", 1);
	EXPECT_STREQ(aBuf, "AA==");
	str_base64(aBuf, sizeof(aBuf), "\0\0", 2);
	EXPECT_STREQ(aBuf, "AAA=");
	str_base64(aBuf, sizeof(aBuf), "\0\0\0", 3);
	EXPECT_STREQ(aBuf, "AAAA");

	StrBase64Str(aBuf, sizeof(aBuf), "");
	EXPECT_STREQ(aBuf, "");

	// https://en.wikipedia.org/w/index.php?title=Base64&oldid=1033503483#Output_padding
	StrBase64Str(aBuf, sizeof(aBuf), "pleasure.");
	EXPECT_STREQ(aBuf, "cGxlYXN1cmUu");
	StrBase64Str(aBuf, sizeof(aBuf), "leasure.");
	EXPECT_STREQ(aBuf, "bGVhc3VyZS4=");
	StrBase64Str(aBuf, sizeof(aBuf), "easure.");
	EXPECT_STREQ(aBuf, "ZWFzdXJlLg==");
	StrBase64Str(aBuf, sizeof(aBuf), "asure.");
	EXPECT_STREQ(aBuf, "YXN1cmUu");
	StrBase64Str(aBuf, sizeof(aBuf), "sure.");
	EXPECT_STREQ(aBuf, "c3VyZS4=");
}

TEST(Str, Base64Decode)
{
	char aOut[17];
	str_copy(aOut, "XXXXXXXXXXXXXXXX", sizeof(aOut));
	EXPECT_EQ(str_base64_decode(aOut, sizeof(aOut), ""), 0);
	EXPECT_STREQ(aOut, "XXXXXXXXXXXXXXXX");

	// https://en.wikipedia.org/w/index.php?title=Base64&oldid=1033503483#Output_padding
	str_copy(aOut, "XXXXXXXXXXXXXXXX", sizeof(aOut));
	EXPECT_EQ(str_base64_decode(aOut, sizeof(aOut), "cGxlYXN1cmUu"), 9);
	EXPECT_STREQ(aOut, "pleasure.XXXXXXX");
	str_copy(aOut, "XXXXXXXXXXXXXXXX", sizeof(aOut));
	EXPECT_EQ(str_base64_decode(aOut, sizeof(aOut), "bGVhc3VyZS4="), 8);
	EXPECT_STREQ(aOut, "leasure.XXXXXXXX");
	str_copy(aOut, "XXXXXXXXXXXXXXXX", sizeof(aOut));
	EXPECT_EQ(str_base64_decode(aOut, sizeof(aOut), "ZWFzdXJlLg=="), 7);
	EXPECT_STREQ(aOut, "easure.XXXXXXXXX");
	str_copy(aOut, "XXXXXXXXXXXXXXXX", sizeof(aOut));
	EXPECT_EQ(str_base64_decode(aOut, sizeof(aOut), "YXN1cmUu"), 6);
	EXPECT_STREQ(aOut, "asure.XXXXXXXXXX");
	str_copy(aOut, "XXXXXXXXXXXXXXXX", sizeof(aOut));
	EXPECT_EQ(str_base64_decode(aOut, sizeof(aOut), "c3VyZS4="), 5);
	EXPECT_STREQ(aOut, "sure.XXXXXXXXXXX");
	str_copy(aOut, "XXXXXXXXXXXXXXXX", sizeof(aOut));
	EXPECT_EQ(str_base64_decode(aOut, sizeof(aOut), "////"), 3);
	EXPECT_STREQ(aOut, "\xff\xff\xffXXXXXXXXXXXXX");
}

TEST(Str, Base64DecodeError)
{
	char aBuf[128];
	// Wrong padding.
	EXPECT_LT(str_base64_decode(aBuf, sizeof(aBuf), "A"), 0);
	EXPECT_LT(str_base64_decode(aBuf, sizeof(aBuf), "AA"), 0);
	EXPECT_LT(str_base64_decode(aBuf, sizeof(aBuf), "AAA"), 0);
	EXPECT_LT(str_base64_decode(aBuf, sizeof(aBuf), "A==="), 0);
	EXPECT_LT(str_base64_decode(aBuf, sizeof(aBuf), "=AAA"), 0);
	EXPECT_LT(str_base64_decode(aBuf, sizeof(aBuf), "===="), 0);
	EXPECT_LT(str_base64_decode(aBuf, sizeof(aBuf), "AAA=AAAA"), 0);
	// Invalid characters.
	EXPECT_LT(str_base64_decode(aBuf, sizeof(aBuf), "----"), 0);
	EXPECT_LT(str_base64_decode(aBuf, sizeof(aBuf), "AAAA "), 0);
	EXPECT_LT(str_base64_decode(aBuf, sizeof(aBuf), "AAA "), 0);
	// Invalid padding values.
	EXPECT_LT(str_base64_decode(aBuf, sizeof(aBuf), "//=="), 0);
}

TEST(Str, Tokenize)
{
	char aTest[] = "GER,RUS,ZAF,BRA,CAN";
	const char *apOut[] = {"GER", "RUS", "ZAF", "BRA", "CAN"};
	char aBuf[4];

	int n = 0;
	for(const char *pTok = aTest; (pTok = str_next_token(pTok, ",", aBuf, sizeof(aBuf)));)
		EXPECT_STREQ(apOut[n++], aBuf);

	char aTest2[] = "";
	EXPECT_EQ(str_next_token(aTest2, ",", aBuf, sizeof(aBuf)), nullptr);

	char aTest3[] = "+b";
	str_next_token(aTest3, "+", aBuf, sizeof(aBuf));
	EXPECT_STREQ(aBuf, "b");
}

TEST(Str, InList)
{
	char aTest[] = "GER,RUS,ZAF,BRA,CAN";
	EXPECT_TRUE(str_in_list(aTest, ",", "GER"));
	EXPECT_TRUE(str_in_list(aTest, ",", "RUS"));
	EXPECT_TRUE(str_in_list(aTest, ",", "ZAF"));
	EXPECT_TRUE(str_in_list(aTest, ",", "BRA"));
	EXPECT_TRUE(str_in_list(aTest, ",", "CAN"));

	EXPECT_FALSE(str_in_list(aTest, ",", "CHN"));
	EXPECT_FALSE(str_in_list(aTest, ",", "R,R"));

	EXPECT_FALSE(str_in_list("abc,xyz", ",", "abcdef"));
	EXPECT_FALSE(str_in_list("", ",", ""));
	EXPECT_FALSE(str_in_list("", ",", "xyz"));

	EXPECT_TRUE(str_in_list("FOO,,BAR", ",", ""));
	EXPECT_TRUE(str_in_list("abc,,def", ",", "def"));
}

TEST(Str, StrFormat)
{
	char aBuf[4];
	EXPECT_EQ(str_format(aBuf, 4, "%d:", 9), 2);
	EXPECT_STREQ(aBuf, "9:");
	EXPECT_EQ(str_format(aBuf, 4, "%d: ", 9), 3);
	EXPECT_STREQ(aBuf, "9: ");
	EXPECT_EQ(str_format(aBuf, 4, "%d: ", 99), 3);
	EXPECT_STREQ(aBuf, "99:");
}

TEST(Str, StrFormatTruncate)
{
	const char *pStr = "DDNet最好了";
	char aBuf[64];
	str_format(aBuf, 7, "%s", pStr);
	EXPECT_STREQ(aBuf, "DDNet");
	str_format(aBuf, 8, "%s", pStr);
	EXPECT_STREQ(aBuf, "DDNet");
	str_format(aBuf, 9, "%s", pStr);
	EXPECT_STREQ(aBuf, "DDNet最");
	str_format(aBuf, 10, "%s", pStr);
	EXPECT_STREQ(aBuf, "DDNet最");
	str_format(aBuf, 11, "%s", pStr);
	EXPECT_STREQ(aBuf, "DDNet最");
	str_format(aBuf, 12, "%s", pStr);
	EXPECT_STREQ(aBuf, "DDNet最好");
	str_format(aBuf, 13, "%s", pStr);
	EXPECT_STREQ(aBuf, "DDNet最好");
	str_format(aBuf, 14, "%s", pStr);
	EXPECT_STREQ(aBuf, "DDNet最好");
	str_format(aBuf, 15, "%s", pStr);
	EXPECT_STREQ(aBuf, "DDNet最好了");
	str_format(aBuf, 16, "%s", pStr);
	EXPECT_STREQ(aBuf, "DDNet最好了");
}

TEST(Str, StrCopyNum)
{
	const char *pFoo = "Foobaré";
	char aBuf[64];
	str_utf8_truncate(aBuf, 3, pFoo, 1);
	EXPECT_STREQ(aBuf, "F");
	str_utf8_truncate(aBuf, 3, pFoo, 2);
	EXPECT_STREQ(aBuf, "Fo");
	str_utf8_truncate(aBuf, 3, pFoo, 3);
	EXPECT_STREQ(aBuf, "Fo");
	str_utf8_truncate(aBuf, sizeof(aBuf), pFoo, 6);
	EXPECT_STREQ(aBuf, "Foobar");
	str_utf8_truncate(aBuf, sizeof(aBuf), pFoo, 7);
	EXPECT_STREQ(aBuf, "Foobaré");
	str_utf8_truncate(aBuf, sizeof(aBuf), pFoo, 0);
	EXPECT_STREQ(aBuf, "");

	char aBuf2[8];
	str_utf8_truncate(aBuf2, sizeof(aBuf2), pFoo, 7);
	EXPECT_STREQ(aBuf2, "Foobar");
	char aBuf3[9];
	str_utf8_truncate(aBuf3, sizeof(aBuf3), pFoo, 7);
	EXPECT_STREQ(aBuf3, "Foobaré");
}

TEST(Str, StrCopy)
{
	const char *pStr = "DDNet最好了";
	char aBuf[64];
	str_copy(aBuf, pStr, 7);
	EXPECT_STREQ(aBuf, "DDNet");
	str_copy(aBuf, pStr, 8);
	EXPECT_STREQ(aBuf, "DDNet");
	str_copy(aBuf, pStr, 9);
	EXPECT_STREQ(aBuf, "DDNet最");
	str_copy(aBuf, pStr, 10);
	EXPECT_STREQ(aBuf, "DDNet最");
	str_copy(aBuf, pStr, 11);
	EXPECT_STREQ(aBuf, "DDNet最");
	str_copy(aBuf, pStr, 12);
	EXPECT_STREQ(aBuf, "DDNet最好");
	str_copy(aBuf, pStr, 13);
	EXPECT_STREQ(aBuf, "DDNet最好");
	str_copy(aBuf, pStr, 14);
	EXPECT_STREQ(aBuf, "DDNet最好");
	str_copy(aBuf, pStr, 15);
	EXPECT_STREQ(aBuf, "DDNet最好了");
	str_copy(aBuf, pStr, 16);
	EXPECT_STREQ(aBuf, "DDNet最好了");
}

TEST(Str, Utf8Stats)
{
	int Size, Count;

	str_utf8_stats("abc", 4, 3, &Size, &Count);
	EXPECT_EQ(Size, 3);
	EXPECT_EQ(Count, 3);

	str_utf8_stats("abc", 2, 3, &Size, &Count);
	EXPECT_EQ(Size, 1);
	EXPECT_EQ(Count, 1);

	str_utf8_stats("", 1, 0, &Size, &Count);
	EXPECT_EQ(Size, 0);
	EXPECT_EQ(Count, 0);

	str_utf8_stats("abcde", 6, 5, &Size, &Count);
	EXPECT_EQ(Size, 5);
	EXPECT_EQ(Count, 5);

	str_utf8_stats("любовь", 13, 6, &Size, &Count);
	EXPECT_EQ(Size, 12);
	EXPECT_EQ(Count, 6);

	str_utf8_stats("abc愛", 7, 4, &Size, &Count);
	EXPECT_EQ(Size, 6);
	EXPECT_EQ(Count, 4);

	str_utf8_stats("abc愛", 6, 4, &Size, &Count);
	EXPECT_EQ(Size, 3);
	EXPECT_EQ(Count, 3);

	str_utf8_stats("любовь", 13, 3, &Size, &Count);
	EXPECT_EQ(Size, 6);
	EXPECT_EQ(Count, 3);
}

TEST(Str, StrTime)
{
	char aBuf[32] = "foobar";

	EXPECT_EQ(str_time(123456, TIME_DAYS, aBuf, 0), -1);
	EXPECT_STREQ(aBuf, "foobar");

	EXPECT_EQ(str_time(123456, TIME_MINS_CENTISECS + 1, aBuf, sizeof(aBuf)), -1);
	EXPECT_STREQ(aBuf, "");

	EXPECT_EQ(str_time(-123456, TIME_MINS_CENTISECS, aBuf, sizeof(aBuf)), 8);
	EXPECT_STREQ(aBuf, "00:00.00");

	EXPECT_EQ(str_time(INT64_MAX, TIME_DAYS, aBuf, sizeof(aBuf)), 23);
	EXPECT_STREQ(aBuf, "1067519911673d 00:09:18");

	EXPECT_EQ(str_time(123456, TIME_DAYS, aBuf, sizeof(aBuf)), 5);
	EXPECT_STREQ(aBuf, "20:34");
	EXPECT_EQ(str_time(1234567, TIME_DAYS, aBuf, sizeof(aBuf)), 8);
	EXPECT_STREQ(aBuf, "03:25:45");
	EXPECT_EQ(str_time(12345678, TIME_DAYS, aBuf, sizeof(aBuf)), 11);
	EXPECT_STREQ(aBuf, "1d 10:17:36");

	EXPECT_EQ(str_time(123456, TIME_HOURS, aBuf, sizeof(aBuf)), 5);
	EXPECT_STREQ(aBuf, "20:34");
	EXPECT_EQ(str_time(1234567, TIME_HOURS, aBuf, sizeof(aBuf)), 8);
	EXPECT_STREQ(aBuf, "03:25:45");
	EXPECT_EQ(str_time(12345678, TIME_HOURS, aBuf, sizeof(aBuf)), 8);
	EXPECT_STREQ(aBuf, "34:17:36");

	EXPECT_EQ(str_time(123456, TIME_MINS, aBuf, sizeof(aBuf)), 5);
	EXPECT_STREQ(aBuf, "20:34");
	EXPECT_EQ(str_time(1234567, TIME_MINS, aBuf, sizeof(aBuf)), 6);
	EXPECT_STREQ(aBuf, "205:45");
	EXPECT_EQ(str_time(12345678, TIME_MINS, aBuf, sizeof(aBuf)), 7);
	EXPECT_STREQ(aBuf, "2057:36");

	EXPECT_EQ(str_time(123456, TIME_HOURS_CENTISECS, aBuf, sizeof(aBuf)), 8);
	EXPECT_STREQ(aBuf, "20:34.56");
	EXPECT_EQ(str_time(1234567, TIME_HOURS_CENTISECS, aBuf, sizeof(aBuf)), 11);
	EXPECT_STREQ(aBuf, "03:25:45.67");
	EXPECT_EQ(str_time(12345678, TIME_HOURS_CENTISECS, aBuf, sizeof(aBuf)), 11);
	EXPECT_STREQ(aBuf, "34:17:36.78");

	EXPECT_EQ(str_time(123456, TIME_MINS_CENTISECS, aBuf, sizeof(aBuf)), 8);
	EXPECT_STREQ(aBuf, "20:34.56");
	EXPECT_EQ(str_time(1234567, TIME_MINS_CENTISECS, aBuf, sizeof(aBuf)), 9);
	EXPECT_STREQ(aBuf, "205:45.67");
	EXPECT_EQ(str_time(12345678, TIME_MINS_CENTISECS, aBuf, sizeof(aBuf)), 10);
	EXPECT_STREQ(aBuf, "2057:36.78");
}

TEST(Str, StrTimeFloat)
{
	char aBuf[64];
	EXPECT_EQ(str_time_float(123456.78, TIME_DAYS, aBuf, sizeof(aBuf)), 11);
	EXPECT_STREQ(aBuf, "1d 10:17:36");

	EXPECT_EQ(str_time_float(12.16, TIME_HOURS_CENTISECS, aBuf, sizeof(aBuf)), 8);
	EXPECT_STREQ(aBuf, "00:12.16");
}
