From d1a68204b3fcda30d1bacc85bd9b6713dd8077ee Mon Sep 17 00:00:00 2001 From: Andy Heninger Date: Wed, 12 Nov 2003 07:00:38 +0000 Subject: [PATCH] ICU-2403 trace tests added, trace API doc comments tweaked. X-SVN-Rev: 13679 --- icu4c/source/common/common.dsp | 8 +- icu4c/source/common/unicode/utrace.h | 25 ++- icu4c/source/common/utrace.c | 2 +- icu4c/source/common/utracimp.h | 5 - icu4c/source/test/cintltst/calltest.c | 3 + icu4c/source/test/cintltst/cintltst.dsp | 4 + icu4c/source/test/cintltst/tracetst.c | 211 ++++++++++++++++++++++++ 7 files changed, 246 insertions(+), 12 deletions(-) create mode 100644 icu4c/source/test/cintltst/tracetst.c diff --git a/icu4c/source/common/common.dsp b/icu4c/source/common/common.dsp index 3669e4c3741..1f25289d86d 100644 --- a/icu4c/source/common/common.dsp +++ b/icu4c/source/common/common.dsp @@ -1076,6 +1076,10 @@ InputPath=.\unicode\utrace.h # End Source File # Begin Source File +SOURCE=.\utracimp.h +# End Source File +# Begin Source File + SOURCE=.\unicode\utypes.h !IF "$(CFG)" == "common - Win32 Release" @@ -1851,10 +1855,6 @@ InputPath=.\unicode\uidna.h !ENDIF -# End Source File -# Begin Source File - -SOURCE=.\utracimp.h # End Source File # End Group # Begin Group "locales & resources" diff --git a/icu4c/source/common/unicode/utrace.h b/icu4c/source/common/unicode/utrace.h index 35ca78dc35b..8c924e7bc18 100644 --- a/icu4c/source/common/unicode/utrace.h +++ b/icu4c/source/common/unicode/utrace.h @@ -32,11 +32,17 @@ U_CDECL_BEGIN */ enum UTraceLevel { + /** Disable all tracing */ UTRACE_OFF=-1, + /** Trace error conditions only */ UTRACE_ERROR=0, + /** Trace errors and warnings */ UTRACE_WARNING=3, + /** Trace opens and closes of ICU services */ UTRACE_OPEN_CLOSE=5, + /** Trace an intermediate number of ICU operations */ UTRACE_INFO=7, + /** Trace the maximum number of ICU operations */ UTRACE_VERBOSE=9 }; typedef enum UTraceLevel UTraceLevel; @@ -73,11 +79,17 @@ UTraceEntry(const void *context, int32_t fnNumber); * Type signature for the trace function to be called when exiting from a function. * @param context value supplied at the time the trace functions are set. * @param fnNumber Enum value indicating the ICU function being exited. + * @param retType the UTraceExitVal indicating the number and types of + * variable arguments that follow. + * @param argType values returned by the function being traced, may include + * one or both of the function's return value and a + * UErrorCode parameter value. + * @see UTraceExitVal * @draft ICU 2.8 */ typedef void U_CALLCONV UTraceExit(const void *context, int32_t fnNumber, - int32_t retType, va_list args); + int32_t argType, va_list args); /** * Type signature for the trace function to be called from within an ICU function @@ -94,7 +106,10 @@ UTraceData(const void *context, int32_t fnNumber, int32_t level, * Set ICU Tracing functions. Installs application-provided tracing * functions into ICU. After doing this, subsequent ICU operations * will call back to the installed functions, providing a trace - * of the use of ICU. + * of the use of ICU. Passing a NULL pointer for a tracing function + * is allowed, and inhibits tracing action at points where that function + * would be called. + * * @param context an uninterpretted pointer. Whatever is passed in * here will in turn be passed to each of the tracing * functions UTraceEntry, UTraceExit and UTraceData. @@ -259,11 +274,17 @@ utrace_format(char *outBuf, int32_t capacity, * @draft ICU 2.8 */ enum UTraceExitVal { + /** The traced function returns no value */ UTRACE_EXITV_NONE = 0, + /** The traced function returns an int32_t, or compatible, type. */ UTRACE_EXITV_I32 = 1, + /** The traced function returns a pointer */ UTRACE_EXITV_PTR = 2, + /** The traced function returns a UBool */ UTRACE_EXITV_BOOL = 3, + /** Mask to extract the return type values from a UTraceExitVal */ UTRACE_EXITV_MASK = 0xf, + /** Bit indicating that the traced function includes a UErrorCode parameter */ UTRACE_EXITV_STATUS = 0x10 }; typedef enum UTraceExitVal UTraceExitVal; diff --git a/icu4c/source/common/utrace.c b/icu4c/source/common/utrace.c index 310aa4a3cf7..c0a8f24c49b 100644 --- a/icu4c/source/common/utrace.c +++ b/icu4c/source/common/utrace.c @@ -134,7 +134,7 @@ static void outputUString(const UChar *s, int32_t len, for (i=0; i +#include + + +static void TestTraceAPI(void); + + +void +addUTraceTest(TestNode** root) +{ + addTest(root, &TestTraceAPI, "tsutil/TraceTest/TestTraceAPI" ); +} + + +/* + * Macro for assert style tests. + */ +#define TEST_ASSERT(expr) \ +if (!(expr)) { \ + log_err("FAILED Assertion \"" #expr "\" at %s:%d.\n", __FILE__, __LINE__); \ +} + + +/* + * test_format. Helper function for checking the results of a formatting + * operation. Compares the actual results in buf parameter + * with the expected results. + * + * params: format: the format to be applied. + * bufCap buffer size to pass to formatter. + * indent: indent value to give to formatter + * result expected result. Do not truncate for short bufCap - + * this function will do it. + * line __LINE__, so we can report where failure happened. + * ... variable args to pass to formatter + * + */ +static void test_format(const char *format, int32_t bufCap, int32_t indent, + const char *result, int32_t line, ...) { + int32_t len; + va_list args; + char buf[300]; + char expectedResult[300]; + + /* check that local buffers are big enough for the test case */ + if (sizeof(buf) <= bufCap) { + log_err("At file:line %s:%d, requested bufCap too large.\n"); + return; + } + if (strlen(result) >= sizeof(expectedResult)) { + log_err("At file:line %s:%d, expected result too large.\n"); + return; + } + + /* Guarantee a nul term if buffer is smaller than output */ + strcpy(expectedResult, result); + expectedResult[bufCap] = 0; + + /* run the formatter */ + va_start(args, line); + memset(buf, 0, sizeof(buf)); + len = utrace_format(buf, bufCap, indent, format, args); + + /* Check results. */ + if (strcmp(expectedResult, buf) != 0) { + log_err("At file:line %s:%d Expected \"%s\", got \"%s\" \n", + __FILE__, line, expectedResult, buf); + } + va_end(args); +} + + +/* + * define trace functions for use in this test. + */ +void testTraceEntry(const void *context, int32_t fnNumber) { +} + +void testTraceExit(const void *context, int32_t fnNumber, + int32_t argType, va_list args) { +} + +void testTraceData(const void *context, int32_t fnNumber, int32_t level, + const char *fmt, va_list args) { +} + + +/* + * TestTraceAPI + */ +static void TestTraceAPI() { + + + UTraceEntry *originalTEntryFunc; + UTraceExit *originalTExitFunc; + UTraceData *originalTDataFunc; + const void *originalTContext; + + /* + * Save the original tracing state so that we can restore it after the test. + */ + utrace_getFunctions(&originalTContext, &originalTEntryFunc, &originalTExitFunc, + &originalTDataFunc); + + + /* verify that set/get of tracing functions returns what was set. */ + { + UTraceEntry *e; + UTraceExit *x; + UTraceData *d; + const void *context; + const void *newContext = (const char *)originalTContext + 1; + + TEST_ASSERT(originalTEntryFunc != testTraceEntry); + TEST_ASSERT(originalTExitFunc != testTraceExit); + TEST_ASSERT(originalTDataFunc != testTraceData); + + utrace_setFunctions(newContext, testTraceEntry, testTraceExit, testTraceData); + utrace_getFunctions(&context, &e, &x, &d); + TEST_ASSERT(e == testTraceEntry); + TEST_ASSERT(x == testTraceExit); + TEST_ASSERT(d == testTraceData); + TEST_ASSERT(context == newContext); + } + + /* verify that set/get level work as a pair, and that the level + * identifiers all exist. + */ + + { + int32_t level; + + utrace_setLevel(UTRACE_OFF); + level = utrace_getLevel(); + TEST_ASSERT(level==UTRACE_OFF); + utrace_setLevel(UTRACE_VERBOSE); + level = utrace_getLevel(); + TEST_ASSERT(level==UTRACE_VERBOSE); + utrace_setLevel(UTRACE_ERROR); + utrace_setLevel(UTRACE_WARNING); + utrace_setLevel(UTRACE_OPEN_CLOSE); + utrace_setLevel(UTRACE_INFO); + } + + + /* + * trace data formatter operation. + */ + { + UChar s1[] = {0x41fe, 0x42, 0x43, 00}; + const char *a1[] = {"s1", "s2", "s3"}; + void *ptr; + + test_format("hello, world", 50, 0, "hello, world", __LINE__); + test_format("hello, world", 50, 4, " hello, world", __LINE__); + test_format("hello, world", 3, 0, "hello, world", __LINE__); + + test_format("a character %c", 50, 0, "a character x", __LINE__, 'x'); + test_format("a string %s ", 50, 0, "a string hello ", __LINE__, "hello"); + test_format("uchars %S ", 50, 0, "uchars 41fe 0042 0043 0000 ", __LINE__, s1, -1); + test_format("uchars %S ", 50, 0, "uchars 41fe 0042 ", __LINE__, s1, 2); + + test_format("a byte %b--", 50, 0, "a byte dd--", __LINE__, 0xdd); + test_format("a 16 bit val %h", 50, 0, "a 16 bit val 1234", __LINE__, 0x1234); + test_format("a 32 bit val %d...", 50, 0, "a 32 bit val 6789abcd...", __LINE__, 0x6789abcd); + test_format("a 64 bit val %l", 50, 0, "a 64 bit val 123456780abcdef0" + , __LINE__, 0x123456780abcdef0); + if (sizeof(ptr) == 4) { + ptr = (void *)0xdeadbeef; + test_format("a 32 bit ptr %p", 50, 0, "a 32 bit ptr deadbeef", __LINE__, ptr); + } else if (sizeof(void *) == 8) { + ptr = (void *)0x1000200030004000; + test_format("a 64 bit ptr %p", 50, 0, "a 64 bit ptr 1000200030004000", __LINE__, ptr); + } else { + TEST_ASSERT(FALSE); + /* TODO: others? */ + } + + test_format("%vc", 100, 0, "abc[ffffffff]", __LINE__, "abc", -1); + test_format("%vs", 100, 0, "s1\ns2\n[00000002]", __LINE__, a1, 2); + test_format("%vs", 100, 4, " s1\n s2\n [00000002]", __LINE__, a1, 2); + + test_format("%vb", 100, 0, "41 42 43 [00000003]", __LINE__, "ABC", 3); + + + } + + + +} + + +