2 ********************************************************************************
3 * Copyright (C) 1999-2013 International Business Machines Corporation and
4 * others. All Rights Reserved.
5 ********************************************************************************
6 * Date Name Description
7 * 10/20/99 alan Creation.
8 * 03/22/2000 Madhu Added additional tests
9 ********************************************************************************
15 #include "unicode/utypes.h"
17 #include "unicode/ucnv.h"
18 #include "unicode/uniset.h"
19 #include "unicode/uchar.h"
20 #include "unicode/usetiter.h"
21 #include "unicode/ustring.h"
22 #include "unicode/parsepos.h"
23 #include "unicode/symtable.h"
24 #include "unicode/uversion.h"
27 #define LENGTHOF(array) (int32_t)(sizeof(array)/sizeof((array)[0]))
29 #define TEST_ASSERT_SUCCESS(status) {if (U_FAILURE(status)) { \
30 dataerrln("fail in file \"%s\", line %d: \"%s\"", __FILE__, __LINE__, \
31 u_errorName(status));}}
33 #define TEST_ASSERT(expr) {if (!(expr)) { \
34 dataerrln("fail in file \"%s\", line %d", __FILE__, __LINE__); }}
36 UnicodeString operator+(const UnicodeString& left, const UnicodeSet& set) {
39 return left + UnicodeSetTest::escape(pat);
42 #define CASE(id,test) case id: \
51 UnicodeSetTest::UnicodeSetTest() : utf8Cnv(NULL) {
54 UConverter *UnicodeSetTest::openUTF8Converter() {
56 UErrorCode errorCode=U_ZERO_ERROR;
57 utf8Cnv=ucnv_open("UTF-8", &errorCode);
62 UnicodeSetTest::~UnicodeSetTest() {
67 UnicodeSetTest::runIndexedTest(int32_t index, UBool exec,
68 const char* &name, char* /*par*/) {
69 // if (exec) logln((UnicodeString)"TestSuite UnicodeSetTest");
72 CASE(1,TestAddRemove);
73 CASE(2,TestCategories);
74 CASE(3,TestCloneEqualHash);
75 CASE(4,TestMinimalRep);
77 CASE(6,TestScriptSet);
78 CASE(7,TestPropertySet);
80 CASE(9,TestExhaustive);
81 CASE(10,TestToPattern);
85 CASE(14,TestCloseOver);
86 CASE(15,TestEscapePattern);
87 CASE(16,TestInvalidCodePoint);
88 CASE(17,TestSymbolTable);
89 CASE(18,TestSurrogate);
90 CASE(19,TestPosixClasses);
91 CASE(20,TestIteration);
92 CASE(21,TestFreezable);
94 CASE(23,TestStringSpan);
95 default: name = ""; break;
99 static const char NOT[] = "%%%%";
102 * UVector was improperly copying contents
103 * This code will crash this is still true
105 void UnicodeSetTest::Testj2268() {
107 t.add(UnicodeString("abc"));
109 UnicodeString ustrPat;
110 test.toPattern(ustrPat, TRUE);
116 void UnicodeSetTest::TestToPattern() {
117 UErrorCode ec = U_ZERO_ERROR;
119 // Test that toPattern() round trips with syntax characters and
122 static const char* OTHER_TOPATTERN_TESTS[] = {
123 "[[:latin:]&[:greek:]]",
124 "[[:latin:]-[:greek:]]",
125 "[:nonspacing mark:]",
129 for (int32_t j=0; OTHER_TOPATTERN_TESTS[j]!=NULL; ++j) {
131 UnicodeSet s(OTHER_TOPATTERN_TESTS[j], ec);
133 dataerrln((UnicodeString)"FAIL: bad pattern " + OTHER_TOPATTERN_TESTS[j] + " - " + UnicodeString(u_errorName(ec)));
136 checkPat(OTHER_TOPATTERN_TESTS[j], s);
139 for (UChar32 i = 0; i <= 0x10FFFF; ++i) {
140 if ((i <= 0xFF && !u_isalpha(i)) || u_isspace(i)) {
142 // check various combinations to make sure they all work.
143 if (i != 0 && !toPatternAux(i, i)){
146 if (!toPatternAux(0, i)){
149 if (!toPatternAux(i, 0xFFFF)){
156 // Test pattern behavior of multicharacter strings.
159 UnicodeSet* s = new UnicodeSet("[a-z {aa} {ab}]", ec);
161 // This loop isn't a loop. It's here to make the compiler happy.
162 // If you're curious, try removing it and changing the 'break'
163 // statements (except for the last) to goto's.
165 if (U_FAILURE(ec)) break;
166 const char* exp1[] = {"aa", "ab", NOT, "ac", NULL};
167 expectToPattern(*s, "[a-z{aa}{ab}]", exp1);
170 const char* exp2[] = {"aa", "ab", "ac", NOT, "xy", NULL};
171 expectToPattern(*s, "[a-z{aa}{ab}{ac}]", exp2);
173 s->applyPattern(UNICODE_STRING_SIMPLE("[a-z {\\{l} {r\\}}]"), ec);
174 if (U_FAILURE(ec)) break;
175 const char* exp3[] = {"{l", "r}", NOT, "xy", NULL};
176 expectToPattern(*s, UNICODE_STRING_SIMPLE("[a-z{r\\}}{\\{l}]"), exp3);
179 const char* exp4[] = {"{l", "r}", "[]", NOT, "xy", NULL};
180 expectToPattern(*s, UNICODE_STRING_SIMPLE("[a-z{\\[\\]}{r\\}}{\\{l}]"), exp4);
182 s->applyPattern(UNICODE_STRING_SIMPLE("[a-z {\\u4E01\\u4E02}{\\n\\r}]"), ec);
183 if (U_FAILURE(ec)) break;
184 const char* exp5[] = {"\\u4E01\\u4E02", "\n\r", NULL};
185 expectToPattern(*s, UNICODE_STRING_SIMPLE("[a-z{\\u000A\\u000D}{\\u4E01\\u4E02}]"), exp5);
189 s->add(UnicodeString("abc", ""));
190 s->add(UnicodeString("abc", ""));
191 const char* exp6[] = {"abc", NOT, "ab", NULL};
192 expectToPattern(*s, "[{abc}]", exp6);
197 if (U_FAILURE(ec)) errln("FAIL: pattern parse error");
201 // JB#3400: For 2 character ranges prefer [ab] to [a-b]
203 s.add((UChar)97, (UChar)98); // 'a', 'b'
204 expectToPattern(s, "[ab]", NULL);
207 UBool UnicodeSetTest::toPatternAux(UChar32 start, UChar32 end) {
209 // use Integer.toString because Utility.hex doesn't handle ints
210 UnicodeString pat = "";
211 // TODO do these in hex
212 //String source = "0x" + Integer.toString(start,16).toUpperCase();
213 //if (start != end) source += "..0x" + Integer.toString(end,16).toUpperCase();
214 UnicodeString source;
215 source = source + (uint32_t)start;
217 source = source + ".." + (uint32_t)end;
219 testSet.add(start, end);
220 return checkPat(source, testSet);
223 UBool UnicodeSetTest::checkPat(const UnicodeString& source,
224 const UnicodeSet& testSet) {
225 // What we want to make sure of is that a pattern generated
226 // by toPattern(), with or without escaped unprintables, can
227 // be passed back into the UnicodeSet constructor.
230 testSet.toPattern(pat0, TRUE);
232 if (!checkPat(source + " (escaped)", testSet, pat0)) return FALSE;
234 //String pat1 = unescapeLeniently(pat0);
235 //if (!checkPat(source + " (in code)", testSet, pat1)) return false;
238 testSet.toPattern(pat2, FALSE);
239 if (!checkPat(source, testSet, pat2)) return FALSE;
241 //String pat3 = unescapeLeniently(pat2);
242 // if (!checkPat(source + " (in code)", testSet, pat3)) return false;
244 //logln(source + " => " + pat0 + ", " + pat1 + ", " + pat2 + ", " + pat3);
245 logln((UnicodeString)source + " => " + pat0 + ", " + pat2);
249 UBool UnicodeSetTest::checkPat(const UnicodeString& source,
250 const UnicodeSet& testSet,
251 const UnicodeString& pat) {
252 UErrorCode ec = U_ZERO_ERROR;
253 UnicodeSet testSet2(pat, ec);
254 if (testSet2 != testSet) {
255 errln((UnicodeString)"Fail toPattern: " + source + " => " + pat);
262 UnicodeSetTest::TestPatterns(void) {
264 expectPattern(set, UnicodeString("[[a-m]&[d-z]&[k-y]]", ""), "km");
265 expectPattern(set, UnicodeString("[[a-z]-[m-y]-[d-r]]", ""), "aczz");
266 expectPattern(set, UnicodeString("[a\\-z]", ""), "--aazz");
267 expectPattern(set, UnicodeString("[-az]", ""), "--aazz");
268 expectPattern(set, UnicodeString("[az-]", ""), "--aazz");
269 expectPattern(set, UnicodeString("[[[a-z]-[aeiou]i]]", ""), "bdfnptvz");
271 // Throw in a test of complement
274 exp.append((UChar)0x0000).append("aeeoouu").append((UChar)(0x007a+1)).append((UChar)0xFFFF);
275 expectPairs(set, exp);
279 UnicodeSetTest::TestCategories(void) {
280 UErrorCode status = U_ZERO_ERROR;
281 const char* pat = " [:Lu:] "; // Whitespace ok outside [:..:]
282 UnicodeSet set(pat, status);
283 if (U_FAILURE(status)) {
284 dataerrln((UnicodeString)"Fail: Can't construct set with " + pat + " - " + UnicodeString(u_errorName(status)));
287 expectContainment(set, pat, "ABC", "abc");
291 int32_t failures = 0;
292 // Make sure generation of L doesn't pollute cached Lu set
293 // First generate L, then Lu
294 set.applyPattern("[:L:]", status);
295 if (U_FAILURE(status)) { errln("FAIL"); return; }
296 for (i=0; i<0x200; ++i) {
297 UBool l = u_isalpha((UChar)i);
298 if (l != set.contains(i)) {
299 errln((UnicodeString)"FAIL: L contains " + (unsigned short)i + " = " +
301 if (++failures == 10) break;
305 set.applyPattern("[:Lu:]", status);
306 if (U_FAILURE(status)) { errln("FAIL"); return; }
307 for (i=0; i<0x200; ++i) {
308 UBool lu = (u_charType((UChar)i) == U_UPPERCASE_LETTER);
309 if (lu != set.contains(i)) {
310 errln((UnicodeString)"FAIL: Lu contains " + (unsigned short)i + " = " +
312 if (++failures == 20) break;
317 UnicodeSetTest::TestCloneEqualHash(void) {
318 UErrorCode status = U_ZERO_ERROR;
319 // set1 and set2 used to be built with the obsolete constructor taking
320 // UCharCategory values; replaced with pattern constructors
322 UnicodeSet *set1=new UnicodeSet(UNICODE_STRING_SIMPLE("\\p{Lowercase Letter}"), status); // :Ll: Letter, lowercase
323 UnicodeSet *set1a=new UnicodeSet(UNICODE_STRING_SIMPLE("[:Ll:]"), status); // Letter, lowercase
324 if (U_FAILURE(status)){
325 dataerrln((UnicodeString)"FAIL: Can't construst set with category->Ll" + " - " + UnicodeString(u_errorName(status)));
328 UnicodeSet *set2=new UnicodeSet(UNICODE_STRING_SIMPLE("\\p{Decimal Number}"), status); //Number, Decimal digit
329 UnicodeSet *set2a=new UnicodeSet(UNICODE_STRING_SIMPLE("[:Nd:]"), status); //Number, Decimal digit
330 if (U_FAILURE(status)){
331 errln((UnicodeString)"FAIL: Can't construct set with category->Nd");
335 if (*set1 != *set1a) {
336 errln("FAIL: category constructor for Ll broken");
338 if (*set2 != *set2a) {
339 errln("FAIL: category constructor for Nd broken");
344 logln("Testing copy construction");
345 UnicodeSet *set1copy=new UnicodeSet(*set1);
346 if(*set1 != *set1copy || *set1 == *set2 ||
347 getPairs(*set1) != getPairs(*set1copy) ||
348 set1->hashCode() != set1copy->hashCode()){
349 errln("FAIL : Error in copy construction");
353 logln("Testing =operator");
354 UnicodeSet set1equal=*set1;
355 UnicodeSet set2equal=*set2;
356 if(set1equal != *set1 || set1equal != *set1copy || set2equal != *set2 ||
357 set2equal == *set1 || set2equal == *set1copy || set2equal == set1equal){
358 errln("FAIL: Error in =operator");
361 logln("Testing clone()");
362 UnicodeSet *set1clone=(UnicodeSet*)set1->clone();
363 UnicodeSet *set2clone=(UnicodeSet*)set2->clone();
364 if(*set1clone != *set1 || *set1clone != *set1copy || *set1clone != set1equal ||
365 *set2clone != *set2 || *set2clone == *set1copy || *set2clone != set2equal ||
366 *set2clone == *set1 || *set2clone == set1equal || *set2clone == *set1clone){
367 errln("FAIL: Error in clone");
370 logln("Testing hashcode");
371 if(set1->hashCode() != set1equal.hashCode() || set1->hashCode() != set1clone->hashCode() ||
372 set2->hashCode() != set2equal.hashCode() || set2->hashCode() != set2clone->hashCode() ||
373 set1copy->hashCode() != set1equal.hashCode() || set1copy->hashCode() != set1clone->hashCode() ||
374 set1->hashCode() == set2->hashCode() || set1copy->hashCode() == set2->hashCode() ||
375 set2->hashCode() == set1clone->hashCode() || set2->hashCode() == set1equal.hashCode() ){
376 errln("FAIL: Error in hashCode()");
388 UnicodeSetTest::TestAddRemove(void) {
389 UnicodeSet set; // Construct empty set
390 doAssert(set.isEmpty() == TRUE, "set should be empty");
391 doAssert(set.size() == 0, "size should be 0");
393 doAssert(set.size() == 0x110000, "size should be 0x110000");
395 set.add(0x0061, 0x007a);
396 expectPairs(set, "az");
397 doAssert(set.isEmpty() == FALSE, "set should not be empty");
398 doAssert(set.size() != 0, "size should not be equal to 0");
399 doAssert(set.size() == 26, "size should be equal to 26");
400 set.remove(0x006d, 0x0070);
401 expectPairs(set, "alqz");
402 doAssert(set.size() == 22, "size should be equal to 22");
403 set.remove(0x0065, 0x0067);
404 expectPairs(set, "adhlqz");
405 doAssert(set.size() == 19, "size should be equal to 19");
406 set.remove(0x0064, 0x0069);
407 expectPairs(set, "acjlqz");
408 doAssert(set.size() == 16, "size should be equal to 16");
409 set.remove(0x0063, 0x0072);
410 expectPairs(set, "absz");
411 doAssert(set.size() == 10, "size should be equal to 10");
412 set.add(0x0066, 0x0071);
413 expectPairs(set, "abfqsz");
414 doAssert(set.size() == 22, "size should be equal to 22");
415 set.remove(0x0061, 0x0067);
416 expectPairs(set, "hqsz");
417 set.remove(0x0061, 0x007a);
418 expectPairs(set, "");
419 doAssert(set.isEmpty() == TRUE, "set should be empty");
420 doAssert(set.size() == 0, "size should be 0");
422 doAssert(set.isEmpty() == FALSE, "set should not be empty");
423 doAssert(set.size() == 1, "size should not be equal to 1");
426 expectPairs(set, "ac");
427 doAssert(set.size() == 3, "size should not be equal to 3");
430 expectPairs(set, "acpq");
431 doAssert(set.size() == 5, "size should not be equal to 5");
433 expectPairs(set, "");
434 doAssert(set.isEmpty() == TRUE, "set should be empty");
435 doAssert(set.size() == 0, "size should be 0");
437 // Try removing an entire set from another set
438 expectPattern(set, "[c-x]", "cx");
440 expectPattern(set2, "[f-ky-za-bc[vw]]", "acfkvwyz");
442 expectPairs(set, "deluxx");
444 // Try adding an entire set to another set
445 expectPattern(set, "[jackiemclean]", "aacceein");
446 expectPattern(set2, "[hitoshinamekatajamesanderson]", "aadehkmort");
448 expectPairs(set, "aacehort");
449 doAssert(set.containsAll(set2) == TRUE, "set should contain all the elements in set2");
451 // Try retaining an set of elements contained in another set (intersection)
453 expectPattern(set3, "[a-c]", "ac");
454 doAssert(set.containsAll(set3) == FALSE, "set doesn't contain all the elements in set3");
456 expectPairs(set3, "aacc");
457 doAssert(set.containsAll(set3) == TRUE, "set should contain all the elements in set3");
459 expectPairs(set, "aacc");
460 doAssert(set.size() == set3.size(), "set.size() should be set3.size()");
461 doAssert(set.containsAll(set3) == TRUE, "set should contain all the elements in set3");
463 doAssert(set.size() != set3.size(), "set.size() != set3.size()");
465 // Test commutativity
466 expectPattern(set, "[hitoshinamekatajamesanderson]", "aadehkmort");
467 expectPattern(set2, "[jackiemclean]", "aacceein");
469 expectPairs(set, "aacehort");
470 doAssert(set.containsAll(set2) == TRUE, "set should contain all the elements in set2");
478 * Make sure minimal representation is maintained.
480 void UnicodeSetTest::TestMinimalRep() {
481 UErrorCode status = U_ZERO_ERROR;
482 // This is pretty thoroughly tested by checkCanonicalRep()
483 // run against the exhaustive operation results. Use the code
484 // here for debugging specific spot problems.
486 // 1 overlap against 2
487 UnicodeSet set("[h-km-q]", status);
488 if (U_FAILURE(status)) { errln("FAIL"); return; }
489 UnicodeSet set2("[i-o]", status);
490 if (U_FAILURE(status)) { errln("FAIL"); return; }
492 expectPairs(set, "hq");
494 set.applyPattern("[a-m]", status);
495 if (U_FAILURE(status)) { errln("FAIL"); return; }
496 set2.applyPattern("[e-o]", status);
497 if (U_FAILURE(status)) { errln("FAIL"); return; }
499 expectPairs(set, "ao");
501 set.applyPattern("[e-o]", status);
502 if (U_FAILURE(status)) { errln("FAIL"); return; }
503 set2.applyPattern("[a-m]", status);
504 if (U_FAILURE(status)) { errln("FAIL"); return; }
506 expectPairs(set, "ao");
507 // 1 overlap against 3
508 set.applyPattern("[a-eg-mo-w]", status);
509 if (U_FAILURE(status)) { errln("FAIL"); return; }
510 set2.applyPattern("[d-q]", status);
511 if (U_FAILURE(status)) { errln("FAIL"); return; }
513 expectPairs(set, "aw");
516 void UnicodeSetTest::TestAPI() {
517 UErrorCode status = U_ZERO_ERROR;
520 if (!set.isEmpty() || set.getRangeCount() != 0) {
521 errln((UnicodeString)"FAIL, set should be empty but isn't: " +
525 // clear(), isEmpty()
528 errln((UnicodeString)"FAIL, set shouldn't be empty but is: " +
532 if (!set.isEmpty()) {
533 errln((UnicodeString)"FAIL, set should be empty but isn't: " +
539 if (set.size() != 0) {
540 errln((UnicodeString)"FAIL, size should be 0, but is " + set.size() +
544 if (set.size() != 1) {
545 errln((UnicodeString)"FAIL, size should be 1, but is " + set.size() +
548 set.add(0x0031, 0x0039);
549 if (set.size() != 10) {
550 errln((UnicodeString)"FAIL, size should be 10, but is " + set.size() +
554 // contains(first, last)
556 set.applyPattern("[A-Y 1-8 b-d l-y]", status);
557 if (U_FAILURE(status)) { errln("FAIL"); return; }
558 for (int32_t i = 0; i<set.getRangeCount(); ++i) {
559 UChar32 a = set.getRangeStart(i);
560 UChar32 b = set.getRangeEnd(i);
561 if (!set.contains(a, b)) {
562 errln((UnicodeString)"FAIL, should contain " + (unsigned short)a + '-' + (unsigned short)b +
563 " but doesn't: " + set);
565 if (set.contains((UChar32)(a-1), b)) {
566 errln((UnicodeString)"FAIL, shouldn't contain " +
567 (unsigned short)(a-1) + '-' + (unsigned short)b +
568 " but does: " + set);
570 if (set.contains(a, (UChar32)(b+1))) {
571 errln((UnicodeString)"FAIL, shouldn't contain " +
572 (unsigned short)a + '-' + (unsigned short)(b+1) +
573 " but does: " + set);
577 // Ported InversionList test.
578 UnicodeSet a((UChar32)3,(UChar32)10);
579 UnicodeSet b((UChar32)7,(UChar32)15);
582 logln((UnicodeString)"a [3-10]: " + a);
583 logln((UnicodeString)"b [7-15]: " + b);
586 UnicodeSet exp((UChar32)3,(UChar32)15);
588 logln((UnicodeString)"c.set(a).add(b): " + c);
590 errln((UnicodeString)"FAIL: c.set(a).add(b) = " + c + ", expect " + exp);
593 exp.set((UChar32)0, (UChar32)2);
594 exp.add((UChar32)16, UnicodeSet::MAX_VALUE);
596 logln((UnicodeString)"c.complement(): " + c);
598 errln((UnicodeString)"FAIL: c.complement() = " + c + ", expect " + exp);
601 exp.set((UChar32)3, (UChar32)15);
603 logln((UnicodeString)"c.complement(): " + c);
605 errln((UnicodeString)"FAIL: c.complement() = " + c + ", expect " + exp);
609 exp.set((UChar32)3,(UChar32)6);
610 exp.add((UChar32)11,(UChar32) 15);
612 logln((UnicodeString)"c.set(a).exclusiveOr(b): " + c);
614 errln((UnicodeString)"FAIL: c.set(a).exclusiveOr(b) = " + c + ", expect " + exp);
618 bitsToSet(setToBits(c), c);
620 logln((UnicodeString)"bitsToSet(setToBits(c)): " + c);
622 errln((UnicodeString)"FAIL: bitsToSet(setToBits(c)) = " + c + ", expect " + exp);
625 // Additional tests for coverage JB#2118
626 //UnicodeSet::complement(class UnicodeString const &)
627 //UnicodeSet::complementAll(class UnicodeString const &)
628 //UnicodeSet::containsNone(class UnicodeSet const &)
629 //UnicodeSet::containsNone(long,long)
630 //UnicodeSet::containsSome(class UnicodeSet const &)
631 //UnicodeSet::containsSome(long,long)
632 //UnicodeSet::removeAll(class UnicodeString const &)
633 //UnicodeSet::retain(long)
634 //UnicodeSet::retainAll(class UnicodeString const &)
635 //UnicodeSet::serialize(unsigned short *,long,enum UErrorCode &)
636 //UnicodeSetIterator::getString(void)
638 set.complement("ab");
639 exp.applyPattern("[{ab}]", status);
640 if (U_FAILURE(status)) { errln("FAIL"); return; }
641 if (set != exp) { errln("FAIL: complement(\"ab\")"); return; }
643 UnicodeSetIterator iset(set);
644 if (!iset.next() || !iset.isString()) {
645 errln("FAIL: UnicodeSetIterator::next/isString");
646 } else if (iset.getString() != "ab") {
647 errln("FAIL: UnicodeSetIterator::getString");
650 set.add((UChar32)0x61, (UChar32)0x7A);
651 set.complementAll("alan");
652 exp.applyPattern("[{ab}b-kmo-z]", status);
653 if (U_FAILURE(status)) { errln("FAIL"); return; }
654 if (set != exp) { errln("FAIL: complementAll(\"alan\")"); return; }
656 exp.applyPattern("[a-z]", status);
657 if (U_FAILURE(status)) { errln("FAIL"); return; }
658 if (set.containsNone(exp)) { errln("FAIL: containsNone(UnicodeSet)"); }
659 if (!set.containsSome(exp)) { errln("FAIL: containsSome(UnicodeSet)"); }
660 exp.applyPattern("[aln]", status);
661 if (U_FAILURE(status)) { errln("FAIL"); return; }
662 if (!set.containsNone(exp)) { errln("FAIL: containsNone(UnicodeSet)"); }
663 if (set.containsSome(exp)) { errln("FAIL: containsSome(UnicodeSet)"); }
665 if (set.containsNone((UChar32)0x61, (UChar32)0x7A)) {
666 errln("FAIL: containsNone(UChar32, UChar32)");
668 if (!set.containsSome((UChar32)0x61, (UChar32)0x7A)) {
669 errln("FAIL: containsSome(UChar32, UChar32)");
671 if (!set.containsNone((UChar32)0x41, (UChar32)0x5A)) {
672 errln("FAIL: containsNone(UChar32, UChar32)");
674 if (set.containsSome((UChar32)0x41, (UChar32)0x5A)) {
675 errln("FAIL: containsSome(UChar32, UChar32)");
678 set.removeAll("liu");
679 exp.applyPattern("[{ab}b-hj-kmo-tv-z]", status);
680 if (U_FAILURE(status)) { errln("FAIL"); return; }
681 if (set != exp) { errln("FAIL: removeAll(\"liu\")"); return; }
683 set.retainAll("star");
684 exp.applyPattern("[rst]", status);
685 if (U_FAILURE(status)) { errln("FAIL"); return; }
686 if (set != exp) { errln("FAIL: retainAll(\"star\")"); return; }
688 set.retain((UChar32)0x73);
689 exp.applyPattern("[s]", status);
690 if (U_FAILURE(status)) { errln("FAIL"); return; }
691 if (set != exp) { errln("FAIL: retain('s')"); return; }
694 int32_t slen = set.serialize(buf, sizeof(buf)/sizeof(buf[0]), status);
695 if (U_FAILURE(status)) { errln("FAIL: serialize"); return; }
696 if (slen != 3 || buf[0] != 2 || buf[1] != 0x73 || buf[2] != 0x74) {
697 errln("FAIL: serialize");
701 // Conversions to and from USet
702 UnicodeSet *uniset = &set;
703 USet *uset = uniset->toUSet();
704 TEST_ASSERT((void *)uset == (void *)uniset);
705 UnicodeSet *setx = UnicodeSet::fromUSet(uset);
706 TEST_ASSERT((void *)setx == (void *)uset);
707 const UnicodeSet *constSet = uniset;
708 const USet *constUSet = constSet->toUSet();
709 TEST_ASSERT((void *)constUSet == (void *)constSet);
710 const UnicodeSet *constSetx = UnicodeSet::fromUSet(constUSet);
711 TEST_ASSERT((void *)constSetx == (void *)constUSet);
713 // span(UnicodeString) and spanBack(UnicodeString) convenience methods
714 UnicodeString longString=UNICODE_STRING_SIMPLE("aaaaaaaaaabbbbbbbbbbcccccccccc");
715 UnicodeSet ac(0x61, 0x63);
716 ac.remove(0x62).freeze();
717 if( ac.span(longString, -5, USET_SPAN_CONTAINED)!=10 ||
718 ac.span(longString, 0, USET_SPAN_CONTAINED)!=10 ||
719 ac.span(longString, 5, USET_SPAN_CONTAINED)!=10 ||
720 ac.span(longString, 10, USET_SPAN_CONTAINED)!=10 ||
721 ac.span(longString, 15, USET_SPAN_CONTAINED)!=15 ||
722 ac.span(longString, 20, USET_SPAN_CONTAINED)!=30 ||
723 ac.span(longString, 25, USET_SPAN_CONTAINED)!=30 ||
724 ac.span(longString, 30, USET_SPAN_CONTAINED)!=30 ||
725 ac.span(longString, 35, USET_SPAN_CONTAINED)!=30 ||
726 ac.span(longString, INT32_MAX, USET_SPAN_CONTAINED)!=30
728 errln("UnicodeSet.span(UnicodeString, ...) returns incorrect end indexes");
730 if( ac.spanBack(longString, -5, USET_SPAN_CONTAINED)!=0 ||
731 ac.spanBack(longString, 0, USET_SPAN_CONTAINED)!=0 ||
732 ac.spanBack(longString, 5, USET_SPAN_CONTAINED)!=0 ||
733 ac.spanBack(longString, 10, USET_SPAN_CONTAINED)!=0 ||
734 ac.spanBack(longString, 15, USET_SPAN_CONTAINED)!=15 ||
735 ac.spanBack(longString, 20, USET_SPAN_CONTAINED)!=20 ||
736 ac.spanBack(longString, 25, USET_SPAN_CONTAINED)!=20 ||
737 ac.spanBack(longString, 30, USET_SPAN_CONTAINED)!=20 ||
738 ac.spanBack(longString, 35, USET_SPAN_CONTAINED)!=20 ||
739 ac.spanBack(longString, INT32_MAX, USET_SPAN_CONTAINED)!=20
741 errln("UnicodeSet.spanBack(UnicodeString, ...) returns incorrect start indexes");
745 void UnicodeSetTest::TestIteration() {
746 UErrorCode ec = U_ZERO_ERROR;
750 // 6 code points, 3 ranges, 2 strings, 8 total elements
751 // Iteration will access them in sorted order - a, b, c, y, z, U0001abcd, "str1", "str2"
752 UnicodeSet set(UNICODE_STRING_SIMPLE("[zabyc\\U0001abcd{str1}{str2}]"), ec);
753 TEST_ASSERT_SUCCESS(ec);
754 UnicodeSetIterator it(set);
756 for (outerLoop=0; outerLoop<3; outerLoop++) {
757 // Run the test multiple times, to check that iterator.reset() is working.
758 for (i=0; i<10; i++) {
759 UBool nextv = it.next();
760 UBool isString = it.isString();
761 int32_t codePoint = it.getCodepoint();
762 //int32_t codePointEnd = it.getCodepointEnd();
763 UnicodeString s = it.getString();
766 TEST_ASSERT(nextv == TRUE);
767 TEST_ASSERT(isString == FALSE);
768 TEST_ASSERT(codePoint==0x61);
769 TEST_ASSERT(s == "a");
772 TEST_ASSERT(nextv == TRUE);
773 TEST_ASSERT(isString == FALSE);
774 TEST_ASSERT(codePoint==0x62);
775 TEST_ASSERT(s == "b");
778 TEST_ASSERT(nextv == TRUE);
779 TEST_ASSERT(isString == FALSE);
780 TEST_ASSERT(codePoint==0x63);
781 TEST_ASSERT(s == "c");
784 TEST_ASSERT(nextv == TRUE);
785 TEST_ASSERT(isString == FALSE);
786 TEST_ASSERT(codePoint==0x79);
787 TEST_ASSERT(s == "y");
790 TEST_ASSERT(nextv == TRUE);
791 TEST_ASSERT(isString == FALSE);
792 TEST_ASSERT(codePoint==0x7a);
793 TEST_ASSERT(s == "z");
796 TEST_ASSERT(nextv == TRUE);
797 TEST_ASSERT(isString == FALSE);
798 TEST_ASSERT(codePoint==0x1abcd);
799 TEST_ASSERT(s == UnicodeString((UChar32)0x1abcd));
802 TEST_ASSERT(nextv == TRUE);
803 TEST_ASSERT(isString == TRUE);
804 TEST_ASSERT(s == "str1");
807 TEST_ASSERT(nextv == TRUE);
808 TEST_ASSERT(isString == TRUE);
809 TEST_ASSERT(s == "str2");
812 TEST_ASSERT(nextv == FALSE);
815 TEST_ASSERT(nextv == FALSE);
819 it.reset(); // prepare to run the iteration again.
826 void UnicodeSetTest::TestStrings() {
827 UErrorCode ec = U_ZERO_ERROR;
829 UnicodeSet* testList[] = {
830 UnicodeSet::createFromAll("abc"),
831 new UnicodeSet("[a-c]", ec),
833 &(UnicodeSet::createFrom("ch")->add('a','z').add("ll")),
834 new UnicodeSet("[{ll}{ch}a-z]", ec),
836 UnicodeSet::createFrom("ab}c"),
837 new UnicodeSet("[{ab\\}c}]", ec),
839 &((new UnicodeSet('a','z'))->add('A', 'Z').retain('M','m').complement('X')),
840 new UnicodeSet("[[a-zA-Z]&[M-m]-[X]]", ec),
846 errln("FAIL: couldn't construct test sets");
849 for (int32_t i = 0; testList[i] != NULL; i+=2) {
851 UnicodeString pat0, pat1;
852 testList[i]->toPattern(pat0, TRUE);
853 testList[i+1]->toPattern(pat1, TRUE);
854 if (*testList[i] == *testList[i+1]) {
855 logln((UnicodeString)"Ok: " + pat0 + " == " + pat1);
857 logln((UnicodeString)"FAIL: " + pat0 + " != " + pat1);
861 delete testList[i+1];
866 * Test the [:Latin:] syntax.
868 void UnicodeSetTest::TestScriptSet() {
869 expectContainment(UNICODE_STRING_SIMPLE("[:Latin:]"), "aA", CharsToUnicodeString("\\u0391\\u03B1"));
871 expectContainment(UNICODE_STRING_SIMPLE("[:Greek:]"), CharsToUnicodeString("\\u0391\\u03B1"), "aA");
874 expectContainment(UNICODE_STRING_SIMPLE("[[:Common:][:Inherited:]]"), CharsToUnicodeString("\\U00003099\\U0001D169\\u0000"), "aA");
879 * Test the [:Latin:] syntax.
881 void UnicodeSetTest::TestPropertySet() {
882 static const char* const DATA[] = {
883 // Pattern, Chars IN, Chars NOT in
893 "\\P{ GENERAL Category = upper case letter }",
897 #if !UCONFIG_NO_NORMALIZATION
898 // Combining class: @since ICU 2.2
899 // Check both symbolic and numeric
904 "\\p{Canonical Combining Class = 11}",
908 "[:c c c = iota subscript :]",
913 // Bidi class: @since ICU 2.2
914 "\\p{bidiclass=lefttoright}",
918 // Binary properties: @since ICU 2.2
925 // weiv: )(and * were removed from math in Unicode 4.0.1
929 // JB#1767 \N{}, \p{ASCII}
934 "[\\N{ latin small letter a }[:name= latin small letter z:]]",
950 "\\u03D8\\u03D9", // 3.2
953 "\\u1800\\u3400\\U0002f800",
954 "\\u0220\\u034f\\u30ff\\u33ff\\ufe73\\U00010000\\U00050000",
956 // JB#2350: Case_Sensitive
957 "[:Case Sensitive:]",
958 "A\\u1FFC\\U00010410",
959 ";\\u00B4\\U00010500",
961 // JB#2832: C99-compatibility props
968 " \\u0003\\u0007\\u0009\\u000A\\u000D",
971 "!@#%&*()[]{}-_\\/;:,.?'\"",
978 // Regex compatibility test
979 "[-b]", // leading '-' is literal
983 "[^-b]", // leading '-' is literal
987 "[b-]", // trailing '-' is literal
991 "[^b-]", // trailing '-' is literal
995 "[a-b-]", // trailing '-' is literal
999 "[[a-q]&[p-z]-]", // trailing '-' is literal
1003 "[\\s|\\)|:|$|\\>]", // from regex tests
1007 "[\\uDC00cd]", // JB#2906: isolated trail at start
1009 "ab\\uD800\\U00010000",
1011 "[ab\\uD800]", // JB#2906: isolated trail at start
1013 "cd\\uDC00\\U00010000",
1015 "[ab\\uD800cd]", // JB#2906: isolated lead in middle
1017 "ef\\uDC00\\U00010000",
1019 "[ab\\uDC00cd]", // JB#2906: isolated trail in middle
1021 "ef\\uD800\\U00010000",
1023 #if !UCONFIG_NO_NORMALIZATION
1024 "[:^lccc=0:]", // Lead canonical class
1026 "abcd\\u00c0\\u00c5",
1028 "[:^tccc=0:]", // Trail canonical class
1029 "\\u0300\\u0301\\u00c0\\u00c5",
1032 "[[:^lccc=0:][:^tccc=0:]]", // Lead and trail canonical class
1033 "\\u0300\\u0301\\u00c0\\u00c5",
1036 "[[:^lccc=0:]-[:^tccc=0:]]", // Stuff that starts with an accent but ends with a base (none right now)
1038 "abcd\\u0300\\u0301\\u00c0\\u00c5",
1040 "[[:ccc=0:]-[:lccc=0:]-[:tccc=0:]]", // Weirdos. Complete canonical class is zero, but both lead and trail are not
1041 "\\u0F73\\u0F75\\u0F81",
1042 "abcd\\u0300\\u0301\\u00c0\\u00c5",
1043 #endif /* !UCONFIG_NO_NORMALIZATION */
1046 "A\\uE000\\uF8FF\\uFDC7\\U00010000\\U0010FFFD",
1047 "\\u0888\\uFDD3\\uFFFE\\U00050005",
1049 // Script_Extensions, new in Unicode 6.0
1051 "\\u061E\\u061F\\u0620\\u0621\\u063F\\u0640\\u0650\\u065E\\uFDF1\\uFDF2\\uFDF3",
1052 "\\u061D\\uFDEF\\uFDFE",
1054 // U+FDF2 has Script=Arabic and also Arab in its Script_Extensions,
1055 // so scx-sc is missing U+FDF2.
1056 "[[:Script_Extensions=Arabic:]-[:Arab:]]",
1057 "\\u0640\\u064B\\u0650\\u0655\\uFDFD",
1061 static const int32_t DATA_LEN = sizeof(DATA)/sizeof(DATA[0]);
1063 for (int32_t i=0; i<DATA_LEN; i+=3) {
1064 expectContainment(UnicodeString(DATA[i], -1, US_INV), CharsToUnicodeString(DATA[i+1]),
1065 CharsToUnicodeString(DATA[i+2]));
1070 * Test that Posix style character classes [:digit:], etc.
1071 * have the Unicode definitions from TR 18.
1073 void UnicodeSetTest::TestPosixClasses() {
1075 UErrorCode status = U_ZERO_ERROR;
1076 UnicodeSet s1("[:alpha:]", status);
1077 UnicodeSet s2(UNICODE_STRING_SIMPLE("\\p{Alphabetic}"), status);
1078 TEST_ASSERT_SUCCESS(status);
1079 TEST_ASSERT(s1==s2);
1082 UErrorCode status = U_ZERO_ERROR;
1083 UnicodeSet s1("[:lower:]", status);
1084 UnicodeSet s2(UNICODE_STRING_SIMPLE("\\p{lowercase}"), status);
1085 TEST_ASSERT_SUCCESS(status);
1086 TEST_ASSERT(s1==s2);
1089 UErrorCode status = U_ZERO_ERROR;
1090 UnicodeSet s1("[:upper:]", status);
1091 UnicodeSet s2(UNICODE_STRING_SIMPLE("\\p{Uppercase}"), status);
1092 TEST_ASSERT_SUCCESS(status);
1093 TEST_ASSERT(s1==s2);
1096 UErrorCode status = U_ZERO_ERROR;
1097 UnicodeSet s1("[:punct:]", status);
1098 UnicodeSet s2(UNICODE_STRING_SIMPLE("\\p{gc=Punctuation}"), status);
1099 TEST_ASSERT_SUCCESS(status);
1100 TEST_ASSERT(s1==s2);
1103 UErrorCode status = U_ZERO_ERROR;
1104 UnicodeSet s1("[:digit:]", status);
1105 UnicodeSet s2(UNICODE_STRING_SIMPLE("\\p{gc=DecimalNumber}"), status);
1106 TEST_ASSERT_SUCCESS(status);
1107 TEST_ASSERT(s1==s2);
1110 UErrorCode status = U_ZERO_ERROR;
1111 UnicodeSet s1("[:xdigit:]", status);
1112 UnicodeSet s2(UNICODE_STRING_SIMPLE("[\\p{DecimalNumber}\\p{HexDigit}]"), status);
1113 TEST_ASSERT_SUCCESS(status);
1114 TEST_ASSERT(s1==s2);
1117 UErrorCode status = U_ZERO_ERROR;
1118 UnicodeSet s1("[:alnum:]", status);
1119 UnicodeSet s2(UNICODE_STRING_SIMPLE("[\\p{Alphabetic}\\p{DecimalNumber}]"), status);
1120 TEST_ASSERT_SUCCESS(status);
1121 TEST_ASSERT(s1==s2);
1124 UErrorCode status = U_ZERO_ERROR;
1125 UnicodeSet s1("[:space:]", status);
1126 UnicodeSet s2(UNICODE_STRING_SIMPLE("\\p{Whitespace}"), status);
1127 TEST_ASSERT_SUCCESS(status);
1128 TEST_ASSERT(s1==s2);
1131 UErrorCode status = U_ZERO_ERROR;
1132 UnicodeSet s1("[:blank:]", status);
1133 TEST_ASSERT_SUCCESS(status);
1134 UnicodeSet s2(UNICODE_STRING_SIMPLE("[\\p{Whitespace}-[\\u000a\\u000B\\u000c\\u000d\\u0085\\p{LineSeparator}\\p{ParagraphSeparator}]]"),
1136 TEST_ASSERT_SUCCESS(status);
1137 TEST_ASSERT(s1==s2);
1140 UErrorCode status = U_ZERO_ERROR;
1141 UnicodeSet s1("[:cntrl:]", status);
1142 TEST_ASSERT_SUCCESS(status);
1143 UnicodeSet s2(UNICODE_STRING_SIMPLE("\\p{Control}"), status);
1144 TEST_ASSERT_SUCCESS(status);
1145 TEST_ASSERT(s1==s2);
1148 UErrorCode status = U_ZERO_ERROR;
1149 UnicodeSet s1("[:graph:]", status);
1150 TEST_ASSERT_SUCCESS(status);
1151 UnicodeSet s2(UNICODE_STRING_SIMPLE("[^\\p{Whitespace}\\p{Control}\\p{Surrogate}\\p{Unassigned}]"), status);
1152 TEST_ASSERT_SUCCESS(status);
1153 TEST_ASSERT(s1==s2);
1156 UErrorCode status = U_ZERO_ERROR;
1157 UnicodeSet s1("[:print:]", status);
1158 TEST_ASSERT_SUCCESS(status);
1159 UnicodeSet s2(UNICODE_STRING_SIMPLE("[[:graph:][:blank:]-[\\p{Control}]]") ,status);
1160 TEST_ASSERT_SUCCESS(status);
1161 TEST_ASSERT(s1==s2);
1165 * Test cloning of UnicodeSet. For C++, we test the copy constructor.
1167 void UnicodeSetTest::TestClone() {
1168 UErrorCode ec = U_ZERO_ERROR;
1169 UnicodeSet s("[abcxyz]", ec);
1171 expectContainment(t, "abc", "def");
1175 * Test the indexOf() and charAt() methods.
1177 void UnicodeSetTest::TestIndexOf() {
1178 UErrorCode ec = U_ZERO_ERROR;
1179 UnicodeSet set("[a-cx-y3578]", ec);
1180 if (U_FAILURE(ec)) {
1181 errln("FAIL: UnicodeSet constructor");
1184 for (int32_t i=0; i<set.size(); ++i) {
1185 UChar32 c = set.charAt(i);
1186 if (set.indexOf(c) != i) {
1187 errln("FAIL: charAt(%d) = %X => indexOf() => %d",
1188 i, c, set.indexOf(c));
1191 UChar32 c = set.charAt(set.size());
1193 errln("FAIL: charAt(<out of range>) = %X", c);
1195 int32_t j = set.indexOf((UChar32)0x71/*'q'*/);
1197 errln((UnicodeString)"FAIL: indexOf('q') = " + j);
1204 void UnicodeSetTest::TestCloseOver() {
1205 UErrorCode ec = U_ZERO_ERROR;
1207 char CASE[] = {(char)USET_CASE_INSENSITIVE};
1208 char CASE_MAPPINGS[] = {(char)USET_ADD_CASE_MAPPINGS};
1209 const char* DATA[] = {
1210 // selector, input, output
1212 "[aq\\u00DF{Bc}{bC}{Fi}]",
1213 "[aAqQ\\u00DF\\u1E9E\\uFB01{ss}{bc}{fi}]", // U+1E9E LATIN CAPITAL LETTER SHARP S is new in Unicode 5.1
1216 "[\\u01F1]", // 'DZ'
1217 "[\\u01F1\\u01F2\\u01F3]",
1221 "[\\u1FB4{\\u03AC\\u03B9}]",
1227 CASE, // make sure binary search finds limits
1229 "[aA\\uFF3A\\uFF5A]",
1232 "[a-z]","[A-Za-z\\u017F\\u212A]",
1238 CASE, "[i]", "[iI]",
1240 CASE, "[\\u0130]", "[\\u0130{i\\u0307}]", // dotted I
1241 CASE, "[{i\\u0307}]", "[\\u0130{i\\u0307}]", // i with dot
1243 CASE, "[\\u0131]", "[\\u0131]", // dotless i
1245 CASE, "[\\u0390]", "[\\u0390\\u1FD3{\\u03B9\\u0308\\u0301}]",
1247 CASE, "[\\u03c2]", "[\\u03a3\\u03c2\\u03c3]", // sigmas
1249 CASE, "[\\u03f2]", "[\\u03f2\\u03f9]", // lunate sigmas
1251 CASE, "[\\u03f7]", "[\\u03f7\\u03f8]",
1253 CASE, "[\\u1fe3]", "[\\u03b0\\u1fe3{\\u03c5\\u0308\\u0301}]",
1255 CASE, "[\\ufb05]", "[\\ufb05\\ufb06{st}]",
1256 CASE, "[{st}]", "[\\ufb05\\ufb06{st}]",
1258 CASE, "[\\U0001044F]", "[\\U00010427\\U0001044F]",
1260 CASE, "[{a\\u02BE}]", "[\\u1E9A{a\\u02BE}]", // first in sorted table
1262 CASE, "[{\\u1f7c\\u03b9}]", "[\\u1ff2{\\u1f7c\\u03b9}]", // last in sorted table
1264 #if !UCONFIG_NO_FILE_IO
1266 "[aq\\u00DF{Bc}{bC}{Fi}]",
1267 "[aAqQ\\u00DF{ss}{Ss}{SS}{Bc}{BC}{bC}{bc}{FI}{Fi}{fi}]",
1271 "[\\u01F1]", // 'DZ'
1272 "[\\u01F1\\u01F2\\u01F3]",
1284 for (int32_t i=0; DATA[i]!=NULL; i+=3) {
1285 int32_t selector = DATA[i][0];
1286 UnicodeString pat(DATA[i+1], -1, US_INV);
1287 UnicodeString exp(DATA[i+2], -1, US_INV);
1288 s.applyPattern(pat, ec);
1289 s.closeOver(selector);
1290 t.applyPattern(exp, ec);
1291 if (U_FAILURE(ec)) {
1292 errln("FAIL: applyPattern failed");
1296 logln((UnicodeString)"Ok: " + pat + ".closeOver(" + selector + ") => " + exp);
1298 dataerrln((UnicodeString)"FAIL: " + pat + ".closeOver(" + selector + ") => " +
1299 s.toPattern(buf, TRUE) + ", expected " + exp);
1306 * This was used to compare the old implementation (using USET_CASE)
1307 * with the new one (using 0x100 temporarily)
1308 * while transitioning from hardcoded case closure tables in uniset.cpp
1309 * (moved to uniset_props.cpp) to building the data by gencase into ucase.icu.
1310 * and using ucase.c functions for closure.
1311 * See Jitterbug 3432 RFE: Move uniset.cpp data to a data file
1313 * Note: The old and new implementation never fully matched because
1314 * the old implementation turned out to not map U+0130 and U+0131 correctly
1315 * (dotted I and dotless i) and because the old implementation's data tables
1316 * were outdated compared to Unicode 4.0.1 at the time of the change to the
1317 * new implementation. (So sigmas and some other characters were not handled
1318 * according to the newer Unicode version.)
1320 UnicodeSet sens("[:case_sensitive:]", ec), sens2, s2;
1321 UnicodeSetIterator si(sens);
1322 UnicodeString str, buf2;
1323 const UnicodeString *pStr;
1326 if(!si.isString()) {
1327 c=si.getCodepoint();
1336 s.closeOver(USET_CASE);
1339 errln("FAIL: closeOver(U+%04x) differs: ", c);
1340 errln((UnicodeString)"old "+s.toPattern(buf, TRUE)+" new: "+t.toPattern(buf2, TRUE));
1344 // remove all code points
1345 // should contain all full case folding mapping strings
1346 sens2.remove(0, 0x10ffff);
1350 pStr=&si.getString();
1354 s.closeOver(USET_CASE);
1357 errln((UnicodeString)"FAIL: closeOver("+s2.toPattern(buf, TRUE)+") differs: ");
1358 errln((UnicodeString)"old "+s.toPattern(buf, TRUE)+" new: "+t.toPattern(buf2, TRUE));
1364 // Test the pattern API
1365 s.applyPattern("[abc]", USET_CASE_INSENSITIVE, NULL, ec);
1366 if (U_FAILURE(ec)) {
1367 errln("FAIL: applyPattern failed");
1369 expectContainment(s, "abcABC", "defDEF");
1371 UnicodeSet v("[^abc]", USET_CASE_INSENSITIVE, NULL, ec);
1372 if (U_FAILURE(ec)) {
1373 errln("FAIL: constructor failed");
1375 expectContainment(v, "defDEF", "abcABC");
1377 UnicodeSet cm("[abck]", USET_ADD_CASE_MAPPINGS, NULL, ec);
1378 if (U_FAILURE(ec)) {
1379 errln("FAIL: construct w/case mappings failed");
1381 expectContainment(cm, "abckABCK", CharsToUnicodeString("defDEF\\u212A"));
1385 void UnicodeSetTest::TestEscapePattern() {
1386 const char pattern[] =
1387 "[\\uFEFF \\u200A-\\u200E \\U0001D173-\\U0001D17A \\U000F0000-\\U000FFFFD ]";
1389 "[\\u200A-\\u200E\\uFEFF\\U0001D173-\\U0001D17A\\U000F0000-\\U000FFFFD]";
1390 // We test this with two passes; in the second pass we
1391 // pre-unescape the pattern. Since U+200E is Pattern_White_Space,
1392 // this fails -- which is what we expect.
1393 for (int32_t pass=1; pass<=2; ++pass) {
1394 UErrorCode ec = U_ZERO_ERROR;
1395 UnicodeString pat(pattern, -1, US_INV);
1397 pat = pat.unescape();
1399 // Pattern is only good for pass 1
1400 UBool isPatternValid = (pass==1);
1402 UnicodeSet set(pat, ec);
1403 if (U_SUCCESS(ec) != isPatternValid){
1404 errln((UnicodeString)"FAIL: applyPattern(" +
1405 escape(pat) + ") => " +
1409 if (U_FAILURE(ec)) {
1412 if (set.contains((UChar)0x0644)){
1413 errln((UnicodeString)"FAIL: " + escape(pat) + " contains(U+0664)");
1416 UnicodeString newpat;
1417 set.toPattern(newpat, TRUE);
1418 if (newpat == UnicodeString(exp, -1, US_INV)) {
1419 logln(escape(pat) + " => " + newpat);
1421 errln((UnicodeString)"FAIL: " + escape(pat) + " => " + newpat);
1424 for (int32_t i=0; i<set.getRangeCount(); ++i) {
1425 UnicodeString str("Range ");
1426 str.append((UChar)(0x30 + i))
1428 .append((UChar32)set.getRangeStart(i))
1430 .append((UChar32)set.getRangeEnd(i));
1431 str = str + " (" + set.getRangeStart(i) + " - " +
1432 set.getRangeEnd(i) + ")";
1433 if (set.getRangeStart(i) < 0) {
1434 errln((UnicodeString)"FAIL: " + escape(str));
1442 void UnicodeSetTest::expectRange(const UnicodeString& label,
1443 const UnicodeSet& set,
1444 UChar32 start, UChar32 end) {
1445 UnicodeSet exp(start, end);
1448 logln(label + " => " + set.toPattern(pat, TRUE));
1451 errln((UnicodeString)"FAIL: " + label + " => " +
1452 set.toPattern(pat, TRUE) +
1453 ", expected " + exp.toPattern(xpat, TRUE));
1457 void UnicodeSetTest::TestInvalidCodePoint() {
1459 const UChar32 DATA[] = {
1460 // Test range Expected range
1461 0, 0x10FFFF, 0, 0x10FFFF,
1462 (UChar32)-1, 8, 0, 8,
1463 8, 0x110000, 8, 0x10FFFF
1465 const int32_t DATA_LENGTH = sizeof(DATA)/sizeof(DATA[0]);
1470 for (i=0; i<DATA_LENGTH; i+=4) {
1471 UChar32 start = DATA[i];
1472 UChar32 end = DATA[i+1];
1473 UChar32 xstart = DATA[i+2];
1474 UChar32 xend = DATA[i+3];
1476 // Try various API using the test code points
1478 UnicodeSet set(start, end);
1479 expectRange((UnicodeString)"ct(" + start + "," + end + ")",
1483 set.set(start, end);
1484 expectRange((UnicodeString)"set(" + start + "," + end + ")",
1487 UBool b = set.contains(start);
1488 b = set.contains(start, end);
1489 b = set.containsNone(start, end);
1490 b = set.containsSome(start, end);
1491 (void)b; // Suppress set but not used warning.
1493 /*int32_t index = set.indexOf(start);*/
1497 set.add(start, end);
1498 expectRange((UnicodeString)"add(" + start + "," + end + ")",
1501 set.set(0, 0x10FFFF);
1502 set.retain(start, end);
1503 expectRange((UnicodeString)"retain(" + start + "," + end + ")",
1507 set.set(0, 0x10FFFF);
1509 set.remove(start, end);
1511 expectRange((UnicodeString)"!remove(" + start + "," + end + ")",
1514 set.set(0, 0x10FFFF);
1515 set.complement(start, end);
1517 expectRange((UnicodeString)"!complement(" + start + "," + end + ")",
1519 set.complement(start);
1522 const UChar32 DATA2[] = {
1528 const int32_t DATA2_LENGTH = sizeof(DATA2)/sizeof(DATA2[0]);
1530 for (i=0; i<DATA2_LENGTH; ++i) {
1531 UChar32 c = DATA2[i], end = 0x10FFFF;
1532 UBool valid = (c >= 0 && c <= 0x10FFFF);
1534 UnicodeSet set(0, 0x10FFFF);
1536 // For single-codepoint contains, invalid codepoints are NOT contained
1537 UBool b = set.contains(c);
1539 logln((UnicodeString)"[\\u0000-\\U0010FFFF].contains(" + c +
1542 errln((UnicodeString)"FAIL: [\\u0000-\\U0010FFFF].contains(" + c +
1546 // For codepoint range contains, containsNone, and containsSome,
1547 // invalid or empty (start > end) ranges have UNDEFINED behavior.
1548 b = set.contains(c, end);
1549 logln((UnicodeString)"* [\\u0000-\\U0010FFFF].contains(" + c +
1550 "," + end + ") = " + b);
1552 b = set.containsNone(c, end);
1553 logln((UnicodeString)"* [\\u0000-\\U0010FFFF].containsNone(" + c +
1554 "," + end + ") = " + b);
1556 b = set.containsSome(c, end);
1557 logln((UnicodeString)"* [\\u0000-\\U0010FFFF].containsSome(" + c +
1558 "," + end + ") = " + b);
1560 int32_t index = set.indexOf(c);
1561 if ((index >= 0) == valid) {
1562 logln((UnicodeString)"[\\u0000-\\U0010FFFF].indexOf(" + c +
1565 errln((UnicodeString)"FAIL: [\\u0000-\\U0010FFFF].indexOf(" + c +
1571 // Used by TestSymbolTable
1572 class TokenSymbolTable : public SymbolTable {
1576 TokenSymbolTable(UErrorCode& ec) : contents(FALSE, ec) {
1577 contents.setValueDeleter(uprv_deleteUObject);
1580 ~TokenSymbolTable() {}
1583 * (Non-SymbolTable API) Add the given variable and value to
1584 * the table. Variable should NOT contain leading '$'.
1586 void add(const UnicodeString& var, const UnicodeString& value,
1588 if (U_SUCCESS(ec)) {
1589 contents.put(var, new UnicodeString(value), ec);
1596 virtual const UnicodeString* lookup(const UnicodeString& s) const {
1597 return (const UnicodeString*) contents.get(s);
1603 virtual const UnicodeFunctor* lookupMatcher(UChar32 /*ch*/) const {
1610 virtual UnicodeString parseReference(const UnicodeString& text,
1611 ParsePosition& pos, int32_t limit) const {
1612 int32_t start = pos.getIndex();
1614 UnicodeString result;
1616 UChar c = text.charAt(i);
1617 if ((i==start && !u_isIDStart(c)) || !u_isIDPart(c)) {
1622 if (i == start) { // No valid name chars
1623 return result; // Indicate failure with empty string
1626 text.extractBetween(start, i, result);
1631 void UnicodeSetTest::TestSymbolTable() {
1632 // Multiple test cases can be set up here. Each test case
1633 // is terminated by null:
1634 // var, value, var, value,..., input pat., exp. output pat., null
1635 const char* DATA[] = {
1636 "us", "a-z", "[0-1$us]", "[0-1a-z]", NULL,
1637 "us", "[a-z]", "[0-1$us]", "[0-1[a-z]]", NULL,
1638 "us", "\\[a\\-z\\]", "[0-1$us]", "[-01\\[\\]az]", NULL,
1642 for (int32_t i=0; DATA[i]!=NULL; ++i) {
1643 UErrorCode ec = U_ZERO_ERROR;
1644 TokenSymbolTable sym(ec);
1645 if (U_FAILURE(ec)) {
1646 errln("FAIL: couldn't construct TokenSymbolTable");
1651 while (DATA[i+2] != NULL) {
1652 sym.add(UnicodeString(DATA[i], -1, US_INV), UnicodeString(DATA[i+1], -1, US_INV), ec);
1653 if (U_FAILURE(ec)) {
1654 errln("FAIL: couldn't add to TokenSymbolTable");
1660 // Input pattern and expected output pattern
1661 UnicodeString inpat = UnicodeString(DATA[i], -1, US_INV), exppat = UnicodeString(DATA[i+1], -1, US_INV);
1664 ParsePosition pos(0);
1665 UnicodeSet us(inpat, pos, USET_IGNORE_SPACE, &sym, ec);
1666 if (U_FAILURE(ec)) {
1667 errln("FAIL: couldn't construct UnicodeSet");
1672 if (pos.getIndex() != inpat.length()) {
1673 errln((UnicodeString)"Failed to read to end of string \""
1674 + inpat + "\": read to "
1675 + pos.getIndex() + ", length is "
1679 UnicodeSet us2(exppat, ec);
1680 if (U_FAILURE(ec)) {
1681 errln("FAIL: couldn't construct expected UnicodeSet");
1687 errln((UnicodeString)"Failed, got " + us.toPattern(a, TRUE) +
1688 ", expected " + us2.toPattern(b, TRUE));
1690 logln((UnicodeString)"Ok, got " + us.toPattern(a, TRUE));
1695 void UnicodeSetTest::TestSurrogate() {
1696 const char* DATA[] = {
1697 // These should all behave identically
1698 "[abc\\uD800\\uDC00]",
1699 // "[abc\uD800\uDC00]", // Can't do this on C -- only Java
1703 for (int i=0; DATA[i] != 0; ++i) {
1704 UErrorCode ec = U_ZERO_ERROR;
1705 logln((UnicodeString)"Test pattern " + i + " :" + UnicodeString(DATA[i], -1, US_INV));
1706 UnicodeString str = UnicodeString(DATA[i], -1, US_INV);
1707 UnicodeSet set(str, ec);
1708 if (U_FAILURE(ec)) {
1709 errln("FAIL: UnicodeSet constructor");
1712 expectContainment(set,
1713 CharsToUnicodeString("abc\\U00010000"),
1714 CharsToUnicodeString("\\uD800;\\uDC00")); // split apart surrogate-pair
1715 if (set.size() != 4) {
1716 errln((UnicodeString)"FAIL: " + UnicodeString(DATA[i], -1, US_INV) + ".size() == " +
1717 set.size() + ", expected 4");
1722 void UnicodeSetTest::TestExhaustive() {
1723 // exhaustive tests. Simulate UnicodeSets with integers.
1724 // That gives us very solid tests (except for large memory tests).
1726 int32_t limit = 128;
1728 UnicodeSet x, y, z, aa;
1730 for (int32_t i = 0; i < limit; ++i) {
1732 logln((UnicodeString)"Testing " + i + ", " + x);
1733 _testComplement(i, x, y);
1735 // AS LONG AS WE ARE HERE, check roundtrip
1736 checkRoundTrip(bitsToSet(i, aa));
1738 for (int32_t j = 0; j < limit; ++j) {
1739 _testAdd(i,j, x,y,z);
1740 _testXor(i,j, x,y,z);
1741 _testRetain(i,j, x,y,z);
1742 _testRemove(i,j, x,y,z);
1747 void UnicodeSetTest::_testComplement(int32_t a, UnicodeSet& x, UnicodeSet& z) {
1751 int32_t c = setToBits(z);
1753 errln((UnicodeString)"FAILED: add: ~" + x + " != " + z);
1754 errln((UnicodeString)"FAILED: add: ~" + a + " != " + c);
1756 checkCanonicalRep(z, (UnicodeString)"complement " + a);
1759 void UnicodeSetTest::_testAdd(int32_t a, int32_t b, UnicodeSet& x, UnicodeSet& y, UnicodeSet& z) {
1764 int32_t c = setToBits(z);
1766 errln((UnicodeString)"FAILED: add: " + x + " | " + y + " != " + z);
1767 errln((UnicodeString)"FAILED: add: " + a + " | " + b + " != " + c);
1769 checkCanonicalRep(z, (UnicodeString)"add " + a + "," + b);
1772 void UnicodeSetTest::_testRetain(int32_t a, int32_t b, UnicodeSet& x, UnicodeSet& y, UnicodeSet& z) {
1777 int32_t c = setToBits(z);
1779 errln((UnicodeString)"FAILED: retain: " + x + " & " + y + " != " + z);
1780 errln((UnicodeString)"FAILED: retain: " + a + " & " + b + " != " + c);
1782 checkCanonicalRep(z, (UnicodeString)"retain " + a + "," + b);
1785 void UnicodeSetTest::_testRemove(int32_t a, int32_t b, UnicodeSet& x, UnicodeSet& y, UnicodeSet& z) {
1790 int32_t c = setToBits(z);
1791 if (c != (a &~ b)) {
1792 errln((UnicodeString)"FAILED: remove: " + x + " &~ " + y + " != " + z);
1793 errln((UnicodeString)"FAILED: remove: " + a + " &~ " + b + " != " + c);
1795 checkCanonicalRep(z, (UnicodeString)"remove " + a + "," + b);
1798 void UnicodeSetTest::_testXor(int32_t a, int32_t b, UnicodeSet& x, UnicodeSet& y, UnicodeSet& z) {
1803 int32_t c = setToBits(z);
1805 errln((UnicodeString)"FAILED: complement: " + x + " ^ " + y + " != " + z);
1806 errln((UnicodeString)"FAILED: complement: " + a + " ^ " + b + " != " + c);
1808 checkCanonicalRep(z, (UnicodeString)"complement " + a + "," + b);
1812 * Check that ranges are monotonically increasing and non-
1815 void UnicodeSetTest::checkCanonicalRep(const UnicodeSet& set, const UnicodeString& msg) {
1816 int32_t n = set.getRangeCount();
1818 errln((UnicodeString)"FAIL result of " + msg +
1819 ": range count should be >= 0 but is " +
1820 n /*+ " for " + set.toPattern())*/);
1824 for (int32_t i=0; i<n; ++i) {
1825 UChar32 start = set.getRangeStart(i);
1826 UChar32 end = set.getRangeEnd(i);
1828 errln((UnicodeString)"FAIL result of " + msg +
1829 ": range " + (i+1) +
1830 " start > end: " + (int)start + ", " + (int)end +
1833 if (i > 0 && start <= last) {
1834 errln((UnicodeString)"FAIL result of " + msg +
1835 ": range " + (i+1) +
1836 " overlaps previous range: " + (int)start + ", " + (int)end +
1844 * Convert a bitmask to a UnicodeSet.
1846 UnicodeSet& UnicodeSetTest::bitsToSet(int32_t a, UnicodeSet& result) {
1848 for (UChar32 i = 0; i < 32; ++i) {
1849 if ((a & (1<<i)) != 0) {
1857 * Convert a UnicodeSet to a bitmask. Only the characters
1858 * U+0000 to U+0020 are represented in the bitmask.
1860 int32_t UnicodeSetTest::setToBits(const UnicodeSet& x) {
1862 for (int32_t i = 0; i < 32; ++i) {
1863 if (x.contains((UChar32)i)) {
1871 * Return the representation of an inversion list based UnicodeSet
1872 * as a pairs list. Ranges are listed in ascending Unicode order.
1873 * For example, the set [a-zA-M3] is represented as "33AMaz".
1875 UnicodeString UnicodeSetTest::getPairs(const UnicodeSet& set) {
1876 UnicodeString pairs;
1877 for (int32_t i=0; i<set.getRangeCount(); ++i) {
1878 UChar32 start = set.getRangeStart(i);
1879 UChar32 end = set.getRangeEnd(i);
1882 i = set.getRangeCount(); // Should be unnecessary
1884 pairs.append((UChar)start).append((UChar)end);
1890 * Basic consistency check for a few items.
1891 * That the iterator works, and that we can create a pattern and
1892 * get the same thing back
1894 void UnicodeSetTest::checkRoundTrip(const UnicodeSet& s) {
1895 UErrorCode ec = U_ZERO_ERROR;
1898 checkEqual(s, t, "copy ct");
1901 checkEqual(s, t, "operator=");
1903 copyWithIterator(t, s, FALSE);
1904 checkEqual(s, t, "iterator roundtrip");
1906 copyWithIterator(t, s, TRUE); // try range
1907 checkEqual(s, t, "iterator roundtrip");
1909 UnicodeString pat; s.toPattern(pat, FALSE);
1910 t.applyPattern(pat, ec);
1911 if (U_FAILURE(ec)) {
1912 errln("FAIL: applyPattern");
1915 checkEqual(s, t, "toPattern(false)");
1918 s.toPattern(pat, TRUE);
1919 t.applyPattern(pat, ec);
1920 if (U_FAILURE(ec)) {
1921 errln("FAIL: applyPattern");
1924 checkEqual(s, t, "toPattern(true)");
1928 void UnicodeSetTest::copyWithIterator(UnicodeSet& t, const UnicodeSet& s, UBool withRange) {
1930 UnicodeSetIterator it(s);
1932 while (it.nextRange()) {
1933 if (it.isString()) {
1934 t.add(it.getString());
1936 t.add(it.getCodepoint(), it.getCodepointEnd());
1941 if (it.isString()) {
1942 t.add(it.getString());
1944 t.add(it.getCodepoint());
1950 UBool UnicodeSetTest::checkEqual(const UnicodeSet& s, const UnicodeSet& t, const char* message) {
1951 UnicodeString source; s.toPattern(source, TRUE);
1952 UnicodeString result; t.toPattern(result, TRUE);
1954 errln((UnicodeString)"FAIL: " + message
1955 + "; source = " + source
1956 + "; result = " + result
1960 logln((UnicodeString)"Ok: " + message
1961 + "; source = " + source
1962 + "; result = " + result
1969 UnicodeSetTest::expectContainment(const UnicodeString& pat,
1970 const UnicodeString& charsIn,
1971 const UnicodeString& charsOut) {
1972 UErrorCode ec = U_ZERO_ERROR;
1973 UnicodeSet set(pat, ec);
1974 if (U_FAILURE(ec)) {
1975 dataerrln((UnicodeString)"FAIL: pattern \"" +
1976 pat + "\" => " + u_errorName(ec));
1979 expectContainment(set, pat, charsIn, charsOut);
1983 UnicodeSetTest::expectContainment(const UnicodeSet& set,
1984 const UnicodeString& charsIn,
1985 const UnicodeString& charsOut) {
1988 expectContainment(set, pat, charsIn, charsOut);
1992 UnicodeSetTest::expectContainment(const UnicodeSet& set,
1993 const UnicodeString& setName,
1994 const UnicodeString& charsIn,
1995 const UnicodeString& charsOut) {
2000 for (i=0; i<charsIn.length(); i+=U16_LENGTH(c)) {
2001 c = charsIn.char32At(i);
2002 if (!set.contains(c)) {
2006 if (bad.length() > 0) {
2007 errln((UnicodeString)"Fail: set " + setName + " does not contain " + prettify(bad) +
2008 ", expected containment of " + prettify(charsIn));
2010 logln((UnicodeString)"Ok: set " + setName + " contains " + prettify(charsIn));
2014 for (i=0; i<charsOut.length(); i+=U16_LENGTH(c)) {
2015 c = charsOut.char32At(i);
2016 if (set.contains(c)) {
2020 if (bad.length() > 0) {
2021 errln((UnicodeString)"Fail: set " + setName + " contains " + prettify(bad) +
2022 ", expected non-containment of " + prettify(charsOut));
2024 logln((UnicodeString)"Ok: set " + setName + " does not contain " + prettify(charsOut));
2029 UnicodeSetTest::expectPattern(UnicodeSet& set,
2030 const UnicodeString& pattern,
2031 const UnicodeString& expectedPairs){
2032 UErrorCode status = U_ZERO_ERROR;
2033 set.applyPattern(pattern, status);
2034 if (U_FAILURE(status)) {
2035 errln(UnicodeString("FAIL: applyPattern(\"") + pattern +
2039 if (getPairs(set) != expectedPairs ) {
2040 errln(UnicodeString("FAIL: applyPattern(\"") + pattern +
2042 escape(getPairs(set)) + "\", expected \"" +
2043 escape(expectedPairs) + "\"");
2045 logln(UnicodeString("Ok: applyPattern(\"") + pattern +
2047 escape(getPairs(set)) + "\"");
2050 // the result of calling set.toPattern(), which is the string representation of
2051 // this set(set), is passed to a UnicodeSet constructor, and tested that it
2052 // will produce another set that is equal to this one.
2053 UnicodeString temppattern;
2054 set.toPattern(temppattern);
2055 UnicodeSet *tempset=new UnicodeSet(temppattern, status);
2056 if (U_FAILURE(status)) {
2057 errln(UnicodeString("FAIL: applyPattern(\""+ pattern + "\").toPattern() => " + temppattern + " => invalid pattern"));
2060 if(*tempset != set || getPairs(*tempset) != getPairs(set)){
2061 errln(UnicodeString("FAIL: applyPattern(\""+ pattern + "\").toPattern() => " + temppattern + " => pairs \""+ escape(getPairs(*tempset)) + "\", expected pairs \"" +
2062 escape(getPairs(set)) + "\""));
2064 logln(UnicodeString("Ok: applyPattern(\""+ pattern + "\").toPattern() => " + temppattern + " => pairs \"" + escape(getPairs(*tempset)) + "\""));
2072 UnicodeSetTest::expectPairs(const UnicodeSet& set, const UnicodeString& expectedPairs) {
2073 if (getPairs(set) != expectedPairs) {
2074 errln(UnicodeString("FAIL: Expected pair list \"") +
2075 escape(expectedPairs) + "\", got \"" +
2076 escape(getPairs(set)) + "\"");
2080 void UnicodeSetTest::expectToPattern(const UnicodeSet& set,
2081 const UnicodeString& expPat,
2082 const char** expStrings) {
2084 set.toPattern(pat, TRUE);
2085 if (pat == expPat) {
2086 logln((UnicodeString)"Ok: toPattern() => \"" + pat + "\"");
2088 errln((UnicodeString)"FAIL: toPattern() => \"" + pat + "\", expected \"" + expPat + "\"");
2091 if (expStrings == NULL) {
2095 for (int32_t i=0; expStrings[i] != NULL; ++i) {
2096 if (expStrings[i] == NOT) { // sic; pointer comparison
2100 UnicodeString s = CharsToUnicodeString(expStrings[i]);
2101 UBool contained = set.contains(s);
2102 if (contained == in) {
2103 logln((UnicodeString)"Ok: " + expPat +
2104 (contained ? " contains {" : " does not contain {") +
2105 escape(expStrings[i]) + "}");
2107 errln((UnicodeString)"FAIL: " + expPat +
2108 (contained ? " contains {" : " does not contain {") +
2109 escape(expStrings[i]) + "}");
2114 static UChar toHexString(int32_t i) { return (UChar)(i + (i < 10 ? 0x30 : (0x41 - 10))); }
2117 UnicodeSetTest::doAssert(UBool condition, const char *message)
2120 errln(UnicodeString("ERROR : ") + message);
2125 UnicodeSetTest::escape(const UnicodeString& s) {
2127 for (int32_t i=0; i<s.length(); )
2129 UChar32 c = s.char32At(i);
2130 if (0x0020 <= c && c <= 0x007F) {
2134 buf += (UChar)0x5c; buf += (UChar)0x75;
2136 buf += (UChar)0x5c; buf += (UChar)0x55;
2137 buf += toHexString((c & 0xF0000000) >> 28);
2138 buf += toHexString((c & 0x0F000000) >> 24);
2139 buf += toHexString((c & 0x00F00000) >> 20);
2140 buf += toHexString((c & 0x000F0000) >> 16);
2142 buf += toHexString((c & 0xF000) >> 12);
2143 buf += toHexString((c & 0x0F00) >> 8);
2144 buf += toHexString((c & 0x00F0) >> 4);
2145 buf += toHexString(c & 0x000F);
2152 void UnicodeSetTest::TestFreezable() {
2153 UErrorCode errorCode=U_ZERO_ERROR;
2154 UnicodeString idPattern=UNICODE_STRING("[:ID_Continue:]", 15);
2155 UnicodeSet idSet(idPattern, errorCode);
2156 if(U_FAILURE(errorCode)) {
2157 dataerrln("FAIL: unable to create UnicodeSet([:ID_Continue:]) - %s", u_errorName(errorCode));
2161 UnicodeString wsPattern=UNICODE_STRING("[:White_Space:]", 15);
2162 UnicodeSet wsSet(wsPattern, errorCode);
2163 if(U_FAILURE(errorCode)) {
2164 dataerrln("FAIL: unable to create UnicodeSet([:White_Space:]) - %s", u_errorName(errorCode));
2168 idSet.add(idPattern);
2169 UnicodeSet frozen(idSet);
2172 if(idSet.isFrozen() || !frozen.isFrozen()) {
2173 errln("FAIL: isFrozen() is wrong");
2175 if(frozen!=idSet || !(frozen==idSet)) {
2176 errln("FAIL: a copy-constructed frozen set differs from its original");
2180 if(frozen!=idSet || !(frozen==idSet)) {
2181 errln("FAIL: a frozen set was modified by operator=");
2184 UnicodeSet frozen2(frozen);
2185 if(frozen2!=frozen || frozen2!=idSet) {
2186 errln("FAIL: a copied frozen set differs from its frozen original");
2188 if(!frozen2.isFrozen()) {
2189 errln("FAIL: copy-constructing a frozen set results in a thawed one");
2191 UnicodeSet frozen3(5, 55); // Set to some values to really test assignment below, not copy construction.
2192 if(frozen3.contains(0, 4) || !frozen3.contains(5, 55) || frozen3.contains(56, 0x10ffff)) {
2193 errln("FAIL: UnicodeSet(5, 55) failed");
2196 if(!frozen3.isFrozen()) {
2197 errln("FAIL: copying a frozen set results in a thawed one");
2200 UnicodeSet *cloned=(UnicodeSet *)frozen.clone();
2201 if(!cloned->isFrozen() || *cloned!=frozen || cloned->containsSome(0xd802, 0xd805)) {
2202 errln("FAIL: clone() failed");
2204 cloned->add(0xd802, 0xd805);
2205 if(cloned->containsSome(0xd802, 0xd805)) {
2206 errln("FAIL: unable to modify clone");
2210 UnicodeSet *thawed=(UnicodeSet *)frozen.cloneAsThawed();
2211 if(thawed->isFrozen() || *thawed!=frozen || thawed->containsSome(0xd802, 0xd805)) {
2212 errln("FAIL: cloneAsThawed() failed");
2214 thawed->add(0xd802, 0xd805);
2215 if(!thawed->contains(0xd802, 0xd805)) {
2216 errln("FAIL: unable to modify thawed clone");
2221 if(frozen!=idSet || !(frozen==idSet)) {
2222 errln("FAIL: UnicodeSet::set() modified a frozen set");
2226 if(frozen!=idSet || !(frozen==idSet)) {
2227 errln("FAIL: UnicodeSet::clear() modified a frozen set");
2230 frozen.closeOver(USET_CASE_INSENSITIVE);
2231 if(frozen!=idSet || !(frozen==idSet)) {
2232 errln("FAIL: UnicodeSet::closeOver() modified a frozen set");
2236 if(frozen!=idSet || !(frozen==idSet)) {
2237 errln("FAIL: UnicodeSet::compact() modified a frozen set");
2242 applyPattern(wsPattern, errorCode).
2243 applyPattern(wsPattern, USET_IGNORE_SPACE, NULL, errorCode).
2244 applyPattern(wsPattern, pos, USET_IGNORE_SPACE, NULL, errorCode).
2245 applyIntPropertyValue(UCHAR_CANONICAL_COMBINING_CLASS, 230, errorCode).
2246 applyPropertyAlias(UNICODE_STRING_SIMPLE("Assigned"), UnicodeString(), errorCode);
2247 if(frozen!=idSet || !(frozen==idSet)) {
2248 errln("FAIL: UnicodeSet::applyXYZ() modified a frozen set");
2253 add(0xd802, 0xd805).
2257 if(frozen!=idSet || !(frozen==idSet)) {
2258 errln("FAIL: UnicodeSet::addXYZ() modified a frozen set");
2264 retainAll(wsPattern).
2266 if(frozen!=idSet || !(frozen==idSet)) {
2267 errln("FAIL: UnicodeSet::retainXYZ() modified a frozen set");
2274 removeAll(idPattern).
2276 if(frozen!=idSet || !(frozen==idSet)) {
2277 errln("FAIL: UnicodeSet::removeXYZ() modified a frozen set");
2283 complement(0x64, 0x69).
2284 complement(idPattern).
2285 complementAll(idPattern).
2286 complementAll(idSet);
2287 if(frozen!=idSet || !(frozen==idSet)) {
2288 errln("FAIL: UnicodeSet::complementXYZ() modified a frozen set");
2292 // Test span() etc. -------------------------------------------------------- ***
2294 // Append the UTF-8 version of the string to t and return the appended UTF-8 length.
2296 appendUTF8(const UChar *s, int32_t length, char *t, int32_t capacity) {
2297 UErrorCode errorCode=U_ZERO_ERROR;
2299 u_strToUTF8(t, capacity, &length8, s, length, &errorCode);
2300 if(U_SUCCESS(errorCode)) {
2303 // The string contains an unpaired surrogate.
2304 // Ignore this string.
2309 class UnicodeSetWithStringsIterator;
2311 // Make the strings in a UnicodeSet easily accessible.
2312 class UnicodeSetWithStrings {
2314 UnicodeSetWithStrings(const UnicodeSet &normalSet) :
2315 set(normalSet), stringsLength(0), hasSurrogates(FALSE) {
2316 int32_t size=set.size();
2317 if(size>0 && set.charAt(size-1)<0) {
2318 // If a set's last element is not a code point, then it must contain strings.
2319 // Iterate over the set, skip all code point ranges, and cache the strings.
2320 // Convert them to UTF-8 for spanUTF8().
2321 UnicodeSetIterator iter(set);
2322 const UnicodeString *s;
2324 int32_t length8, utf8Count=0;
2325 while(iter.nextRange() && stringsLength<LENGTHOF(strings)) {
2326 if(iter.isString()) {
2327 // Store the pointer to the set's string element
2328 // which we happen to know is a stable pointer.
2329 strings[stringsLength]=s=&iter.getString();
2331 utf8Lengths[stringsLength]=length8=
2332 appendUTF8(s->getBuffer(), s->length(),
2333 s8, (int32_t)(sizeof(utf8)-utf8Count));
2335 hasSurrogates=TRUE; // Contains unpaired surrogates.
2344 const UnicodeSet &getSet() const {
2348 UBool hasStrings() const {
2349 return (UBool)(stringsLength>0);
2352 UBool hasStringsWithSurrogates() const {
2353 return hasSurrogates;
2357 friend class UnicodeSetWithStringsIterator;
2359 const UnicodeSet &set;
2361 const UnicodeString *strings[20];
2362 int32_t stringsLength;
2363 UBool hasSurrogates;
2366 int32_t utf8Lengths[20];
2369 class UnicodeSetWithStringsIterator {
2371 UnicodeSetWithStringsIterator(const UnicodeSetWithStrings &set) :
2372 fSet(set), nextStringIndex(0), nextUTF8Start(0) {
2376 nextStringIndex=nextUTF8Start=0;
2379 const UnicodeString *nextString() {
2380 if(nextStringIndex<fSet.stringsLength) {
2381 return fSet.strings[nextStringIndex++];
2387 // Do not mix with calls to nextString().
2388 const char *nextUTF8(int32_t &length) {
2389 if(nextStringIndex<fSet.stringsLength) {
2390 const char *s8=fSet.utf8+nextUTF8Start;
2391 nextUTF8Start+=length=fSet.utf8Lengths[nextStringIndex++];
2400 const UnicodeSetWithStrings &fSet;
2401 int32_t nextStringIndex;
2402 int32_t nextUTF8Start;
2405 // Compare 16-bit Unicode strings (which may be malformed UTF-16)
2406 // at code point boundaries.
2407 // That is, each edge of a match must not be in the middle of a surrogate pair.
2409 matches16CPB(const UChar *s, int32_t start, int32_t limit, const UnicodeString &t) {
2412 int32_t length=t.length();
2413 return 0==t.compare(s, length) &&
2414 !(0<start && U16_IS_LEAD(s[-1]) && U16_IS_TRAIL(s[0])) &&
2415 !(length<limit && U16_IS_LEAD(s[length-1]) && U16_IS_TRAIL(s[length]));
2418 // Implement span() with contains() for comparison.
2419 static int32_t containsSpanUTF16(const UnicodeSetWithStrings &set, const UChar *s, int32_t length,
2420 USetSpanCondition spanCondition) {
2421 const UnicodeSet &realSet(set.getSet());
2422 if(!set.hasStrings()) {
2423 if(spanCondition!=USET_SPAN_NOT_CONTAINED) {
2424 spanCondition=USET_SPAN_CONTAINED; // Pin to 0/1 values.
2428 int32_t start=0, prev;
2429 while((prev=start)<length) {
2430 U16_NEXT(s, start, length, c);
2431 if(realSet.contains(c)!=spanCondition) {
2436 } else if(spanCondition==USET_SPAN_NOT_CONTAINED) {
2437 UnicodeSetWithStringsIterator iter(set);
2439 int32_t start, next;
2440 for(start=next=0; start<length;) {
2441 U16_NEXT(s, next, length, c);
2442 if(realSet.contains(c)) {
2445 const UnicodeString *str;
2447 while((str=iter.nextString())!=NULL) {
2448 if(str->length()<=(length-start) && matches16CPB(s, start, length, *str)) {
2449 // spanNeedsStrings=TRUE;
2456 } else /* USET_SPAN_CONTAINED or USET_SPAN_SIMPLE */ {
2457 UnicodeSetWithStringsIterator iter(set);
2459 int32_t start, next, maxSpanLimit=0;
2460 for(start=next=0; start<length;) {
2461 U16_NEXT(s, next, length, c);
2462 if(!realSet.contains(c)) {
2463 next=start; // Do not span this single, not-contained code point.
2465 const UnicodeString *str;
2467 while((str=iter.nextString())!=NULL) {
2468 if(str->length()<=(length-start) && matches16CPB(s, start, length, *str)) {
2469 // spanNeedsStrings=TRUE;
2470 int32_t matchLimit=start+str->length();
2471 if(matchLimit==length) {
2474 if(spanCondition==USET_SPAN_CONTAINED) {
2475 // Iterate for the shortest match at each position.
2476 // Recurse for each but the shortest match.
2478 next=matchLimit; // First match from start.
2480 if(matchLimit<next) {
2481 // Remember shortest match from start for iteration.
2486 // Recurse for non-shortest match from start.
2487 int32_t spanLength=containsSpanUTF16(set, s+matchLimit, length-matchLimit,
2488 USET_SPAN_CONTAINED);
2489 if((matchLimit+spanLength)>maxSpanLimit) {
2490 maxSpanLimit=matchLimit+spanLength;
2491 if(maxSpanLimit==length) {
2496 } else /* spanCondition==USET_SPAN_SIMPLE */ {
2497 if(matchLimit>next) {
2498 // Remember longest match from start.
2505 break; // No match from start.
2509 if(start>maxSpanLimit) {
2512 return maxSpanLimit;
2517 static int32_t containsSpanBackUTF16(const UnicodeSetWithStrings &set, const UChar *s, int32_t length,
2518 USetSpanCondition spanCondition) {
2522 const UnicodeSet &realSet(set.getSet());
2523 if(!set.hasStrings()) {
2524 if(spanCondition!=USET_SPAN_NOT_CONTAINED) {
2525 spanCondition=USET_SPAN_CONTAINED; // Pin to 0/1 values.
2529 int32_t prev=length;
2531 U16_PREV(s, 0, length, c);
2532 if(realSet.contains(c)!=spanCondition) {
2535 } while((prev=length)>0);
2537 } else if(spanCondition==USET_SPAN_NOT_CONTAINED) {
2538 UnicodeSetWithStringsIterator iter(set);
2540 int32_t prev=length, length0=length;
2542 U16_PREV(s, 0, length, c);
2543 if(realSet.contains(c)) {
2546 const UnicodeString *str;
2548 while((str=iter.nextString())!=NULL) {
2549 if(str->length()<=prev && matches16CPB(s, prev-str->length(), length0, *str)) {
2550 // spanNeedsStrings=TRUE;
2554 } while((prev=length)>0);
2556 } else /* USET_SPAN_CONTAINED or USET_SPAN_SIMPLE */ {
2557 UnicodeSetWithStringsIterator iter(set);
2559 int32_t prev=length, minSpanStart=length, length0=length;
2561 U16_PREV(s, 0, length, c);
2562 if(!realSet.contains(c)) {
2563 length=prev; // Do not span this single, not-contained code point.
2565 const UnicodeString *str;
2567 while((str=iter.nextString())!=NULL) {
2568 if(str->length()<=prev && matches16CPB(s, prev-str->length(), length0, *str)) {
2569 // spanNeedsStrings=TRUE;
2570 int32_t matchStart=prev-str->length();
2574 if(spanCondition==USET_SPAN_CONTAINED) {
2575 // Iterate for the shortest match at each position.
2576 // Recurse for each but the shortest match.
2578 length=matchStart; // First match from prev.
2580 if(matchStart>length) {
2581 // Remember shortest match from prev for iteration.
2582 int32_t temp=length;
2586 // Recurse for non-shortest match from prev.
2587 int32_t spanStart=containsSpanBackUTF16(set, s, matchStart,
2588 USET_SPAN_CONTAINED);
2589 if(spanStart<minSpanStart) {
2590 minSpanStart=spanStart;
2591 if(minSpanStart==0) {
2596 } else /* spanCondition==USET_SPAN_SIMPLE */ {
2597 if(matchStart<length) {
2598 // Remember longest match from prev.
2605 break; // No match from prev.
2607 } while((prev=length)>0);
2608 if(prev<minSpanStart) {
2611 return minSpanStart;
2616 static int32_t containsSpanUTF8(const UnicodeSetWithStrings &set, const char *s, int32_t length,
2617 USetSpanCondition spanCondition) {
2618 const UnicodeSet &realSet(set.getSet());
2619 if(!set.hasStrings()) {
2620 if(spanCondition!=USET_SPAN_NOT_CONTAINED) {
2621 spanCondition=USET_SPAN_CONTAINED; // Pin to 0/1 values.
2625 int32_t start=0, prev;
2626 while((prev=start)<length) {
2627 U8_NEXT_OR_FFFD(s, start, length, c);
2628 if(realSet.contains(c)!=spanCondition) {
2633 } else if(spanCondition==USET_SPAN_NOT_CONTAINED) {
2634 UnicodeSetWithStringsIterator iter(set);
2636 int32_t start, next;
2637 for(start=next=0; start<length;) {
2638 U8_NEXT_OR_FFFD(s, next, length, c);
2639 if(realSet.contains(c)) {
2645 while((s8=iter.nextUTF8(length8))!=NULL) {
2646 if(length8!=0 && length8<=(length-start) && 0==memcmp(s+start, s8, length8)) {
2647 // spanNeedsStrings=TRUE;
2654 } else /* USET_SPAN_CONTAINED or USET_SPAN_SIMPLE */ {
2655 UnicodeSetWithStringsIterator iter(set);
2657 int32_t start, next, maxSpanLimit=0;
2658 for(start=next=0; start<length;) {
2659 U8_NEXT_OR_FFFD(s, next, length, c);
2660 if(!realSet.contains(c)) {
2661 next=start; // Do not span this single, not-contained code point.
2666 while((s8=iter.nextUTF8(length8))!=NULL) {
2667 if(length8!=0 && length8<=(length-start) && 0==memcmp(s+start, s8, length8)) {
2668 // spanNeedsStrings=TRUE;
2669 int32_t matchLimit=start+length8;
2670 if(matchLimit==length) {
2673 if(spanCondition==USET_SPAN_CONTAINED) {
2674 // Iterate for the shortest match at each position.
2675 // Recurse for each but the shortest match.
2677 next=matchLimit; // First match from start.
2679 if(matchLimit<next) {
2680 // Remember shortest match from start for iteration.
2685 // Recurse for non-shortest match from start.
2686 int32_t spanLength=containsSpanUTF8(set, s+matchLimit, length-matchLimit,
2687 USET_SPAN_CONTAINED);
2688 if((matchLimit+spanLength)>maxSpanLimit) {
2689 maxSpanLimit=matchLimit+spanLength;
2690 if(maxSpanLimit==length) {
2695 } else /* spanCondition==USET_SPAN_SIMPLE */ {
2696 if(matchLimit>next) {
2697 // Remember longest match from start.
2704 break; // No match from start.
2708 if(start>maxSpanLimit) {
2711 return maxSpanLimit;
2716 static int32_t containsSpanBackUTF8(const UnicodeSetWithStrings &set, const char *s, int32_t length,
2717 USetSpanCondition spanCondition) {
2721 const UnicodeSet &realSet(set.getSet());
2722 if(!set.hasStrings()) {
2723 if(spanCondition!=USET_SPAN_NOT_CONTAINED) {
2724 spanCondition=USET_SPAN_CONTAINED; // Pin to 0/1 values.
2728 int32_t prev=length;
2730 U8_PREV_OR_FFFD(s, 0, length, c);
2731 if(realSet.contains(c)!=spanCondition) {
2734 } while((prev=length)>0);
2736 } else if(spanCondition==USET_SPAN_NOT_CONTAINED) {
2737 UnicodeSetWithStringsIterator iter(set);
2739 int32_t prev=length;
2741 U8_PREV_OR_FFFD(s, 0, length, c);
2742 if(realSet.contains(c)) {
2748 while((s8=iter.nextUTF8(length8))!=NULL) {
2749 if(length8!=0 && length8<=prev && 0==memcmp(s+prev-length8, s8, length8)) {
2750 // spanNeedsStrings=TRUE;
2754 } while((prev=length)>0);
2756 } else /* USET_SPAN_CONTAINED or USET_SPAN_SIMPLE */ {
2757 UnicodeSetWithStringsIterator iter(set);
2759 int32_t prev=length, minSpanStart=length;
2761 U8_PREV_OR_FFFD(s, 0, length, c);
2762 if(!realSet.contains(c)) {
2763 length=prev; // Do not span this single, not-contained code point.
2768 while((s8=iter.nextUTF8(length8))!=NULL) {
2769 if(length8!=0 && length8<=prev && 0==memcmp(s+prev-length8, s8, length8)) {
2770 // spanNeedsStrings=TRUE;
2771 int32_t matchStart=prev-length8;
2775 if(spanCondition==USET_SPAN_CONTAINED) {
2776 // Iterate for the shortest match at each position.
2777 // Recurse for each but the shortest match.
2779 length=matchStart; // First match from prev.
2781 if(matchStart>length) {
2782 // Remember shortest match from prev for iteration.
2783 int32_t temp=length;
2787 // Recurse for non-shortest match from prev.
2788 int32_t spanStart=containsSpanBackUTF8(set, s, matchStart,
2789 USET_SPAN_CONTAINED);
2790 if(spanStart<minSpanStart) {
2791 minSpanStart=spanStart;
2792 if(minSpanStart==0) {
2797 } else /* spanCondition==USET_SPAN_SIMPLE */ {
2798 if(matchStart<length) {
2799 // Remember longest match from prev.
2806 break; // No match from prev.
2808 } while((prev=length)>0);
2809 if(prev<minSpanStart) {
2812 return minSpanStart;
2817 // spans to be performed and compared
2831 SPAN_CONTAINED =0x100,
2833 SPAN_CONDITION =0x300,
2838 static inline USetSpanCondition invertSpanCondition(USetSpanCondition spanCondition, USetSpanCondition contained) {
2839 return spanCondition == USET_SPAN_NOT_CONTAINED ? contained : USET_SPAN_NOT_CONTAINED;
2842 static inline int32_t slen(const void *s, UBool isUTF16) {
2843 return isUTF16 ? u_strlen((const UChar *)s) : strlen((const char *)s);
2847 * Count spans on a string with the method according to type and set the span limits.
2848 * The set may be the complement of the original.
2849 * When using spanBack() and comparing with span(), use a span condition for the first spanBack()
2850 * according to the expected number of spans.
2851 * Sets typeName to an empty string if there is no such type.
2852 * Returns -1 if the span option is filtered out.
2854 static int32_t getSpans(const UnicodeSetWithStrings &set, UBool isComplement,
2855 const void *s, int32_t length, UBool isUTF16,
2856 uint32_t whichSpans,
2857 int type, const char *&typeName,
2858 int32_t limits[], int32_t limitsCapacity,
2859 int32_t expectCount) {
2860 const UnicodeSet &realSet(set.getSet());
2861 int32_t start, count;
2862 USetSpanCondition spanCondition, firstSpanCondition, contained;
2865 if(type<0 || 7<type) {
2870 static const char *const typeNames16[]={
2871 "contains", "contains(LM)",
2873 "containsBack", "containsBack(LM)",
2874 "spanBack", "spanBack(LM)"
2877 static const char *const typeNames8[]={
2878 "containsUTF8", "containsUTF8(LM)",
2879 "spanUTF8", "spanUTF8(LM)",
2880 "containsBackUTF8", "containsBackUTF8(LM)", // not implemented
2881 "spanBackUTF8", "spanBackUTF8(LM)"
2884 typeName= isUTF16 ? typeNames16[type] : typeNames8[type];
2886 // filter span options
2889 if((whichSpans&SPAN_FWD)==0) {
2895 if((whichSpans&SPAN_BACK)==0) {
2901 // use USET_SPAN_CONTAINED
2902 if((whichSpans&SPAN_CONTAINED)==0) {
2905 contained=USET_SPAN_CONTAINED;
2907 // use USET_SPAN_SIMPLE
2908 if((whichSpans&SPAN_SIMPLE)==0) {
2911 contained=USET_SPAN_SIMPLE;
2914 // Default first span condition for going forward with an uncomplemented set.
2915 spanCondition=USET_SPAN_NOT_CONTAINED;
2917 spanCondition=invertSpanCondition(spanCondition, contained);
2920 // First span condition for span(), used to terminate the spanBack() iteration.
2921 firstSpanCondition=spanCondition;
2923 // spanBack(): Its initial span condition is span()'s last span condition,
2924 // which is the opposite of span()'s first span condition
2925 // if we expect an even number of spans.
2926 // (The loop inverts spanCondition (expectCount-1) times
2927 // before the expectCount'th span() call.)
2928 // If we do not compare forward and backward directions, then we do not have an
2929 // expectCount and just start with firstSpanCondition.
2930 if(!isForward && (whichSpans&SPAN_FWD)!=0 && (expectCount&1)==0) {
2931 spanCondition=invertSpanCondition(spanCondition, contained);
2940 length=slen(s, isUTF16);
2943 start+= isUTF16 ? containsSpanUTF16(set, (const UChar *)s+start, length-start, spanCondition) :
2944 containsSpanUTF8(set, (const char *)s+start, length-start, spanCondition);
2945 if(count<limitsCapacity) {
2946 limits[count]=start;
2952 spanCondition=invertSpanCondition(spanCondition, contained);
2959 start+= isUTF16 ? realSet.span((const UChar *)s+start, length>=0 ? length-start : length, spanCondition) :
2960 realSet.spanUTF8((const char *)s+start, length>=0 ? length-start : length, spanCondition);
2961 if(count<limitsCapacity) {
2962 limits[count]=start;
2965 if(length>=0 ? start>=length :
2966 isUTF16 ? ((const UChar *)s)[start]==0 :
2967 ((const char *)s)[start]==0
2971 spanCondition=invertSpanCondition(spanCondition, contained);
2977 length=slen(s, isUTF16);
2981 if(count<=limitsCapacity) {
2982 limits[limitsCapacity-count]=length;
2984 length= isUTF16 ? containsSpanBackUTF16(set, (const UChar *)s, length, spanCondition) :
2985 containsSpanBackUTF8(set, (const char *)s, length, spanCondition);
2986 if(length==0 && spanCondition==firstSpanCondition) {
2989 spanCondition=invertSpanCondition(spanCondition, contained);
2991 if(count<limitsCapacity) {
2992 memmove(limits, limits+(limitsCapacity-count), count*4);
2999 if(count<=limitsCapacity) {
3000 limits[limitsCapacity-count]= length >=0 ? length : slen(s, isUTF16);
3002 // Note: Length<0 is tested only for the first spanBack().
3003 // If we wanted to keep length<0 for all spanBack()s, we would have to
3004 // temporarily modify the string by placing a NUL where the previous spanBack() stopped.
3005 length= isUTF16 ? realSet.spanBack((const UChar *)s, length, spanCondition) :
3006 realSet.spanBackUTF8((const char *)s, length, spanCondition);
3007 if(length==0 && spanCondition==firstSpanCondition) {
3010 spanCondition=invertSpanCondition(spanCondition, contained);
3012 if(count<limitsCapacity) {
3013 memmove(limits, limits+(limitsCapacity-count), count*4);
3024 // sets to be tested; odd index=isComplement
3033 static const char *const setNames[SET_COUNT]={
3041 * Verify that we get the same results whether we look at text with contains(),
3042 * span() or spanBack(), using unfrozen or frozen versions of the set,
3043 * and using the set or its complement (switching the spanConditions accordingly).
3044 * The latter verifies that
3045 * set.span(spanCondition) == set.complement().span(!spanCondition).
3047 * The expectLimits[] are either provided by the caller (with expectCount>=0)
3048 * or returned to the caller (with an input expectCount<0).
3050 void UnicodeSetTest::testSpan(const UnicodeSetWithStrings *sets[4],
3051 const void *s, int32_t length, UBool isUTF16,
3052 uint32_t whichSpans,
3053 int32_t expectLimits[], int32_t &expectCount,
3054 const char *testName, int32_t index) {
3055 int32_t limits[500];
3056 int32_t limitsCount;
3059 const char *typeName;
3062 for(i=0; i<SET_COUNT; ++i) {
3064 // Even-numbered sets are original, uncomplemented sets.
3065 if((whichSpans&SPAN_SET)==0) {
3069 // Odd-numbered sets are complemented.
3070 if((whichSpans&SPAN_COMPLEMENT)==0) {
3074 for(type=0;; ++type) {
3075 limitsCount=getSpans(*sets[i], (UBool)(i&1),
3079 limits, LENGTHOF(limits), expectCount);
3080 if(typeName[0]==0) {
3081 break; // All types tried.
3084 continue; // Span option filtered out.
3087 expectCount=limitsCount;
3088 if(limitsCount>LENGTHOF(limits)) {
3089 errln("FAIL: %s[0x%lx].%s.%s span count=%ld > %ld capacity - too many spans",
3090 testName, (long)index, setNames[i], typeName, (long)limitsCount, (long)LENGTHOF(limits));
3093 memcpy(expectLimits, limits, limitsCount*4);
3094 } else if(limitsCount!=expectCount) {
3095 errln("FAIL: %s[0x%lx].%s.%s span count=%ld != %ld",
3096 testName, (long)index, setNames[i], typeName, (long)limitsCount, (long)expectCount);
3098 for(j=0; j<limitsCount; ++j) {
3099 if(limits[j]!=expectLimits[j]) {
3100 errln("FAIL: %s[0x%lx].%s.%s span count=%ld limits[%d]=%ld != %ld",
3101 testName, (long)index, setNames[i], typeName, (long)limitsCount,
3102 j, (long)limits[j], (long)expectLimits[j]);
3110 // Compare span() with containsAll()/containsNone(),
3111 // but only if we have expectLimits[] from the uncomplemented set.
3112 if(isUTF16 && (whichSpans&SPAN_SET)!=0) {
3113 const UChar *s16=(const UChar *)s;
3114 UnicodeString string;
3115 int32_t prev=0, limit, length;
3116 for(i=0; i<expectCount; ++i) {
3117 limit=expectLimits[i];
3120 string.setTo(FALSE, s16+prev, length); // read-only alias
3122 if(!sets[SLOW]->getSet().containsAll(string)) {
3123 errln("FAIL: %s[0x%lx].%s.containsAll(%ld..%ld)==FALSE contradicts span()",
3124 testName, (long)index, setNames[SLOW], (long)prev, (long)limit);
3127 if(!sets[FAST]->getSet().containsAll(string)) {
3128 errln("FAIL: %s[0x%lx].%s.containsAll(%ld..%ld)==FALSE contradicts span()",
3129 testName, (long)index, setNames[FAST], (long)prev, (long)limit);
3133 if(!sets[SLOW]->getSet().containsNone(string)) {
3134 errln("FAIL: %s[0x%lx].%s.containsNone(%ld..%ld)==FALSE contradicts span()",
3135 testName, (long)index, setNames[SLOW], (long)prev, (long)limit);
3138 if(!sets[FAST]->getSet().containsNone(string)) {
3139 errln("FAIL: %s[0x%lx].%s.containsNone(%ld..%ld)==FALSE contradicts span()",
3140 testName, (long)index, setNames[FAST], (long)prev, (long)limit);
3150 // Specifically test either UTF-16 or UTF-8.
3151 void UnicodeSetTest::testSpan(const UnicodeSetWithStrings *sets[4],
3152 const void *s, int32_t length, UBool isUTF16,
3153 uint32_t whichSpans,
3154 const char *testName, int32_t index) {
3155 int32_t expectLimits[500];
3156 int32_t expectCount=-1;
3157 testSpan(sets, s, length, isUTF16, whichSpans, expectLimits, expectCount, testName, index);
3160 UBool stringContainsUnpairedSurrogate(const UChar *s, int32_t length) {
3167 if(0xd800<=c && c<0xe000) {
3168 if(c>=0xdc00 || length==0 || !U16_IS_TRAIL(c2=*s++)) {
3175 while((c=*s++)!=0) {
3176 if(0xd800<=c && c<0xe000) {
3177 if(c>=0xdc00 || !U16_IS_TRAIL(c2=*s++)) {
3186 // Test both UTF-16 and UTF-8 versions of span() etc. on the same sets and text,
3187 // unless either UTF is turned off in whichSpans.
3188 // Testing UTF-16 and UTF-8 together requires that surrogate code points
3189 // have the same contains(c) value as U+FFFD.
3190 void UnicodeSetTest::testSpanBothUTFs(const UnicodeSetWithStrings *sets[4],
3191 const UChar *s16, int32_t length16,
3192 uint32_t whichSpans,
3193 const char *testName, int32_t index) {
3194 int32_t expectLimits[500];
3195 int32_t expectCount;
3197 expectCount=-1; // Get expectLimits[] from testSpan().
3199 if((whichSpans&SPAN_UTF16)!=0) {
3200 testSpan(sets, s16, length16, TRUE, whichSpans, expectLimits, expectCount, testName, index);
3202 if((whichSpans&SPAN_UTF8)==0) {
3206 // Convert s16[] and expectLimits[] to UTF-8.
3208 int32_t offsets[3000];
3210 const UChar *s16Limit=s16+length16;
3212 char *tLimit=t+sizeof(s8);
3214 UErrorCode errorCode=U_ZERO_ERROR;
3216 // Convert with substitution: Turn unpaired surrogates into U+FFFD.
3217 ucnv_fromUnicode(openUTF8Converter(), &t, tLimit, &s16, s16Limit, o, TRUE, &errorCode);
3218 if(U_FAILURE(errorCode)) {
3219 errln("FAIL: %s[0x%lx] ucnv_fromUnicode(to UTF-8) fails with %s",
3220 testName, (long)index, u_errorName(errorCode));
3221 ucnv_resetFromUnicode(utf8Cnv);
3224 int32_t length8=(int32_t)(t-(char *)s8);
3226 // Convert expectLimits[].
3227 int32_t i, j, expect;
3228 for(i=j=0; i<expectCount; ++i) {
3229 expect=expectLimits[i];
3230 if(expect==length16) {
3231 expectLimits[i]=length8;
3233 while(offsets[j]<expect) {
3240 testSpan(sets, s8, length8, FALSE, whichSpans, expectLimits, expectCount, testName, index);
3243 static UChar32 nextCodePoint(UChar32 c) {
3244 // Skip some large and boring ranges.
3265 // Verify that all implementations represent the same set.
3266 void UnicodeSetTest::testSpanContents(const UnicodeSetWithStrings *sets[4], uint32_t whichSpans, const char *testName) {
3267 // contains(U+FFFD) is inconsistent with contains(some surrogates),
3268 // or the set contains strings with unpaired surrogates which don't translate to valid UTF-8:
3269 // Skip the UTF-8 part of the test - if the string contains surrogates -
3270 // because it is likely to produce a different result.
3271 UBool inconsistentSurrogates=
3272 (!(sets[0]->getSet().contains(0xfffd) ?
3273 sets[0]->getSet().contains(0xd800, 0xdfff) :
3274 sets[0]->getSet().containsNone(0xd800, 0xdfff)) ||
3275 sets[0]->hasStringsWithSurrogates());
3279 uint32_t localWhichSpans;
3282 for(first=c=0;; c=nextCodePoint(c)) {
3283 if(c>0x10ffff || length>(LENGTHOF(s)-U16_MAX_LENGTH)) {
3284 localWhichSpans=whichSpans;
3285 if(stringContainsUnpairedSurrogate(s, length) && inconsistentSurrogates) {
3286 localWhichSpans&=~SPAN_UTF8;
3288 testSpanBothUTFs(sets, s, length, localWhichSpans, testName, first);
3295 U16_APPEND_UNSAFE(s, length, c);
3299 // Test with a particular, interesting string.
3300 // Specify length and try NUL-termination.
3301 void UnicodeSetTest::testSpanUTF16String(const UnicodeSetWithStrings *sets[4], uint32_t whichSpans, const char *testName) {
3302 static const UChar s[]={
3303 0x61, 0x62, 0x20, // Latin, space
3304 0x3b1, 0x3b2, 0x3b3, // Greek
3305 0xd900, // lead surrogate
3306 0x3000, 0x30ab, 0x30ad, // wide space, Katakana
3307 0xdc05, // trail surrogate
3308 0xa0, 0xac00, 0xd7a3, // nbsp, Hangul
3309 0xd900, 0xdc05, // unassigned supplementary
3310 0xd840, 0xdfff, 0xd860, 0xdffe, // Han supplementary
3311 0xd7a4, 0xdc05, 0xd900, 0x2028, // unassigned, surrogates in wrong order, LS
3315 if((whichSpans&SPAN_UTF16)==0) {
3318 testSpan(sets, s, -1, TRUE, (whichSpans&~SPAN_UTF8), testName, 0);
3319 testSpan(sets, s, LENGTHOF(s)-1, TRUE, (whichSpans&~SPAN_UTF8), testName, 1);
3322 void UnicodeSetTest::testSpanUTF8String(const UnicodeSetWithStrings *sets[4], uint32_t whichSpans, const char *testName) {
3323 static const char s[]={
3326 /* trail byte in lead position */
3331 /* truncated multi-byte sequences */
3343 "\xCE\xB1\xCE\xB2\xCE\xB3" // Greek
3345 /* trail byte in lead position */
3362 "\xE3\x80\x80\xE3\x82\xAB\xE3\x82\xAD" // wide space, Katakana
3364 /* trail byte in lead position */
3375 "\xC2\xA0\xEA\xB0\x80\xED\x9E\xA3" // nbsp, Hangul
3377 /* trail byte in lead position */
3383 "\xF1\x90\x80\x85" // unassigned supplementary
3385 /* trail byte in lead position */
3388 "\xfc\x80\x80\x80\x80"
3390 "\xF0\xA0\x8F\xBF\xF0\xA8\x8F\xBE" // Han supplementary
3392 /* trail byte in lead position */
3395 /* complete sequences but non-shortest forms or out of range etc. */
3401 "\xf8\x80\x80\x80\x80"
3402 "\xfc\x80\x80\x80\x80\x80"
3406 /* trail byte in lead position */
3409 "\xED\x9E\xA4\xE2\x80\xA8" // unassigned, LS, NUL-terminated
3412 if((whichSpans&SPAN_UTF8)==0) {
3415 testSpan(sets, s, -1, FALSE, (whichSpans&~SPAN_UTF16), testName, 0);
3416 testSpan(sets, s, LENGTHOF(s)-1, FALSE, (whichSpans&~SPAN_UTF16), testName, 1);
3419 // Take a set of span options and multiply them so that
3420 // each portion only has one of the options a, b and c.
3421 // If b==0, then the set of options is just modified with mask and a.
3422 // If b!=0 and c==0, then the set of options is just modified with mask, a and b.
3424 addAlternative(uint32_t whichSpans[], int32_t whichSpansCount,
3425 uint32_t mask, uint32_t a, uint32_t b, uint32_t c) {
3429 for(i=0; i<whichSpansCount; ++i) {
3430 s=whichSpans[i]&mask;
3433 whichSpans[whichSpansCount+i]=s|b;
3435 whichSpans[2*whichSpansCount+i]=s|c;
3439 return b==0 ? whichSpansCount : c==0 ? 2*whichSpansCount : 3*whichSpansCount;
3442 #define _63_a "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
3443 #define _64_a "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
3444 #define _63_b "bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb"
3445 #define _64_b "bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb"
3447 void UnicodeSetTest::TestSpan() {
3448 // "[...]" is a UnicodeSet pattern.
3449 // "*" performs tests on all Unicode code points and on a selection of
3450 // malformed UTF-8/16 strings.
3451 // "-options" limits the scope of testing for the current set.
3452 // By default, the test verifies that equivalent boundaries are found
3453 // for UTF-16 and UTF-8, going forward and backward,
3454 // alternating USET_SPAN_NOT_CONTAINED with
3455 // either USET_SPAN_CONTAINED or USET_SPAN_SIMPLE.
3456 // Single-character options:
3457 // 8 -- UTF-16 and UTF-8 boundaries may differ.
3458 // Cause: contains(U+FFFD) is inconsistent with contains(some surrogates),
3459 // or the set contains strings with unpaired surrogates
3460 // which do not translate to valid UTF-8.
3461 // c -- set.span() and set.complement().span() boundaries may differ.
3462 // Cause: Set strings are not complemented.
3463 // b -- span() and spanBack() boundaries may differ.
3464 // Cause: Strings in the set overlap, and spanBack(USET_SPAN_CONTAINED)
3465 // and spanBack(USET_SPAN_SIMPLE) are defined to
3466 // match with non-overlapping substrings.
3467 // For example, with a set containing "ab" and "ba",
3468 // span() of "aba" yields boundaries { 0, 2, 3 }
3469 // because the initial "ab" matches from 0 to 2,
3470 // while spanBack() yields boundaries { 0, 1, 3 }
3471 // because the final "ba" matches from 1 to 3.
3472 // l -- USET_SPAN_CONTAINED and USET_SPAN_SIMPLE boundaries may differ.
3473 // Cause: Strings in the set overlap, and a longer match may
3474 // require a sequence including non-longest substrings.
3475 // For example, with a set containing "ab", "abc" and "cd",
3476 // span(contained) of "abcd" spans the entire string
3477 // but span(longest match) only spans the first 3 characters.
3478 // Each "-options" first resets all options and then applies the specified options.
3479 // A "-" without options resets the options.
3480 // The options are also reset for each new set.
3481 // Other strings will be spanned.
3482 static const char *const testdata[]={
3489 "[\\u0000-\\U0010FFFF]",
3491 "[\\u0000\\u0080\\u0800\\U00010000]",
3493 "[\\u007F\\u07FF\\uFFFF\\U0010FFFF]",
3495 "[[[:ID_Continue:]-[\\u30ab\\u30ad]]{\\u3000\\u30ab}{\\u3000\\u30ab\\u30ad}]",
3498 "[[[:ID_Continue:]-[\\u30ab\\u30ad]]{\\u30ab\\u30ad}{\\u3000\\u30ab\\u30ad}]",
3502 // Overlapping strings cause overlapping attempts to match.
3503 "[x{xy}{xya}{axy}{ax}]",
3506 // More repetitions of "xya" would take too long with the recursive
3507 // reference implementation.
3508 // containsAll()=FALSE
3511 "xyaxyaxyaxya" // set.complement().span(longest match) will stop here.
3512 "xx" // set.complement().span(contained) will stop between the two 'x'es.
3515 "xyaxyaxyaxya" // span() ends here.
3518 // containsAll()=TRUE
3529 "byayaxya", // span() -> { 4, 7, 8 } spanBack() -> { 5, 8 }
3531 "byayaxy", // span() -> { 4, 7 } complement.span() -> { 7 }
3532 "byayax", // span() -> { 4, 6 } complement.span() -> { 6 }
3534 "byaya", // span() -> { 5 }
3535 "byay", // span() -> { 4 }
3536 "bya", // span() -> { 3 }
3538 // span(longest match) will not span the whole string.
3548 // spanBack(longest match) will not span the whole string.
3557 // Test with non-ASCII set strings - test proper handling of surrogate pairs
3558 // and UTF-8 trail bytes.
3559 // Copies of above test sets and strings, but transliterated to have
3560 // different code points with similar trail units.
3561 // Previous: a b c d
3562 // Unicode: 042B 30AB 200AB 204AB
3563 // UTF-16: 042B 30AB D840 DCAB D841 DCAB
3564 // UTF-8: D0 AB E3 82 AB F0 A0 82 AB F0 A0 92 AB
3565 "[\\u042B{\\u042B\\u30AB}{\\u042B\\u30AB\\U000200AB}{\\U000200AB\\U000204AB}]",
3567 "\\u042B\\U000200AB\\U000204AB\\u042B\\u30AB\\U000200AB\\U000204AB\\u042B\\u30AB\\U000200AB\\U000200AB\\U000204AB",
3569 "[\\U000204AB{\\U000200AB\\U000204AB}{\\u30AB\\U000200AB\\U000204AB}{\\u042B\\u30AB}]",
3571 "\\u042B\\u30AB\\u30AB\\U000200AB\\U000204AB\\u042B\\u30AB\\U000200AB\\U000204AB\\u042B\\u30AB\\U000204AB",
3573 // Stress bookkeeping and recursion.
3574 // The following strings are barely doable with the recursive
3575 // reference implementation.
3576 // The not-contained character at the end prevents an early exit from the span().
3580 "bbbbbbbbbbbbbbbbbbbbbbbb-",
3581 // On complement sets, span() and spanBack() get different results
3582 // because b is not in the complement set and there is an odd number of b's
3583 // in the test string.
3585 "bbbbbbbbbbbbbbbbbbbbbbbbb-",
3587 // Test with set strings with an initial or final code point span
3589 "[a{" _64_a _64_a _64_a _64_a "b}"
3590 "{a" _64_b _64_b _64_b _64_b "}]",
3592 _64_a _64_a _64_a _63_a "b",
3593 _64_a _64_a _64_a _64_a "b",
3594 _64_a _64_a _64_a _64_a "aaaabbbb",
3595 "a" _64_b _64_b _64_b _63_b,
3596 "a" _64_b _64_b _64_b _64_b,
3597 "aaaabbbb" _64_b _64_b _64_b _64_b,
3599 // Test with strings containing unpaired surrogates.
3600 // They are not representable in UTF-8, and a leading trail surrogate
3601 // and a trailing lead surrogate must not match in the middle of a proper surrogate pair.
3602 // U+20001 == \\uD840\\uDC01
3603 // U+20400 == \\uD841\\uDC00
3604 "[a\\U00020001\\U00020400{ab}{b\\uD840}{\\uDC00a}]",
3606 "aaab\\U00020001ba\\U00020400aba\\uD840ab\\uD840\\U00020000b\\U00020000a\\U00020000\\uDC00a\\uDC00babbb"
3608 uint32_t whichSpans[96]={ SPAN_ALL };
3609 int32_t whichSpansCount=1;
3611 UnicodeSet *sets[SET_COUNT]={ NULL };
3612 const UnicodeSetWithStrings *sets_with_str[SET_COUNT]={ NULL };
3614 char testName[1024];
3615 char *testNameLimit=testName;
3618 for(i=0; i<LENGTHOF(testdata); ++i) {
3619 const char *s=testdata[i];
3621 // Create new test sets from this pattern.
3622 for(j=0; j<SET_COUNT; ++j) {
3623 delete sets_with_str[j];
3626 UErrorCode errorCode=U_ZERO_ERROR;
3627 sets[SLOW]=new UnicodeSet(UnicodeString(s, -1, US_INV).unescape(), errorCode);
3628 if(U_FAILURE(errorCode)) {
3629 dataerrln("FAIL: Unable to create UnicodeSet(%s) - %s", s, u_errorName(errorCode));
3632 sets[SLOW_NOT]=new UnicodeSet(*sets[SLOW]);
3633 sets[SLOW_NOT]->complement();
3634 // Intermediate set: Test cloning of a frozen set.
3635 UnicodeSet *fast=new UnicodeSet(*sets[SLOW]);
3637 sets[FAST]=(UnicodeSet *)fast->clone();
3639 UnicodeSet *fastNot=new UnicodeSet(*sets[SLOW_NOT]);
3641 sets[FAST_NOT]=(UnicodeSet *)fastNot->clone();
3644 for(j=0; j<SET_COUNT; ++j) {
3645 sets_with_str[j]=new UnicodeSetWithStrings(*sets[j]);
3648 strcpy(testName, s);
3649 testNameLimit=strchr(testName, 0);
3650 *testNameLimit++=':';
3653 whichSpans[0]=SPAN_ALL;
3655 } else if(s[0]=='-') {
3656 whichSpans[0]=SPAN_ALL;
3662 whichSpansCount=addAlternative(whichSpans, whichSpansCount,
3669 whichSpansCount=addAlternative(whichSpans, whichSpansCount,
3676 // test USET_SPAN_CONTAINED FWD & BACK, and separately
3677 // USET_SPAN_SIMPLE only FWD, and separately
3678 // USET_SPAN_SIMPLE only BACK
3679 whichSpansCount=addAlternative(whichSpans, whichSpansCount,
3680 ~(SPAN_DIRS|SPAN_CONDITION),
3681 SPAN_DIRS|SPAN_CONTAINED,
3682 SPAN_FWD|SPAN_SIMPLE,
3683 SPAN_BACK|SPAN_SIMPLE);
3686 whichSpansCount=addAlternative(whichSpans, whichSpansCount,
3693 errln("FAIL: unrecognized span set option in \"%s\"", testdata[i]);
3697 } else if(0==strcmp(s, "*")) {
3698 strcpy(testNameLimit, "bad_string");
3699 for(j=0; j<whichSpansCount; ++j) {
3700 if(whichSpansCount>1) {
3701 sprintf(testNameLimit+10 /* strlen("bad_string") */,
3705 testSpanUTF16String(sets_with_str, whichSpans[j], testName);
3706 testSpanUTF8String(sets_with_str, whichSpans[j], testName);
3709 strcpy(testNameLimit, "contents");
3710 for(j=0; j<whichSpansCount; ++j) {
3711 if(whichSpansCount>1) {
3712 sprintf(testNameLimit+8 /* strlen("contents") */,
3716 testSpanContents(sets_with_str, whichSpans[j], testName);
3719 UnicodeString string=UnicodeString(s, -1, US_INV).unescape();
3720 strcpy(testNameLimit, "test_string");
3721 for(j=0; j<whichSpansCount; ++j) {
3722 if(whichSpansCount>1) {
3723 sprintf(testNameLimit+11 /* strlen("test_string") */,
3727 testSpanBothUTFs(sets_with_str, string.getBuffer(), string.length(), whichSpans[j], testName, i);
3731 for(j=0; j<SET_COUNT; ++j) {
3732 delete sets_with_str[j];
3737 // Test select patterns and strings, and test USET_SPAN_SIMPLE.
3738 void UnicodeSetTest::TestStringSpan() {
3739 static const char *pattern="[x{xy}{xya}{axy}{ax}]";
3740 static const char *const string=
3742 "xyaxyaxyaxyaxyaxyaxyaxyaxyaxyaxyaxyaxyaxyaxyaxyaxyaxyaxyaxyaxya"
3744 "xyaxyaxyaxyaxyaxyaxyaxyaxyaxyaxyaxyaxyaxyaxyaxyaxyaxyaxyaxyaxya"
3746 "xyaxyaxyaxyaxyaxyaxyaxyaxyaxyaxyaxyaxyaxyaxyaxyaxyaxyaxyaxyaxy"
3749 UErrorCode errorCode=U_ZERO_ERROR;
3750 UnicodeString pattern16=UnicodeString(pattern, -1, US_INV);
3751 UnicodeSet set(pattern16, errorCode);
3752 if(U_FAILURE(errorCode)) {
3753 errln("FAIL: Unable to create UnicodeSet(%s) - %s", pattern, u_errorName(errorCode));
3757 UnicodeString string16=UnicodeString(string, -1, US_INV).unescape();
3759 if(set.containsAll(string16)) {
3760 errln("FAIL: UnicodeSet(%s).containsAll(%s) should be FALSE", pattern, string);
3763 // Remove trailing "aaaa".
3764 string16.truncate(string16.length()-4);
3765 if(!set.containsAll(string16)) {
3766 errln("FAIL: UnicodeSet(%s).containsAll(%s[:-4]) should be TRUE", pattern, string);
3769 string16=UNICODE_STRING_SIMPLE("byayaxya");
3770 const UChar *s16=string16.getBuffer();
3771 int32_t length16=string16.length();
3772 (void)length16; // Suppress set but not used warning.
3773 if( set.span(s16, 8, USET_SPAN_NOT_CONTAINED)!=4 ||
3774 set.span(s16, 7, USET_SPAN_NOT_CONTAINED)!=4 ||
3775 set.span(s16, 6, USET_SPAN_NOT_CONTAINED)!=4 ||
3776 set.span(s16, 5, USET_SPAN_NOT_CONTAINED)!=5 ||
3777 set.span(s16, 4, USET_SPAN_NOT_CONTAINED)!=4 ||
3778 set.span(s16, 3, USET_SPAN_NOT_CONTAINED)!=3
3780 errln("FAIL: UnicodeSet(%s).span(while not) returns the wrong value", pattern);
3783 pattern="[a{ab}{abc}{cd}]";
3784 pattern16=UnicodeString(pattern, -1, US_INV);
3785 set.applyPattern(pattern16, errorCode);
3786 if(U_FAILURE(errorCode)) {
3787 errln("FAIL: Unable to create UnicodeSet(%s) - %s", pattern, u_errorName(errorCode));
3790 string16=UNICODE_STRING_SIMPLE("acdabcdabccd");
3791 s16=string16.getBuffer();
3792 length16=string16.length();
3793 if( set.span(s16, 12, USET_SPAN_CONTAINED)!=12 ||
3794 set.span(s16, 12, USET_SPAN_SIMPLE)!=6 ||
3795 set.span(s16+7, 5, USET_SPAN_SIMPLE)!=5
3797 errln("FAIL: UnicodeSet(%s).span(while longest match) returns the wrong value", pattern);
3800 pattern="[d{cd}{bcd}{ab}]";
3801 pattern16=UnicodeString(pattern, -1, US_INV);
3802 set.applyPattern(pattern16, errorCode).freeze();
3803 if(U_FAILURE(errorCode)) {
3804 errln("FAIL: Unable to create UnicodeSet(%s) - %s", pattern, u_errorName(errorCode));
3807 string16=UNICODE_STRING_SIMPLE("abbcdabcdabd");
3808 s16=string16.getBuffer();
3809 length16=string16.length();
3810 if( set.spanBack(s16, 12, USET_SPAN_CONTAINED)!=0 ||
3811 set.spanBack(s16, 12, USET_SPAN_SIMPLE)!=6 ||
3812 set.spanBack(s16, 5, USET_SPAN_SIMPLE)!=0
3814 errln("FAIL: UnicodeSet(%s).spanBack(while longest match) returns the wrong value", pattern);