/*********************************************************************************************************************************** Decompress data ***********************************************************************************************************************************/ static Buffer * testDecompress(IoFilter *decompress, Buffer *compressed, size_t inputSize, size_t outputSize) { Buffer *decompressed = bufNew(1024 * 1024); Buffer *output = bufNew(outputSize); ioBufferSizeSet(inputSize); IoFilterGroup *filterGroup = ioFilterGroupNew(); ioFilterGroupAdd(filterGroup, decompress); IoRead *read = ioBufferReadNew(compressed); ioReadFilterGroupSet(read, filterGroup); ioReadOpen(read); while (!ioReadEof(read)) { ioRead(read, output); bufCat(decompressed, output); bufUsedZero(output); } ioReadClose(read); bufFree(output); memContextFree(((GzipDecompress *)ioFilterDriver(decompress))->memContext); return decompressed; }
/*********************************************************************************************************************************** Compress data ***********************************************************************************************************************************/ static Buffer * testCompress(IoFilter *compress, Buffer *decompressed, size_t inputSize, size_t outputSize) { Buffer *compressed = bufNew(1024 * 1024); size_t inputTotal = 0; ioBufferSizeSet(outputSize); IoFilterGroup *filterGroup = ioFilterGroupNew(); ioFilterGroupAdd(filterGroup, compress); IoWrite *write = ioBufferWriteNew(compressed); ioWriteFilterGroupSet(write, filterGroup); ioWriteOpen(write); // Compress input data while (inputTotal < bufSize(decompressed)) { // Generate the input buffer based on input size. This breaks the data up into chunks as it would be in a real scenario. Buffer *input = bufNewC( bufPtr(decompressed) + inputTotal, inputSize > bufSize(decompressed) - inputTotal ? bufSize(decompressed) - inputTotal : inputSize); ioWrite(write, input); inputTotal += bufUsed(input); bufFree(input); } ioWriteClose(write); memContextFree(((GzipCompress *)ioFilterDriver(compress))->memContext); return compressed; }
/* * Return a processed source line list for the next line of the file. * The source line list may have several entries if the line is an * includer directive or requires a continuation. */ SrcLineList includeLine(FileName fn, FILE *fin, int *plineno, InclIsContinuedFun iscont) { SrcLineList r; inclBuffer = bufNew(); localAssertList = globalAssertList; fileState.curDir = osCurDirName(); fileState.curFile = strCopy(fnameUnparseStatic(fn)); fileState.curFname = fn; fileState.infile = fin; fileState.fileCodes = 0; fileState.fileNames = 0; fileState.lineNumber= *plineno; ifState = NoIf; r = 0; inclLine(&r, iscont); r = listNReverse(SrcLine)(r); /* Leave the assert list and included files for the next call. */ globalAssertList = localAssertList; bufFree(inclBuffer); /* strFree(fileState.curFile); !!This is held on to by the srclines.*/ listFree(Hash) (fileState.fileCodes); listFree(String)(fileState.fileNames); *plineno = fileState.lineNumber; inclFileLineNo = fileState.lineNumber; return r; }
/*********************************************************************************************************************************** Read all IO into a buffer ***********************************************************************************************************************************/ Buffer * ioReadBuf(IoRead *read) { FUNCTION_TEST_BEGIN(); FUNCTION_TEST_PARAM(IO_READ, read); FUNCTION_TEST_END(); ASSERT(read != NULL); Buffer *result = NULL; MEM_CONTEXT_TEMP_BEGIN() { // Read IO into the buffer result = bufNew(0); do { bufResize(result, bufSize(result) + ioBufferSize()); ioRead(read, result); } while (!ioReadEof(read)); // Resize the buffer and move to calling context bufResize(result, bufUsed(result)); bufMove(result, MEM_CONTEXT_OLD()); } MEM_CONTEXT_TEMP_END(); FUNCTION_TEST_RETURN(result); }
/* * Return a processed source line list of the file contents. */ SrcLineList includeFile(FileName fname) { String fnameString; SrcLineList r; inclSerialLineNo = 0; fnameString = strCopy(fnameUnparseStatic(fname)); inclBuffer = bufNew(); includedFileCodes = 0; localAssertList = listCopy(String)(globalAssertList); fileState.curDir = osCurDirName(); fileState.fileCodes = 0; fileState.fileNames = 0; r = listNReverse(SrcLine)( inclFile(fnameString, false, true, &inclFileLineNo)); strFree(fnameString); bufFree(inclBuffer); listFree(String)(localAssertList); listFree(Hash)(includedFileCodes); return r; }
String strVPrintf(const char *fmt, va_list argp) { Buffer b = bufNew(); bufVPrintf(b, fmt, argp); return bufLiberate(b); }
local String arRdItemArch(Archive ar) { String name = arRdItemArch0(ar); ULong idx = 0L; Buffer buf; String ptr; if (name[0] != '\0') return name; if (name[1] == '/') { /* Do we ever get more than one of these? */ arReadNameTable(ar); /* Just go round again... */ return arRdItemArch(ar); } /* Indirect name: character offset into the name table. */ (void)sscanf(&name[1], "%8lu ", &idx); /* Debugging */ arDEBUG(dbOut, ">>> Reading offset #%lu (out of %lu)\n", idx, (ULong)strLength(ar->names)); /* Start a new character buffer */ buf = bufNew(); /* Jump to the correct place in the buffer */ ptr = ar->names + idx; /* Scan characters up until a / or newline */ while ((*ptr != '\n') && (*ptr != '/') && *ptr) bufPutc(buf, *ptr++); /* Convert the buffer into a text string */ name = bufLiberate(buf); /* Debugging */ arDEBUG(dbOut, ">>> [%s]\n", name); /* Return the name from the directory table */ return name; }
String strPrintf(const char *fmt, ...) { va_list argp; Buffer buf = bufNew(); va_start(argp, fmt); bufVPrintf(buf, fmt, argp); va_end(argp); return bufLiberate(buf); }
void forgTest() { Buffer buf = bufNew(); ForeignOrigin forg1 = forgNew(FOAM_Proto_Java, strCopy("hello")); ForeignOrigin forg2 = forgNew(FOAM_Proto_C, strCopy("world")); ForeignOrigin forg3 = forgNew(FOAM_Proto_C, NULL); ForeignOrigin forg1_r, forg2_r, forg3_r; testTrue("1", forgEqual(forg1, forg1)); testTrue("2", forgEqual(forg2, forg2)); testFalse("3", forgEqual(forg1, forg2)); testFalse("4", forgEqual(forg1, forg3)); forgToBuffer(buf, forg1); forgToBuffer(buf, forg2); bufSetPosition(buf, 0); forg1_r = forgFrBuffer(buf); forg2_r = forgFrBuffer(buf); testTrue("5", forgEqual(forg1_r, forg1)); testTrue("6", forgEqual(forg2_r, forg2)); int pos = bufPosition(buf); bufSetPosition(buf, 0); forgBufferSkip(buf); forgBufferSkip(buf); testIntEqual("7", pos, bufPosition(buf)); bufSetPosition(buf, 0); forgToBuffer(buf, forg3); forgToBuffer(buf, forg1); pos = bufPosition(buf); bufSetPosition(buf, 0); forg3_r = forgFrBuffer(buf); forg1_r = forgFrBuffer(buf); testTrue("8", forgEqual(forg3_r, forg3)); testTrue("8", forgEqual(forg1_r, forg1)); testIntEqual("10", pos, bufPosition(buf)); }
/* * Given the list fnames [z,...,b,a] and punct "->", * allocate the string "'a'->'b'->...->'z'". */ local String inclActiveFileChain(StringList fnames, String punct) { StringList sl0, sl; Buffer buf; String s; int i; buf = bufNew(); sl0 = listReverse(String)(fnames); for (sl = sl0, i = 0; sl; sl = cdr(sl), i++) { if (i > 0) bufPuts(buf, punct); bufPrintf(buf, "'%s'", car(sl)); } s = bufLiberate(buf); listFree(String)(sl0); return s; }
String strReplace(String txt, String orig, String repl) { Buffer buf = bufNew(); String s; int replLen; bufNeed(buf, strlen(orig)); replLen = strlen(repl); while (true) { char *nxt = strstr(txt, orig); if (nxt == NULL) break; bufAddn(buf, txt, nxt-txt); bufAddn(buf, repl, replLen); txt = nxt; txt += strlen(orig); } bufAddn(buf, txt, strlen(txt)); bufAdd1(buf, '\0'); s = bufLiberate(buf); return s; }
/* Evalute all lines in the edit box "id" b/ween "fromLine" and "toLine" */ local void wglEvalLines(int editBox, int fromLine, int toLine) { int i; LPSTR lineStr; Buffer evalBuf = bufNew(); for (i = fromLine; i < toLine; i++) { lineStr = pfcGetLine(editBox, i); if (lineStr[0] == NULL) continue; /* Skip blank lines */ bufPuts(evalBuf, lineStr); bufPutc(evalBuf, '\n'); } bufPutc(evalBuf, EOF); bufStart(evalBuf); osSetStdinBuffer(evalBuf); compGLoopEval(osStdin, osStdout, finfo); wglShowOutput(editBox); bufFree(evalBuf); }
/*********************************************************************************************************************************** Test Run ***********************************************************************************************************************************/ void testRun(void) { FUNCTION_HARNESS_VOID(); // Additional coverage not provided by testing with actual certificates // ***************************************************************************************************************************** if (testBegin("asn1ToStr(), tlsClientHostVerify(), and tlsClientHostVerifyName()")) { TEST_ERROR(asn1ToStr(NULL), CryptoError, "TLS certificate name entry is missing"); TEST_ERROR( tlsClientHostVerifyName( strNew("host"), strNewN("ab\0cd", 5)), CryptoError, "TLS certificate name contains embedded null"); TEST_ERROR(tlsClientHostVerify(strNew("host"), NULL), CryptoError, "No certificate presented by the TLS server"); TEST_RESULT_BOOL(tlsClientHostVerifyName(strNew("host"), strNew("**")), false, "invalid pattern"); TEST_RESULT_BOOL(tlsClientHostVerifyName(strNew("host"), strNew("*.")), false, "invalid pattern"); TEST_RESULT_BOOL(tlsClientHostVerifyName(strNew("a.bogus.host.com"), strNew("*.host.com")), false, "invalid host"); } // ***************************************************************************************************************************** if (testBegin("TlsClient verification")) { TlsClient *client = NULL; // Connection errors // ------------------------------------------------------------------------------------------------------------------------- TEST_ASSIGN(client, tlsClientNew(strNew("99.99.99.99.99"), 9443, 0, true, NULL, NULL), "new client"); TEST_ERROR( tlsClientOpen(client), HostConnectError, "unable to get address for '99.99.99.99.99': [-2] Name or service not known"); TEST_ASSIGN(client, tlsClientNew(strNew("localhost"), 9443, 100, true, NULL, NULL), "new client"); TEST_ERROR(tlsClientOpen(client), HostConnectError, "unable to connect to 'localhost:9443': [111] Connection refused"); // Certificate location and validation errors // ------------------------------------------------------------------------------------------------------------------------- // Add test hosts if (system( // {uncoverable_branch} "echo \"127.0.0.1 test.pgbackrest.org host.test2.pgbackrest.org test3.pgbackrest.org\" |" " sudo tee -a /etc/hosts > /dev/null") != 0) { THROW(AssertError, "unable to add test hosts to /etc/hosts"); // {uncovered+} } // Start server to test various certificate errors testTlsServerAltName(); TEST_ERROR( tlsClientOpen(tlsClientNew(strNew("localhost"), 9443, 500, true, strNew("bogus.crt"), strNew("/bogus"))), CryptoError, "unable to set user-defined CA certificate location: [33558530] No such file or directory"); TEST_ERROR( tlsClientOpen(tlsClientNew(strNew("localhost"), 9443, 500, true, NULL, strNew("/bogus"))), CryptoError, "unable to verify certificate presented by 'localhost:9443': [20] unable to get local issuer certificate"); TEST_RESULT_VOID( tlsClientOpen( tlsClientNew(strNew("test.pgbackrest.org"), 9443, 500, true, strNewFmt("%s/" TEST_CERTIFICATE_PREFIX "-ca.crt", testRepoPath()), NULL)), "success on valid ca file and match common name"); TEST_RESULT_VOID( tlsClientOpen( tlsClientNew(strNew("host.test2.pgbackrest.org"), 9443, 500, true, strNewFmt("%s/" TEST_CERTIFICATE_PREFIX "-ca.crt", testRepoPath()), NULL)), "success on valid ca file and match alt name"); TEST_ERROR( tlsClientOpen( tlsClientNew(strNew("test3.pgbackrest.org"), 9443, 500, true, strNewFmt("%s/" TEST_CERTIFICATE_PREFIX "-ca.crt", testRepoPath()), NULL)), CryptoError, "unable to find hostname 'test3.pgbackrest.org' in certificate common name or subject alternative names"); TEST_ERROR( tlsClientOpen( tlsClientNew(strNew("localhost"), 9443, 500, true, strNewFmt("%s/" TEST_CERTIFICATE_PREFIX ".crt", testRepoPath()), NULL)), CryptoError, "unable to verify certificate presented by 'localhost:9443': [20] unable to get local issuer certificate"); TEST_RESULT_VOID( tlsClientOpen(tlsClientNew(strNew("localhost"), 9443, 500, false, NULL, NULL)), "success on no verify"); } // ***************************************************************************************************************************** if (testBegin("TlsClient general usage")) { TlsClient *client = NULL; // Reset statistics tlsClientStatLocal = (TlsClientStat){0}; TEST_RESULT_STR(tlsClientStatStr(), NULL, "no stats yet"); testTlsServer(); ioBufferSizeSet(12); TEST_ASSIGN(client, tlsClientNew(strNew(TLS_TEST_HOST), 9443, 500, true, NULL, NULL), "new client"); TEST_RESULT_VOID(tlsClientOpen(client), "open client"); const Buffer *input = BUFSTRDEF("some protocol info"); TEST_RESULT_VOID(ioWrite(tlsClientIoWrite(client), input), "write input"); ioWriteFlush(tlsClientIoWrite(client)); TEST_RESULT_STR(strPtr(ioReadLine(tlsClientIoRead(client))), "something:0", "read line"); TEST_RESULT_BOOL(ioReadEof(tlsClientIoRead(client)), false, " check eof = false"); Buffer *output = bufNew(12); TEST_RESULT_INT(ioRead(tlsClientIoRead(client), output), 12, "read output"); TEST_RESULT_STR(strPtr(strNewBuf(output)), "some content", " check output"); TEST_RESULT_BOOL(ioReadEof(tlsClientIoRead(client)), false, " check eof = false"); output = bufNew(8); TEST_RESULT_INT(ioRead(tlsClientIoRead(client), output), 8, "read output"); TEST_RESULT_STR(strPtr(strNewBuf(output)), "AND MORE", " check output"); TEST_RESULT_BOOL(ioReadEof(tlsClientIoRead(client)), false, " check eof = false"); output = bufNew(12); TEST_ERROR( ioRead(tlsClientIoRead(client), output), FileReadError, "unable to read data from 'tls.test.pgbackrest.org:9443' after 500ms"); // ------------------------------------------------------------------------------------------------------------------------- input = BUFSTRDEF("more protocol info"); TEST_RESULT_VOID(tlsClientOpen(client), "open client again (it is already open)"); TEST_RESULT_VOID(ioWrite(tlsClientIoWrite(client), input), "write input"); ioWriteFlush(tlsClientIoWrite(client)); output = bufNew(12); TEST_RESULT_INT(ioRead(tlsClientIoRead(client), output), 12, "read output"); TEST_RESULT_STR(strPtr(strNewBuf(output)), "0123456789AB", " check output"); TEST_RESULT_BOOL(ioReadEof(tlsClientIoRead(client)), false, " check eof = false"); output = bufNew(12); TEST_RESULT_INT(ioRead(tlsClientIoRead(client), output), 0, "read no output after eof"); TEST_RESULT_BOOL(ioReadEof(tlsClientIoRead(client)), true, " check eof = true"); TEST_RESULT_BOOL(tlsClientStatStr() != NULL, true, "check statistics exist"); TEST_RESULT_VOID(tlsClientFree(client), "free client"); } FUNCTION_HARNESS_RESULT_VOID(); }
/*********************************************************************************************************************************** Test Run ***********************************************************************************************************************************/ void testRun(void) { FUNCTION_HARNESS_VOID(); // ***************************************************************************************************************************** if (testBegin("gzipError")) { TEST_RESULT_INT(gzipError(Z_OK), Z_OK, "check ok"); TEST_RESULT_INT(gzipError(Z_STREAM_END), Z_STREAM_END, "check stream end"); TEST_ERROR(gzipError(Z_NEED_DICT), AssertError, "zlib threw error: [2] need dictionary"); TEST_ERROR(gzipError(Z_ERRNO), AssertError, "zlib threw error: [-1] file error"); TEST_ERROR(gzipError(Z_STREAM_ERROR), FormatError, "zlib threw error: [-2] stream error"); TEST_ERROR(gzipError(Z_DATA_ERROR), FormatError, "zlib threw error: [-3] data error"); TEST_ERROR(gzipError(Z_MEM_ERROR), MemoryError, "zlib threw error: [-4] insufficient memory"); TEST_ERROR(gzipError(Z_BUF_ERROR), AssertError, "zlib threw error: [-5] no space in buffer"); TEST_ERROR(gzipError(Z_VERSION_ERROR), FormatError, "zlib threw error: [-6] incompatible version"); TEST_ERROR(gzipError(999), AssertError, "zlib threw error: [999] unknown error"); } // ***************************************************************************************************************************** if (testBegin("gzipWindowBits")) { TEST_RESULT_INT(gzipWindowBits(true), -15, "raw window bits"); TEST_RESULT_INT(gzipWindowBits(false), 31, "gzip window bits"); } // ***************************************************************************************************************************** if (testBegin("GzipCompress and GzipDecompress")) { const char *simpleData = "A simple string"; Buffer *compressed = NULL; Buffer *decompressed = bufNewC(simpleData, strlen(simpleData)); TEST_ASSIGN( compressed, testCompress(gzipCompressNew(3, false), decompressed, 1024, 1024), "simple data - compress large in/large out buffer"); TEST_RESULT_BOOL( bufEq(compressed, testCompress(gzipCompressNew(3, false), decompressed, 1024, 1)), true, "simple data - compress large in/small out buffer"); TEST_RESULT_BOOL( bufEq(compressed, testCompress(gzipCompressNew(3, false), decompressed, 1, 1024)), true, "simple data - compress small in/large out buffer"); TEST_RESULT_BOOL( bufEq(compressed, testCompress(gzipCompressNew(3, false), decompressed, 1, 1)), true, "simple data - compress small in/small out buffer"); TEST_RESULT_BOOL( bufEq(decompressed, testDecompress(gzipDecompressNew(false), compressed, 1024, 1024)), true, "simple data - decompress large in/large out buffer"); TEST_RESULT_BOOL( bufEq(decompressed, testDecompress(gzipDecompressNew(false), compressed, 1024, 1)), true, "simple data - decompress large in/small out buffer"); TEST_RESULT_BOOL( bufEq(decompressed, testDecompress(gzipDecompressNew(false), compressed, 1, 1024)), true, "simple data - decompress small in/large out buffer"); TEST_RESULT_BOOL( bufEq(decompressed, testDecompress(gzipDecompressNew(false), compressed, 1, 1)), true, "simple data - decompress small in/small out buffer"); // Compress a large zero input buffer into small output buffer // ------------------------------------------------------------------------------------------------------------------------- decompressed = bufNew(1024 * 1024 - 1); memset(bufPtr(decompressed), 0, bufSize(decompressed)); bufUsedSet(decompressed, bufSize(decompressed)); TEST_ASSIGN( compressed, testCompress(gzipCompressNew(3, true), decompressed, bufSize(decompressed), 1024), "zero data - compress large in/small out buffer"); TEST_RESULT_BOOL( bufEq(decompressed, testDecompress(gzipDecompressNew(true), compressed, bufSize(compressed), 1024 * 256)), true, "zero data - decompress large in/small out buffer"); } // ***************************************************************************************************************************** if (testBegin("gzipDecompressToLog() and gzipCompressToLog()")) { GzipDecompress *decompress = (GzipDecompress *)ioFilterDriver(gzipDecompressNew(false)); TEST_RESULT_STR(strPtr(gzipDecompressToLog(decompress)), "{inputSame: false, done: false, availIn: 0}", "format object"); decompress->inputSame = true; decompress->done = true; TEST_RESULT_STR(strPtr(gzipDecompressToLog(decompress)), "{inputSame: true, done: true, availIn: 0}", "format object"); } FUNCTION_HARNESS_RESULT_VOID(); }
/*********************************************************************************************************************************** Test Run ***********************************************************************************************************************************/ void testRun(void) { FUNCTION_HARNESS_VOID(); // ***************************************************************************************************************************** if (testBegin("strNew(), strNewBuf(), strNewN(), strEmpty(), strPtr(), strSize(), and strFree()")) { // We don't want this struct to grow since there are generally a lot of strings, so make sure it doesn't grow without us // knowing about it TEST_RESULT_UINT(sizeof(StringConst), TEST_64BIT() ? 16 : 12, "check StringConst struct size"); // Test the size macro TEST_RESULT_VOID(CHECK_SIZE(555), "valid size"); TEST_ERROR(CHECK_SIZE(STRING_SIZE_MAX + 1), AssertError, "string size must be <= 1073741824 bytes"); String *string = strNew("static string"); TEST_RESULT_STR(strPtr(string), "static string", "new with static string"); TEST_RESULT_INT(strSize(string), 13, "check size"); TEST_RESULT_BOOL(strEmpty(string), false, "is not empty"); TEST_RESULT_INT(strlen(strPtr(string)), 13, "check size with strlen()"); TEST_RESULT_CHAR(strPtr(string)[2], 'a', "check character"); TEST_RESULT_VOID(strFree(string), "free string"); // ------------------------------------------------------------------------------------------------------------------------- TEST_RESULT_STR(strPtr(strNewN("testmorestring", 4)), "test", "new string with size limit"); // ------------------------------------------------------------------------------------------------------------------------- Buffer *buffer = bufNew(8); memcpy(bufPtr(buffer), "12345678", 8); bufUsedSet(buffer, 8); TEST_RESULT_STR(strPtr(strNewBuf(buffer)), "12345678", "new string from buffer"); // ------------------------------------------------------------------------------------------------------------------------- string = strNewFmt("formatted %s %04d", "string", 1); TEST_RESULT_STR(strPtr(string), "formatted string 0001", "new with formatted string"); TEST_RESULT_PTR(strPtr(NULL), NULL, "null string pointer"); TEST_RESULT_VOID(strFree(string), "free string"); TEST_RESULT_VOID(strFree(NULL), "free null string"); } // ***************************************************************************************************************************** if (testBegin("STRING_STATIC()")) { TEST_RESULT_STR(strPtr(TEST_STRING), "a very interesting string!", "check static string"); TEST_RESULT_STR(strPtr(strSubN(TEST_STRING, 0, 6)), "a very", "read-only strSub() works"); } // ***************************************************************************************************************************** if (testBegin("strBase() and strPath()")) { TEST_RESULT_STR(strPtr(strBase(STRDEF(""))), "", "empty string"); TEST_RESULT_STR(strPtr(strBase(STRDEF("/"))), "", "/ only"); TEST_RESULT_STR(strPtr(strBase(STRDEF("/file"))), "file", "root file"); TEST_RESULT_STR(strPtr(strBase(STRDEF("/dir1/dir2/file"))), "file", "subdirectory file"); TEST_RESULT_STR(strPtr(strPath(STRDEF(""))), "", "empty string"); TEST_RESULT_STR(strPtr(strPath(STRDEF("/"))), "/", "/ only"); TEST_RESULT_STR(strPtr(strPath(STRDEF("/file"))), "/", "root path"); TEST_RESULT_STR(strPtr(strPath(STRDEF("/dir1/dir2/file"))), "/dir1/dir2", "subdirectory file"); } // ***************************************************************************************************************************** if (testBegin("strCat(), strCatChr(), and strCatFmt()")) { String *string = strNew("XXXX"); String *string2 = strNew("ZZZZ"); TEST_RESULT_STR(strPtr(strCat(string, "YYYY")), "XXXXYYYY", "cat string"); TEST_RESULT_SIZE(string->extra, 4, "check extra"); TEST_RESULT_STR(strPtr(strCatFmt(string, "%05d", 777)), "XXXXYYYY00777", "cat formatted string"); TEST_RESULT_SIZE(string->extra, 6, "check extra"); TEST_RESULT_STR(strPtr(strCatChr(string, '!')), "XXXXYYYY00777!", "cat chr"); TEST_RESULT_SIZE(string->extra, 5, "check extra"); TEST_RESULT_STR(strPtr(string2), "ZZZZ", "check unaltered string"); } // ***************************************************************************************************************************** if (testBegin("strDup()")) { const String *string = STRDEF("duplicated string"); String *stringDup = strDup(string); TEST_RESULT_STR(strPtr(stringDup), strPtr(string), "duplicated strings match"); TEST_RESULT_PTR(strDup(NULL), NULL, "duplicate null string"); } // ***************************************************************************************************************************** if (testBegin("strBeginsWith() and strBeginsWithZ()")) { TEST_RESULT_BOOL(strBeginsWith(STRDEF(""), STRDEF("aaa")), false, "empty string"); TEST_RESULT_BOOL(strBeginsWith(STRDEF("astring"), STRDEF("")), true, "empty begins with"); TEST_RESULT_BOOL(strBeginsWithZ(STRDEF("astring"), "astr"), true, "partial begins with"); TEST_RESULT_BOOL(strBeginsWithZ(STRDEF("astring"), "astring"), true, "equal strings"); } // ***************************************************************************************************************************** if (testBegin("strEndsWith() and strEndsWithZ()")) { TEST_RESULT_BOOL(strEndsWith(STRDEF(""), STRDEF(".doc")), false, "empty string"); TEST_RESULT_BOOL(strEndsWith(STRDEF("astring"), STRDEF("")), true, "empty ends with"); TEST_RESULT_BOOL(strEndsWithZ(STRDEF("astring"), "ing"), true, "partial ends with"); TEST_RESULT_BOOL(strEndsWithZ(STRDEF("astring"), "astring"), true, "equal strings"); } // ***************************************************************************************************************************** if (testBegin("strEq(), strEqZ(), strCmp(), strCmpZ()")) { TEST_RESULT_BOOL(strEq(STRDEF("equalstring"), STRDEF("equalstring")), true, "strings equal"); TEST_RESULT_BOOL(strEq(STRDEF("astring"), STRDEF("anotherstring")), false, "strings not equal"); TEST_RESULT_BOOL(strEq(STRDEF("astring"), STRDEF("bstring")), false, "equal length strings not equal"); TEST_RESULT_INT(strCmp(STRDEF("equalstring"), STRDEF("equalstring")), 0, "strings equal"); TEST_RESULT_INT(strCmp(STRDEF("a"), STRDEF("b")), -1, "a < b"); TEST_RESULT_INT(strCmp(STRDEF("b"), STRDEF("a")), 1, "b > a"); TEST_RESULT_BOOL(strEqZ(STRDEF("equalstring"), "equalstring"), true, "strings equal"); TEST_RESULT_BOOL(strEqZ(STRDEF("astring"), "anotherstring"), false, "strings not equal"); TEST_RESULT_BOOL(strEqZ(STRDEF("astring"), "bstring"), false, "equal length strings not equal"); TEST_RESULT_INT(strCmpZ(STRDEF("equalstring"), "equalstring"), 0, "strings equal"); TEST_RESULT_INT(strCmpZ(STRDEF("a"), "b"), -1, "a < b"); TEST_RESULT_INT(strCmpZ(STRDEF("b"), "a"), 1, "b > a"); } // ***************************************************************************************************************************** if (testBegin("strFirstUpper(), strFirstLower(), strUpper(), strLower()")) { TEST_RESULT_STR(strPtr(strFirstUpper(strNew(""))), "", "empty first upper"); TEST_RESULT_STR(strPtr(strFirstUpper(strNew("aaa"))), "Aaa", "first upper"); TEST_RESULT_STR(strPtr(strFirstUpper(strNew("Aaa"))), "Aaa", "first already upper"); TEST_RESULT_STR(strPtr(strFirstLower(strNew(""))), "", "empty first lower"); TEST_RESULT_STR(strPtr(strFirstLower(strNew("AAA"))), "aAA", "first lower"); TEST_RESULT_STR(strPtr(strFirstLower(strNew("aAA"))), "aAA", "first already lower"); TEST_RESULT_STR(strPtr(strLower(strNew("K123aBc"))), "k123abc", "all lower"); TEST_RESULT_STR(strPtr(strLower(strNew("k123abc"))), "k123abc", "already lower"); TEST_RESULT_STR(strPtr(strLower(strNew("C"))), "c", "char lower"); TEST_RESULT_STR(strPtr(strLower(strNew(""))), "", "empty lower"); TEST_RESULT_STR(strPtr(strUpper(strNew("K123aBc"))), "K123ABC", "all upper"); TEST_RESULT_STR(strPtr(strUpper(strNew("K123ABC"))), "K123ABC", "already upper"); TEST_RESULT_STR(strPtr(strUpper(strNew("c"))), "C", "char upper"); TEST_RESULT_STR(strPtr(strUpper(strNew(""))), "", "empty upper"); } // ***************************************************************************************************************************** if (testBegin("strQuote()")) { TEST_RESULT_STR(strPtr(strQuote(STRDEF("abcd"), STRDEF("'"))), "'abcd'", "quote string"); } // ***************************************************************************************************************************** if (testBegin("strReplaceChr()")) { TEST_RESULT_STR(strPtr(strReplaceChr(strNew("ABCD"), 'B', 'R')), "ARCD", "replace chr"); } // ***************************************************************************************************************************** if (testBegin("strSub() and strSubN()")) { TEST_RESULT_STR(strPtr(strSub(STRDEF("ABCD"), 2)), "CD", "sub string"); TEST_RESULT_STR(strPtr(strSubN(STRDEF("ABCD"), 1, 2)), "BC", "sub string with length"); } // ***************************************************************************************************************************** if (testBegin("strTrim()")) { TEST_RESULT_STR(strPtr(strTrim(strNew(""))), "", "trim empty"); TEST_RESULT_STR(strPtr(strTrim(strNew("X"))), "X", "no trim (one char)"); TEST_RESULT_STR(strPtr(strTrim(strNew("no-trim"))), "no-trim", "no trim (string)"); TEST_RESULT_STR(strPtr(strTrim(strNew(" \t\r\n"))), "", "all whitespace"); TEST_RESULT_STR(strPtr(strTrim(strNew(" \tbegin-only"))), "begin-only", "trim begin"); TEST_RESULT_STR(strPtr(strTrim(strNew("end-only\t "))), "end-only", "trim end"); TEST_RESULT_STR(strPtr(strTrim(strNew("\n\rboth\r\n"))), "both", "trim both"); TEST_RESULT_STR(strPtr(strTrim(strNew("begin \r\n\tend"))), "begin \r\n\tend", "ignore whitespace in middle"); } // ***************************************************************************************************************************** if (testBegin("strChr() and strTrunc()")) { TEST_RESULT_INT(strChr(STRDEF("abcd"), 'c'), 2, "c found"); TEST_RESULT_INT(strChr(STRDEF("abcd"), 'C'), -1, "capital C not found"); TEST_RESULT_INT(strChr(STRDEF("abcd"), 'i'), -1, "i not found"); TEST_RESULT_INT(strChr(STRDEF(""), 'x'), -1, "empty string - x not found"); String *val = strNew("abcdef"); TEST_ERROR( strTrunc(val, (int)(strSize(val) + 1)), AssertError, "assertion 'idx >= 0 && (size_t)idx <= this->size' failed"); TEST_ERROR(strTrunc(val, -1), AssertError, "assertion 'idx >= 0 && (size_t)idx <= this->size' failed"); TEST_RESULT_STR(strPtr(strTrunc(val, strChr(val, 'd'))), "abc", "simple string truncated"); strCat(val, "\r\n to end"); TEST_RESULT_STR(strPtr(strTrunc(val, strChr(val, 'n'))), "abc\r\n to e", "complex string truncated"); TEST_RESULT_STR(strPtr(strTrunc(val, strChr(val, 'a'))), "", "complete string truncated - empty string"); TEST_RESULT_INT(strSize(val), 0, "0 size"); TEST_RESULT_STR(strPtr(strTrunc(val, 0)), "", "test coverage of empty string - no error thrown for index 0"); } // ***************************************************************************************************************************** if (testBegin("strToLog() and strObjToLog()")) { TEST_RESULT_STR(strPtr(strToLog(STRDEF("test"))), "{\"test\"}", "format string"); TEST_RESULT_STR(strPtr(strToLog(NULL)), "null", "format null string"); char buffer[256]; TEST_RESULT_UINT(strObjToLog(NULL, (StrObjToLogFormat)strToLog, buffer, sizeof(buffer)), 4, "format null string"); TEST_RESULT_STR(buffer, "null", "check null string"); TEST_RESULT_UINT(strObjToLog(STRDEF("teststr"), (StrObjToLogFormat)strToLog, buffer, sizeof(buffer)), 11, "format string"); TEST_RESULT_STR(buffer, "{\"teststr\"}", "check string"); } // ***************************************************************************************************************************** if (testBegin("strSizeFormat()")) { TEST_RESULT_STR(strPtr(strSizeFormat(0)), "0B", "zero bytes"); TEST_RESULT_STR(strPtr(strSizeFormat(1023)), "1023B", "1023 bytes"); TEST_RESULT_STR(strPtr(strSizeFormat(1024)), "1KB", "1 KB"); TEST_RESULT_STR(strPtr(strSizeFormat(2200)), "2.1KB", "2.1 KB"); TEST_RESULT_STR(strPtr(strSizeFormat(1048576)), "1MB", "1 MB"); TEST_RESULT_STR(strPtr(strSizeFormat(20162900)), "19.2MB", "19.2 MB"); TEST_RESULT_STR(strPtr(strSizeFormat(1073741824)), "1GB", "1 GB"); TEST_RESULT_STR(strPtr(strSizeFormat(1073741824 + 107374183)), "1.1GB", "1.1 GB"); TEST_RESULT_STR(strPtr(strSizeFormat(UINT64_MAX)), "17179869183GB", "uint64 max"); } // ***************************************************************************************************************************** if (testBegin("strLstNew(), strLstAdd*(), strLstGet(), strLstMove(), strLstSize(), and strLstFree()")) { // Add strings to the list // ------------------------------------------------------------------------------------------------------------------------- StringList *list = NULL; MEM_CONTEXT_TEMP_BEGIN() { list = strLstNew(); for (int listIdx = 0; listIdx <= LIST_INITIAL_SIZE; listIdx++) { if (listIdx == 0) { TEST_RESULT_PTR(strLstAdd(list, NULL), list, "add null item"); } else TEST_RESULT_PTR(strLstAdd(list, strNewFmt("STR%02d", listIdx)), list, "add item %d", listIdx); } strLstMove(list, MEM_CONTEXT_OLD()); } MEM_CONTEXT_TEMP_END(); TEST_RESULT_INT(strLstSize(list), 9, "list size"); // Read them back and check values // ------------------------------------------------------------------------------------------------------------------------- for (unsigned int listIdx = 0; listIdx < strLstSize(list); listIdx++) { if (listIdx == 0) { TEST_RESULT_PTR(strLstGet(list, listIdx), NULL, "check null item"); } else TEST_RESULT_STR(strPtr(strLstGet(list, listIdx)), strPtr(strNewFmt("STR%02u", listIdx)), "check item %u", listIdx); } TEST_RESULT_VOID(strLstFree(list), "free string list"); TEST_RESULT_VOID(strLstFree(NULL), "free null string list"); }
static void ccInitCommand() { ccBuf = bufNew(); }