diff options
Diffstat (limited to 'Build/source/libs/icu/icu-xetex/test/cintltst/reapits.c')
-rw-r--r-- | Build/source/libs/icu/icu-xetex/test/cintltst/reapits.c | 1038 |
1 files changed, 1038 insertions, 0 deletions
diff --git a/Build/source/libs/icu/icu-xetex/test/cintltst/reapits.c b/Build/source/libs/icu/icu-xetex/test/cintltst/reapits.c new file mode 100644 index 00000000000..74fe674f7dc --- /dev/null +++ b/Build/source/libs/icu/icu-xetex/test/cintltst/reapits.c @@ -0,0 +1,1038 @@ +/******************************************************************** + * COPYRIGHT: + * Copyright (c) 2004-2006, International Business Machines Corporation and + * others. All Rights Reserved. + ********************************************************************/ +/******************************************************************************** +* +* File reapits.c +* +*********************************************************************************/ +/*C API TEST FOR Regular Expressions */ +/** +* This is an API test for ICU regular expressions in C. It doesn't test very many cases, and doesn't +* try to test the full functionality. It just calls each function and verifies that it +* works on a basic level. +* +* More complete testing of regular expression functionality is done with the C++ tests. +**/ + +#include "unicode/utypes.h" + +#if !UCONFIG_NO_REGULAR_EXPRESSIONS + +#include <stdlib.h> +#include <string.h> +#include "unicode/uloc.h" +#include "unicode/uregex.h" +#include "unicode/ustring.h" +#include "cintltst.h" + +#define TEST_ASSERT_SUCCESS(status) {if (U_FAILURE(status)) { \ +log_err("Failure at file %s, line %d, error = %s\n", __FILE__, __LINE__, u_errorName(status));}} + +#define TEST_ASSERT(expr) {if ((expr)==FALSE) { \ +log_err("Test Failure at file %s, line %d\n", __FILE__, __LINE__);}} + +static void test_assert_string(const char *expected, const UChar *actual, UBool nulTerm, const char *file, int line) { + char buf_inside_macro[120]; + int32_t len = (int32_t)strlen(expected); + UBool success; + if (nulTerm) { + u_austrncpy(buf_inside_macro, (actual), len+1); + buf_inside_macro[len+2] = 0; + success = (strcmp((expected), buf_inside_macro) == 0); + } else { + u_austrncpy(buf_inside_macro, (actual), len); + buf_inside_macro[len+1] = 0; + success = (strncmp((expected), buf_inside_macro, len) == 0); + } + if (success == FALSE) { + log_err("Failure at file %s, line %d, expected \"%s\", got \"%s\"\n", + file, line, (expected), buf_inside_macro); + } +} + +#define TEST_ASSERT_STRING(expected, actual, nulTerm) test_assert_string(expected, actual, nulTerm, __FILE__, __LINE__) + + + + + +static void TestRegexCAPI(void); +static void TestBug4315(void); + +void addURegexTest(TestNode** root); + +void addURegexTest(TestNode** root) +{ + addTest(root, &TestRegexCAPI, "regex/TestRegexCAPI"); + addTest(root, &TestBug4315, "regex/TestBug4315"); +} + + +static void TestRegexCAPI(void) { + UErrorCode status = U_ZERO_ERROR; + URegularExpression *re; + UChar pat[200]; + UChar *minus1; + + memset(&minus1, -1, sizeof(minus1)); + + /* Mimimalist open/close */ + u_uastrncpy(pat, "abc*", sizeof(pat)/2); + re = uregex_open(pat, -1, 0, 0, &status); + TEST_ASSERT_SUCCESS(status); + uregex_close(re); + + /* Open with all flag values set */ + status = U_ZERO_ERROR; + re = uregex_open(pat, -1, + UREGEX_CASE_INSENSITIVE | UREGEX_COMMENTS | UREGEX_DOTALL | UREGEX_MULTILINE | UREGEX_UWORD, + 0, &status); + TEST_ASSERT_SUCCESS(status); + uregex_close(re); + + /* Open with an invalid flag */ + status = U_ZERO_ERROR; + re = uregex_open(pat, -1, 0x40000000, 0, &status); + TEST_ASSERT(status == U_REGEX_INVALID_FLAG); + uregex_close(re); + + /* openC with an invalid parameter */ + status = U_ZERO_ERROR; + re = uregex_openC(NULL, + UREGEX_CASE_INSENSITIVE | UREGEX_COMMENTS | UREGEX_DOTALL | UREGEX_MULTILINE | UREGEX_UWORD, 0, &status); + TEST_ASSERT(status == U_ILLEGAL_ARGUMENT_ERROR && re == NULL); + + /* openC with an invalid parameter */ + status = U_USELESS_COLLATOR_ERROR; + re = uregex_openC(NULL, + UREGEX_CASE_INSENSITIVE | UREGEX_COMMENTS | UREGEX_DOTALL | UREGEX_MULTILINE | UREGEX_UWORD, 0, &status); + TEST_ASSERT(status == U_USELESS_COLLATOR_ERROR && re == NULL); + + /* openC open from a C string */ + { + const UChar *p; + int32_t len; + status = U_ZERO_ERROR; + re = uregex_openC("abc*", 0, 0, &status); + TEST_ASSERT_SUCCESS(status); + p = uregex_pattern(re, &len, &status); + TEST_ASSERT_SUCCESS(status); + + /* The TEST_ASSERT_SUCCESS above should change too... */ + if(U_SUCCESS(status)) { + u_uastrncpy(pat, "abc*", sizeof(pat)/2); + TEST_ASSERT(u_strcmp(pat, p) == 0); + TEST_ASSERT(len==(int32_t)strlen("abc*")); + } + + uregex_close(re); + + /* TODO: Open with ParseError parameter */ + } + + /* + * clone + */ + { + URegularExpression *clone1; + URegularExpression *clone2; + URegularExpression *clone3; + UChar testString1[30]; + UChar testString2[30]; + UBool result; + + + status = U_ZERO_ERROR; + re = uregex_openC("abc*", 0, 0, &status); + TEST_ASSERT_SUCCESS(status); + clone1 = uregex_clone(re, &status); + TEST_ASSERT_SUCCESS(status); + TEST_ASSERT(clone1 != NULL); + + status = U_ZERO_ERROR; + clone2 = uregex_clone(re, &status); + TEST_ASSERT_SUCCESS(status); + TEST_ASSERT(clone2 != NULL); + uregex_close(re); + + status = U_ZERO_ERROR; + clone3 = uregex_clone(clone2, &status); + TEST_ASSERT_SUCCESS(status); + TEST_ASSERT(clone3 != NULL); + + u_uastrncpy(testString1, "abcccd", sizeof(pat)/2); + u_uastrncpy(testString2, "xxxabcccd", sizeof(pat)/2); + + status = U_ZERO_ERROR; + uregex_setText(clone1, testString1, -1, &status); + TEST_ASSERT_SUCCESS(status); + result = uregex_lookingAt(clone1, 0, &status); + TEST_ASSERT_SUCCESS(status); + TEST_ASSERT(result==TRUE); + + status = U_ZERO_ERROR; + uregex_setText(clone2, testString2, -1, &status); + TEST_ASSERT_SUCCESS(status); + result = uregex_lookingAt(clone2, 0, &status); + TEST_ASSERT_SUCCESS(status); + TEST_ASSERT(result==FALSE); + result = uregex_find(clone2, 0, &status); + TEST_ASSERT_SUCCESS(status); + TEST_ASSERT(result==TRUE); + + uregex_close(clone1); + uregex_close(clone2); + uregex_close(clone3); + + } + + /* + * pattern() + */ + { + const UChar *resultPat; + int32_t resultLen; + u_uastrncpy(pat, "hello", sizeof(pat)/2); + status = U_ZERO_ERROR; + re = uregex_open(pat, -1, 0, NULL, &status); + resultPat = uregex_pattern(re, &resultLen, &status); + TEST_ASSERT_SUCCESS(status); + + /* The TEST_ASSERT_SUCCESS above should change too... */ + if (U_SUCCESS(status)) { + TEST_ASSERT(resultLen == -1); + TEST_ASSERT(u_strcmp(resultPat, pat) == 0); + } + + uregex_close(re); + + status = U_ZERO_ERROR; + re = uregex_open(pat, 3, 0, NULL, &status); + resultPat = uregex_pattern(re, &resultLen, &status); + TEST_ASSERT_SUCCESS(status); + TEST_ASSERT_SUCCESS(status); + + /* The TEST_ASSERT_SUCCESS above should change too... */ + if (U_SUCCESS(status)) { + TEST_ASSERT(resultLen == 3); + TEST_ASSERT(u_strncmp(resultPat, pat, 3) == 0); + TEST_ASSERT(u_strlen(resultPat) == 3); + } + + uregex_close(re); + } + + /* + * flags() + */ + { + int32_t t; + + status = U_ZERO_ERROR; + re = uregex_open(pat, -1, 0, NULL, &status); + t = uregex_flags(re, &status); + TEST_ASSERT_SUCCESS(status); + TEST_ASSERT(t == 0); + uregex_close(re); + + status = U_ZERO_ERROR; + re = uregex_open(pat, -1, 0, NULL, &status); + t = uregex_flags(re, &status); + TEST_ASSERT_SUCCESS(status); + TEST_ASSERT(t == 0); + uregex_close(re); + + status = U_ZERO_ERROR; + re = uregex_open(pat, -1, UREGEX_CASE_INSENSITIVE | UREGEX_DOTALL, NULL, &status); + t = uregex_flags(re, &status); + TEST_ASSERT_SUCCESS(status); + TEST_ASSERT(t == (UREGEX_CASE_INSENSITIVE | UREGEX_DOTALL)); + uregex_close(re); + } + + /* + * setText() and lookingAt() + */ + { + UChar text1[50]; + UChar text2[50]; + UBool result; + + u_uastrncpy(text1, "abcccd", sizeof(text1)/2); + u_uastrncpy(text2, "abcccxd", sizeof(text2)/2); + status = U_ZERO_ERROR; + u_uastrncpy(pat, "abc*d", sizeof(pat)/2); + re = uregex_open(pat, -1, 0, NULL, &status); + TEST_ASSERT_SUCCESS(status); + + /* Operation before doing a setText should fail... */ + status = U_ZERO_ERROR; + uregex_lookingAt(re, 0, &status); + TEST_ASSERT( status== U_REGEX_INVALID_STATE); + + status = U_ZERO_ERROR; + uregex_setText(re, text1, -1, &status); + result = uregex_lookingAt(re, 0, &status); + TEST_ASSERT(result == TRUE); + TEST_ASSERT_SUCCESS(status); + + status = U_ZERO_ERROR; + uregex_setText(re, text2, -1, &status); + result = uregex_lookingAt(re, 0, &status); + TEST_ASSERT(result == FALSE); + TEST_ASSERT_SUCCESS(status); + + status = U_ZERO_ERROR; + uregex_setText(re, text1, -1, &status); + result = uregex_lookingAt(re, 0, &status); + TEST_ASSERT(result == TRUE); + TEST_ASSERT_SUCCESS(status); + + status = U_ZERO_ERROR; + uregex_setText(re, text1, 5, &status); + result = uregex_lookingAt(re, 0, &status); + TEST_ASSERT(result == FALSE); + TEST_ASSERT_SUCCESS(status); + + status = U_ZERO_ERROR; + uregex_setText(re, text1, 6, &status); + result = uregex_lookingAt(re, 0, &status); + TEST_ASSERT(result == TRUE); + TEST_ASSERT_SUCCESS(status); + + uregex_close(re); + } + + + /* + * getText() + */ + { + UChar text1[50]; + UChar text2[50]; + const UChar *result; + int32_t textLength; + + u_uastrncpy(text1, "abcccd", sizeof(text1)/2); + u_uastrncpy(text2, "abcccxd", sizeof(text2)/2); + status = U_ZERO_ERROR; + u_uastrncpy(pat, "abc*d", sizeof(pat)/2); + re = uregex_open(pat, -1, 0, NULL, &status); + + uregex_setText(re, text1, -1, &status); + result = uregex_getText(re, &textLength, &status); + TEST_ASSERT(result == text1); + TEST_ASSERT(textLength == -1); + TEST_ASSERT_SUCCESS(status); + + status = U_ZERO_ERROR; + uregex_setText(re, text2, 7, &status); + result = uregex_getText(re, &textLength, &status); + TEST_ASSERT(result == text2); + TEST_ASSERT(textLength == 7); + TEST_ASSERT_SUCCESS(status); + + status = U_ZERO_ERROR; + uregex_setText(re, text2, 4, &status); + result = uregex_getText(re, &textLength, &status); + TEST_ASSERT(result == text2); + TEST_ASSERT(textLength == 4); + TEST_ASSERT_SUCCESS(status); + uregex_close(re); + } + + /* + * matches() + */ + { + UChar text1[50]; + UBool result; + int len; + UChar nullString[] = {0,0,0}; + + u_uastrncpy(text1, "abcccde", sizeof(text1)/2); + status = U_ZERO_ERROR; + u_uastrncpy(pat, "abc*d", sizeof(pat)/2); + re = uregex_open(pat, -1, 0, NULL, &status); + + uregex_setText(re, text1, -1, &status); + result = uregex_matches(re, 0, &status); + TEST_ASSERT(result == FALSE); + TEST_ASSERT_SUCCESS(status); + + status = U_ZERO_ERROR; + uregex_setText(re, text1, 6, &status); + result = uregex_matches(re, 0, &status); + TEST_ASSERT(result == TRUE); + TEST_ASSERT_SUCCESS(status); + + status = U_ZERO_ERROR; + uregex_setText(re, text1, 6, &status); + result = uregex_matches(re, 1, &status); + TEST_ASSERT(result == FALSE); + TEST_ASSERT_SUCCESS(status); + uregex_close(re); + + status = U_ZERO_ERROR; + re = uregex_openC(".?", 0, NULL, &status); + uregex_setText(re, text1, -1, &status); + len = u_strlen(text1); + result = uregex_matches(re, len, &status); + TEST_ASSERT(result == TRUE); + TEST_ASSERT_SUCCESS(status); + + status = U_ZERO_ERROR; + uregex_setText(re, nullString, -1, &status); + TEST_ASSERT_SUCCESS(status); + result = uregex_matches(re, 0, &status); + TEST_ASSERT(result == TRUE); + TEST_ASSERT_SUCCESS(status); + uregex_close(re); + } + + + /* + * lookingAt() Used in setText test. + */ + + + /* + * find(), findNext, start, end, reset + */ + { + UChar text1[50]; + UBool result; + u_uastrncpy(text1, "012rx5rx890rxrx...", sizeof(text1)/2); + status = U_ZERO_ERROR; + re = uregex_openC("rx", 0, NULL, &status); + + uregex_setText(re, text1, -1, &status); + result = uregex_find(re, 0, &status); + TEST_ASSERT(result == TRUE); + TEST_ASSERT(uregex_start(re, 0, &status) == 3); + TEST_ASSERT(uregex_end(re, 0, &status) == 5); + TEST_ASSERT_SUCCESS(status); + + result = uregex_find(re, 9, &status); + TEST_ASSERT(result == TRUE); + TEST_ASSERT(uregex_start(re, 0, &status) == 11); + TEST_ASSERT(uregex_end(re, 0, &status) == 13); + TEST_ASSERT_SUCCESS(status); + + result = uregex_find(re, 14, &status); + TEST_ASSERT(result == FALSE); + TEST_ASSERT_SUCCESS(status); + + status = U_ZERO_ERROR; + uregex_reset(re, 0, &status); + + result = uregex_findNext(re, &status); + TEST_ASSERT(result == TRUE); + TEST_ASSERT(uregex_start(re, 0, &status) == 3); + TEST_ASSERT(uregex_end(re, 0, &status) == 5); + TEST_ASSERT_SUCCESS(status); + + result = uregex_findNext(re, &status); + TEST_ASSERT(result == TRUE); + TEST_ASSERT(uregex_start(re, 0, &status) == 6); + TEST_ASSERT(uregex_end(re, 0, &status) == 8); + TEST_ASSERT_SUCCESS(status); + + status = U_ZERO_ERROR; + uregex_reset(re, 12, &status); + + result = uregex_findNext(re, &status); + TEST_ASSERT(result == TRUE); + TEST_ASSERT(uregex_start(re, 0, &status) == 13); + TEST_ASSERT(uregex_end(re, 0, &status) == 15); + TEST_ASSERT_SUCCESS(status); + + result = uregex_findNext(re, &status); + TEST_ASSERT(result == FALSE); + TEST_ASSERT_SUCCESS(status); + + uregex_close(re); + } + + /* + * groupCount + */ + { + int32_t result; + + status = U_ZERO_ERROR; + re = uregex_openC("abc", 0, NULL, &status); + result = uregex_groupCount(re, &status); + TEST_ASSERT_SUCCESS(status); + TEST_ASSERT(result == 0); + uregex_close(re); + + status = U_ZERO_ERROR; + re = uregex_openC("abc(def)(ghi(j))", 0, NULL, &status); + result = uregex_groupCount(re, &status); + TEST_ASSERT_SUCCESS(status); + TEST_ASSERT(result == 3); + uregex_close(re); + + } + + + /* + * group() + */ + { + UChar text1[80]; + UChar buf[80]; + UBool result; + int32_t resultSz; + u_uastrncpy(text1, "noise abc interior def, and this is off the end", sizeof(text1)/2); + + status = U_ZERO_ERROR; + re = uregex_openC("abc(.*?)def", 0, NULL, &status); + TEST_ASSERT_SUCCESS(status); + + + uregex_setText(re, text1, -1, &status); + result = uregex_find(re, 0, &status); + TEST_ASSERT(result==TRUE); + + /* Capture Group 0, the full match. Should succeed. */ + status = U_ZERO_ERROR; + resultSz = uregex_group(re, 0, buf, sizeof(buf)/2, &status); + TEST_ASSERT_SUCCESS(status); + TEST_ASSERT_STRING("abc interior def", buf, TRUE); + TEST_ASSERT(resultSz == (int32_t)strlen("abc interior def")); + + /* Capture group #1. Should succeed. */ + status = U_ZERO_ERROR; + resultSz = uregex_group(re, 1, buf, sizeof(buf)/2, &status); + TEST_ASSERT_SUCCESS(status); + TEST_ASSERT_STRING(" interior ", buf, TRUE); + TEST_ASSERT(resultSz == (int32_t)strlen(" interior ")); + + /* Capture group out of range. Error. */ + status = U_ZERO_ERROR; + uregex_group(re, 2, buf, sizeof(buf)/2, &status); + TEST_ASSERT(status == U_INDEX_OUTOFBOUNDS_ERROR); + + /* NULL buffer, pure pre-flight */ + status = U_ZERO_ERROR; + resultSz = uregex_group(re, 0, NULL, 0, &status); + TEST_ASSERT(status == U_BUFFER_OVERFLOW_ERROR); + TEST_ASSERT(resultSz == (int32_t)strlen("abc interior def")); + + /* Too small buffer, truncated string */ + status = U_ZERO_ERROR; + memset(buf, -1, sizeof(buf)); + resultSz = uregex_group(re, 0, buf, 5, &status); + TEST_ASSERT(status == U_BUFFER_OVERFLOW_ERROR); + TEST_ASSERT_STRING("abc i", buf, FALSE); + TEST_ASSERT(buf[5] == (UChar)0xffff); + TEST_ASSERT(resultSz == (int32_t)strlen("abc interior def")); + + /* Output string just fits buffer, no NUL term. */ + status = U_ZERO_ERROR; + resultSz = uregex_group(re, 0, buf, (int32_t)strlen("abc interior def"), &status); + TEST_ASSERT(status == U_STRING_NOT_TERMINATED_WARNING); + TEST_ASSERT_STRING("abc interior def", buf, FALSE); + TEST_ASSERT(resultSz == (int32_t)strlen("abc interior def")); + TEST_ASSERT(buf[strlen("abc interior def")] == (UChar)0xffff); + + uregex_close(re); + + } + + /* + * replaceFirst() + */ + { + UChar text1[80]; + UChar text2[80]; + UChar replText[80]; + UChar buf[80]; + int32_t resultSz; + u_uastrncpy(text1, "Replace xaax x1x x...x.", sizeof(text1)/2); + u_uastrncpy(text2, "No match here.", sizeof(text2)/2); + u_uastrncpy(replText, "<$1>", sizeof(replText)/2); + + status = U_ZERO_ERROR; + re = uregex_openC("x(.*?)x", 0, NULL, &status); + TEST_ASSERT_SUCCESS(status); + + /* Normal case, with match */ + uregex_setText(re, text1, -1, &status); + resultSz = uregex_replaceFirst(re, replText, -1, buf, sizeof(buf)/2, &status); + TEST_ASSERT_SUCCESS(status); + TEST_ASSERT_STRING("Replace <aa> x1x x...x.", buf, TRUE); + TEST_ASSERT(resultSz == (int32_t)strlen("Replace xaax x1x x...x.")); + + /* No match. Text should copy to output with no changes. */ + status = U_ZERO_ERROR; + uregex_setText(re, text2, -1, &status); + resultSz = uregex_replaceFirst(re, replText, -1, buf, sizeof(buf)/2, &status); + TEST_ASSERT_SUCCESS(status); + TEST_ASSERT_STRING("No match here.", buf, TRUE); + TEST_ASSERT(resultSz == (int32_t)strlen("No match here.")); + + /* Match, output just fills buffer, no termination warning. */ + status = U_ZERO_ERROR; + uregex_setText(re, text1, -1, &status); + memset(buf, -1, sizeof(buf)); + resultSz = uregex_replaceFirst(re, replText, -1, buf, strlen("Replace <aa> x1x x...x."), &status); + TEST_ASSERT(status == U_STRING_NOT_TERMINATED_WARNING); + TEST_ASSERT_STRING("Replace <aa> x1x x...x.", buf, FALSE); + TEST_ASSERT(resultSz == (int32_t)strlen("Replace xaax x1x x...x.")); + TEST_ASSERT(buf[resultSz] == (UChar)0xffff); + + /* Do the replaceFirst again, without first resetting anything. + * Should give the same results. + */ + status = U_ZERO_ERROR; + memset(buf, -1, sizeof(buf)); + resultSz = uregex_replaceFirst(re, replText, -1, buf, strlen("Replace <aa> x1x x...x."), &status); + TEST_ASSERT(status == U_STRING_NOT_TERMINATED_WARNING); + TEST_ASSERT_STRING("Replace <aa> x1x x...x.", buf, FALSE); + TEST_ASSERT(resultSz == (int32_t)strlen("Replace xaax x1x x...x.")); + TEST_ASSERT(buf[resultSz] == (UChar)0xffff); + + /* NULL buffer, zero buffer length */ + status = U_ZERO_ERROR; + resultSz = uregex_replaceFirst(re, replText, -1, NULL, 0, &status); + TEST_ASSERT(status == U_BUFFER_OVERFLOW_ERROR); + TEST_ASSERT(resultSz == (int32_t)strlen("Replace xaax x1x x...x.")); + + /* Buffer too small by one */ + status = U_ZERO_ERROR; + memset(buf, -1, sizeof(buf)); + resultSz = uregex_replaceFirst(re, replText, -1, buf, strlen("Replace <aa> x1x x...x.")-1, &status); + TEST_ASSERT(status == U_BUFFER_OVERFLOW_ERROR); + TEST_ASSERT_STRING("Replace <aa> x1x x...x", buf, FALSE); + TEST_ASSERT(resultSz == (int32_t)strlen("Replace xaax x1x x...x.")); + TEST_ASSERT(buf[resultSz] == (UChar)0xffff); + + uregex_close(re); + } + + + /* + * replaceAll() + */ + { + UChar text1[80]; + UChar text2[80]; + UChar replText[80]; + UChar buf[80]; + int32_t resultSz; + int32_t expectedResultSize; + int32_t i; + + u_uastrncpy(text1, "Replace xaax x1x x...x.", sizeof(text1)/2); + u_uastrncpy(text2, "No match here.", sizeof(text2)/2); + u_uastrncpy(replText, "<$1>", sizeof(replText)/2); + expectedResultSize = u_strlen(text1); + + status = U_ZERO_ERROR; + re = uregex_openC("x(.*?)x", 0, NULL, &status); + TEST_ASSERT_SUCCESS(status); + + /* Normal case, with match */ + uregex_setText(re, text1, -1, &status); + resultSz = uregex_replaceAll(re, replText, -1, buf, sizeof(buf)/2, &status); + TEST_ASSERT_SUCCESS(status); + TEST_ASSERT_STRING("Replace <aa> <1> <...>.", buf, TRUE); + TEST_ASSERT(resultSz == (int32_t)strlen("Replace xaax x1x x...x.")); + + /* No match. Text should copy to output with no changes. */ + status = U_ZERO_ERROR; + uregex_setText(re, text2, -1, &status); + resultSz = uregex_replaceAll(re, replText, -1, buf, sizeof(buf)/2, &status); + TEST_ASSERT_SUCCESS(status); + TEST_ASSERT_STRING("No match here.", buf, TRUE); + TEST_ASSERT(resultSz == (int32_t)strlen("No match here.")); + + /* Match, output just fills buffer, no termination warning. */ + status = U_ZERO_ERROR; + uregex_setText(re, text1, -1, &status); + memset(buf, -1, sizeof(buf)); + resultSz = uregex_replaceAll(re, replText, -1, buf, strlen("Replace xaax x1x x...x."), &status); + TEST_ASSERT(status == U_STRING_NOT_TERMINATED_WARNING); + TEST_ASSERT_STRING("Replace <aa> <1> <...>.", buf, FALSE); + TEST_ASSERT(resultSz == (int32_t)strlen("Replace <aa> <1> <...>.")); + TEST_ASSERT(buf[resultSz] == (UChar)0xffff); + + /* Do the replaceFirst again, without first resetting anything. + * Should give the same results. + */ + status = U_ZERO_ERROR; + memset(buf, -1, sizeof(buf)); + resultSz = uregex_replaceAll(re, replText, -1, buf, strlen("Replace xaax x1x x...x."), &status); + TEST_ASSERT(status == U_STRING_NOT_TERMINATED_WARNING); + TEST_ASSERT_STRING("Replace <aa> <1> <...>.", buf, FALSE); + TEST_ASSERT(resultSz == (int32_t)strlen("Replace <aa> <1> <...>.")); + TEST_ASSERT(buf[resultSz] == (UChar)0xffff); + + /* NULL buffer, zero buffer length */ + status = U_ZERO_ERROR; + resultSz = uregex_replaceAll(re, replText, -1, NULL, 0, &status); + TEST_ASSERT(status == U_BUFFER_OVERFLOW_ERROR); + TEST_ASSERT(resultSz == (int32_t)strlen("Replace <aa> <1> <...>.")); + + /* Buffer too small. Try every size, which will tickle edge cases + * in uregex_appendReplacement (used by replaceAll) */ + for (i=0; i<expectedResultSize; i++) { + char expected[80]; + status = U_ZERO_ERROR; + memset(buf, -1, sizeof(buf)); + resultSz = uregex_replaceAll(re, replText, -1, buf, i, &status); + TEST_ASSERT(status == U_BUFFER_OVERFLOW_ERROR); + strcpy(expected, "Replace <aa> <1> <...>."); + expected[i] = 0; + TEST_ASSERT_STRING(expected, buf, FALSE); + TEST_ASSERT(resultSz == expectedResultSize); + TEST_ASSERT(buf[i] == (UChar)0xffff); + } + + uregex_close(re); + } + + + /* + * appendReplacement() + */ + { + UChar text[100]; + UChar repl[100]; + UChar buf[100]; + UChar *bufPtr; + int32_t bufCap; + + + status = U_ZERO_ERROR; + re = uregex_openC(".*", 0, 0, &status); + TEST_ASSERT_SUCCESS(status); + + u_uastrncpy(text, "whatever", sizeof(text)/2); + u_uastrncpy(repl, "some other", sizeof(repl)/2); + uregex_setText(re, text, -1, &status); + + /* match covers whole target string */ + uregex_find(re, 0, &status); + TEST_ASSERT_SUCCESS(status); + bufPtr = buf; + bufCap = sizeof(buf) / 2; + uregex_appendReplacement(re, repl, -1, &bufPtr, &bufCap, &status); + TEST_ASSERT_SUCCESS(status); + TEST_ASSERT_STRING("some other", buf, TRUE); + + /* Match has \u \U escapes */ + uregex_find(re, 0, &status); + TEST_ASSERT_SUCCESS(status); + bufPtr = buf; + bufCap = sizeof(buf) / 2; + u_uastrncpy(repl, "abc\\u0041\\U00000042 \\\\ $ \\abc", sizeof(repl)/2); + uregex_appendReplacement(re, repl, -1, &bufPtr, &bufCap, &status); + TEST_ASSERT_SUCCESS(status); + TEST_ASSERT_STRING("abcAB \\ $ abc", buf, TRUE); + + uregex_close(re); + } + + + /* + * appendTail(). Checked in ReplaceFirst(), replaceAll(). + */ + + /* + * split() + */ + { + UChar textToSplit[80]; + UChar text2[80]; + UChar buf[200]; + UChar *fields[10]; + int32_t numFields; + int32_t requiredCapacity; + int32_t spaceNeeded; + int32_t sz; + + u_uastrncpy(textToSplit, "first : second: third", sizeof(textToSplit)/2); + u_uastrncpy(text2, "No match here.", sizeof(text2)/2); + + status = U_ZERO_ERROR; + re = uregex_openC(":", 0, NULL, &status); + + + /* Simple split */ + + uregex_setText(re, textToSplit, -1, &status); + TEST_ASSERT_SUCCESS(status); + + /* The TEST_ASSERT_SUCCESS call above should change too... */ + if (U_SUCCESS(status)) { + memset(fields, -1, sizeof(fields)); + numFields = + uregex_split(re, buf, sizeof(buf)/2, &requiredCapacity, fields, 10, &status); + TEST_ASSERT_SUCCESS(status); + + /* The TEST_ASSERT_SUCCESS call above should change too... */ + if(U_SUCCESS(status)) { + TEST_ASSERT(numFields == 3); + TEST_ASSERT_STRING("first ", fields[0], TRUE); + TEST_ASSERT_STRING(" second", fields[1], TRUE); + TEST_ASSERT_STRING(" third", fields[2], TRUE); + TEST_ASSERT(fields[3] == NULL); + + spaceNeeded = u_strlen(textToSplit) - + (numFields - 1) + /* Field delimiters do not appear in output */ + numFields; /* Each field gets a NUL terminator */ + + TEST_ASSERT(spaceNeeded == requiredCapacity); + } + } + + uregex_close(re); + + + /* Split with too few output strings available */ + status = U_ZERO_ERROR; + re = uregex_openC(":", 0, NULL, &status); + uregex_setText(re, textToSplit, -1, &status); + TEST_ASSERT_SUCCESS(status); + + /* The TEST_ASSERT_SUCCESS call above should change too... */ + if(U_SUCCESS(status)) { + memset(fields, -1, sizeof(fields)); + numFields = + uregex_split(re, buf, sizeof(buf)/2, &requiredCapacity, fields, 2, &status); + TEST_ASSERT_SUCCESS(status); + + /* The TEST_ASSERT_SUCCESS call above should change too... */ + if(U_SUCCESS(status)) { + TEST_ASSERT(numFields == 2); + TEST_ASSERT_STRING("first ", fields[0], TRUE); + TEST_ASSERT_STRING(" second: third", fields[1], TRUE); + TEST_ASSERT(!memcmp(&fields[2],&minus1,sizeof(UChar*))); + + spaceNeeded = u_strlen(textToSplit) - + (numFields - 1) + /* Field delimiters do not appear in output */ + numFields; /* Each field gets a NUL terminator */ + + TEST_ASSERT(spaceNeeded == requiredCapacity); + + /* Split with a range of output buffer sizes. */ + spaceNeeded = u_strlen(textToSplit) - + (numFields - 1) + /* Field delimiters do not appear in output */ + numFields; /* Each field gets a NUL terminator */ + + for (sz=0; sz < spaceNeeded+1; sz++) { + memset(fields, -1, sizeof(fields)); + status = U_ZERO_ERROR; + numFields = + uregex_split(re, buf, sz, &requiredCapacity, fields, 10, &status); + if (sz >= spaceNeeded) { + TEST_ASSERT_SUCCESS(status); + TEST_ASSERT_STRING("first ", fields[0], TRUE); + TEST_ASSERT_STRING(" second", fields[1], TRUE); + TEST_ASSERT_STRING(" third", fields[2], TRUE); + } else { + TEST_ASSERT(status == U_BUFFER_OVERFLOW_ERROR); + } + TEST_ASSERT(numFields == 3); + TEST_ASSERT(fields[3] == NULL); + TEST_ASSERT(spaceNeeded == requiredCapacity); + } + } + } + + uregex_close(re); + } + + + + + /* Split(), part 2. Patterns with capture groups. The capture group text + * comes out as additional fields. */ + { + UChar textToSplit[80]; + UChar buf[200]; + UChar *fields[10]; + int32_t numFields; + int32_t requiredCapacity; + int32_t spaceNeeded; + int32_t sz; + + u_uastrncpy(textToSplit, "first <tag-a> second<tag-b> third", sizeof(textToSplit)/2); + + status = U_ZERO_ERROR; + re = uregex_openC("<(.*?)>", 0, NULL, &status); + + uregex_setText(re, textToSplit, -1, &status); + TEST_ASSERT_SUCCESS(status); + + /* The TEST_ASSERT_SUCCESS call above should change too... */ + if(U_SUCCESS(status)) { + memset(fields, -1, sizeof(fields)); + numFields = + uregex_split(re, buf, sizeof(buf)/2, &requiredCapacity, fields, 10, &status); + TEST_ASSERT_SUCCESS(status); + + /* The TEST_ASSERT_SUCCESS call above should change too... */ + if(U_SUCCESS(status)) { + TEST_ASSERT(numFields == 5); + TEST_ASSERT_STRING("first ", fields[0], TRUE); + TEST_ASSERT_STRING("tag-a", fields[1], TRUE); + TEST_ASSERT_STRING(" second", fields[2], TRUE); + TEST_ASSERT_STRING("tag-b", fields[3], TRUE); + TEST_ASSERT_STRING(" third", fields[4], TRUE); + TEST_ASSERT(fields[5] == NULL); + spaceNeeded = strlen("first .tag-a. second.tag-b. third."); /* "." at NUL positions */ + TEST_ASSERT(spaceNeeded == requiredCapacity); + } + } + + /* Split with too few output strings available (2) */ + status = U_ZERO_ERROR; + memset(fields, -1, sizeof(fields)); + numFields = + uregex_split(re, buf, sizeof(buf)/2, &requiredCapacity, fields, 2, &status); + TEST_ASSERT_SUCCESS(status); + + /* The TEST_ASSERT_SUCCESS call above should change too... */ + if(U_SUCCESS(status)) { + TEST_ASSERT(numFields == 2); + TEST_ASSERT_STRING("first ", fields[0], TRUE); + TEST_ASSERT_STRING(" second<tag-b> third", fields[1], TRUE); + TEST_ASSERT(!memcmp(&fields[2],&minus1,sizeof(UChar*))); + + spaceNeeded = strlen("first . second<tag-b> third."); /* "." at NUL positions */ + TEST_ASSERT(spaceNeeded == requiredCapacity); + } + + /* Split with too few output strings available (3) */ + status = U_ZERO_ERROR; + memset(fields, -1, sizeof(fields)); + numFields = + uregex_split(re, buf, sizeof(buf)/2, &requiredCapacity, fields, 3, &status); + TEST_ASSERT_SUCCESS(status); + + /* The TEST_ASSERT_SUCCESS call above should change too... */ + if(U_SUCCESS(status)) { + TEST_ASSERT(numFields == 3); + TEST_ASSERT_STRING("first ", fields[0], TRUE); + TEST_ASSERT_STRING("tag-a", fields[1], TRUE); + TEST_ASSERT_STRING(" second<tag-b> third", fields[2], TRUE); + TEST_ASSERT(!memcmp(&fields[3],&minus1,sizeof(UChar*))); + + spaceNeeded = strlen("first .tag-a. second<tag-b> third."); /* "." at NUL positions */ + TEST_ASSERT(spaceNeeded == requiredCapacity); + } + + /* Split with just enough output strings available (5) */ + status = U_ZERO_ERROR; + memset(fields, -1, sizeof(fields)); + numFields = + uregex_split(re, buf, sizeof(buf)/2, &requiredCapacity, fields, 5, &status); + TEST_ASSERT_SUCCESS(status); + + /* The TEST_ASSERT_SUCCESS call above should change too... */ + if(U_SUCCESS(status)) { + TEST_ASSERT(numFields == 5); + TEST_ASSERT_STRING("first ", fields[0], TRUE); + TEST_ASSERT_STRING("tag-a", fields[1], TRUE); + TEST_ASSERT_STRING(" second", fields[2], TRUE); + TEST_ASSERT_STRING("tag-b", fields[3], TRUE); + TEST_ASSERT_STRING(" third", fields[4], TRUE); + TEST_ASSERT(!memcmp(&fields[5],&minus1,sizeof(UChar*))); + + spaceNeeded = strlen("first .tag-a. second.tag-b. third."); /* "." at NUL positions */ + TEST_ASSERT(spaceNeeded == requiredCapacity); + } + + /* Split, end of text is a field delimiter. */ + status = U_ZERO_ERROR; + sz = strlen("first <tag-a> second<tag-b>"); + uregex_setText(re, textToSplit, sz, &status); + TEST_ASSERT_SUCCESS(status); + + /* The TEST_ASSERT_SUCCESS call above should change too... */ + if(U_SUCCESS(status)) { + memset(fields, -1, sizeof(fields)); + numFields = + uregex_split(re, buf, sizeof(buf)/2, &requiredCapacity, fields, 9, &status); + TEST_ASSERT_SUCCESS(status); + + /* The TEST_ASSERT_SUCCESS call above should change too... */ + if(U_SUCCESS(status)) { + TEST_ASSERT(numFields == 4); + TEST_ASSERT_STRING("first ", fields[0], TRUE); + TEST_ASSERT_STRING("tag-a", fields[1], TRUE); + TEST_ASSERT_STRING(" second", fields[2], TRUE); + TEST_ASSERT_STRING("tag-b", fields[3], TRUE); + TEST_ASSERT(fields[4] == NULL); + TEST_ASSERT(fields[8] == NULL); + TEST_ASSERT(!memcmp(&fields[9],&minus1,sizeof(UChar*))); + spaceNeeded = strlen("first .tag-a. second.tag-b."); /* "." at NUL positions */ + TEST_ASSERT(spaceNeeded == requiredCapacity); + } + } + + uregex_close(re); + } + +} + +static void TestBug4315(void) { + UErrorCode theICUError = U_ZERO_ERROR; + URegularExpression *theRegEx; + UChar *textBuff; + const char *thePattern; + UChar theString[100]; + UChar *destFields[24]; + int32_t neededLength1; + int32_t neededLength2; + + int32_t wordCount = 0; + int32_t destFieldsSize = 24; + + thePattern = "ck "; + u_uastrcpy(theString, "The quick brown fox jumped over the slow black turtle."); + + /* open a regex */ + theRegEx = uregex_openC(thePattern, 0, NULL, &theICUError); + TEST_ASSERT_SUCCESS(theICUError); + + /* set the input string */ + uregex_setText(theRegEx, theString, u_strlen(theString), &theICUError); + TEST_ASSERT_SUCCESS(theICUError); + + /* split */ + /*explicitly pass NULL and 0 to force the overflow error -> this is where the + * error occurs! */ + wordCount = uregex_split(theRegEx, NULL, 0, &neededLength1, destFields, + destFieldsSize, &theICUError); + + TEST_ASSERT(theICUError == U_BUFFER_OVERFLOW_ERROR); + TEST_ASSERT(wordCount==3); + + if(theICUError == U_BUFFER_OVERFLOW_ERROR) + { + theICUError = U_ZERO_ERROR; + textBuff = (UChar *) malloc(sizeof(UChar) * (neededLength1 + 1)); + wordCount = uregex_split(theRegEx, textBuff, neededLength1+1, &neededLength2, + destFields, destFieldsSize, &theICUError); + TEST_ASSERT(wordCount==3); + TEST_ASSERT_SUCCESS(theICUError); + TEST_ASSERT(neededLength1 == neededLength2); + TEST_ASSERT_STRING("The qui", destFields[0], TRUE); + TEST_ASSERT_STRING("brown fox jumped over the slow bla", destFields[1], TRUE); + TEST_ASSERT_STRING("turtle.", destFields[2], TRUE); + TEST_ASSERT(destFields[3] == NULL); + free(textBuff); + } + uregex_close(theRegEx); +} + +#endif /* !UCONFIG_NO_REGULAR_EXPRESSIONS */ |