• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // © 2016 and later: Unicode, Inc. and others.
2 // License & terms of use: http://www.unicode.org/copyright.html
3 /*
4 **********************************************************************
5 * Copyright (c) 2002-2016, International Business Machines
6 * Corporation and others.  All Rights Reserved.
7 **********************************************************************
8 */
9 #include "unicode/uset.h"
10 #include "unicode/ustring.h"
11 #include "cintltst.h"
12 #include "cmemory.h"
13 #include <stdlib.h>
14 #include <string.h>
15 
16 #define TEST(x) addTest(root, &x, "uset/" # x)
17 
18 static void TestAPI(void);
19 static void Testj2269(void);
20 static void TestSerialized(void);
21 static void TestNonInvariantPattern(void);
22 static void TestBadPattern(void);
23 static void TestFreezable(void);
24 static void TestSpan(void);
25 
26 void addUSetTest(TestNode** root);
27 
28 static void expect(const USet* set,
29                    const char* inList,
30                    const char* outList,
31                    UErrorCode* ec);
32 static void expectContainment(const USet* set,
33                               const char* list,
34                               UBool isIn);
35 static char oneUCharToChar(UChar32 c);
36 static void expectItems(const USet* set,
37                         const char* items);
38 
39 void
addUSetTest(TestNode ** root)40 addUSetTest(TestNode** root) {
41     TEST(TestAPI);
42     TEST(Testj2269);
43     TEST(TestSerialized);
44     TEST(TestNonInvariantPattern);
45     TEST(TestBadPattern);
46     TEST(TestFreezable);
47     TEST(TestSpan);
48 }
49 
50 /*------------------------------------------------------------------
51  * Tests
52  *------------------------------------------------------------------*/
53 
Testj2269()54 static void Testj2269() {
55   UErrorCode status = U_ZERO_ERROR;
56   UChar a[4] = { 0x61, 0x62, 0x63, 0 };
57   USet *s = uset_open(1, 0);
58   uset_addString(s, a, 3);
59   a[0] = 0x63; a[1] = 0x63;
60   expect(s, "{abc}", "{ccc}", &status);
61   uset_close(s);
62 }
63 
64 static const UChar PAT[] = {91,97,45,99,123,97,98,125,93,0}; /* "[a-c{ab}]" */
65 static const int32_t PAT_LEN = UPRV_LENGTHOF(PAT) - 1;
66 
67 static const UChar PAT_lb[] = {0x6C, 0x62, 0}; /* "lb" */
68 static const int32_t PAT_lb_LEN = UPRV_LENGTHOF(PAT_lb) - 1;
69 
70 static const UChar VAL_SP[] = {0x53, 0x50, 0}; /* "SP" */
71 static const int32_t VAL_SP_LEN = UPRV_LENGTHOF(VAL_SP) - 1;
72 
73 static const UChar STR_bc[] = {98,99,0}; /* "bc" */
74 static const int32_t STR_bc_LEN = UPRV_LENGTHOF(STR_bc) - 1;
75 
76 static const UChar STR_ab[] = {97,98,0}; /* "ab" */
77 static const int32_t STR_ab_LEN = UPRV_LENGTHOF(STR_ab) - 1;
78 
79 /**
80  * Basic API test for uset.x
81  */
TestAPI()82 static void TestAPI() {
83     USet* set;
84     USet* set2;
85     UErrorCode ec;
86 
87     /* [] */
88     set = uset_openEmpty();
89     expect(set, "", "abc{ab}", NULL);
90     uset_close(set);
91 
92     set = uset_open(1, 0);
93     expect(set, "", "abc{ab}", NULL);
94     uset_close(set);
95 
96     set = uset_open(1, 1);
97     uset_clear(set);
98     expect(set, "", "abc{ab}", NULL);
99     uset_close(set);
100 
101     /* [ABC] */
102     set = uset_open(0x0041, 0x0043);
103     expect(set, "ABC", "DEF{ab}", NULL);
104     uset_close(set);
105 
106     /* [a-c{ab}] */
107     ec = U_ZERO_ERROR;
108     set = uset_openPattern(PAT, PAT_LEN, &ec);
109     if(U_FAILURE(ec)) {
110         log_err("uset_openPattern([a-c{ab}]) failed - %s\n", u_errorName(ec));
111         return;
112     }
113     if(!uset_resemblesPattern(PAT, PAT_LEN, 0)) {
114         log_err("uset_resemblesPattern of PAT failed\n");
115     }
116     expect(set, "abc{ab}", "def{bc}", &ec);
117 
118     /* [a-d{ab}] */
119     uset_add(set, 0x64);
120     expect(set, "abcd{ab}", "ef{bc}", NULL);
121 
122     /* [acd{ab}{bc}] */
123     uset_remove(set, 0x62);
124     uset_addString(set, STR_bc, STR_bc_LEN);
125     expect(set, "acd{ab}{bc}", "bef{cd}", NULL);
126 
127     /* [acd{bc}] */
128     uset_removeString(set, STR_ab, STR_ab_LEN);
129     expect(set, "acd{bc}", "bfg{ab}", NULL);
130 
131     /* [^acd{bc}] */
132     uset_complement(set);
133     expect(set, "bef{bc}", "acd{ac}", NULL);
134 
135     /* [a-e{bc}] */
136     uset_complement(set);
137     uset_addRange(set, 0x0062, 0x0065);
138     expect(set, "abcde{bc}", "fg{ab}", NULL);
139 
140     /* [de{bc}] */
141     uset_removeRange(set, 0x0050, 0x0063);
142     expect(set, "de{bc}", "bcfg{ab}", NULL);
143 
144     /* [g-l] */
145     uset_set(set, 0x0067, 0x006C);
146     expect(set, "ghijkl", "de{bc}", NULL);
147 
148     if (uset_indexOf(set, 0x0067) != 0) {
149         log_err("uset_indexOf failed finding correct index of 'g'\n");
150     }
151 
152     if (uset_charAt(set, 0) != 0x0067) {
153         log_err("uset_charAt failed finding correct char 'g' at index 0\n");
154     }
155 
156     /* How to test this one...? */
157     uset_compact(set);
158 
159     /* [g-i] */
160     uset_retain(set, 0x0067, 0x0069);
161     expect(set, "ghi", "dejkl{bc}", NULL);
162 
163     /* UCHAR_ASCII_HEX_DIGIT */
164     uset_applyIntPropertyValue(set, UCHAR_ASCII_HEX_DIGIT, 1, &ec);
165     if(U_FAILURE(ec)) {
166         log_err("uset_applyIntPropertyValue([UCHAR_ASCII_HEX_DIGIT]) failed - %s\n", u_errorName(ec));
167         return;
168     }
169     expect(set, "0123456789ABCDEFabcdef", "GHIjkl{bc}", NULL);
170 
171     /* [ab] */
172     uset_clear(set);
173     uset_addAllCodePoints(set, STR_ab, STR_ab_LEN);
174     expect(set, "ab", "def{ab}", NULL);
175     if (uset_containsAllCodePoints(set, STR_bc, STR_bc_LEN)){
176         log_err("set should not conatin all characters of \"bc\" \n");
177     }
178 
179     /* [] */
180     set2 = uset_open(1, 1);
181     uset_clear(set2);
182 
183     /* space */
184     uset_applyPropertyAlias(set2, PAT_lb, PAT_lb_LEN, VAL_SP, VAL_SP_LEN, &ec);
185     expect(set2, " ", "abcdefghi{bc}", NULL);
186 
187     /* [a-c] */
188     uset_set(set2, 0x0061, 0x0063);
189     /* [g-i] */
190     uset_set(set, 0x0067, 0x0069);
191 
192     /* [a-c g-i] */
193     if (uset_containsSome(set, set2)) {
194         log_err("set should not contain some of set2 yet\n");
195     }
196     uset_complementAll(set, set2);
197     if (!uset_containsSome(set, set2)) {
198         log_err("set should contain some of set2\n");
199     }
200     expect(set, "abcghi", "def{bc}", NULL);
201 
202     /* [g-i] */
203     uset_removeAll(set, set2);
204     expect(set, "ghi", "abcdef{bc}", NULL);
205 
206     /* [a-c g-i] */
207     uset_addAll(set2, set);
208     expect(set2, "abcghi", "def{bc}", NULL);
209 
210     /* [g-i] */
211     uset_retainAll(set2, set);
212     expect(set2, "ghi", "abcdef{bc}", NULL);
213 
214     // ICU 69 added some missing functions for parity with C++ and Java.
215     uset_applyPattern(set, u"[abcdef{ch}{sch}]", -1, 0, &ec);
216     if(U_FAILURE(ec)) {
217         log_err("uset_openPattern([abcdef{ch}{sch}]) failed - %s\n", u_errorName(ec));
218         return;
219     }
220     expect(set, "abcdef{ch}{sch}", "", NULL);
221 
222     uset_removeAllCodePoints(set, u"ce", 2);
223     expect(set, "abdf{ch}{sch}", "ce", NULL);
224 
225     uset_complementRange(set, u'b', u'f');
226     expect(set, "ace{ch}{sch}", "bdf", NULL);
227 
228     uset_complementString(set, u"ch", -1);
229     expect(set, "ace{sch}", "bdf{ch}", NULL);
230 
231     uset_complementString(set, u"xy", -1);
232     expect(set, "ace{sch}{xy}", "bdf{ch}", NULL);
233 
234     uset_complementAllCodePoints(set, u"abef", 4);
235     expect(set, "bcf{sch}{xy}", "ade{ch}", NULL);
236 
237     uset_retainAllCodePoints(set, u"abef", -1);
238     expect(set, "bf", "acde{ch}{sch}{xy}", NULL);
239 
240     uset_applyPattern(set, u"[abcdef{ch}{sch}]", -1, 0, &ec);
241     if(U_FAILURE(ec)) {
242         log_err("uset_openPattern([abcdef{ch}{sch}]) failed - %s\n", u_errorName(ec));
243         return;
244     }
245     expect(set, "abcdef{ch}{sch}", "", NULL);
246 
247     uset_retainString(set, u"sch", 3);
248     expect(set, "{sch}", "abcdef{ch}", NULL);
249 
250     uset_retainString(set, u"ch", 3);
251     expect(set, "", "abcdef{ch}{sch}", NULL);
252 
253     uset_close(set);
254     uset_close(set2);
255 }
256 
257 /*------------------------------------------------------------------
258  * Support
259  *------------------------------------------------------------------*/
260 
261 /**
262  * Verifies that the given set contains the characters and strings in
263  * inList, and does not contain those in outList.  Also verifies that
264  * 'set' is not NULL and that 'ec' succeeds.
265  * @param set the set to test, or NULL (on error)
266  * @param inList list of set contents, in iteration order.  Format is
267  * list of individual strings, in iteration order, followed by sorted
268  * list of strings, delimited by {}.  This means we do not test
269  * characters '{' or '}' and we do not test strings containing those
270  * characters either.
271  * @param outList list of things not in the set.  Same format as
272  * inList.
273  * @param ec an error code, checked for success.  May be NULL in which
274  * case it is ignored.
275  */
expect(const USet * set,const char * inList,const char * outList,UErrorCode * ec)276 static void expect(const USet* set,
277                    const char* inList,
278                    const char* outList,
279                    UErrorCode* ec) {
280     if (ec!=NULL && U_FAILURE(*ec)) {
281         log_err("FAIL: %s\n", u_errorName(*ec));
282         return;
283     }
284     if (set == NULL) {
285         log_err("FAIL: USet is NULL\n");
286         return;
287     }
288     expectContainment(set, inList, TRUE);
289     expectContainment(set, outList, FALSE);
290     expectItems(set, inList);
291 }
292 
expectContainment(const USet * set,const char * list,UBool isIn)293 static void expectContainment(const USet* set,
294                               const char* list,
295                               UBool isIn) {
296     const char* p = list;
297     UChar ustr[4096];
298     char *pat;
299     UErrorCode ec;
300     int32_t rangeStart = -1, rangeEnd = -1, length;
301 
302     ec = U_ZERO_ERROR;
303     length = uset_toPattern(set, ustr, sizeof(ustr), TRUE, &ec);
304     if(U_FAILURE(ec)) {
305         log_err("FAIL: uset_toPattern() fails in expectContainment() - %s\n", u_errorName(ec));
306         return;
307     }
308     pat=aescstrdup(ustr, length);
309 
310     while (*p) {
311         if (*p=='{') {
312             const char* stringStart = ++p;
313             int32_t stringLength = 0;
314             char strCopy[64];
315 
316             while (*p++ != '}') {
317             }
318             stringLength = (int32_t)(p - stringStart - 1);
319             strncpy(strCopy, stringStart, stringLength);
320             strCopy[stringLength] = 0;
321 
322             u_charsToUChars(stringStart, ustr, stringLength);
323 
324             if (uset_containsString(set, ustr, stringLength) == isIn) {
325                 log_verbose("Ok: %s %s \"%s\"\n", pat,
326                             (isIn ? "contains" : "does not contain"),
327                             strCopy);
328             } else {
329                 log_data_err("FAIL: %s %s \"%s\" (Are you missing data?)\n", pat,
330                         (isIn ? "does not contain" : "contains"),
331                         strCopy);
332             }
333         }
334 
335         else {
336             UChar32 c;
337 
338             u_charsToUChars(p, ustr, 1);
339             c = ustr[0];
340 
341             if (uset_contains(set, c) == isIn) {
342                 log_verbose("Ok: %s %s '%c'\n", pat,
343                             (isIn ? "contains" : "does not contain"),
344                             *p);
345             } else {
346                 log_data_err("FAIL: %s %s '%c' (Are you missing data?)\n", pat,
347                         (isIn ? "does not contain" : "contains"),
348                         *p);
349             }
350 
351             /* Test the range API too by looking for ranges */
352             if (c == rangeEnd+1) {
353                 rangeEnd = c;
354             } else {
355                 if (rangeStart >= 0) {
356                     if (uset_containsRange(set, rangeStart, rangeEnd) == isIn) {
357                         log_verbose("Ok: %s %s U+%04X-U+%04X\n", pat,
358                                     (isIn ? "contains" : "does not contain"),
359                                     rangeStart, rangeEnd);
360                     } else {
361                         log_data_err("FAIL: %s %s U+%04X-U+%04X (Are you missing data?)\n", pat,
362                                 (isIn ? "does not contain" : "contains"),
363                                 rangeStart, rangeEnd);
364                     }
365                 }
366                 rangeStart = rangeEnd = c;
367             }
368 
369             ++p;
370         }
371     }
372 
373     if (rangeStart >= 0) {
374         if (uset_containsRange(set, rangeStart, rangeEnd) == isIn) {
375             log_verbose("Ok: %s %s U+%04X-U+%04X\n", pat,
376                         (isIn ? "contains" : "does not contain"),
377                         rangeStart, rangeEnd);
378         } else {
379             log_data_err("FAIL: %s %s U+%04X-U+%04X (Are you missing data?)\n", pat,
380                     (isIn ? "does not contain" : "contains"),
381                     rangeStart, rangeEnd);
382         }
383     }
384 }
385 
386 /* This only works for invariant BMP chars */
oneUCharToChar(UChar32 c)387 static char oneUCharToChar(UChar32 c) {
388     UChar ubuf[1];
389     char buf[1];
390     ubuf[0] = (UChar) c;
391     u_UCharsToChars(ubuf, buf, 1);
392     return buf[0];
393 }
394 
expectItems(const USet * set,const char * items)395 static void expectItems(const USet* set,
396                         const char* items) {
397     const char* p = items;
398     UChar ustr[4096], itemStr[4096];
399     char buf[4096];
400     char *pat;
401     UErrorCode ec;
402     int32_t expectedSize = 0;
403     int32_t itemCount = uset_getItemCount(set);
404     int32_t itemIndex = 0;
405     UChar32 start = 1, end = 0;
406     int32_t itemLen = 0, length;
407 
408     ec = U_ZERO_ERROR;
409     length = uset_toPattern(set, ustr, sizeof(ustr), TRUE, &ec);
410     if (U_FAILURE(ec)) {
411         log_err("FAIL: uset_toPattern => %s\n", u_errorName(ec));
412         return;
413     }
414     pat=aescstrdup(ustr, length);
415 
416     if (uset_isEmpty(set) != (strlen(items)==0)) {
417         log_data_err("FAIL: %s should return %s from isEmpty (Are you missing data?)\n",
418                 pat,
419                 strlen(items)==0 ? "TRUE" : "FALSE");
420     }
421 
422     /* Don't test patterns starting with "[^" */
423     if (u_strlen(ustr) > 2 && ustr[1] == 0x5e /*'^'*/) {
424         return;
425     }
426 
427     while (*p) {
428 
429         ++expectedSize;
430 
431         if (start > end || start == -1) {
432             /* Fetch our next item */
433             if (itemIndex >= itemCount) {
434                 log_data_err("FAIL: ran out of items iterating %s (Are you missing data?)\n", pat);
435                 return;
436             }
437 
438             itemLen = uset_getItem(set, itemIndex, &start, &end,
439                                    itemStr, sizeof(itemStr), &ec);
440             if (U_FAILURE(ec) || itemLen < 0) {
441                 log_err("FAIL: uset_getItem => %s\n", u_errorName(ec));
442                 return;
443             }
444 
445             if (itemLen == 0) {
446                 log_verbose("Ok: %s item %d is %c-%c\n", pat,
447                             itemIndex, oneUCharToChar(start),
448                             oneUCharToChar(end));
449             } else {
450                 itemStr[itemLen] = 0;
451                 u_UCharsToChars(itemStr, buf, itemLen+1);
452                 log_verbose("Ok: %s item %d is \"%s\"\n", pat, itemIndex, buf);
453             }
454 
455             ++itemIndex;
456         }
457 
458         if (*p=='{') {
459             const char* stringStart = ++p;
460             int32_t stringLength = 0;
461             char strCopy[64];
462 
463             while (*p++ != '}') {
464             }
465             stringLength = (int32_t)(p - stringStart - 1);
466             strncpy(strCopy, stringStart, stringLength);
467             strCopy[stringLength] = 0;
468 
469             u_charsToUChars(stringStart, ustr, stringLength);
470             ustr[stringLength] = 0;
471 
472             if (itemLen == 0) {
473                 log_err("FAIL: for %s expect \"%s\" next, but got a char\n",
474                         pat, strCopy);
475                 return;
476             }
477 
478             if (u_strcmp(ustr, itemStr) != 0) {
479                 log_err("FAIL: for %s expect \"%s\" next\n",
480                         pat, strCopy);
481                 return;
482             }
483         }
484 
485         else {
486             UChar32 c;
487 
488             u_charsToUChars(p, ustr, 1);
489             c = ustr[0];
490 
491             if (itemLen != 0) {
492                 log_err("FAIL: for %s expect '%c' next, but got a string\n",
493                         pat, *p);
494                 return;
495             }
496 
497             if (c != start++) {
498                 log_err("FAIL: for %s expect '%c' next\n",
499                         pat, *p);
500                 return;
501             }
502 
503             ++p;
504         }
505     }
506 
507     if (uset_size(set) == expectedSize) {
508         log_verbose("Ok: %s size is %d\n", pat, expectedSize);
509     } else {
510         log_err("FAIL: %s size is %d, expected %d\n",
511                 pat, uset_size(set), expectedSize);
512     }
513 }
514 
515 static void
TestSerialized()516 TestSerialized() {
517     uint16_t buffer[1000];
518     USerializedSet sset;
519     USet *set;
520     UErrorCode errorCode;
521     UChar32 c;
522     int32_t length;
523 
524     /* use a pattern that generates both BMP and supplementary code points */
525     U_STRING_DECL(pattern, "[:Cf:]", 6);
526     U_STRING_INIT(pattern, "[:Cf:]", 6);
527 
528     errorCode=U_ZERO_ERROR;
529     set=uset_openPattern(pattern, -1, &errorCode);
530     if(U_FAILURE(errorCode)) {
531         log_data_err("uset_openPattern([:Cf:]) failed - %s (Are you missing data?)\n", u_errorName(errorCode));
532         return;
533     }
534 
535     length=uset_serialize(set, buffer, UPRV_LENGTHOF(buffer), &errorCode);
536     if(U_FAILURE(errorCode)) {
537         log_err("unable to uset_serialize([:Cf:]) - %s\n", u_errorName(errorCode));
538         uset_close(set);
539         return;
540     }
541 
542     uset_getSerializedSet(&sset, buffer, length);
543     for(c=0; c<=0x10ffff; ++c) {
544         if(uset_contains(set, c)!=uset_serializedContains(&sset, c)) {
545             log_err("uset_contains(U+%04x)!=uset_serializedContains(U+%04x)\n", c);
546             break;
547         }
548     }
549 
550     uset_close(set);
551 }
552 
553 /**
554  * Make sure that when non-invariant chars are passed to uset_openPattern
555  * they do not cause an ugly failure mode (e.g. assertion failure).
556  * JB#3795.
557  */
558 static void
TestNonInvariantPattern()559 TestNonInvariantPattern() {
560     UErrorCode ec = U_ZERO_ERROR;
561     /* The critical part of this test is that the following pattern
562        must contain a non-invariant character. */
563     static const char *pattern = "[:ccc!=0:]";
564     UChar buf[256];
565     int32_t len = u_unescape(pattern, buf, 256);
566     /* This test 'fails' by having an assertion failure within the
567        following call.  It passes by running to completion with no
568        assertion failure. */
569     USet *set = uset_openPattern(buf, len, &ec);
570     uset_close(set);
571 }
572 
TestBadPattern(void)573 static void TestBadPattern(void) {
574     UErrorCode status = U_ZERO_ERROR;
575     USet *pat;
576     U_STRING_DECL(pattern, "[", 1);
577     U_STRING_INIT(pattern, "[", 1);
578     pat = uset_openPatternOptions(pattern, u_strlen(pattern), 0, &status);
579     if (pat != NULL || U_SUCCESS(status)) {
580         log_err("uset_openPatternOptions did not fail as expected %s\n", u_errorName(status));
581     }
582 }
583 
openIDSet()584 static USet *openIDSet() {
585     UErrorCode errorCode = U_ZERO_ERROR;
586     U_STRING_DECL(pattern, "[:ID_Continue:]", 15);
587     U_STRING_INIT(pattern, "[:ID_Continue:]", 15);
588     return uset_openPattern(pattern, 15, &errorCode);
589 }
590 
TestFreezable()591 static void TestFreezable() {
592     USet *idSet;
593     USet *frozen;
594     USet *thawed;
595 
596     idSet=openIDSet();
597 
598     if (idSet == NULL) {
599         log_data_err("openIDSet() returned NULL. (Are you missing data?)\n");
600         uset_close(idSet);
601         return;
602     }
603 
604     frozen=uset_clone(idSet);
605 
606     if (frozen == NULL) {
607         log_err("uset_Clone() returned NULL\n");
608         return;
609     }
610 
611     if(!uset_equals(frozen, idSet)) {
612         log_err("uset_clone() did not make an equal copy\n");
613     }
614 
615     uset_freeze(frozen);
616     uset_addRange(frozen, 0xd802, 0xd805);
617 
618     if(uset_isFrozen(idSet) || !uset_isFrozen(frozen) || !uset_equals(frozen, idSet)) {
619         log_err("uset_freeze() or uset_isFrozen() does not work\n");
620     }
621 
622     thawed=uset_cloneAsThawed(frozen);
623 
624     if (thawed == NULL) {
625         log_err("uset_cloneAsThawed(frozen) returned NULL");
626         uset_close(frozen);
627         uset_close(idSet);
628         return;
629     }
630 
631     uset_addRange(thawed, 0xd802, 0xd805);
632 
633     if(uset_isFrozen(thawed) || uset_equals(thawed, idSet) || !uset_containsRange(thawed, 0xd802, 0xd805)) {
634         log_err("uset_cloneAsThawed() does not work\n");
635     }
636 
637     uset_close(idSet);
638     uset_close(frozen);
639     uset_close(thawed);
640 }
641 
TestSpan()642 static void TestSpan() {
643     static const UChar s16[2]={ 0xe01, 0x3000 };
644     static const char* s8="\xE0\xB8\x81\xE3\x80\x80";
645 
646     USet *idSet=openIDSet();
647 
648     if (idSet == NULL) {
649         log_data_err("openIDSet() returned NULL (Are you missing data?)\n");
650         return;
651     }
652 
653     if(
654         1!=uset_span(idSet, s16, 2, USET_SPAN_CONTAINED) ||
655         0!=uset_span(idSet, s16, 2, USET_SPAN_NOT_CONTAINED) ||
656         2!=uset_spanBack(idSet, s16, 2, USET_SPAN_CONTAINED) ||
657         1!=uset_spanBack(idSet, s16, 2, USET_SPAN_NOT_CONTAINED)
658     ) {
659         log_err("uset_span() or uset_spanBack() does not work\n");
660     }
661 
662     if(
663         3!=uset_spanUTF8(idSet, s8, 6, USET_SPAN_CONTAINED) ||
664         0!=uset_spanUTF8(idSet, s8, 6, USET_SPAN_NOT_CONTAINED) ||
665         6!=uset_spanBackUTF8(idSet, s8, 6, USET_SPAN_CONTAINED) ||
666         3!=uset_spanBackUTF8(idSet, s8, 6, USET_SPAN_NOT_CONTAINED)
667     ) {
668         log_err("uset_spanUTF8() or uset_spanBackUTF8() does not work\n");
669     }
670 
671     uset_freeze(idSet);
672 
673     if(
674         1!=uset_span(idSet, s16, 2, USET_SPAN_CONTAINED) ||
675         0!=uset_span(idSet, s16, 2, USET_SPAN_NOT_CONTAINED) ||
676         2!=uset_spanBack(idSet, s16, 2, USET_SPAN_CONTAINED) ||
677         1!=uset_spanBack(idSet, s16, 2, USET_SPAN_NOT_CONTAINED)
678     ) {
679         log_err("uset_span(frozen) or uset_spanBack(frozen) does not work\n");
680     }
681 
682     if(
683         3!=uset_spanUTF8(idSet, s8, 6, USET_SPAN_CONTAINED) ||
684         0!=uset_spanUTF8(idSet, s8, 6, USET_SPAN_NOT_CONTAINED) ||
685         6!=uset_spanBackUTF8(idSet, s8, 6, USET_SPAN_CONTAINED) ||
686         3!=uset_spanBackUTF8(idSet, s8, 6, USET_SPAN_NOT_CONTAINED)
687     ) {
688         log_err("uset_spanUTF8(frozen) or uset_spanBackUTF8(frozen) does not work\n");
689     }
690 
691     uset_close(idSet);
692 }
693 
694 /*eof*/
695