]> git.saurik.com Git - apple/icu.git/blob - icuSources/test/cintltst/reapits.c
ICU-400.38.tar.gz
[apple/icu.git] / icuSources / test / cintltst / reapits.c
1 /********************************************************************
2 * COPYRIGHT:
3 * Copyright (c) 2004-2008, International Business Machines Corporation and
4 * others. All Rights Reserved.
5 ********************************************************************/
6 /********************************************************************************
7 *
8 * File reapits.c
9 *
10 *********************************************************************************/
11 /*C API TEST FOR Regular Expressions */
12 /**
13 * This is an API test for ICU regular expressions in C. It doesn't test very many cases, and doesn't
14 * try to test the full functionality. It just calls each function and verifies that it
15 * works on a basic level.
16 *
17 * More complete testing of regular expression functionality is done with the C++ tests.
18 **/
19
20 #include "unicode/utypes.h"
21
22 #if !UCONFIG_NO_REGULAR_EXPRESSIONS
23
24 #include <stdlib.h>
25 #include <string.h>
26 #include "unicode/uloc.h"
27 #include "unicode/uregex.h"
28 #include "unicode/ustring.h"
29 #include "cintltst.h"
30
31 #define TEST_ASSERT_SUCCESS(status) {if (U_FAILURE(status)) { \
32 log_err("Failure at file %s, line %d, error = %s\n", __FILE__, __LINE__, u_errorName(status));}}
33
34 #define TEST_ASSERT(expr) {if ((expr)==FALSE) { \
35 log_err("Test Failure at file %s, line %d\n", __FILE__, __LINE__);}}
36
37 /*
38 * TEST_SETUP and TEST_TEARDOWN
39 * macros to handle the boilerplate around setting up regex test cases.
40 * parameteres to setup:
41 * pattern: The regex pattern, a (char *) null terminated C string.
42 * testString: The string data, also a (char *) C string.
43 * flags: Regex flags to set when compiling the pattern
44 *
45 * Put arbitrary test code between SETUP and TEARDOWN.
46 * 're" is the compiled, ready-to-go regular expression.
47 */
48 #define TEST_SETUP(pattern, testString, flags) { \
49 UChar *srcString = NULL; \
50 status = U_ZERO_ERROR; \
51 re = uregex_openC(pattern, flags, NULL, &status); \
52 TEST_ASSERT_SUCCESS(status); \
53 srcString = (UChar *)malloc((strlen(testString)+2)*sizeof(UChar)); \
54 u_uastrncpy(srcString, testString, strlen(testString)+1); \
55 uregex_setText(re, srcString, -1, &status); \
56 TEST_ASSERT_SUCCESS(status); \
57 if (U_SUCCESS(status)) {
58
59 #define TEST_TEARDOWN \
60 } \
61 TEST_ASSERT_SUCCESS(status); \
62 uregex_close(re); \
63 free(srcString); \
64 }
65
66
67 static void test_assert_string(const char *expected, const UChar *actual, UBool nulTerm, const char *file, int line) {
68 char buf_inside_macro[120];
69 int32_t len = (int32_t)strlen(expected);
70 UBool success;
71 if (nulTerm) {
72 u_austrncpy(buf_inside_macro, (actual), len+1);
73 buf_inside_macro[len+2] = 0;
74 success = (strcmp((expected), buf_inside_macro) == 0);
75 } else {
76 u_austrncpy(buf_inside_macro, (actual), len);
77 buf_inside_macro[len+1] = 0;
78 success = (strncmp((expected), buf_inside_macro, len) == 0);
79 }
80 if (success == FALSE) {
81 log_err("Failure at file %s, line %d, expected \"%s\", got \"%s\"\n",
82 file, line, (expected), buf_inside_macro);
83 }
84 }
85
86 #define TEST_ASSERT_STRING(expected, actual, nulTerm) test_assert_string(expected, actual, nulTerm, __FILE__, __LINE__)
87
88
89
90
91
92 static void TestRegexCAPI(void);
93 static void TestBug4315(void);
94
95 void addURegexTest(TestNode** root);
96
97 void addURegexTest(TestNode** root)
98 {
99 addTest(root, &TestRegexCAPI, "regex/TestRegexCAPI");
100 addTest(root, &TestBug4315, "regex/TestBug4315");
101 }
102
103 /*
104 * Call back function and context struct used for testing
105 * regular expression user callbacks. This test is mostly the same as
106 * the corresponding C++ test in intltest.
107 */
108 typedef struct callBackContext {
109 int32_t maxCalls;
110 int32_t numCalls;
111 int32_t lastSteps;
112 } callBackContext;
113
114 static UBool U_EXPORT2 U_CALLCONV
115 TestCallbackFn(const void *context, int32_t steps) {
116 callBackContext *info = (callBackContext *)context;
117 if (info->lastSteps+1 != steps) {
118 log_err("incorrect steps in callback. Expected %d, got %d\n", info->lastSteps+1, steps);
119 }
120 info->lastSteps = steps;
121 info->numCalls++;
122 return (info->numCalls < info->maxCalls);
123 }
124
125 /*
126 * Regular Expression C API Tests
127 */
128 static void TestRegexCAPI(void) {
129 UErrorCode status = U_ZERO_ERROR;
130 URegularExpression *re;
131 UChar pat[200];
132 UChar *minus1;
133
134 memset(&minus1, -1, sizeof(minus1));
135
136 /* Mimimalist open/close */
137 u_uastrncpy(pat, "abc*", sizeof(pat)/2);
138 re = uregex_open(pat, -1, 0, 0, &status);
139 if (U_FAILURE(status)) {
140 log_err("Failed to open regular expression, line %d, error is \"%s\"\n", __LINE__, u_errorName(status));
141 return;
142 }
143 uregex_close(re);
144
145 /* Open with all flag values set */
146 status = U_ZERO_ERROR;
147 re = uregex_open(pat, -1,
148 UREGEX_CASE_INSENSITIVE | UREGEX_COMMENTS | UREGEX_DOTALL | UREGEX_MULTILINE | UREGEX_UWORD,
149 0, &status);
150 TEST_ASSERT_SUCCESS(status);
151 uregex_close(re);
152
153 /* Open with an invalid flag */
154 status = U_ZERO_ERROR;
155 re = uregex_open(pat, -1, 0x40000000, 0, &status);
156 TEST_ASSERT(status == U_REGEX_INVALID_FLAG);
157 uregex_close(re);
158
159 /* openC with an invalid parameter */
160 status = U_ZERO_ERROR;
161 re = uregex_openC(NULL,
162 UREGEX_CASE_INSENSITIVE | UREGEX_COMMENTS | UREGEX_DOTALL | UREGEX_MULTILINE | UREGEX_UWORD, 0, &status);
163 TEST_ASSERT(status == U_ILLEGAL_ARGUMENT_ERROR && re == NULL);
164
165 /* openC with an invalid parameter */
166 status = U_USELESS_COLLATOR_ERROR;
167 re = uregex_openC(NULL,
168 UREGEX_CASE_INSENSITIVE | UREGEX_COMMENTS | UREGEX_DOTALL | UREGEX_MULTILINE | UREGEX_UWORD, 0, &status);
169 TEST_ASSERT(status == U_USELESS_COLLATOR_ERROR && re == NULL);
170
171 /* openC open from a C string */
172 {
173 const UChar *p;
174 int32_t len;
175 status = U_ZERO_ERROR;
176 re = uregex_openC("abc*", 0, 0, &status);
177 TEST_ASSERT_SUCCESS(status);
178 p = uregex_pattern(re, &len, &status);
179 TEST_ASSERT_SUCCESS(status);
180
181 /* The TEST_ASSERT_SUCCESS above should change too... */
182 if(U_SUCCESS(status)) {
183 u_uastrncpy(pat, "abc*", sizeof(pat)/2);
184 TEST_ASSERT(u_strcmp(pat, p) == 0);
185 TEST_ASSERT(len==(int32_t)strlen("abc*"));
186 }
187
188 uregex_close(re);
189
190 /* TODO: Open with ParseError parameter */
191 }
192
193 /*
194 * clone
195 */
196 {
197 URegularExpression *clone1;
198 URegularExpression *clone2;
199 URegularExpression *clone3;
200 UChar testString1[30];
201 UChar testString2[30];
202 UBool result;
203
204
205 status = U_ZERO_ERROR;
206 re = uregex_openC("abc*", 0, 0, &status);
207 TEST_ASSERT_SUCCESS(status);
208 clone1 = uregex_clone(re, &status);
209 TEST_ASSERT_SUCCESS(status);
210 TEST_ASSERT(clone1 != NULL);
211
212 status = U_ZERO_ERROR;
213 clone2 = uregex_clone(re, &status);
214 TEST_ASSERT_SUCCESS(status);
215 TEST_ASSERT(clone2 != NULL);
216 uregex_close(re);
217
218 status = U_ZERO_ERROR;
219 clone3 = uregex_clone(clone2, &status);
220 TEST_ASSERT_SUCCESS(status);
221 TEST_ASSERT(clone3 != NULL);
222
223 u_uastrncpy(testString1, "abcccd", sizeof(pat)/2);
224 u_uastrncpy(testString2, "xxxabcccd", sizeof(pat)/2);
225
226 status = U_ZERO_ERROR;
227 uregex_setText(clone1, testString1, -1, &status);
228 TEST_ASSERT_SUCCESS(status);
229 result = uregex_lookingAt(clone1, 0, &status);
230 TEST_ASSERT_SUCCESS(status);
231 TEST_ASSERT(result==TRUE);
232
233 status = U_ZERO_ERROR;
234 uregex_setText(clone2, testString2, -1, &status);
235 TEST_ASSERT_SUCCESS(status);
236 result = uregex_lookingAt(clone2, 0, &status);
237 TEST_ASSERT_SUCCESS(status);
238 TEST_ASSERT(result==FALSE);
239 result = uregex_find(clone2, 0, &status);
240 TEST_ASSERT_SUCCESS(status);
241 TEST_ASSERT(result==TRUE);
242
243 uregex_close(clone1);
244 uregex_close(clone2);
245 uregex_close(clone3);
246
247 }
248
249 /*
250 * pattern()
251 */
252 {
253 const UChar *resultPat;
254 int32_t resultLen;
255 u_uastrncpy(pat, "hello", sizeof(pat)/2);
256 status = U_ZERO_ERROR;
257 re = uregex_open(pat, -1, 0, NULL, &status);
258 resultPat = uregex_pattern(re, &resultLen, &status);
259 TEST_ASSERT_SUCCESS(status);
260
261 /* The TEST_ASSERT_SUCCESS above should change too... */
262 if (U_SUCCESS(status)) {
263 TEST_ASSERT(resultLen == -1);
264 TEST_ASSERT(u_strcmp(resultPat, pat) == 0);
265 }
266
267 uregex_close(re);
268
269 status = U_ZERO_ERROR;
270 re = uregex_open(pat, 3, 0, NULL, &status);
271 resultPat = uregex_pattern(re, &resultLen, &status);
272 TEST_ASSERT_SUCCESS(status);
273 TEST_ASSERT_SUCCESS(status);
274
275 /* The TEST_ASSERT_SUCCESS above should change too... */
276 if (U_SUCCESS(status)) {
277 TEST_ASSERT(resultLen == 3);
278 TEST_ASSERT(u_strncmp(resultPat, pat, 3) == 0);
279 TEST_ASSERT(u_strlen(resultPat) == 3);
280 }
281
282 uregex_close(re);
283 }
284
285 /*
286 * flags()
287 */
288 {
289 int32_t t;
290
291 status = U_ZERO_ERROR;
292 re = uregex_open(pat, -1, 0, NULL, &status);
293 t = uregex_flags(re, &status);
294 TEST_ASSERT_SUCCESS(status);
295 TEST_ASSERT(t == 0);
296 uregex_close(re);
297
298 status = U_ZERO_ERROR;
299 re = uregex_open(pat, -1, 0, NULL, &status);
300 t = uregex_flags(re, &status);
301 TEST_ASSERT_SUCCESS(status);
302 TEST_ASSERT(t == 0);
303 uregex_close(re);
304
305 status = U_ZERO_ERROR;
306 re = uregex_open(pat, -1, UREGEX_CASE_INSENSITIVE | UREGEX_DOTALL, NULL, &status);
307 t = uregex_flags(re, &status);
308 TEST_ASSERT_SUCCESS(status);
309 TEST_ASSERT(t == (UREGEX_CASE_INSENSITIVE | UREGEX_DOTALL));
310 uregex_close(re);
311 }
312
313 /*
314 * setText() and lookingAt()
315 */
316 {
317 UChar text1[50];
318 UChar text2[50];
319 UBool result;
320
321 u_uastrncpy(text1, "abcccd", sizeof(text1)/2);
322 u_uastrncpy(text2, "abcccxd", sizeof(text2)/2);
323 status = U_ZERO_ERROR;
324 u_uastrncpy(pat, "abc*d", sizeof(pat)/2);
325 re = uregex_open(pat, -1, 0, NULL, &status);
326 TEST_ASSERT_SUCCESS(status);
327
328 /* Operation before doing a setText should fail... */
329 status = U_ZERO_ERROR;
330 uregex_lookingAt(re, 0, &status);
331 TEST_ASSERT( status== U_REGEX_INVALID_STATE);
332
333 status = U_ZERO_ERROR;
334 uregex_setText(re, text1, -1, &status);
335 result = uregex_lookingAt(re, 0, &status);
336 TEST_ASSERT(result == TRUE);
337 TEST_ASSERT_SUCCESS(status);
338
339 status = U_ZERO_ERROR;
340 uregex_setText(re, text2, -1, &status);
341 result = uregex_lookingAt(re, 0, &status);
342 TEST_ASSERT(result == FALSE);
343 TEST_ASSERT_SUCCESS(status);
344
345 status = U_ZERO_ERROR;
346 uregex_setText(re, text1, -1, &status);
347 result = uregex_lookingAt(re, 0, &status);
348 TEST_ASSERT(result == TRUE);
349 TEST_ASSERT_SUCCESS(status);
350
351 status = U_ZERO_ERROR;
352 uregex_setText(re, text1, 5, &status);
353 result = uregex_lookingAt(re, 0, &status);
354 TEST_ASSERT(result == FALSE);
355 TEST_ASSERT_SUCCESS(status);
356
357 status = U_ZERO_ERROR;
358 uregex_setText(re, text1, 6, &status);
359 result = uregex_lookingAt(re, 0, &status);
360 TEST_ASSERT(result == TRUE);
361 TEST_ASSERT_SUCCESS(status);
362
363 uregex_close(re);
364 }
365
366
367 /*
368 * getText()
369 */
370 {
371 UChar text1[50];
372 UChar text2[50];
373 const UChar *result;
374 int32_t textLength;
375
376 u_uastrncpy(text1, "abcccd", sizeof(text1)/2);
377 u_uastrncpy(text2, "abcccxd", sizeof(text2)/2);
378 status = U_ZERO_ERROR;
379 u_uastrncpy(pat, "abc*d", sizeof(pat)/2);
380 re = uregex_open(pat, -1, 0, NULL, &status);
381
382 uregex_setText(re, text1, -1, &status);
383 result = uregex_getText(re, &textLength, &status);
384 TEST_ASSERT(result == text1);
385 TEST_ASSERT(textLength == -1);
386 TEST_ASSERT_SUCCESS(status);
387
388 status = U_ZERO_ERROR;
389 uregex_setText(re, text2, 7, &status);
390 result = uregex_getText(re, &textLength, &status);
391 TEST_ASSERT(result == text2);
392 TEST_ASSERT(textLength == 7);
393 TEST_ASSERT_SUCCESS(status);
394
395 status = U_ZERO_ERROR;
396 uregex_setText(re, text2, 4, &status);
397 result = uregex_getText(re, &textLength, &status);
398 TEST_ASSERT(result == text2);
399 TEST_ASSERT(textLength == 4);
400 TEST_ASSERT_SUCCESS(status);
401 uregex_close(re);
402 }
403
404 /*
405 * matches()
406 */
407 {
408 UChar text1[50];
409 UBool result;
410 int len;
411 UChar nullString[] = {0,0,0};
412
413 u_uastrncpy(text1, "abcccde", sizeof(text1)/2);
414 status = U_ZERO_ERROR;
415 u_uastrncpy(pat, "abc*d", sizeof(pat)/2);
416 re = uregex_open(pat, -1, 0, NULL, &status);
417
418 uregex_setText(re, text1, -1, &status);
419 result = uregex_matches(re, 0, &status);
420 TEST_ASSERT(result == FALSE);
421 TEST_ASSERT_SUCCESS(status);
422
423 status = U_ZERO_ERROR;
424 uregex_setText(re, text1, 6, &status);
425 result = uregex_matches(re, 0, &status);
426 TEST_ASSERT(result == TRUE);
427 TEST_ASSERT_SUCCESS(status);
428
429 status = U_ZERO_ERROR;
430 uregex_setText(re, text1, 6, &status);
431 result = uregex_matches(re, 1, &status);
432 TEST_ASSERT(result == FALSE);
433 TEST_ASSERT_SUCCESS(status);
434 uregex_close(re);
435
436 status = U_ZERO_ERROR;
437 re = uregex_openC(".?", 0, NULL, &status);
438 uregex_setText(re, text1, -1, &status);
439 len = u_strlen(text1);
440 result = uregex_matches(re, len, &status);
441 TEST_ASSERT(result == TRUE);
442 TEST_ASSERT_SUCCESS(status);
443
444 status = U_ZERO_ERROR;
445 uregex_setText(re, nullString, -1, &status);
446 TEST_ASSERT_SUCCESS(status);
447 result = uregex_matches(re, 0, &status);
448 TEST_ASSERT(result == TRUE);
449 TEST_ASSERT_SUCCESS(status);
450 uregex_close(re);
451 }
452
453
454 /*
455 * lookingAt() Used in setText test.
456 */
457
458
459 /*
460 * find(), findNext, start, end, reset
461 */
462 {
463 UChar text1[50];
464 UBool result;
465 u_uastrncpy(text1, "012rx5rx890rxrx...", sizeof(text1)/2);
466 status = U_ZERO_ERROR;
467 re = uregex_openC("rx", 0, NULL, &status);
468
469 uregex_setText(re, text1, -1, &status);
470 result = uregex_find(re, 0, &status);
471 TEST_ASSERT(result == TRUE);
472 TEST_ASSERT(uregex_start(re, 0, &status) == 3);
473 TEST_ASSERT(uregex_end(re, 0, &status) == 5);
474 TEST_ASSERT_SUCCESS(status);
475
476 result = uregex_find(re, 9, &status);
477 TEST_ASSERT(result == TRUE);
478 TEST_ASSERT(uregex_start(re, 0, &status) == 11);
479 TEST_ASSERT(uregex_end(re, 0, &status) == 13);
480 TEST_ASSERT_SUCCESS(status);
481
482 result = uregex_find(re, 14, &status);
483 TEST_ASSERT(result == FALSE);
484 TEST_ASSERT_SUCCESS(status);
485
486 status = U_ZERO_ERROR;
487 uregex_reset(re, 0, &status);
488
489 result = uregex_findNext(re, &status);
490 TEST_ASSERT(result == TRUE);
491 TEST_ASSERT(uregex_start(re, 0, &status) == 3);
492 TEST_ASSERT(uregex_end(re, 0, &status) == 5);
493 TEST_ASSERT_SUCCESS(status);
494
495 result = uregex_findNext(re, &status);
496 TEST_ASSERT(result == TRUE);
497 TEST_ASSERT(uregex_start(re, 0, &status) == 6);
498 TEST_ASSERT(uregex_end(re, 0, &status) == 8);
499 TEST_ASSERT_SUCCESS(status);
500
501 status = U_ZERO_ERROR;
502 uregex_reset(re, 12, &status);
503
504 result = uregex_findNext(re, &status);
505 TEST_ASSERT(result == TRUE);
506 TEST_ASSERT(uregex_start(re, 0, &status) == 13);
507 TEST_ASSERT(uregex_end(re, 0, &status) == 15);
508 TEST_ASSERT_SUCCESS(status);
509
510 result = uregex_findNext(re, &status);
511 TEST_ASSERT(result == FALSE);
512 TEST_ASSERT_SUCCESS(status);
513
514 uregex_close(re);
515 }
516
517 /*
518 * groupCount
519 */
520 {
521 int32_t result;
522
523 status = U_ZERO_ERROR;
524 re = uregex_openC("abc", 0, NULL, &status);
525 result = uregex_groupCount(re, &status);
526 TEST_ASSERT_SUCCESS(status);
527 TEST_ASSERT(result == 0);
528 uregex_close(re);
529
530 status = U_ZERO_ERROR;
531 re = uregex_openC("abc(def)(ghi(j))", 0, NULL, &status);
532 result = uregex_groupCount(re, &status);
533 TEST_ASSERT_SUCCESS(status);
534 TEST_ASSERT(result == 3);
535 uregex_close(re);
536
537 }
538
539
540 /*
541 * group()
542 */
543 {
544 UChar text1[80];
545 UChar buf[80];
546 UBool result;
547 int32_t resultSz;
548 u_uastrncpy(text1, "noise abc interior def, and this is off the end", sizeof(text1)/2);
549
550 status = U_ZERO_ERROR;
551 re = uregex_openC("abc(.*?)def", 0, NULL, &status);
552 TEST_ASSERT_SUCCESS(status);
553
554
555 uregex_setText(re, text1, -1, &status);
556 result = uregex_find(re, 0, &status);
557 TEST_ASSERT(result==TRUE);
558
559 /* Capture Group 0, the full match. Should succeed. */
560 status = U_ZERO_ERROR;
561 resultSz = uregex_group(re, 0, buf, sizeof(buf)/2, &status);
562 TEST_ASSERT_SUCCESS(status);
563 TEST_ASSERT_STRING("abc interior def", buf, TRUE);
564 TEST_ASSERT(resultSz == (int32_t)strlen("abc interior def"));
565
566 /* Capture group #1. Should succeed. */
567 status = U_ZERO_ERROR;
568 resultSz = uregex_group(re, 1, buf, sizeof(buf)/2, &status);
569 TEST_ASSERT_SUCCESS(status);
570 TEST_ASSERT_STRING(" interior ", buf, TRUE);
571 TEST_ASSERT(resultSz == (int32_t)strlen(" interior "));
572
573 /* Capture group out of range. Error. */
574 status = U_ZERO_ERROR;
575 uregex_group(re, 2, buf, sizeof(buf)/2, &status);
576 TEST_ASSERT(status == U_INDEX_OUTOFBOUNDS_ERROR);
577
578 /* NULL buffer, pure pre-flight */
579 status = U_ZERO_ERROR;
580 resultSz = uregex_group(re, 0, NULL, 0, &status);
581 TEST_ASSERT(status == U_BUFFER_OVERFLOW_ERROR);
582 TEST_ASSERT(resultSz == (int32_t)strlen("abc interior def"));
583
584 /* Too small buffer, truncated string */
585 status = U_ZERO_ERROR;
586 memset(buf, -1, sizeof(buf));
587 resultSz = uregex_group(re, 0, buf, 5, &status);
588 TEST_ASSERT(status == U_BUFFER_OVERFLOW_ERROR);
589 TEST_ASSERT_STRING("abc i", buf, FALSE);
590 TEST_ASSERT(buf[5] == (UChar)0xffff);
591 TEST_ASSERT(resultSz == (int32_t)strlen("abc interior def"));
592
593 /* Output string just fits buffer, no NUL term. */
594 status = U_ZERO_ERROR;
595 resultSz = uregex_group(re, 0, buf, (int32_t)strlen("abc interior def"), &status);
596 TEST_ASSERT(status == U_STRING_NOT_TERMINATED_WARNING);
597 TEST_ASSERT_STRING("abc interior def", buf, FALSE);
598 TEST_ASSERT(resultSz == (int32_t)strlen("abc interior def"));
599 TEST_ASSERT(buf[strlen("abc interior def")] == (UChar)0xffff);
600
601 uregex_close(re);
602
603 }
604
605 /*
606 * Regions
607 */
608
609
610 /* SetRegion(), getRegion() do something */
611 TEST_SETUP(".*", "0123456789ABCDEF", 0)
612 UChar resultString[40];
613 TEST_ASSERT(uregex_regionStart(re, &status) == 0);
614 TEST_ASSERT(uregex_regionEnd(re, &status) == 16);
615 uregex_setRegion(re, 3, 6, &status);
616 TEST_ASSERT(uregex_regionStart(re, &status) == 3);
617 TEST_ASSERT(uregex_regionEnd(re, &status) == 6);
618 TEST_ASSERT(uregex_findNext(re, &status));
619 TEST_ASSERT(uregex_group(re, 0, resultString, sizeof(resultString)/2, &status) == 3)
620 TEST_ASSERT_STRING("345", resultString, TRUE);
621 TEST_TEARDOWN;
622
623 /* find(start=-1) uses regions */
624 TEST_SETUP(".*", "0123456789ABCDEF", 0);
625 uregex_setRegion(re, 4, 6, &status);
626 TEST_ASSERT(uregex_find(re, -1, &status) == TRUE);
627 TEST_ASSERT(uregex_start(re, 0, &status) == 4);
628 TEST_ASSERT(uregex_end(re, 0, &status) == 6);
629 TEST_TEARDOWN;
630
631 /* find (start >=0) does not use regions */
632 TEST_SETUP(".*", "0123456789ABCDEF", 0);
633 uregex_setRegion(re, 4, 6, &status);
634 TEST_ASSERT(uregex_find(re, 0, &status) == TRUE);
635 TEST_ASSERT(uregex_start(re, 0, &status) == 0);
636 TEST_ASSERT(uregex_end(re, 0, &status) == 16);
637 TEST_TEARDOWN;
638
639 /* findNext() obeys regions */
640 TEST_SETUP(".", "0123456789ABCDEF", 0);
641 uregex_setRegion(re, 4, 6, &status);
642 TEST_ASSERT(uregex_findNext(re,&status) == TRUE);
643 TEST_ASSERT(uregex_start(re, 0, &status) == 4);
644 TEST_ASSERT(uregex_findNext(re, &status) == TRUE);
645 TEST_ASSERT(uregex_start(re, 0, &status) == 5);
646 TEST_ASSERT(uregex_findNext(re, &status) == FALSE);
647 TEST_TEARDOWN;
648
649 /* matches(start=-1) uses regions */
650 /* Also, verify that non-greedy *? succeeds in finding the full match. */
651 TEST_SETUP(".*?", "0123456789ABCDEF", 0);
652 uregex_setRegion(re, 4, 6, &status);
653 TEST_ASSERT(uregex_matches(re, -1, &status) == TRUE);
654 TEST_ASSERT(uregex_start(re, 0, &status) == 4);
655 TEST_ASSERT(uregex_end(re, 0, &status) == 6);
656 TEST_TEARDOWN;
657
658 /* matches (start >=0) does not use regions */
659 TEST_SETUP(".*?", "0123456789ABCDEF", 0);
660 uregex_setRegion(re, 4, 6, &status);
661 TEST_ASSERT(uregex_matches(re, 0, &status) == TRUE);
662 TEST_ASSERT(uregex_start(re, 0, &status) == 0);
663 TEST_ASSERT(uregex_end(re, 0, &status) == 16);
664 TEST_TEARDOWN;
665
666 /* lookingAt(start=-1) uses regions */
667 /* Also, verify that non-greedy *? finds the first (shortest) match. */
668 TEST_SETUP(".*?", "0123456789ABCDEF", 0);
669 uregex_setRegion(re, 4, 6, &status);
670 TEST_ASSERT(uregex_lookingAt(re, -1, &status) == TRUE);
671 TEST_ASSERT(uregex_start(re, 0, &status) == 4);
672 TEST_ASSERT(uregex_end(re, 0, &status) == 4);
673 TEST_TEARDOWN;
674
675 /* lookingAt (start >=0) does not use regions */
676 TEST_SETUP(".*?", "0123456789ABCDEF", 0);
677 uregex_setRegion(re, 4, 6, &status);
678 TEST_ASSERT(uregex_lookingAt(re, 0, &status) == TRUE);
679 TEST_ASSERT(uregex_start(re, 0, &status) == 0);
680 TEST_ASSERT(uregex_end(re, 0, &status) == 0);
681 TEST_TEARDOWN;
682
683 /* hitEnd() */
684 TEST_SETUP("[a-f]*", "abcdefghij", 0);
685 TEST_ASSERT(uregex_find(re, 0, &status) == TRUE);
686 TEST_ASSERT(uregex_hitEnd(re, &status) == FALSE);
687 TEST_TEARDOWN;
688
689 TEST_SETUP("[a-f]*", "abcdef", 0);
690 TEST_ASSERT(uregex_find(re, 0, &status) == TRUE);
691 TEST_ASSERT(uregex_hitEnd(re, &status) == TRUE);
692 TEST_TEARDOWN;
693
694 /* requireEnd */
695 TEST_SETUP("abcd", "abcd", 0);
696 TEST_ASSERT(uregex_find(re, 0, &status) == TRUE);
697 TEST_ASSERT(uregex_requireEnd(re, &status) == FALSE);
698 TEST_TEARDOWN;
699
700 TEST_SETUP("abcd$", "abcd", 0);
701 TEST_ASSERT(uregex_find(re, 0, &status) == TRUE);
702 TEST_ASSERT(uregex_requireEnd(re, &status) == TRUE);
703 TEST_TEARDOWN;
704
705 /* anchoringBounds */
706 TEST_SETUP("abc$", "abcdef", 0);
707 TEST_ASSERT(uregex_hasAnchoringBounds(re, &status) == TRUE);
708 uregex_useAnchoringBounds(re, FALSE, &status);
709 TEST_ASSERT(uregex_hasAnchoringBounds(re, &status) == FALSE);
710
711 TEST_ASSERT(uregex_find(re, -1, &status) == FALSE);
712 uregex_useAnchoringBounds(re, TRUE, &status);
713 uregex_setRegion(re, 0, 3, &status);
714 TEST_ASSERT(uregex_find(re, -1, &status) == TRUE);
715 TEST_ASSERT(uregex_end(re, 0, &status) == 3);
716 TEST_TEARDOWN;
717
718 /* Transparent Bounds */
719 TEST_SETUP("abc(?=def)", "abcdef", 0);
720 TEST_ASSERT(uregex_hasTransparentBounds(re, &status) == FALSE);
721 uregex_useTransparentBounds(re, TRUE, &status);
722 TEST_ASSERT(uregex_hasTransparentBounds(re, &status) == TRUE);
723
724 uregex_useTransparentBounds(re, FALSE, &status);
725 TEST_ASSERT(uregex_find(re, -1, &status) == TRUE); /* No Region */
726 uregex_setRegion(re, 0, 3, &status);
727 TEST_ASSERT(uregex_find(re, -1, &status) == FALSE); /* with region, opaque bounds */
728 uregex_useTransparentBounds(re, TRUE, &status);
729 TEST_ASSERT(uregex_find(re, -1, &status) == TRUE); /* with region, transparent bounds */
730 TEST_ASSERT(uregex_end(re, 0, &status) == 3);
731 TEST_TEARDOWN;
732
733
734 /*
735 * replaceFirst()
736 */
737 {
738 UChar text1[80];
739 UChar text2[80];
740 UChar replText[80];
741 UChar buf[80];
742 int32_t resultSz;
743 u_uastrncpy(text1, "Replace xaax x1x x...x.", sizeof(text1)/2);
744 u_uastrncpy(text2, "No match here.", sizeof(text2)/2);
745 u_uastrncpy(replText, "<$1>", sizeof(replText)/2);
746
747 status = U_ZERO_ERROR;
748 re = uregex_openC("x(.*?)x", 0, NULL, &status);
749 TEST_ASSERT_SUCCESS(status);
750
751 /* Normal case, with match */
752 uregex_setText(re, text1, -1, &status);
753 resultSz = uregex_replaceFirst(re, replText, -1, buf, sizeof(buf)/2, &status);
754 TEST_ASSERT_SUCCESS(status);
755 TEST_ASSERT_STRING("Replace <aa> x1x x...x.", buf, TRUE);
756 TEST_ASSERT(resultSz == (int32_t)strlen("Replace xaax x1x x...x."));
757
758 /* No match. Text should copy to output with no changes. */
759 status = U_ZERO_ERROR;
760 uregex_setText(re, text2, -1, &status);
761 resultSz = uregex_replaceFirst(re, replText, -1, buf, sizeof(buf)/2, &status);
762 TEST_ASSERT_SUCCESS(status);
763 TEST_ASSERT_STRING("No match here.", buf, TRUE);
764 TEST_ASSERT(resultSz == (int32_t)strlen("No match here."));
765
766 /* Match, output just fills buffer, no termination warning. */
767 status = U_ZERO_ERROR;
768 uregex_setText(re, text1, -1, &status);
769 memset(buf, -1, sizeof(buf));
770 resultSz = uregex_replaceFirst(re, replText, -1, buf, strlen("Replace <aa> x1x x...x."), &status);
771 TEST_ASSERT(status == U_STRING_NOT_TERMINATED_WARNING);
772 TEST_ASSERT_STRING("Replace <aa> x1x x...x.", buf, FALSE);
773 TEST_ASSERT(resultSz == (int32_t)strlen("Replace xaax x1x x...x."));
774 TEST_ASSERT(buf[resultSz] == (UChar)0xffff);
775
776 /* Do the replaceFirst again, without first resetting anything.
777 * Should give the same results.
778 */
779 status = U_ZERO_ERROR;
780 memset(buf, -1, sizeof(buf));
781 resultSz = uregex_replaceFirst(re, replText, -1, buf, strlen("Replace <aa> x1x x...x."), &status);
782 TEST_ASSERT(status == U_STRING_NOT_TERMINATED_WARNING);
783 TEST_ASSERT_STRING("Replace <aa> x1x x...x.", buf, FALSE);
784 TEST_ASSERT(resultSz == (int32_t)strlen("Replace xaax x1x x...x."));
785 TEST_ASSERT(buf[resultSz] == (UChar)0xffff);
786
787 /* NULL buffer, zero buffer length */
788 status = U_ZERO_ERROR;
789 resultSz = uregex_replaceFirst(re, replText, -1, NULL, 0, &status);
790 TEST_ASSERT(status == U_BUFFER_OVERFLOW_ERROR);
791 TEST_ASSERT(resultSz == (int32_t)strlen("Replace xaax x1x x...x."));
792
793 /* Buffer too small by one */
794 status = U_ZERO_ERROR;
795 memset(buf, -1, sizeof(buf));
796 resultSz = uregex_replaceFirst(re, replText, -1, buf, strlen("Replace <aa> x1x x...x.")-1, &status);
797 TEST_ASSERT(status == U_BUFFER_OVERFLOW_ERROR);
798 TEST_ASSERT_STRING("Replace <aa> x1x x...x", buf, FALSE);
799 TEST_ASSERT(resultSz == (int32_t)strlen("Replace xaax x1x x...x."));
800 TEST_ASSERT(buf[resultSz] == (UChar)0xffff);
801
802 uregex_close(re);
803 }
804
805
806 /*
807 * replaceAll()
808 */
809 {
810 UChar text1[80];
811 UChar text2[80];
812 UChar replText[80];
813 UChar buf[80];
814 int32_t resultSz;
815 int32_t expectedResultSize;
816 int32_t i;
817
818 u_uastrncpy(text1, "Replace xaax x1x x...x.", sizeof(text1)/2);
819 u_uastrncpy(text2, "No match here.", sizeof(text2)/2);
820 u_uastrncpy(replText, "<$1>", sizeof(replText)/2);
821 expectedResultSize = u_strlen(text1);
822
823 status = U_ZERO_ERROR;
824 re = uregex_openC("x(.*?)x", 0, NULL, &status);
825 TEST_ASSERT_SUCCESS(status);
826
827 /* Normal case, with match */
828 uregex_setText(re, text1, -1, &status);
829 resultSz = uregex_replaceAll(re, replText, -1, buf, sizeof(buf)/2, &status);
830 TEST_ASSERT_SUCCESS(status);
831 TEST_ASSERT_STRING("Replace <aa> <1> <...>.", buf, TRUE);
832 TEST_ASSERT(resultSz == (int32_t)strlen("Replace xaax x1x x...x."));
833
834 /* No match. Text should copy to output with no changes. */
835 status = U_ZERO_ERROR;
836 uregex_setText(re, text2, -1, &status);
837 resultSz = uregex_replaceAll(re, replText, -1, buf, sizeof(buf)/2, &status);
838 TEST_ASSERT_SUCCESS(status);
839 TEST_ASSERT_STRING("No match here.", buf, TRUE);
840 TEST_ASSERT(resultSz == (int32_t)strlen("No match here."));
841
842 /* Match, output just fills buffer, no termination warning. */
843 status = U_ZERO_ERROR;
844 uregex_setText(re, text1, -1, &status);
845 memset(buf, -1, sizeof(buf));
846 resultSz = uregex_replaceAll(re, replText, -1, buf, strlen("Replace xaax x1x x...x."), &status);
847 TEST_ASSERT(status == U_STRING_NOT_TERMINATED_WARNING);
848 TEST_ASSERT_STRING("Replace <aa> <1> <...>.", buf, FALSE);
849 TEST_ASSERT(resultSz == (int32_t)strlen("Replace <aa> <1> <...>."));
850 TEST_ASSERT(buf[resultSz] == (UChar)0xffff);
851
852 /* Do the replaceFirst again, without first resetting anything.
853 * Should give the same results.
854 */
855 status = U_ZERO_ERROR;
856 memset(buf, -1, sizeof(buf));
857 resultSz = uregex_replaceAll(re, replText, -1, buf, strlen("Replace xaax x1x x...x."), &status);
858 TEST_ASSERT(status == U_STRING_NOT_TERMINATED_WARNING);
859 TEST_ASSERT_STRING("Replace <aa> <1> <...>.", buf, FALSE);
860 TEST_ASSERT(resultSz == (int32_t)strlen("Replace <aa> <1> <...>."));
861 TEST_ASSERT(buf[resultSz] == (UChar)0xffff);
862
863 /* NULL buffer, zero buffer length */
864 status = U_ZERO_ERROR;
865 resultSz = uregex_replaceAll(re, replText, -1, NULL, 0, &status);
866 TEST_ASSERT(status == U_BUFFER_OVERFLOW_ERROR);
867 TEST_ASSERT(resultSz == (int32_t)strlen("Replace <aa> <1> <...>."));
868
869 /* Buffer too small. Try every size, which will tickle edge cases
870 * in uregex_appendReplacement (used by replaceAll) */
871 for (i=0; i<expectedResultSize; i++) {
872 char expected[80];
873 status = U_ZERO_ERROR;
874 memset(buf, -1, sizeof(buf));
875 resultSz = uregex_replaceAll(re, replText, -1, buf, i, &status);
876 TEST_ASSERT(status == U_BUFFER_OVERFLOW_ERROR);
877 strcpy(expected, "Replace <aa> <1> <...>.");
878 expected[i] = 0;
879 TEST_ASSERT_STRING(expected, buf, FALSE);
880 TEST_ASSERT(resultSz == expectedResultSize);
881 TEST_ASSERT(buf[i] == (UChar)0xffff);
882 }
883
884 uregex_close(re);
885 }
886
887
888 /*
889 * appendReplacement()
890 */
891 {
892 UChar text[100];
893 UChar repl[100];
894 UChar buf[100];
895 UChar *bufPtr;
896 int32_t bufCap;
897
898
899 status = U_ZERO_ERROR;
900 re = uregex_openC(".*", 0, 0, &status);
901 TEST_ASSERT_SUCCESS(status);
902
903 u_uastrncpy(text, "whatever", sizeof(text)/2);
904 u_uastrncpy(repl, "some other", sizeof(repl)/2);
905 uregex_setText(re, text, -1, &status);
906
907 /* match covers whole target string */
908 uregex_find(re, 0, &status);
909 TEST_ASSERT_SUCCESS(status);
910 bufPtr = buf;
911 bufCap = sizeof(buf) / 2;
912 uregex_appendReplacement(re, repl, -1, &bufPtr, &bufCap, &status);
913 TEST_ASSERT_SUCCESS(status);
914 TEST_ASSERT_STRING("some other", buf, TRUE);
915
916 /* Match has \u \U escapes */
917 uregex_find(re, 0, &status);
918 TEST_ASSERT_SUCCESS(status);
919 bufPtr = buf;
920 bufCap = sizeof(buf) / 2;
921 u_uastrncpy(repl, "abc\\u0041\\U00000042 \\\\ $ \\abc", sizeof(repl)/2);
922 uregex_appendReplacement(re, repl, -1, &bufPtr, &bufCap, &status);
923 TEST_ASSERT_SUCCESS(status);
924 TEST_ASSERT_STRING("abcAB \\ $ abc", buf, TRUE);
925
926 uregex_close(re);
927 }
928
929
930 /*
931 * appendTail(). Checked in ReplaceFirst(), replaceAll().
932 */
933
934 /*
935 * split()
936 */
937 {
938 UChar textToSplit[80];
939 UChar text2[80];
940 UChar buf[200];
941 UChar *fields[10];
942 int32_t numFields;
943 int32_t requiredCapacity;
944 int32_t spaceNeeded;
945 int32_t sz;
946
947 u_uastrncpy(textToSplit, "first : second: third", sizeof(textToSplit)/2);
948 u_uastrncpy(text2, "No match here.", sizeof(text2)/2);
949
950 status = U_ZERO_ERROR;
951 re = uregex_openC(":", 0, NULL, &status);
952
953
954 /* Simple split */
955
956 uregex_setText(re, textToSplit, -1, &status);
957 TEST_ASSERT_SUCCESS(status);
958
959 /* The TEST_ASSERT_SUCCESS call above should change too... */
960 if (U_SUCCESS(status)) {
961 memset(fields, -1, sizeof(fields));
962 numFields =
963 uregex_split(re, buf, sizeof(buf)/2, &requiredCapacity, fields, 10, &status);
964 TEST_ASSERT_SUCCESS(status);
965
966 /* The TEST_ASSERT_SUCCESS call above should change too... */
967 if(U_SUCCESS(status)) {
968 TEST_ASSERT(numFields == 3);
969 TEST_ASSERT_STRING("first ", fields[0], TRUE);
970 TEST_ASSERT_STRING(" second", fields[1], TRUE);
971 TEST_ASSERT_STRING(" third", fields[2], TRUE);
972 TEST_ASSERT(fields[3] == NULL);
973
974 spaceNeeded = u_strlen(textToSplit) -
975 (numFields - 1) + /* Field delimiters do not appear in output */
976 numFields; /* Each field gets a NUL terminator */
977
978 TEST_ASSERT(spaceNeeded == requiredCapacity);
979 }
980 }
981
982 uregex_close(re);
983
984
985 /* Split with too few output strings available */
986 status = U_ZERO_ERROR;
987 re = uregex_openC(":", 0, NULL, &status);
988 uregex_setText(re, textToSplit, -1, &status);
989 TEST_ASSERT_SUCCESS(status);
990
991 /* The TEST_ASSERT_SUCCESS call above should change too... */
992 if(U_SUCCESS(status)) {
993 memset(fields, -1, sizeof(fields));
994 numFields =
995 uregex_split(re, buf, sizeof(buf)/2, &requiredCapacity, fields, 2, &status);
996 TEST_ASSERT_SUCCESS(status);
997
998 /* The TEST_ASSERT_SUCCESS call above should change too... */
999 if(U_SUCCESS(status)) {
1000 TEST_ASSERT(numFields == 2);
1001 TEST_ASSERT_STRING("first ", fields[0], TRUE);
1002 TEST_ASSERT_STRING(" second: third", fields[1], TRUE);
1003 TEST_ASSERT(!memcmp(&fields[2],&minus1,sizeof(UChar*)));
1004
1005 spaceNeeded = u_strlen(textToSplit) -
1006 (numFields - 1) + /* Field delimiters do not appear in output */
1007 numFields; /* Each field gets a NUL terminator */
1008
1009 TEST_ASSERT(spaceNeeded == requiredCapacity);
1010
1011 /* Split with a range of output buffer sizes. */
1012 spaceNeeded = u_strlen(textToSplit) -
1013 (numFields - 1) + /* Field delimiters do not appear in output */
1014 numFields; /* Each field gets a NUL terminator */
1015
1016 for (sz=0; sz < spaceNeeded+1; sz++) {
1017 memset(fields, -1, sizeof(fields));
1018 status = U_ZERO_ERROR;
1019 numFields =
1020 uregex_split(re, buf, sz, &requiredCapacity, fields, 10, &status);
1021 if (sz >= spaceNeeded) {
1022 TEST_ASSERT_SUCCESS(status);
1023 TEST_ASSERT_STRING("first ", fields[0], TRUE);
1024 TEST_ASSERT_STRING(" second", fields[1], TRUE);
1025 TEST_ASSERT_STRING(" third", fields[2], TRUE);
1026 } else {
1027 TEST_ASSERT(status == U_BUFFER_OVERFLOW_ERROR);
1028 }
1029 TEST_ASSERT(numFields == 3);
1030 TEST_ASSERT(fields[3] == NULL);
1031 TEST_ASSERT(spaceNeeded == requiredCapacity);
1032 }
1033 }
1034 }
1035
1036 uregex_close(re);
1037 }
1038
1039
1040
1041
1042 /* Split(), part 2. Patterns with capture groups. The capture group text
1043 * comes out as additional fields. */
1044 {
1045 UChar textToSplit[80];
1046 UChar buf[200];
1047 UChar *fields[10];
1048 int32_t numFields;
1049 int32_t requiredCapacity;
1050 int32_t spaceNeeded;
1051 int32_t sz;
1052
1053 u_uastrncpy(textToSplit, "first <tag-a> second<tag-b> third", sizeof(textToSplit)/2);
1054
1055 status = U_ZERO_ERROR;
1056 re = uregex_openC("<(.*?)>", 0, NULL, &status);
1057
1058 uregex_setText(re, textToSplit, -1, &status);
1059 TEST_ASSERT_SUCCESS(status);
1060
1061 /* The TEST_ASSERT_SUCCESS call above should change too... */
1062 if(U_SUCCESS(status)) {
1063 memset(fields, -1, sizeof(fields));
1064 numFields =
1065 uregex_split(re, buf, sizeof(buf)/2, &requiredCapacity, fields, 10, &status);
1066 TEST_ASSERT_SUCCESS(status);
1067
1068 /* The TEST_ASSERT_SUCCESS call above should change too... */
1069 if(U_SUCCESS(status)) {
1070 TEST_ASSERT(numFields == 5);
1071 TEST_ASSERT_STRING("first ", fields[0], TRUE);
1072 TEST_ASSERT_STRING("tag-a", fields[1], TRUE);
1073 TEST_ASSERT_STRING(" second", fields[2], TRUE);
1074 TEST_ASSERT_STRING("tag-b", fields[3], TRUE);
1075 TEST_ASSERT_STRING(" third", fields[4], TRUE);
1076 TEST_ASSERT(fields[5] == NULL);
1077 spaceNeeded = strlen("first .tag-a. second.tag-b. third."); /* "." at NUL positions */
1078 TEST_ASSERT(spaceNeeded == requiredCapacity);
1079 }
1080 }
1081
1082 /* Split with too few output strings available (2) */
1083 status = U_ZERO_ERROR;
1084 memset(fields, -1, sizeof(fields));
1085 numFields =
1086 uregex_split(re, buf, sizeof(buf)/2, &requiredCapacity, fields, 2, &status);
1087 TEST_ASSERT_SUCCESS(status);
1088
1089 /* The TEST_ASSERT_SUCCESS call above should change too... */
1090 if(U_SUCCESS(status)) {
1091 TEST_ASSERT(numFields == 2);
1092 TEST_ASSERT_STRING("first ", fields[0], TRUE);
1093 TEST_ASSERT_STRING(" second<tag-b> third", fields[1], TRUE);
1094 TEST_ASSERT(!memcmp(&fields[2],&minus1,sizeof(UChar*)));
1095
1096 spaceNeeded = strlen("first . second<tag-b> third."); /* "." at NUL positions */
1097 TEST_ASSERT(spaceNeeded == requiredCapacity);
1098 }
1099
1100 /* Split with too few output strings available (3) */
1101 status = U_ZERO_ERROR;
1102 memset(fields, -1, sizeof(fields));
1103 numFields =
1104 uregex_split(re, buf, sizeof(buf)/2, &requiredCapacity, fields, 3, &status);
1105 TEST_ASSERT_SUCCESS(status);
1106
1107 /* The TEST_ASSERT_SUCCESS call above should change too... */
1108 if(U_SUCCESS(status)) {
1109 TEST_ASSERT(numFields == 3);
1110 TEST_ASSERT_STRING("first ", fields[0], TRUE);
1111 TEST_ASSERT_STRING("tag-a", fields[1], TRUE);
1112 TEST_ASSERT_STRING(" second<tag-b> third", fields[2], TRUE);
1113 TEST_ASSERT(!memcmp(&fields[3],&minus1,sizeof(UChar*)));
1114
1115 spaceNeeded = strlen("first .tag-a. second<tag-b> third."); /* "." at NUL positions */
1116 TEST_ASSERT(spaceNeeded == requiredCapacity);
1117 }
1118
1119 /* Split with just enough output strings available (5) */
1120 status = U_ZERO_ERROR;
1121 memset(fields, -1, sizeof(fields));
1122 numFields =
1123 uregex_split(re, buf, sizeof(buf)/2, &requiredCapacity, fields, 5, &status);
1124 TEST_ASSERT_SUCCESS(status);
1125
1126 /* The TEST_ASSERT_SUCCESS call above should change too... */
1127 if(U_SUCCESS(status)) {
1128 TEST_ASSERT(numFields == 5);
1129 TEST_ASSERT_STRING("first ", fields[0], TRUE);
1130 TEST_ASSERT_STRING("tag-a", fields[1], TRUE);
1131 TEST_ASSERT_STRING(" second", fields[2], TRUE);
1132 TEST_ASSERT_STRING("tag-b", fields[3], TRUE);
1133 TEST_ASSERT_STRING(" third", fields[4], TRUE);
1134 TEST_ASSERT(!memcmp(&fields[5],&minus1,sizeof(UChar*)));
1135
1136 spaceNeeded = strlen("first .tag-a. second.tag-b. third."); /* "." at NUL positions */
1137 TEST_ASSERT(spaceNeeded == requiredCapacity);
1138 }
1139
1140 /* Split, end of text is a field delimiter. */
1141 status = U_ZERO_ERROR;
1142 sz = strlen("first <tag-a> second<tag-b>");
1143 uregex_setText(re, textToSplit, sz, &status);
1144 TEST_ASSERT_SUCCESS(status);
1145
1146 /* The TEST_ASSERT_SUCCESS call above should change too... */
1147 if(U_SUCCESS(status)) {
1148 memset(fields, -1, sizeof(fields));
1149 numFields =
1150 uregex_split(re, buf, sizeof(buf)/2, &requiredCapacity, fields, 9, &status);
1151 TEST_ASSERT_SUCCESS(status);
1152
1153 /* The TEST_ASSERT_SUCCESS call above should change too... */
1154 if(U_SUCCESS(status)) {
1155 TEST_ASSERT(numFields == 4);
1156 TEST_ASSERT_STRING("first ", fields[0], TRUE);
1157 TEST_ASSERT_STRING("tag-a", fields[1], TRUE);
1158 TEST_ASSERT_STRING(" second", fields[2], TRUE);
1159 TEST_ASSERT_STRING("tag-b", fields[3], TRUE);
1160 TEST_ASSERT(fields[4] == NULL);
1161 TEST_ASSERT(fields[8] == NULL);
1162 TEST_ASSERT(!memcmp(&fields[9],&minus1,sizeof(UChar*)));
1163 spaceNeeded = strlen("first .tag-a. second.tag-b."); /* "." at NUL positions */
1164 TEST_ASSERT(spaceNeeded == requiredCapacity);
1165 }
1166 }
1167
1168 uregex_close(re);
1169 }
1170
1171 /*
1172 * set/getTimeLimit
1173 */
1174 TEST_SETUP("abc$", "abcdef", 0);
1175 TEST_ASSERT(uregex_getTimeLimit(re, &status) == 0);
1176 uregex_setTimeLimit(re, 1000, &status);
1177 TEST_ASSERT(uregex_getTimeLimit(re, &status) == 1000);
1178 TEST_ASSERT_SUCCESS(status);
1179 uregex_setTimeLimit(re, -1, &status);
1180 TEST_ASSERT(status == U_ILLEGAL_ARGUMENT_ERROR);
1181 status = U_ZERO_ERROR;
1182 TEST_ASSERT(uregex_getTimeLimit(re, &status) == 1000);
1183 TEST_TEARDOWN;
1184
1185 /*
1186 * set/get Stack Limit
1187 */
1188 TEST_SETUP("abc$", "abcdef", 0);
1189 TEST_ASSERT(uregex_getStackLimit(re, &status) == 8000000);
1190 uregex_setStackLimit(re, 40000, &status);
1191 TEST_ASSERT(uregex_getStackLimit(re, &status) == 40000);
1192 TEST_ASSERT_SUCCESS(status);
1193 uregex_setStackLimit(re, -1, &status);
1194 TEST_ASSERT(status == U_ILLEGAL_ARGUMENT_ERROR);
1195 status = U_ZERO_ERROR;
1196 TEST_ASSERT(uregex_getStackLimit(re, &status) == 40000);
1197 TEST_TEARDOWN;
1198
1199
1200 /*
1201 * Get/Set callback functions
1202 * This test is copied from intltest regex/Callbacks
1203 * The pattern and test data will run long enough to cause the callback
1204 * to be invoked. The nested '+' operators give exponential time
1205 * behavior with increasing string length.
1206 */
1207 TEST_SETUP("((.)+\\2)+x", "aaaaaaaaaaaaaaaaaaab", 0)
1208 callBackContext cbInfo = {4, 0, 0};
1209 const void *pContext = &cbInfo;
1210 URegexMatchCallback *returnedFn = &TestCallbackFn;
1211
1212 /* Getting the callback fn when it hasn't been set must return NULL */
1213 uregex_getMatchCallback(re, &returnedFn, &pContext, &status);
1214 TEST_ASSERT_SUCCESS(status);
1215 TEST_ASSERT(returnedFn == NULL);
1216 TEST_ASSERT(pContext == NULL);
1217
1218 /* Set thecallback and do a match. */
1219 /* The callback function should record that it has been called. */
1220 uregex_setMatchCallback(re, &TestCallbackFn, &cbInfo, &status);
1221 TEST_ASSERT_SUCCESS(status);
1222 TEST_ASSERT(cbInfo.numCalls == 0);
1223 TEST_ASSERT(uregex_matches(re, -1, &status) == FALSE);
1224 TEST_ASSERT_SUCCESS(status);
1225 TEST_ASSERT(cbInfo.numCalls > 0);
1226
1227 /* Getting the callback should return the values that were set above. */
1228 uregex_getMatchCallback(re, &returnedFn, &pContext, &status);
1229 TEST_ASSERT(returnedFn == &TestCallbackFn);
1230 TEST_ASSERT(pContext == &cbInfo);
1231
1232 TEST_TEARDOWN;
1233 }
1234
1235
1236
1237 static void TestBug4315(void) {
1238 UErrorCode theICUError = U_ZERO_ERROR;
1239 URegularExpression *theRegEx;
1240 UChar *textBuff;
1241 const char *thePattern;
1242 UChar theString[100];
1243 UChar *destFields[24];
1244 int32_t neededLength1;
1245 int32_t neededLength2;
1246
1247 int32_t wordCount = 0;
1248 int32_t destFieldsSize = 24;
1249
1250 thePattern = "ck ";
1251 u_uastrcpy(theString, "The quick brown fox jumped over the slow black turtle.");
1252
1253 /* open a regex */
1254 theRegEx = uregex_openC(thePattern, 0, NULL, &theICUError);
1255 TEST_ASSERT_SUCCESS(theICUError);
1256
1257 /* set the input string */
1258 uregex_setText(theRegEx, theString, u_strlen(theString), &theICUError);
1259 TEST_ASSERT_SUCCESS(theICUError);
1260
1261 /* split */
1262 /*explicitly pass NULL and 0 to force the overflow error -> this is where the
1263 * error occurs! */
1264 wordCount = uregex_split(theRegEx, NULL, 0, &neededLength1, destFields,
1265 destFieldsSize, &theICUError);
1266
1267 TEST_ASSERT(theICUError == U_BUFFER_OVERFLOW_ERROR);
1268 TEST_ASSERT(wordCount==3);
1269
1270 if(theICUError == U_BUFFER_OVERFLOW_ERROR)
1271 {
1272 theICUError = U_ZERO_ERROR;
1273 textBuff = (UChar *) malloc(sizeof(UChar) * (neededLength1 + 1));
1274 wordCount = uregex_split(theRegEx, textBuff, neededLength1+1, &neededLength2,
1275 destFields, destFieldsSize, &theICUError);
1276 TEST_ASSERT(wordCount==3);
1277 TEST_ASSERT_SUCCESS(theICUError);
1278 TEST_ASSERT(neededLength1 == neededLength2);
1279 TEST_ASSERT_STRING("The qui", destFields[0], TRUE);
1280 TEST_ASSERT_STRING("brown fox jumped over the slow bla", destFields[1], TRUE);
1281 TEST_ASSERT_STRING("turtle.", destFields[2], TRUE);
1282 TEST_ASSERT(destFields[3] == NULL);
1283 free(textBuff);
1284 }
1285 uregex_close(theRegEx);
1286 }
1287
1288 #endif /* !UCONFIG_NO_REGULAR_EXPRESSIONS */