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