itspoof.cpp revision 6d5deb12725f146643d443090dfa11b206df528a
1b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru/*
2b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru**********************************************************************
3b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru* Copyright (C) 2009, International Business Machines Corporation
4b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru* and others.  All Rights Reserved.
5b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru**********************************************************************
6b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru*/
7b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru/**
8b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru * IntlTestSpoof tests for USpoofDetector
9b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru */
10b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru
11b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru#include "unicode/utypes.h"
12b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru
13b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru#if !UCONFIG_NO_REGULAR_EXPRESSIONS
14b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru
15b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru#include "itspoof.h"
16b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru#include "unicode/uspoof.h"
17b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru
18b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru#define TEST_ASSERT_SUCCESS(status) {if (U_FAILURE(status)) { \
196d5deb12725f146643d443090dfa11b206df528aJean-Baptiste Queru    errcheckln(status, "Failure at file %s, line %d, error = %s", __FILE__, __LINE__, u_errorName(status));}}
20b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru
21b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru#define TEST_ASSERT(expr) {if ((expr)==FALSE) { \
22b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru    errln("Test Failure at file %s, line %d: \"%s\" is false.\n", __FILE__, __LINE__, #expr);};}
23b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru
24b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru#define TEST_ASSERT_EQ(a, b) { if ((a) != (b)) { \
25b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru    errln("Test Failure at file %s, line %d: \"%s\" (%d) != \"%s\" (%d) \n", \
26b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru             __FILE__, __LINE__, #a, (a), #b, (b)); }}
27b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru
28b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru#define TEST_ASSERT_NE(a, b) { if ((a) == (b)) { \
29b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru    errln("Test Failure at file %s, line %d: \"%s\" (%d) == \"%s\" (%d) \n", \
30b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru             __FILE__, __LINE__, #a, (a), #b, (b)); }}
31b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru
32b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru/*
33b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru *   TEST_SETUP and TEST_TEARDOWN
34b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru *         macros to handle the boilerplate around setting up test case.
35b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru *         Put arbitrary test code between SETUP and TEARDOWN.
36b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru *         "sc" is the ready-to-go  SpoofChecker for use in the tests.
37b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru */
38b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru#define TEST_SETUP {  \
39b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru    UErrorCode status = U_ZERO_ERROR; \
40b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru    USpoofChecker *sc;     \
41b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru    sc = uspoof_open(&status);  \
42b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru    TEST_ASSERT_SUCCESS(status);   \
43b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru    if (U_SUCCESS(status)){
44b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru
45b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru#define TEST_TEARDOWN  \
46b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru    }  \
47b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru    TEST_ASSERT_SUCCESS(status);  \
48b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru    uspoof_close(sc);  \
49b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru}
50b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru
51b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru
52b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru
53b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru
54b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queruvoid IntlTestSpoof::runIndexedTest( int32_t index, UBool exec, const char* &name, char* /*par*/ )
55b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru{
56b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru    if (exec) logln("TestSuite spoof: ");
57b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru    switch (index) {
58b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru        case 0:
59b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru            name = "TestSpoofAPI";
60b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru            if (exec) {
61b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru                testSpoofAPI();
62b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru            }
63b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru            break;
64b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru         case 1:
65b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru            name = "TestSkeleton";
66b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru            if (exec) {
67b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru                testSkeleton();
68b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru            }
69b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru            break;
70b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru         case 2:
71b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru            name = "TestAreConfusable";
72b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru            if (exec) {
73b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru                testAreConfusable();
74b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru            }
75b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru            break;
76b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru          case 3:
77b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru            name = "TestInvisible";
78b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru            if (exec) {
79b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru                testInvisible();
80b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru            }
81b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru            break;
82b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru        default: name=""; break;
83b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru    }
84b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru}
85b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru
86b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queruvoid IntlTestSpoof::testSpoofAPI() {
87b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru
88b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru    TEST_SETUP
89b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru        UnicodeString s("uvw");
90b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru        int32_t position = 666;
91b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru        int32_t checkResults = uspoof_checkUnicodeString(sc, s, &position, &status);
92b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru        TEST_ASSERT_SUCCESS(status);
93b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru        TEST_ASSERT_EQ(0, checkResults);
94b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru        TEST_ASSERT_EQ(666, position);
95b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru    TEST_TEARDOWN;
96b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru
97b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru    TEST_SETUP
98b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru        UnicodeString s1("cxs");
99b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru        UnicodeString s2 = UnicodeString("\\u0441\\u0445\\u0455").unescape();  // Cyrillic "cxs"
100b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru        int32_t checkResults = uspoof_areConfusableUnicodeString(sc, s1, s2, &status);
101b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru        TEST_ASSERT_EQ(USPOOF_MIXED_SCRIPT_CONFUSABLE | USPOOF_WHOLE_SCRIPT_CONFUSABLE, checkResults);
102b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru
103b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru    TEST_TEARDOWN;
104b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru
105b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru    TEST_SETUP
106b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru        UnicodeString s("I1l0O");
107b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru        UnicodeString dest;
108b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru        UnicodeString &retStr = uspoof_getSkeletonUnicodeString(sc, USPOOF_ANY_CASE, s, dest, &status);
109b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru        TEST_ASSERT_SUCCESS(status);
110b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru        TEST_ASSERT(UnicodeString("11100") == dest);
111b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru        TEST_ASSERT(&dest == &retStr);
112b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru    TEST_TEARDOWN;
113b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru}
114b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru
115b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru
116b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru#define CHECK_SKELETON(type, input, expected) { \
117b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru    checkSkeleton(sc, type, input, expected, __LINE__); \
118b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru    }
119b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru
120b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru
121b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru// testSkeleton.   Spot check a number of confusable skeleton substitutions from the
122b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru//                 Unicode data file confusables.txt
123b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru//                 Test cases chosen for substitutions of various lengths, and
124b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru//                 membership in different mapping tables.
125b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queruvoid IntlTestSpoof::testSkeleton() {
126b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru    const uint32_t ML = 0;
127b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru    const uint32_t SL = USPOOF_SINGLE_SCRIPT_CONFUSABLE;
128b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru    const uint32_t MA = USPOOF_ANY_CASE;
129b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru    const uint32_t SA = USPOOF_SINGLE_SCRIPT_CONFUSABLE | USPOOF_ANY_CASE;
130b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru
131b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru    TEST_SETUP
132b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru        // A long "identifier" that will overflow implementation stack buffers, forcing heap allocations.
133b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru        CHECK_SKELETON(SL, " A long 'identifier' that will overflow implementation stack buffers, forcing heap allocations."
134b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru                           " A long 'identifier' that will overflow implementation stack buffers, forcing heap allocations."
135b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru                           " A long 'identifier' that will overflow implementation stack buffers, forcing heap allocations."
136b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru                           " A long 'identifier' that will overflow implementation stack buffers, forcing heap allocations.",
137b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru
138b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru               " A 1ong \\u02b9identifier\\u02b9 that wi11 overf1ow imp1ementation stack buffers, forcing heap a11ocations."
139b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru               " A 1ong \\u02b9identifier\\u02b9 that wi11 overf1ow imp1ementation stack buffers, forcing heap a11ocations."
140b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru               " A 1ong \\u02b9identifier\\u02b9 that wi11 overf1ow imp1ementation stack buffers, forcing heap a11ocations."
141b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru               " A 1ong \\u02b9identifier\\u02b9 that wi11 overf1ow imp1ementation stack buffers, forcing heap a11ocations.")
142b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru
143b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru        // FC5F ;	FE74 0651 ;   ML  #* ARABIC LIGATURE SHADDA WITH KASRATAN ISOLATED FORM to
144b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru        //                                ARABIC KASRATAN ISOLATED FORM, ARABIC SHADDA
145b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru        //    This character NFKD normalizes to \u0020 \u064d \u0651, so its confusable mapping
146b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru        //    is never used in creating a skeleton.
147b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru        CHECK_SKELETON(SL, "\\uFC5F", " \\u064d\\u0651");
148b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru
149b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru        CHECK_SKELETON(SL, "nochange", "nochange");
150b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru        CHECK_SKELETON(MA, "love", "1ove");   // lower case l to digit 1
151b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru        CHECK_SKELETON(ML, "OOPS", "OOPS");
152b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru        CHECK_SKELETON(MA, "OOPS", "00PS");   // Letter O to digit 0 in any case mode only
153b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru        CHECK_SKELETON(SL, "\\u059c", "\\u0301");
154b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru        CHECK_SKELETON(SL, "\\u2A74", "\\u003A\\u003A\\u003D");
155b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru        CHECK_SKELETON(SL, "\\u247E", "\\u0028\\u0031\\u0031\\u0029");
156b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru        CHECK_SKELETON(SL, "\\uFDFB", "\\u062C\\u0644\\u0020\\u062C\\u0644\\u0627\\u0644\\u0647");
157b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru
158b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru        // This mapping exists in the ML and MA tables, does not exist in SL, SA
159b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru        //0C83 ;	0C03 ;	ML	# ( ಃ → ః ) KANNADA SIGN VISARGA → TELUGU SIGN VISARGA	# {source:513}
160b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru        CHECK_SKELETON(SL, "\\u0C83", "\\u0C83");
161b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru        CHECK_SKELETON(SA, "\\u0C83", "\\u0C83");
162b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru        CHECK_SKELETON(ML, "\\u0C83", "\\u0C03");
163b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru        CHECK_SKELETON(MA, "\\u0C83", "\\u0C03");
164b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru
165b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru        // 0391 ; 0041 ; MA # ( Α → A ) GREEK CAPITAL LETTER ALPHA to LATIN CAPITAL LETTER A
166b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru        // This mapping exists only in the MA table.
167b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru        CHECK_SKELETON(MA, "\\u0391", "A");
168b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru        CHECK_SKELETON(SA, "\\u0391", "\\u0391");
169b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru        CHECK_SKELETON(ML, "\\u0391", "\\u0391");
170b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru        CHECK_SKELETON(SL, "\\u0391", "\\u0391");
171b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru
172b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru        // 13CF ;  0062 ;  MA  #  CHEROKEE LETTER SI to LATIN SMALL LETTER B
173b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru        // This mapping exists in the ML and MA tables
174b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru        CHECK_SKELETON(ML, "\\u13CF", "b");
175b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru        CHECK_SKELETON(MA, "\\u13CF", "b");
176b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru        CHECK_SKELETON(SL, "\\u13CF", "\\u13CF");
177b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru        CHECK_SKELETON(SA, "\\u13CF", "\\u13CF");
178b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru
179b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru        // 0022 ;  02B9 02B9 ;  SA  #*  QUOTATION MARK to MODIFIER LETTER PRIME, MODIFIER LETTER PRIME
180b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru        // all tables.
181b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru        CHECK_SKELETON(SL, "\\u0022", "\\u02B9\\u02B9");
182b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru        CHECK_SKELETON(SA, "\\u0022", "\\u02B9\\u02B9");
183b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru        CHECK_SKELETON(ML, "\\u0022", "\\u02B9\\u02B9");
184b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru        CHECK_SKELETON(MA, "\\u0022", "\\u02B9\\u02B9");
185b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru
186b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru    TEST_TEARDOWN;
187b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru}
188b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru
189b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru
190b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru//
191b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru//  Run a single confusable skeleton transformation test case.
192b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru//
193b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queruvoid IntlTestSpoof::checkSkeleton(const USpoofChecker *sc, uint32_t type,
194b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru                                  const char *input, const char *expected, int32_t lineNum) {
195b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru    UnicodeString uInput = UnicodeString(input).unescape();
196b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru    UnicodeString uExpected = UnicodeString(expected).unescape();
197b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru
198b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru    UErrorCode status = U_ZERO_ERROR;
199b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru    UnicodeString actual;
200b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru    uspoof_getSkeletonUnicodeString(sc, type, uInput, actual, &status);
201b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru    if (U_FAILURE(status)) {
202b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru        errln("File %s, Line %d, Test case from line %d, status is %s", __FILE__, __LINE__, lineNum,
203b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru              u_errorName(status));
204b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru        return;
205b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru    }
206b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru    if (uExpected != actual) {
207b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru        errln("File %s, Line %d, Test case from line %d, Actual and Expected skeletons differ.",
208b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru               __FILE__, __LINE__, lineNum);
209b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru        errln(UnicodeString(" Actual   Skeleton: \"") + actual + UnicodeString("\"\n") +
210b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru              UnicodeString(" Expected Skeleton: \"") + uExpected + UnicodeString("\""));
211b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru    }
212b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru}
213b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru
214b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queruvoid IntlTestSpoof::testAreConfusable() {
215b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru    TEST_SETUP
216b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru        UnicodeString s1("A long string that will overflow stack buffers.  A long string that will overflow stack buffers. "
217b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru                         "A long string that will overflow stack buffers.  A long string that will overflow stack buffers. ");
218b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru        UnicodeString s2("A long string that wi11 overflow stack buffers.  A long string that will overflow stack buffers. "
219b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru                         "A long string that wi11 overflow stack buffers.  A long string that will overflow stack buffers. ");
220b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru        TEST_ASSERT_EQ(USPOOF_SINGLE_SCRIPT_CONFUSABLE, uspoof_areConfusableUnicodeString(sc, s1, s2, &status));
221b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru        TEST_ASSERT_SUCCESS(status);
222b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru
223b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru    TEST_TEARDOWN;
224b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru}
225b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru
226b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queruvoid IntlTestSpoof::testInvisible() {
227b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru    TEST_SETUP
228b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru        UnicodeString  s = UnicodeString("abcd\\u0301ef").unescape();
229b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru        int32_t position = -42;
230b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru        TEST_ASSERT_EQ(0, uspoof_checkUnicodeString(sc, s, &position, &status));
231b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru        TEST_ASSERT_SUCCESS(status);
232b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru        TEST_ASSERT(position == -42);
233b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru
234b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru        UnicodeString  s2 = UnicodeString("abcd\\u0301\\u0302\\u0301ef").unescape();
235b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru        TEST_ASSERT_EQ(USPOOF_INVISIBLE, uspoof_checkUnicodeString(sc, s2, &position, &status));
236b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru        TEST_ASSERT_SUCCESS(status);
237b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru        TEST_ASSERT_EQ(7, position);
238b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru
239b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru        // Tow acute accents, one from the composed a with acute accent, \u00e1,
240b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru        // and one separate.
241b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru        position = -42;
242b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru        UnicodeString  s3 = UnicodeString("abcd\\u00e1\\u0301xyz").unescape();
243b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru        TEST_ASSERT_EQ(USPOOF_INVISIBLE, uspoof_checkUnicodeString(sc, s3, &position, &status));
244b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru        TEST_ASSERT_SUCCESS(status);
245b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru        TEST_ASSERT_EQ(7, position);
246b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru    TEST_TEARDOWN;
247b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru}
248b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru#endif // UCONFIG_NO_REGULAR_EXPRESSIONS
249b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru
250