/*H********************************************************************************/ /*! \File netprint.c \Description Test ds_vsnprintf() for compliance with standard routines. \Copyright Copyright (c) 2009-2010 Electronic Arts Inc. \Version 10/28/2009 (jbrookes) First Version */ /********************************************************************************H*/ /*** Include files ****************************************************************/ #include #include #include #include #include "DirtySDK/platform.h" #include "DirtySDK/dirtysock/dirtynet.h" #include "DirtySDK/dirtysock/netconn.h" #include "libsample/zlib.h" #include "testermodules.h" /*** Defines **********************************************************************/ /*** Type Definitions *************************************************************/ /*** Variables ********************************************************************/ // Variables /*** Private Functions ************************************************************/ /*F********************************************************************************/ /*! \Function _NetFormatAddr6 \Description Initialize a struct sockaddr_in6 given address and port \Input *pAddr6 - address to fill in \Input *pWords - 128 bit address \Input *uPort - port \Version 09/01/2017 (jbrookes) */ /********************************************************************************F*/ #if !defined(DIRTYCODE_NX) static void _NetFormatAddr6(struct sockaddr_in6 *pAddr6, const uint16_t *pWords, uint16_t uPort) { int32_t iWord; ds_memclr(pAddr6, sizeof(*pAddr6)); pAddr6->sin6_family = AF_INET6; pAddr6->sin6_port = SocketNtohs(uPort); pAddr6->sin6_flowinfo = 0; for (iWord = 0; iWord < 8; iWord += 1) { pAddr6->sin6_addr.s6_addr[(iWord*2)+0] = (uint8_t)(pWords[iWord]>>8); pAddr6->sin6_addr.s6_addr[(iWord*2)+1] = (uint8_t)(pWords[iWord]&0xff); } } #endif /*F********************************************************************************/ /*! \Function _NetPrintStrCmp \Description Compare two strings; if they are the same, print one out, otherwise print both out. \Input *pStrCtrl - pointer to "control" string (what we are expecting) \Input *pStrTest - pointer to "test" string (what we actually produced) \Input *pStrType - pointer to type field, to use in displaying the result \Output int32_t - 0=same, 1=different \Version 05/05/2010 (jbrookes) */ /********************************************************************************F*/ static int32_t _NetPrintStrCmp(const char *pStrCtrl, const char *pStrTest, const char *pStrType) { int32_t iResult; if (strcmp(pStrCtrl, pStrTest) != 0) { ZPrintf("netprint: [%s] ctrl(%s) != test(%s)\n", pStrType, pStrCtrl, pStrTest); iResult = 1; } else { ZPrintf("netprint: [%s] \"%s\"\n", pStrType, pStrTest); iResult = 0; } return(iResult); } /*F********************************************************************************/ /*! \Function _NetPrintMemCmp \Description Compare two buffers; if they are the same, print one out, otherwise print both out. \Input *pCtrl - pointer to "control" buffer (what we are expecting) \Input *pTest - pointer to "test" buffer (what we actually produced) \Input iLen - buffer length \Input *pType - pointer to type field, to use in displaying the result \Output int32_t - 0=same, 1=different \Version 09/01/2017 (jbrookes) */ /********************************************************************************F*/ #ifndef DIRTYCODE_NX static int32_t _NetPrintMemCmp(const uint8_t *pCtrl, int32_t iCtrlLen, const uint8_t *pTest, int32_t iTestLen, const char *pStrType) { int32_t iResult = 1; if (iCtrlLen != iTestLen) { ZPrintf("netprint: [%s] ctrllen(%d) != testlen(%d)\n", pStrType, iCtrlLen, iTestLen); } else if (memcmp(pCtrl, pTest, iCtrlLen) != 0) { ZPrintf("netprint: [%s] ctrl != test\n", pStrType); NetPrintMem(pCtrl, iCtrlLen, "ctrl"); NetPrintMem(pTest, iCtrlLen, "test"); } else { ZPrintf("netprint: [%s] ctrl=test\n", pStrType); iResult = 0; } return(iResult); } #endif /*F********************************************************************************/ /*! \Function _NetPrintStrIntCmp \Description Compare two strings AND two results; if they are the same, print one out, otherwise print both out. \Input *pStrCtrl - pointer to "control" string (what we are expecting) \Input *_pStrTest - pointer to "test" string (what we actually produced) \Input iCtrlRslt - expected result \Input iTestRslt - actual result \Input iBufferLimit - size of buffer we were writing into \Input *pStrType - pointer to type field, to use in displaying the result \Output int32_t - 0=same, 1=different \Version 02/15/2011 (jbrookes) */ /********************************************************************************F*/ static int32_t _NetPrintStrIntCmp(const char *pStrCtrl, const char *_pStrTest, int32_t iCtrlRslt, int32_t iTestRslt, int32_t iBufferLimit, const char *pStrType) { int32_t iResult, iStrCmp; const char *pStrTest; // if we have a zero-sized buffer, point to an empty string so we can compare/print it safely pStrTest = (iBufferLimit > 0) ? _pStrTest : ""; // compare the strings iStrCmp = strcmp(pStrCtrl, pStrTest); if ((iStrCmp != 0) && (iCtrlRslt != iTestRslt)) { ZPrintf("netprint: [%s] ctrl(%s) != test(%s) and ctrl(%d) != test(%d)\n", pStrType, pStrCtrl, pStrTest, iCtrlRslt, iTestRslt); iResult = 1; } else if (iStrCmp != 0) { ZPrintf("netprint: [%s] ctrl(%s) != test(%s)\n", pStrType, pStrCtrl, pStrTest); iResult = 1; } else if (iCtrlRslt != iTestRslt) { ZPrintf("netprint: [%s] ctrl(%d) != test(%d)\n", pStrType, iCtrlRslt, iTestRslt); iResult = 1; } else { if (iTestRslt > 0) { ZPrintf("netprint: [%s] \"%s\" (%d)\n", pStrType, pStrTest, iTestRslt); } else { ZPrintf("netprint: [%s] "" (%d)\n", pStrType, iTestRslt); } iResult = 0; } return(iResult); } /*F********************************************************************************/ /*! \Function _NetPrintFloat \Description Print a floating-point value with both ds_snzprintf and platform sprintf(), and compare the results. Flag a warning if they are different. \Input *pFmt - format string \Input fValue - float to print \Output int32_t - 0=same, 1=different \Version 05/05/2010 (jbrookes) */ /********************************************************************************F*/ static int32_t _NetPrintFloat(const char *pFmt, double fValue) { char strCtrl[256], strTest[256]; sprintf(strCtrl, pFmt, fValue); ds_snzprintf(strTest, sizeof(strTest), pFmt, fValue); return(_NetPrintStrCmp(strCtrl, strTest, "flt")); } /*F********************************************************************************/ /*! \Function _NetPrintInt \Description Print an integer value with both ds_snzprintf and platform sprintf(), and compare the results. Flag a warning if they are different. \Input *pFmt - format string \Input iValue - integer to print \Output int32_t - 0=same, 1=different \Version 05/05/2010 (jbrookes) */ /********************************************************************************F*/ static int32_t _NetPrintInt(const char *pFmt, int32_t iValue) { char strCtrl[256], strTest[256]; sprintf(strCtrl, pFmt, iValue); ds_snzprintf(strTest, sizeof(strTest), pFmt, iValue); return(_NetPrintStrCmp(strCtrl, strTest, "int")); } /*F********************************************************************************/ /*! \Function _NetPrintLongInt \Description Print a 64-bit integer value with both ds_snzprintf and platform sprintf(), and compare the results. Flag a warning if they are different. \Input *pFmt - format string \Input iValue - 64-bit integer to print \Output int32_t - 0=same, 1=different \Version 05/05/2010 (jbrookes) */ /********************************************************************************F*/ static int32_t _NetPrintLongInt(const char *pFmt, int64_t iValue) { char strCtrl[256], strTest[256]; sprintf(strCtrl, pFmt, iValue); ds_snzprintf(strTest, sizeof(strTest), pFmt, iValue); return(_NetPrintStrCmp(strCtrl, strTest, "lng")); } /*F********************************************************************************/ /*! \Function _NetPrintStr \Description Print a string with both ds_snzprintf() and platform sprintf(), and compare the results. Flag a warning if they are different. \Input *pFmt - format string \Input *pStr - string to print \Output int32_t - 0=same, 1=different \Version 05/05/2010 (jbrookes) */ /********************************************************************************F*/ static int32_t _NetPrintStr(const char *pFmt, const char *pStr) { char strCtrl[256], strTest[256]; sprintf(strCtrl, pFmt, pStr); ds_snzprintf(strTest, sizeof(strTest), pFmt, pStr); return(_NetPrintStrCmp(strCtrl, strTest, "str")); } /*F********************************************************************************/ /*! \Function _NetPrintPregen \Description Print formatted output with ds_vsnprintf() and compare to a pre-generated (static) string. Flag a warning if they are different. \Input *pPreGen - pointer to pre-generated string (what we expect) \Input *pFmt - format specifier \Input ... - variable argument list \Output int32_t - 0=same, 1=different \Version 05/05/2010 (jbrookes) */ /********************************************************************************F*/ static int32_t _NetPrintPregen(const char *pPreGen, const char *pFmt, ...) { char strTest[1024]; va_list Args; // format the output va_start(Args, pFmt); ds_vsnprintf(strTest, sizeof(strTest), pFmt, Args); va_end(Args); return(_NetPrintStrCmp(pPreGen, strTest, "pre")); } /*F********************************************************************************/ /*! \Function _NetPrintOverflow \Description Print formatted output with ds_vsnprintf() and compare to a pre-generated (static) string. Flag a warning if they are different. \Input iBufferLimit - size we want to limit buffer to \Input *pPreGen - pre-generated string to compare formatted result to \Input iExpectedResult - expected result code from ds_vsnzprintf() \Input *pFmt - format specifier \Input ... - variable argument list \Output int32_t - 0=same, 1=different \Version 02/15/2011 (jbrookes) */ /********************************************************************************F*/ static int32_t _NetPrintOverflow(int32_t iBufferLimit, const char *pPreGen, int32_t iExpectedResult, const char *pFmt, ...) { char strTest[128]; int32_t iResult, iStrCmp, iCheck, iMemStomp; char cMemChar = 0xcc; va_list Args; // pre-initialize array ds_memset(strTest, cMemChar, sizeof(strTest)); // format the output va_start(Args, pFmt); iResult = ds_vsnzprintf(strTest, iBufferLimit, pFmt, Args); va_end(Args); // make sure we didn't write outside our bounds for (iCheck = iBufferLimit, iMemStomp = 0; iCheck < (signed)sizeof(strTest); iCheck += 1) { if (strTest[iCheck] != cMemChar) { iMemStomp += 1; } } // did the test succeed or fail? iStrCmp = _NetPrintStrIntCmp(pPreGen, strTest, iExpectedResult, iResult, iBufferLimit, "ovr"); if ((iStrCmp != 0) || (iMemStomp != 0)) { return(1); } else { return(0); } } /*F********************************************************************************/ /*! \Function _NetPrintTestFlts \Description Execute a series of floating-point printing tests. \Output int32_t - number of test failures \Version 05/05/2010 (jbrookes) */ /********************************************************************************F*/ static int32_t _NetPrintTestFlts(void) { int32_t iResult = 0; ZPrintf("netprint: Floating-point comparative tests\n"); iResult += _NetPrintFloat("%2.0f", 10.0f); iResult += _NetPrintFloat("%f", pow(2,52)); iResult += _NetPrintFloat("%f", pow(2,53)); iResult += _NetPrintFloat("%.15f", 0.00000000000000000000099f); // we don't test .16 here; ms printf doesn't round at 16+ digits iResult += _NetPrintFloat("%.15f", 0.0099f); iResult += _NetPrintFloat("%.15f", 0.0000000099f); iResult += _NetPrintFloat("%f", 1.99f); iResult += _NetPrintFloat("%f", -1.99); iResult += _NetPrintFloat("%f", 1.0f); iResult += _NetPrintFloat("%f", 0.75f); iResult += _NetPrintFloat("%2.2f", 1.0); iResult += _NetPrintFloat("%+2.2f", 1.0); iResult += _NetPrintFloat("%f", -1.99); iResult += _NetPrintFloat("%.2f", 9.99); iResult += _NetPrintFloat("%.2f", 9.999); iResult += _NetPrintFloat("%.2f", -1.999); iResult += _NetPrintFloat("%.2f", 0.1); iResult += _NetPrintFloat("%.15f", 3.1415926535897932384626433832795); /* this section is for stuff that is not compatible with sprintf() or is not compatible with the single-param _NetPrintFloat(). For these tests, we compare against a pre-generated string to make sure our output is consistently what we expect across all platforms. */ // make sure all fp selectors result in %f behavior iResult += _NetPrintPregen("%e 1.000000 %E 1.000000", "%%e %e %%E %E", 1.0f, 1.0f); iResult += _NetPrintPregen("%g 1.000000 %G 1.000000", "%%g %g %%G %G", 1.0f, 1.0f); iResult += _NetPrintPregen("%F 1.000000", "%%F %F", 1.0f); // test variable width with fp iResult += _NetPrintPregen(" 1", "%2.*f", 2, 1.0f); // test a really large number, but less than our maximum iResult += _NetPrintPregen("9223372036854775808.000000", "%f", pow(2,63)); // test a really large number, greater than our max iResult += _NetPrintPregen("0.(BIG)", "%f", pow(2,64)); // floating-point test summary ZPrintf("netprint: %d floating-point test discrepencies\n", iResult); ZPrintf("netprint: ------------------------------------\n"); return(iResult); } /*F********************************************************************************/ /*! \Function _NetPrintTestInts \Description Execute a series of integer printing tests. \Output int32_t - number of test failures \Version 05/05/2010 (jbrookes) */ /********************************************************************************F*/ static int32_t _NetPrintTestInts(void) { int32_t iResult = 0; const int32_t iBits = (signed)sizeof(int32_t)*8; const int32_t iMaxInt = (1 << (iBits - 1)) + 1; int32_t iInt0 = 8; ZPrintf("netprint: Integer tests\n"); iResult += _NetPrintInt("%d = 8", iInt0); iResult += _NetPrintInt("%+d = +8", iInt0); iResult += _NetPrintInt("%d = -maxint", iMaxInt); iResult += _NetPrintInt("char %c = 'a'", 'a'); iResult += _NetPrintInt("hex %x = ff", 0xff); iResult += _NetPrintInt("hex %02x = 00", 0); iResult += _NetPrintInt("oct %o = 10", 010); iResult += _NetPrintInt("oct %03o = 010", 8); iResult += _NetPrintLongInt("%llu", 0x900f123412341234ull); iResult += _NetPrintLongInt("0x%llx", 0x900f123412341234ull); #if defined(DIRTYCODE_PC) iResult += _NetPrintLongInt("%I64d", 0x900f123412341234ull); #endif #if defined(DIRTYCODE_LINUX) || defined(DIRTYCODE_APPLEIOS) iResult += _NetPrintLongInt("%qd", 0x900f123412341234ull); #endif iResult += _NetPrintPregen("signed -5 = unsigned 4294967291 = hex fffffffb", "signed %d = unsigned %u = hex %x", -5, -5, -5); iResult += _NetPrintPregen("4294967286,-10", "%u,%d", -10, -10); iResult += _NetPrintPregen("0,10,20,30,100,200,1000", "%d,%d,%d,%d,%d,%d,%d", 0, 10, 20, 30, 100, 200, 1000); iResult += _NetPrintPregen("0,-10,-20,-30,-100,-200,-1000", "%d,%d,%d,%d,%d,%d,%d", 0, -10, -20, -30, -100, -200, -1000); ZPrintf("netprint: %d integer test discrepencies\n", iResult); ZPrintf("netprint: ------------------------------------\n"); return(iResult); } /*F********************************************************************************/ /*! \Function _NetPrintTestPtrs \Description Execute a series of pointer printing tests. \Output int32_t - number of test failures \Version 05/05/2010 (jbrookes) */ /********************************************************************************F*/ static int32_t _NetPrintTestPtrs(void) { int32_t iResult = 0; char *pStr = "string test", *pNul = NULL; char strTemp[128]; ZPrintf("netprint: Pointer tests\n"); #if DIRTYCODE_64BITPTR _NetPrintPregen("p=$123456789abcdef0", "p=%p", (void *)0x123456789abcdef0); #if defined(DIRTYCODE_LINUX) || defined(DIRTYCODE_APPLEIOS) || defined(DIRTYCODE_APPLEOSX) || defined(DIRTYCODE_PS4) sprintf(strTemp, "p=$%016lx, null p=(null)", (uintptr_t)pStr); #else sprintf(strTemp, "p=$%016llx, null p=(null)", (uintptr_t)pStr); #endif #else _NetPrintPregen("p=$12345678", "p=%p", (void *)0x12345678); sprintf(strTemp, "p=$%08x, null p=(null)", (uint32_t)pStr); #endif iResult += _NetPrintPregen(strTemp, "p=%p, null p=%p", pStr, pNul); ZPrintf("netprint: %d pointer test discrepencies\n", iResult); ZPrintf("netprint: ------------------------------------\n"); return(iResult); } /*F********************************************************************************/ /*! \Function _NetPrintTestStrs \Description Execute a series of string printing tests. \Output int32_t - number of test failures \Version 05/05/2010 (jbrookes) */ /********************************************************************************F*/ static int32_t _NetPrintTestStrs(void) { int32_t iResult = 0; char *pStr = "string test"; wchar_t *pWideStr = L"wide string test"; ZPrintf("netprint: String tests\n"); iResult += _NetPrintStr("string test=%s", pStr); #if defined(DIRTYCODE_PC) iResult += _NetPrintStr("wide string test=%S", (const char *)pWideStr); #else iResult += _NetPrintStr("wide string test=%ls", (const char *)pWideStr); #endif iResult += _NetPrintStr("string test=%s", NULL); ZPrintf("netprint: %d string test discrepencies\n", iResult); ZPrintf("netprint: ------------------------------------\n"); return(iResult); } /*F********************************************************************************/ /*! \Function _NetPrintTestAlgn \Description Execute a series of string alignment formatting tests. \Output int32_t - number of test failures \Version 05/05/2010 (jbrookes) */ /********************************************************************************F*/ static int32_t _NetPrintTestAlgn(void) { int32_t iResult = 0; ZPrintf("netprint: Alignment tests\n"); iResult += _NetPrintStr(" left just: \"%-10s\"", "left"); iResult += _NetPrintStr("right just: \"%10s\"", "right"); iResult += _NetPrintInt(" 6: %04d zero padded", 6); iResult += _NetPrintInt(" 6: %-4d left just", 6); iResult += _NetPrintInt(" 6: %4d right just", 6); iResult += _NetPrintInt("-6: %04d zero padded", -6); iResult += _NetPrintInt("-6: %-4d left just", -6); iResult += _NetPrintInt("-6: %4d right just", -6); iResult += _NetPrintPregen(" 6: 0006 zero padded, variable-length", " 6: %0*d zero padded, variable-length", 4, 6); iResult += _NetPrintPregen(" 6: 6 left just, variable-length", " 6: %-*d left just, variable-length", 4, 6); iResult += _NetPrintPregen(" a: a left just", " a: %-8c left just", 'a'); iResult += _NetPrintPregen(" b: b right just", " b: %8c right just", 'b'); iResult += _NetPrintPregen(" c: c left just, variable-length", " c: %-*c left just, variable-length", 8, 'c'); iResult += _NetPrintPregen(" d: d right just, variable-length", " d: %*c right just, variable-length", 8, 'd'); ZPrintf("netprint: %d alignment test discrepencies\n", iResult); ZPrintf("netprint: ------------------------------------\n"); return(iResult); } /*F********************************************************************************/ /*! \Function _NetPrintTestMisc \Description Execute a series of miscelleneous printing tests. \Output int32_t - number of test failures \Version 05/05/2010 (jbrookes) */ /********************************************************************************F*/ static int32_t _NetPrintTestMisc(void) { int32_t iResult = 0; int32_t iInt1 = 0; char strTest[256], strTest2[128]; ZPrintf("netprint: Misc tests\n"); // test %n selector ds_snzprintf(strTest, sizeof(strTest), "%%n test %n", &iInt1); ds_snzprintf(strTest2, sizeof(strTest2), "(%d chars written)", iInt1); ds_strnzcat(strTest, strTest2, sizeof(strTest)); iResult += _NetPrintStrCmp("%n test (8 chars written)", strTest, "msc"); iResult += _NetPrintPregen("# test: 10", "# test: %#d", 10); iResult += _NetPrintPregen("1 1 1 1 1.000000 1 1 1", "%hd %hhd %ld %lld %f %zd %jd %td", 1, 1, 1l, 1ll, 1.0, 1, 1, 1); iResult += _NetPrintPregen("testing invalid trailing pct: ", "testing invalid trailing pct: %"); iResult += _NetPrintPregen("testing valid trailing pct: %", "testing valid trailing pct: %%"); ZPrintf("netprint: %d misc test discrepencies\n", iResult); ZPrintf("netprint: ------------------------------------\n"); return(iResult); } /*F********************************************************************************/ /*! \Function _NetPrintTestAddr \Description Execute a series of address printing tests. \Output int32_t - number of test failures \Version 08/28/2017 (jbrookes) */ /********************************************************************************F*/ #ifndef DIRTYCODE_NX static int32_t _NetPrintTestAddr(void) { uint32_t uAddr, uNumAddrs, uWord; struct sockaddr_in6 SockAddr6; char strAddr6[48]; int32_t iResult = 0; uint16_t aWords[8]; struct _NetAddr6 { const uint16_t aWords[8]; const char *pAddrText; }; static const struct _NetAddr6 _aAddr6ToString[] = { { { 0x2001, 0x0db8, 0x0000, 0x0000, 0x0008, 0x0800, 0x200c, 0x417A }, "2001:db8::8:800:200c:417a" }, // a unicast address { { 0xff01, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0101 }, "ff01::101" }, // a multicast address { { 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0001 }, "::1" }, // the loopback address { { 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000 }, "::" }, // the unspecified address { { 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0xffff, 0xc0a8, 0x0001 }, "::ffff:192.168.0.1" }, // an ipv4-mapped ipv6 address { { 0x0064, 0xff9b, 0x0000, 0x0000, 0x0000, 0x0000, 0xc0a8, 0x0001 }, "64:ff9b::192.168.0.1" }, // a nat64 address { { 0x0102, 0x0000, 0x0506, 0x0000, 0x0000, 0x0708, 0x090a, 0x0000 }, "102:0:506::708:90a:0" }, // synthetic test { { 0x1234, 0x5678, 0x9abc, 0xdef0, 0x0000, 0x1234, 0x5678, 0x9abc }, "1234:5678:9abc:def0:0:1234:5678:9abc" } // synthetic test }; static const struct _NetAddr6 _aStringToAddr6[] = { { { 0x2001, 0x0db8, 0x0000, 0x0000, 0x0008, 0x0800, 0x200c, 0x417A }, "2001:DB8::8:800:200C:417A" }, // a unicast address { { 0xff01, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0101 }, "FF01::101" }, // a multicast address { { 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0001 }, "::1" }, // the loopback address { { 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000 }, "::" }, // the unspecified address { { 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0xffff, 0xc0a8, 0x0001 }, "::ffff:c0a8:1" }, // an ipv4-mapped ipv6 address { { 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0xffff, 0xc0a8, 0x0001 }, "::ffff:192.168.0.1" }, // a mixed-notation ipv4-mapped ipv6 address { { 0x0064, 0xff9b, 0x0000, 0x0000, 0x0000, 0x0000, 0xc0a8, 0x0001 }, "64:ff9b::c0a8:1" }, // a nat64 address { { 0x0064, 0xff9b, 0x0000, 0x0000, 0x0000, 0x0000, 0xc0a8, 0x9b18 }, "64:ff9b::192.168.155.24" }, // a mixed-notation nat64 address { { 0x0102, 0x0000, 0x0506, 0x0000, 0x0000, 0x0708, 0x090a, 0x0000 }, "102:0:506::708:90a:0" }, // synthetic test { { 0x1234, 0x5678, 0x9abc, 0xdef0, 0x0000, 0x1234, 0x5678, 0x9abc }, "1234:5678:9abc:def0:0:1234:5678:9abc" } // synthetic test }; // test addr6 to string conversion uNumAddrs = sizeof(_aAddr6ToString) / sizeof(_aAddr6ToString[0]); for (uAddr = 0; uAddr < uNumAddrs; uAddr += 1) { _NetFormatAddr6(&SockAddr6, _aAddr6ToString[uAddr].aWords, 0); SockaddrInGetAddrText((struct sockaddr *)&SockAddr6, strAddr6, sizeof(strAddr6)); iResult += _NetPrintStrCmp(_aAddr6ToString[uAddr].pAddrText, strAddr6, "addr"); } // test string to addr6 conversion uNumAddrs = sizeof(_aStringToAddr6)/sizeof(_aStringToAddr6[0]); for (uAddr = 0; uAddr < uNumAddrs; uAddr += 1) { SockaddrInSetAddrText((struct sockaddr *)&SockAddr6, _aStringToAddr6[uAddr].pAddrText); for (uWord = 0; uWord < 8; uWord += 1) { aWords[uWord] = SocketNtohs(*(uint16_t *)(SockAddr6.sin6_addr.s6_addr+(uWord*2))); } iResult += _NetPrintMemCmp((const uint8_t *)_aStringToAddr6[uAddr].aWords, sizeof(_aStringToAddr6[uAddr].aWords), (const uint8_t *)aWords, sizeof(aWords), "addr"); } return(iResult); } /*F********************************************************************************/ /*! \Function _NetPrintTestCust \Description Execute a series of custom printing tests. These are for selectors that are specific to the DirtySock platform string formatting functions. \Output int32_t - number of test failures \Version 05/05/2010 (jbrookes) */ /********************************************************************************F*/ static int32_t _NetPrintTestCust(void) { int32_t iResult = 0; struct sockaddr SockAddr4; struct sockaddr_in6 SockAddr6, SockAddr6_2, SockAddr6_3; uint8_t aSin6Addr[16] = { 0x5a, 0x23, 0x01, 0x32, 0xff, 0x12, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x12, 0xde, 0x00, 0x02 }; uint32_t uAddr; SockaddrInit(&SockAddr4, AF_INET); SockaddrInSetAddr(&SockAddr4, 0xC0A80001); SockaddrInSetPort(&SockAddr4, 3658); // create an IPv4-mapped IPv6 address ds_memclr(&SockAddr6, sizeof(SockAddr6)); uAddr = SockaddrInGetAddr(&SockAddr4); SockAddr6.sin6_family = AF_INET6; SockAddr6.sin6_port = SocketNtohs(SockaddrInGetPort(&SockAddr4)); SockAddr6.sin6_flowinfo = 0; SockAddr6.sin6_addr.s6_addr[10] = 0xff; SockAddr6.sin6_addr.s6_addr[11] = 0xff; SockAddr6.sin6_addr.s6_addr[12] = (uint8_t)(uAddr >> 24); SockAddr6.sin6_addr.s6_addr[13] = (uint8_t)(uAddr >> 16); SockAddr6.sin6_addr.s6_addr[14] = (uint8_t)(uAddr >> 8); SockAddr6.sin6_addr.s6_addr[15] = (uint8_t)(uAddr >> 0); // create a simulated full IPv6 address SockaddrInit6(&SockAddr6_2, AF_INET6); SockAddr6_2.sin6_port = SocketNtohs(3658); ds_memcpy(&SockAddr6_2.sin6_addr, aSin6Addr, sizeof(SockAddr6_2.sin6_addr)); // create a NAT64 address ds_memcpy(&SockAddr6_3, &SockAddr6, sizeof(SockAddr6_3)); SockAddr6_3.sin6_addr.s6_addr[1] = 0x64; SockAddr6_3.sin6_addr.s6_addr[2] = 0xff; SockAddr6_3.sin6_addr.s6_addr[3] = 0x9b; SockAddr6_3.sin6_addr.s6_addr[10] = 0x00; SockAddr6_3.sin6_addr.s6_addr[11] = 0x00; ZPrintf("netprint: Custom tests\n"); iResult += _NetPrintPregen("addr=192.168.0.1", "addr=%a", SockaddrInGetAddr(&SockAddr4)); iResult += _NetPrintPregen("addr=255.255.255.255", "addr=%a", 0xffffffff); iResult += _NetPrintPregen("addr=[192.168.0.1]:3658", "addr=%A", &SockAddr4); iResult += _NetPrintPregen("addr=[::ffff:192.168.0.1]:3658", "addr=%A", &SockAddr6); iResult += _NetPrintPregen("addr=[64:ff9b::192.168.0.1]:3658", "addr=%A", &SockAddr6_3); iResult += _NetPrintPregen("addr=[5a23:132:ff12::12de:2]:3658", "addr=%A", &SockAddr6_2); iResult += _NetPrintPregen("'dflt' = 'dflt'", "'dflt' = '%C'", 'dflt'); iResult += _NetPrintPregen("'d*l*' = 'd*l*'", "'d*l*' = '%C'", ('d' << 24) | ('l' << 8)); ZPrintf("netprint: %d custom test discrepencies\n", iResult); ZPrintf("netprint: ------------------------------------\n"); return(iResult); } #endif /*F********************************************************************************/ /*! \Function _NetPrintTestOver \Description Execute a series of printing tests exercising the overflow functionality. \Output int32_t - number of test failures \Version 02/15/2011 (jbrookes) */ /********************************************************************************F*/ static int32_t _NetPrintTestOver(void) { const char strOver[] = "<<>>"; int32_t iResult0 = 0, iResult1 = 0; // test some overflow scenarios with ds_snzprintf2 ZPrintf("netprint: Overflow tests\n"); iResult1 += _NetPrintOverflow( 0, "", 14, "%s", strOver); iResult1 += _NetPrintOverflow( 1, "", 14, "%s", strOver); iResult1 += _NetPrintOverflow(12, "<<>", 14, "%s", strOver); iResult1 += _NetPrintOverflow(15, "<<>>", 14, "%s", strOver); iResult1 += _NetPrintOverflow(20, " <<>", 20, "%20s", strOver); iResult1 += _NetPrintOverflow(20, "<<>> ", 20, "%-20s", strOver); iResult1 += _NetPrintOverflow(21, " <<>>", 20, "%20s", strOver); iResult1 += _NetPrintOverflow(16, "-<<>>", 16, "-%s-", strOver); iResult1 += _NetPrintOverflow(17, "-<<>>-", 16, "-%s-", strOver); ZPrintf("netprint: %d overflow test discrepencies\n", iResult1); ZPrintf("netprint: ------------------------------------\n"); return(iResult0+iResult1); } /*F********************************************************************************/ /*! \Function _NetPrintTestSpam \Description Execute a series of printing tests exercising the spam suppression \Output int32_t - number of test failures \Version 04/05/2016 (jbrookes) */ /********************************************************************************F*/ static int32_t _NetPrintTestSpam(void) { int32_t iTest; // test suppression of multiple identical lines, with output forced by a non-identical line NetPrintf(("netprint: rate limit test #1 start\n")); for (iTest = 0; iTest < 32; iTest += 1) { NetPrintf(("netprint: testing rate limiter\n")); } NetPrintf(("netprint: rate limit test #1 finish\n")); // test suppression of multiple identical lines, with output forced by timeout NetPrintf(("netprint: rate limit test #2 start\n")); for (iTest = 0; iTest < 32; iTest += 1) { NetPrintf(("netprint: testing rate limiter\n")); NetConnSleep(30); } NetPrintf(("netprint: rate limit test #2 finish\n")); return(0); } /*** Public functions *************************************************************/ /*F********************************************************************************/ /*! \Function CmdNetPrint \Description Test the ds_vsnprintf function \Input *argz - environment \Input argc - standard number of arguments \Input *argv[] - standard arg list \Output int32_t - standard return value \Version 10/28/2009 (jbrookes) */ /********************************************************************************F*/ int32_t CmdNetPrint(ZContext *argz, int32_t argc, char *argv[]) { int32_t iResult = 0; ZPrintf("netprint: ------------------------------------\n"); ZPrintf("netprint: Testing ds_snzprintf() vs sprintf()\n"); ZPrintf("netprint: ------------------------------------\n"); iResult += _NetPrintTestStrs(); iResult += _NetPrintTestFlts(); iResult += _NetPrintTestInts(); iResult += _NetPrintTestPtrs(); #ifndef DIRTYCODE_NX iResult += _NetPrintTestAddr(); iResult += _NetPrintTestCust(); #endif iResult += _NetPrintTestAlgn(); iResult += _NetPrintTestMisc(); iResult += _NetPrintTestOver(); iResult += _NetPrintTestSpam(); ZPrintf("netprint: Test results: %d total discrepencies\n", iResult); ZPrintf("netprint: ------------------------------------\n"); return(0); }