Home | History | Annotate | Download | only in cintltst
      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*
    126 pseudoScript(const UChar *str) {
    127     return aescstrdup(str, -1);
    128 }
    129 #endif
    130 
    131 static void
    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
    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
    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
    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
    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
    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
    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