#include "unittest/TestSuite.h" #include "utilities/printfFormats.h" #include "utilities/IOUtilities.h" #include #include #include #include #include #include #include #define assertBytesMatch(expectedBytes, actualBytes, length) { \ char * _failString; \ unsigned int _index; \ \ _failString = malloc(strlen("Expected but got") + 3 * (length) * 2 + 1); \ _failString[0] = 0; \ strcat(_failString, "Expected"); \ for (_index = 0; _index < (length); _index++) { \ sprintf(_failString + strlen(_failString), " %02X", ((unsigned char *) (expectedBytes))[_index]); \ } \ strcat(_failString, " but got"); \ for (_index = 0; _index < (length); _index++) { \ sprintf(_failString + strlen(_failString), " %02X", ((unsigned char *) (actualBytes))[_index]); \ } \ \ TestCase_assert(!memcmp((expectedBytes), (actualBytes), (length)), "%s", _failString); \ \ free(_failString); \ } #ifdef WIN32 #include static int mkstemp(char * template) { int result = -1; mktemp(template); result = open(template, O_RDWR | O_BINARY | O_CREAT | O_EXCL | _O_SHORT_LIVED, _S_IREAD | _S_IWRITE); return result; } #endif static void testMemreadContextInit() { struct memreadContext context; char * data1 = "abcd", * data2 = "efg"; context = memreadContextInit(data1, 4); TestCase_assert(context.data == data1, "Expected %p but got %p", data1, context.data); TestCase_assert(context.length == 4, "Expected 4 but got %d", (int) context.length); TestCase_assert(context.position == 0, "Expected 0 but got %d", (int) context.position); context = memreadContextInit(data2, 3); TestCase_assert(context.data == data2, "Expected %p but got %p", data2, context.data); TestCase_assert(context.length == 3, "Expected 3 but got %d", (int) context.length); TestCase_assert(context.position == 0, "Expected 0 but got %d", (int) context.position); } static void testMemread() { char target[4]; char expectedTarget1[4] = {'a', 'b', 'c', 'd'}, expectedTarget2[4] = {'1', '2', '3', '\x00'}; struct memreadContext context; bool result; context = memreadContextInit("abcd1234", 8); memset(target, 0, 4); result = memread(&context, 4, target); TestCase_assert(result, "Expected true but got false"); TestCase_assert(context.position == 4, "Expected 4 but got %d", (int) context.position); assertBytesMatch(expectedTarget1, target, 4); memset(target, 0, 4); result = memread(&context, 3, target); TestCase_assert(result, "Expected true but got false"); TestCase_assert(context.position == 7, "Expected 7 but got %d", (int) context.position); assertBytesMatch(expectedTarget2, target, 4); result = memread(&context, 2, NULL); TestCase_assert(!result, "Expected false but got true"); TestCase_assert(context.position == 7, "Expected 7 but got %d", (int) context.position); result = memread(&context, 1, NULL); TestCase_assert(result, "Expected true but got false"); TestCase_assert(context.position == 8, "Expected 8 but got %d", (int) context.position); } static void testMemwriteContextInit() { struct memwriteContext context; char * data1 = "abcd", * data2 = "efg"; context = memwriteContextInit(data1, 4, 5, false); TestCase_assert(context.data == data1, "Expected %p but got %p", data1, context.data); TestCase_assert(context.length == 4, "Expected 4 but got %d", (int) context.length); TestCase_assert(context.allocatedSize == 5, "Expected 5 but got %d", (int) context.allocatedSize); TestCase_assert(context.position == 0, "Expected 0 but got %d", (int) context.position); TestCase_assert(!context.realloc, "Expected false but got true"); context = memwriteContextInit(data2, 3, 4, true); TestCase_assert(context.data == data2, "Expected %p but got %p", data2, context.data); TestCase_assert(context.length == 3, "Expected 3 but got %d", (int) context.length); TestCase_assert(context.allocatedSize == 4, "Expected 4 but got %d", (int) context.allocatedSize); TestCase_assert(context.position == 0, "Expected 0 but got %d", (int) context.position); TestCase_assert(context.realloc, "Expected true but got false"); } static void testMemwrite() { struct memwriteContext context; char target[4]; bool result; memset(target, 0, 4); context = memwriteContextInit(target, 3, 4, false); result = memwrite(&context, 2, "fg"); TestCase_assert(result, "Expected true but got false"); TestCase_assert(context.length == 3, "Expected 3 but got %d", (int) context.length); TestCase_assert(context.position == 2, "Expected 2 but got %d", (int) context.position); assertBytesMatch("fg\x00\x00", target, 4); result = memwrite(&context, 3, "sfd"); TestCase_assert(!result, "Expected false but got true"); TestCase_assert(context.length == 3, "Expected 3 but got %d", (int) context.length); TestCase_assert(context.position == 2, "Expected 2 but got %d", (int) context.position); assertBytesMatch("fg\x00\x00", target, 4); result = memwrite(&context, 1, "s"); TestCase_assert(result, "Expected true but got false"); TestCase_assert(context.length == 3, "Expected 3 but got %d", (int) context.length); TestCase_assert(context.position == 3, "Expected 3 but got %d", (int) context.position); assertBytesMatch("fgs\x00", target, 4); target[3] = 0xFF; result = memwrite(&context, 1, NULL); TestCase_assert(result, "Expected true but got false"); TestCase_assert(context.length == 4, "Expected 4 but got %d", (int) context.length); TestCase_assert(context.position == 4, "Expected 4 but got %d", (int) context.position); assertBytesMatch("fgs\x00", target, 4); context = memwriteContextInit(malloc(1), 0, 1, true); result = memwrite(&context, 2, "aa"); TestCase_assert(result, "Expected true but got false"); TestCase_assert(context.length == 2, "Expected 2 but got %d", (int) context.length); TestCase_assert(context.allocatedSize >= 2, "Expected >= 2 but got %d", (int) context.allocatedSize); TestCase_assert(context.position == 2, "Expected 2 but got %d", (int) context.position); assertBytesMatch("aa", context.data, 2); result = memwrite(&context, 5, NULL); TestCase_assert(result, "Expected true but got false"); TestCase_assert(context.length == 7, "Expected 7 but got %d", (int) context.length); TestCase_assert(context.allocatedSize >= 7, "Expected >= 7 but got %d", (int) context.allocatedSize); TestCase_assert(context.position == 7, "Expected 7 but got %d", (int) context.position); assertBytesMatch("aa\x00\x00\x00\x00\x00", context.data, 7); context.position = 6; result = memwrite(&context, 3, "baz"); TestCase_assert(result, "Expected true but got false"); TestCase_assert(context.length == 9, "Expected 9 but got %d", (int) context.length); TestCase_assert(context.allocatedSize >= 9, "Expected >= 9 but got %d", (int) context.allocatedSize); TestCase_assert(context.position == 9, "Expected 9 but got %d", (int) context.position); assertBytesMatch("aa\x00\x00\x00\x00""baz", context.data, 9); free(context.data); context = memwriteContextInit(NULL, 0, 0, true); result = memwrite(&context, 2, "bb"); TestCase_assert(result, "Expected true but got false"); TestCase_assert(context.length == 2, "Expected 2 but got %d", (int) context.length); TestCase_assert(context.allocatedSize == 2, "Expected 2 but got %d", (int) context.allocatedSize); TestCase_assert(context.position == 2, "Expected 2 but got %d", (int) context.position); assertBytesMatch("bb", context.data, 2); char * string = "Hello"; result = memwrite_str(&context, string); TestCase_assertBoolTrue(result); TestCase_assertSizeEqual(context.length, 7); TestCase_assertSizeEqual(context.position, 7); assertBytesMatch("bbHello", context.data, 7); result = memwrite_strl(&context, " world"); TestCase_assertBoolTrue(result); TestCase_assertSizeEqual(context.length, 13); TestCase_assertSizeEqual(context.position, 13); assertBytesMatch("bbHello world", context.data, 13); free(context.data); } static void testReadFileSimple() { char fileName[10]; int fileHandle; size_t length; void * result; FILE * file; strcpy(fileName, "tmpXXXXXX"); fileHandle = mkstemp(fileName); close(fileHandle); unlink(fileName); result = readFileSimple(fileName, NULL); TestCase_assert(result == NULL, "Expected NULL but got %p", result); strcpy(fileName, "tmpXXXXXX"); fileHandle = mkstemp(fileName); file = fdopen(fileHandle, "wb"); fprintf(file, "foo bar\nbaz"); fclose(file); result = readFileSimple(fileName, &length); unlink(fileName); TestCase_assert(result != NULL, "Expected non-NULL but got NULL"); TestCase_assert(length == 11, "Expected 11 but got %d", (int) length); assertBytesMatch("foo bar\nbaz", result, 11); strcpy(fileName, "tmpXXXXXX"); fileHandle = mkstemp(fileName); file = fdopen(fileHandle, "wb"); fprintf(file, "Hello, world!"); fclose(file); result = readFileSimple(fileName, &length); unlink(fileName); TestCase_assert(result != NULL, "Expected non-NULL but got NULL"); TestCase_assert(length == 13, "Expected 13 but got %d", (int) length); assertBytesMatch("Hello, world!", result, 13); } static void testWriteFileSimple() { char fileName[10]; int fileHandle; bool result; FILE * file; size_t fileLength; char * fileContents; strcpy(fileName, "tmpXXXXXX"); fileHandle = mkstemp(fileName); result = writeFileSimple(fileName, "foo bar\nbaz", 11); file = fdopen(fileHandle, "rb"); TestCase_assert(file != NULL, "writeFileSimple failed to create target file"); fseek(file, 0, SEEK_END); fileLength = ftell(file); fseek(file, 0, SEEK_SET); fileContents = malloc(fileLength); fread(fileContents, 1, fileLength, file); fclose(file); unlink(fileName); TestCase_assert(result, "Expected true but got false"); TestCase_assert(fileLength == 11, "Expected 11 but got %d", (int) fileLength); assertBytesMatch("foo bar\nbaz", fileContents, 11); free(fileContents); strcpy(fileName, "tmpXXXXXX"); fileHandle = mkstemp(fileName); result = writeFileSimple(fileName, "Hello, world!", 13); file = fdopen(fileHandle, "rb"); TestCase_assert(file != NULL, "writeFileSimple failed to create target file"); fseek(file, 0, SEEK_END); fileLength = ftell(file); fseek(file, 0, SEEK_SET); fileContents = malloc(fileLength); fread(fileContents, 1, fileLength, file); fclose(file); unlink(fileName); TestCase_assert(result, "Expected true but got false"); TestCase_assert(fileLength == 13, "Expected 13 but got %d", (int) fileLength); assertBytesMatch("Hello, world!", fileContents, 13); free(fileContents); } static void testWriteFileAtomic() { char fileName[10]; int fileHandle; bool result; FILE * file; size_t fileLength; char * fileContents; strcpy(fileName, "tmpXXXXXX"); fileHandle = mkstemp(fileName); close(fileHandle); result = writeFileAtomic(fileName, "foo bar\nbaz", 11); file = fopen(fileName, "rb"); TestCase_assert(file != NULL, "writeFileAtomic failed to create target file"); fseek(file, 0, SEEK_END); fileLength = ftell(file); fseek(file, 0, SEEK_SET); fileContents = malloc(fileLength); fread(fileContents, 1, fileLength, file); fclose(file); unlink(fileName); TestCase_assert(result, "Expected true but got false"); TestCase_assert(fileLength == 11, "Expected 11 but got %d", (int) fileLength); assertBytesMatch("foo bar\nbaz", fileContents, 11); free(fileContents); strcpy(fileName, "tmpXXXXXX"); fileHandle = mkstemp(fileName); close(fileHandle); result = writeFileAtomic(fileName, "Hello, world!", 13); file = fopen(fileName, "rb"); TestCase_assert(file != NULL, "writeFileAtomic failed to create target file"); fseek(file, 0, SEEK_END); fileLength = ftell(file); fseek(file, 0, SEEK_SET); fileContents = malloc(fileLength); fread(fileContents, 1, fileLength, file); fclose(file); unlink(fileName); TestCase_assert(result, "Expected true but got false"); TestCase_assert(fileLength == 13, "Expected 13 but got %d", (int) fileLength); assertBytesMatch("Hello, world!", fileContents, 13); free(fileContents); } static void testTemporaryFilePath() { int fd; const char * template, * path; const char * uniqueString; bool success; FILE * file; size_t fileLength; char * fileContents; template = "tmpXXXXXX"; uniqueString = "Unique string 1"; fd = -1; path = temporaryFilePath(template, &fd); TestCase_assert(path != NULL, "temporaryFilePath unexpectedly returned NULL"); TestCase_assert(strlen(path) >= strlen(template), "temporaryFilePath returned a shorter path (\"%s\") than the provided template", path); TestCase_assert(!strncmp(path + strlen(path) - strlen(template), template, 3), "Template prefix not preserved in path (\"%s\")", path); TestCase_assert(fd != -1, "temporaryFilePath didn't return a file descriptor"); success = writeFileSimple(path, uniqueString, strlen(uniqueString)); TestCase_assert(success, "Failed to write to returned path \"%s\"", path); file = fdopen(fd, "rb"); TestCase_assert(file != NULL, "temporaryFilePath didn't return a file descriptor that could be opened with fdopen"); fseek(file, 0, SEEK_END); fileLength = ftell(file); TestCase_assert(fileLength == strlen(uniqueString), "File length (%d) didn't match length of string written to path (%d)", (int) fileLength, (int) strlen(uniqueString)); fseek(file, 0, SEEK_SET); fileContents = malloc(fileLength); fread(fileContents, 1, fileLength, file); TestCase_assert(!memcmp(fileContents, uniqueString, fileLength), "File contents \"%.*s\" didn't match expected string \"%s\"", (int) fileLength, fileContents, uniqueString); fclose(file); unlink(path); template = "helloXXXXXX"; uniqueString = "Unique string 2"; fd = -1; path = temporaryFilePath(template, &fd); TestCase_assert(path != NULL, "temporaryFilePath unexpectedly returned NULL"); TestCase_assert(strlen(path) >= strlen(template), "temporaryFilePath returned a shorter path (\"%s\") than the provided template", path); TestCase_assert(!strncmp(path + strlen(path) - strlen(template), template, 5), "Template prefix not preserved in path (\"%s\")", path); TestCase_assert(fd != -1, "temporaryFilePath didn't return a file descriptor"); success = writeFileSimple(path, uniqueString, strlen(uniqueString)); TestCase_assert(success, "Failed to write to returned path \"%s\"", path); file = fdopen(fd, "rb"); TestCase_assert(file != NULL, "temporaryFilePath didn't return a file descriptor that could be opened with fdopen"); fseek(file, 0, SEEK_END); fileLength = ftell(file); TestCase_assert(fileLength == strlen(uniqueString), "File length (%d) didn't match length of string written to path (%d)", (int) fileLength, (int) strlen(uniqueString)); fseek(file, 0, SEEK_SET); fileContents = malloc(fileLength); fread(fileContents, 1, fileLength, file); TestCase_assert(!memcmp(fileContents, uniqueString, fileLength), "File contents \"%.*s\" didn't match expected string \"%s\"", (int) fileLength, fileContents, uniqueString); fclose(file); unlink(path); } static void testFilePathFunctions() { const char * path, * result; path = "abcd"; result = getFileExtension(path); TestCase_assertStringPointerEqual(result, path + 4); path = "Hello.txt"; result = getFileExtension(path); TestCase_assertStringPointerEqual(result, path + 6); path = "/path/to/Hello.txt"; result = getFileExtension(path); TestCase_assertStringPointerEqual(result, path + 15); path = "/test.dir/"; result = getFileExtension(path); TestCase_assertStringPointerEqual(result, path + 10); path = ".ext"; result = getFileExtension(path); TestCase_assertStringPointerEqual(result, path + 1); path = "/hello/test.dir/name"; result = getFileExtension(path); TestCase_assertStringPointerEqual(result, path + 20); path = "test.a"; result = getBaseName(path); TestCase_assertStringEqual(result, "test"); path = "test2.txt"; result = getBaseName(path); TestCase_assertStringEqual(result, "test2"); path = "test"; result = getBaseName(path); TestCase_assertStringEqual(result, "test"); path = "/hello/test.dir/name.ext"; result = getBaseName(path); TestCase_assertStringEqual(result, "/hello/test.dir/name"); path = "/hello/test.dir/name"; result = getBaseName(path); TestCase_assertStringEqual(result, "/hello/test.dir/name"); path = ""; result = getBaseName(path); TestCase_assertStringEqual(result, ""); path = "abcd"; result = getLastPathComponent(path); TestCase_assertStringPointerEqual(result, path); path = "/path/to/Hello.txt"; result = getLastPathComponent(path); TestCase_assertStringPointerEqual(result, path + 9); path = "local/path/to/a directory/"; result = getLastPathComponent(path); TestCase_assertStringPointerEqual(result, path + 14); path = "/"; result = getLastPathComponent(path); TestCase_assertStringPointerEqual(result, path); path = "abcd"; result = getDirectory(path); TestCase_assertStringEqual(result, ""); path = "abcd/efgh"; result = getDirectory(path); TestCase_assertStringEqual(result, "abcd/"); path = "/path/to/something"; result = getDirectory(path); TestCase_assertStringEqual(result, "/path/to/"); path = "/path"; result = getDirectory(path); TestCase_assertStringEqual(result, "/"); path = "/"; result = getDirectory(path); TestCase_assertStringEqual(result, "/"); #if defined(STEM_PLATFORM_windows) path = "C:\\path\\to\\Hello.txt"; result = getFileExtension(path); TestCase_assertStringPointerEqual(result, path + 17); path = "\\test.dir\\"; result = getFileExtension(path); TestCase_assertStringPointerEqual(result, path + 10); path = "D:\\path\\to\\Hello.txt"; result = getLastPathComponent(path); TestCase_assertStringPointerEqual(result, path + 11); path = "local\\path\\to\\a directory\\"; result = getLastPathComponent(path); TestCase_assertStringPointerEqual(result, path + 14); path = "F:\\"; result = getLastPathComponent(path); TestCase_assertStringPointerEqual(result, path); path = "G:"; result = getLastPathComponent(path); TestCase_assertStringPointerEqual(result, path); path = "abcd\\efgh"; result = getDirectory(path); TestCase_assertStringEqual(result, "abcd\\"); path = "\\path\\to\\something"; result = getDirectory(path); TestCase_assertStringEqual(result, "\\path\\to\\"); path = "C:\\path\\to\\something"; result = getDirectory(path); TestCase_assertStringEqual(result, "C:\\path\\to\\"); path = "\\path"; result = getDirectory(path); TestCase_assertStringEqual(result, "\\"); path = "D:\\path"; result = getDirectory(path); TestCase_assertStringEqual(result, "D:\\"); path = "\\"; result = getDirectory(path); TestCase_assertStringEqual(result, "\\"); path = "A:\\"; result = getDirectory(path); TestCase_assertStringEqual(result, "A:\\"); path = "a:\\"; result = getDirectory(path); TestCase_assertStringEqual(result, "a:\\"); path = "Z:"; result = getDirectory(path); TestCase_assertStringEqual(result, "Z:"); path = "z:"; result = getDirectory(path); TestCase_assertStringEqual(result, "z:"); path = "D:/"; result = getDirectory(path); TestCase_assertStringEqual(result, "D:/"); #endif } static void testEndianSwapping() { uint16_t value16; uint32_t value32; uint64_t value64; value16 = swapEndian16(0x0100); TestCase_assert(value16 == 0x1, "Expected 0x1 but got 0x%X", value16); value16 = swapEndian16(0x0203); TestCase_assert(value16 == 0x302, "Expected 0x302 but got 0x%X", value16); value16 = swapEndian16(0x0001); TestCase_assert(value16 == 0x100, "Expected 0x100 but got 0x%X", value16); value16 = swapEndian16(0x0302); TestCase_assert(value16 == 0x203, "Expected 0x203 but got 0x%X", value16); value32 = swapEndian32(0x01000000); TestCase_assert(value32 == 0x1, "Expected 0x1 but got 0x%X", value32); value32 = swapEndian32(0x02030405); TestCase_assert(value32 == 0x5040302, "Expected 0x5040302 but got 0x%X", value32); value32 = swapEndian32(0x00000001); TestCase_assert(value32 == 0x1000000, "Expected 0x1000000 but got 0x%X", value32); value32 = swapEndian32(0x05040302); TestCase_assert(value32 == 0x2030405, "Expected 0x2030405 but got 0x%X", value32); value64 = swapEndian64(0x0100000000000000ull); TestCase_assert(value64 == 0x1, "Expected 0x1 but got 0x" XINT64_FORMAT, value64); value64 = swapEndian64(0x0203040506070809ull); TestCase_assert(value64 == 0x908070605040302ull, "Expected 0x908070605040302 but got 0x" XINT64_FORMAT, value64); value64 = swapEndian64(0x0000000000000001ull); TestCase_assert(value64 == 0x100000000000000ull, "Expected 0x100000000000000 but got 0x" XINT64_FORMAT, value64); value64 = swapEndian64(0x0908070605040302ull); TestCase_assert(value64 == 0x203040506070809ull, "Expected 0x203040506070809 but got 0x" XINT64_FORMAT, value64); } static void vsnprintfTest(char * string, size_t size, const char * format, ...) { va_list args; va_start(args, format); vsnprintf_safe(string, size, format, args); va_end(args); } static void testSafeStringFunctions() { char string[16]; string[15] = 0; memset(string, '*', 15); snprintf_safe(string, 14, "Hello, %s!", "world"); TestCase_assertStringEqual(string, "Hello, world!"); memset(string, '*', 15); snprintf_safe(string, 6, "Hello, %s!", "world"); TestCase_assertStringEqual(string, "Hello"); memset(string, '*', 15); vsnprintfTest(string, 14, "Hello, %s!", "world"); TestCase_assertStringEqual(string, "Hello, world!"); memset(string, '*', 15); vsnprintfTest(string, 6, "Hello, %s!", "world"); TestCase_assertStringEqual(string, "Hello"); memset(string, '*', 15); string[2] = 0; snprintf_append(string, 15, "%d", 1); TestCase_assertStringEqual(string, "**1"); memset(string, '*', 15); string[3] = 0; snprintf_append(string, 15, "%d", 20); TestCase_assertStringEqual(string, "***20"); memset(string, '*', 15); string[3] = 0; snprintf_append(string, 5, "%d", 20); TestCase_assertStringEqual(string, "***2"); memset(string, '*', 15); strncpy_safe(string, "Hello, world!", 14); TestCase_assertStringEqual(string, "Hello, world!"); memset(string, '*', 15); strncpy_safe(string, "Hello, world!", 6); TestCase_assertStringEqual(string, "Hello"); char * duplicatedString; duplicatedString = strdup_nullSafe(NULL); TestCase_assertPointerNULL(duplicatedString); duplicatedString = strdup_nullSafe(string); TestCase_assertPointerNonNULL(duplicatedString); TestCase_assertPointerUnequal(duplicatedString, (char *) string); TestCase_assertStringEqual(duplicatedString, "Hello"); free(duplicatedString); int cmpResult = strcmp_nullSafe(NULL, NULL); TestCase_assertIntEqual(cmpResult, 0); cmpResult = strcmp_nullSafe(NULL, "a"); TestCase_assertIntEqual(cmpResult, -1); cmpResult = strcmp_nullSafe("a", NULL); TestCase_assertIntEqual(cmpResult, 1); cmpResult = strcmp_nullSafe("a", "a"); TestCase_assertIntEqual(cmpResult, 0); cmpResult = strcmp_nullSafe("a", "b"); TestCase_assertIntEqual(cmpResult, -1); cmpResult = strcmp_nullSafe("b", "a"); TestCase_assertIntEqual(cmpResult, 1); char unterminated[6] = {'a', 'b', 'c', 'd', 'e', 'f'}; duplicatedString = strdup_length(unterminated, 3); TestCase_assertStringEqual(duplicatedString, "abc"); free(duplicatedString); duplicatedString = strdup_length(unterminated, 6); TestCase_assertStringEqual(duplicatedString, "abcdef"); free(duplicatedString); } static void testMemdup(void) { char bytes[4] = {1, 3, 5, 2}; char * result; result = memdup(bytes, 0); TestCase_assertPointerNULL(result); result = memdup(bytes, 2); TestCase_assertPointerNonNULL(result); TestCase_assertPointerUnequal(result, (char *) bytes); TestCase_assert(!memcmp(result, bytes, 2), "Expected {1, 3} but got {%d, %d}", bytes[0], bytes[1]); free(result); result = memdup(bytes, 4); TestCase_assertPointerNonNULL(result); TestCase_assertPointerUnequal(result, (char *) bytes); TestCase_assert(!memcmp(result, bytes, 4), "Expected {1, 3, 5, 2} but got {%d, %d, %d, %d}", bytes[0], bytes[1], bytes[2], bytes[3]); free(result); } static void testMemappend(void) { char buffer[12]; memset(buffer, 0, sizeof(buffer)); size_t result = memappend(buffer, 0, "abcdef", 5); TestCase_assertSizeEqual(result, 5); TestCase_assertBytesEqual(buffer, "abcde", 6); result = memappend(buffer, 5, "fghi", 4); TestCase_assertSizeEqual(result, 9); TestCase_assertBytesEqual(buffer, "abcdefghi", 10); const char * string = "Hello"; result = memappend_str(buffer, 2, string); TestCase_assertSizeEqual(result, 7); TestCase_assertBytesEqual(buffer, "abHellohi", 10); result = memappend_strl(buffer, 2, "world"); TestCase_assertSizeEqual(result, 7); TestCase_assertBytesEqual(buffer, "abworldhi", 10); } static void testMemnappend(void) { char buffer[12]; memset(buffer, 0, sizeof(buffer)); size_t result = memnappend(buffer, 0, sizeof(buffer), "abcdef", 5); TestCase_assertSizeEqual(result, 5); TestCase_assertBytesEqual(buffer, "abcde", 6); result = memnappend(buffer, 5, sizeof(buffer), "fghi", 4); TestCase_assertSizeEqual(result, 9); TestCase_assertBytesEqual(buffer, "abcdefghi", 10); const char * string = "Hello"; result = memnappend_str(buffer, 2, sizeof(buffer), string); TestCase_assertSizeEqual(result, 7); TestCase_assertBytesEqual(buffer, "abHellohi", 10); result = memnappend_strl(buffer, 2, sizeof(buffer), "world"); TestCase_assertSizeEqual(result, 7); TestCase_assertBytesEqual(buffer, "abworldhi", 10); result = memnappend(buffer, 1, 2, "XX", 1); TestCase_assertSizeEqual(result, 2); TestCase_assertBytesEqual(buffer, "aXw", 3); result = memnappend(buffer, 2, 1, "hi", 2); TestCase_assertSizeEqual(result, 1); TestCase_assertBytesEqual(buffer, "aXw", 3); result = memnappend_str(buffer, 1, 2, string); TestCase_assertSizeEqual(result, 2); TestCase_assertBytesEqual(buffer, "aHw", 3); result = memnappend_strl(buffer, 1, 2, "zz"); TestCase_assertSizeEqual(result, 2); TestCase_assertBytesEqual(buffer, "azw", 3); result = memnterminate(buffer, 2, 3); TestCase_assertSizeEqual(result, 2); TestCase_assertBytesEqual(buffer, "az", 3); result = memnterminate(buffer, 2, 2); TestCase_assertSizeEqual(result, 1); TestCase_assertBytesEqual(buffer, "a", 2); buffer[1] = ';'; result = memnterminate(buffer, 1, 2); TestCase_assertSizeEqual(result, 1); TestCase_assertBytesEqual(buffer, "a", 2); result = memnappend_snprintf(buffer, 1, 5, "%u", 123); TestCase_assertSizeEqual(result, 4); TestCase_assertBytesEqual(buffer, "a123", 5); result = memnappend_snprintf(buffer, 1, 4, "%u", 456); TestCase_assertSizeEqual(result, 3); TestCase_assertBytesEqual(buffer, "a45", 4); result = memnappend_double(buffer, 3, 6, 1.625, 0, DECIMAL_PRECISION_MAX); TestCase_assertSizeEqual(result, 6); TestCase_assertBytesEqual(buffer, "a451.6", 6); result = memnappend_double(buffer, 1, 6, 2.0, 2, DECIMAL_PRECISION_MAX); TestCase_assertSizeEqual(result, 5); TestCase_assertBytesEqual(buffer, "a2.00", 5); result = memnappend_integer(buffer, 2, 6, 123456); TestCase_assertSizeEqual(result, 6); TestCase_assertBytesEqual(buffer, "a21234", 6); result = memnappend_integer(buffer, 1, 6, 999); TestCase_assertSizeEqual(result, 4); TestCase_assertBytesEqual(buffer, "a99934", 6); } static void testLexstrcmp(void) { TestCase_assertIntEqual(lexstrcmp("a", "b"), -1); TestCase_assertIntEqual(lexstrcmp("b", "b"), 0); TestCase_assertIntEqual(lexstrcmp("b", "a"), 1); TestCase_assertIntEqual(lexstrcmp("Test 5", "Test 6"), -1); TestCase_assertIntEqual(lexstrcmp("Test 5", "Test 10"), -1); TestCase_assertIntEqual(lexstrcmp("a200b4", "a39b9000"), 1); TestCase_assertIntEqual(lexstrcmp("a200b4", "a200b4"), 0); TestCase_assertIntEqual(lexstrcmp("a200b4", "a200b"), 1); TestCase_assertIntEqual(lexstrcmp("a200b", "a200b4"), -1); TestCase_assertIntEqual(lexstrcmp("a1", "ab"), -1); TestCase_assertIntEqual(lexstrcmp("ab", "a1"), 1); TestCase_assertIntEqual(lexstrcmp("a001", "a000"), 1); TestCase_assertIntEqual(lexstrcmp("a000", "a001"), -1); TestCase_assertIntEqual(lexstrcmp("a002", "a2"), 1); TestCase_assertIntEqual(lexstrcmp("a2", "a002"), -1); TestCase_assertIntEqual(lexstrcmp("a002", "a1"), 1); TestCase_assertIntEqual(lexstrcmp("a1", "a002"), -1); TestCase_assertIntEqual(lexstrcmp("a002", "a3"), -1); TestCase_assertIntEqual(lexstrcmp("a3", "a002"), 1); TestCase_assertIntEqual(lexstrcmp("a00b", "a00b"), 0); TestCase_assertIntEqual(lexstrcmp("a000b", "a00b"), 1); TestCase_assertIntEqual(lexstrcmp("a00b", "a000b"), -1); TestCase_assertIntEqual(lexstrcmp("Ab", "aB"), 0); } static void testPrintHexString() { char buffer[32]; char hex1[] = {0x00, 0x01, 0x02, 0x03}, hex2[] = "Hello"; char * result; buffer[31] = 0; result = printHexString(hex1, sizeof(hex1), buffer, 32); TestCase_assert(result == buffer, "Expected %p but got %p", buffer, result); TestCase_assert(!strcmp(buffer, "00 01 02 03"), "Expected \"00 01 02 03\" but got \"%s\"", buffer); result = printHexString(hex2, sizeof(hex2), buffer, 32); TestCase_assert(result == buffer, "Expected %p but got %p", buffer, result); TestCase_assert(!strcmp(buffer, "48 65 6C 6C 6F 00"), "Expected \"48 65 6C 6C 6F 00\" but got \"%s\"", buffer); result = printHexString(hex2, sizeof(hex2), buffer, 5); TestCase_assert(result == buffer, "Expected %p but got %p", buffer, result); TestCase_assert(!strcmp(buffer, "48 6"), "Expected \"48 6\" but got \"%s\"", buffer); result = printHexString(hex1, 0, buffer, 32); TestCase_assert(result == buffer, "Expected %p but got %p", buffer, result); TestCase_assert(!strcmp(buffer, ""), "Expected \"\" but got \"%s\"", buffer); } static void testFormatDecimalString(void) { char result[DECIMAL_STRING_MAX]; unsigned int length; length = formatDecimalString(1, result, sizeof(result), 0, DECIMAL_PRECISION_MAX); TestCase_assertStringEqual(result, "1"); TestCase_assertUIntEqual(length, 1); length = formatDecimalString(-243.25, result, sizeof(result), 0, DECIMAL_PRECISION_MAX); TestCase_assertStringEqual(result, "-243.25"); TestCase_assertUIntEqual(length, 7); length = formatDecimalString(0.0000152587890625, result, sizeof(result), 0, DECIMAL_PRECISION_MAX); TestCase_assertStringEqual(result, "0.0000152587890625"); TestCase_assertUIntEqual(length, 18); length = formatDecimalString(0.0000152587890625, result, 8, 0, DECIMAL_PRECISION_MAX); TestCase_assertStringEqual(result, "0.00001"); TestCase_assertUIntEqual(length, 7); length = formatDecimalString(INFINITY, result, sizeof(result), 0, DECIMAL_PRECISION_MAX); TestCase_assertStringEqual(result, "inf"); TestCase_assertUIntEqual(length, 3); length = formatDecimalString(-INFINITY, result, sizeof(result), 0, DECIMAL_PRECISION_MAX); TestCase_assertStringEqual(result, "-inf"); TestCase_assertUIntEqual(length, 4); length = formatDecimalString(NAN, result, sizeof(result), 0, DECIMAL_PRECISION_MAX); TestCase_assertStringEqual(result, "nan"); TestCase_assertUIntEqual(length, 3); length = formatDecimalString(2, result, sizeof(result), 4, DECIMAL_PRECISION_MAX); TestCase_assertStringEqual(result, "2.0000"); TestCase_assertUIntEqual(length, 6); length = formatDecimalString(2.0625, result, sizeof(result), 0, 2); TestCase_assertStringEqual(result, "2.06"); TestCase_assertUIntEqual(length, 4); length = formatDecimalString(1.5, result, 0, 0, DECIMAL_PRECISION_MAX); TestCase_assertStringEqual(result, "2.06"); TestCase_assertUIntEqual(length, 0); length = formatDecimalString(1.5, result, 1, 0, DECIMAL_PRECISION_MAX); TestCase_assertStringEqual(result, ""); TestCase_assertUIntEqual(length, 0); length = formatDecimalString(1.5, result, 2, 0, DECIMAL_PRECISION_MAX); TestCase_assertStringEqual(result, "1"); TestCase_assertUIntEqual(length, 1); length = formatDecimalString(1.5, result, 3, 0, DECIMAL_PRECISION_MAX); TestCase_assertStringEqual(result, "1."); TestCase_assertUIntEqual(length, 2); length = formatDecimalString(1.5, result, 4, 0, DECIMAL_PRECISION_MAX); TestCase_assertStringEqual(result, "1.5"); TestCase_assertUIntEqual(length, 3); } static void testParseDecimalString(void) { unsigned int lengthRead = 0; double result = 1.0; bool success = parseDecimalString(&result, "0", UINT_MAX, &lengthRead); TestCase_assertDoubleEqual(result, 0.0); TestCase_assertBoolTrue(success); TestCase_assertUIntEqual(lengthRead, 1); success = parseDecimalString(&result, "aaaa1", UINT_MAX, &lengthRead); TestCase_assertBoolFalse(success); TestCase_assertUIntEqual(lengthRead, 0); success = parseDecimalString(&result, "1.5", UINT_MAX, &lengthRead); TestCase_assertDoubleEqual(result, 1.5); TestCase_assertBoolTrue(success); TestCase_assertUIntEqual(lengthRead, 3); success = parseDecimalString(&result, "-5.0jjj", UINT_MAX, &lengthRead); TestCase_assertDoubleEqual(result, -5.0); TestCase_assertBoolTrue(success); TestCase_assertUIntEqual(lengthRead, 4); success = parseDecimalString(&result, "123.45678", 3, &lengthRead); TestCase_assertDoubleEqual(result, 123.0); TestCase_assertBoolTrue(success); TestCase_assertUIntEqual(lengthRead, 3); success = parseDecimalString(&result, "0.0000152587890625", UINT_MAX, &lengthRead); TestCase_assertDoubleEqual(result, 0.0000152587890625); TestCase_assertBoolTrue(success); TestCase_assertUIntEqual(lengthRead, 18); success = parseDecimalString(&result, "inf", UINT_MAX, &lengthRead); TestCase_assertDoubleEqual(result, INFINITY); TestCase_assertBoolTrue(success); TestCase_assertUIntEqual(lengthRead, 3); success = parseDecimalString(&result, "-inf", UINT_MAX, &lengthRead); TestCase_assertDoubleEqual(result, -INFINITY); TestCase_assertBoolTrue(success); TestCase_assertUIntEqual(lengthRead, 4); success = parseDecimalString(&result, "nan", UINT_MAX, &lengthRead); TestCase_assertBoolTrue(isnan(result)); TestCase_assertBoolTrue(success); TestCase_assertUIntEqual(lengthRead, 3); success = parseDecimalString(&result, "1e+2", UINT_MAX, &lengthRead); TestCase_assertDoubleEqual(result, 100.0); TestCase_assertBoolTrue(success); TestCase_assertUIntEqual(lengthRead, 4); success = parseDecimalString(&result, "5e-3", UINT_MAX, &lengthRead); TestCase_assertDoubleEqual(result, 0.005); TestCase_assertBoolTrue(success); TestCase_assertUIntEqual(lengthRead, 4); success = parseDecimalString(&result, "2e1", UINT_MAX, &lengthRead); TestCase_assertDoubleEqual(result, 20.0); TestCase_assertBoolTrue(success); TestCase_assertUIntEqual(lengthRead, 3); success = parseDecimalString(&result, "0.50000000000000000000000000000000", UINT_MAX, &lengthRead); TestCase_assertDoubleEqual(result, 0.5); TestCase_assertBoolTrue(success); TestCase_assertUIntEqual(lengthRead, 34); success = parseDecimalString(&result, "", 0, &lengthRead); TestCase_assertBoolFalse(success); TestCase_assertUIntEqual(lengthRead, 0); success = parseDecimalString(&result, "000123", UINT_MAX, &lengthRead); TestCase_assertDoubleEqual(result, 123.0); TestCase_assertBoolTrue(success); TestCase_assertUIntEqual(lengthRead, 6); success = parseDecimalString(&result, "-002", UINT_MAX, &lengthRead); TestCase_assertDoubleEqual(result, -2.0); TestCase_assertBoolTrue(success); TestCase_assertUIntEqual(lengthRead, 4); } static void testFormatDecimalIntegerString(void) { char result[DECIMAL_INTEGER_STRING_MAX]; unsigned int length; length = formatDecimalIntegerString(0, result, sizeof(result)); TestCase_assertStringEqual(result, "0"); TestCase_assertUIntEqual(length, 1); length = formatDecimalIntegerString(1, result, sizeof(result)); TestCase_assertStringEqual(result, "1"); TestCase_assertUIntEqual(length, 1); length = formatDecimalIntegerString(-243, result, sizeof(result)); TestCase_assertStringEqual(result, "-243"); TestCase_assertUIntEqual(length, 4); length = formatDecimalIntegerString(9223372036854775807ll, result, sizeof(result)); TestCase_assertStringEqual(result, "9223372036854775807"); TestCase_assertUIntEqual(length, 19); length = formatDecimalIntegerString(9223372036854775806ll, result, sizeof(result)); TestCase_assertStringEqual(result, "9223372036854775806"); TestCase_assertUIntEqual(length, 19); length = formatDecimalIntegerString(INT64_MIN, result, sizeof(result)); TestCase_assertStringEqual(result, "-9223372036854775808"); TestCase_assertUIntEqual(length, 20); length = formatDecimalIntegerString(-9223372036854775807ll, result, sizeof(result)); TestCase_assertStringEqual(result, "-9223372036854775807"); TestCase_assertUIntEqual(length, 20); length = formatDecimalIntegerString(123456789, result, 5); TestCase_assertStringEqual(result, "1234"); TestCase_assertUIntEqual(length, 4); length = formatDecimalIntegerString(5678, result, 0); TestCase_assertStringEqual(result, "1234"); TestCase_assertUIntEqual(length, 0); length = formatDecimalIntegerString(5678, result, 1); TestCase_assertStringEqual(result, ""); TestCase_assertUIntEqual(length, 0); length = formatDecimalIntegerString(5678, result, 2); TestCase_assertStringEqual(result, "5"); TestCase_assertUIntEqual(length, 1); length = formatDecimalIntegerString(5678, result, 3); TestCase_assertStringEqual(result, "56"); TestCase_assertUIntEqual(length, 2); length = formatDecimalIntegerString(5678, result, 4); TestCase_assertStringEqual(result, "567"); TestCase_assertUIntEqual(length, 3); } static void testParseDecimalIntegerString(void) { unsigned int lengthRead = 0; int64_t result = 1; bool success = parseDecimalIntegerString(&result, "0", UINT_MAX, &lengthRead); TestCase_assertInt64Equal(result, 0); TestCase_assertBoolTrue(success); TestCase_assertUIntEqual(lengthRead, 1); success = parseDecimalIntegerString(&result, "aaaa1", UINT_MAX, &lengthRead); TestCase_assertBoolFalse(success); TestCase_assertUIntEqual(lengthRead, 0); success = parseDecimalIntegerString(&result, "1.5", UINT_MAX, &lengthRead); TestCase_assertInt64Equal(result, 1); TestCase_assertBoolTrue(success); TestCase_assertUIntEqual(lengthRead, 1); success = parseDecimalIntegerString(&result, "-5jjj", UINT_MAX, &lengthRead); TestCase_assertInt64Equal(result, -5); TestCase_assertBoolTrue(success); TestCase_assertUIntEqual(lengthRead, 2); success = parseDecimalIntegerString(&result, "12345678", 3, &lengthRead); TestCase_assertInt64Equal(result, 123); TestCase_assertBoolTrue(success); TestCase_assertUIntEqual(lengthRead, 3); success = parseDecimalIntegerString(&result, "9223372036854775808", UINT_MAX, &lengthRead); TestCase_assertBoolFalse(success); TestCase_assertUIntEqual(lengthRead, 0); success = parseDecimalIntegerString(&result, "9223372036854775807", UINT_MAX, &lengthRead); TestCase_assertInt64Equal(result, 9223372036854775807ll); TestCase_assertBoolTrue(success); TestCase_assertUIntEqual(lengthRead, 19); success = parseDecimalIntegerString(&result, "9223372036854775806", UINT_MAX, &lengthRead); TestCase_assertInt64Equal(result, 9223372036854775806ll); TestCase_assertBoolTrue(success); TestCase_assertUIntEqual(lengthRead, 19); success = parseDecimalIntegerString(&result, "-9223372036854775809", UINT_MAX, &lengthRead); TestCase_assertBoolFalse(success); TestCase_assertUIntEqual(lengthRead, 0); success = parseDecimalIntegerString(&result, "-9223372036854775808", UINT_MAX, &lengthRead); TestCase_assertInt64Equal(result, INT64_MIN); TestCase_assertBoolTrue(success); TestCase_assertUIntEqual(lengthRead, 20); success = parseDecimalIntegerString(&result, "-9223372036854775807", UINT_MAX, &lengthRead); TestCase_assertInt64Equal(result, -9223372036854775807ll); TestCase_assertBoolTrue(success); TestCase_assertUIntEqual(lengthRead, 20); success = parseDecimalIntegerString(&result, "", 0, &lengthRead); TestCase_assertBoolFalse(success); TestCase_assertUIntEqual(lengthRead, 0); success = parseDecimalIntegerString(&result, "005", UINT_MAX, &lengthRead); TestCase_assertInt64Equal(result, 5); TestCase_assertBoolTrue(success); TestCase_assertUIntEqual(lengthRead, 3); success = parseDecimalIntegerString(&result, "-00023", UINT_MAX, &lengthRead); TestCase_assertInt64Equal(result, -23); TestCase_assertBoolTrue(success); TestCase_assertUIntEqual(lengthRead, 6); } static void testCreateIdentifierFromDisplayString(void) { char * result; result = createIdentifierFromDisplayString("", 40); TestCase_assertStringEqual(result, ""); free(result); result = createIdentifierFromDisplayString("hello", 40); TestCase_assertStringEqual(result, "hello"); free(result); result = createIdentifierFromDisplayString("HeLlO", 40); TestCase_assertStringEqual(result, "hello"); free(result); result = createIdentifierFromDisplayString("I'm going to be an identifier", 40); TestCase_assertStringEqual(result, "i_m_going_to_be_an_identifier"); free(result); result = createIdentifierFromDisplayString("i_m_already_an_identifier_123", 40); TestCase_assertStringEqual(result, "i_m_already_an_identifier_123"); free(result); result = createIdentifierFromDisplayString(" space space space ", 40); TestCase_assertStringEqual(result, "space_space_space"); free(result); result = createIdentifierFromDisplayString("`~!@#$%^&*()-=+[{]}\\|;:'\",<.>/?", 40); TestCase_assertStringEqual(result, ""); free(result); result = createIdentifierFromDisplayString("too long", 5); TestCase_assertStringEqual(result, "too_l"); free(result); result = createIdentifierFromDisplayString("_underscore_", 40); TestCase_assertStringEqual(result, "_underscore_"); free(result); result = createIdentifierFromDisplayString("@nounderscore@", 40); TestCase_assertStringEqual(result, "nounderscore"); free(result); } static void testGetFileExtension(void) { const char * result = getFileExtension("/a/b/c.d"); TestCase_assertStringEqual(result, "d"); result = getFileExtension("a/b/ccc.ddd.ee"); TestCase_assertStringEqual(result, "ee"); result = getFileExtension("/abc/def/ghi"); TestCase_assertStringEqual(result, ""); result = getFileExtension("/abc/de.f/ghi"); TestCase_assertStringEqual(result, ""); result = getFileExtension("hello.txt"); TestCase_assertStringEqual(result, "txt"); result = getFileExtension(""); TestCase_assertStringEqual(result, ""); #ifdef WIN32 result = getFileExtension("C:\\a\\b\\c.d"); TestCase_assertStringEqual(result, "d"); result = getFileExtension("D:\\a\\b\\ccc.ddd.ee"); TestCase_assertStringEqual(result, "ee"); result = getFileExtension("C:\\abc\\def\\ghi"); TestCase_assertStringEqual(result, ""); result = getFileExtension("C:\\abc\\de.f\\ghi"); TestCase_assertStringEqual(result, ""); #endif } static void testGetLastPathComponent(void) { const char * result = getLastPathComponent("/a/b/c.d"); TestCase_assertStringEqual(result, "c.d"); result = getLastPathComponent("/abc/def/"); TestCase_assertStringEqual(result, "def/"); result = getLastPathComponent("hello"); TestCase_assertStringEqual(result, "hello"); result = getLastPathComponent("/"); TestCase_assertStringEqual(result, "/"); result = getLastPathComponent(""); TestCase_assertStringEqual(result, ""); #ifdef WIN32 result = getLastPathComponent("\\a\\b\\c.d"); TestCase_assertStringEqual(result, "c.d"); result = getLastPathComponent("\\abc\\def\\"); TestCase_assertStringEqual(result, "def\\"); result = getLastPathComponent("hello"); TestCase_assertStringEqual(result, "hello"); result = getLastPathComponent("\\"); TestCase_assertStringEqual(result, "\\"); #endif } static void testGetDirectory(void) { const char * result = getDirectory("/a/b/c.d"); TestCase_assertStringEqual(result, "/a/b/"); result = getDirectory("abc/def"); TestCase_assertStringEqual(result, "abc/"); result = getDirectory("hello"); TestCase_assertStringEqual(result, ""); result = getDirectory("/"); TestCase_assertStringEqual(result, "/"); result = getDirectory(""); TestCase_assertStringEqual(result, ""); #ifdef WIN32 result = getDirectory("\\a\\b\\c.d"); TestCase_assertStringEqual(result, "\\a\\b\\"); result = getDirectory("abc\\def"); TestCase_assertStringEqual(result, "abc\\"); result = getDirectory("hello"); TestCase_assertStringEqual(result, ""); result = getDirectory("\\"); TestCase_assertStringEqual(result, "\\"); result = getDirectory("C:\\a\\b\\c.d"); TestCase_assertStringEqual(result, "C:\\a\\b\\"); result = getDirectory("C:\\a"); TestCase_assertStringEqual(result, "C:\\"); result = getDirectory("C:\\"); TestCase_assertStringEqual(result, "C:\\"); result = getDirectory("C:"); TestCase_assertStringEqual(result, "C:"); #endif } static void testGetBaseName(void) { const char * result = getBaseName("abc.def"); TestCase_assertStringEqual(result, "abc"); result = getBaseName("aa.bb.cc"); TestCase_assertStringEqual(result, "aa.bb"); result = getBaseName("/aa/aa.bb.cc"); TestCase_assertStringEqual(result, "/aa/aa.bb"); result = getBaseName("/aa.bb/cc"); TestCase_assertStringEqual(result, "/aa.bb/cc"); result = getBaseName("/a/b"); TestCase_assertStringEqual(result, "/a/b"); result = getBaseName(""); TestCase_assertStringEqual(result, ""); #ifdef WIN32 result = getBaseName("\\aa\\aa.bb.cc"); TestCase_assertStringEqual(result, "\\aa\\aa.bb"); result = getBaseName("\\aa.bb\\cc"); TestCase_assertStringEqual(result, "\\aa.bb\\cc"); result = getBaseName("\\a\\b"); TestCase_assertStringEqual(result, "\\a\\b"); #endif } static void testGetSiblingFilePath(void) { const char * result = getSiblingFilePath("/a/b/c", "d"); TestCase_assertStringEqual(result, "/a/b/d"); result = getSiblingFilePath("aa/bb", "hello"); TestCase_assertStringEqual(result, "aa/hello"); result = getSiblingFilePath("aa/bb", ""); TestCase_assertStringEqual(result, "aa/"); result = getSiblingFilePath("", "a"); TestCase_assertStringEqual(result, "a"); result = getSiblingFilePath("", ""); TestCase_assertStringEqual(result, ""); #ifdef WIN32 result = getSiblingFilePath("\\a\\b\\c", "d"); TestCase_assertStringEqual(result, "\\a\\b\\d"); result = getSiblingFilePath("aa\\bb", "hello"); TestCase_assertStringEqual(result, "aa\\hello"); result = getSiblingFilePath("aa\\bb", ""); TestCase_assertStringEqual(result, "aa\\"); #endif } static void testGetPathRelativeTo(void) { const char * result = getPathRelativeTo("/a/", "/a/c"); TestCase_assertStringEqual(result, "c"); result = getPathRelativeTo("/a/b/", "/a/c"); TestCase_assertStringEqual(result, "../c"); result = getPathRelativeTo("a/b/", "a/c"); TestCase_assertStringEqual(result, "../c"); result = getPathRelativeTo("a/b/c/", "a/d/e"); TestCase_assertStringEqual(result, "../../d/e"); result = getPathRelativeTo("/base/subdir/subdir2", "/base/subdir/subdir2/file"); TestCase_assertStringEqual(result, "subdir2/file"); result = getPathRelativeTo("/base/subdir/subdir2/", "/base/subdir/subdir2/file"); TestCase_assertStringEqual(result, "file"); #ifdef WIN32 result = getPathRelativeTo("\\a\\", "\\a\\c"); TestCase_assertStringEqual(result, "c"); result = getPathRelativeTo("\\a\\b\\", "\\a\\c"); TestCase_assertStringEqual(result, "../c"); result = getPathRelativeTo("a\\b\\", "a\\c"); TestCase_assertStringEqual(result, "../c"); result = getPathRelativeTo("a\\b\\c\\", "a\\d\\e"); TestCase_assertStringEqual(result, "../../d\\e"); result = getPathRelativeTo("\\base\\subdir\\subdir2", "\\base\\subdir\\subdir2\\file"); TestCase_assertStringEqual(result, "subdir2\\file"); result = getPathRelativeTo("\\base\\subdir\\subdir2\\", "\\base\\subdir\\subdir2\\file"); TestCase_assertStringEqual(result, "file"); #endif } static void testGetAbsolutePath(void) { const char * result = getAbsolutePath("/a/", "b"); TestCase_assertStringEqual(result, "/a/b"); result = getAbsolutePath("/a/b", "c"); TestCase_assertStringEqual(result, "/a/c"); result = getAbsolutePath("/a/b", "/d/c"); TestCase_assertStringEqual(result, "/d/c"); result = getAbsolutePath("/a/b/", "../e/f"); TestCase_assertStringEqual(result, "/a/e/f"); result = getAbsolutePath("/a/b/", "../../e/f"); TestCase_assertStringEqual(result, "/e/f"); result = getAbsolutePath("/a/b/", "../../../e/f"); TestCase_assertStringEqual(result, "/e/f"); result = getAbsolutePath("/i/", "./g"); TestCase_assertStringEqual(result, "/i/g"); result = getAbsolutePath("/base/subdir/subdir/", "../r/../g"); TestCase_assertStringEqual(result, "/base/subdir/g"); result = getAbsolutePath("/base/subdir/subdir2/", ".."); TestCase_assertStringEqual(result, "/base/subdir/"); result = getAbsolutePath("/a/b/", "/q/../r/"); TestCase_assertStringEqual(result, "/r/"); #ifdef WIN32 result = getAbsolutePath("\\a\\", "b"); TestCase_assertStringEqual(result, "\\a\\b"); result = getAbsolutePath("\\a\\b", "c"); TestCase_assertStringEqual(result, "\\a\\c"); result = getAbsolutePath("C:\\a\\b", "C:\\d\\c"); TestCase_assertStringEqual(result, "C:\\d\\c"); result = getAbsolutePath("C:\\a\\b", "\\d\\c"); TestCase_assertStringEqual(result, "\\d\\c"); result = getAbsolutePath("\\a\\b\\", "../e\\f"); TestCase_assertStringEqual(result, "\\a\\e\\f"); result = getAbsolutePath("\\a\\b\\", "../../e\\f"); TestCase_assertStringEqual(result, "\\e\\f"); result = getAbsolutePath("\\a\\b\\", "../../../e\\f"); TestCase_assertStringEqual(result, "\\e\\f"); result = getAbsolutePath("\\i\\", ".\\g"); TestCase_assertStringEqual(result, "\\i\\g"); result = getAbsolutePath("\\base\\subdir\\subdir\\", "..\\r\\..\\g"); TestCase_assertStringEqual(result, "\\base\\subdir\\g"); result = getAbsolutePath("\\base\\subdir\\subdir2\\", ".."); TestCase_assertStringEqual(result, "\\base\\subdir\\"); result = getAbsolutePath("\\a\\b\\", "\\q\\..\\r\\"); TestCase_assertStringEqual(result, "\\r\\"); #endif } static void testIsAbsolutePath(void) { TestCase_assertBoolTrue(isAbsolutePath("/")); TestCase_assertBoolTrue(isAbsolutePath("/a/b")); TestCase_assertBoolFalse(isAbsolutePath("a/b")); TestCase_assertBoolFalse(isAbsolutePath("a")); TestCase_assertBoolFalse(isAbsolutePath("")); #ifdef WIN32 TestCase_assertBoolTrue(isAbsolutePath("\\")); TestCase_assertBoolTrue(isAbsolutePath("\\a\\b")); TestCase_assertBoolFalse(isAbsolutePath("a\\b")); TestCase_assertBoolTrue(isAbsolutePath("a:")); TestCase_assertBoolTrue(isAbsolutePath("C:")); TestCase_assertBoolTrue(isAbsolutePath("C:\\")); TestCase_assertBoolTrue(isAbsolutePath("C:/")); TestCase_assertBoolTrue(isAbsolutePath("C:/a")); TestCase_assertBoolTrue(isAbsolutePath("C:\\a")); TestCase_assertBoolFalse(isAbsolutePath("C/a")); TestCase_assertBoolFalse(isAbsolutePath("C\\a")); #endif } struct enumerateFilesContext { unsigned int fileCount; unsigned int fileCountMax; char ** fileNames; const char * expectedDirectoryPath; }; static bool enumerateDirectoryCallback(const char * directoryPath, const char * fileName, void * context) { struct enumerateFilesContext * contextStruct = context; TestCase_assertStringEqual(directoryPath, contextStruct->expectedDirectoryPath); contextStruct->fileNames[contextStruct->fileCount++] = strdup(fileName); return contextStruct->fileCount < contextStruct->fileCountMax; } static void testEnumerateFilesInDirectory(void) { mkdir("testdir1" #ifndef WIN32 , 0777 #endif ); fclose(fopen("testdir1/testfile1", "w")); mkdir("testdir2" #ifndef WIN32 , 0777 #endif ); fclose(fopen("testdir2/a", "w")); fclose(fopen("testdir2/b", "w")); char * fileNames[3] = {NULL, NULL, NULL}; struct enumerateFilesContext contextStruct = {0, 3, fileNames, "testdir1"}; enumerateFilesInDirectory("testdir1", false, enumerateDirectoryCallback, &contextStruct); TestCase_assertUIntEqual(contextStruct.fileCount, 1); TestCase_assertStringEqual(contextStruct.fileNames[0], "testfile1"); free(contextStruct.fileNames[0]); contextStruct.fileNames[0] = NULL; contextStruct.fileCount = 0; contextStruct.expectedDirectoryPath = "testdir2"; enumerateFilesInDirectory("testdir2", false, enumerateDirectoryCallback, &contextStruct); TestCase_assertUIntEqual(contextStruct.fileCount, 2); if (!strcmp(contextStruct.fileNames[0], "a")) { TestCase_assertStringEqual(contextStruct.fileNames[0], "a"); TestCase_assertStringEqual(contextStruct.fileNames[1], "b"); } else { TestCase_assertStringEqual(contextStruct.fileNames[0], "b"); TestCase_assertStringEqual(contextStruct.fileNames[1], "a"); } free(contextStruct.fileNames[0]); free(contextStruct.fileNames[1]); contextStruct.fileNames[0] = NULL; contextStruct.fileNames[1] = NULL; contextStruct.fileCount = 0; contextStruct.fileCountMax = 1; enumerateFilesInDirectory("testdir2", false, enumerateDirectoryCallback, &contextStruct); TestCase_assertUIntEqual(contextStruct.fileCount, 1); free(contextStruct.fileNames[0]); } static void testPercentEncode(void) { char encodedString[768]; size_t length = percentEncode(NULL, 0, "a%b", 3); TestCase_assertSizeEqual(length, 5); length = percentEncode(encodedString, sizeof(encodedString), "a%b", 3); TestCase_assertSizeEqual(length, 5); TestCase_assertBytesEqual(encodedString, "a%25b", 5); length = percentEncode(NULL, 0, "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz-._~", 66); TestCase_assertSizeEqual(length, 66); length = percentEncode(encodedString, sizeof(encodedString), "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz-._~", 66); TestCase_assertSizeEqual(length, 66); TestCase_assertBytesEqual(encodedString, "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz-._~", 66); length = percentEncode(NULL, 0, "\x00\x01\x02\x03\x04\x05\x06\x07\x08\x09\x0A\x0B\x0C\x0D\x0E\x0F" "\x10\x11\x12\x13\x14\x15\x16\x17\x18\x19\x1A\x1B\x1C\x1D\x1E\x1F" "\x20\x21\x22\x23\x24\x25\x26\x27\x28\x29\x2A\x2B\x2C\x2D\x2E\x2F" "\x30\x31\x32\x33\x34\x35\x36\x37\x38\x39\x3A\x3B\x3C\x3D\x3E\x3F" "\x40\x41\x42\x43\x44\x45\x46\x47\x48\x49\x4A\x4B\x4C\x4D\x4E\x4F" "\x50\x51\x52\x53\x54\x55\x56\x57\x58\x59\x5A\x5B\x5C\x5D\x5E\x5F" "\x60\x61\x62\x63\x64\x65\x66\x67\x68\x69\x6A\x6B\x6C\x6D\x6E\x6F" "\x70\x71\x72\x73\x74\x75\x76\x77\x78\x79\x7A\x7B\x7C\x7D\x7E\x7F" "\x80\x81\x82\x83\x84\x85\x86\x87\x88\x89\x8A\x8B\x8C\x8D\x8E\x8F" "\x90\x91\x92\x93\x94\x95\x96\x97\x98\x99\x9A\x9B\x9C\x9D\x9E\x9F" "\xA0\xA1\xA2\xA3\xA4\xA5\xA6\xA7\xA8\xA9\xAA\xAB\xAC\xAD\xAE\xAF" "\xB0\xB1\xB2\xB3\xB4\xB5\xB6\xB7\xB8\xB9\xBA\xBB\xBC\xBD\xBE\xBF" "\xC0\xC1\xC2\xC3\xC4\xC5\xC6\xC7\xC8\xC9\xCA\xCB\xCC\xCD\xCE\xCF" "\xD0\xD1\xD2\xD3\xD4\xD5\xD6\xD7\xD8\xD9\xDA\xDB\xDC\xDD\xDE\xDF" "\xE0\xE1\xE2\xE3\xE4\xE5\xE6\xE7\xE8\xE9\xEA\xEB\xEC\xED\xEE\xEF" "\xF0\xF1\xF2\xF3\xF4\xF5\xF6\xF7\xF8\xF9\xFA\xFB\xFC\xFD\xFE\xFF", 256); TestCase_assertSizeEqual(length, 636); length = percentEncode(encodedString, sizeof(encodedString), "\x00\x01\x02\x03\x04\x05\x06\x07\x08\x09\x0A\x0B\x0C\x0D\x0E\x0F" "\x10\x11\x12\x13\x14\x15\x16\x17\x18\x19\x1A\x1B\x1C\x1D\x1E\x1F" "\x20\x21\x22\x23\x24\x25\x26\x27\x28\x29\x2A\x2B\x2C\x2D\x2E\x2F" "\x30\x31\x32\x33\x34\x35\x36\x37\x38\x39\x3A\x3B\x3C\x3D\x3E\x3F" "\x40\x41\x42\x43\x44\x45\x46\x47\x48\x49\x4A\x4B\x4C\x4D\x4E\x4F" "\x50\x51\x52\x53\x54\x55\x56\x57\x58\x59\x5A\x5B\x5C\x5D\x5E\x5F" "\x60\x61\x62\x63\x64\x65\x66\x67\x68\x69\x6A\x6B\x6C\x6D\x6E\x6F" "\x70\x71\x72\x73\x74\x75\x76\x77\x78\x79\x7A\x7B\x7C\x7D\x7E\x7F" "\x80\x81\x82\x83\x84\x85\x86\x87\x88\x89\x8A\x8B\x8C\x8D\x8E\x8F" "\x90\x91\x92\x93\x94\x95\x96\x97\x98\x99\x9A\x9B\x9C\x9D\x9E\x9F" "\xA0\xA1\xA2\xA3\xA4\xA5\xA6\xA7\xA8\xA9\xAA\xAB\xAC\xAD\xAE\xAF" "\xB0\xB1\xB2\xB3\xB4\xB5\xB6\xB7\xB8\xB9\xBA\xBB\xBC\xBD\xBE\xBF" "\xC0\xC1\xC2\xC3\xC4\xC5\xC6\xC7\xC8\xC9\xCA\xCB\xCC\xCD\xCE\xCF" "\xD0\xD1\xD2\xD3\xD4\xD5\xD6\xD7\xD8\xD9\xDA\xDB\xDC\xDD\xDE\xDF" "\xE0\xE1\xE2\xE3\xE4\xE5\xE6\xE7\xE8\xE9\xEA\xEB\xEC\xED\xEE\xEF" "\xF0\xF1\xF2\xF3\xF4\xF5\xF6\xF7\xF8\xF9\xFA\xFB\xFC\xFD\xFE\xFF", 256); TestCase_assertSizeEqual(length, 636); TestCase_assertBytesEqual(encodedString, "%00%01%02%03%04%05%06%07%08%09%0A%0B%0C%0D%0E%0F" "%10%11%12%13%14%15%16%17%18%19%1A%1B%1C%1D%1E%1F" "%20%21%22%23%24%25%26%27%28%29%2A%2B%2C-.%2F" "0123456789%3A%3B%3C%3D%3E%3F" "%40ABCDEFGHIJKLMNO" "PQRSTUVWXYZ%5B%5C%5D%5E_" "%60abcdefghijklmno" "pqrstuvwxyz%7B%7C%7D~%7F" "%80%81%82%83%84%85%86%87%88%89%8A%8B%8C%8D%8E%8F" "%90%91%92%93%94%95%96%97%98%99%9A%9B%9C%9D%9E%9F" "%A0%A1%A2%A3%A4%A5%A6%A7%A8%A9%AA%AB%AC%AD%AE%AF" "%B0%B1%B2%B3%B4%B5%B6%B7%B8%B9%BA%BB%BC%BD%BE%BF" "%C0%C1%C2%C3%C4%C5%C6%C7%C8%C9%CA%CB%CC%CD%CE%CF" "%D0%D1%D2%D3%D4%D5%D6%D7%D8%D9%DA%DB%DC%DD%DE%DF" "%E0%E1%E2%E3%E4%E5%E6%E7%E8%E9%EA%EB%EC%ED%EE%EF" "%F0%F1%F2%F3%F4%F5%F6%F7%F8%F9%FA%FB%FC%FD%FE%FF", 636); encodedString[5] = '?'; length = percentEncode(encodedString, 5, "0123456789", 10); TestCase_assertSizeEqual(length, 5); TestCase_assertBytesEqual(encodedString, "01234?", 6); length = percentEncode(encodedString, 5, "%%%", 3); TestCase_assertSizeEqual(length, 5); TestCase_assertBytesEqual(encodedString, "%25%2?", 6); char * encodedString2 = percentEncodeString("A%B%C", NULL); TestCase_assertStringEqual(encodedString2, "A%25B%25C"); free(encodedString2); encodedString2 = percentEncodeString("1*2:3.", &length); TestCase_assertStringEqual(encodedString2, "1%2A2%3A3."); TestCase_assertSizeEqual(length, 10); free(encodedString2); } static void testPercentDecode(void) { char decodedString[256]; size_t length = percentDecode(NULL, 0, "a%25b", 5); TestCase_assertSizeEqual(length, 3); length = percentDecode(decodedString, sizeof(decodedString), "a%25b", 5); TestCase_assertSizeEqual(length, 3); TestCase_assertBytesEqual(decodedString, "a%b", 3); length = percentDecode(NULL, 0, "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz-._~", 66); TestCase_assertSizeEqual(length, 66); length = percentDecode(decodedString, sizeof(decodedString), "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz-._~", 66); TestCase_assertSizeEqual(length, 66); TestCase_assertBytesEqual(decodedString, "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz-._~", 66); length = percentDecode(NULL, 0, "%00%01%02%03%04%05%06%07%08%09%0A%0B%0C%0D%0E%0F" "%10%11%12%13%14%15%16%17%18%19%1A%1B%1C%1D%1E%1F" "%20%21%22%23%24%25%26%27%28%29%2A%2B%2C%2D%2E%2F" "%30%31%32%33%34%35%36%37%38%39%3A%3B%3C%3D%3E%3F" "%40%41%42%43%44%45%46%47%48%49%4A%4B%4C%4D%4E%4F" "%50%51%52%53%54%55%56%57%58%59%5A%5B%5C%5D%5E%5F" "%60%61%62%63%64%65%66%67%68%69%6A%6B%6C%6D%6E%6F" "%70%71%72%73%74%75%76%77%78%79%7A%7B%7C%7D%7E%7F" "%80%81%82%83%84%85%86%87%88%89%8A%8B%8C%8D%8E%8F" "%90%91%92%93%94%95%96%97%98%99%9A%9B%9C%9D%9E%9F" "%A0%A1%A2%A3%A4%A5%A6%A7%A8%A9%AA%AB%AC%AD%AE%AF" "%B0%B1%B2%B3%B4%B5%B6%B7%B8%B9%BA%BB%BC%BD%BE%BF" "%C0%C1%C2%C3%C4%C5%C6%C7%C8%C9%CA%CB%CC%CD%CE%CF" "%D0%D1%D2%D3%D4%D5%D6%D7%D8%D9%DA%DB%DC%DD%DE%DF" "%E0%E1%E2%E3%E4%E5%E6%E7%E8%E9%EA%EB%EC%ED%EE%EF" "%F0%F1%F2%F3%F4%F5%F6%F7%F8%F9%FA%FB%FC%FD%FE%FF", 768); TestCase_assertSizeEqual(length, 256); length = percentDecode(decodedString, sizeof(decodedString), "%00%01%02%03%04%05%06%07%08%09%0A%0B%0C%0D%0E%0F" "%10%11%12%13%14%15%16%17%18%19%1A%1B%1C%1D%1E%1F" "%20%21%22%23%24%25%26%27%28%29%2A%2B%2C%2D%2E%2F" "%30%31%32%33%34%35%36%37%38%39%3A%3B%3C%3D%3E%3F" "%40%41%42%43%44%45%46%47%48%49%4A%4B%4C%4D%4E%4F" "%50%51%52%53%54%55%56%57%58%59%5A%5B%5C%5D%5E%5F" "%60%61%62%63%64%65%66%67%68%69%6A%6B%6C%6D%6E%6F" "%70%71%72%73%74%75%76%77%78%79%7A%7B%7C%7D%7E%7F" "%80%81%82%83%84%85%86%87%88%89%8A%8B%8C%8D%8E%8F" "%90%91%92%93%94%95%96%97%98%99%9A%9B%9C%9D%9E%9F" "%A0%A1%A2%A3%A4%A5%A6%A7%A8%A9%AA%AB%AC%AD%AE%AF" "%B0%B1%B2%B3%B4%B5%B6%B7%B8%B9%BA%BB%BC%BD%BE%BF" "%C0%C1%C2%C3%C4%C5%C6%C7%C8%C9%CA%CB%CC%CD%CE%CF" "%D0%D1%D2%D3%D4%D5%D6%D7%D8%D9%DA%DB%DC%DD%DE%DF" "%E0%E1%E2%E3%E4%E5%E6%E7%E8%E9%EA%EB%EC%ED%EE%EF" "%F0%F1%F2%F3%F4%F5%F6%F7%F8%F9%FA%FB%FC%FD%FE%FF", 768); TestCase_assertSizeEqual(length, 256); TestCase_assertBytesEqual(decodedString, "\x00\x01\x02\x03\x04\x05\x06\x07\x08\x09\x0A\x0B\x0C\x0D\x0E\x0F" "\x10\x11\x12\x13\x14\x15\x16\x17\x18\x19\x1A\x1B\x1C\x1D\x1E\x1F" "\x20\x21\x22\x23\x24\x25\x26\x27\x28\x29\x2A\x2B\x2C\x2D\x2E\x2F" "\x30\x31\x32\x33\x34\x35\x36\x37\x38\x39\x3A\x3B\x3C\x3D\x3E\x3F" "\x40\x41\x42\x43\x44\x45\x46\x47\x48\x49\x4A\x4B\x4C\x4D\x4E\x4F" "\x50\x51\x52\x53\x54\x55\x56\x57\x58\x59\x5A\x5B\x5C\x5D\x5E\x5F" "\x60\x61\x62\x63\x64\x65\x66\x67\x68\x69\x6A\x6B\x6C\x6D\x6E\x6F" "\x70\x71\x72\x73\x74\x75\x76\x77\x78\x79\x7A\x7B\x7C\x7D\x7E\x7F" "\x80\x81\x82\x83\x84\x85\x86\x87\x88\x89\x8A\x8B\x8C\x8D\x8E\x8F" "\x90\x91\x92\x93\x94\x95\x96\x97\x98\x99\x9A\x9B\x9C\x9D\x9E\x9F" "\xA0\xA1\xA2\xA3\xA4\xA5\xA6\xA7\xA8\xA9\xAA\xAB\xAC\xAD\xAE\xAF" "\xB0\xB1\xB2\xB3\xB4\xB5\xB6\xB7\xB8\xB9\xBA\xBB\xBC\xBD\xBE\xBF" "\xC0\xC1\xC2\xC3\xC4\xC5\xC6\xC7\xC8\xC9\xCA\xCB\xCC\xCD\xCE\xCF" "\xD0\xD1\xD2\xD3\xD4\xD5\xD6\xD7\xD8\xD9\xDA\xDB\xDC\xDD\xDE\xDF" "\xE0\xE1\xE2\xE3\xE4\xE5\xE6\xE7\xE8\xE9\xEA\xEB\xEC\xED\xEE\xEF" "\xF0\xF1\xF2\xF3\xF4\xF5\xF6\xF7\xF8\xF9\xFA\xFB\xFC\xFD\xFE\xFF", 256); decodedString[5] = '?'; length = percentDecode(decodedString, 5, "0123456789", 10); TestCase_assertSizeEqual(length, 5); TestCase_assertBytesEqual(decodedString, "01234?", 6); length = percentDecode(decodedString, 5, "%25%25%25%25%25%25", 18); TestCase_assertSizeEqual(length, 5); TestCase_assertBytesEqual(decodedString, "%%%%%?", 6); length = percentDecode(decodedString, sizeof(decodedString), "a%", 2); TestCase_assertSizeEqual(length, 2); TestCase_assertBytesEqual(decodedString, "a%", 2); length = percentDecode(decodedString, sizeof(decodedString), "a%2", 3); TestCase_assertSizeEqual(length, 3); TestCase_assertBytesEqual(decodedString, "a%2", 3); length = percentDecode(decodedString, sizeof(decodedString), "a%20", 4); TestCase_assertSizeEqual(length, 2); TestCase_assertBytesEqual(decodedString, "a ", 2); length = percentDecode(decodedString, sizeof(decodedString), "a%7a", 4); TestCase_assertSizeEqual(length, 2); TestCase_assertBytesEqual(decodedString, "az", 2); length = percentDecode(decodedString, sizeof(decodedString), "a%7g", 4); TestCase_assertSizeEqual(length, 4); TestCase_assertBytesEqual(decodedString, "a%7g", 4); length = percentDecode(decodedString, sizeof(decodedString), "a%%7A", 5); TestCase_assertSizeEqual(length, 3); TestCase_assertBytesEqual(decodedString, "a%z", 3); char * decodedString2 = percentDecodeString("A%25B%25C", &length); TestCase_assertStringEqual(decodedString2, "A%B%C"); TestCase_assertSizeEqual(length, 5); free(decodedString2); decodedString2 = percentDecodeString("1%2A2%3A3.", &length); TestCase_assertStringEqual(decodedString2, "1*2:3."); TestCase_assertSizeEqual(length, 6); free(decodedString2); } TEST_SUITE(IOUtilitiesTest, testMemreadContextInit, testMemread, testMemwriteContextInit, testMemwrite, testReadFileSimple, testWriteFileSimple, testWriteFileAtomic, testTemporaryFilePath, testFilePathFunctions, testEndianSwapping, testSafeStringFunctions, testMemdup, testMemappend, testMemnappend, testLexstrcmp, testPrintHexString, testFormatDecimalString, testParseDecimalString, testFormatDecimalIntegerString, testParseDecimalIntegerString, testCreateIdentifierFromDisplayString, testGetFileExtension, testGetLastPathComponent, testGetDirectory, testGetBaseName, testGetSiblingFilePath, testGetPathRelativeTo, testGetAbsolutePath, testIsAbsolutePath, testEnumerateFilesInDirectory, testPercentEncode, testPercentDecode)