Home | History | Annotate | Download | only in cintltst
      1 /********************************************************************
      2  * COPYRIGHT:
      3  * Copyright (c) 2003-2007, International Business Machines Corporation and
      4  * others. All Rights Reserved.
      5  ********************************************************************/
      6 /*
      7  * File tracetst.c
      8  *
      9  */
     10 
     11 
     12 #include "unicode/utypes.h"
     13 #include "unicode/utrace.h"
     14 #include "unicode/uclean.h"
     15 #include "unicode/uchar.h"
     16 #include "unicode/ures.h"
     17 #include "unicode/ucnv.h"
     18 #include "cintltst.h"
     19 #include <stdlib.h>
     20 #include <stdio.h>
     21 #include <string.h>
     22 
     23 /* We define the following to always test tracing, even when it's off in the library. */
     24 #if U_ENABLE_TRACING
     25 #define ENABLE_TRACING_ORIG_VAL 1
     26 #else
     27 #define ENABLE_TRACING_ORIG_VAL 0
     28 #endif
     29 #undef U_ENABLE_TRACING
     30 #define U_ENABLE_TRACING 1
     31 #include "utracimp.h"
     32 
     33 
     34 static void TestTraceAPI(void);
     35 
     36 
     37 void
     38 addUTraceTest(TestNode** root);
     39 
     40 void
     41 addUTraceTest(TestNode** root)
     42 {
     43     addTest(root, &TestTraceAPI,            "tsutil/TraceTest/TestTraceAPI"  );
     44 }
     45 
     46 
     47 /*
     48  * Macro for assert style tests.
     49  */
     50 #define TEST_ASSERT(expr) \
     51 if (!(expr)) { \
     52     log_err("FAILED Assertion \"" #expr "\" at  %s:%d.\n", __FILE__, __LINE__); \
     53 }
     54 
     55 
     56 /*
     57  *  test_format.   Helper function for checking the results of a formatting
     58  *                 operation.  Executes the format op and compares actual
     59  *                 results with the expected results.
     60  *
     61  *       params:   format:  the format to be applied.
     62  *                 bufCap   buffer size to pass to formatter.
     63  *                 indent:  indent value to give to formatter
     64  *                 result   expected result.  Do not truncate for short bufCap -
     65  *                          this function will do it.
     66  *                 line     __LINE__, so we can report where failure happened.
     67  *                 ...      variable args to pass to formatter
     68  *
     69  */
     70 static void test_format(const char *format, int32_t bufCap, int32_t indent,
     71                         const char *result, int32_t line, ...) {
     72     int32_t  len;
     73     va_list  args;
     74     char  buf[300];
     75     char  expectedResult[300];
     76 
     77     /* check that local buffers are big enough for the test case */
     78     if (sizeof(buf) <= bufCap) {
     79         log_err("At file:line %s:%d, requested bufCap too large.\n");
     80         return;
     81     }
     82     if (strlen(result) >= sizeof(expectedResult)) {
     83         log_err("At file:line %s:%d, expected result too large.\n");
     84         return;
     85     }
     86 
     87    /* Guarantee a nul term if buffer is smaller than output */
     88     strcpy(expectedResult, result);
     89     expectedResult[bufCap] = 0;
     90 
     91     /* run the formatter */
     92     va_start(args, line);
     93     memset(buf, 0, sizeof(buf));
     94     len = utrace_vformat(buf, bufCap, indent, format, args);
     95 
     96     /* Check results.   */
     97     if (strcmp(expectedResult, buf) != 0) {
     98         log_err("At file:line %s:%d  Expected \"%s\", got \"%s\"  \n",
     99              __FILE__, line, expectedResult, buf);
    100     }
    101     va_end(args);
    102 }
    103 
    104 
    105 /*
    106  *  define trace functions for use in this test.
    107  */
    108 static int    gTraceEntryCount;
    109 static int    gTraceExitCount;
    110 static int    gTraceDataCount;
    111 static UBool  gFnNameError   = FALSE;
    112 static UBool  gFnFormatError = FALSE;
    113 
    114 static void U_CALLCONV testTraceEntry(const void *context, int32_t fnNumber) {
    115     const char *fnName;
    116     const char *bogusFnName;
    117 
    118     gTraceEntryCount++;
    119 
    120     /* Verify that a name is available for the fnNumber passed to us */
    121     bogusFnName = utrace_functionName(-1);
    122     fnName = utrace_functionName(fnNumber);
    123     if (strcmp(fnName, bogusFnName) == 0) {
    124         gFnNameError = TRUE;
    125     }
    126     /* printf("%s() Enter\n", fnName); */
    127 
    128 }
    129 
    130 static void U_CALLCONV testTraceExit(const void *context, int32_t fnNumber,
    131                    const char *fmt, va_list args) {
    132     char        buf[1000];
    133     const char *fnName;
    134     const char *bogusFnName;
    135 
    136     gTraceExitCount++;
    137 
    138     /* Verify that a name is available for the fnNumber passed to us */
    139     bogusFnName = utrace_functionName(-1);
    140     fnName = utrace_functionName(fnNumber);
    141     if (strcmp(fnName, bogusFnName) == 0) {
    142         gFnNameError = TRUE;
    143     }
    144 
    145     /* Verify that the format can be used.  */
    146     buf[0] = 0;
    147     utrace_vformat(buf, sizeof(buf), 0, fmt, args);
    148     if (strlen(buf) == 0) {
    149         gFnFormatError = TRUE;
    150     }
    151 
    152     /* printf("%s() %s\n", fnName, buf); */
    153 
    154 }
    155 
    156 static void U_CALLCONV testTraceData(const void *context, int32_t fnNumber, int32_t level,
    157                    const char *fmt, va_list args) {
    158     char        buf[1000];
    159     const char *fnName;
    160     const char *bogusFnName;
    161 
    162     gTraceDataCount++;
    163 
    164     /* Verify that a name is available for the fnNumber passed to us */
    165     bogusFnName = utrace_functionName(-1);
    166     fnName = utrace_functionName(fnNumber);
    167     if (strcmp(fnName, bogusFnName) == 0) {
    168         gFnNameError = TRUE;
    169     }
    170 
    171     /* Verify that the format can be used.  */
    172     buf[0] = 0;
    173     utrace_vformat(buf, sizeof(buf), 0, fmt, args);
    174     if (strlen(buf) == 0) {
    175         gFnFormatError = TRUE;
    176     }
    177 
    178     /* printf("  %s()   %s\n", fnName, buf); */
    179 }
    180 
    181 static UConverter * psuedo_ucnv_open(const char *name, UErrorCode * err)
    182 {
    183     UTRACE_ENTRY_OC(UTRACE_UCNV_LOAD);
    184 
    185     UTRACE_DATA2(UTRACE_OPEN_CLOSE, "error code is %s for %s", u_errorName(*err), name);
    186 
    187     UTRACE_EXIT_PTR_STATUS(NULL, *err);
    188     return NULL;
    189 }
    190 static void psuedo_ucnv_close(UConverter * cnv)
    191 {
    192     UTRACE_ENTRY_OC(UTRACE_UCNV_UNLOAD);
    193     UTRACE_DATA1(UTRACE_OPEN_CLOSE, "unload converter %p", cnv);
    194     UTRACE_EXIT_VALUE((int32_t)TRUE);
    195 }
    196 
    197 
    198 /*
    199  *   TestTraceAPI
    200  */
    201 static void TestTraceAPI() {
    202 
    203 
    204     UTraceEntry   *originalTEntryFunc;
    205     UTraceExit    *originalTExitFunc;
    206     UTraceData    *originalTDataFunc;
    207     const void    *originalTContext;
    208     int32_t        originalLevel;
    209 
    210     /*
    211      * Save the original tracing state so that we can restore it after the test.
    212      */
    213     utrace_getFunctions(&originalTContext, &originalTEntryFunc, &originalTExitFunc,
    214                         &originalTDataFunc);
    215     originalLevel = utrace_getLevel();
    216 
    217 
    218     /* verify that set/get of tracing functions returns what was set.  */
    219     {
    220         UTraceEntry *e;
    221         UTraceExit  *x;
    222         UTraceData  *d;
    223         const void  *context;
    224         const void  *newContext = (const char *)originalTContext + 1;
    225 
    226         TEST_ASSERT(originalTEntryFunc != testTraceEntry);
    227         TEST_ASSERT(originalTExitFunc != testTraceExit);
    228         TEST_ASSERT(originalTDataFunc != testTraceData);
    229 
    230         utrace_setFunctions(newContext, testTraceEntry, testTraceExit, testTraceData);
    231         utrace_getFunctions(&context, &e, &x, &d);
    232         TEST_ASSERT(e == testTraceEntry);
    233         TEST_ASSERT(x == testTraceExit);
    234         TEST_ASSERT(d == testTraceData);
    235         TEST_ASSERT(context == newContext);
    236     }
    237 
    238     /* verify that set/get level work as a pair, and that the level
    239      * identifiers all exist.
    240      */
    241 
    242     {
    243         int32_t  level;
    244 
    245         utrace_setLevel(UTRACE_OFF);
    246         level = utrace_getLevel();
    247         TEST_ASSERT(level==UTRACE_OFF);
    248         utrace_setLevel(UTRACE_VERBOSE);
    249         level = utrace_getLevel();
    250         TEST_ASSERT(level==UTRACE_VERBOSE);
    251         utrace_setLevel(UTRACE_ERROR);
    252         utrace_setLevel(UTRACE_WARNING);
    253         utrace_setLevel(UTRACE_OPEN_CLOSE);
    254         utrace_setLevel(UTRACE_INFO);
    255     }
    256 
    257     /*
    258      * Open and close a converter with tracing enabled.
    259      *   Verify that our tracing callback functions get called.
    260      */
    261     {
    262         UErrorCode  status = U_ZERO_ERROR;
    263         UConverter *cnv;
    264 
    265         gTraceEntryCount = 0;
    266         gTraceExitCount  = 0;
    267         gTraceDataCount  = 0;
    268         gFnNameError     = FALSE;
    269         gFnFormatError   = FALSE;
    270         utrace_setLevel(UTRACE_OPEN_CLOSE);
    271 #if ENABLE_TRACING_ORIG_VAL
    272         cnv = ucnv_open(NULL, &status);
    273         TEST_ASSERT(U_SUCCESS(status));
    274         ucnv_close(cnv);
    275 #else
    276         cnv = psuedo_ucnv_open(NULL, &status);
    277         TEST_ASSERT(U_SUCCESS(status));
    278         psuedo_ucnv_close(cnv);
    279 #endif
    280         TEST_ASSERT(gTraceEntryCount > 0);
    281         TEST_ASSERT(gTraceExitCount  > 0);
    282         TEST_ASSERT(gTraceDataCount  > 0);
    283         TEST_ASSERT(gFnNameError   == FALSE);
    284         TEST_ASSERT(gFnFormatError == FALSE);
    285     }
    286 
    287 
    288 
    289     /*
    290      * trace data formatter operation.
    291      */
    292     {
    293         UChar s1[] = {0x41fe, 0x42, 0x43, 00};
    294         const char  *a1[] = {"s1", "s2", "s3"};
    295         void  *ptr;
    296 
    297         test_format("hello, world", 50, 0, "hello, world", __LINE__);
    298         test_format("hello, world", 50, 4, "    hello, world", __LINE__);
    299         test_format("hello, world", 3, 0,  "hello, world", __LINE__);
    300 
    301         test_format("a character %c", 50, 0, "a character x", __LINE__, 'x');
    302         test_format("a string %s ", 50, 0, "a string hello ", __LINE__, "hello");
    303         test_format("uchars %S ", 50, 0, "uchars 41fe 0042 0043 0000  ", __LINE__, s1, -1);
    304         test_format("uchars %S ", 50, 0, "uchars 41fe 0042  ", __LINE__, s1, 2);
    305 
    306         test_format("a byte %b--", 50, 0, "a byte dd--", __LINE__, 0xdd);
    307         test_format("a 16 bit val %h", 50, 0, "a 16 bit val 1234", __LINE__, 0x1234);
    308         test_format("a 32 bit val %d...", 50, 0, "a 32 bit val 6789abcd...", __LINE__, 0x6789abcd);
    309         test_format("a 64 bit val %l", 50, 0, "a 64 bit val 123456780abcdef0"
    310             , __LINE__, INT64_C(0x123456780abcdef0));
    311 
    312         if (sizeof(void *) == 4) {
    313             ptr = (void *)0xdeadbeef;
    314             test_format("a 32 bit ptr %p", 50, 0, "a 32 bit ptr deadbeef", __LINE__, ptr);
    315         } else if (sizeof(void *) == 8) {
    316             ptr = (void *) INT64_C(0x1000200030004000);
    317             test_format("a 64 bit ptr %p", 50, 0, "a 64 bit ptr 1000200030004000", __LINE__, ptr);
    318         } else if (sizeof(void *) == 16) {
    319             /* iSeries */
    320             union {
    321                 int32_t arr[4];
    322                 void *ptr;
    323             } massiveBigEndianPtr = {{ 0x10002000, 0x30004000, 0x50006000, 0x70008000 }};
    324             ptr = massiveBigEndianPtr.ptr;
    325             test_format("a 128 bit ptr %p", 50, 0, "a 128 bit ptr 10002000300040005000600070008000", __LINE__, ptr);
    326         } else {
    327             TEST_ASSERT(FALSE);
    328             /*  TODO:  others? */
    329         }
    330 
    331         test_format("%vc", 100, 0, "abc[ffffffff]", __LINE__, "abc", -1);
    332         test_format("%vs", 100, 0, "s1\ns2\n[00000002]", __LINE__, a1, 2);
    333         test_format("%vs", 100, 4, "    s1\n    s2\n    [00000002]", __LINE__, a1, 2);
    334 
    335         test_format("%vb", 100, 0, "41 42 43 [00000003]", __LINE__, "\x41\x42\x43", 3);
    336 
    337         /* Null ptrs for strings, vectors  */
    338         test_format("Null string - %s", 50, 0, "Null string - *NULL*", __LINE__, NULL);
    339         test_format("Null string - %S", 50, 0, "Null string - *NULL*", __LINE__, NULL);
    340         test_format("Null vector - %vc", 50, 0, "Null vector - *NULL* [00000002]", __LINE__, NULL, 2);
    341         test_format("Null vector - %vC", 50, 0, "Null vector - *NULL* [00000002]", __LINE__, NULL, 2);
    342         test_format("Null vector - %vd", 50, 0, "Null vector - *NULL* [00000002]", __LINE__, NULL, 2);
    343 
    344     }
    345 
    346     /*
    347      * utrace_format.  Only need a minimal test to see that the function works at all.
    348      *                 Full functionality is tested via utrace_vformat.
    349      */
    350     {
    351         char      buf[100];
    352         int32_t   x;
    353         x = utrace_format(buf, 100, 0, "%s", "Hello, World.");
    354         TEST_ASSERT(strcmp(buf, "Hello, World.") == 0);
    355         TEST_ASSERT(x == 14);
    356     }
    357 
    358     /*
    359      * utrace_functionName.  Just spot-check a couple of them.
    360      */
    361     {
    362         const char   *name;
    363         name = utrace_functionName(UTRACE_U_INIT);
    364         TEST_ASSERT(strcmp(name, "u_init") == 0);
    365         name = utrace_functionName(UTRACE_UCNV_OPEN);
    366         TEST_ASSERT(strcmp(name, "ucnv_open") == 0);
    367         name = utrace_functionName(UTRACE_UCOL_GET_SORTKEY);
    368         TEST_ASSERT(strcmp(name, "ucol_getSortKey") == 0);
    369     }
    370 
    371 
    372 
    373     /*  Restore the trace function settings to their original values. */
    374     utrace_setFunctions(originalTContext, originalTEntryFunc, originalTExitFunc, originalTDataFunc);
    375     utrace_setLevel(originalLevel);
    376 }
    377 
    378 
    379 
    380