• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /********************************************************************
2  * © 2016 and later: Unicode, Inc. and others.
3  * License & terms of use: http://www.unicode.org/copyright.html
4  ********************************************************************/
5 /*   file name:  cbiditransformtst.c
6  *   encoding:   UTF-8
7  *   tab size:   8 (not used)
8  *   indentation:4
9  *
10  *   created on: 2016aug21
11  *   created by: Lina Kemmel
12 */
13 
14 #include "cintltst.h"
15 #include "unicode/ubidi.h"
16 #include "unicode/ubiditransform.h"
17 #include "unicode/ushape.h"
18 #include "unicode/ustring.h"
19 #include "unicode/utf16.h"
20 
21 #ifdef __cplusplus
22 extern "C" {
23 #endif
24 
25 #define     LATN_ZERO           0x0030
26 #define     ARAB_ZERO           0x0660
27 #define     MIN_HEB_LETTER      0x05D0
28 #define     MIN_ARAB_LETTER     0x0630 /* relevant to this test only */
29 #define     MIN_SHAPED_LETTER   0xFEAB /* relevant to this test only */
30 
31 #define     STR_CAPACITY        100
32 
33 #define     NUM_LETTERS         5       /* Used for arrays hereafter */
34 static const UChar unshapedLetters[NUM_LETTERS + 1] = {0x0630, 0, 0x0631, 0, 0x0632, 2};
35 static const UChar shapedLetters  [NUM_LETTERS + 1] = {0xfeab, 0, 0xfead, 0, 0xfeaf, 1};
36 
37 typedef struct {
38     UBiDiLevel  inLevel;
39     UBiDiOrder  inOr;
40     UBiDiLevel  outLevel;
41     UBiDiOrder  outOr;
42     const char  *pReorderNoMirror;
43     const char  *pReorderAndMirror;
44     const char  *pContextShapes;
45     const char  *pMessage;
46 } UBidiTestCases;
47 
48 UChar src[STR_CAPACITY] = { 0 };
49 UChar dest[STR_CAPACITY] = { 0 };
50 UChar expected[STR_CAPACITY] = { 0 };
51 UChar temp[STR_CAPACITY * 2] = { 0 };
52 char pseudo[STR_CAPACITY] = { 0 };
53 
54 void addBidiTransformTest(TestNode** root);
55 
56 static void testAutoDirection(void);
57 
58 static void testAllTransformOptions(void);
59 
60 static char* pseudoScript(const UChar *str);
61 
62 static void shapeDigits(UChar *str, UChar srcZero, UChar destZero);
63 
64 static void shapeLetters(UChar *str, const UChar *from, const UChar *to);
65 
66 static void logResultsForDir(const UChar *srcText, const UChar *destTxt,
67             const UChar *expectedTxt, UBiDiLevel inLevel, UBiDiLevel outLevel);
68 
69 static void verifyResultsForAllOpt(const UBidiTestCases *pTest, const UChar *srcTxt,
70             const UChar *destTxt, const char *expectedChars, uint32_t digits,
71             uint32_t letters);
72 
73 #if 0
74 static void substituteByPseudoChar(const UChar *src, char *dest,
75             const UChar baseReal, const char basePseudo, const char max);
76 
77 
78 /* TODO: This code assumes the codepage is ASCII based. */
79 
80 /*
81  * Using the following conventions:
82  * AL unshaped: A-E
83  * AL shaped: F-J
84  * R:  K-Z
85  * EN: 0-4
86  * AN: 5-9
87 */
88 static void
89 substituteByPseudoChar(const UChar *src, char *dest, const UChar baseReal,
90            const char basePseudo, const char max) {
91     *dest = basePseudo + (*src - baseReal); /* (range math won't work on EBCDIC) */
92     if (*dest > max) {
93         *dest = max;
94     }
95 }
96 
97 static char*
98 pseudoScript(const UChar *str) {
99     char *p = pseudo;
100     if (str) {
101         for (; *str; str++, p++) {
102             switch (u_charDirection(*str)) {
103                 case U_RIGHT_TO_LEFT:
104                     substituteByPseudoChar(str, p, MIN_HEB_LETTER, 'K', 'Z');
105                     break;
106                 case U_RIGHT_TO_LEFT_ARABIC:
107                     if (*str > 0xFE00) {
108                         substituteByPseudoChar(str, p, MIN_SHAPED_LETTER, 'F', 'J');
109                     } else {
110                         substituteByPseudoChar(str, p, MIN_ARAB_LETTER, 'A', 'E');
111                     }
112                     break;
113                 case U_ARABIC_NUMBER:
114                     substituteByPseudoChar(str, p, ARAB_ZERO, '5', '9');
115                     break;
116                 default:
117                     *p = (char)*str;
118                     break;
119             }
120         }
121     }
122     *p = '\0';
123     return pseudo;
124 }
125 #else
126 static char*
pseudoScript(const UChar * str)127 pseudoScript(const UChar *str) {
128     return aescstrdup(str, -1);
129 }
130 #endif
131 
132 static void
logResultsForDir(const UChar * srcTxt,const UChar * destTxt,const UChar * expectedTxt,UBiDiLevel inLevel,UBiDiLevel outLevel)133 logResultsForDir(const UChar *srcTxt, const UChar *destTxt, const UChar *expectedTxt,
134             UBiDiLevel inLevel, UBiDiLevel outLevel)
135 {
136     if (u_strcmp(expectedTxt, destTxt)) {
137         log_err("Unexpected transform Dest: inLevel: 0x%02x; outLevel: 0x%02x;\ninText: %s; outText: %s; expected: %s\n",
138                 inLevel, outLevel, pseudoScript(srcTxt), pseudoScript(destTxt), pseudoScript(expectedTxt));
139     }
140 }
141 
142 /**
143  * Tests various combinations of base directions, with the input either
144  * <code>UBIDI_DEFAULT_LTR</code> or <code>UBIDI_DEFAULT_RTL</code>, and the
145  * output either <code>UBIDI_LTR</code> or <code>UBIDI_RTL</code>. Order is
146  * always <code>UBIDI_LOGICAL</code> for the input and <code>UBIDI_VISUAL</code>
147  * for the output.
148  */
149 static void
testAutoDirection(void)150 testAutoDirection(void)
151 {
152     static const UBiDiLevel inLevels[] = {
153         UBIDI_DEFAULT_LTR, UBIDI_DEFAULT_RTL
154     };
155     static const UBiDiLevel outLevels[] = {
156         UBIDI_LTR, UBIDI_RTL
157     };
158     static const char *srcTexts[] = {
159         "abc \\u05d0\\u05d1",
160         "... abc \\u05d0\\u05d1",
161         "\\u05d0\\u05d1 abc",
162         "... \\u05d0\\u05d1 abc",
163         ".*:"
164     };
165     uint32_t nTexts = sizeof(srcTexts) / sizeof(srcTexts[0]);
166     uint32_t i, nInLevels = sizeof(inLevels) / sizeof(inLevels[0]);
167     uint32_t j, nOutLevels = sizeof(outLevels) / sizeof(outLevels[0]);
168 
169     UBiDi *pBidi = ubidi_open();
170 
171     UErrorCode errorCode = U_ZERO_ERROR;
172     UBiDiTransform *pTransform = ubiditransform_open(&errorCode);
173 
174     while (nTexts-- > 0) {
175         uint32_t srcLen;
176         u_unescape(srcTexts[nTexts], src, STR_CAPACITY);
177         srcLen = u_strlen(src);
178         for (i = 0; i < nInLevels; i++) {
179             for (j = 0; j < nOutLevels; j++) {
180                 ubiditransform_transform(pTransform, src, -1, dest, STR_CAPACITY - 1,
181                         inLevels[i], UBIDI_LOGICAL, outLevels[j], UBIDI_VISUAL,
182                         UBIDI_MIRRORING_OFF, 0, &errorCode);
183                 /* Use UBiDi as a model we compare to */
184                 ubidi_setPara(pBidi, src, srcLen, inLevels[i], NULL, &errorCode);
185                 ubidi_writeReordered(pBidi, expected, STR_CAPACITY, UBIDI_REORDER_DEFAULT, &errorCode);
186                 if (outLevels[j] == UBIDI_RTL) {
187                     ubidi_writeReverse(expected, u_strlen(expected), temp, STR_CAPACITY,
188                             UBIDI_OUTPUT_REVERSE, &errorCode);
189                     logResultsForDir(src, dest, temp, inLevels[i], outLevels[j]);
190                 } else {
191                     logResultsForDir(src, dest, expected, inLevels[i], outLevels[j]);
192                 }
193             }
194         }
195     }
196     ubidi_close(pBidi);
197     ubiditransform_close(pTransform);
198 }
199 
200 static void
shapeDigits(UChar * str,UChar srcZero,UChar destZero)201 shapeDigits(UChar *str, UChar srcZero, UChar destZero)
202 {
203     UChar32 c = 0;
204     uint32_t i = 0, j, length = u_strlen(str);
205     while (i < length) {
206         j = i;
207         U16_NEXT(str, i, length, c);
208         if (c >= srcZero && c <= srcZero + 9) {
209             /* length of c here is always a single UChar16 */
210             str[j] = c + (destZero - srcZero);
211         }
212     }
213 }
214 
215 static void
shapeLetters(UChar * str,const UChar * from,const UChar * to)216 shapeLetters(UChar *str, const UChar *from, const UChar *to)
217 {
218     uint32_t i = 0, j, length = u_strlen(expected), index;
219     UChar32 c = 0;
220     while (i < length) {
221         j = i;
222         U16_NEXT(str, i, length, c);
223         index = c - from[0];
224         if (index < NUM_LETTERS && from[index * from[NUM_LETTERS]] != 0) {
225             /* The length of old and new values is always a single UChar16,
226                so can just assign a new value to str[j] */
227             str[j] = to[index * from[NUM_LETTERS]];
228         }
229     }
230 }
231 
232 static void
verifyResultsForAllOpt(const UBidiTestCases * pTest,const UChar * srcTxt,const UChar * destTxt,const char * expectedChars,uint32_t digits,uint32_t letters)233 verifyResultsForAllOpt(const UBidiTestCases *pTest, const UChar *srcTxt,
234         const UChar *destTxt, const char *expectedChars, uint32_t digits, uint32_t letters)
235 {
236     u_unescape(expectedChars, expected, STR_CAPACITY);
237 
238     switch (digits) {
239         case U_SHAPE_DIGITS_EN2AN:
240             shapeDigits(expected, LATN_ZERO, ARAB_ZERO);
241             break;
242         case U_SHAPE_DIGITS_AN2EN:
243             shapeDigits(expected, ARAB_ZERO, LATN_ZERO);
244             break;
245         default:
246             break;
247     }
248     switch (letters) {
249         case U_SHAPE_LETTERS_SHAPE:
250             shapeLetters(expected, unshapedLetters, shapedLetters);
251             break;
252         case U_SHAPE_LETTERS_UNSHAPE:
253             shapeLetters(expected, shapedLetters, unshapedLetters);
254             break;
255     }
256     if (u_strcmp(expected, dest)) {
257         log_err("Unexpected transform Dest: Test: %s; Digits: 0x%08x; Letters: 0x%08x\ninText: %s; outText: %s; expected: %s\n",
258                 pTest->pMessage, digits, letters, pseudoScript(srcTxt), pseudoScript(destTxt), pseudoScript(expected));
259     }
260 }
261 
262 /**
263  * This function covers:
264  * <ul>
265  * <li>all possible combinations of ordering schemes and <strong>explicit</strong>
266  * base directions, applied to both input and output,</li>
267  * <li>selected tests for auto direction (systematically, auto direction is
268  * covered in a dedicated test) applied on both input and output,</li>
269  * <li>all possible combinations of mirroring, digits and letters applied
270  * to output only.</li>
271  * </ul>
272  */
273 static void
testAllTransformOptions(void)274 testAllTransformOptions(void)
275 {
276     static const char *inText =
277             "a[b]c \\u05d0(\\u05d1\\u05d2 \\u05d3)\\u05d4 1 d \\u0630 23\\u0660 e\\u06314 f \\ufeaf \\u0661\\u0662";
278 
279     static const UBidiTestCases testCases[] = {
280         { UBIDI_LTR, UBIDI_LOGICAL, UBIDI_LTR, UBIDI_LOGICAL,
281             "a[b]c \\u05d0(\\u05d1\\u05d2 \\u05d3)\\u05d4 1 d \\u0630 23\\u0660 e\\u06314 f \\ufeaf \\u0661\\u0662", // reordering no mirroring
282             "a[b]c \\u05d0)\\u05d1\\u05d2 \\u05d3(\\u05d4 1 d \\u0630 23\\u0660 e\\u06314 f \\ufeaf \\u0661\\u0662", // mirroring
283             "a[b]c \\u05d0(\\u05d1\\u05d2 \\u05d3)\\u05d4 1 d \\u0630 \\u0662\\u0663\\u0660 e\\u0631\\u0664 f \\ufeaf \\u0661\\u0662", // context numeric shaping
284             "1: Logical LTR ==> Logical LTR" },
285         { UBIDI_LTR, UBIDI_LOGICAL, UBIDI_LTR, UBIDI_VISUAL,
286             "a[b]c 1 \\u05d4)\\u05d3 \\u05d2\\u05d1(\\u05d0 d 23\\u0660 \\u0630 e4\\u0631 f \\u0661\\u0662 \\ufeaf",
287             "a[b]c 1 \\u05d4(\\u05d3 \\u05d2\\u05d1)\\u05d0 d 23\\u0660 \\u0630 e4\\u0631 f \\u0661\\u0662 \\ufeaf",
288             "a[b]c 1 \\u05d4)\\u05d3 \\u05d2\\u05d1(\\u05d0 d \\u0662\\u0663\\u0660 \\u0630 e\\u0664\\u0631 f \\u0661\\u0662 \\ufeaf",
289             "2: Logical LTR ==> Visual LTR" },
290         { UBIDI_LTR, UBIDI_LOGICAL, UBIDI_RTL, UBIDI_LOGICAL,
291             "\\ufeaf \\u0661\\u0662 f \\u0631e4 \\u0630 23\\u0660 d \\u05d0(\\u05d1\\u05d2 \\u05d3)\\u05d4 1 a[b]c",
292             "\\ufeaf \\u0661\\u0662 f \\u0631e4 \\u0630 23\\u0660 d \\u05d0)\\u05d1\\u05d2 \\u05d3(\\u05d4 1 a[b]c",
293             "\\ufeaf \\u0661\\u0662 f \\u0631e\\u0664 \\u0630 \\u0662\\u0663\\u0660 d \\u05d0(\\u05d1\\u05d2 \\u05d3)\\u05d4 1 a[b]c",
294             "3: Logical LTR ==> Logical RTL" },
295         { UBIDI_LTR, UBIDI_LOGICAL, UBIDI_RTL, UBIDI_VISUAL,
296             "\\ufeaf \\u0662\\u0661 f \\u06314e \\u0630 \\u066032 d \\u05d0(\\u05d1\\u05d2 \\u05d3)\\u05d4 1 c]b[a",
297             "\\ufeaf \\u0662\\u0661 f \\u06314e \\u0630 \\u066032 d \\u05d0)\\u05d1\\u05d2 \\u05d3(\\u05d4 1 c]b[a",
298             "\\ufeaf \\u0662\\u0661 f \\u0631\\u0664e \\u0630 \\u0660\\u0663\\u0662 d \\u05d0(\\u05d1\\u05d2 \\u05d3)\\u05d4 1 c]b[a",
299             "4: Logical LTR ==> Visual RTL" },
300         { UBIDI_RTL, UBIDI_LOGICAL, UBIDI_RTL, UBIDI_LOGICAL,
301             "a[b]c \\u05d0(\\u05d1\\u05d2 \\u05d3)\\u05d4 1 d \\u0630 23\\u0660 e\\u06314 f \\ufeaf \\u0661\\u0662",
302             "a[b]c \\u05d0)\\u05d1\\u05d2 \\u05d3(\\u05d4 1 d \\u0630 23\\u0660 e\\u06314 f \\ufeaf \\u0661\\u0662", // mirroring
303             "a[b]c \\u05d0(\\u05d1\\u05d2 \\u05d3)\\u05d4 1 d \\u0630 23\\u0660 e\\u06314 f \\ufeaf \\u0661\\u0662",
304             "5: Logical RTL ==> Logical RTL" },
305         { UBIDI_RTL, UBIDI_LOGICAL, UBIDI_RTL, UBIDI_VISUAL,
306             "c]b[a \\u05d0(\\u05d1\\u05d2 \\u05d3)\\u05d4 1 d \\u0630 \\u066032 e\\u06314 f \\ufeaf \\u0662\\u0661",
307             "c]b[a \\u05d0)\\u05d1\\u05d2 \\u05d3(\\u05d4 1 d \\u0630 \\u066032 e\\u06314 f \\ufeaf \\u0662\\u0661",
308             "c]b[a \\u05d0(\\u05d1\\u05d2 \\u05d3)\\u05d4 1 d \\u0630 \\u066032 e\\u06314 f \\ufeaf \\u0662\\u0661",
309             "6: Logical RTL ==> Visual RTL" },
310         { UBIDI_RTL, UBIDI_LOGICAL, UBIDI_LTR, UBIDI_LOGICAL,
311             "\\ufeaf \\u0661\\u0662 f 4\\u0631e 23\\u0630 \\u0660 d 1 \\u05d0(\\u05d1\\u05d2 \\u05d3)\\u05d4 a[b]c",
312             "\\ufeaf \\u0661\\u0662 f 4\\u0631e 23\\u0630 \\u0660 d 1 \\u05d0)\\u05d1\\u05d2 \\u05d3(\\u05d4 a[b]c",
313             "\\ufeaf \\u0661\\u0662 f 4\\u0631e 23\\u0630 \\u0660 d 1 \\u05d0(\\u05d1\\u05d2 \\u05d3)\\u05d4 a[b]c",
314             "7: Logical RTL ==> Logical LTR" },
315         { UBIDI_RTL, UBIDI_LOGICAL, UBIDI_LTR, UBIDI_VISUAL,
316             "\\u0661\\u0662 \\ufeaf f 4\\u0631e 23\\u0660 \\u0630 d 1 \\u05d4)\\u05d3 \\u05d2\\u05d1(\\u05d0 a[b]c",
317             "\\u0661\\u0662 \\ufeaf f 4\\u0631e 23\\u0660 \\u0630 d 1 \\u05d4(\\u05d3 \\u05d2\\u05d1)\\u05d0 a[b]c",
318             "\\u0661\\u0662 \\ufeaf f 4\\u0631e 23\\u0660 \\u0630 d 1 \\u05d4)\\u05d3 \\u05d2\\u05d1(\\u05d0 a[b]c",
319             "8: Logical RTL ==> Visual LTR" },
320         { UBIDI_LTR, UBIDI_VISUAL, UBIDI_LTR, UBIDI_VISUAL,
321             "a[b]c \\u05d0(\\u05d1\\u05d2 \\u05d3)\\u05d4 1 d \\u0630 23\\u0660 e\\u06314 f \\ufeaf \\u0661\\u0662",
322             "a[b]c \\u05d0)\\u05d1\\u05d2 \\u05d3(\\u05d4 1 d \\u0630 23\\u0660 e\\u06314 f \\ufeaf \\u0661\\u0662", // mirroring
323             "a[b]c \\u05d0(\\u05d1\\u05d2 \\u05d3)\\u05d4 1 d \\u0630 \\u0662\\u0663\\u0660 e\\u0631\\u0664 f \\ufeaf \\u0661\\u0662",
324             "9: Visual LTR ==> Visual LTR" },
325         { UBIDI_LTR, UBIDI_VISUAL, UBIDI_LTR, UBIDI_LOGICAL,
326             "a[b]c 1 \\u05d4)\\u05d3 \\u05d2\\u05d1(\\u05d0 d 23\\u0660 \\u0630 e4\\u0631 f \\u0661\\u0662 \\ufeaf",
327             "a[b]c 1 \\u05d4(\\u05d3 \\u05d2\\u05d1)\\u05d0 d 23\\u0660 \\u0630 e4\\u0631 f \\u0661\\u0662 \\ufeaf",
328             "a[b]c 1 \\u05d4)\\u05d3 \\u05d2\\u05d1(\\u05d0 d 23\\u0660 \\u0630 e4\\u0631 f \\u0661\\u0662 \\ufeaf",
329             "10: Visual LTR ==> Logical LTR" },
330         { UBIDI_LTR, UBIDI_VISUAL, UBIDI_RTL, UBIDI_VISUAL,
331             "\\u0662\\u0661 \\ufeaf f 4\\u0631e \\u066032 \\u0630 d 1 \\u05d4)\\u05d3 \\u05d2\\u05d1(\\u05d0 c]b[a",
332             "\\u0662\\u0661 \\ufeaf f 4\\u0631e \\u066032 \\u0630 d 1 \\u05d4(\\u05d3 \\u05d2\\u05d1)\\u05d0 c]b[a",
333             "\\u0662\\u0661 \\ufeaf f \\u0664\\u0631e \\u0660\\u0663\\u0662 \\u0630 d 1 \\u05d4)\\u05d3 \\u05d2\\u05d1(\\u05d0 c]b[a",
334             "11: Visual LTR ==> Visual RTL" },
335         { UBIDI_LTR, UBIDI_VISUAL, UBIDI_RTL, UBIDI_LOGICAL,
336             "\\u0661\\u0662 \\ufeaf f 4\\u0631e 23\\u0660 \\u0630 d 1 \\u05d4)\\u05d3 \\u05d2\\u05d1(\\u05d0 a[b]c",
337             "\\u0661\\u0662 \\ufeaf f 4\\u0631e 23\\u0660 \\u0630 d 1 \\u05d4(\\u05d3 \\u05d2\\u05d1)\\u05d0 a[b]c",
338             "\\u0661\\u0662 \\ufeaf f \\u0664\\u0631e \\u0662\\u0663\\u0660 \\u0630 d 1 \\u05d4)\\u05d3 \\u05d2\\u05d1(\\u05d0 a[b]c",
339             "12: Visual LTR ==> Logical RTL" },
340         { UBIDI_RTL, UBIDI_VISUAL, UBIDI_RTL, UBIDI_VISUAL,
341             "a[b]c \\u05d0(\\u05d1\\u05d2 \\u05d3)\\u05d4 1 d \\u0630 23\\u0660 e\\u06314 f \\ufeaf \\u0661\\u0662",
342             "a[b]c \\u05d0)\\u05d1\\u05d2 \\u05d3(\\u05d4 1 d \\u0630 23\\u0660 e\\u06314 f \\ufeaf \\u0661\\u0662",
343             "a[b]c \\u05d0(\\u05d1\\u05d2 \\u05d3)\\u05d4 1 d \\u0630 23\\u0660 e\\u06314 f \\ufeaf \\u0661\\u0662",
344             "13: Visual RTL ==> Visual RTL" },
345         { UBIDI_RTL, UBIDI_VISUAL, UBIDI_RTL, UBIDI_LOGICAL,
346             "c]b[a \\u05d0(\\u05d1\\u05d2 \\u05d3)\\u05d4 1 d \\u0630 \\u066032 e\\u06314 f \\ufeaf \\u0662\\u0661",
347             "c]b[a \\u05d0)\\u05d1\\u05d2 \\u05d3(\\u05d4 1 d \\u0630 \\u066032 e\\u06314 f \\ufeaf \\u0662\\u0661",
348             "c]b[a \\u05d0(\\u05d1\\u05d2 \\u05d3)\\u05d4 1 d \\u0630 \\u066032 e\\u06314 f \\ufeaf \\u0662\\u0661",
349             "14: Visual RTL ==> Logical RTL" },
350         { UBIDI_RTL, UBIDI_VISUAL, UBIDI_LTR, UBIDI_VISUAL,
351             "\\u0662\\u0661 \\ufeaf f 4\\u0631e \\u066032 \\u0630 d 1 \\u05d4)\\u05d3 \\u05d2\\u05d1(\\u05d0 c]b[a",
352             "\\u0662\\u0661 \\ufeaf f 4\\u0631e \\u066032 \\u0630 d 1 \\u05d4(\\u05d3 \\u05d2\\u05d1)\\u05d0 c]b[a",
353             "\\u0662\\u0661 \\ufeaf f 4\\u0631e \\u066032 \\u0630 d 1 \\u05d4)\\u05d3 \\u05d2\\u05d1(\\u05d0 c]b[a",
354             "15: Visual RTL ==> Visual LTR" },
355         { UBIDI_RTL, UBIDI_VISUAL, UBIDI_LTR, UBIDI_LOGICAL,
356             "\\ufeaf \\u0662\\u0661 f 4\\u0631e \\u066032 \\u0630 d 1 \\u05d0(\\u05d1\\u05d2 \\u05d3)\\u05d4 c]b[a",
357             "\\ufeaf \\u0662\\u0661 f 4\\u0631e \\u066032 \\u0630 d 1 \\u05d0)\\u05d1\\u05d2 \\u05d3(\\u05d4 c]b[a",
358             "\\ufeaf \\u0662\\u0661 f 4\\u0631e \\u066032 \\u0630 d 1 \\u05d0(\\u05d1\\u05d2 \\u05d3)\\u05d4 c]b[a",
359             "16: Visual RTL ==> Logical LTR" },
360         { UBIDI_DEFAULT_RTL, UBIDI_LOGICAL, UBIDI_LTR, UBIDI_VISUAL,
361             "a[b]c 1 \\u05d4)\\u05d3 \\u05d2\\u05d1(\\u05d0 d 23\\u0660 \\u0630 e4\\u0631 f \\u0661\\u0662 \\ufeaf",
362             "a[b]c 1 \\u05d4(\\u05d3 \\u05d2\\u05d1)\\u05d0 d 23\\u0660 \\u0630 e4\\u0631 f \\u0661\\u0662 \\ufeaf",
363             "a[b]c 1 \\u05d4)\\u05d3 \\u05d2\\u05d1(\\u05d0 d \\u0662\\u0663\\u0660 \\u0630 e\\u0664\\u0631 f \\u0661\\u0662 \\ufeaf",
364             "17: Logical DEFAULT_RTL ==> Visual LTR" },
365         { UBIDI_RTL, UBIDI_LOGICAL, UBIDI_DEFAULT_LTR, UBIDI_VISUAL,
366             "c]b[a \\u05d0(\\u05d1\\u05d2 \\u05d3)\\u05d4 1 d \\u0630 \\u066032 e\\u06314 f \\ufeaf \\u0662\\u0661",
367             "c]b[a \\u05d0)\\u05d1\\u05d2 \\u05d3(\\u05d4 1 d \\u0630 \\u066032 e\\u06314 f \\ufeaf \\u0662\\u0661",
368             "c]b[a \\u05d0(\\u05d1\\u05d2 \\u05d3)\\u05d4 1 d \\u0630 \\u066032 e\\u06314 f \\ufeaf \\u0662\\u0661",
369             "18: Logical RTL ==> Visual DEFAULT_LTR" },
370         { UBIDI_DEFAULT_LTR, UBIDI_LOGICAL, UBIDI_LTR, UBIDI_VISUAL,
371             "a[b]c 1 \\u05d4)\\u05d3 \\u05d2\\u05d1(\\u05d0 d 23\\u0660 \\u0630 e4\\u0631 f \\u0661\\u0662 \\ufeaf",
372             "a[b]c 1 \\u05d4(\\u05d3 \\u05d2\\u05d1)\\u05d0 d 23\\u0660 \\u0630 e4\\u0631 f \\u0661\\u0662 \\ufeaf",
373             "a[b]c 1 \\u05d4)\\u05d3 \\u05d2\\u05d1(\\u05d0 d \\u0662\\u0663\\u0660 \\u0630 e\\u0664\\u0631 f \\u0661\\u0662 \\ufeaf",
374             "19: Logical DEFAULT_LTR ==> Visual LTR" },
375         { UBIDI_RTL, UBIDI_LOGICAL, UBIDI_DEFAULT_RTL, UBIDI_VISUAL,
376             "c]b[a \\u05d0(\\u05d1\\u05d2 \\u05d3)\\u05d4 1 d \\u0630 \\u066032 e\\u06314 f \\ufeaf \\u0662\\u0661",
377             "c]b[a \\u05d0)\\u05d1\\u05d2 \\u05d3(\\u05d4 1 d \\u0630 \\u066032 e\\u06314 f \\ufeaf \\u0662\\u0661",
378             "c]b[a \\u05d0(\\u05d1\\u05d2 \\u05d3)\\u05d4 1 d \\u0630 \\u066032 e\\u06314 f \\ufeaf \\u0662\\u0661",
379             "20: Logical RTL ==> Visual DEFAULT_RTL" }
380     };
381     static const uint32_t digits[] = {
382         U_SHAPE_DIGITS_NOOP,
383         U_SHAPE_DIGITS_AN2EN,
384         U_SHAPE_DIGITS_EN2AN,
385         U_SHAPE_DIGITS_ALEN2AN_INIT_LR
386     };
387     static const uint32_t letters[] = {
388         U_SHAPE_LETTERS_UNSHAPE,
389         U_SHAPE_LETTERS_SHAPE
390     };
391     const char *expectedStr;
392     uint32_t i, nTestCases = sizeof(testCases) / sizeof(testCases[0]);
393     uint32_t j, nDigits = sizeof(digits) / sizeof(digits[0]);
394     uint32_t k, nLetters = sizeof(letters) / sizeof(letters[0]);
395 
396     UErrorCode errorCode = U_ZERO_ERROR;
397     UBiDiTransform *pTransform = ubiditransform_open(&errorCode);
398 
399     u_unescape(inText, src, STR_CAPACITY);
400 
401     // Test various combinations of base levels, orders, mirroring, digits and letters
402     for (i = 0; i < nTestCases; i++) {
403         expectedStr = testCases[i].pReorderAndMirror;
404         ubiditransform_transform(pTransform, src, -1, dest, STR_CAPACITY,
405                 testCases[i].inLevel, testCases[i].inOr,
406                 testCases[i].outLevel, testCases[i].outOr,
407                 UBIDI_MIRRORING_ON, 0, &errorCode);
408         verifyResultsForAllOpt(&testCases[i], src, dest, expectedStr, U_SHAPE_DIGITS_NOOP,
409                 U_SHAPE_LETTERS_NOOP);
410 
411         for (j = 0; j < nDigits; j++) {
412             expectedStr = digits[j] == U_SHAPE_DIGITS_ALEN2AN_INIT_LR ? testCases[i].pContextShapes
413                     : testCases[i].pReorderNoMirror;
414             for (k = 0; k < nLetters; k++) {
415                 /* Use here NULL for pTransform */
416                 ubiditransform_transform(NULL, src, -1, dest, STR_CAPACITY,
417                         testCases[i].inLevel, testCases[i].inOr,
418                         testCases[i].outLevel, testCases[i].outOr,
419                         UBIDI_MIRRORING_OFF, digits[j] | letters[k],
420                         &errorCode);
421                 verifyResultsForAllOpt(&testCases[i], src, dest, expectedStr, digits[j],
422                         letters[k]);
423             }
424         }
425     }
426     ubiditransform_close(pTransform);
427 }
428 
429 void
addBidiTransformTest(TestNode ** root)430 addBidiTransformTest(TestNode** root)
431 {
432     addTest(root, testAutoDirection, "complex/bidi-transform/TestAutoDirection");
433     addTest(root, testAllTransformOptions, "complex/bidi-transform/TestAllTransformOptions");
434 }
435 
436 #ifdef __cplusplus
437 }
438 #endif
439