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