#include <string.h>
#include <sc_unittest.h>
#include <sc_mmgr.h>
#include <sc_string.h>

static void UT_SC_string_strnlen(void);
static void UT_SC_string_strnlen_over(void);
static void UT_SC_string_strdup(void);
static void UT_SC_string_strndup(void);
static void UT_SC_string_strndup_over(void);
static void UT_SC_string_strndup_null(void);
static void UT_SC_string_strndup_nodbg(void);
static void UT_SC_string_strdupa(void);
static void UT_SC_string_strndupa(void);
static void UT_SC_string_strndupa_over(void);
static void UT_SC_string_strndupa_null(void);
static void UT_SC_string_memindex(void);
static void UT_SC_string_memindex_targetNull(void);
static void UT_SC_string_memindex_searchNull(void);
static void UT_SC_string_memindex_notfound(void);
static void UT_SC_string_indexOf(void);
static void UT_SC_string_lastIndexOf(void);
static void UT_SC_string_new(void);
static void UT_SC_string_append(void);
static void UT_SC_string_setLength(void);
static void UT_SC_string_isEmpty(void);



void UT_regist_sc_string(void)
{
	SC_Unittest_add("SC_string_strnlen"					, UT_SC_string_strnlen);
	SC_Unittest_add("SC_string_strnlen_over"			, UT_SC_string_strnlen_over);
	SC_Unittest_add("SC_string_strdup"					, UT_SC_string_strdup);
	SC_Unittest_add("SC_string_strndup"				 	, UT_SC_string_strndup);
	SC_Unittest_add("SC_string_strndup_over"			, UT_SC_string_strndup_over);
	SC_Unittest_add("SC_string_strndup_null"			, UT_SC_string_strndup_null);
	SC_Unittest_add("SC_string_strndup_nodbg"			, UT_SC_string_strndup_nodbg);
	SC_Unittest_add("SC_string_strdupa"					, UT_SC_string_strdupa);
	SC_Unittest_add("SC_string_strndupa"				, UT_SC_string_strndupa);
	SC_Unittest_add("SC_string_strndupa_over"			, UT_SC_string_strndupa_over);
	SC_Unittest_add("SC_string_strndupa_null"			, UT_SC_string_strndupa_null);
	SC_Unittest_add("SC_string_memindex"				, UT_SC_string_memindex);
	SC_Unittest_add("SC_string_memindex_targetNull"		, UT_SC_string_memindex_targetNull);
	SC_Unittest_add("SC_string_memindex_searchNull"		, UT_SC_string_memindex_searchNull);
	SC_Unittest_add("SC_string_memindex_notfound"		, UT_SC_string_memindex_notfound);
	SC_Unittest_add("SC_string_indexOf"					, UT_SC_string_indexOf);
	SC_Unittest_add("SC_string_lastIndexOf"				, UT_SC_string_lastIndexOf);
	SC_Unittest_add("SC_string_new"						, UT_SC_string_new);
	SC_Unittest_add("SC_string_append"					, UT_SC_string_append);
	SC_Unittest_add("SC_string_setLength"				, UT_SC_string_setLength);
	SC_Unittest_add("SC_string_isEmpty"					, UT_SC_string_isEmpty);
}

static
void UT_SC_string_strnlen(void)
{
	size_t size = strnlen("ABCDEFG", 10);
	SC_assertNumber(7, size);
}
void UT_SC_string_strnlen_over(void)
{
	size_t size = strnlen("ABCDEFG", 5);
	SC_assertNumber(5, size);
}

static
void UT_SC_string_strdup(void)
{
	char* ret = strdup("ABCDEFG");
	SC_assertString("ABCDEFG", ret);
	free(ret);
}

static
void UT_SC_string_strndup(void)
{
	char* ret = strndup("ABCDEFG", 10);
	SC_assertString("ABCDEFG", ret);
	free(ret);
}

static
void UT_SC_string_strndup_over(void)
{
	char* ret = strndup("ABCDEFG", 5);
	SC_assertString("ABCDE", ret);
	free(ret);
}

static
void UT_SC_string_strndup_null(void)
{
	char* ret = strndup(NULL, 5);
	SC_assert(ret == NULL);
}

static
void UT_SC_string_strndup_nodbg(void)
{
	char* ret = SC_strndup("ABC", 5, NULL, 0);
	SC_assertString("ABC", ret);
	free(ret);
}

static
void UT_SC_string_strdupa(void)
{
	char* ret = strdupa("ABCDEFG");
	SC_assertString("ABCDEFG", ret);
}

static
void UT_SC_string_strndupa(void)
{
	char* ret = strndupa("ABCDEFG", 10);
	SC_assertString("ABCDEFG", ret);
}

static
void UT_SC_string_strndupa_over(void)
{
	char* ret = strndupa("ABCDEFG", 5);
	SC_assertString("ABCDE", ret);
}

static
void UT_SC_string_strndupa_null(void)
{
	char* ret = strndupa(NULL, 5);
	SC_assert(ret == NULL);
}

static const char UT_SC_STRING_SEARCH_TARGET[] = {
	'A', 'B', 'C', 'D', 'E', '\0',
	'F', 'G', 'H', 'I', 'J', 'K',
	'L', 'M', 'N', '\0'
};

static
void UT_SC_string_memindex(void)
{
	const char* ptr = SC_memindex(
			UT_SC_STRING_SEARCH_TARGET,
			sizeof(UT_SC_STRING_SEARCH_TARGET),
			"GHI", strlen("GHI"));
	SC_assertString("GHIJKLMN", ptr);

}

static
void UT_SC_string_memindex_targetNull(void)
{
	const char* ptr = SC_memindex(
			NULL,
			sizeof(UT_SC_STRING_SEARCH_TARGET),
			"GHI", strlen("GHI"));
	SC_assert(NULL == ptr);
}

static
void UT_SC_string_memindex_searchNull(void)
{
	const char* ptr = SC_memindex(
			UT_SC_STRING_SEARCH_TARGET,
			sizeof(UT_SC_STRING_SEARCH_TARGET),
			NULL, strlen("GHI"));
	SC_assertString("ABCDE", ptr);
}

static
void UT_SC_string_memindex_notfound(void)
{
	const char* ptr = SC_memindex(
			UT_SC_STRING_SEARCH_TARGET,
			sizeof(UT_SC_STRING_SEARCH_TARGET),
			"XYZ" , strlen("XYZ"));
	SC_assert(NULL == ptr);
}

static
void UT_SC_string_indexOf(void)
{
	char* data = "ABCDEFGHIJKLMNABCDEFG";
	int   tmpBase;
	int   pos;
	pos = SC_indexOf(data, "DEF");
	SC_assertString("DEFGHIJKLMNABCDEFG", &data[pos]);

	tmpBase = pos + 1;
	pos     = SC_indexOf(&data[tmpBase], "DEF");
	SC_assertString("DEFG", &data[tmpBase + pos]);

	pos     = SC_indexOf(data, "XYZ");
	SC_assertNumber(-1, pos);
}

static
void UT_SC_string_lastIndexOf(void)
{
	char* data = "ABCDEFGHIJKLMNABCDEFG";
	int   pos;
	pos = SC_lastIndexOf(data, "DEF");
	SC_assertString("DEFG", &data[pos]);

	pos = SC_lastIndexOf(data, "XYZ");
	SC_assertNumber(-1, pos);
}

static
void UT_SC_string_new(void)
{
	SC_String* str = SC_String_new(1);
	SC_assert(NULL != str);
	SC_String_delete(str);
}

static
void UT_SC_string_append(void)
{
	SC_String* str = SC_String_new(4);
	str->append(str, "AB");
	SC_assertString("AB", str->buffer);
	SC_assertNumber(4, str->_bufSize);
	str->append(str, "CD");
	SC_assertString("ABCD", str->buffer);
	SC_assertNumber(10, str->_bufSize);
	str->append(str, "EF");
	SC_assertString("ABCDEF", str->buffer);
	SC_assertNumber(10, str->_bufSize);
	str->clear(str);
	str->append(str, "XYZXYZ");
	SC_assertString("XYZXYZ", str->buffer);
	SC_assertNumber(10, str->_bufSize);
	SC_String_delete(str);
}

static
void UT_SC_string_setLength(void)
{
	SC_String* str = SC_String_new(4);
	str->append(str, "ABC");
	str->setLength(str, 2);
	SC_assertString("AB", str->buffer);

	str->setLength(str, 3);
	SC_assertString("AB", str->buffer);

	SC_String_delete(str);
}

static
void UT_SC_string_isEmpty(void)
{
	SC_String* str = SC_String_new(4);
	SC_assert(str->isEmpty(str));

	str->append(str, "ab");
	SC_assert(!str->isEmpty(str));

	SC_String_delete(str);
}

