Home | History | Annotate | Download | only in cintltst
      1 /********************************************************************
      2  * COPYRIGHT:
      3  * Copyright (c) 1997-2014, International Business Machines Corporation and
      4  * others. All Rights Reserved.
      5  ********************************************************************/
      6 /*   file name:  cbiditst.c
      7 *   encoding:   US-ASCII
      8 *   tab size:   8 (not used)
      9 *   indentation:4
     10 *
     11 *   created on: 1999sep27
     12 *   created by: Markus W. Scherer, updated by Matitiahu Allouche
     13 */
     14 
     15 #include "cintltst.h"
     16 #include "unicode/utypes.h"
     17 #include "unicode/uchar.h"
     18 #include "unicode/ustring.h"
     19 #include "unicode/ubidi.h"
     20 #include "unicode/ushape.h"
     21 #include "cbiditst.h"
     22 #include "cstring.h"
     23 /* the following include is needed for sprintf */
     24 #include <stdio.h>
     25 
     26 #define MAXLEN      MAX_STRING_LENGTH
     27 
     28 /* prototypes ---------------------------------------------------------------*/
     29 
     30 void addComplexTest(TestNode** root);
     31 
     32 static void testCharFromDirProp(void);
     33 
     34 static void testBidi(void);
     35 
     36 static void doTests(UBiDi *pBiDi, UBiDi *pLine, UBool countRunsFirst);
     37 
     38 static void doMisc(void);
     39 
     40 static void doTest(UBiDi *pBiDi, int testNumber, const BiDiTestData *test,
     41                    int32_t lineStart, UBool countRunsFirst);
     42 
     43 static void _testReordering(UBiDi *pBiDi, int testNumber);
     44 
     45 static void testInverse(void);
     46 
     47 static void _testManyInverseBidi(UBiDi *pBiDi, UBiDiLevel direction);
     48 
     49 static void _testInverseBidi(UBiDi *pBiDi, const UChar *src, int32_t srcLength,
     50                              UBiDiLevel direction, UErrorCode *pErrorCode);
     51 
     52 static void _testWriteReverse(void);
     53 
     54 static void _testManyAddedPoints(void);
     55 
     56 static void _testMisc(void);
     57 
     58 static void doArabicShapingTest(void);
     59 
     60 static void doLamAlefSpecialVLTRArabicShapingTest(void);
     61 
     62 static void doTashkeelSpecialVLTRArabicShapingTest(void);
     63 
     64 static void doLOGICALArabicDeShapingTest(void);
     65 
     66 static void doArabicShapingTestForBug5421(void);
     67 
     68 static void doArabicShapingTestForBug8703(void);
     69 
     70 static void doArabicShapingTestForBug9024(void);
     71 
     72 static void _testPresentationForms(const UChar *in);
     73 
     74 static void doArabicShapingTestForNewCharacters(void);
     75 
     76 static void testReorder(void);
     77 
     78 static void testReorderArabicMathSymbols(void);
     79 
     80 static void testFailureRecovery(void);
     81 
     82 static void testMultipleParagraphs(void);
     83 
     84 static void testGetBaseDirection(void);
     85 
     86 static void testContext(void);
     87 
     88 static void doTailTest(void);
     89 
     90 static void testBracketOverflow(void);
     91 
     92 /* new BIDI API */
     93 static void testReorderingMode(void);
     94 static void testReorderRunsOnly(void);
     95 static void testStreaming(void);
     96 static void testClassOverride(void);
     97 static const char* inverseBasic(UBiDi *pBiDi, const char *src, int32_t srcLen,
     98                                 uint32_t option, UBiDiLevel level, char *result);
     99 static UBool assertRoundTrip(UBiDi *pBiDi, int32_t tc, int32_t outIndex,
    100                              const char *srcChars, const char *destChars,
    101                              const UChar *dest, int32_t destLen, int mode,
    102                              int option, UBiDiLevel level);
    103 static UBool checkResultLength(UBiDi *pBiDi, const char *srcChars,
    104                                const char *destChars,
    105                                int32_t destLen, const char *mode,
    106                                const char *option, UBiDiLevel level);
    107 static UBool checkMaps(UBiDi *pBiDi, int32_t stringIndex, const char *src,
    108                        const char *dest, const char *mode, const char* option,
    109                        UBiDiLevel level, UBool forward);
    110 
    111 /* helpers ------------------------------------------------------------------ */
    112 
    113 static const char *levelString="...............................................................";
    114 
    115 static void initCharFromDirProps(void);
    116 
    117 static UChar *
    118 getStringFromDirProps(const uint8_t *dirProps, int32_t length, UChar *buffer);
    119 
    120 static void printUnicode(const UChar *s, int32_t length, const UBiDiLevel *levels);
    121 
    122 /* regression tests ---------------------------------------------------------*/
    123 
    124 void
    125 addComplexTest(TestNode** root) {
    126     addTest(root, testCharFromDirProp, "complex/bidi/TestCharFromDirProp");
    127     addTest(root, testBidi, "complex/bidi/TestBidi");
    128     addTest(root, testInverse, "complex/bidi/TestInverse");
    129     addTest(root, testReorder,"complex/bidi/TestReorder");
    130     addTest(root, testFailureRecovery,"complex/bidi/TestFailureRecovery");
    131     addTest(root, testMultipleParagraphs,"complex/bidi/TestMultipleParagraphs");
    132     addTest(root, testReorderingMode, "complex/bidi/TestReorderingMode");
    133     addTest(root, testReorderRunsOnly, "complex/bidi/TestReorderRunsOnly");
    134     addTest(root, testStreaming, "complex/bidi/TestStreaming");
    135     addTest(root, testClassOverride, "complex/bidi/TestClassOverride");
    136     addTest(root, testGetBaseDirection, "complex/bidi/testGetBaseDirection");
    137     addTest(root, testContext, "complex/bidi/testContext");
    138     addTest(root, testBracketOverflow, "complex/bidi/TestBracketOverflow");
    139 
    140     addTest(root, doArabicShapingTest, "complex/arabic-shaping/ArabicShapingTest");
    141     addTest(root, doLamAlefSpecialVLTRArabicShapingTest, "complex/arabic-shaping/lamalef");
    142     addTest(root, doTashkeelSpecialVLTRArabicShapingTest, "complex/arabic-shaping/tashkeel");
    143     addTest(root, doLOGICALArabicDeShapingTest, "complex/arabic-shaping/unshaping");
    144     addTest(root, doArabicShapingTestForBug5421, "complex/arabic-shaping/bug-5421");
    145     addTest(root, doTailTest, "complex/arabic-shaping/tailtest");
    146     addTest(root, doArabicShapingTestForBug8703, "complex/arabic-shaping/bug-8703");
    147     addTest(root, testReorderArabicMathSymbols, "complex/bidi/bug-9024");
    148     addTest(root, doArabicShapingTestForBug9024, "complex/arabic-shaping/bug-9024");
    149     addTest(root, doArabicShapingTestForNewCharacters, "complex/arabic-shaping/shaping2");
    150 }
    151 
    152 static void
    153 testCharFromDirProp(void) {
    154     /* verify that the exemplar characters have the expected bidi classes */
    155     int32_t i;
    156 
    157     log_verbose("\nEntering TestCharFromDirProp\n\n");
    158     initCharFromDirProps();
    159 
    160     for(i=0; i<U_CHAR_DIRECTION_COUNT; ++i) {
    161         if(u_charDirection(charFromDirProp[i])!=(UCharDirection)i) {
    162             log_err("\nu_charDirection(charFromDirProp[%d]=U+%04x)==%d!=%d\n",
    163                     i, charFromDirProp[i], u_charDirection(charFromDirProp[i]), i);
    164         }
    165     }
    166     log_verbose("\nExiting TestCharFromDirProp\n\n");
    167 }
    168 
    169 static void
    170 testBidi(void) {
    171     UBiDi *pBiDi, *pLine=NULL;
    172     UErrorCode errorCode=U_ZERO_ERROR;
    173 
    174     log_verbose("\nEntering TestBidi\n\n");
    175 
    176     pBiDi=ubidi_openSized(MAXLEN, 0, &errorCode);
    177     if(pBiDi!=NULL) {
    178         pLine=ubidi_open();
    179         if(pLine!=NULL) {
    180             doTests(pBiDi, pLine, FALSE);
    181             doTests(pBiDi, pLine, TRUE);
    182         } else {
    183             log_err("ubidi_open() returned NULL, out of memory\n");
    184         }
    185     } else {
    186         log_err("ubidi_openSized() returned NULL, errorCode %s\n", myErrorName(errorCode));
    187     }
    188     doMisc();
    189 
    190     if(pLine!=NULL) {
    191         ubidi_close(pLine);
    192     }
    193     if(pBiDi!=NULL) {
    194         ubidi_close(pBiDi);
    195     }
    196 
    197     log_verbose("\nExiting TestBidi\n\n");
    198 }
    199 
    200 static void
    201 doTests(UBiDi *pBiDi, UBiDi *pLine, UBool countRunsFirst) {
    202     int testNumber;
    203     UChar string[MAXLEN];
    204     UErrorCode errorCode;
    205     int32_t lineStart;
    206     UBiDiLevel paraLevel;
    207 
    208     for(testNumber=0; testNumber<bidiTestCount; ++testNumber) {
    209         errorCode=U_ZERO_ERROR;
    210         getStringFromDirProps(tests[testNumber].text, tests[testNumber].length, string);
    211         paraLevel=tests[testNumber].paraLevel;
    212         ubidi_setPara(pBiDi, string, -1, paraLevel, NULL, &errorCode);
    213         if(U_SUCCESS(errorCode)) {
    214             log_verbose("ubidi_setPara(tests[%d], paraLevel %d) ok, direction %d paraLevel=%d\n",
    215                     testNumber, paraLevel, ubidi_getDirection(pBiDi), paraLevel);
    216             lineStart=tests[testNumber].lineStart;
    217             if(lineStart==-1) {
    218                 doTest(pBiDi, testNumber, tests+testNumber, 0, countRunsFirst);
    219             } else {
    220                 ubidi_setLine(pBiDi, lineStart, tests[testNumber].lineLimit, pLine, &errorCode);
    221                 if(U_SUCCESS(errorCode)) {
    222                     log_verbose("ubidi_setLine(%d, %d) ok, direction %d paraLevel=%d\n",
    223                             lineStart, tests[testNumber].lineLimit, ubidi_getDirection(pLine), ubidi_getParaLevel(pLine));
    224                     doTest(pLine, testNumber, tests+testNumber, lineStart, countRunsFirst);
    225                 } else {
    226                     log_err("ubidi_setLine(tests[%d], %d, %d) failed with errorCode %s\n",
    227                             testNumber, lineStart, tests[testNumber].lineLimit, myErrorName(errorCode));
    228                 }
    229             }
    230         } else {
    231             log_err("ubidi_setPara(tests[%d], paraLevel %d) failed with errorCode %s\n",
    232                     testNumber, paraLevel, myErrorName(errorCode));
    233         }
    234     }
    235 }
    236 
    237 static const char columns[] = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz";
    238 
    239 #define TABLE_SIZE  256
    240 static UBool   tablesInitialized = FALSE;
    241 static UChar   pseudoToUChar[TABLE_SIZE];
    242 static uint8_t UCharToPseudo[TABLE_SIZE];    /* used for Unicode chars < 0x0100 */
    243 static uint8_t UCharToPseud2[TABLE_SIZE];    /* used for Unicode chars >=0x0100 */
    244 
    245 static void buildPseudoTables(void)
    246 /*
    247     The rules for pseudo-Bidi are as follows:
    248     - [ == LRE
    249     - ] == RLE
    250     - { == LRO
    251     - } == RLO
    252     - ^ == PDF
    253     - @ == LRM
    254     - & == RLM
    255     - A-F == Arabic Letters 0631-0636
    256     - G-V == Hebrew letters 05d7-05e6
    257     - W-Z == Unassigned RTL 08d0-08d3
    258     - 0-5 == western digits 0030-0035
    259     - 6-9 == Arabic-Indic digits 0666-0669
    260     - ` == Combining Grave Accent 0300 (NSM)
    261     - ~ == Delete 007f (BN)
    262     - | == Paragraph Separator 2029 (B)
    263     - _ == Info Separator 1 001f (S)
    264     All other characters represent themselves as Latin-1, with the corresponding
    265     Bidi properties.
    266 */
    267 {
    268     int             i;
    269     UChar           uchar;
    270     uint8_t         c;
    271     /* initialize all tables to unknown */
    272     for (i=0; i < TABLE_SIZE; i++) {
    273         pseudoToUChar[i] = 0xFFFD;
    274         UCharToPseudo[i] = '?';
    275         UCharToPseud2[i] = '?';
    276     }
    277     /* initialize non letters or digits */
    278     pseudoToUChar[(uint8_t) 0 ] = 0x0000;    UCharToPseudo[0x00] = (uint8_t) 0 ;
    279     pseudoToUChar[(uint8_t)' '] = 0x0020;    UCharToPseudo[0x20] = (uint8_t)' ';
    280     pseudoToUChar[(uint8_t)'!'] = 0x0021;    UCharToPseudo[0x21] = (uint8_t)'!';
    281     pseudoToUChar[(uint8_t)'"'] = 0x0022;    UCharToPseudo[0x22] = (uint8_t)'"';
    282     pseudoToUChar[(uint8_t)'#'] = 0x0023;    UCharToPseudo[0x23] = (uint8_t)'#';
    283     pseudoToUChar[(uint8_t)'$'] = 0x0024;    UCharToPseudo[0x24] = (uint8_t)'$';
    284     pseudoToUChar[(uint8_t)'%'] = 0x0025;    UCharToPseudo[0x25] = (uint8_t)'%';
    285     pseudoToUChar[(uint8_t)'\'']= 0x0027;    UCharToPseudo[0x27] = (uint8_t)'\'';
    286     pseudoToUChar[(uint8_t)'('] = 0x0028;    UCharToPseudo[0x28] = (uint8_t)'(';
    287     pseudoToUChar[(uint8_t)')'] = 0x0029;    UCharToPseudo[0x29] = (uint8_t)')';
    288     pseudoToUChar[(uint8_t)'*'] = 0x002A;    UCharToPseudo[0x2A] = (uint8_t)'*';
    289     pseudoToUChar[(uint8_t)'+'] = 0x002B;    UCharToPseudo[0x2B] = (uint8_t)'+';
    290     pseudoToUChar[(uint8_t)','] = 0x002C;    UCharToPseudo[0x2C] = (uint8_t)',';
    291     pseudoToUChar[(uint8_t)'-'] = 0x002D;    UCharToPseudo[0x2D] = (uint8_t)'-';
    292     pseudoToUChar[(uint8_t)'.'] = 0x002E;    UCharToPseudo[0x2E] = (uint8_t)'.';
    293     pseudoToUChar[(uint8_t)'/'] = 0x002F;    UCharToPseudo[0x2F] = (uint8_t)'/';
    294     pseudoToUChar[(uint8_t)':'] = 0x003A;    UCharToPseudo[0x3A] = (uint8_t)':';
    295     pseudoToUChar[(uint8_t)';'] = 0x003B;    UCharToPseudo[0x3B] = (uint8_t)';';
    296     pseudoToUChar[(uint8_t)'<'] = 0x003C;    UCharToPseudo[0x3C] = (uint8_t)'<';
    297     pseudoToUChar[(uint8_t)'='] = 0x003D;    UCharToPseudo[0x3D] = (uint8_t)'=';
    298     pseudoToUChar[(uint8_t)'>'] = 0x003E;    UCharToPseudo[0x3E] = (uint8_t)'>';
    299     pseudoToUChar[(uint8_t)'?'] = 0x003F;    UCharToPseudo[0x3F] = (uint8_t)'?';
    300     pseudoToUChar[(uint8_t)'\\']= 0x005C;    UCharToPseudo[0x5C] = (uint8_t)'\\';
    301     /* initialize specially used characters */
    302     pseudoToUChar[(uint8_t)'`'] = 0x0300;    UCharToPseud2[0x00] = (uint8_t)'`';  /* NSM */
    303     pseudoToUChar[(uint8_t)'@'] = 0x200E;    UCharToPseud2[0x0E] = (uint8_t)'@';  /* LRM */
    304     pseudoToUChar[(uint8_t)'&'] = 0x200F;    UCharToPseud2[0x0F] = (uint8_t)'&';  /* RLM */
    305     pseudoToUChar[(uint8_t)'_'] = 0x001F;    UCharToPseudo[0x1F] = (uint8_t)'_';  /* S   */
    306     pseudoToUChar[(uint8_t)'|'] = 0x2029;    UCharToPseud2[0x29] = (uint8_t)'|';  /* B   */
    307     pseudoToUChar[(uint8_t)'['] = 0x202A;    UCharToPseud2[0x2A] = (uint8_t)'[';  /* LRE */
    308     pseudoToUChar[(uint8_t)']'] = 0x202B;    UCharToPseud2[0x2B] = (uint8_t)']';  /* RLE */
    309     pseudoToUChar[(uint8_t)'^'] = 0x202C;    UCharToPseud2[0x2C] = (uint8_t)'^';  /* PDF */
    310     pseudoToUChar[(uint8_t)'{'] = 0x202D;    UCharToPseud2[0x2D] = (uint8_t)'{';  /* LRO */
    311     pseudoToUChar[(uint8_t)'}'] = 0x202E;    UCharToPseud2[0x2E] = (uint8_t)'}';  /* RLO */
    312     pseudoToUChar[(uint8_t)'~'] = 0x007F;    UCharToPseudo[0x7F] = (uint8_t)'~';  /* BN  */
    313     /* initialize western digits */
    314     for (i = 0, uchar = 0x0030; i < 6; i++, uchar++) {
    315         c = (uint8_t)columns[i];
    316         pseudoToUChar[c] = uchar;
    317         UCharToPseudo[uchar & 0x00ff] = c;
    318     }
    319     /* initialize Hindi digits */
    320     for (i = 6, uchar = 0x0666; i < 10; i++, uchar++) {
    321         c = (uint8_t)columns[i];
    322         pseudoToUChar[c] = uchar;
    323         UCharToPseud2[uchar & 0x00ff] = c;
    324     }
    325     /* initialize Arabic letters */
    326     for (i = 10, uchar = 0x0631; i < 16; i++, uchar++) {
    327         c = (uint8_t)columns[i];
    328         pseudoToUChar[c] = uchar;
    329         UCharToPseud2[uchar & 0x00ff] = c;
    330     }
    331     /* initialize Hebrew letters */
    332     for (i = 16, uchar = 0x05D7; i < 32; i++, uchar++) {
    333         c = (uint8_t)columns[i];
    334         pseudoToUChar[c] = uchar;
    335         UCharToPseud2[uchar & 0x00ff] = c;
    336     }
    337     /* initialize Unassigned code points */
    338     for (i = 32, uchar=0x08D0; i < 36; i++, uchar++) {
    339         c = (uint8_t)columns[i];
    340         pseudoToUChar[c] = uchar;
    341         UCharToPseud2[uchar & 0x00ff] = c;
    342     }
    343     /* initialize Latin lower case letters */
    344     for (i = 36, uchar = 0x0061; i < 62; i++, uchar++) {
    345         c = (uint8_t)columns[i];
    346         pseudoToUChar[c] = uchar;
    347         UCharToPseudo[uchar & 0x00ff] = c;
    348     }
    349     tablesInitialized = TRUE;
    350 }
    351 
    352 /*----------------------------------------------------------------------*/
    353 
    354 static int pseudoToU16(const int length, const char * input, UChar * output)
    355 /*  This function converts a pseudo-Bidi string into a UChar string.
    356     It returns the length of the UChar string.
    357 */
    358 {
    359     int             i;
    360     if (!tablesInitialized) {
    361         buildPseudoTables();
    362     }
    363     for (i = 0; i < length; i++)
    364         output[i] = pseudoToUChar[(uint8_t)input[i]];
    365     output[length] = 0;
    366     return length;
    367 }
    368 
    369 /*----------------------------------------------------------------------*/
    370 
    371 static int u16ToPseudo(const int length, const UChar * input, char * output)
    372 /*  This function converts a UChar string into a pseudo-Bidi string.
    373     It returns the length of the pseudo-Bidi string.
    374 */
    375 {
    376     int             i;
    377     UChar           uchar;
    378     if (!tablesInitialized) {
    379         buildPseudoTables();
    380     }
    381     for (i = 0; i < length; i++)
    382     {
    383         uchar = input[i];
    384         output[i] = uchar < 0x0100 ? UCharToPseudo[uchar] :
    385                                         UCharToPseud2[uchar & 0x00ff];
    386     }
    387     output[length] = '\0';
    388     return length;
    389 }
    390 
    391 static char * formatLevels(UBiDi *bidi, char *buffer) {
    392     UErrorCode ec = U_ZERO_ERROR;
    393     const UBiDiLevel* gotLevels = ubidi_getLevels(bidi, &ec);
    394     int len = ubidi_getLength(bidi);
    395     char c;
    396     int i, k;
    397 
    398     if(U_FAILURE(ec)) {
    399         strcpy(buffer, "BAD LEVELS");
    400         return buffer;
    401     }
    402     for (i=0; i<len; i++) {
    403         k = gotLevels[i];
    404         if (k >= sizeof(columns))
    405             c = '+';
    406         else
    407             c = columns[k];
    408         buffer[i] = c;
    409     }
    410     buffer[len] = '\0';
    411     return buffer;
    412 }
    413 static const char *reorderingModeNames[] = {
    414     "UBIDI_REORDER_DEFAULT",
    415     "UBIDI_REORDER_NUMBERS_SPECIAL",
    416     "UBIDI_REORDER_GROUP_NUMBERS_WITH_R",
    417     "UBIDI_REORDER_RUNS_ONLY",
    418     "UBIDI_REORDER_INVERSE_NUMBERS_AS_L",
    419     "UBIDI_REORDER_INVERSE_LIKE_DIRECT",
    420     "UBIDI_REORDER_INVERSE_FOR_NUMBERS_SPECIAL"};
    421 
    422 static char *reorderingOptionNames(char *buffer, int options) {
    423     buffer[0] = 0;
    424     if (options & UBIDI_OPTION_INSERT_MARKS) {
    425         strcat(buffer, " UBIDI_OPTION_INSERT_MARKS");
    426     }
    427     if (options & UBIDI_OPTION_REMOVE_CONTROLS) {
    428         strcat(buffer, " UBIDI_OPTION_REMOVE_CONTROLS");
    429     }
    430     if (options & UBIDI_OPTION_STREAMING) {
    431         strcat(buffer, " UBIDI_OPTION_STREAMING");
    432     }
    433     return buffer;
    434 }
    435 
    436 static void printCaseInfo(UBiDi *bidi, const char *src, const char *dst)
    437 /* src and dst are char arrays encoded as pseudo Bidi */
    438 {
    439     /* Since calls to log_err with a \n within the pattern increment the
    440      * error count, new lines are issued via fputs, except when we want the
    441      * increment to happen.
    442      */
    443     UErrorCode errorCode=U_ZERO_ERROR;
    444     int32_t i, length = ubidi_getProcessedLength(bidi);
    445     const UBiDiLevel *levels;
    446     char levelChars[MAXLEN];
    447     UBiDiLevel lev;
    448     int32_t runCount;
    449     char buffer[100];
    450     log_err("========================================"); fputs("\n", stderr);
    451     levels = ubidi_getLevels(bidi, &errorCode);
    452     if (U_FAILURE(errorCode)) {
    453         strcpy(levelChars, "BAD LEVELS");
    454     } else {
    455         log_err("Processed length: %d", length); fputs("\n", stderr);
    456         for (i = 0; i < length; i++) {
    457             lev = levels[i];
    458             if (lev < sizeof(columns)) {
    459                 levelChars[i] = columns[lev];
    460             } else {
    461                 levelChars[i] = '+';
    462             }
    463         }
    464         levelChars[length] = 0;
    465     }
    466     log_err("Levels: %s", levelChars); fputs("\n", stderr);
    467     log_err("Source: %s", src); fputs("\n", stderr);
    468     log_err("Result: %s", dst); fputs("\n", stderr);
    469     log_err("Direction: %d", ubidi_getDirection(bidi)); fputs("\n", stderr);
    470     log_err("paraLevel: %d", ubidi_getParaLevel(bidi)); fputs("\n", stderr);
    471     i = ubidi_getReorderingMode(bidi);
    472     log_err("reorderingMode: %d = %s", i, reorderingModeNames[i]);
    473     fputs("\n", stderr);
    474     i = ubidi_getReorderingOptions(bidi);
    475     log_err("reorderingOptions: %d = %s", i, reorderingOptionNames(buffer, i));
    476     fputs("\n", stderr);
    477     runCount = ubidi_countRuns(bidi, &errorCode);
    478     if (U_FAILURE(errorCode)) {
    479         log_err( "BAD RUNS");
    480     } else {
    481         log_err("Runs: %d => logicalStart.length/level: ", runCount);
    482         for (i = 0; i < runCount; i++) {
    483             UBiDiDirection dir;
    484             int32_t start, len;
    485             dir = ubidi_getVisualRun(bidi, i, &start, &len);
    486             log_err(" %d.%d/%d", start, len, dir);
    487         }
    488     }
    489     fputs("\n", stderr);
    490 }
    491 
    492 static UBool matchingPair(UBiDi *bidi, int32_t i, char c1, char c2)
    493 {
    494     /* No test for []{} since they have special meaning for pseudo Bidi */
    495     static char mates1Chars[] = "<>()";
    496     static char mates2Chars[] = "><)(";
    497     UBiDiLevel level;
    498     int k, len;
    499 
    500     if (c1 == c2) {
    501         return TRUE;
    502     }
    503     /* For UBIDI_REORDER_RUNS_ONLY, it would not be correct to check levels[i],
    504        so we use the appropriate run's level, which is good for all cases.
    505      */
    506     ubidi_getLogicalRun(bidi, i, NULL, &level);
    507     if ((level & 1) == 0) {
    508         return FALSE;
    509     }
    510     len = strlen(mates1Chars);
    511     for (k = 0; k < len; k++) {
    512         if ((c1 == mates1Chars[k]) && (c2 == mates2Chars[k])) {
    513             return TRUE;
    514         }
    515     }
    516     return FALSE;
    517 }
    518 
    519 static UBool checkWhatYouCan(UBiDi *bidi, const char *srcChars, const char *dstChars)
    520 /* srcChars and dstChars are char arrays encoded as pseudo Bidi */
    521 {
    522     int32_t i, idx, logLimit, visLimit;
    523     UBool testOK, errMap, errDst;
    524     UErrorCode errorCode=U_ZERO_ERROR;
    525     int32_t visMap[MAXLEN];
    526     int32_t logMap[MAXLEN];
    527     char accumSrc[MAXLEN];
    528     char accumDst[MAXLEN];
    529     ubidi_getVisualMap(bidi, visMap, &errorCode);
    530     ubidi_getLogicalMap(bidi, logMap, &errorCode);
    531     if (U_FAILURE(errorCode)) {
    532         log_err("Error #1 invoking ICU within checkWhatYouCan\n");
    533         return FALSE;
    534     }
    535 
    536     testOK = TRUE;
    537     errMap = errDst = FALSE;
    538     logLimit = ubidi_getProcessedLength(bidi);
    539     visLimit = ubidi_getResultLength(bidi);
    540     memset(accumSrc, '?', logLimit);
    541     memset(accumDst, '?', visLimit);
    542 
    543     for (i = 0; i < logLimit; i++) {
    544         idx = ubidi_getVisualIndex(bidi, i, &errorCode);
    545         if (idx != logMap[i]) {
    546             errMap = TRUE;
    547         }
    548         if (idx == UBIDI_MAP_NOWHERE) {
    549             continue;
    550         }
    551         if (idx >= visLimit) {
    552             continue;
    553         }
    554         accumDst[idx] = srcChars[i];
    555         if (!matchingPair(bidi, i, srcChars[i], dstChars[idx])) {
    556             errDst = TRUE;
    557         }
    558     }
    559     accumDst[visLimit] = 0;
    560     if (U_FAILURE(errorCode)) {
    561         log_err("Error #2 invoking ICU within checkWhatYouCan\n");
    562         return FALSE;
    563     }
    564     if (errMap) {
    565         if (testOK) {
    566             printCaseInfo(bidi, srcChars, dstChars);
    567             testOK = FALSE;
    568         }
    569         log_err("Mismatch between getLogicalMap() and getVisualIndex()\n");
    570         log_err("Map    :");
    571         for (i = 0; i < logLimit; i++) {
    572             log_err(" %d", logMap[i]);
    573         }
    574         fputs("\n", stderr);
    575         log_err("Indexes:");
    576         for (i = 0; i < logLimit; i++) {
    577             log_err(" %d", ubidi_getVisualIndex(bidi, i, &errorCode));
    578         }
    579         fputs("\n", stderr);
    580     }
    581     if (errDst) {
    582         if (testOK) {
    583             printCaseInfo(bidi, srcChars, dstChars);
    584             testOK = FALSE;
    585         }
    586         log_err("Source does not map to Result\n");
    587         log_err("We got: %s", accumDst); fputs("\n", stderr);
    588     }
    589 
    590     errMap = errDst = FALSE;
    591     for (i = 0; i < visLimit; i++) {
    592         idx = ubidi_getLogicalIndex(bidi, i, &errorCode);
    593         if (idx != visMap[i]) {
    594             errMap = TRUE;
    595         }
    596         if (idx == UBIDI_MAP_NOWHERE) {
    597             continue;
    598         }
    599         if (idx >= logLimit) {
    600             continue;
    601         }
    602         accumSrc[idx] = dstChars[i];
    603         if (!matchingPair(bidi, idx, srcChars[idx], dstChars[i])) {
    604             errDst = TRUE;
    605         }
    606     }
    607     accumSrc[logLimit] = 0;
    608     if (U_FAILURE(errorCode)) {
    609         log_err("Error #3 invoking ICU within checkWhatYouCan\n");
    610         return FALSE;
    611     }
    612     if (errMap) {
    613         if (testOK) {
    614             printCaseInfo(bidi, srcChars, dstChars);
    615             testOK = FALSE;
    616         }
    617         log_err("Mismatch between getVisualMap() and getLogicalIndex()\n");
    618         log_err("Map    :");
    619         for (i = 0; i < visLimit; i++) {
    620             log_err(" %d", visMap[i]);
    621         }
    622         fputs("\n", stderr);
    623         log_err("Indexes:");
    624         for (i = 0; i < visLimit; i++) {
    625             log_err(" %d", ubidi_getLogicalIndex(bidi, i, &errorCode));
    626         }
    627         fputs("\n", stderr);
    628     }
    629     if (errDst) {
    630         if (testOK) {
    631             printCaseInfo(bidi, srcChars, dstChars);
    632             testOK = FALSE;
    633         }
    634         log_err("Result does not map to Source\n");
    635         log_err("We got: %s", accumSrc);
    636         fputs("\n", stderr);
    637     }
    638     return testOK;
    639 }
    640 
    641 static void
    642 testReorder(void) {
    643     static const char* const logicalOrder[] ={
    644             "del(KC)add(K.C.&)",
    645             "del(QDVT) add(BVDL)",
    646             "del(PQ)add(R.S.)T)U.&",
    647             "del(LV)add(L.V.) L.V.&",
    648             "day  0  R  DPDHRVR dayabbr",
    649             "day  1  H  DPHPDHDA dayabbr",
    650             "day  2   L  DPBLENDA dayabbr",
    651             "day  3  J  DPJQVM  dayabbr",
    652             "day  4   I  DPIQNF    dayabbr",
    653             "day  5  M  DPMEG  dayabbr",
    654             "helloDPMEG",
    655             "hello WXYZ"
    656     };
    657     static const char* const visualOrder[]={
    658             "del(CK)add(&.C.K)",
    659             "del(TVDQ) add(LDVB)",
    660             "del(QP)add(S.R.)&.U(T",            /* updated for Unicode 6.3 matching brackets */
    661             "del(VL)add(V.L.) &.V.L",           /* updated for Unicode 6.3 matching brackets */
    662             "day  0  RVRHDPD  R dayabbr",
    663             "day  1  ADHDPHPD  H dayabbr",
    664             "day  2   ADNELBPD  L dayabbr",
    665             "day  3  MVQJPD  J  dayabbr",
    666             "day  4   FNQIPD  I    dayabbr",
    667             "day  5  GEMPD  M  dayabbr",
    668             "helloGEMPD",
    669             "hello ZYXW"
    670     };
    671     static const char* const visualOrder1[]={
    672             ")K.C.&(dda)KC(led",
    673             ")BVDL(dda )QDVT(led",
    674             "T(U.&).R.S(dda)PQ(led",            /* updated for Unicode 6.3 matching brackets */
    675             "L.V.& ).L.V(dda)LV(led",           /* updated for Unicode 6.3 matching brackets */
    676             "rbbayad R  DPDHRVR  0  yad",
    677             "rbbayad H  DPHPDHDA  1  yad",
    678             "rbbayad L  DPBLENDA   2  yad",
    679             "rbbayad  J  DPJQVM  3  yad",
    680             "rbbayad    I  DPIQNF   4  yad",
    681             "rbbayad  M  DPMEG  5  yad",
    682             "DPMEGolleh",
    683             "WXYZ olleh"
    684     };
    685 
    686     static const char* const visualOrder2[]={
    687             "@)@K.C.&@(dda)@KC@(led",
    688             "@)@BVDL@(dda )@QDVT@(led",
    689             "R.S.)T)U.&@(dda)@PQ@(led",
    690             "L.V.) L.V.&@(dda)@LV@(led",
    691             "rbbayad @R  DPDHRVR@  0  yad",
    692             "rbbayad @H  DPHPDHDA@  1  yad",
    693             "rbbayad @L  DPBLENDA@   2  yad",
    694             "rbbayad  @J  DPJQVM@  3  yad",
    695             "rbbayad    @I  DPIQNF@   4  yad",
    696             "rbbayad  @M  DPMEG@  5  yad",
    697             "DPMEGolleh",
    698             "WXYZ@ olleh"
    699     };
    700     static const char* const visualOrder3[]={
    701             ")K.C.&(KC)dda(led",
    702             ")BVDL(ddaQDVT) (led",
    703             "R.S.)T)U.&(PQ)dda(led",
    704             "L.V.) L.V.&(LV)dda(led",
    705             "rbbayad DPDHRVR   R  0 yad",
    706             "rbbayad DPHPDHDA   H  1 yad",
    707             "rbbayad DPBLENDA     L 2 yad",
    708             "rbbayad  DPJQVM   J  3 yad",
    709             "rbbayad    DPIQNF     I 4 yad",
    710             "rbbayad  DPMEG   M  5 yad",
    711             "DPMEGolleh",
    712             "WXYZ olleh"
    713     };
    714     static const char* const visualOrder4[]={
    715             "del(add(CK(.C.K)",
    716             "del( (TVDQadd(LDVB)",
    717             "del(add(QP(.U(T(.S.R",
    718             "del(add(VL(.V.L (.V.L",
    719             "day 0  R   RVRHDPD dayabbr",
    720             "day 1  H   ADHDPHPD dayabbr",
    721             "day 2 L     ADNELBPD dayabbr",
    722             "day 3  J   MVQJPD  dayabbr",
    723             "day 4 I     FNQIPD    dayabbr",
    724             "day 5  M   GEMPD  dayabbr",
    725             "helloGEMPD",
    726             "hello ZYXW"
    727     };
    728     char formatChars[MAXLEN];
    729     UErrorCode ec = U_ZERO_ERROR;
    730     UBiDi* bidi = ubidi_open();
    731     int i;
    732 
    733     log_verbose("\nEntering TestReorder\n\n");
    734 
    735     for(i=0;i<UPRV_LENGTHOF(logicalOrder);i++){
    736         int32_t srcSize = (int32_t)strlen(logicalOrder[i]);
    737         int32_t destSize = srcSize*2;
    738         UChar src[MAXLEN];
    739         UChar dest[MAXLEN];
    740         char chars[MAXLEN];
    741         log_verbose("Testing L2V #1 for case %d\n", i);
    742         pseudoToU16(srcSize,logicalOrder[i],src);
    743         ec = U_ZERO_ERROR;
    744         ubidi_setPara(bidi,src,srcSize,UBIDI_DEFAULT_LTR ,NULL,&ec);
    745         if(U_FAILURE(ec)){
    746             log_err("ubidi_setPara(tests[%d], paraLevel %d) failed with errorCode %s\n",
    747                     i, UBIDI_DEFAULT_LTR, u_errorName(ec));
    748         }
    749         /* try pre-flighting */
    750         destSize = ubidi_writeReordered(bidi,dest,0,UBIDI_DO_MIRRORING,&ec);
    751         if(ec!=U_BUFFER_OVERFLOW_ERROR){
    752             log_err("Pre-flighting did not give expected error: Expected: U_BUFFER_OVERFLOW_ERROR. Got: %s \n",u_errorName(ec));
    753         }else if(destSize!=srcSize){
    754             log_err("Pre-flighting did not give expected size: Expected: %d. Got: %d \n",srcSize,destSize);
    755         }else{
    756             ec= U_ZERO_ERROR;
    757         }
    758         destSize=ubidi_writeReordered(bidi,dest,destSize+1,UBIDI_DO_MIRRORING,&ec);
    759         u16ToPseudo(destSize,dest,chars);
    760         if(destSize!=srcSize){
    761             log_err("ubidi_writeReordered() destSize and srcSize do not match\n");
    762         }else if(strcmp(visualOrder[i],chars)!=0){
    763             log_err("ubidi_writeReordered() did not give expected results for UBIDI_DO_MIRRORING.\n"
    764                     "Input   : %s\nExpected: %s\nGot     : %s\nLevels  : %s\nAt Index: %d\n",
    765                     logicalOrder[i],visualOrder[i],chars,formatLevels(bidi, formatChars),i);
    766         }
    767         checkWhatYouCan(bidi, logicalOrder[i], chars);
    768     }
    769 
    770     for(i=0;i<UPRV_LENGTHOF(logicalOrder);i++){
    771         int32_t srcSize = (int32_t)strlen(logicalOrder[i]);
    772         int32_t destSize = srcSize*2;
    773         UChar src[MAXLEN];
    774         UChar dest[MAXLEN];
    775         char chars[MAXLEN];
    776         log_verbose("Testing L2V #2 for case %d\n", i);
    777         pseudoToU16(srcSize,logicalOrder[i],src);
    778         ec = U_ZERO_ERROR;
    779         ubidi_setPara(bidi,src,srcSize,UBIDI_DEFAULT_LTR ,NULL,&ec);
    780         if(U_FAILURE(ec)){
    781             log_err("ubidi_setPara(tests[%d], paraLevel %d) failed with errorCode %s\n",
    782                     i, UBIDI_DEFAULT_LTR, u_errorName(ec));
    783         }
    784         /* try pre-flighting */
    785         destSize = ubidi_writeReordered(bidi,dest,0,UBIDI_DO_MIRRORING+UBIDI_OUTPUT_REVERSE,&ec);
    786         if(ec!=U_BUFFER_OVERFLOW_ERROR){
    787             log_err("Pre-flighting did not give expected error: Expected: U_BUFFER_OVERFLOW_ERROR. Got: %s \n",u_errorName(ec));
    788         }else if(destSize!=srcSize){
    789             log_err("Pre-flighting did not give expected size: Expected: %d. Got: %d \n",srcSize,destSize);
    790         }else{
    791             ec= U_ZERO_ERROR;
    792         }
    793         destSize=ubidi_writeReordered(bidi,dest,destSize+1,UBIDI_DO_MIRRORING+UBIDI_OUTPUT_REVERSE,&ec);
    794         u16ToPseudo(destSize,dest,chars);
    795         if(destSize!=srcSize){
    796             log_err("ubidi_writeReordered() destSize and srcSize do not match\n");
    797         }else if(strcmp(visualOrder1[i],chars)!=0){
    798             log_err("ubidi_writeReordered() did not give expected results for UBIDI_DO_MIRRORING+UBIDI_OUTPUT_REVERSE.\n"
    799                     "Input   : %s\nExpected: %s\nGot     : %s\nLevels  : %s\nAt Index: %d\n",
    800                     logicalOrder[i],visualOrder1[i],chars,formatLevels(bidi, formatChars),i);
    801         }
    802     }
    803 
    804     for(i=0;i<UPRV_LENGTHOF(logicalOrder);i++){
    805         int32_t srcSize = (int32_t)strlen(logicalOrder[i]);
    806         int32_t destSize = srcSize*2;
    807         UChar src[MAXLEN];
    808         UChar dest[MAXLEN];
    809         char chars[MAXLEN];
    810         log_verbose("Testing V2L #3 for case %d\n", i);
    811         pseudoToU16(srcSize,logicalOrder[i],src);
    812         ec = U_ZERO_ERROR;
    813         ubidi_setInverse(bidi,TRUE);
    814         ubidi_setPara(bidi,src,srcSize,UBIDI_DEFAULT_LTR ,NULL,&ec);
    815         if(U_FAILURE(ec)){
    816             log_err("ubidi_setPara(tests[%d], paraLevel %d) failed with errorCode %s\n",
    817                     i, UBIDI_DEFAULT_LTR, u_errorName(ec));
    818         }
    819                 /* try pre-flighting */
    820         destSize = ubidi_writeReordered(bidi,dest,0,UBIDI_INSERT_LRM_FOR_NUMERIC+UBIDI_OUTPUT_REVERSE,&ec);
    821         if(ec!=U_BUFFER_OVERFLOW_ERROR){
    822             log_err("Pre-flighting did not give expected error: Expected: U_BUFFER_OVERFLOW_ERROR. Got: %s \n",u_errorName(ec));
    823         }else{
    824             ec= U_ZERO_ERROR;
    825         }
    826         destSize=ubidi_writeReordered(bidi,dest,destSize+1,UBIDI_INSERT_LRM_FOR_NUMERIC+UBIDI_OUTPUT_REVERSE,&ec);
    827         u16ToPseudo(destSize,dest,chars);
    828         if(strcmp(visualOrder2[i],chars)!=0){
    829             log_err("ubidi_writeReordered() did not give expected results for UBIDI_INSERT_LRM_FOR_NUMERIC+UBIDI_OUTPUT_REVERSE.\n"
    830                     "Input   : %s\nExpected: %s\nGot     : %s\nLevels  : %s\nAt Index: %d\n",
    831                     logicalOrder[i],visualOrder2[i],chars,formatLevels(bidi, formatChars),i);
    832         }
    833     }
    834         /* Max Explicit level */
    835     for(i=0;i<UPRV_LENGTHOF(logicalOrder);i++){
    836         int32_t srcSize = (int32_t)strlen(logicalOrder[i]);
    837         int32_t destSize = srcSize*2;
    838         UChar src[MAXLEN];
    839         UChar dest[MAXLEN];
    840         char chars[MAXLEN];
    841         UBiDiLevel levels[UBIDI_MAX_EXPLICIT_LEVEL]={1,2,3,4,5,6,7,8,9,10};
    842         log_verbose("Testing V2L #4 for case %d\n", i);
    843         pseudoToU16(srcSize,logicalOrder[i],src);
    844         ec = U_ZERO_ERROR;
    845         ubidi_setPara(bidi,src,srcSize,UBIDI_DEFAULT_LTR,levels,&ec);
    846         if(U_FAILURE(ec)){
    847             log_err("ubidi_setPara(tests[%d], paraLevel %d) failed with errorCode %s\n",
    848                     i, UBIDI_MAX_EXPLICIT_LEVEL, u_errorName(ec));
    849         }
    850                 /* try pre-flighting */
    851         destSize = ubidi_writeReordered(bidi,dest,0,UBIDI_OUTPUT_REVERSE,&ec);
    852         if(ec!=U_BUFFER_OVERFLOW_ERROR){
    853             log_err("Pre-flighting did not give expected error: Expected: U_BUFFER_OVERFLOW_ERROR. Got: %s \n",u_errorName(ec));
    854         }else if(destSize!=srcSize){
    855             log_err("Pre-flighting did not give expected size: Expected: %d. Got: %d \n",srcSize,destSize);
    856         }else{
    857             ec = U_ZERO_ERROR;
    858         }
    859         destSize=ubidi_writeReordered(bidi,dest,destSize+1,UBIDI_OUTPUT_REVERSE,&ec);
    860         u16ToPseudo(destSize,dest,chars);
    861         if(destSize!=srcSize){
    862             log_err("ubidi_writeReordered() destSize and srcSize do not match. Dest Size = %d Source Size = %d\n",destSize,srcSize );
    863         }else if(strcmp(visualOrder3[i],chars)!=0){
    864             log_err("ubidi_writeReordered() did not give expected results for UBIDI_OUTPUT_REVERSE.\n"
    865                     "Input   : %s\nExpected: %s\nGot     : %s\nLevels  : %s\nAt Index: %d\n",
    866                     logicalOrder[i],visualOrder3[i],chars,formatLevels(bidi, formatChars),i);
    867         }
    868     }
    869     for(i=0;i<UPRV_LENGTHOF(logicalOrder);i++){
    870         int32_t srcSize = (int32_t)strlen(logicalOrder[i]);
    871         int32_t destSize = srcSize*2;
    872         UChar src[MAXLEN];
    873         UChar dest[MAXLEN];
    874         char chars[MAXLEN];
    875         UBiDiLevel levels[UBIDI_MAX_EXPLICIT_LEVEL]={1,2,3,4,5,6,7,8,9,10};
    876         log_verbose("Testing V2L #5 for case %d\n", i);
    877         pseudoToU16(srcSize,logicalOrder[i],src);
    878         ec = U_ZERO_ERROR;
    879         ubidi_setPara(bidi,src,srcSize,UBIDI_DEFAULT_LTR,levels,&ec);
    880         if(U_FAILURE(ec)){
    881             log_err("ubidi_setPara(tests[%d], paraLevel %d) failed with errorCode %s\n",
    882                     i, UBIDI_MAX_EXPLICIT_LEVEL, u_errorName(ec));
    883         }
    884         /* try pre-flighting */
    885         destSize = ubidi_writeReordered(bidi,dest,0,UBIDI_DO_MIRRORING+UBIDI_REMOVE_BIDI_CONTROLS,&ec);
    886         if(ec!=U_BUFFER_OVERFLOW_ERROR){
    887             log_err("Pre-flighting did not give expected error: Expected: U_BUFFER_OVERFLOW_ERROR. Got: %s \n",u_errorName(ec));
    888         }else{
    889             ec= U_ZERO_ERROR;
    890         }
    891         destSize=ubidi_writeReordered(bidi,dest,destSize+1,UBIDI_DO_MIRRORING+UBIDI_REMOVE_BIDI_CONTROLS,&ec);
    892         u16ToPseudo(destSize,dest,chars);
    893         if(strcmp(visualOrder4[i],chars)!=0){
    894             log_err("ubidi_writeReordered() did not give expected results for UBIDI_DO_MIRRORING+UBIDI_REMOVE_BIDI_CONTROLS.\n"
    895                     "Input   : %s\nExpected: %s\nGot     : %s\nLevels  : %s\nAt Index: %d\n",
    896                     logicalOrder[i],visualOrder4[i],chars,formatLevels(bidi, formatChars),i);
    897         }
    898     }
    899     ubidi_close(bidi);
    900 
    901     log_verbose("\nExiting TestReorder\n\n");
    902 }
    903 
    904 static void
    905 testReorderArabicMathSymbols(void) {
    906     static const UChar logicalOrder[][MAXLEN]={
    907         /* Arabic mathematical Symbols 0x1EE00 - 0x1EE1B */
    908         {0xD83B, 0xDE00, 0xD83B, 0xDE01, 0xD83B, 0xDE02, 0xD83B, 0xDE03, 0x20,
    909         0xD83B, 0xDE24, 0xD83B, 0xDE05, 0xD83B, 0xDE06, 0x20,
    910         0xD83B, 0xDE07, 0xD83B, 0xDE08, 0xD83B, 0xDE09, 0x20,
    911         0xD83B, 0xDE0A, 0xD83B, 0xDE0B, 0xD83B, 0xDE0C, 0xD83B, 0xDE0D, 0x20,
    912         0xD83B, 0xDE0E, 0xD83B, 0xDE0F, 0xD83B, 0xDE10, 0xD83B, 0xDE11, 0x20,
    913         0xD83B, 0xDE12, 0xD83B, 0xDE13, 0xD83B, 0xDE14, 0xD83B, 0xDE15, 0x20,
    914         0xD83B, 0xDE16, 0xD83B, 0xDE17, 0xD83B, 0xDE18, 0x20,
    915         0xD83B, 0xDE19, 0xD83B, 0xDE1A, 0xD83B, 0xDE1B},
    916         /* Arabic mathematical Symbols - Looped Symbols, 0x1EE80 - 0x1EE9B */
    917         {0xD83B, 0xDE80, 0xD83B, 0xDE81, 0xD83B, 0xDE82, 0xD83B, 0xDE83, 0x20,
    918         0xD83B, 0xDE84, 0xD83B, 0xDE85, 0xD83B, 0xDE86, 0x20,
    919         0xD83B, 0xDE87, 0xD83B, 0xDE88, 0xD83B, 0xDE89, 0x20,
    920         0xD83B, 0xDE8B, 0xD83B, 0xDE8C, 0xD83B, 0xDE8D, 0x20,
    921         0xD83B, 0xDE8E, 0xD83B, 0xDE8F, 0xD83B, 0xDE90, 0xD83B, 0xDE91, 0x20,
    922         0xD83B, 0xDE92, 0xD83B, 0xDE93, 0xD83B, 0xDE94, 0xD83B, 0xDE95, 0x20,
    923         0xD83B, 0xDE96, 0xD83B, 0xDE97, 0xD83B, 0xDE98, 0x20,
    924         0xD83B, 0xDE99, 0xD83B, 0xDE9A, 0xD83B, 0xDE9B},
    925         /* Arabic mathematical Symbols - Double-struck Symbols, 0x1EEA1 - 0x1EEBB */
    926         {0xD83B, 0xDEA1, 0xD83B, 0xDEA2, 0xD83B, 0xDEA3, 0x20,
    927         0xD83B, 0xDEA5, 0xD83B, 0xDEA6, 0x20,
    928         0xD83B, 0xDEA7, 0xD83B, 0xDEA8, 0xD83B, 0xDEA9, 0x20,
    929         0xD83B, 0xDEAB, 0xD83B, 0xDEAC, 0xD83B, 0xDEAD, 0x20,
    930         0xD83B, 0xDEAE, 0xD83B, 0xDEAF, 0xD83B, 0xDEB0, 0xD83B, 0xDEB1, 0x20,
    931         0xD83B, 0xDEB2, 0xD83B, 0xDEB3, 0xD83B, 0xDEB4, 0xD83B, 0xDEB5, 0x20,
    932         0xD83B, 0xDEB6, 0xD83B, 0xDEB7, 0xD83B, 0xDEB8, 0x20,
    933         0xD83B, 0xDEB9, 0xD83B, 0xDEBA, 0xD83B, 0xDEBB},
    934         /* Arabic mathematical Symbols - Initial Symbols, 0x1EE21 - 0x1EE3B */
    935         {0xD83B, 0xDE21, 0xD83B, 0xDE22, 0x20,
    936         0xD83B, 0xDE27, 0xD83B, 0xDE29, 0x20,
    937         0xD83B, 0xDE2A, 0xD83B, 0xDE2B, 0xD83B, 0xDE2C, 0xD83B, 0xDE2D, 0x20,
    938         0xD83B, 0xDE2E, 0xD83B, 0xDE2F, 0xD83B, 0xDE30, 0xD83B, 0xDE31, 0x20,
    939         0xD83B, 0xDE32, 0xD83B, 0xDE34, 0xD83B, 0xDE35, 0x20,
    940         0xD83B, 0xDE36, 0xD83B, 0xDE37, 0x20,
    941         0xD83B, 0xDE39, 0xD83B, 0xDE3B},
    942         /* Arabic mathematical Symbols - Tailed Symbols */
    943         {0xD83B, 0xDE42, 0xD83B, 0xDE47, 0xD83B, 0xDE49, 0xD83B, 0xDE4B, 0x20,
    944         0xD83B, 0xDE4D, 0xD83B, 0xDE4E, 0xD83B, 0xDE4F, 0x20,
    945         0xD83B, 0xDE51, 0xD83B, 0xDE52, 0xD83B, 0xDE54, 0xD83B, 0xDE57, 0x20,
    946         0xD83B, 0xDE59, 0xD83B, 0xDE5B, 0xD83B, 0xDE5D, 0xD83B, 0xDE5F}
    947     };
    948     static const UChar visualOrder[][MAXLEN]={
    949         /* Arabic mathematical Symbols 0x1EE00 - 0x1EE1B */
    950         {0xD83B, 0xDE1B, 0xD83B, 0xDE1A, 0xD83B, 0xDE19, 0x20,
    951         0xD83B, 0xDE18, 0xD83B, 0xDE17, 0xD83B, 0xDE16, 0x20,
    952         0xD83B, 0xDE15, 0xD83B, 0xDE14, 0xD83B, 0xDE13, 0xD83B, 0xDE12, 0x20,
    953         0xD83B, 0xDE11, 0xD83B, 0xDE10, 0xD83B, 0xDE0F, 0xD83B, 0xDE0E, 0x20,
    954         0xD83B, 0xDE0D, 0xD83B, 0xDE0C, 0xD83B, 0xDE0B, 0xD83B, 0xDE0A, 0x20,
    955         0xD83B, 0xDE09, 0xD83B, 0xDE08, 0xD83B, 0xDE07, 0x20,
    956         0xD83B, 0xDE06, 0xD83B, 0xDE05, 0xD83B, 0xDE24, 0x20,
    957         0xD83B, 0xDE03, 0xD83B, 0xDE02, 0xD83B, 0xDE01, 0xD83B, 0xDE00},
    958         /* Arabic mathematical Symbols - Looped Symbols, 0x1EE80 - 0x1EE9B */
    959         {0xD83B, 0xDE9B, 0xD83B, 0xDE9A, 0xD83B, 0xDE99, 0x20,
    960         0xD83B, 0xDE98, 0xD83B, 0xDE97, 0xD83B, 0xDE96, 0x20,
    961         0xD83B, 0xDE95, 0xD83B, 0xDE94, 0xD83B, 0xDE93, 0xD83B, 0xDE92, 0x20,
    962         0xD83B, 0xDE91, 0xD83B, 0xDE90, 0xD83B, 0xDE8F, 0xD83B, 0xDE8E, 0x20,
    963         0xD83B, 0xDE8D, 0xD83B, 0xDE8C, 0xD83B, 0xDE8B, 0x20,
    964         0xD83B, 0xDE89, 0xD83B, 0xDE88, 0xD83B, 0xDE87, 0x20,
    965         0xD83B, 0xDE86, 0xD83B, 0xDE85, 0xD83B, 0xDE84, 0x20,
    966         0xD83B, 0xDE83, 0xD83B, 0xDE82, 0xD83B, 0xDE81, 0xD83B, 0xDE80},
    967         /* Arabic mathematical Symbols - Double-struck Symbols, 0x1EEA1 - 0x1EEBB */
    968         {0xD83B, 0xDEBB, 0xD83B, 0xDEBA, 0xD83B, 0xDEB9, 0x20,
    969         0xD83B, 0xDEB8, 0xD83B, 0xDEB7, 0xD83B, 0xDEB6, 0x20,
    970         0xD83B, 0xDEB5, 0xD83B, 0xDEB4, 0xD83B, 0xDEB3, 0xD83B, 0xDEB2, 0x20,
    971         0xD83B, 0xDEB1, 0xD83B, 0xDEB0, 0xD83B, 0xDEAF, 0xD83B, 0xDEAE, 0x20,
    972         0xD83B, 0xDEAD, 0xD83B, 0xDEAC, 0xD83B, 0xDEAB, 0x20,
    973         0xD83B, 0xDEA9, 0xD83B, 0xDEA8, 0xD83B, 0xDEA7, 0x20,
    974         0xD83B, 0xDEA6, 0xD83B, 0xDEA5, 0x20,
    975         0xD83B, 0xDEA3, 0xD83B, 0xDEA2, 0xD83B, 0xDEA1},
    976         /* Arabic mathematical Symbols - Initial Symbols, 0x1EE21 - 0x1EE3B */
    977         {0xD83B, 0xDE3B, 0xD83B, 0xDE39, 0x20,
    978         0xD83B, 0xDE37, 0xD83B, 0xDE36, 0x20,
    979         0xD83B, 0xDE35, 0xD83B, 0xDE34, 0xD83B, 0xDE32, 0x20,
    980         0xD83B, 0xDE31, 0xD83B, 0xDE30, 0xD83B, 0xDE2F, 0xD83B, 0xDE2E, 0x20,
    981         0xD83B, 0xDE2D, 0xD83B, 0xDE2C, 0xD83B, 0xDE2B, 0xD83B, 0xDE2A, 0x20,
    982         0xD83B, 0xDE29, 0xD83B, 0xDE27, 0x20,
    983         0xD83B, 0xDE22, 0xD83B, 0xDE21},
    984         /* Arabic mathematical Symbols - Tailed Symbols */
    985         {0xD83B, 0xDE5F, 0xD83B, 0xDE5D, 0xD83B, 0xDE5B, 0xD83B, 0xDE59, 0x20,
    986         0xD83B, 0xDE57, 0xD83B, 0xDE54, 0xD83B, 0xDE52, 0xD83B, 0xDE51, 0x20,
    987         0xD83B, 0xDE4F, 0xD83B, 0xDE4E, 0xD83B, 0xDE4D, 0x20,
    988         0xD83B, 0xDE4B, 0xD83B, 0xDE49, 0xD83B, 0xDE47, 0xD83B, 0xDE42}
    989     };
    990     char formatChars[MAXLEN];
    991     UErrorCode ec = U_ZERO_ERROR;
    992     UBiDi* bidi = ubidi_open();
    993     int i;
    994 
    995     log_verbose("\nEntering TestReorderArabicMathSymbols\n\n");
    996 
    997     for(i=0;i<UPRV_LENGTHOF(logicalOrder);i++){
    998         int32_t srcSize = u_strlen(logicalOrder[i]);
    999         int32_t destSize = srcSize*2;
   1000         UChar dest[MAXLEN];
   1001         log_verbose("Testing L2V #1 for case %d\n", i);
   1002         ec = U_ZERO_ERROR;
   1003         ubidi_setPara(bidi,logicalOrder[i],srcSize,UBIDI_DEFAULT_LTR ,NULL,&ec);
   1004         if(U_FAILURE(ec)){
   1005             log_err("ubidi_setPara(tests[%d], paraLevel %d) failed with errorCode %s\n",
   1006                     i, UBIDI_DEFAULT_LTR, u_errorName(ec));
   1007         }
   1008         /* try pre-flighting */
   1009         destSize = ubidi_writeReordered(bidi,dest,0,UBIDI_DO_MIRRORING,&ec);
   1010         if(ec!=U_BUFFER_OVERFLOW_ERROR){
   1011             log_err("Pre-flighting did not give expected error: Expected: U_BUFFER_OVERFLOW_ERROR. Got: %s \n",u_errorName(ec));
   1012         }else if(destSize!=srcSize){
   1013             log_err("Pre-flighting did not give expected size: Expected: %d. Got: %d \n",srcSize,destSize);
   1014         }else{
   1015             ec= U_ZERO_ERROR;
   1016         }
   1017         destSize=ubidi_writeReordered(bidi,dest,destSize+1,UBIDI_DO_MIRRORING,&ec);
   1018         if(destSize!=srcSize){
   1019             log_err("ubidi_writeReordered() destSize and srcSize do not match\n");
   1020         }else if(memcmp(dest, visualOrder[i], destSize*U_SIZEOF_UCHAR)!=0){
   1021             log_err("ubidi_writeReordered() did not give expected results for UBIDI_DO_MIRRORING.\n"
   1022                     "Input   : %s\nExpected: %s\nGot     : %s\nLevels  : %s\nAt Index: %d\n",
   1023                     logicalOrder[i],visualOrder[i],dest,formatLevels(bidi, formatChars),i);
   1024         }
   1025     }
   1026 
   1027     ubidi_close(bidi);
   1028 
   1029     log_verbose("\nExiting TestReorderArabicMathSymbols\n\n");
   1030 }
   1031 
   1032 static void
   1033 doTest(UBiDi *pBiDi, int testNumber, const BiDiTestData *test, int32_t lineStart, UBool countRunsFirst) {
   1034     const uint8_t *dirProps=test->text+lineStart;
   1035     const UBiDiLevel *levels=test->levels;
   1036     const uint8_t *visualMap=test->visualMap;
   1037     int32_t i, len=ubidi_getLength(pBiDi), logicalIndex, runCount = 0;
   1038     UErrorCode errorCode=U_ZERO_ERROR;
   1039     UBiDiLevel level, level2;
   1040 
   1041     if (countRunsFirst) {
   1042         log_verbose("Calling ubidi_countRuns() first.\n");
   1043 
   1044         runCount = ubidi_countRuns(pBiDi, &errorCode);
   1045 
   1046         if(U_FAILURE(errorCode)) {
   1047             log_err("ubidi_countRuns(tests[%d]): error %s\n", testNumber, myErrorName(errorCode));
   1048             return;
   1049         }
   1050     } else {
   1051         log_verbose("Calling ubidi_getLogicalMap() first.\n");
   1052     }
   1053 
   1054     _testReordering(pBiDi, testNumber);
   1055 
   1056     for(i=0; i<len; ++i) {
   1057         log_verbose("%3d %3d %.*s%-3s @%d\n",
   1058                 i, ubidi_getLevelAt(pBiDi, i), ubidi_getLevelAt(pBiDi, i), levelString,
   1059                 dirPropNames[dirProps[i]],
   1060                 ubidi_getVisualIndex(pBiDi, i, &errorCode));
   1061     }
   1062 
   1063     log_verbose("\n-----levels:");
   1064     for(i=0; i<len; ++i) {
   1065         if(i>0) {
   1066             log_verbose(",");
   1067         }
   1068         log_verbose(" %d", ubidi_getLevelAt(pBiDi, i));
   1069     }
   1070 
   1071     log_verbose("\n--reordered:");
   1072     for(i=0; i<len; ++i) {
   1073         if(i>0) {
   1074             log_verbose(",");
   1075         }
   1076         log_verbose(" %d", ubidi_getVisualIndex(pBiDi, i, &errorCode));
   1077     }
   1078     log_verbose("\n");
   1079 
   1080     if(test->direction!=ubidi_getDirection(pBiDi)) {
   1081         log_err("ubidi_getDirection(tests[%d]): wrong direction %d\n", testNumber, ubidi_getDirection(pBiDi));
   1082     }
   1083 
   1084     if(test->resultLevel!=ubidi_getParaLevel(pBiDi)) {
   1085         log_err("ubidi_getParaLevel(tests[%d]): wrong paragraph level %d\n", testNumber, ubidi_getParaLevel(pBiDi));
   1086     }
   1087 
   1088     for(i=0; i<len; ++i) {
   1089         if(levels[i]!=ubidi_getLevelAt(pBiDi, i)) {
   1090             log_err("ubidi_getLevelAt(tests[%d], %d): wrong level %d, expected %d\n", testNumber, i, ubidi_getLevelAt(pBiDi, i), levels[i]);
   1091             return;
   1092         }
   1093     }
   1094 
   1095     for(i=0; i<len; ++i) {
   1096         logicalIndex=ubidi_getVisualIndex(pBiDi, i, &errorCode);
   1097         if(U_FAILURE(errorCode)) {
   1098             log_err("ubidi_getVisualIndex(tests[%d], %d): error %s\n", testNumber, i, myErrorName(errorCode));
   1099             return;
   1100         }
   1101         if(visualMap[i]!=logicalIndex) {
   1102             log_err("ubidi_getVisualIndex(tests[%d], %d): wrong index %d\n", testNumber, i, logicalIndex);
   1103             return;
   1104         }
   1105     }
   1106 
   1107     if (! countRunsFirst) {
   1108         runCount=ubidi_countRuns(pBiDi, &errorCode);
   1109         if(U_FAILURE(errorCode)) {
   1110             log_err("ubidi_countRuns(tests[%d]): error %s\n", testNumber, myErrorName(errorCode));
   1111             return;
   1112         }
   1113     }
   1114 
   1115     for(logicalIndex=0; logicalIndex<len;) {
   1116         level=ubidi_getLevelAt(pBiDi, logicalIndex);
   1117         ubidi_getLogicalRun(pBiDi, logicalIndex, &logicalIndex, &level2);
   1118         if(level!=level2) {
   1119             log_err("ubidi_getLogicalRun(tests[%d], run ending at index %d): "
   1120                     "wrong level %d instead of %d\n",
   1121                     testNumber, logicalIndex, level, level2);
   1122         }
   1123         if(--runCount<0) {
   1124             log_err("\nubidi_getLogicalRun(tests[%d]): wrong number of runs "
   1125                     "compared to %d=ubidi_countRuns()\n",
   1126                     testNumber, ubidi_countRuns(pBiDi, &errorCode));
   1127             return;
   1128         }
   1129     }
   1130     if(runCount!=0) {
   1131         log_err("\nubidi_getLogicalRun(tests[%d]): wrong number of runs "
   1132                 "compared to %d=ubidi_getRunCount()\n",
   1133                 testNumber, ubidi_countRuns(pBiDi, &errorCode));
   1134         return;
   1135     }
   1136 
   1137     log_verbose("\n\n");
   1138 }
   1139 
   1140 static void
   1141 _testReordering(UBiDi *pBiDi, int testNumber) {
   1142     int32_t
   1143         logicalMap1[MAXLEN], logicalMap2[MAXLEN], logicalMap3[MAXLEN],
   1144         visualMap1[MAXLEN], visualMap2[MAXLEN], visualMap3[MAXLEN], visualMap4[MAXLEN];
   1145     UErrorCode errorCode=U_ZERO_ERROR;
   1146     const UBiDiLevel *levels;
   1147     int32_t i, length=ubidi_getLength(pBiDi),
   1148                destLength=ubidi_getResultLength(pBiDi);
   1149     int32_t runCount, visualIndex, logicalStart, runLength;
   1150     UBool odd;
   1151 
   1152     if(length<=0) {
   1153         return;
   1154     }
   1155 
   1156     /* get the logical and visual maps from the object */
   1157     ubidi_getLogicalMap(pBiDi, logicalMap1, &errorCode);
   1158     if(U_FAILURE(errorCode)) {
   1159         log_err("ubidi_getLogicalMap(tests[%d]): error %s\n", testNumber, myErrorName(errorCode));
   1160         return;
   1161     }
   1162 
   1163     ubidi_getVisualMap(pBiDi, visualMap1, &errorCode);
   1164     if(U_FAILURE(errorCode)) {
   1165         log_err("ubidi_getVisualMap(tests[%d]): error %s\n", testNumber, myErrorName(errorCode));
   1166         return;
   1167     }
   1168 
   1169     /* invert them both */
   1170     ubidi_invertMap(logicalMap1, visualMap2, length);
   1171     ubidi_invertMap(visualMap1, logicalMap2, destLength);
   1172 
   1173     /* get them from the levels array, too */
   1174     levels=ubidi_getLevels(pBiDi, &errorCode);
   1175 
   1176     if(U_FAILURE(errorCode)) {
   1177         log_err("ubidi_getLevels(tests[%d]): error %s\n", testNumber, myErrorName(errorCode));
   1178         return;
   1179     }
   1180 
   1181     ubidi_reorderLogical(levels, length, logicalMap3);
   1182     ubidi_reorderVisual(levels, length, visualMap3);
   1183 
   1184     /* get the visual map from the runs, too */
   1185     runCount=ubidi_countRuns(pBiDi, &errorCode);
   1186     if(U_FAILURE(errorCode)) {
   1187         log_err("ubidi_countRuns(tests[%d]): error %s\n", testNumber, myErrorName(errorCode));
   1188         return;
   1189     }
   1190     log_verbose("\n----%2d runs:", runCount);
   1191     visualIndex=0;
   1192     for(i=0; i<runCount; ++i) {
   1193         odd=(UBool)ubidi_getVisualRun(pBiDi, i, &logicalStart, &runLength);
   1194         log_verbose(" (%c @%d[%d])", odd ? 'R' : 'L', logicalStart, runLength);
   1195         if(UBIDI_LTR==odd) {
   1196             do { /* LTR */
   1197                 visualMap4[visualIndex++]=logicalStart++;
   1198             } while(--runLength>0);
   1199         } else {
   1200             logicalStart+=runLength;   /* logicalLimit */
   1201             do { /* RTL */
   1202                 visualMap4[visualIndex++]=--logicalStart;
   1203             } while(--runLength>0);
   1204         }
   1205     }
   1206     log_verbose("\n");
   1207 
   1208     /* print all the maps */
   1209     log_verbose("logical maps:\n");
   1210     for(i=0; i<length; ++i) {
   1211         log_verbose("%4d", logicalMap1[i]);
   1212     }
   1213     log_verbose("\n");
   1214     for(i=0; i<length; ++i) {
   1215         log_verbose("%4d", logicalMap2[i]);
   1216     }
   1217     log_verbose("\n");
   1218     for(i=0; i<length; ++i) {
   1219         log_verbose("%4d", logicalMap3[i]);
   1220     }
   1221 
   1222     log_verbose("\nvisual maps:\n");
   1223     for(i=0; i<destLength; ++i) {
   1224         log_verbose("%4d", visualMap1[i]);
   1225     }
   1226     log_verbose("\n");
   1227     for(i=0; i<destLength; ++i) {
   1228         log_verbose("%4d", visualMap2[i]);
   1229     }
   1230     log_verbose("\n");
   1231     for(i=0; i<length; ++i) {
   1232         log_verbose("%4d", visualMap3[i]);
   1233     }
   1234     log_verbose("\n");
   1235     for(i=0; i<length; ++i) {
   1236         log_verbose("%4d", visualMap4[i]);
   1237     }
   1238     log_verbose("\n");
   1239 
   1240     /* check that the indexes are the same between these and ubidi_getLogical/VisualIndex() */
   1241     for(i=0; i<length; ++i) {
   1242         if(logicalMap1[i]!=logicalMap2[i]) {
   1243             log_err("bidi reordering error in tests[%d]: logicalMap1[i]!=logicalMap2[i] at i=%d\n", testNumber, i);
   1244             break;
   1245         }
   1246         if(logicalMap1[i]!=logicalMap3[i]) {
   1247             log_err("bidi reordering error in tests[%d]: logicalMap1[i]!=logicalMap3[i] at i=%d\n", testNumber, i);
   1248             break;
   1249         }
   1250 
   1251         if(visualMap1[i]!=visualMap2[i]) {
   1252             log_err("bidi reordering error in tests[%d]: visualMap1[i]!=visualMap2[i] at i=%d\n", testNumber, i);
   1253             break;
   1254         }
   1255         if(visualMap1[i]!=visualMap3[i]) {
   1256             log_err("bidi reordering error in tests[%d]: visualMap1[i]!=visualMap3[i] at i=%d\n", testNumber, i);
   1257             break;
   1258         }
   1259         if(visualMap1[i]!=visualMap4[i]) {
   1260             log_err("bidi reordering error in tests[%d]: visualMap1[i]!=visualMap4[i] at i=%d\n", testNumber, i);
   1261             break;
   1262         }
   1263 
   1264         if(logicalMap1[i]!=ubidi_getVisualIndex(pBiDi, i, &errorCode)) {
   1265             log_err("bidi reordering error in tests[%d]: logicalMap1[i]!=ubidi_getVisualIndex(i) at i=%d\n", testNumber, i);
   1266             break;
   1267         }
   1268         if(U_FAILURE(errorCode)) {
   1269             log_err("ubidi_getVisualIndex(tests[%d], %d): error %s\n", testNumber, i, myErrorName(errorCode));
   1270             break;
   1271         }
   1272         if(visualMap1[i]!=ubidi_getLogicalIndex(pBiDi, i, &errorCode)) {
   1273             log_err("bidi reordering error in tests[%d]: visualMap1[i]!=ubidi_getLogicalIndex(i) at i=%d\n", testNumber, i);
   1274             break;
   1275         }
   1276         if(U_FAILURE(errorCode)) {
   1277             log_err("ubidi_getLogicalIndex(tests[%d], %d): error %s\n", testNumber, i, myErrorName(errorCode));
   1278             break;
   1279         }
   1280     }
   1281 }
   1282 
   1283 #define RETURN_IF_BAD_ERRCODE(x)    \
   1284     if (U_FAILURE(errorCode)) {      \
   1285         log_err("\nbad errorCode %d at %s\n", errorCode, (x));  \
   1286         return;     \
   1287     }               \
   1288 
   1289 #define STRING_TEST_CASE(s) { (s), UPRV_LENGTHOF(s) }
   1290 
   1291 static void testGetBaseDirection(void) {
   1292     UBiDiDirection dir;
   1293     int i;
   1294 
   1295 /* Test Data */
   1296     static const UChar
   1297 /*Mixed Start with L*/
   1298     stringMixedEnglishFirst[]={ 0x61, 0x627, 0x32, 0x6f3, 0x61, 0x34, 0 },
   1299 /*Mixed Start with AL*/
   1300     stringMixedArabicFirst[]={ 0x661, 0x627, 0x662, 0x6f3, 0x61, 0x664, 0 },
   1301 /*Mixed Start with R*/
   1302     stringMixedHebrewFirst[]={ 0x05EA, 0x627, 0x662, 0x6f3, 0x61, 0x664, 0 },
   1303 /*All AL (Arabic. Persian)*/
   1304     stringPersian[]={0x0698, 0x067E, 0x0686, 0x06AF, 0},
   1305 /*All R (Hebrew etc.)*/
   1306     stringHebrew[]={0x0590, 0x05D5, 0x05EA, 0x05F1, 0},
   1307 /*All L (English)*/
   1308     stringEnglish[]={0x71, 0x61, 0x66, 0},
   1309 /*Mixed Start with weak AL an then L*/
   1310     stringStartWeakAL[]={ 0x0663, 0x71, 0x61, 0x66, 0},
   1311 /*Mixed Start with weak L and then AL*/
   1312     stringStartWeakL[]={0x31, 0x0698, 0x067E, 0x0686, 0x06AF, 0},
   1313 /*Empty*/
   1314     stringEmpty[]={0},
   1315 /*Surrogate Char.*/
   1316     stringSurrogateChar[]={0xD800, 0xDC00, 0},
   1317 /*Invalid UChar*/
   1318     stringInvalidUchar[]={-1},
   1319 /*All weak L (English Digits)*/
   1320     stringAllEnglishDigits[]={0x31, 0x32, 0x33, 0},
   1321 /*All weak AL (Arabic Digits)*/
   1322     stringAllArabicDigits[]={0x0663, 0x0664, 0x0665, 0},
   1323 /*First L (English) others are R (Hebrew etc.) */
   1324     stringFirstL[] = {0x71, 0x0590, 0x05D5, 0x05EA, 0x05F1, 0},
   1325 /*Last R (Hebrew etc.) others are weak L (English Digits)*/
   1326     stringLastR[] = {0x31, 0x32, 0x33, 0x05F1, 0};
   1327 
   1328     static const struct {
   1329         const UChar *s;
   1330         int32_t length;
   1331     } testCases[]={
   1332         STRING_TEST_CASE(stringMixedEnglishFirst),
   1333         STRING_TEST_CASE(stringMixedArabicFirst),
   1334         STRING_TEST_CASE(stringMixedHebrewFirst),
   1335         STRING_TEST_CASE(stringPersian),
   1336         STRING_TEST_CASE(stringHebrew),
   1337         STRING_TEST_CASE(stringEnglish),
   1338         STRING_TEST_CASE(stringStartWeakAL),
   1339         STRING_TEST_CASE(stringStartWeakL),
   1340         STRING_TEST_CASE(stringEmpty),
   1341         STRING_TEST_CASE(stringSurrogateChar),
   1342         STRING_TEST_CASE(stringInvalidUchar),
   1343         STRING_TEST_CASE(stringAllEnglishDigits),
   1344         STRING_TEST_CASE(stringAllArabicDigits),
   1345         STRING_TEST_CASE(stringFirstL),
   1346         STRING_TEST_CASE(stringLastR),
   1347     };
   1348 
   1349 /* Expected results */
   1350     static const UBiDiDirection expectedDir[] ={
   1351         UBIDI_LTR, UBIDI_RTL, UBIDI_RTL,
   1352         UBIDI_RTL, UBIDI_RTL, UBIDI_LTR,
   1353         UBIDI_LTR, UBIDI_RTL, UBIDI_NEUTRAL,
   1354         UBIDI_LTR, UBIDI_NEUTRAL, UBIDI_NEUTRAL,
   1355         UBIDI_NEUTRAL, UBIDI_LTR, UBIDI_RTL
   1356     };
   1357 
   1358     log_verbose("testGetBaseDirection() with %u test cases ---\n",
   1359     UPRV_LENGTHOF(testCases));
   1360 /* Run Tests */
   1361      for(i=0; i<UPRV_LENGTHOF(testCases); ++i) {
   1362         dir = ubidi_getBaseDirection(testCases[i].s, testCases[i].length );
   1363         log_verbose("Testing case %d\tReceived dir %d\n", i, dir);
   1364         if (dir != expectedDir[i])
   1365             log_err("\nFailed getBaseDirection case %d Expected  %d \tReceived %d\n",
   1366             i, expectedDir[i], dir);
   1367     }
   1368 
   1369 /* Misc. tests */
   1370 /* NULL string */
   1371     dir = ubidi_getBaseDirection(NULL, 3);
   1372     if (dir != UBIDI_NEUTRAL )
   1373         log_err("\nFailed getBaseDirection for NULL string " ,
   1374         "\nExpected  %d \nReceived %d", UBIDI_NEUTRAL, dir);
   1375 /*All L- English string and length=-3 */
   1376     dir = ubidi_getBaseDirection( stringEnglish, -3);
   1377     if (dir != UBIDI_NEUTRAL )
   1378         log_err("\nFailed getBaseDirection for string w length= -3 ",
   1379         "\nExpected  %d \nReceived %d", UBIDI_NEUTRAL, dir);
   1380 /*All L- English string and length=-1 */
   1381     dir = ubidi_getBaseDirection( stringEnglish, -1);
   1382     if (dir != UBIDI_LTR )
   1383         log_err("\nFailed getBaseDirection for English string w length= -1 ",
   1384         "\nExpected  %d \nReceived %d", UBIDI_LTR, dir);
   1385 /*All AL- Persian string and length=-1 */
   1386     dir = ubidi_getBaseDirection( stringPersian, -1);
   1387     if (dir != UBIDI_RTL )
   1388         log_err("\nFailed getBaseDirection for Persian string w length= -1 ",
   1389         "\nExpected  %d \nReceived %d", UBIDI_RTL, dir);
   1390 /*All R- Hebrew string and length=-1 */
   1391     dir = ubidi_getBaseDirection( stringHebrew, -1);
   1392     if (dir != UBIDI_RTL )
   1393         log_err("\nFailed getBaseDirection for Hebrew string w length= -1 ",
   1394         "\nExpected  %d \nReceived %d", UBIDI_RTL, dir);
   1395 /*All weak L- English digits string and length=-1 */
   1396     dir = ubidi_getBaseDirection(stringAllEnglishDigits, -1);
   1397     if (dir != UBIDI_NEUTRAL )
   1398         log_err("\nFailed getBaseDirection for English digits string w length= -1 ",
   1399         "\nExpected  %d \nReceived %d", UBIDI_NEUTRAL, dir);
   1400 /*All weak AL- Arabic digits string and length=-1 */
   1401     dir = ubidi_getBaseDirection(stringAllArabicDigits, -1);
   1402     if (dir != UBIDI_NEUTRAL )
   1403         log_err("\nFailed getBaseDirection for Arabic string w length= -1 ",
   1404         "\nExpected  %d \nReceived %d", UBIDI_NEUTRAL, dir);
   1405 
   1406 }
   1407 
   1408 
   1409 static void doMisc(void) {
   1410 /* Miscellaneous tests to exercize less popular code paths */
   1411     UBiDi *bidi, *bidiLine;
   1412     UChar src[MAXLEN], dest[MAXLEN];
   1413     int32_t srcLen, destLen, runCount, i;
   1414     UBiDiLevel level;
   1415     UBiDiDirection dir;
   1416     int32_t map[MAXLEN];
   1417     UErrorCode errorCode=U_ZERO_ERROR;
   1418     static const int32_t srcMap[6] = {0,1,-1,5,4};
   1419     static const int32_t dstMap[6] = {0,1,-1,-1,4,3};
   1420 
   1421     bidi = ubidi_openSized(120, 66, &errorCode);
   1422     if (bidi == NULL) {
   1423         log_err("Error with openSized(120, 66)\n");
   1424         return;
   1425     }
   1426     bidiLine = ubidi_open();
   1427     if (bidi == NULL) {
   1428         log_err("Error with open()\n");
   1429         return;
   1430     }
   1431 
   1432     destLen = ubidi_writeReverse(src, 0, dest, MAXLEN, 0, &errorCode);
   1433     if (destLen != 0) {
   1434         log_err("\nwriteReverse should return zero length, ",
   1435                 "returned %d instead\n", destLen);
   1436     }
   1437     RETURN_IF_BAD_ERRCODE("#1#");
   1438 
   1439     ubidi_setPara(bidi, src, 0, UBIDI_LTR, NULL, &errorCode);
   1440     destLen = ubidi_writeReordered(bidi, dest, MAXLEN, 0, &errorCode);
   1441     if (destLen != 0) {
   1442         log_err("\nwriteReordered should return zero length, ",
   1443                 "returned %d instead\n", destLen);
   1444     }
   1445     RETURN_IF_BAD_ERRCODE("#2#");
   1446 
   1447     srcLen = u_unescape("abc       ", src, MAXLEN);
   1448     ubidi_setPara(bidi, src, srcLen, UBIDI_RTL, NULL, &errorCode);
   1449     ubidi_setLine(bidi, 0, 6, bidiLine, &errorCode);
   1450     for (i = 3; i < 6; i++) {
   1451         level = ubidi_getLevelAt(bidiLine, i);
   1452         if (level != UBIDI_RTL) {
   1453             log_err("\nTrailing space at index %d should get paragraph level"
   1454                     "%d, got %d instead\n", i, UBIDI_RTL, level);
   1455         }
   1456     }
   1457     RETURN_IF_BAD_ERRCODE("#3#");
   1458 
   1459     srcLen = u_unescape("abc       def", src, MAXLEN);
   1460     ubidi_setPara(bidi, src, srcLen, UBIDI_RTL, NULL, &errorCode);
   1461     ubidi_setLine(bidi, 0, 6, bidiLine, &errorCode);
   1462     for (i = 3; i < 6; i++) {
   1463         level = ubidi_getLevelAt(bidiLine, i);
   1464         if (level != UBIDI_RTL) {
   1465             log_err("\nTrailing space at index %d should get paragraph level"
   1466                     "%d, got %d instead\n", i, UBIDI_RTL, level);
   1467         }
   1468     }
   1469     RETURN_IF_BAD_ERRCODE("#4#");
   1470 
   1471     srcLen = u_unescape("abcdefghi    ", src, MAXLEN);
   1472     ubidi_setPara(bidi, src, srcLen, UBIDI_RTL, NULL, &errorCode);
   1473     ubidi_setLine(bidi, 0, 6, bidiLine, &errorCode);
   1474     for (i = 3; i < 6; i++) {
   1475         level = ubidi_getLevelAt(bidiLine, i);
   1476         if (level != 2) {
   1477             log_err("\nTrailing char at index %d should get level 2, "
   1478                     "got %d instead\n", i, level);
   1479         }
   1480     }
   1481     RETURN_IF_BAD_ERRCODE("#5#");
   1482 
   1483     ubidi_setReorderingOptions(bidi, UBIDI_OPTION_REMOVE_CONTROLS);
   1484     srcLen = u_unescape("\\u200eabc       def", src, MAXLEN);
   1485     ubidi_setPara(bidi, src, srcLen, UBIDI_RTL, NULL, &errorCode);
   1486     ubidi_setLine(bidi, 0, 6, bidiLine, &errorCode);
   1487     destLen = ubidi_getResultLength(bidiLine);
   1488     if (destLen != 5) {
   1489         log_err("\nWrong result length, should be 5, got %d\n", destLen);
   1490     }
   1491     RETURN_IF_BAD_ERRCODE("#6#");
   1492 
   1493     srcLen = u_unescape("abcdefghi", src, MAXLEN);
   1494     ubidi_setPara(bidi, src, srcLen, UBIDI_LTR, NULL, &errorCode);
   1495     ubidi_setLine(bidi, 0, 6, bidiLine, &errorCode);
   1496     dir = ubidi_getDirection(bidiLine);
   1497     if (dir != UBIDI_LTR) {
   1498         log_err("\nWrong direction #1, should be %d, got %d\n",
   1499                 UBIDI_LTR, dir);
   1500     }
   1501     RETURN_IF_BAD_ERRCODE("#7#");
   1502 
   1503     ubidi_setPara(bidi, src, 0, UBIDI_LTR, NULL, &errorCode);
   1504     runCount = ubidi_countRuns(bidi, &errorCode);
   1505     if (runCount != 0) {
   1506         log_err("\nWrong number of runs #1, should be 0, got %d\n", runCount);
   1507     }
   1508     RETURN_IF_BAD_ERRCODE("#8#");
   1509 
   1510     srcLen = u_unescape("          ", src, MAXLEN);
   1511     ubidi_setPara(bidi, src, srcLen, UBIDI_RTL, NULL, &errorCode);
   1512     ubidi_setLine(bidi, 0, 6, bidiLine, &errorCode);
   1513     runCount = ubidi_countRuns(bidiLine, &errorCode);
   1514     if (runCount != 1) {
   1515         log_err("\nWrong number of runs #2, should be 1, got %d\n", runCount);
   1516     }
   1517     RETURN_IF_BAD_ERRCODE("#9#");
   1518 
   1519     srcLen = u_unescape("a\\u05d0        bc", src, MAXLEN);
   1520     ubidi_setPara(bidi, src, srcLen, UBIDI_RTL, NULL, &errorCode);
   1521     ubidi_setLine(bidi, 0, 6, bidiLine, &errorCode);
   1522     dir = ubidi_getDirection(bidi);
   1523     if (dir != UBIDI_MIXED) {
   1524         log_err("\nWrong direction #2, should be %d, got %d\n",
   1525                 UBIDI_MIXED, dir);
   1526     }
   1527     dir = ubidi_getDirection(bidiLine);
   1528     if (dir != UBIDI_MIXED) {
   1529         log_err("\nWrong direction #3, should be %d, got %d\n",
   1530                 UBIDI_MIXED, dir);
   1531     }
   1532     runCount = ubidi_countRuns(bidiLine, &errorCode);
   1533     if (runCount != 2) {
   1534         log_err("\nWrong number of runs #3, should be 2, got %d\n", runCount);
   1535     }
   1536     RETURN_IF_BAD_ERRCODE("#10#");
   1537 
   1538     ubidi_invertMap(srcMap, map, 5);
   1539     if (memcmp(dstMap, map, sizeof(dstMap))) {
   1540         log_err("\nUnexpected inverted Map, got ");
   1541         for (i = 0; i < 6; i++) {
   1542             log_err("%d ", map[i]);
   1543         }
   1544         log_err("\n");
   1545     }
   1546 
   1547     /* test REMOVE_BIDI_CONTROLS together with DO_MIRRORING */
   1548     srcLen = u_unescape("abc\\u200e", src, MAXLEN);
   1549     ubidi_setPara(bidi, src, srcLen, UBIDI_LTR, NULL, &errorCode);
   1550     destLen = ubidi_writeReordered(bidi, dest, MAXLEN,
   1551               UBIDI_REMOVE_BIDI_CONTROLS | UBIDI_DO_MIRRORING, &errorCode);
   1552     if (destLen != 3 || memcmp(dest, src, 3 * sizeof(UChar))) {
   1553         log_err("\nWrong result #1, should be 'abc', got '%s'\n",
   1554                 aescstrdup(dest, destLen));
   1555     }
   1556     RETURN_IF_BAD_ERRCODE("#11#");
   1557 
   1558     /* test inverse Bidi with marks and contextual orientation */
   1559     ubidi_setReorderingMode(bidi, UBIDI_REORDER_INVERSE_LIKE_DIRECT);
   1560     ubidi_setReorderingOptions(bidi, UBIDI_OPTION_INSERT_MARKS);
   1561     ubidi_setPara(bidi, src, 0, UBIDI_DEFAULT_RTL, NULL, &errorCode);
   1562     destLen = ubidi_writeReordered(bidi, dest, MAXLEN, 0, &errorCode);
   1563     if (destLen != 0) {
   1564         log_err("\nWrong result #2, length should be 0, got %d\n", destLen);
   1565     }
   1566     RETURN_IF_BAD_ERRCODE("#12#");
   1567     srcLen = u_unescape("   ", src, MAXLEN);
   1568     ubidi_setPara(bidi, src, srcLen, UBIDI_DEFAULT_RTL, NULL, &errorCode);
   1569     destLen = ubidi_writeReordered(bidi, dest, MAXLEN, 0, &errorCode);
   1570     if (destLen != 3 || memcmp(dest, src, destLen * sizeof(UChar))) {
   1571         log_err("\nWrong result #3, should be '   ', got '%s'\n",
   1572                 aescstrdup(dest, destLen));
   1573     }
   1574     RETURN_IF_BAD_ERRCODE("#13#");
   1575     srcLen = u_unescape("abc", src, MAXLEN);
   1576     ubidi_setPara(bidi, src, srcLen, UBIDI_DEFAULT_RTL, NULL, &errorCode);
   1577     destLen = ubidi_writeReordered(bidi, dest, MAXLEN, 0, &errorCode);
   1578     if (destLen != 3 || memcmp(dest, src, destLen * sizeof(UChar))) {
   1579         log_err("\nWrong result #4, should be 'abc', got '%s'\n",
   1580                 aescstrdup(dest, destLen));
   1581     }
   1582     RETURN_IF_BAD_ERRCODE("#14#");
   1583     srcLen = u_unescape("\\u05d0\\u05d1", src, MAXLEN);
   1584     ubidi_setPara(bidi, src, srcLen, UBIDI_DEFAULT_RTL, NULL, &errorCode);
   1585     destLen = ubidi_writeReordered(bidi, dest, MAXLEN, 0, &errorCode);
   1586     srcLen = u_unescape("\\u05d1\\u05d0", src, MAXLEN);
   1587     if (destLen != 2 || memcmp(dest, src, destLen * sizeof(UChar))) {
   1588         log_err("\nWrong result #5, should be '%s', got '%s'\n",
   1589                 aescstrdup(src, srcLen), aescstrdup(dest, destLen));
   1590     }
   1591     RETURN_IF_BAD_ERRCODE("#15#");
   1592     srcLen = u_unescape("abc \\u05d0\\u05d1", src, MAXLEN);
   1593     ubidi_setPara(bidi, src, srcLen, UBIDI_DEFAULT_RTL, NULL, &errorCode);
   1594     destLen = ubidi_writeReordered(bidi, dest, MAXLEN, 0, &errorCode);
   1595     srcLen = u_unescape("\\u05d1\\u05d0 abc", src, MAXLEN);
   1596     if (destLen != 6 || memcmp(dest, src, destLen * sizeof(UChar))) {
   1597         log_err("\nWrong result #6, should be '%s', got '%s'\n",
   1598                 aescstrdup(src, srcLen), aescstrdup(dest, destLen));
   1599     }
   1600     RETURN_IF_BAD_ERRCODE("#16#");
   1601     srcLen = u_unescape("\\u05d0\\u05d1 abc", src, MAXLEN);
   1602     ubidi_setPara(bidi, src, srcLen, UBIDI_DEFAULT_RTL, NULL, &errorCode);
   1603     destLen = ubidi_writeReordered(bidi, dest, MAXLEN, 0, &errorCode);
   1604     srcLen = u_unescape("\\u200fabc \\u05d1\\u05d0", src, MAXLEN);
   1605     if (destLen != 7 || memcmp(dest, src, destLen * sizeof(UChar))) {
   1606         log_err("\nWrong result #7, should be '%s', got '%s'\n",
   1607                 aescstrdup(src, srcLen), aescstrdup(dest, destLen));
   1608     }
   1609     RETURN_IF_BAD_ERRCODE("#17#");
   1610     srcLen = u_unescape("\\u05d0\\u05d1 abc .-=", src, MAXLEN);
   1611     ubidi_setPara(bidi, src, srcLen, UBIDI_DEFAULT_RTL, NULL, &errorCode);
   1612     destLen = ubidi_writeReordered(bidi, dest, MAXLEN, 0, &errorCode);
   1613     srcLen = u_unescape("\\u200f=-. abc \\u05d1\\u05d0", src, MAXLEN);
   1614     if (destLen != 11 || memcmp(dest, src, destLen * sizeof(UChar))) {
   1615         log_err("\nWrong result #8, should be '%s', got '%s'\n",
   1616                 aescstrdup(src, srcLen), aescstrdup(dest, destLen));
   1617     }
   1618     RETURN_IF_BAD_ERRCODE("#18#");
   1619     ubidi_orderParagraphsLTR(bidi, TRUE);
   1620     srcLen = u_unescape("\n\r   \n\rabc\n\\u05d0\\u05d1\rabc \\u05d2\\u05d3\n\r"
   1621                         "\\u05d4\\u05d5 abc\n\\u05d6\\u05d7 abc .-=\r\n"
   1622                         "-* \\u05d8\\u05d9 abc .-=", src, MAXLEN);
   1623     ubidi_setPara(bidi, src, srcLen, UBIDI_DEFAULT_RTL, NULL, &errorCode);
   1624     destLen = ubidi_writeReordered(bidi, dest, MAXLEN, 0, &errorCode);
   1625     srcLen = u_unescape("\n\r   \n\rabc\n\\u05d1\\u05d0\r\\u05d3\\u05d2 abc\n\r"
   1626                         "\\u200fabc \\u05d5\\u05d4\n\\u200f=-. abc \\u05d7\\u05d6\r\n"
   1627                         "\\u200f=-. abc \\u05d9\\u05d8 *-", src, MAXLEN);
   1628     if (destLen != 57 || memcmp(dest, src, destLen * sizeof(UChar))) {
   1629         log_err("\nWrong result #9, should be '%s', got '%s'\n",
   1630                 aescstrdup(src, srcLen), aescstrdup(dest, destLen));
   1631     }
   1632     RETURN_IF_BAD_ERRCODE("#19#");
   1633     srcLen = u_unescape("\\u05d0 \t", src, MAXLEN);
   1634     ubidi_setPara(bidi, src, srcLen, UBIDI_LTR, NULL, &errorCode);
   1635     destLen = ubidi_writeReordered(bidi, dest, MAXLEN, 0, &errorCode);
   1636     srcLen = u_unescape("\\u05D0\\u200e \t", src, MAXLEN);
   1637     if (destLen != 4 || memcmp(dest, src, destLen * sizeof(UChar))) {
   1638         log_err("\nWrong result #10, should be '%s', got '%s'\n",
   1639                 aescstrdup(src, srcLen), aescstrdup(dest, destLen));
   1640     }
   1641     RETURN_IF_BAD_ERRCODE("#20#");
   1642     srcLen = u_unescape("\\u05d0 123 \t\\u05d1 123 \\u05d2", src, MAXLEN);
   1643     ubidi_setPara(bidi, src, srcLen, UBIDI_LTR, NULL, &errorCode);
   1644     destLen = ubidi_writeReordered(bidi, dest, MAXLEN, 0, &errorCode);
   1645     srcLen = u_unescape("\\u05d0 \\u200e123\\u200e \t\\u05d2 123 \\u05d1", src, MAXLEN);
   1646     if (destLen != 16 || memcmp(dest, src, destLen * sizeof(UChar))) {
   1647         log_err("\nWrong result #11, should be '%s', got '%s'\n",
   1648                 aescstrdup(src, srcLen), aescstrdup(dest, destLen));
   1649     }
   1650     RETURN_IF_BAD_ERRCODE("#21#");
   1651     srcLen = u_unescape("\\u05d0 123 \\u0660\\u0661 ab", src, MAXLEN);
   1652     ubidi_setPara(bidi, src, srcLen, UBIDI_LTR, NULL, &errorCode);
   1653     destLen = ubidi_writeReordered(bidi, dest, MAXLEN, 0, &errorCode);
   1654     srcLen = u_unescape("\\u05d0 \\u200e123 \\u200e\\u0660\\u0661 ab", src, MAXLEN);
   1655     if (destLen != 13 || memcmp(dest, src, destLen * sizeof(UChar))) {
   1656         log_err("\nWrong result #12, should be '%s', got '%s'\n",
   1657                 aescstrdup(src, srcLen), aescstrdup(dest, destLen));
   1658     }
   1659     RETURN_IF_BAD_ERRCODE("#22#");
   1660     srcLen = u_unescape("ab \t", src, MAXLEN);
   1661     ubidi_setPara(bidi, src, srcLen, UBIDI_RTL, NULL, &errorCode);
   1662     destLen = ubidi_writeReordered(bidi, dest, MAXLEN, 0, &errorCode);
   1663     srcLen = u_unescape("\\u200f\t ab", src, MAXLEN);
   1664     if (destLen != 5 || memcmp(dest, src, destLen * sizeof(UChar))) {
   1665         log_err("\nWrong result #13, should be '%s', got '%s'\n",
   1666                 aescstrdup(src, srcLen), aescstrdup(dest, destLen));
   1667     }
   1668     RETURN_IF_BAD_ERRCODE("#23#");
   1669 
   1670     /* check exceeding para level */
   1671     ubidi_close(bidi);
   1672     bidi = ubidi_open();
   1673     srcLen = u_unescape("A\\u202a\\u05d0\\u202aC\\u202c\\u05d1\\u202cE", src, MAXLEN);
   1674     ubidi_setPara(bidi, src, srcLen, UBIDI_MAX_EXPLICIT_LEVEL - 1, NULL, &errorCode);
   1675     level = ubidi_getLevelAt(bidi, 2);
   1676     if (level != UBIDI_MAX_EXPLICIT_LEVEL) {
   1677         log_err("\nWrong level at index 2\n, should be %d, got %d\n", UBIDI_MAX_EXPLICIT_LEVEL, level);
   1678     }
   1679     RETURN_IF_BAD_ERRCODE("#24#");
   1680 
   1681     /* check 1-char runs with RUNS_ONLY */
   1682     ubidi_setReorderingMode(bidi, UBIDI_REORDER_RUNS_ONLY);
   1683     srcLen = u_unescape("a \\u05d0 b \\u05d1 c \\u05d2 d ", src, MAXLEN);
   1684     ubidi_setPara(bidi, src, srcLen, UBIDI_LTR, NULL, &errorCode);
   1685     runCount = ubidi_countRuns(bidi, &errorCode);
   1686     if (runCount != 14) {
   1687         log_err("\nWrong number of runs #3, should be 14, got %d\n", runCount);
   1688     }
   1689     RETURN_IF_BAD_ERRCODE("#25#");
   1690 
   1691     ubidi_close(bidi);
   1692     ubidi_close(bidiLine);
   1693 }
   1694 
   1695 static void
   1696 testFailureRecovery(void) {
   1697     UErrorCode errorCode;
   1698     UBiDi *bidi, *bidiLine;
   1699     UChar src[MAXLEN];
   1700     int32_t srcLen;
   1701     UBiDiLevel level;
   1702     UBiDiReorderingMode rm;
   1703     static UBiDiLevel myLevels[3] = {6,5,4};
   1704 
   1705     log_verbose("\nEntering TestFailureRecovery\n\n");
   1706     errorCode = U_FILE_ACCESS_ERROR;
   1707     if (ubidi_writeReordered(NULL, NULL, 0, 0, &errorCode) != 0) {
   1708         log_err("ubidi_writeReordered did not return 0 when passed a failing UErrorCode\n");
   1709     }
   1710     if (ubidi_writeReverse(NULL, 0, NULL, 0, 0, &errorCode) != 0) {
   1711         log_err("ubidi_writeReverse did not return 0 when passed a failing UErrorCode\n");
   1712     }
   1713     errorCode = U_ZERO_ERROR;
   1714     if (ubidi_writeReordered(NULL, NULL, 0, 0, &errorCode) != 0 || errorCode != U_ILLEGAL_ARGUMENT_ERROR) {
   1715         log_err("ubidi_writeReordered did not fail as expected\n");
   1716     }
   1717 
   1718     bidi = ubidi_open();
   1719     srcLen = u_unescape("abc", src, MAXLEN);
   1720     errorCode = U_ZERO_ERROR;
   1721     ubidi_setPara(bidi, src, srcLen, UBIDI_DEFAULT_LTR - 1, NULL, &errorCode);
   1722     if (U_SUCCESS(errorCode)) {
   1723         log_err("\nubidi_setPara did not fail when passed too big para level\n");
   1724     }
   1725     errorCode = U_ZERO_ERROR;
   1726     if (ubidi_writeReverse(NULL, 0, NULL, 0, 0, &errorCode) != 0 || errorCode != U_ILLEGAL_ARGUMENT_ERROR) {
   1727         log_err("ubidi_writeReverse did not fail as expected\n");
   1728     }
   1729     bidiLine = ubidi_open();
   1730     errorCode = U_ZERO_ERROR;
   1731     ubidi_setLine(bidi, 0, 6, bidiLine, &errorCode);
   1732     if (U_SUCCESS(errorCode)) {
   1733         log_err("\nubidi_setLine did not fail when called before valid setPara()\n");
   1734     }
   1735     errorCode = U_ZERO_ERROR;
   1736     srcLen = u_unescape("abc", src, MAXLEN);
   1737     ubidi_setPara(bidi, src, srcLen, UBIDI_LTR + 4, NULL, &errorCode);
   1738     level = ubidi_getLevelAt(bidi, 3);
   1739     if (level != 0) {
   1740         log_err("\nubidi_getLevelAt did not fail when called with bad argument\n");
   1741     }
   1742     errorCode = U_ZERO_ERROR;
   1743     ubidi_close(bidi);
   1744     bidi = ubidi_openSized(-1, 0, &errorCode);
   1745     if (U_SUCCESS(errorCode)) {
   1746         log_err("\nubidi_openSized did not fail when called with bad argument\n");
   1747     }
   1748     ubidi_close(bidi);
   1749     bidi = ubidi_openSized(2, 1, &errorCode);
   1750     errorCode = U_ZERO_ERROR;
   1751     srcLen = u_unescape("abc", src, MAXLEN);
   1752     ubidi_setPara(bidi, src, srcLen, UBIDI_LTR, NULL, &errorCode);
   1753     if (U_SUCCESS(errorCode)) {
   1754         log_err("\nsetPara did not fail when called with text too long\n");
   1755     }
   1756     errorCode = U_ZERO_ERROR;
   1757     srcLen = u_unescape("=2", src, MAXLEN);
   1758     ubidi_setPara(bidi, src, srcLen, UBIDI_RTL, NULL, &errorCode);
   1759     ubidi_countRuns(bidi, &errorCode);
   1760     if (U_SUCCESS(errorCode)) {
   1761         log_err("\nsetPara did not fail when called for too many runs\n");
   1762     }
   1763     ubidi_close(bidi);
   1764     bidi = ubidi_open();
   1765     rm = ubidi_getReorderingMode(bidi);
   1766     ubidi_setReorderingMode(bidi, UBIDI_REORDER_DEFAULT - 1);
   1767     if (rm != ubidi_getReorderingMode(bidi)) {
   1768         log_err("\nsetReorderingMode with bad argument #1 should have no effect\n");
   1769     }
   1770     ubidi_setReorderingMode(bidi, 9999);
   1771     if (rm != ubidi_getReorderingMode(bidi)) {
   1772         log_err("\nsetReorderingMode with bad argument #2 should have no effect\n");
   1773     }
   1774 
   1775     /* Try a surrogate char */
   1776     errorCode = U_ZERO_ERROR;
   1777     srcLen = u_unescape("\\uD800\\uDC00", src, MAXLEN);
   1778     ubidi_setPara(bidi, src, srcLen, UBIDI_RTL, NULL, &errorCode);
   1779     if (ubidi_getDirection(bidi) != UBIDI_MIXED) {
   1780         log_err("\ngetDirection for 1st surrogate char should be MIXED\n");
   1781     }
   1782     errorCode = U_ZERO_ERROR;
   1783     srcLen = u_unescape("abc", src, MAXLEN);
   1784     ubidi_setPara(bidi, src, srcLen, 5, myLevels, &errorCode);
   1785     if (U_SUCCESS(errorCode)) {
   1786         log_err("\nsetPara did not fail when called with bad levels\n");
   1787     }
   1788     ubidi_close(bidi);
   1789     ubidi_close(bidiLine);
   1790 
   1791     log_verbose("\nExiting TestFailureRecovery\n\n");
   1792 }
   1793 
   1794 static void
   1795 testMultipleParagraphs(void) {
   1796     static const char* const text = "__ABC\\u001c"          /* Para #0 offset 0 */
   1797                                     "__\\u05d0DE\\u001c"    /*       1        6 */
   1798                                     "__123\\u001c"          /*       2       12 */
   1799                                     "\\u000d\\u000a"        /*       3       18 */
   1800                                     "FG\\u000d"             /*       4       20 */
   1801                                     "\\u000d"               /*       5       23 */
   1802                                     "HI\\u000d\\u000a"      /*       6       24 */
   1803                                     "\\u000d\\u000a"        /*       7       28 */
   1804                                     "\\u000a"               /*       8       30 */
   1805                                     "\\u000a"               /*       9       31 */
   1806                                     "JK\\u001c";            /*      10       32 */
   1807     static const int32_t paraCount=11;
   1808     static const int32_t paraBounds[]={0, 6, 12, 18, 20, 23, 24, 28, 30, 31, 32, 35};
   1809     static const UBiDiLevel paraLevels[]={UBIDI_LTR, UBIDI_RTL, UBIDI_DEFAULT_LTR, UBIDI_DEFAULT_RTL, 22, 23};
   1810     static const UBiDiLevel multiLevels[6][11] = {{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
   1811                                                   {1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1},
   1812                                                   {0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0},
   1813                                                   {0, 1, 1, 1, 0, 1, 0, 1, 1, 1, 0},
   1814                                                   {22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22},
   1815                                                   {23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23}};
   1816     static const char* const text2 = "\\u05d0 1-2\\u001c\\u0630 1-2\\u001c1-2";
   1817     static const UBiDiLevel levels2[] = {1,1,2,2,2,0, 1,1,2,1,2,0, 2,2,2};
   1818     static UBiDiLevel myLevels[10] = {0,0,0,0,0,0,0,0,0,0};
   1819     static const UChar multiparaTestString[] = {
   1820         0x5de, 0x5e0, 0x5e1, 0x5d4, 0x20,  0x5e1, 0x5e4, 0x5da,
   1821         0x20,  0xa,   0xa,   0x41,  0x72,  0x74,  0x69,  0x73,
   1822         0x74,  0x3a,  0x20,  0x5de, 0x5e0, 0x5e1, 0x5d4, 0x20,
   1823         0x5e1, 0x5e4, 0x5da, 0x20,  0xa,   0xa,   0x41,  0x6c,
   1824         0x62,  0x75,  0x6d,  0x3a,  0x20,  0x5de, 0x5e0, 0x5e1,
   1825         0x5d4, 0x20,  0x5e1, 0x5e4, 0x5da, 0x20,  0xa,   0xa,
   1826         0x54,  0x69,  0x6d,  0x65,  0x3a,  0x20,  0x32,  0x3a,
   1827         0x32,  0x37,  0xa,  0xa
   1828     };
   1829     static const UBiDiLevel multiparaTestLevels[] = {
   1830         1, 1, 1, 1, 1, 1, 1, 1,
   1831         1, 1, 0, 0, 0, 0, 0, 0,
   1832         0, 0, 0, 1, 1, 1, 1, 1,
   1833         1, 1, 1, 0, 0, 0, 0, 0,
   1834         0, 0, 0, 0, 0, 1, 1, 1,
   1835         1, 1, 1, 1, 1, 0, 0, 0,
   1836         0, 0, 0, 0, 0, 0, 0, 0,
   1837         0, 0, 0, 0
   1838     };
   1839     UBiDiLevel gotLevel;
   1840     const UBiDiLevel* gotLevels;
   1841     UBool orderParagraphsLTR;
   1842     UChar src[MAXLEN], dest[MAXLEN];
   1843     UErrorCode errorCode=U_ZERO_ERROR;
   1844     UBiDi* pBidi=ubidi_open();
   1845     UBiDi* pLine;
   1846     int32_t srcSize, count, paraStart, paraLimit, paraIndex, length;
   1847     int32_t srcLen, destLen;
   1848     int i, j, k;
   1849 
   1850     log_verbose("\nEntering TestMultipleParagraphs\n\n");
   1851     u_unescape(text, src, MAXLEN);
   1852     srcSize=u_strlen(src);
   1853     ubidi_setPara(pBidi, src, srcSize, UBIDI_LTR, NULL, &errorCode);
   1854     if(U_FAILURE(errorCode)){
   1855         log_err("ubidi_setPara failed, paraLevel=%d, errorCode %s\n",
   1856                 UBIDI_LTR, u_errorName(errorCode));
   1857         ubidi_close(pBidi);
   1858         return;
   1859     }
   1860     /* check paragraph count and boundaries */
   1861     if (paraCount!=(count=ubidi_countParagraphs(pBidi))) {
   1862         log_err("ubidi_countParagraphs returned %d, should be %d\n",
   1863                 count, paraCount);
   1864     }
   1865     for (i=0; i<paraCount; i++) {
   1866         ubidi_getParagraphByIndex(pBidi, i, &paraStart, &paraLimit, NULL, &errorCode);
   1867         if ((paraStart!=paraBounds[i]) || (paraLimit!=paraBounds[i+1])) {
   1868             log_err("Found boundaries of paragraph %d: %d-%d; expected: %d-%d\n",
   1869                     i, paraStart, paraLimit, paraBounds[i], paraBounds[i+1]);
   1870         }
   1871     }
   1872     errorCode=U_ZERO_ERROR;
   1873     /* check with last paragraph not terminated by B */
   1874     src[srcSize-1]='L';
   1875     ubidi_setPara(pBidi, src, srcSize, UBIDI_LTR, NULL, &errorCode);
   1876     if(U_FAILURE(errorCode)){
   1877         log_err("2nd ubidi_setPara failed, paraLevel=%d, errorCode %s\n",
   1878                 UBIDI_LTR, u_errorName(errorCode));
   1879         ubidi_close(pBidi);
   1880         return;
   1881     }
   1882     if (paraCount!=(count=ubidi_countParagraphs(pBidi))) {
   1883         log_err("2nd ubidi_countParagraphs returned %d, should be %d\n",
   1884                 count, paraCount);
   1885     }
   1886     i=paraCount-1;
   1887     ubidi_getParagraphByIndex(pBidi, i, &paraStart, &paraLimit, NULL, &errorCode);
   1888     if ((paraStart!=paraBounds[i]) || (paraLimit!=paraBounds[i+1])) {
   1889         log_err("2nd Found boundaries of paragraph %d: %d-%d; expected: %d-%d\n",
   1890                 i, paraStart, paraLimit, paraBounds[i], paraBounds[i+1]);
   1891     }
   1892     errorCode=U_ZERO_ERROR;
   1893     /* check paraLevel for all paragraphs under various paraLevel specs */
   1894     for (k=0; k<6; k++) {
   1895         ubidi_setPara(pBidi, src, srcSize, paraLevels[k], NULL, &errorCode);
   1896         for (i=0; i<paraCount; i++) {
   1897             paraIndex=ubidi_getParagraph(pBidi, paraBounds[i], NULL, NULL, &gotLevel, &errorCode);
   1898             if (paraIndex!=i) {
   1899                 log_err("For paraLevel=%d paragraph=%d, found paragraph index=%d expected=%d\n",
   1900                         paraLevels[k], i, paraIndex, i);
   1901             }
   1902             if (gotLevel!=multiLevels[k][i]) {
   1903                 log_err("For paraLevel=%d paragraph=%d, found level=%d expected %d\n",
   1904                         paraLevels[k], i, gotLevel, multiLevels[k][i]);
   1905             }
   1906         }
   1907         gotLevel=ubidi_getParaLevel(pBidi);
   1908         if (gotLevel!=multiLevels[k][0]) {
   1909             log_err("For paraLevel=%d getParaLevel=%d, expected %d\n",
   1910                     paraLevels[k], gotLevel, multiLevels[k][0]);
   1911         }
   1912     }
   1913     errorCode=U_ZERO_ERROR;
   1914     /* check that the result of ubidi_getParaLevel changes if the first
   1915      * paragraph has a different level
   1916      */
   1917     src[0]=0x05d2;                      /* Hebrew letter Gimel */
   1918     ubidi_setPara(pBidi, src, srcSize, UBIDI_DEFAULT_LTR, NULL, &errorCode);
   1919     gotLevel=ubidi_getParaLevel(pBidi);
   1920     if (gotLevel!=UBIDI_RTL) {
   1921         log_err("For paraLevel=UBIDI_DEFAULT_LTR getParaLevel=%d, expected=%d\n",
   1922                         gotLevel, UBIDI_RTL);
   1923     }
   1924     errorCode=U_ZERO_ERROR;
   1925     /* check that line cannot overlap paragraph boundaries */
   1926     pLine=ubidi_open();
   1927     i=paraBounds[1];
   1928     k=paraBounds[2]+1;
   1929     ubidi_setLine(pBidi, i, k, pLine, &errorCode);
   1930     if (U_SUCCESS(errorCode)) {
   1931         log_err("For line limits %d-%d got success %s\n",
   1932                 i, k, u_errorName(errorCode));
   1933     }
   1934     errorCode=U_ZERO_ERROR;
   1935     i=paraBounds[1];
   1936     k=paraBounds[2];
   1937     ubidi_setLine(pBidi, i, k, pLine, &errorCode);
   1938     if (U_FAILURE(errorCode)) {
   1939         log_err("For line limits %d-%d got error %s\n",
   1940                 i, k, u_errorName(errorCode));
   1941         errorCode=U_ZERO_ERROR;
   1942     }
   1943     /* check level of block separator at end of paragraph when orderParagraphsLTR==FALSE */
   1944     ubidi_setPara(pBidi, src, srcSize, UBIDI_RTL, NULL, &errorCode);
   1945     /* get levels through para Bidi block */
   1946     gotLevels=ubidi_getLevels(pBidi, &errorCode);
   1947     if (U_FAILURE(errorCode)) {
   1948         log_err("Error on Para getLevels %s\n", u_errorName(errorCode));
   1949         ubidi_close(pLine);
   1950         ubidi_close(pBidi);
   1951         return;
   1952     }
   1953     for (i=26; i<32; i++) {
   1954         if (gotLevels[i]!=UBIDI_RTL) {
   1955             log_err("For char %d(%04x), level=%d, expected=%d\n",
   1956                     i, src[i], gotLevels[i], UBIDI_RTL);
   1957         }
   1958     }
   1959     /* get levels through para Line block */
   1960     i=paraBounds[1];
   1961     k=paraBounds[2];
   1962     ubidi_setLine(pBidi, i, k, pLine, &errorCode);
   1963     if (U_FAILURE(errorCode)) {
   1964         log_err("For line limits %d-%d got error %s\n",
   1965                 i, k, u_errorName(errorCode));
   1966         ubidi_close(pLine);
   1967         ubidi_close(pBidi);
   1968         return;
   1969     }
   1970     paraIndex=ubidi_getParagraph(pLine, i, &paraStart, &paraLimit, &gotLevel, &errorCode);
   1971     gotLevels=ubidi_getLevels(pLine, &errorCode);
   1972     if (U_FAILURE(errorCode)) {
   1973         log_err("Error on Line getLevels %s\n", u_errorName(errorCode));
   1974         ubidi_close(pLine);
   1975         ubidi_close(pBidi);
   1976         return;
   1977     }
   1978     length=ubidi_getLength(pLine);
   1979     if ((gotLevel!=UBIDI_RTL) || (gotLevels[length-1]!=UBIDI_RTL)) {
   1980         log_err("For paragraph %d with limits %d-%d, paraLevel=%d expected=%d, "
   1981                 "level of separator=%d expected=%d\n",
   1982                 paraIndex, paraStart, paraLimit, gotLevel, UBIDI_RTL, gotLevels[length-1], UBIDI_RTL);
   1983     }
   1984     orderParagraphsLTR=ubidi_isOrderParagraphsLTR(pBidi);
   1985     if (orderParagraphsLTR) {
   1986         log_err("Found orderParagraphsLTR=%d expected=%d\n", orderParagraphsLTR, FALSE);
   1987     }
   1988     ubidi_orderParagraphsLTR(pBidi, TRUE);
   1989     orderParagraphsLTR=ubidi_isOrderParagraphsLTR(pBidi);
   1990     if (!orderParagraphsLTR) {
   1991         log_err("Found orderParagraphsLTR=%d expected=%d\n", orderParagraphsLTR, TRUE);
   1992     }
   1993     /* check level of block separator at end of paragraph when orderParagraphsLTR==TRUE */
   1994     ubidi_setPara(pBidi, src, srcSize, UBIDI_RTL, NULL, &errorCode);
   1995     /* get levels through para Bidi block */
   1996     gotLevels=ubidi_getLevels(pBidi, &errorCode);
   1997     for (i=26; i<32; i++) {
   1998         if (gotLevels[i]!=0) {
   1999             log_err("For char %d(%04x), level=%d, expected=%d\n",
   2000                     i, src[i], gotLevels[i], 0);
   2001         }
   2002     }
   2003     errorCode=U_ZERO_ERROR;
   2004     /* get levels through para Line block */
   2005     i=paraBounds[1];
   2006     k=paraBounds[2];
   2007     ubidi_setLine(pBidi, paraStart, paraLimit, pLine, &errorCode);
   2008     paraIndex=ubidi_getParagraph(pLine, i, &paraStart, &paraLimit, &gotLevel, &errorCode);
   2009     gotLevels=ubidi_getLevels(pLine, &errorCode);
   2010     length=ubidi_getLength(pLine);
   2011     if ((gotLevel!=UBIDI_RTL) || (gotLevels[length-1]!=0)) {
   2012         log_err("For paragraph %d with limits %d-%d, paraLevel=%d expected=%d, "
   2013                 "level of separator=%d expected=%d\n",
   2014                 paraIndex, paraStart, paraLimit, gotLevel, UBIDI_RTL, gotLevels[length-1], 0);
   2015         log_verbose("levels=");
   2016         for (count=0; count<length; count++) {
   2017             log_verbose(" %d", gotLevels[count]);
   2018         }
   2019         log_verbose("\n");
   2020     }
   2021 
   2022     /* test that the concatenation of separate invocations of the bidi code
   2023      * on each individual paragraph in order matches the levels array that
   2024      * results from invoking bidi once over the entire multiparagraph tests
   2025      * (with orderParagraphsLTR false, of course)
   2026      */
   2027     u_unescape(text, src, MAXLEN);      /* restore original content */
   2028     srcSize=u_strlen(src);
   2029     ubidi_orderParagraphsLTR(pBidi, FALSE);
   2030     ubidi_setPara(pBidi, src, srcSize, UBIDI_DEFAULT_RTL, NULL, &errorCode);
   2031     gotLevels=ubidi_getLevels(pBidi, &errorCode);
   2032     for (i=0; i<paraCount; i++) {
   2033         /* use pLine for individual paragraphs */
   2034         paraStart = paraBounds[i];
   2035         length = paraBounds[i+1] - paraStart;
   2036         ubidi_setPara(pLine, src+paraStart, length, UBIDI_DEFAULT_RTL, NULL, &errorCode);
   2037         for (j=0; j<length; j++) {
   2038             if ((k=ubidi_getLevelAt(pLine, j)) != (gotLevel=gotLevels[paraStart+j])) {
   2039                 log_err("Checking paragraph concatenation: for paragraph=%d, "
   2040                         "char=%d(%04x), level=%d, expected=%d\n",
   2041                         i, j, src[paraStart+j], k, gotLevel);
   2042             }
   2043         }
   2044     }
   2045 
   2046     /* ensure that leading numerics in a paragraph are not treated as arabic
   2047        numerals because of arabic text in a preceding paragraph
   2048      */
   2049     u_unescape(text2, src, MAXLEN);
   2050     srcSize=u_strlen(src);
   2051     ubidi_orderParagraphsLTR(pBidi, TRUE);
   2052     ubidi_setPara(pBidi, src, srcSize, UBIDI_RTL, NULL, &errorCode);
   2053     gotLevels=ubidi_getLevels(pBidi, &errorCode);
   2054     if (U_FAILURE(errorCode)) {
   2055         log_err("Can't get levels. %s\n", u_errorName(errorCode));
   2056         return;
   2057     }
   2058     for (i=0; i<srcSize; i++) {
   2059         if (gotLevels[i]!=levels2[i]) {
   2060             log_err("Checking leading numerics: for char %d(%04x), level=%d, expected=%d\n",
   2061                     i, src[i], gotLevels[i], levels2[i]);
   2062         }
   2063     }
   2064 
   2065     /* check handling of whitespace before end of paragraph separator when
   2066      * orderParagraphsLTR==TRUE, when last paragraph has, and lacks, a terminating B
   2067      */
   2068     u_memset(src, 0x0020, MAXLEN);
   2069     srcSize = 5;
   2070     ubidi_orderParagraphsLTR(pBidi, TRUE);
   2071     for (i=0x001c; i<=0x0020; i+=(0x0020-0x001c)) {
   2072         src[4]=(UChar)i;                /* with and without terminating B */
   2073         for (j=0x0041; j<=0x05d0; j+=(0x05d0-0x0041)) {
   2074             src[0]=(UChar)j;            /* leading 'A' or Alef */
   2075             for (gotLevel=4; gotLevel<=5; gotLevel++) {
   2076                 /* test even and odd paraLevel */
   2077                 ubidi_setPara(pBidi, src, srcSize, gotLevel, NULL, &errorCode);
   2078                 gotLevels=ubidi_getLevels(pBidi, &errorCode);
   2079                 for (k=1; k<=3; k++) {
   2080                     if (gotLevels[k]!=gotLevel) {
   2081                         log_err("Checking trailing spaces: for leading_char=%04x, "
   2082                                 "last_char=%04x, index=%d, level=%d, expected=%d\n",
   2083                                 src[0], src[4], k, gotLevels[k], gotLevel);
   2084                     }
   2085                 }
   2086             }
   2087         }
   2088     }
   2089 
   2090     /* check default orientation when inverse bidi and paragraph starts
   2091      * with LTR strong char and ends with RTL strong char, with and without
   2092      * a terminating B
   2093      */
   2094     ubidi_setReorderingMode(pBidi, UBIDI_REORDER_INVERSE_LIKE_DIRECT);
   2095     srcLen = u_unescape("abc \\u05d2\\u05d1\n", src, MAXLEN);
   2096     ubidi_setPara(pBidi, src, srcLen, UBIDI_DEFAULT_LTR, NULL, &errorCode);
   2097     destLen = ubidi_writeReordered(pBidi, dest, MAXLEN, 0, &errorCode);
   2098     srcLen = u_unescape("\\u05d1\\u05d2 abc\n", src, MAXLEN);
   2099     if (memcmp(src, dest, destLen * sizeof(UChar))) {
   2100         log_err("\nInvalid output #0, should be '%s', got '%s'\n",
   2101                 aescstrdup(src, srcLen), aescstrdup(dest, destLen));
   2102     }
   2103     srcLen = u_unescape("abc \\u05d2\\u05d1", src, MAXLEN);
   2104     ubidi_setPara(pBidi, src, srcLen, UBIDI_DEFAULT_LTR, NULL, &errorCode);
   2105     destLen = ubidi_writeReordered(pBidi, dest, MAXLEN, 0, &errorCode);
   2106     srcLen = u_unescape("\\u05d1\\u05d2 abc", src, MAXLEN);
   2107     if (memcmp(src, dest, destLen * sizeof(UChar))) {
   2108         log_err("\nInvalid output #1, should be '%s', got '%s'\n",
   2109                 aescstrdup(src, srcLen), aescstrdup(dest, destLen));
   2110     }
   2111 
   2112     /* check multiple paragraphs together with explicit levels
   2113      */
   2114     ubidi_setReorderingMode(pBidi, UBIDI_REORDER_DEFAULT);
   2115     srcLen = u_unescape("ab\\u05d1\\u05d2\n\\u05d3\\u05d4123", src, MAXLEN);
   2116     ubidi_setPara(pBidi, src, srcLen, UBIDI_LTR, myLevels, &errorCode);
   2117     destLen = ubidi_writeReordered(pBidi, dest, MAXLEN, 0, &errorCode);
   2118     srcLen = u_unescape("ab\\u05d2\\u05d1\\n123\\u05d4\\u05d3", src, MAXLEN);
   2119     if (memcmp(src, dest, destLen * sizeof(UChar))) {
   2120         log_err("\nInvalid output #2, should be '%s', got '%s'\n",
   2121                 aescstrdup(src, srcLen), aescstrdup(dest, destLen));
   2122     }
   2123     count = ubidi_countParagraphs(pBidi);
   2124     if (count != 2) {
   2125         log_err("\nInvalid number of paras, should be 2, got %d\n", count);
   2126     }
   2127 
   2128     ubidi_close(pLine);
   2129     ubidi_close(pBidi);
   2130     log_verbose("\nExiting TestMultipleParagraphs\n\n");
   2131 
   2132     /* check levels in multiple paragraphs with default para level
   2133      */
   2134     pBidi = ubidi_open();
   2135     errorCode = U_ZERO_ERROR;
   2136     ubidi_setPara(pBidi, multiparaTestString, UPRV_LENGTHOF(multiparaTestString),
   2137                   UBIDI_DEFAULT_LTR, NULL, &errorCode);
   2138     if (U_FAILURE(errorCode)) {
   2139         log_err("ubidi_setPara failed for multiparaTestString\n");
   2140         ubidi_close(pBidi);
   2141         return;
   2142     }
   2143     gotLevels = ubidi_getLevels(pBidi, &errorCode);
   2144     if (U_FAILURE(errorCode)) {
   2145         log_err("ubidi_getLevels failed for multiparaTestString\n");
   2146         ubidi_close(pBidi);
   2147         return;
   2148     }
   2149     for (i = 0; i < UPRV_LENGTHOF(multiparaTestString); i++) {
   2150         if (gotLevels[i] != multiparaTestLevels[i]) {
   2151             log_err("Error on level for multiparaTestString at index %d, "
   2152                     "expected=%d, actual=%d\n",
   2153                     i, multiparaTestLevels[i], gotLevels[i]);
   2154         }
   2155     }
   2156     ubidi_close(pBidi);
   2157 
   2158 }
   2159 
   2160 
   2161 /* inverse BiDi ------------------------------------------------------------- */
   2162 
   2163 static int countRoundtrips=0, countNonRoundtrips=0;
   2164 
   2165 #define STRING_TEST_CASE(s) { (s), UPRV_LENGTHOF(s) }
   2166 
   2167 static void
   2168 testInverse(void) {
   2169     static const UChar
   2170         string0[]={ 0x6c, 0x61, 0x28, 0x74, 0x69, 0x6e, 0x20, 0x5d0, 0x5d1, 0x29, 0x5d2, 0x5d3 },
   2171         string1[]={ 0x6c, 0x61, 0x74, 0x20, 0x5d0, 0x5d1, 0x5d2, 0x20, 0x31, 0x32, 0x33 },
   2172         string2[]={ 0x6c, 0x61, 0x74, 0x20, 0x5d0, 0x28, 0x5d1, 0x5d2, 0x20, 0x31, 0x29, 0x32, 0x33 },
   2173         string3[]={ 0x31, 0x32, 0x33, 0x20, 0x5d0, 0x5d1, 0x5d2, 0x20, 0x34, 0x35, 0x36 },
   2174         string4[]={ 0x61, 0x62, 0x20, 0x61, 0x62, 0x20, 0x661, 0x662 };
   2175 
   2176     static const struct {
   2177         const UChar *s;
   2178         int32_t length;
   2179     } testCases[]={
   2180         STRING_TEST_CASE(string0),
   2181         STRING_TEST_CASE(string1),
   2182         STRING_TEST_CASE(string2),
   2183         STRING_TEST_CASE(string3),
   2184         STRING_TEST_CASE(string4)
   2185     };
   2186 
   2187     UBiDi *pBiDi;
   2188     UErrorCode errorCode;
   2189     int i;
   2190 
   2191     log_verbose("\nEntering TestInverse\n\n");
   2192     pBiDi=ubidi_open();
   2193     if(pBiDi==NULL) {
   2194         log_err("unable to open a UBiDi object (out of memory)\n");
   2195         return;
   2196     }
   2197 
   2198     log_verbose("inverse Bidi: testInverse(L) with %u test cases ---\n", UPRV_LENGTHOF(testCases));
   2199      for(i=0; i<UPRV_LENGTHOF(testCases); ++i) {
   2200         log_verbose("Testing case %d\n", i);
   2201         errorCode=U_ZERO_ERROR;
   2202         _testInverseBidi(pBiDi, testCases[i].s, testCases[i].length, 0, &errorCode);
   2203     }
   2204 
   2205     log_verbose("inverse Bidi: testInverse(R) with %u test cases ---\n", UPRV_LENGTHOF(testCases));
   2206     for(i=0; i<UPRV_LENGTHOF(testCases); ++i) {
   2207         log_verbose("Testing case %d\n", i);
   2208         errorCode=U_ZERO_ERROR;
   2209         _testInverseBidi(pBiDi, testCases[i].s, testCases[i].length, 1, &errorCode);
   2210     }
   2211 
   2212     _testManyInverseBidi(pBiDi, 0);
   2213     _testManyInverseBidi(pBiDi, 1);
   2214 
   2215     ubidi_close(pBiDi);
   2216 
   2217     log_verbose("inverse Bidi: rountrips: %5u\nnon-roundtrips: %5u\n", countRoundtrips, countNonRoundtrips);
   2218 
   2219     _testWriteReverse();
   2220 
   2221     _testManyAddedPoints();
   2222 
   2223     _testMisc();
   2224 
   2225     log_verbose("\nExiting TestInverse\n\n");
   2226 }
   2227 
   2228 #define COUNT_REPEAT_SEGMENTS 6
   2229 
   2230 static const UChar repeatSegments[COUNT_REPEAT_SEGMENTS][2]={
   2231     { 0x61, 0x62 },     /* L */
   2232     { 0x5d0, 0x5d1 },   /* R */
   2233     { 0x627, 0x628 },   /* AL */
   2234     { 0x31, 0x32 },     /* EN */
   2235     { 0x661, 0x662 },   /* AN */
   2236     { 0x20, 0x20 }      /* WS (N) */
   2237 };
   2238 
   2239 static void
   2240 _testManyInverseBidi(UBiDi *pBiDi, UBiDiLevel direction) {
   2241     UChar text[8]={ 0, 0, 0x20, 0, 0, 0x20, 0, 0 };
   2242     int i, j, k;
   2243     UErrorCode errorCode;
   2244 
   2245     log_verbose("inverse Bidi: testManyInverseBidi(%c) - test permutations of text snippets ---\n",
   2246                  direction==0 ? 'L' : 'R');
   2247     for(i=0; i<COUNT_REPEAT_SEGMENTS; ++i) {
   2248         text[0]=repeatSegments[i][0];
   2249         text[1]=repeatSegments[i][1];
   2250         for(j=0; j<COUNT_REPEAT_SEGMENTS; ++j) {
   2251             text[3]=repeatSegments[j][0];
   2252             text[4]=repeatSegments[j][1];
   2253             for(k=0; k<COUNT_REPEAT_SEGMENTS; ++k) {
   2254                 text[6]=repeatSegments[k][0];
   2255                 text[7]=repeatSegments[k][1];
   2256 
   2257                 errorCode=U_ZERO_ERROR;
   2258                 log_verbose("inverse Bidi: testManyInverseBidi()[%u %u %u]\n", i, j, k);
   2259                 _testInverseBidi(pBiDi, text, 8, direction, &errorCode);
   2260             }
   2261         }
   2262     }
   2263 }
   2264 
   2265 static void
   2266 _testInverseBidi(UBiDi *pBiDi, const UChar *src, int32_t srcLength,
   2267                 UBiDiLevel direction, UErrorCode *pErrorCode) {
   2268     UChar visualLTR[MAXLEN], logicalDest[MAXLEN], visualDest[MAXLEN];
   2269     int32_t ltrLength, logicalLength, visualLength;
   2270 
   2271     if(direction==0) {
   2272         log_verbose("inverse Bidi: testInverse(L)\n");
   2273 
   2274         /* convert visual to logical */
   2275         ubidi_setInverse(pBiDi, TRUE);
   2276         if (!ubidi_isInverse(pBiDi)) {
   2277             log_err("Error while doing ubidi_setInverse(TRUE)\n");
   2278         }
   2279         ubidi_setPara(pBiDi, src, srcLength, 0, NULL, pErrorCode);
   2280         if (src != ubidi_getText(pBiDi)) {
   2281             log_err("Wrong value returned by ubidi_getText\n");
   2282         }
   2283         logicalLength=ubidi_writeReordered(pBiDi, logicalDest, UPRV_LENGTHOF(logicalDest),
   2284                                            UBIDI_DO_MIRRORING|UBIDI_INSERT_LRM_FOR_NUMERIC, pErrorCode);
   2285         log_verbose("  v ");
   2286         printUnicode(src, srcLength, ubidi_getLevels(pBiDi, pErrorCode));
   2287         log_verbose("\n");
   2288 
   2289         /* convert back to visual LTR */
   2290         ubidi_setInverse(pBiDi, FALSE);
   2291         if (ubidi_isInverse(pBiDi)) {
   2292             log_err("Error while doing ubidi_setInverse(FALSE)\n");
   2293         }
   2294         ubidi_setPara(pBiDi, logicalDest, logicalLength, 0, NULL, pErrorCode);
   2295         visualLength=ubidi_writeReordered(pBiDi, visualDest, UPRV_LENGTHOF(visualDest),
   2296                                           UBIDI_DO_MIRRORING|UBIDI_REMOVE_BIDI_CONTROLS, pErrorCode);
   2297     } else {
   2298         log_verbose("inverse Bidi: testInverse(R)\n");
   2299 
   2300         /* reverse visual from RTL to LTR */
   2301         ltrLength=ubidi_writeReverse(src, srcLength, visualLTR, UPRV_LENGTHOF(visualLTR), 0, pErrorCode);
   2302         log_verbose("  vr");
   2303         printUnicode(src, srcLength, NULL);
   2304         log_verbose("\n");
   2305 
   2306         /* convert visual RTL to logical */
   2307         ubidi_setInverse(pBiDi, TRUE);
   2308         ubidi_setPara(pBiDi, visualLTR, ltrLength, 0, NULL, pErrorCode);
   2309         logicalLength=ubidi_writeReordered(pBiDi, logicalDest, UPRV_LENGTHOF(logicalDest),
   2310                                            UBIDI_DO_MIRRORING|UBIDI_INSERT_LRM_FOR_NUMERIC, pErrorCode);
   2311         log_verbose("  vl");
   2312         printUnicode(visualLTR, ltrLength, ubidi_getLevels(pBiDi, pErrorCode));
   2313         log_verbose("\n");
   2314 
   2315         /* convert back to visual RTL */
   2316         ubidi_setInverse(pBiDi, FALSE);
   2317         ubidi_setPara(pBiDi, logicalDest, logicalLength, 0, NULL, pErrorCode);
   2318         visualLength=ubidi_writeReordered(pBiDi, visualDest, UPRV_LENGTHOF(visualDest),
   2319                                           UBIDI_DO_MIRRORING|UBIDI_REMOVE_BIDI_CONTROLS|UBIDI_OUTPUT_REVERSE, pErrorCode);
   2320     }
   2321     log_verbose("  l ");
   2322     printUnicode(logicalDest, logicalLength, ubidi_getLevels(pBiDi, pErrorCode));
   2323     log_verbose("\n");
   2324     log_verbose("  v ");
   2325     printUnicode(visualDest, visualLength, NULL);
   2326     log_verbose("\n");
   2327 
   2328     /* check and print results */
   2329     if(U_FAILURE(*pErrorCode)) {
   2330         log_err("inverse BiDi: *** error %s\n"
   2331                 "                 turn on verbose mode to see details\n", u_errorName(*pErrorCode));
   2332     } else if(srcLength==visualLength && memcmp(src, visualDest, srcLength*U_SIZEOF_UCHAR)==0) {
   2333         ++countRoundtrips;
   2334         log_verbose(" + roundtripped\n");
   2335     } else {
   2336         ++countNonRoundtrips;
   2337         log_verbose(" * did not roundtrip\n");
   2338         log_err("inverse BiDi: transformation visual->logical->visual did not roundtrip the text;\n"
   2339                 "                 turn on verbose mode to see details\n");
   2340     }
   2341 }
   2342 
   2343 static void
   2344 _testWriteReverse(void) {
   2345     /* U+064e and U+0650 are combining marks (Mn) */
   2346     static const UChar forward[]={
   2347         0x200f, 0x627, 0x64e, 0x650, 0x20, 0x28, 0x31, 0x29
   2348     }, reverseKeepCombining[]={
   2349         0x29, 0x31, 0x28, 0x20, 0x627, 0x64e, 0x650, 0x200f
   2350     }, reverseRemoveControlsKeepCombiningDoMirror[]={
   2351         0x28, 0x31, 0x29, 0x20, 0x627, 0x64e, 0x650
   2352     };
   2353     UChar reverse[10];
   2354     UErrorCode errorCode;
   2355     int32_t length;
   2356 
   2357     /* test ubidi_writeReverse() with "interesting" options */
   2358     errorCode=U_ZERO_ERROR;
   2359     length=ubidi_writeReverse(forward, UPRV_LENGTHOF(forward),
   2360                               reverse, UPRV_LENGTHOF(reverse),
   2361                               UBIDI_KEEP_BASE_COMBINING,
   2362                               &errorCode);
   2363     if(U_FAILURE(errorCode) || length!=UPRV_LENGTHOF(reverseKeepCombining) || memcmp(reverse, reverseKeepCombining, length*U_SIZEOF_UCHAR)!=0) {
   2364         log_err("failure in ubidi_writeReverse(UBIDI_KEEP_BASE_COMBINING): length=%d (should be %d), error code %s\n",
   2365                 length, UPRV_LENGTHOF(reverseKeepCombining), u_errorName(errorCode));
   2366     }
   2367 
   2368     memset(reverse, 0xa5, UPRV_LENGTHOF(reverse)*U_SIZEOF_UCHAR);
   2369     errorCode=U_ZERO_ERROR;
   2370     length=ubidi_writeReverse(forward, UPRV_LENGTHOF(forward),
   2371                               reverse, UPRV_LENGTHOF(reverse),
   2372                               UBIDI_REMOVE_BIDI_CONTROLS|UBIDI_DO_MIRRORING|UBIDI_KEEP_BASE_COMBINING,
   2373                               &errorCode);
   2374     if(U_FAILURE(errorCode) || length!=UPRV_LENGTHOF(reverseRemoveControlsKeepCombiningDoMirror) || memcmp(reverse, reverseRemoveControlsKeepCombiningDoMirror, length*U_SIZEOF_UCHAR)!=0) {
   2375         log_err("failure in ubidi_writeReverse(UBIDI_REMOVE_BIDI_CONTROLS|UBIDI_DO_MIRRORING|UBIDI_KEEP_BASE_COMBINING):\n"
   2376                 "    length=%d (should be %d), error code %s\n",
   2377                 length, UPRV_LENGTHOF(reverseRemoveControlsKeepCombiningDoMirror), u_errorName(errorCode));
   2378     }
   2379 }
   2380 
   2381 static void _testManyAddedPoints(void) {
   2382     UErrorCode errorCode = U_ZERO_ERROR;
   2383     UBiDi *bidi = ubidi_open();
   2384     UChar text[90], dest[MAXLEN], expected[120];
   2385     int destLen, i;
   2386     for (i = 0; i < UPRV_LENGTHOF(text); i+=3) {
   2387         text[i] = 0x0061; /* 'a' */
   2388         text[i+1] = 0x05d0;
   2389         text[i+2] = 0x0033; /* '3' */
   2390     }
   2391     ubidi_setReorderingMode(bidi, UBIDI_REORDER_INVERSE_LIKE_DIRECT);
   2392     ubidi_setReorderingOptions(bidi, UBIDI_OPTION_INSERT_MARKS);
   2393     ubidi_setPara(bidi, text, UPRV_LENGTHOF(text), UBIDI_LTR, NULL, &errorCode);
   2394     destLen = ubidi_writeReordered(bidi, dest, MAXLEN, 0, &errorCode);
   2395     for (i = 0; i < UPRV_LENGTHOF(expected); i+=4) {
   2396         expected[i] = 0x0061; /* 'a' */
   2397         expected[i+1] = 0x05d0;
   2398         expected[i+2] = 0x200e;
   2399         expected[i+3] = 0x0033; /* '3' */
   2400     }
   2401     if (memcmp(dest, expected, destLen * sizeof(UChar))) {
   2402         log_err("\nInvalid output with many added points, "
   2403                 "expected '%s', got '%s'\n",
   2404                 aescstrdup(expected, UPRV_LENGTHOF(expected)),
   2405                 aescstrdup(dest, destLen));
   2406     }
   2407     ubidi_close(bidi);
   2408 }
   2409 
   2410 static void _testMisc(void) {
   2411     UErrorCode errorCode = U_ZERO_ERROR;
   2412     UBiDi *bidi = ubidi_open();
   2413     UChar src[3], dest[MAXLEN], expected[5];
   2414     int destLen;
   2415     ubidi_setInverse(bidi, TRUE);
   2416     src[0] = src[1] = src[2] = 0x0020;
   2417     ubidi_setPara(bidi, src, UPRV_LENGTHOF(src), UBIDI_RTL, NULL, &errorCode);
   2418     destLen = ubidi_writeReordered(bidi, dest, MAXLEN,
   2419               UBIDI_OUTPUT_REVERSE | UBIDI_INSERT_LRM_FOR_NUMERIC,
   2420               &errorCode);
   2421     u_unescape("\\u200f   \\u200f", expected, 5);
   2422     if (memcmp(dest, expected, destLen * sizeof(UChar))) {
   2423         log_err("\nInvalid output with RLM at both sides, "
   2424                 "expected '%s', got '%s'\n",
   2425                 aescstrdup(expected, UPRV_LENGTHOF(expected)),
   2426                 aescstrdup(dest, destLen));
   2427     }
   2428     ubidi_close(bidi);
   2429 }
   2430 
   2431 /* arabic shaping ----------------------------------------------------------- */
   2432 
   2433 static void
   2434 doArabicShapingTest(void) {
   2435     static const UChar
   2436     source[]={
   2437         0x31,   /* en:1 */
   2438         0x627,  /* arabic:alef */
   2439         0x32,   /* en:2 */
   2440         0x6f3,  /* an:3 */
   2441         0x61,   /* latin:a */
   2442         0x34,   /* en:4 */
   2443         0
   2444     }, en2an[]={
   2445         0x661, 0x627, 0x662, 0x6f3, 0x61, 0x664, 0
   2446     }, an2en[]={
   2447         0x31, 0x627, 0x32, 0x33, 0x61, 0x34, 0
   2448     }, logical_alen2an_init_lr[]={
   2449         0x31, 0x627, 0x662, 0x6f3, 0x61, 0x34, 0
   2450     }, logical_alen2an_init_al[]={
   2451         0x6f1, 0x627, 0x6f2, 0x6f3, 0x61, 0x34, 0
   2452     }, reverse_alen2an_init_lr[]={
   2453         0x661, 0x627, 0x32, 0x6f3, 0x61, 0x34, 0
   2454     }, reverse_alen2an_init_al[]={
   2455         0x6f1, 0x627, 0x32, 0x6f3, 0x61, 0x6f4, 0
   2456     }, lamalef[]={
   2457         0xfefb, 0
   2458     };
   2459     UChar dest[8];
   2460     UErrorCode errorCode;
   2461     int32_t length;
   2462 
   2463     /* test number shaping */
   2464 
   2465     /* european->arabic */
   2466     errorCode=U_ZERO_ERROR;
   2467     length=u_shapeArabic(source, UPRV_LENGTHOF(source),
   2468                          dest, UPRV_LENGTHOF(dest),
   2469                          U_SHAPE_DIGITS_EN2AN|U_SHAPE_DIGIT_TYPE_AN,
   2470                          &errorCode);
   2471     if(U_FAILURE(errorCode) || length!=UPRV_LENGTHOF(source) || memcmp(dest, en2an, length*U_SIZEOF_UCHAR)!=0) {
   2472         log_err("failure in u_shapeArabic(en2an)\n");
   2473     }
   2474 
   2475     /* arabic->european */
   2476     errorCode=U_ZERO_ERROR;
   2477     length=u_shapeArabic(source, -1,
   2478                          dest, UPRV_LENGTHOF(dest),
   2479                          U_SHAPE_DIGITS_AN2EN|U_SHAPE_DIGIT_TYPE_AN_EXTENDED,
   2480                          &errorCode);
   2481     if(U_FAILURE(errorCode) || length!=u_strlen(source) || memcmp(dest, an2en, length*U_SIZEOF_UCHAR)!=0) {
   2482         log_err("failure in u_shapeArabic(an2en)\n");
   2483     }
   2484 
   2485     /* european->arabic with context, logical order, initial state not AL */
   2486     errorCode=U_ZERO_ERROR;
   2487     length=u_shapeArabic(source, UPRV_LENGTHOF(source),
   2488                          dest, UPRV_LENGTHOF(dest),
   2489                          U_SHAPE_DIGITS_ALEN2AN_INIT_LR|U_SHAPE_DIGIT_TYPE_AN,
   2490                          &errorCode);
   2491     if(U_FAILURE(errorCode) || length!=UPRV_LENGTHOF(source) || memcmp(dest, logical_alen2an_init_lr, length*U_SIZEOF_UCHAR)!=0) {
   2492         log_err("failure in u_shapeArabic(logical_alen2an_init_lr)\n");
   2493     }
   2494 
   2495     /* european->arabic with context, logical order, initial state AL */
   2496     errorCode=U_ZERO_ERROR;
   2497     length=u_shapeArabic(source, UPRV_LENGTHOF(source),
   2498                          dest, UPRV_LENGTHOF(dest),
   2499                          U_SHAPE_DIGITS_ALEN2AN_INIT_AL|U_SHAPE_DIGIT_TYPE_AN_EXTENDED,
   2500                          &errorCode);
   2501     if(U_FAILURE(errorCode) || length!=UPRV_LENGTHOF(source) || memcmp(dest, logical_alen2an_init_al, length*U_SIZEOF_UCHAR)!=0) {
   2502         log_err("failure in u_shapeArabic(logical_alen2an_init_al)\n");
   2503     }
   2504 
   2505     /* european->arabic with context, reverse order, initial state not AL */
   2506     errorCode=U_ZERO_ERROR;
   2507     length=u_shapeArabic(source, UPRV_LENGTHOF(source),
   2508                          dest, UPRV_LENGTHOF(dest),
   2509                          U_SHAPE_DIGITS_ALEN2AN_INIT_LR|U_SHAPE_DIGIT_TYPE_AN|U_SHAPE_TEXT_DIRECTION_VISUAL_LTR,
   2510                          &errorCode);
   2511     if(U_FAILURE(errorCode) || length!=UPRV_LENGTHOF(source) || memcmp(dest, reverse_alen2an_init_lr, length*U_SIZEOF_UCHAR)!=0) {
   2512         log_err("failure in u_shapeArabic(reverse_alen2an_init_lr)\n");
   2513     }
   2514 
   2515     /* european->arabic with context, reverse order, initial state AL */
   2516     errorCode=U_ZERO_ERROR;
   2517     length=u_shapeArabic(source, UPRV_LENGTHOF(source),
   2518                          dest, UPRV_LENGTHOF(dest),
   2519                          U_SHAPE_DIGITS_ALEN2AN_INIT_AL|U_SHAPE_DIGIT_TYPE_AN_EXTENDED|U_SHAPE_TEXT_DIRECTION_VISUAL_LTR,
   2520                          &errorCode);
   2521     if(U_FAILURE(errorCode) || length!=UPRV_LENGTHOF(source) || memcmp(dest, reverse_alen2an_init_al, length*U_SIZEOF_UCHAR)!=0) {
   2522         log_err("failure in u_shapeArabic(reverse_alen2an_init_al)\n");
   2523     }
   2524 
   2525     /* test noop */
   2526     errorCode=U_ZERO_ERROR;
   2527     length=u_shapeArabic(source, UPRV_LENGTHOF(source),
   2528                          dest, UPRV_LENGTHOF(dest),
   2529                          0,
   2530                          &errorCode);
   2531     if(U_FAILURE(errorCode) || length!=UPRV_LENGTHOF(source) || memcmp(dest, source, length*U_SIZEOF_UCHAR)!=0) {
   2532         log_err("failure in u_shapeArabic(noop)\n");
   2533     }
   2534 
   2535     errorCode=U_ZERO_ERROR;
   2536     length=u_shapeArabic(source, 0,
   2537                          dest, UPRV_LENGTHOF(dest),
   2538                          U_SHAPE_DIGITS_EN2AN|U_SHAPE_DIGIT_TYPE_AN,
   2539                          &errorCode);
   2540     if(U_FAILURE(errorCode) || length!=0) {
   2541         log_err("failure in u_shapeArabic(en2an, sourceLength=0), returned %d/%s\n", u_errorName(errorCode), UPRV_LENGTHOF(source));
   2542     }
   2543 
   2544     /* preflight digit shaping */
   2545     errorCode=U_ZERO_ERROR;
   2546     length=u_shapeArabic(source, UPRV_LENGTHOF(source),
   2547                          NULL, 0,
   2548                          U_SHAPE_DIGITS_EN2AN|U_SHAPE_DIGIT_TYPE_AN,
   2549                          &errorCode);
   2550     if(errorCode!=U_BUFFER_OVERFLOW_ERROR || length!=UPRV_LENGTHOF(source)) {
   2551         log_err("failure in u_shapeArabic(en2an preflighting), returned %d/%s instead of %d/U_BUFFER_OVERFLOW_ERROR\n",
   2552                 length, u_errorName(errorCode), UPRV_LENGTHOF(source));
   2553     }
   2554 
   2555     /* test illegal arguments */
   2556     errorCode=U_ZERO_ERROR;
   2557     length=u_shapeArabic(NULL, UPRV_LENGTHOF(source),
   2558                          dest, UPRV_LENGTHOF(dest),
   2559                          U_SHAPE_DIGITS_EN2AN|U_SHAPE_DIGIT_TYPE_AN,
   2560                          &errorCode);
   2561     if(errorCode!=U_ILLEGAL_ARGUMENT_ERROR) {
   2562         log_err("failure in u_shapeArabic(source=NULL), returned %s instead of U_ILLEGAL_ARGUMENT_ERROR\n", u_errorName(errorCode));
   2563     }
   2564 
   2565     errorCode=U_ZERO_ERROR;
   2566     length=u_shapeArabic(source, -2,
   2567                          dest, UPRV_LENGTHOF(dest),
   2568                          U_SHAPE_DIGITS_EN2AN|U_SHAPE_DIGIT_TYPE_AN,
   2569                          &errorCode);
   2570     if(errorCode!=U_ILLEGAL_ARGUMENT_ERROR) {
   2571         log_err("failure in u_shapeArabic(sourceLength=-2), returned %s instead of U_ILLEGAL_ARGUMENT_ERROR\n", u_errorName(errorCode));
   2572     }
   2573 
   2574     errorCode=U_ZERO_ERROR;
   2575     length=u_shapeArabic(source, UPRV_LENGTHOF(source),
   2576                          NULL, UPRV_LENGTHOF(dest),
   2577                          U_SHAPE_DIGITS_EN2AN|U_SHAPE_DIGIT_TYPE_AN,
   2578                          &errorCode);
   2579     if(errorCode!=U_ILLEGAL_ARGUMENT_ERROR) {
   2580         log_err("failure in u_shapeArabic(dest=NULL), returned %s instead of U_ILLEGAL_ARGUMENT_ERROR\n", u_errorName(errorCode));
   2581     }
   2582 
   2583     errorCode=U_ZERO_ERROR;
   2584     length=u_shapeArabic(source, UPRV_LENGTHOF(source),
   2585                          dest, -1,
   2586                          U_SHAPE_DIGITS_EN2AN|U_SHAPE_DIGIT_TYPE_AN,
   2587                          &errorCode);
   2588     if(errorCode!=U_ILLEGAL_ARGUMENT_ERROR) {
   2589         log_err("failure in u_shapeArabic(destSize=-1), returned %s instead of U_ILLEGAL_ARGUMENT_ERROR\n", u_errorName(errorCode));
   2590     }
   2591 
   2592     errorCode=U_ZERO_ERROR;
   2593     length=u_shapeArabic(source, UPRV_LENGTHOF(source),
   2594                          dest, UPRV_LENGTHOF(dest),
   2595                          U_SHAPE_DIGITS_RESERVED|U_SHAPE_DIGIT_TYPE_AN,
   2596                          &errorCode);
   2597     if(errorCode!=U_ILLEGAL_ARGUMENT_ERROR) {
   2598         log_err("failure in u_shapeArabic(U_SHAPE_DIGITS_RESERVED), returned %s instead of U_ILLEGAL_ARGUMENT_ERROR\n", u_errorName(errorCode));
   2599     }
   2600 
   2601     errorCode=U_ZERO_ERROR;
   2602     length=u_shapeArabic(source, UPRV_LENGTHOF(source),
   2603                          dest, UPRV_LENGTHOF(dest),
   2604                          U_SHAPE_DIGITS_EN2AN|U_SHAPE_DIGIT_TYPE_RESERVED,
   2605                          &errorCode);
   2606     if(errorCode!=U_ILLEGAL_ARGUMENT_ERROR) {
   2607         log_err("failure in u_shapeArabic(U_SHAPE_DIGIT_TYPE_RESERVED), returned %s instead of U_ILLEGAL_ARGUMENT_ERROR\n", u_errorName(errorCode));
   2608     }
   2609 
   2610     errorCode=U_ZERO_ERROR;
   2611     length=u_shapeArabic(source, UPRV_LENGTHOF(source),
   2612                          (UChar *)(source+2), UPRV_LENGTHOF(dest), /* overlap source and destination */
   2613                          U_SHAPE_DIGITS_EN2AN|U_SHAPE_DIGIT_TYPE_AN,
   2614                          &errorCode);
   2615     if(errorCode!=U_ILLEGAL_ARGUMENT_ERROR) {
   2616         log_err("failure in u_shapeArabic(U_SHAPE_DIGIT_TYPE_RESERVED), returned %s instead of U_ILLEGAL_ARGUMENT_ERROR\n", u_errorName(errorCode));
   2617     }
   2618 
   2619     errorCode=U_ZERO_ERROR;
   2620     length=u_shapeArabic(lamalef, UPRV_LENGTHOF(lamalef),
   2621                          dest, UPRV_LENGTHOF(dest),
   2622                          U_SHAPE_LETTERS_UNSHAPE | U_SHAPE_LENGTH_GROW_SHRINK | U_SHAPE_TEXT_DIRECTION_VISUAL_LTR,
   2623                          &errorCode);
   2624     if(U_FAILURE(errorCode) || length == UPRV_LENGTHOF(lamalef)) {
   2625         log_err("failure in u_shapeArabic(U_SHAPE_LETTERS_UNSHAPE | U_SHAPE_LENGTH_GROW_SHRINK | U_SHAPE_TEXT_DIRECTION_VISUAL_LTR)\n");
   2626         log_err("returned %s instead of U_ZERO_ERROR or returned length %d instead of 3\n", u_errorName(errorCode), length);
   2627     }
   2628 }
   2629 
   2630 static void
   2631 doLamAlefSpecialVLTRArabicShapingTest(void) {
   2632     static const UChar
   2633     source[]={
   2634 /*a*/   0x20 ,0x646,0x622,0x644,0x627,0x20,
   2635 /*b*/   0x646,0x623,0x64E,0x644,0x627,0x20,
   2636 /*c*/   0x646,0x627,0x670,0x644,0x627,0x20,
   2637 /*d*/   0x646,0x622,0x653,0x644,0x627,0x20,
   2638 /*e*/   0x646,0x625,0x655,0x644,0x627,0x20,
   2639 /*f*/   0x646,0x622,0x654,0x644,0x627,0x20,
   2640 /*g*/   0xFEFC,0x639
   2641     }, shape_near[]={
   2642         0x20,0xfee5,0x20,0xfef5,0xfe8d,0x20,0xfee5,0x20,0xfe76,0xfef7,0xfe8d,0x20,
   2643         0xfee5,0x20,0x670,0xfefb,0xfe8d,0x20,0xfee5,0x20,0x653,0xfef5,0xfe8d,0x20,
   2644         0xfee5,0x20,0x655,0xfef9,0xfe8d,0x20,0xfee5,0x20,0x654,0xfef5,0xfe8d,0x20,
   2645         0xfefc,0xfecb
   2646     }, shape_at_end[]={
   2647         0x20,0xfee5,0xfef5,0xfe8d,0x20,0xfee5,0xfe76,0xfef7,0xfe8d,0x20,0xfee5,0x670,
   2648         0xfefb,0xfe8d,0x20,0xfee5,0x653,0xfef5,0xfe8d,0x20,0xfee5,0x655,0xfef9,0xfe8d,
   2649         0x20,0xfee5,0x654,0xfef5,0xfe8d,0x20,0xfefc,0xfecb,0x20,0x20,0x20,0x20,0x20,0x20
   2650     }, shape_at_begin[]={
   2651         0x20,0x20,0x20,0x20,0x20,0x20,0x20,0xfee5,0xfef5,0xfe8d,0x20,0xfee5,0xfe76,
   2652         0xfef7,0xfe8d,0x20,0xfee5,0x670,0xfefb,0xfe8d,0x20,0xfee5,0x653,0xfef5,0xfe8d,
   2653         0x20,0xfee5,0x655,0xfef9,0xfe8d,0x20,0xfee5,0x654,0xfef5,0xfe8d,0x20,0xfefc,0xfecb
   2654     }, shape_grow_shrink[]={
   2655         0x20,0xfee5,0xfef5,0xfe8d,0x20,0xfee5,0xfe76,0xfef7,0xfe8d,0x20,0xfee5,
   2656         0x670,0xfefb,0xfe8d,0x20,0xfee5,0x653,0xfef5,0xfe8d,0x20,0xfee5,0x655,0xfef9,
   2657         0xfe8d,0x20,0xfee5,0x654,0xfef5,0xfe8d,0x20,0xfefc,0xfecb
   2658     }, shape_excepttashkeel_near[]={
   2659         0x20,0xfee5,0x20,0xfef5,0xfe8d,0x20,0xfee5,0x20,0xfe76,0xfef7,0xfe8d,0x20,
   2660         0xfee5,0x20,0x670,0xfefb,0xfe8d,0x20,0xfee5,0x20,0x653,0xfef5,0xfe8d,0x20,
   2661         0xfee5,0x20,0x655,0xfef9,0xfe8d,0x20,0xfee5,0x20,0x654,0xfef5,0xfe8d,0x20,
   2662         0xfefc,0xfecb
   2663     }, shape_excepttashkeel_at_end[]={
   2664         0x20,0xfee5,0xfef5,0xfe8d,0x20,0xfee5,0xfe76,0xfef7,0xfe8d,0x20,0xfee5,
   2665         0x670,0xfefb,0xfe8d,0x20,0xfee5,0x653,0xfef5,0xfe8d,0x20,0xfee5,0x655,0xfef9,
   2666         0xfe8d,0x20,0xfee5,0x654,0xfef5,0xfe8d,0x20,0xfefc,0xfecb,0x20,0x20,0x20,
   2667         0x20,0x20,0x20
   2668     }, shape_excepttashkeel_at_begin[]={
   2669         0x20,0x20,0x20,0x20,0x20,0x20,0x20,0xfee5,0xfef5,0xfe8d,0x20,0xfee5,0xfe76,
   2670         0xfef7,0xfe8d,0x20,0xfee5,0x670,0xfefb,0xfe8d,0x20,0xfee5,0x653,0xfef5,0xfe8d,
   2671         0x20,0xfee5,0x655,0xfef9,0xfe8d,0x20,0xfee5,0x654,0xfef5,0xfe8d,0x20,0xfefc,0xfecb
   2672     }, shape_excepttashkeel_grow_shrink[]={
   2673         0x20,0xfee5,0xfef5,0xfe8d,0x20,0xfee5,0xfe76,0xfef7,0xfe8d,0x20,0xfee5,0x670,
   2674         0xfefb,0xfe8d,0x20,0xfee5,0x653,0xfef5,0xfe8d,0x20,0xfee5,0x655,0xfef9,0xfe8d,
   2675         0x20,0xfee5,0x654,0xfef5,0xfe8d,0x20,0xfefc,0xfecb
   2676     };
   2677 
   2678     UChar dest[38];
   2679     UErrorCode errorCode;
   2680     int32_t length;
   2681 
   2682     errorCode=U_ZERO_ERROR;
   2683 
   2684     length=u_shapeArabic(source, UPRV_LENGTHOF(source),
   2685                          dest, UPRV_LENGTHOF(dest),
   2686                          U_SHAPE_LETTERS_SHAPE|U_SHAPE_LENGTH_FIXED_SPACES_NEAR|
   2687                          U_SHAPE_TEXT_DIRECTION_VISUAL_LTR,
   2688                          &errorCode);
   2689 
   2690     if(U_FAILURE(errorCode) || length!=UPRV_LENGTHOF(shape_near) || memcmp(dest, shape_near, length*U_SIZEOF_UCHAR)!=0) {
   2691         log_err("failure in u_shapeArabic(LAMALEF shape_near)\n");
   2692     }
   2693 
   2694     errorCode=U_ZERO_ERROR;
   2695 
   2696     length=u_shapeArabic(source, UPRV_LENGTHOF(source),
   2697                          dest, UPRV_LENGTHOF(dest),
   2698                          U_SHAPE_LETTERS_SHAPE|U_SHAPE_LENGTH_FIXED_SPACES_AT_END|
   2699                          U_SHAPE_TEXT_DIRECTION_VISUAL_LTR,
   2700                          &errorCode);
   2701 
   2702     if(U_FAILURE(errorCode) || length!=UPRV_LENGTHOF(shape_at_end) || memcmp(dest, shape_at_end, length*U_SIZEOF_UCHAR)!=0) {
   2703         log_err("failure in u_shapeArabic(LAMALEF shape_at_end)\n");
   2704     }
   2705 
   2706     errorCode=U_ZERO_ERROR;
   2707 
   2708     length=u_shapeArabic(source, UPRV_LENGTHOF(source),
   2709                          dest, UPRV_LENGTHOF(dest),
   2710                          U_SHAPE_LETTERS_SHAPE|U_SHAPE_LENGTH_FIXED_SPACES_AT_BEGINNING|
   2711                          U_SHAPE_TEXT_DIRECTION_VISUAL_LTR,
   2712                          &errorCode);
   2713 
   2714     if(U_FAILURE(errorCode) || length!=UPRV_LENGTHOF(shape_at_begin) || memcmp(dest, shape_at_begin, length*U_SIZEOF_UCHAR)!=0) {
   2715         log_err("failure in u_shapeArabic(LAMALEF shape_at_begin)\n");
   2716     }
   2717 
   2718     errorCode=U_ZERO_ERROR;
   2719 
   2720     length=u_shapeArabic(source, UPRV_LENGTHOF(source),
   2721                          dest, UPRV_LENGTHOF(dest),
   2722                          U_SHAPE_LETTERS_SHAPE|U_SHAPE_LENGTH_GROW_SHRINK|
   2723                          U_SHAPE_TEXT_DIRECTION_VISUAL_LTR,
   2724                          &errorCode);
   2725 
   2726     if(U_FAILURE(errorCode) || memcmp(dest, shape_grow_shrink, length*U_SIZEOF_UCHAR)!=0) {
   2727         log_err("failure in u_shapeArabic(LAMALEF shape_grow_shrink)\n");
   2728     }
   2729 
   2730     /* ==================== U_SHAPE_LETTERS_SHAPE_TASHKEEL_ISOLATED ==================== */
   2731 
   2732     errorCode=U_ZERO_ERROR;
   2733 
   2734     length=u_shapeArabic(source, UPRV_LENGTHOF(source),
   2735                          dest, UPRV_LENGTHOF(dest),
   2736                          U_SHAPE_LETTERS_SHAPE_TASHKEEL_ISOLATED|U_SHAPE_LENGTH_FIXED_SPACES_NEAR|
   2737                          U_SHAPE_TEXT_DIRECTION_VISUAL_LTR,
   2738                          &errorCode);
   2739 
   2740     if(U_FAILURE(errorCode) || length!=UPRV_LENGTHOF(shape_excepttashkeel_near) || memcmp(dest, shape_excepttashkeel_near, length*U_SIZEOF_UCHAR)!=0) {
   2741         log_err("failure in u_shapeArabic(LAMALEF shape_excepttashkeel_near)\n");
   2742     }
   2743 
   2744     errorCode=U_ZERO_ERROR;
   2745 
   2746     length=u_shapeArabic(source, UPRV_LENGTHOF(source),
   2747                          dest, UPRV_LENGTHOF(dest),
   2748                          U_SHAPE_LETTERS_SHAPE_TASHKEEL_ISOLATED|U_SHAPE_LENGTH_FIXED_SPACES_AT_END|
   2749                          U_SHAPE_TEXT_DIRECTION_VISUAL_LTR,
   2750                          &errorCode);
   2751 
   2752     if(U_FAILURE(errorCode) || length!=UPRV_LENGTHOF(shape_excepttashkeel_at_end) || memcmp(dest,shape_excepttashkeel_at_end , length*U_SIZEOF_UCHAR)!=0) {
   2753         log_err("failure in u_shapeArabic(LAMALEF shape_excepttashkeel_at_end)\n");
   2754     }
   2755 
   2756     errorCode=U_ZERO_ERROR;
   2757 
   2758     length=u_shapeArabic(source, UPRV_LENGTHOF(source),
   2759                          dest, UPRV_LENGTHOF(dest),
   2760                          U_SHAPE_LETTERS_SHAPE_TASHKEEL_ISOLATED|U_SHAPE_LENGTH_FIXED_SPACES_AT_BEGINNING|
   2761                          U_SHAPE_TEXT_DIRECTION_VISUAL_LTR,
   2762                          &errorCode);
   2763 
   2764     if(U_FAILURE(errorCode) || length!=UPRV_LENGTHOF(shape_excepttashkeel_at_begin) || memcmp(dest, shape_excepttashkeel_at_begin, length*U_SIZEOF_UCHAR)!=0) {
   2765         log_err("failure in u_shapeArabic(LAMALEF shape_excepttashkeel_at_begin)\n");
   2766     }
   2767 
   2768     errorCode=U_ZERO_ERROR;
   2769 
   2770     length=u_shapeArabic(source, UPRV_LENGTHOF(source),
   2771                          dest, UPRV_LENGTHOF(dest),
   2772                          U_SHAPE_LETTERS_SHAPE_TASHKEEL_ISOLATED|U_SHAPE_LENGTH_GROW_SHRINK|
   2773                          U_SHAPE_TEXT_DIRECTION_VISUAL_LTR,
   2774                          &errorCode);
   2775 
   2776     if(U_FAILURE(errorCode) || memcmp(dest, shape_excepttashkeel_grow_shrink, length*U_SIZEOF_UCHAR)!=0) {
   2777         log_err("failure in u_shapeArabic(LAMALEF shape_excepttashkeel_grow_shrink)\n");
   2778     }
   2779 }
   2780 
   2781 static void
   2782 doTashkeelSpecialVLTRArabicShapingTest(void) {
   2783     static const UChar
   2784     source[]={
   2785         0x64A,0x628,0x631,0x639,0x20,
   2786         0x64A,0x628,0x651,0x631,0x64E,0x639,0x20,
   2787         0x64C,0x64A,0x628,0x631,0x64F,0x639,0x20,
   2788         0x628,0x670,0x631,0x670,0x639,0x20,
   2789         0x628,0x653,0x631,0x653,0x639,0x20,
   2790         0x628,0x654,0x631,0x654,0x639,0x20,
   2791         0x628,0x655,0x631,0x655,0x639,0x20,
   2792     }, shape_near[]={
   2793         0xfef2,0xfe91,0xfeae,0xfecb,0x20,0xfef2,0xfe91,0xfe7c,0xfeae,0xfe77,0xfecb,
   2794         0x20,0xfe72,0xfef2,0xfe91,0xfeae,0xfe79,0xfecb,0x20,0xfe8f,0x670,0xfeae,0x670,
   2795         0xfecb,0x20,0xfe8f,0x653,0xfeae,0x653,0xfecb,0x20,0xfe8f,0x654,0xfeae,0x654,
   2796         0xfecb,0x20,0xfe8f,0x655,0xfeae,0x655,0xfecb,0x20
   2797     }, shape_excepttashkeel_near[]={
   2798         0xfef2,0xfe91,0xfeae,0xfecb,0x20,0xfef2,0xfe91,0xfe7c,0xfeae,0xfe76,0xfecb,0x20,
   2799         0xfe72,0xfef2,0xfe91,0xfeae,0xfe78,0xfecb,0x20,0xfe8f,0x670,0xfeae,0x670,0xfecb,
   2800         0x20,0xfe8f,0x653,0xfeae,0x653,0xfecb,0x20,0xfe8f,0x654,0xfeae,0x654,0xfecb,0x20,
   2801         0xfe8f,0x655,0xfeae,0x655,0xfecb,0x20
   2802     };
   2803 
   2804     UChar dest[43];
   2805     UErrorCode errorCode;
   2806     int32_t length;
   2807 
   2808     errorCode=U_ZERO_ERROR;
   2809 
   2810     length=u_shapeArabic(source, UPRV_LENGTHOF(source),
   2811                          dest, UPRV_LENGTHOF(dest),
   2812                          U_SHAPE_LETTERS_SHAPE|U_SHAPE_LENGTH_FIXED_SPACES_NEAR|
   2813                          U_SHAPE_TEXT_DIRECTION_VISUAL_LTR,
   2814                          &errorCode);
   2815 
   2816     if(U_FAILURE(errorCode) || length!=UPRV_LENGTHOF(shape_near) || memcmp(dest, shape_near, length*U_SIZEOF_UCHAR)!=0) {
   2817         log_err("failure in u_shapeArabic(TASHKEEL shape_near)\n");
   2818     }
   2819 
   2820     errorCode=U_ZERO_ERROR;
   2821 
   2822     length=u_shapeArabic(source, UPRV_LENGTHOF(source),
   2823                          dest, UPRV_LENGTHOF(dest),
   2824                          U_SHAPE_LETTERS_SHAPE_TASHKEEL_ISOLATED|U_SHAPE_LENGTH_FIXED_SPACES_NEAR|
   2825                          U_SHAPE_TEXT_DIRECTION_VISUAL_LTR,
   2826                          &errorCode);
   2827 
   2828     if(U_FAILURE(errorCode) || length!=UPRV_LENGTHOF(shape_excepttashkeel_near) || memcmp(dest, shape_excepttashkeel_near, length*U_SIZEOF_UCHAR)!=0) {
   2829         log_err("failure in u_shapeArabic(TASHKEEL shape_excepttashkeel_near)\n");
   2830     }
   2831 }
   2832 
   2833 static void
   2834 doLOGICALArabicDeShapingTest(void) {
   2835     static const UChar
   2836     source[]={
   2837         0x0020,0x0020,0x0020,0xFE8D,0xFEF5,0x0020,0xFEE5,0x0020,0xFE8D,0xFEF7,0x0020,
   2838         0xFED7,0xFEFC,0x0020,0xFEE1,0x0020,0xFE8D,0xFEDF,0xFECC,0xFEAE,0xFE91,0xFEF4,
   2839         0xFE94,0x0020,0xFE8D,0xFEDF,0xFEA4,0xFEAE,0xFE93,0x0020,0x0020,0x0020,0x0020
   2840     }, unshape_near[]={
   2841         0x20,0x20,0x20,0x627,0x644,0x622,0x646,0x20,0x627,0x644,0x623,0x642,0x644,0x627,
   2842         0x645,0x20,0x627,0x644,0x639,0x631,0x628,0x64a,0x629,0x20,0x627,0x644,0x62d,0x631,
   2843         0x629,0x20,0x20,0x20,0x20
   2844     }, unshape_at_end[]={
   2845         0x20,0x20,0x20,0x627,0x644,0x622,0x20,0x646,0x20,0x627,0x644,0x623,0x20,0x642,
   2846         0x644,0x627,0x20,0x645,0x20,0x627,0x644,0x639,0x631,0x628,0x64a,0x629,0x20,0x627,
   2847         0x644,0x62d,0x631,0x629,0x20
   2848     }, unshape_at_begin[]={
   2849         0x627,0x644,0x622,0x20,0x646,0x20,0x627,0x644,0x623,0x20,0x642,0x644,0x627,0x20,
   2850         0x645,0x20,0x627,0x644,0x639,0x631,0x628,0x64a,0x629,0x20,0x627,0x644,0x62d,0x631,
   2851         0x629,0x20,0x20,0x20,0x20
   2852     }, unshape_grow_shrink[]={
   2853         0x20,0x20,0x20,0x627,0x644,0x622,0x20,0x646,0x20,0x627,0x644,0x623,0x20,0x642,
   2854         0x644,0x627,0x20,0x645,0x20,0x627,0x644,0x639,0x631,0x628,0x64a,0x629,0x20,0x627,
   2855         0x644,0x62d,0x631,0x629,0x20,0x20,0x20,0x20
   2856     };
   2857 
   2858     UChar dest[36];
   2859     UErrorCode errorCode;
   2860     int32_t length;
   2861 
   2862     errorCode=U_ZERO_ERROR;
   2863 
   2864     length=u_shapeArabic(source, UPRV_LENGTHOF(source),
   2865                          dest, UPRV_LENGTHOF(dest),
   2866                          U_SHAPE_LETTERS_UNSHAPE|U_SHAPE_LENGTH_FIXED_SPACES_NEAR|
   2867                          U_SHAPE_TEXT_DIRECTION_LOGICAL,
   2868                          &errorCode);
   2869 
   2870     if(U_FAILURE(errorCode) || length!=UPRV_LENGTHOF(unshape_near) || memcmp(dest, unshape_near, length*U_SIZEOF_UCHAR)!=0) {
   2871         log_err("failure in u_shapeArabic(unshape_near)\n");
   2872     }
   2873 
   2874     errorCode=U_ZERO_ERROR;
   2875 
   2876     length=u_shapeArabic(source, UPRV_LENGTHOF(source),
   2877                          dest, UPRV_LENGTHOF(dest),
   2878                          U_SHAPE_LETTERS_UNSHAPE|U_SHAPE_LENGTH_FIXED_SPACES_AT_END|
   2879                          U_SHAPE_TEXT_DIRECTION_LOGICAL,
   2880                          &errorCode);
   2881 
   2882     if(U_FAILURE(errorCode) || length!=UPRV_LENGTHOF(unshape_at_end) || memcmp(dest, unshape_at_end, length*U_SIZEOF_UCHAR)!=0) {
   2883         log_err("failure in u_shapeArabic(unshape_at_end)\n");
   2884     }
   2885 
   2886     errorCode=U_ZERO_ERROR;
   2887 
   2888     length=u_shapeArabic(source, UPRV_LENGTHOF(source),
   2889                          dest, UPRV_LENGTHOF(dest),
   2890                          U_SHAPE_LETTERS_UNSHAPE|U_SHAPE_LENGTH_FIXED_SPACES_AT_BEGINNING|
   2891                          U_SHAPE_TEXT_DIRECTION_LOGICAL,
   2892                          &errorCode);
   2893 
   2894     if(U_FAILURE(errorCode) || length!=UPRV_LENGTHOF(unshape_at_begin) || memcmp(dest, unshape_at_begin, length*U_SIZEOF_UCHAR)!=0) {
   2895         log_err("failure in u_shapeArabic(unshape_at_begin)\n");
   2896     }
   2897 
   2898     errorCode=U_ZERO_ERROR;
   2899 
   2900     length=u_shapeArabic(source, UPRV_LENGTHOF(source),
   2901                          dest, UPRV_LENGTHOF(dest),
   2902                          U_SHAPE_LETTERS_UNSHAPE|U_SHAPE_LENGTH_GROW_SHRINK|
   2903                          U_SHAPE_TEXT_DIRECTION_LOGICAL,
   2904                          &errorCode);
   2905 
   2906     if(U_FAILURE(errorCode) || memcmp(dest, unshape_grow_shrink, length*U_SIZEOF_UCHAR)!=0) {
   2907         log_err("failure in u_shapeArabic(unshape_grow_shrink)\n");
   2908     }
   2909 
   2910 }
   2911 
   2912 static void
   2913 doTailTest(void) {
   2914   static const UChar src[] = { 0x0020, 0x0633, 0 };
   2915   static const UChar dst_old[] = { 0xFEB1, 0x200B,0 };
   2916   static const UChar dst_new[] = { 0xFEB1, 0xFE73,0 };
   2917   UChar dst[3] = { 0x0000, 0x0000,0 };
   2918   int32_t length;
   2919   UErrorCode status;
   2920 
   2921   log_verbose("SRC: U+%04X U+%04X\n", src[0],src[1]);
   2922 
   2923   log_verbose("Trying old tail\n");
   2924   status = U_ZERO_ERROR;
   2925   length = u_shapeArabic(src, -1, dst, UPRV_LENGTHOF(dst),
   2926                          U_SHAPE_LETTERS_SHAPE|U_SHAPE_SEEN_TWOCELL_NEAR, &status);
   2927   if(U_FAILURE(status)) {
   2928     log_err("Fail: status %s\n", u_errorName(status));
   2929   } else if(length!=2) {
   2930     log_err("Fail: len %d expected 3\n", length);
   2931   } else if(u_strncmp(dst,dst_old,UPRV_LENGTHOF(dst))) {
   2932     log_err("Fail: got U+%04X U+%04X expected U+%04X U+%04X\n",
   2933             dst[0],dst[1],dst_old[0],dst_old[1]);
   2934   } else {
   2935     log_verbose("OK:  U+%04X U+%04X len %d err %s\n",
   2936             dst[0],dst[1],length,u_errorName(status));
   2937   }
   2938 
   2939 
   2940   log_verbose("Trying new tail\n");
   2941   status = U_ZERO_ERROR;
   2942   length = u_shapeArabic(src, -1, dst, UPRV_LENGTHOF(dst),
   2943                          U_SHAPE_LETTERS_SHAPE|U_SHAPE_SEEN_TWOCELL_NEAR|U_SHAPE_TAIL_NEW_UNICODE, &status);
   2944   if(U_FAILURE(status)) {
   2945     log_err("Fail: status %s\n", u_errorName(status));
   2946   } else if(length!=2) {
   2947     log_err("Fail: len %d expected 3\n", length);
   2948   } else if(u_strncmp(dst,dst_new,UPRV_LENGTHOF(dst))) {
   2949     log_err("Fail: got U+%04X U+%04X expected U+%04X U+%04X\n",
   2950             dst[0],dst[1],dst_new[0],dst_new[1]);
   2951   } else {
   2952     log_verbose("OK:  U+%04X U+%04X len %d err %s\n",
   2953             dst[0],dst[1],length,u_errorName(status));
   2954   }
   2955 }
   2956 
   2957 static void
   2958 doArabicShapingTestForBug5421(void) {
   2959     static const UChar
   2960     persian_letters_source[]={
   2961         0x0020, 0x0698, 0x067E, 0x0686, 0x06AF, 0x0020
   2962     }, persian_letters[]={
   2963         0x0020, 0xFB8B, 0xFB59, 0xFB7D, 0xFB94, 0x0020
   2964     }, tashkeel_aggregation_source[]={
   2965         0x0020, 0x0628, 0x0651, 0x064E, 0x062A, 0x0631, 0x0645, 0x0020,
   2966         0x0628, 0x064E, 0x0651, 0x062A, 0x0631, 0x0645, 0x0020
   2967     }, tashkeel_aggregation[]={
   2968         0x0020, 0xFE90, 0xFC60, 0xFE97, 0xFEAE, 0xFEE3,
   2969         0x0020, 0xFE90, 0xFC60, 0xFE97, 0xFEAE, 0xFEE3, 0x0020
   2970     }, untouched_presentation_source[]={
   2971         0x0020 ,0x0627, 0xfe90,0x0020
   2972     }, untouched_presentation[]={
   2973         0x0020,0xfe8D, 0xfe90,0x0020
   2974     }, untouched_presentation_r_source[]={
   2975         0x0020 ,0xfe90, 0x0627, 0x0020
   2976     }, untouched_presentation_r[]={
   2977         0x0020, 0xfe90,0xfe8D,0x0020
   2978     };
   2979 
   2980     UChar dest[38];
   2981     UErrorCode errorCode;
   2982     int32_t length;
   2983 
   2984     errorCode=U_ZERO_ERROR;
   2985 
   2986     length=u_shapeArabic(persian_letters_source, UPRV_LENGTHOF(persian_letters_source),
   2987                          dest, UPRV_LENGTHOF(dest),
   2988                          U_SHAPE_LETTERS_SHAPE|U_SHAPE_TEXT_DIRECTION_VISUAL_LTR,
   2989                          &errorCode);
   2990 
   2991     if(U_FAILURE(errorCode) || length!=UPRV_LENGTHOF(persian_letters) || memcmp(dest, persian_letters, length*U_SIZEOF_UCHAR)!=0) {
   2992         log_err("failure in u_shapeArabic(persian_letters)\n");
   2993     }
   2994 
   2995     errorCode=U_ZERO_ERROR;
   2996 
   2997     length=u_shapeArabic(tashkeel_aggregation_source, UPRV_LENGTHOF(tashkeel_aggregation_source),
   2998                          dest, UPRV_LENGTHOF(dest),
   2999                          U_SHAPE_AGGREGATE_TASHKEEL|U_SHAPE_PRESERVE_PRESENTATION|
   3000                          U_SHAPE_LETTERS_SHAPE_TASHKEEL_ISOLATED|U_SHAPE_TEXT_DIRECTION_VISUAL_LTR,
   3001                          &errorCode);
   3002 
   3003     if(U_FAILURE(errorCode) || length!=UPRV_LENGTHOF(tashkeel_aggregation) || memcmp(dest, tashkeel_aggregation, length*U_SIZEOF_UCHAR)!=0) {
   3004         log_err("failure in u_shapeArabic(tashkeel_aggregation)\n");
   3005     }
   3006 
   3007     errorCode=U_ZERO_ERROR;
   3008 
   3009     length=u_shapeArabic(untouched_presentation_source, UPRV_LENGTHOF(untouched_presentation_source),
   3010                          dest, UPRV_LENGTHOF(dest),
   3011                          U_SHAPE_PRESERVE_PRESENTATION|
   3012                          U_SHAPE_LETTERS_SHAPE|U_SHAPE_TEXT_DIRECTION_VISUAL_LTR,
   3013                          &errorCode);
   3014 
   3015     if(U_FAILURE(errorCode) || length!=UPRV_LENGTHOF(untouched_presentation) || memcmp(dest, untouched_presentation, length*U_SIZEOF_UCHAR)!=0) {
   3016         log_err("failure in u_shapeArabic(untouched_presentation)\n");
   3017     }
   3018 
   3019     errorCode=U_ZERO_ERROR;
   3020 
   3021     length=u_shapeArabic(untouched_presentation_r_source, UPRV_LENGTHOF(untouched_presentation_r_source),
   3022                          dest, UPRV_LENGTHOF(dest),
   3023                          U_SHAPE_PRESERVE_PRESENTATION|
   3024                          U_SHAPE_LETTERS_SHAPE|U_SHAPE_TEXT_DIRECTION_LOGICAL,
   3025                          &errorCode);
   3026 
   3027     if(U_FAILURE(errorCode) || length!=UPRV_LENGTHOF(untouched_presentation_r) || memcmp(dest, untouched_presentation_r, length*U_SIZEOF_UCHAR)!=0) {
   3028         log_err("failure in u_shapeArabic(untouched_presentation_r)\n");
   3029     }
   3030 }
   3031 
   3032 static void
   3033 doArabicShapingTestForBug8703(void) {
   3034     static const UChar
   3035     letters_source1[]={
   3036         0x0634,0x0651,0x0645,0x0652,0x0633
   3037     }, letters_source2[]={
   3038         0x0634,0x0651,0x0645,0x0652,0x0633
   3039     }, letters_source3[]={
   3040        0x0634,0x0651,0x0645,0x0652,0x0633
   3041     }, letters_source4[]={
   3042         0x0634,0x0651,0x0645,0x0652,0x0633
   3043     }, letters_source5[]={
   3044         0x0633,0x0652,0x0645,0x0651,0x0634
   3045     }, letters_source6[]={
   3046         0x0633,0x0652,0x0645,0x0651,0x0634
   3047     }, letters_source7[]={
   3048         0x0633,0x0652,0x0645,0x0651,0x0634
   3049     }, letters_source8[]={
   3050         0x0633,0x0652,0x0645,0x0651,0x0634
   3051     }, letters_dest1[]={
   3052         0x0020,0xFEB7,0xFE7D,0xFEE4,0xFEB2
   3053     }, letters_dest2[]={
   3054         0xFEB7,0xFE7D,0xFEE4,0xFEB2,0x0020
   3055     }, letters_dest3[]={
   3056         0xFEB7,0xFE7D,0xFEE4,0xFEB2
   3057     }, letters_dest4[]={
   3058         0xFEB7,0xFE7D,0xFEE4,0x0640,0xFEB2
   3059     }, letters_dest5[]={
   3060         0x0020,0xFEB2,0xFEE4,0xFE7D,0xFEB7
   3061     }, letters_dest6[]={
   3062         0xFEB2,0xFEE4,0xFE7D,0xFEB7,0x0020
   3063     }, letters_dest7[]={
   3064         0xFEB2,0xFEE4,0xFE7D,0xFEB7
   3065     }, letters_dest8[]={
   3066         0xFEB2,0x0640,0xFEE4,0xFE7D,0xFEB7
   3067     };
   3068 
   3069     UChar dest[20];
   3070     UErrorCode errorCode;
   3071     int32_t length;
   3072 
   3073     errorCode=U_ZERO_ERROR;
   3074 
   3075     length=u_shapeArabic(letters_source1, UPRV_LENGTHOF(letters_source1),
   3076                          dest, UPRV_LENGTHOF(dest),
   3077                          U_SHAPE_TEXT_DIRECTION_VISUAL_RTL | U_SHAPE_TASHKEEL_BEGIN | U_SHAPE_LETTERS_SHAPE,
   3078                          &errorCode);
   3079 
   3080     if(U_FAILURE(errorCode) || length!=UPRV_LENGTHOF(letters_dest1) || memcmp(dest, letters_dest1, length*U_SIZEOF_UCHAR)!=0) {
   3081         log_err("failure in u_shapeArabic(letters_source1)\n");
   3082     }
   3083 
   3084     errorCode=U_ZERO_ERROR;
   3085 
   3086     length=u_shapeArabic(letters_source2, UPRV_LENGTHOF(letters_source2),
   3087                          dest, UPRV_LENGTHOF(dest),
   3088                          U_SHAPE_TEXT_DIRECTION_VISUAL_RTL | U_SHAPE_TASHKEEL_END | U_SHAPE_LETTERS_SHAPE,
   3089                          &errorCode);
   3090 
   3091     if(U_FAILURE(errorCode) || length!=UPRV_LENGTHOF(letters_dest2) || memcmp(dest, letters_dest2, length*U_SIZEOF_UCHAR)!=0) {
   3092         log_err("failure in u_shapeArabic(letters_source2)\n");
   3093     }
   3094 
   3095     errorCode=U_ZERO_ERROR;
   3096 
   3097     length=u_shapeArabic(letters_source3, UPRV_LENGTHOF(letters_source3),
   3098                          dest, UPRV_LENGTHOF(dest),
   3099                          U_SHAPE_TEXT_DIRECTION_VISUAL_RTL | U_SHAPE_TASHKEEL_RESIZE | U_SHAPE_LETTERS_SHAPE,
   3100                          &errorCode);
   3101 
   3102     if(U_FAILURE(errorCode) || length!=UPRV_LENGTHOF(letters_dest3) || memcmp(dest, letters_dest3, length*U_SIZEOF_UCHAR)!=0) {
   3103         log_err("failure in u_shapeArabic(letters_source3)\n");
   3104     }
   3105 
   3106     errorCode=U_ZERO_ERROR;
   3107 
   3108     length=u_shapeArabic(letters_source4, UPRV_LENGTHOF(letters_source4),
   3109                          dest, UPRV_LENGTHOF(dest),
   3110                          U_SHAPE_TEXT_DIRECTION_VISUAL_RTL | U_SHAPE_TASHKEEL_REPLACE_BY_TATWEEL | U_SHAPE_LETTERS_SHAPE,
   3111                          &errorCode);
   3112 
   3113     if(U_FAILURE(errorCode) || length!=UPRV_LENGTHOF(letters_dest4) || memcmp(dest, letters_dest4, length*U_SIZEOF_UCHAR)!=0) {
   3114         log_err("failure in u_shapeArabic(letters_source4)\n");
   3115     }
   3116 
   3117     errorCode=U_ZERO_ERROR;
   3118 
   3119     length=u_shapeArabic(letters_source5, UPRV_LENGTHOF(letters_source5),
   3120                          dest, UPRV_LENGTHOF(dest),
   3121                          U_SHAPE_TEXT_DIRECTION_VISUAL_LTR | U_SHAPE_TASHKEEL_BEGIN | U_SHAPE_LETTERS_SHAPE,
   3122                          &errorCode);
   3123 
   3124     if(U_FAILURE(errorCode) || length!=UPRV_LENGTHOF(letters_dest5) || memcmp(dest, letters_dest5, length*U_SIZEOF_UCHAR)!=0) {
   3125         log_err("failure in u_shapeArabic(letters_source5)\n");
   3126     }
   3127 
   3128     errorCode=U_ZERO_ERROR;
   3129 
   3130     length=u_shapeArabic(letters_source6, UPRV_LENGTHOF(letters_source6),
   3131                          dest, UPRV_LENGTHOF(dest),
   3132                          U_SHAPE_TEXT_DIRECTION_VISUAL_LTR | U_SHAPE_TASHKEEL_END | U_SHAPE_LETTERS_SHAPE,
   3133                          &errorCode);
   3134 
   3135     if(U_FAILURE(errorCode) || length!=UPRV_LENGTHOF(letters_dest6) || memcmp(dest, letters_dest6, length*U_SIZEOF_UCHAR)!=0) {
   3136         log_err("failure in u_shapeArabic(letters_source6)\n");
   3137     }
   3138 
   3139     errorCode=U_ZERO_ERROR;
   3140 
   3141     length=u_shapeArabic(letters_source7, UPRV_LENGTHOF(letters_source7),
   3142                          dest, UPRV_LENGTHOF(dest),
   3143                          U_SHAPE_TEXT_DIRECTION_VISUAL_LTR | U_SHAPE_TASHKEEL_RESIZE | U_SHAPE_LETTERS_SHAPE,
   3144                          &errorCode);
   3145 
   3146     if(U_FAILURE(errorCode) || length!=UPRV_LENGTHOF(letters_dest7) || memcmp(dest, letters_dest7, length*U_SIZEOF_UCHAR)!=0) {
   3147         log_err("failure in u_shapeArabic(letters_source7)\n");
   3148     }
   3149 
   3150     errorCode=U_ZERO_ERROR;
   3151 
   3152     length=u_shapeArabic(letters_source8, UPRV_LENGTHOF(letters_source8),
   3153                          dest, UPRV_LENGTHOF(dest),
   3154                          U_SHAPE_TEXT_DIRECTION_VISUAL_LTR | U_SHAPE_TASHKEEL_REPLACE_BY_TATWEEL | U_SHAPE_LETTERS_SHAPE,
   3155                          &errorCode);
   3156 
   3157     if(U_FAILURE(errorCode) || length!=UPRV_LENGTHOF(letters_dest8) || memcmp(dest, letters_dest8, length*U_SIZEOF_UCHAR)!=0) {
   3158         log_err("failure in u_shapeArabic(letters_source8)\n");
   3159     }
   3160 }
   3161 
   3162 static void
   3163 doArabicShapingTestForBug9024(void) {
   3164     static const UChar
   3165     letters_source1[]={  /* Arabic mathematical Symbols 0x1EE00 - 0x1EE1B */
   3166         0xD83B, 0xDE00, 0xD83B, 0xDE01, 0xD83B, 0xDE02, 0xD83B, 0xDE03, 0x20,
   3167         0xD83B, 0xDE24, 0xD83B, 0xDE05, 0xD83B, 0xDE06, 0x20,
   3168         0xD83B, 0xDE07, 0xD83B, 0xDE08, 0xD83B, 0xDE09, 0x20,
   3169         0xD83B, 0xDE0A, 0xD83B, 0xDE0B, 0xD83B, 0xDE0C, 0xD83B, 0xDE0D, 0x20,
   3170         0xD83B, 0xDE0E, 0xD83B, 0xDE0F, 0xD83B, 0xDE10, 0xD83B, 0xDE11, 0x20,
   3171         0xD83B, 0xDE12, 0xD83B, 0xDE13, 0xD83B, 0xDE14, 0xD83B, 0xDE15, 0x20,
   3172         0xD83B, 0xDE16, 0xD83B, 0xDE17, 0xD83B, 0xDE18, 0x20,
   3173         0xD83B, 0xDE19, 0xD83B, 0xDE1A, 0xD83B, 0xDE1B
   3174     }, letters_source2[]={/* Arabic mathematical Symbols - Looped Symbols, 0x1EE80 - 0x1EE9B */
   3175         0xD83B, 0xDE80, 0xD83B, 0xDE81, 0xD83B, 0xDE82, 0xD83B, 0xDE83, 0x20,
   3176         0xD83B, 0xDE84, 0xD83B, 0xDE85, 0xD83B, 0xDE86, 0x20,
   3177         0xD83B, 0xDE87, 0xD83B, 0xDE88, 0xD83B, 0xDE89, 0x20,
   3178         0xD83B, 0xDE8B, 0xD83B, 0xDE8C, 0xD83B, 0xDE8D, 0x20,
   3179         0xD83B, 0xDE8E, 0xD83B, 0xDE8F, 0xD83B, 0xDE90, 0xD83B, 0xDE91, 0x20,
   3180         0xD83B, 0xDE92, 0xD83B, 0xDE93, 0xD83B, 0xDE94, 0xD83B, 0xDE95, 0x20,
   3181         0xD83B, 0xDE96, 0xD83B, 0xDE97, 0xD83B, 0xDE98, 0x20,
   3182         0xD83B, 0xDE99, 0xD83B, 0xDE9A, 0xD83B, 0xDE9B
   3183     }, letters_source3[]={/* Arabic mathematical Symbols - Double-struck Symbols, 0x1EEA1 - 0x1EEBB */
   3184         0xD83B, 0xDEA1, 0xD83B, 0xDEA2, 0xD83B, 0xDEA3, 0x20,
   3185         0xD83B, 0xDEA5, 0xD83B, 0xDEA6, 0x20,
   3186         0xD83B, 0xDEA7, 0xD83B, 0xDEA8, 0xD83B, 0xDEA9, 0x20,
   3187         0xD83B, 0xDEAB, 0xD83B, 0xDEAC, 0xD83B, 0xDEAD, 0x20,
   3188         0xD83B, 0xDEAE, 0xD83B, 0xDEAF, 0xD83B, 0xDEB0, 0xD83B, 0xDEB1, 0x20,
   3189         0xD83B, 0xDEB2, 0xD83B, 0xDEB3, 0xD83B, 0xDEB4, 0xD83B, 0xDEB5, 0x20,
   3190         0xD83B, 0xDEB6, 0xD83B, 0xDEB7, 0xD83B, 0xDEB8, 0x20,
   3191         0xD83B, 0xDEB9, 0xD83B, 0xDEBA, 0xD83B, 0xDEBB
   3192     }, letters_source4[]={/* Arabic mathematical Symbols - Initial Symbols, 0x1EE21 - 0x1EE3B */
   3193         0xD83B, 0xDE21, 0xD83B, 0xDE22, 0x20,
   3194         0xD83B, 0xDE27, 0xD83B, 0xDE29, 0x20,
   3195         0xD83B, 0xDE2A, 0xD83B, 0xDE2B, 0xD83B, 0xDE2C, 0xD83B, 0xDE2D, 0x20,
   3196         0xD83B, 0xDE2E, 0xD83B, 0xDE2F, 0xD83B, 0xDE30, 0xD83B, 0xDE31, 0x20,
   3197         0xD83B, 0xDE32, 0xD83B, 0xDE34, 0xD83B, 0xDE35, 0x20,
   3198         0xD83B, 0xDE36, 0xD83B, 0xDE37, 0x20,
   3199         0xD83B, 0xDE39, 0xD83B, 0xDE3B
   3200     }, letters_source5[]={/* Arabic mathematical Symbols - Tailed Symbols */
   3201         0xD83B, 0xDE42, 0xD83B, 0xDE47, 0xD83B, 0xDE49, 0xD83B, 0xDE4B, 0x20,
   3202         0xD83B, 0xDE4D, 0xD83B, 0xDE4E, 0xD83B, 0xDE4F, 0x20,
   3203         0xD83B, 0xDE51, 0xD83B, 0xDE52, 0xD83B, 0xDE54, 0xD83B, 0xDE57, 0x20,
   3204         0xD83B, 0xDE59, 0xD83B, 0xDE5B, 0xD83B, 0xDE5D, 0xD83B, 0xDE5F
   3205     }, letters_source6[]={/* Arabic mathematical Symbols - Stretched Symbols with 06 range */
   3206         0xD83B, 0xDE21, 0x0633, 0xD83B, 0xDE62, 0x0647
   3207     }, letters_dest1[]={
   3208         0xD83B, 0xDE00, 0xD83B, 0xDE01, 0xD83B, 0xDE02, 0xD83B, 0xDE03, 0x20,
   3209         0xD83B, 0xDE24, 0xD83B, 0xDE05, 0xD83B, 0xDE06, 0x20,
   3210         0xD83B, 0xDE07, 0xD83B, 0xDE08, 0xD83B, 0xDE09, 0x20,
   3211         0xD83B, 0xDE0A, 0xD83B, 0xDE0B, 0xD83B, 0xDE0C, 0xD83B, 0xDE0D, 0x20,
   3212         0xD83B, 0xDE0E, 0xD83B, 0xDE0F, 0xD83B, 0xDE10, 0xD83B, 0xDE11, 0x20,
   3213         0xD83B, 0xDE12, 0xD83B, 0xDE13, 0xD83B, 0xDE14, 0xD83B, 0xDE15, 0x20,
   3214         0xD83B, 0xDE16, 0xD83B, 0xDE17, 0xD83B, 0xDE18, 0x20,
   3215         0xD83B, 0xDE19, 0xD83B, 0xDE1A, 0xD83B, 0xDE1B
   3216     }, letters_dest2[]={
   3217         0xD83B, 0xDE80, 0xD83B, 0xDE81, 0xD83B, 0xDE82, 0xD83B, 0xDE83, 0x20,
   3218         0xD83B, 0xDE84, 0xD83B, 0xDE85, 0xD83B, 0xDE86, 0x20,
   3219         0xD83B, 0xDE87, 0xD83B, 0xDE88, 0xD83B, 0xDE89, 0x20,
   3220         0xD83B, 0xDE8B, 0xD83B, 0xDE8C, 0xD83B, 0xDE8D, 0x20,
   3221         0xD83B, 0xDE8E, 0xD83B, 0xDE8F, 0xD83B, 0xDE90, 0xD83B, 0xDE91, 0x20,
   3222         0xD83B, 0xDE92, 0xD83B, 0xDE93, 0xD83B, 0xDE94, 0xD83B, 0xDE95, 0x20,
   3223         0xD83B, 0xDE96, 0xD83B, 0xDE97, 0xD83B, 0xDE98, 0x20,
   3224         0xD83B, 0xDE99, 0xD83B, 0xDE9A, 0xD83B, 0xDE9B
   3225     }, letters_dest3[]={
   3226         0xD83B, 0xDEA1, 0xD83B, 0xDEA2, 0xD83B, 0xDEA3, 0x20,
   3227         0xD83B, 0xDEA5, 0xD83B, 0xDEA6, 0x20,
   3228         0xD83B, 0xDEA7, 0xD83B, 0xDEA8, 0xD83B, 0xDEA9, 0x20,
   3229         0xD83B, 0xDEAB, 0xD83B, 0xDEAC, 0xD83B, 0xDEAD, 0x20,
   3230         0xD83B, 0xDEAE, 0xD83B, 0xDEAF, 0xD83B, 0xDEB0, 0xD83B, 0xDEB1, 0x20,
   3231         0xD83B, 0xDEB2, 0xD83B, 0xDEB3, 0xD83B, 0xDEB4, 0xD83B, 0xDEB5, 0x20,
   3232         0xD83B, 0xDEB6, 0xD83B, 0xDEB7, 0xD83B, 0xDEB8, 0x20,
   3233         0xD83B, 0xDEB9, 0xD83B, 0xDEBA, 0xD83B, 0xDEBB
   3234     }, letters_dest4[]={
   3235         0xD83B, 0xDE21, 0xD83B, 0xDE22, 0x20,
   3236         0xD83B, 0xDE27, 0xD83B, 0xDE29, 0x20,
   3237         0xD83B, 0xDE2A, 0xD83B, 0xDE2B, 0xD83B, 0xDE2C, 0xD83B, 0xDE2D, 0x20,
   3238         0xD83B, 0xDE2E, 0xD83B, 0xDE2F, 0xD83B, 0xDE30, 0xD83B, 0xDE31, 0x20,
   3239         0xD83B, 0xDE32, 0xD83B, 0xDE34, 0xD83B, 0xDE35, 0x20,
   3240         0xD83B, 0xDE36, 0xD83B, 0xDE37, 0x20,
   3241         0xD83B, 0xDE39, 0xD83B, 0xDE3B
   3242     }, letters_dest5[]={
   3243         0xD83B, 0xDE42, 0xD83B, 0xDE47, 0xD83B, 0xDE49, 0xD83B, 0xDE4B, 0x20,
   3244         0xD83B, 0xDE4D, 0xD83B, 0xDE4E, 0xD83B, 0xDE4F, 0x20,
   3245         0xD83B, 0xDE51, 0xD83B, 0xDE52, 0xD83B, 0xDE54, 0xD83B, 0xDE57, 0x20,
   3246         0xD83B, 0xDE59, 0xD83B, 0xDE5B, 0xD83B, 0xDE5D, 0xD83B, 0xDE5F
   3247     }, letters_dest6[]={
   3248         0xD83B, 0xDE21, 0xFEB1, 0xD83B, 0xDE62, 0xFEE9
   3249     };
   3250 
   3251     UChar dest[MAXLEN];
   3252     UErrorCode errorCode;
   3253     int32_t length;
   3254 
   3255     errorCode=U_ZERO_ERROR;
   3256 
   3257     length=u_shapeArabic(letters_source1, UPRV_LENGTHOF(letters_source1),
   3258                          dest, UPRV_LENGTHOF(dest),
   3259                          U_SHAPE_TEXT_DIRECTION_VISUAL_RTL | U_SHAPE_TASHKEEL_BEGIN | U_SHAPE_LETTERS_SHAPE,
   3260                          &errorCode);
   3261 
   3262     if(U_FAILURE(errorCode) || length!=UPRV_LENGTHOF(letters_dest1) || memcmp(dest, letters_dest1, length*U_SIZEOF_UCHAR)!=0) {
   3263         log_err("failure in u_shapeArabic(letters_source1)\n");
   3264     }
   3265 
   3266     errorCode=U_ZERO_ERROR;
   3267 
   3268     length=u_shapeArabic(letters_source2, UPRV_LENGTHOF(letters_source2),
   3269                          dest, UPRV_LENGTHOF(dest),
   3270                          U_SHAPE_TEXT_DIRECTION_VISUAL_RTL | U_SHAPE_TASHKEEL_END | U_SHAPE_LETTERS_SHAPE,
   3271                          &errorCode);
   3272 
   3273     if(U_FAILURE(errorCode) || length!=UPRV_LENGTHOF(letters_dest2) || memcmp(dest, letters_dest2, length*U_SIZEOF_UCHAR)!=0) {
   3274         log_err("failure in u_shapeArabic(letters_source2)\n");
   3275     }
   3276 
   3277     errorCode=U_ZERO_ERROR;
   3278 
   3279     length=u_shapeArabic(letters_source3, UPRV_LENGTHOF(letters_source3),
   3280                          dest, UPRV_LENGTHOF(dest),
   3281                          U_SHAPE_TEXT_DIRECTION_VISUAL_RTL | U_SHAPE_TASHKEEL_RESIZE | U_SHAPE_LETTERS_SHAPE,
   3282                          &errorCode);
   3283 
   3284     if(U_FAILURE(errorCode) || length!=UPRV_LENGTHOF(letters_dest3) || memcmp(dest, letters_dest3, length*U_SIZEOF_UCHAR)!=0) {
   3285         log_err("failure in u_shapeArabic(letters_source3)\n");
   3286     }
   3287 
   3288     errorCode=U_ZERO_ERROR;
   3289 
   3290     length=u_shapeArabic(letters_source4, UPRV_LENGTHOF(letters_source4),
   3291                          dest, UPRV_LENGTHOF(dest),
   3292                          U_SHAPE_TEXT_DIRECTION_VISUAL_RTL | U_SHAPE_TASHKEEL_REPLACE_BY_TATWEEL | U_SHAPE_LETTERS_SHAPE,
   3293                          &errorCode);
   3294 
   3295     if(U_FAILURE(errorCode) || length!=UPRV_LENGTHOF(letters_dest4) || memcmp(dest, letters_dest4, length*U_SIZEOF_UCHAR)!=0) {
   3296         log_err("failure in u_shapeArabic(letters_source4)\n");
   3297     }
   3298 
   3299     errorCode=U_ZERO_ERROR;
   3300 
   3301     length=u_shapeArabic(letters_source5, UPRV_LENGTHOF(letters_source5),
   3302                          dest, UPRV_LENGTHOF(dest),
   3303                          U_SHAPE_TEXT_DIRECTION_VISUAL_LTR | U_SHAPE_TASHKEEL_BEGIN | U_SHAPE_LETTERS_SHAPE,
   3304                          &errorCode);
   3305 
   3306     if(U_FAILURE(errorCode) || length!=UPRV_LENGTHOF(letters_dest5) || memcmp(dest, letters_dest5, length*U_SIZEOF_UCHAR)!=0) {
   3307         log_err("failure in u_shapeArabic(letters_source5)\n");
   3308     }
   3309 
   3310     errorCode=U_ZERO_ERROR;
   3311 
   3312     length=u_shapeArabic(letters_source6, UPRV_LENGTHOF(letters_source6),
   3313                          dest, UPRV_LENGTHOF(dest),
   3314                          U_SHAPE_TEXT_DIRECTION_VISUAL_LTR | U_SHAPE_TASHKEEL_END | U_SHAPE_LETTERS_SHAPE,
   3315                          &errorCode);
   3316 
   3317     if(U_FAILURE(errorCode) || length!=UPRV_LENGTHOF(letters_dest6) || memcmp(dest, letters_dest6, length*U_SIZEOF_UCHAR)!=0) {
   3318         log_err("failure in u_shapeArabic(letters_source6)\n");
   3319     }
   3320 
   3321 }
   3322 
   3323 static void _testPresentationForms(const UChar* in) {
   3324   enum Forms { GENERIC, ISOLATED, FINAL, INITIAL, MEDIAL };
   3325   /* This character is used to check whether the in-character is rewritten correctly
   3326      and whether the surrounding characters are shaped correctly as well. */
   3327   UChar otherChar[] = {0x0628, 0xfe8f, 0xfe90, 0xfe91, 0xfe92};
   3328   UChar src[3];
   3329   UChar dst[3];
   3330   UErrorCode errorCode;
   3331   int32_t length;
   3332 
   3333   /* Testing isolated shaping */
   3334   src[0] = in[GENERIC];
   3335   errorCode=U_ZERO_ERROR;
   3336   length=u_shapeArabic(src, 1,
   3337                        dst, 1,
   3338                        U_SHAPE_LETTERS_SHAPE,
   3339                        &errorCode);
   3340   if(U_FAILURE(errorCode) || length!=1 || dst[0] != in[ISOLATED]) {
   3341       log_err("failure in u_shapeArabic(_testAllForms: shaping isolated): %x\n", in[GENERIC]);
   3342   }
   3343   errorCode=U_ZERO_ERROR;
   3344   length=u_shapeArabic(dst, 1,
   3345                        src, 1,
   3346                        U_SHAPE_LETTERS_UNSHAPE,
   3347                        &errorCode);
   3348   if(U_FAILURE(errorCode) || length!=1 || src[0] != in[GENERIC]) {
   3349       log_err("failure in u_shapeArabic(_testAllForms: unshaping isolated): %x\n", in[GENERIC]);
   3350   }
   3351 
   3352   /* Testing final shaping */
   3353   src[0] = otherChar[GENERIC];
   3354   src[1] = in[GENERIC];
   3355   if (in[FINAL] != 0) {
   3356     errorCode=U_ZERO_ERROR;
   3357     length=u_shapeArabic(src, 2,
   3358                          dst, 2,
   3359                          U_SHAPE_LETTERS_SHAPE,
   3360                          &errorCode);
   3361     if(U_FAILURE(errorCode) || length!=2 || dst[0] != otherChar[INITIAL] || dst[1] != in[FINAL]) {
   3362       log_err("failure in u_shapeArabic(_testAllForms: shaping final): %x\n", in[GENERIC]);
   3363     }
   3364     errorCode=U_ZERO_ERROR;
   3365     length=u_shapeArabic(dst, 2,
   3366                          src, 2,
   3367                          U_SHAPE_LETTERS_UNSHAPE,
   3368                          &errorCode);
   3369     if(U_FAILURE(errorCode) || length!=2 || src[0] != otherChar[GENERIC] || src[1] != in[GENERIC]) {
   3370       log_err("failure in u_shapeArabic(_testAllForms: unshaping final): %x\n", in[GENERIC]);
   3371     }
   3372   } else {
   3373     errorCode=U_ZERO_ERROR;
   3374     length=u_shapeArabic(src, 2,
   3375                          dst, 2,
   3376                          U_SHAPE_LETTERS_SHAPE,
   3377                          &errorCode);
   3378     if(U_FAILURE(errorCode) || length!=2 || dst[0] != otherChar[ISOLATED] || dst[1] != in[ISOLATED]) {
   3379       log_err("failure in u_shapeArabic(_testAllForms: shaping final): %x\n", in[GENERIC]);
   3380     }
   3381     errorCode=U_ZERO_ERROR;
   3382     length=u_shapeArabic(dst, 2,
   3383                          src, 2,
   3384                          U_SHAPE_LETTERS_UNSHAPE,
   3385                          &errorCode);
   3386     if(U_FAILURE(errorCode) || length!=2 || src[0] != otherChar[GENERIC] || src[1] != in[GENERIC]) {
   3387       log_err("failure in u_shapeArabic(_testAllForms: unshaping final): %x\n", in[GENERIC]);
   3388     }
   3389   }
   3390 
   3391   /* Testing initial shaping */
   3392   src[0] = in[GENERIC];
   3393   src[1] = otherChar[GENERIC];
   3394   if (in[INITIAL] != 0) {
   3395     /* Testing characters that have an initial form */
   3396     errorCode=U_ZERO_ERROR;
   3397     length=u_shapeArabic(src, 2,
   3398                          dst, 2,
   3399                          U_SHAPE_LETTERS_SHAPE,
   3400                          &errorCode);
   3401     if(U_FAILURE(errorCode) || length!=2 || dst[0] != in[INITIAL] || dst[1] != otherChar[FINAL]) {
   3402       log_err("failure in u_shapeArabic(_testAllForms: shaping initial): %x\n", in[GENERIC]);
   3403     }
   3404     errorCode=U_ZERO_ERROR;
   3405     length=u_shapeArabic(dst, 2,
   3406                          src, 2,
   3407                          U_SHAPE_LETTERS_UNSHAPE,
   3408                          &errorCode);
   3409     if(U_FAILURE(errorCode) || length!=2 || src[0] != in[GENERIC] || src[1] != otherChar[GENERIC]) {
   3410       log_err("failure in u_shapeArabic(_testAllForms: unshaping initial): %x\n", in[GENERIC]);
   3411     }
   3412   } else {
   3413     /* Testing characters that do not have an initial form */
   3414     errorCode=U_ZERO_ERROR;
   3415     length=u_shapeArabic(src, 2,
   3416                          dst, 2,
   3417                          U_SHAPE_LETTERS_SHAPE,
   3418                          &errorCode);
   3419     if(U_FAILURE(errorCode) || length!=2 || dst[0] != in[ISOLATED] || dst[1] != otherChar[ISOLATED]) {
   3420       log_err("failure in u_shapeArabic(_testTwoForms: shaping initial): %x\n", in[GENERIC]);
   3421     }
   3422     errorCode=U_ZERO_ERROR;
   3423     length=u_shapeArabic(dst, 2,
   3424                          src, 2,
   3425                          U_SHAPE_LETTERS_UNSHAPE,
   3426                          &errorCode);
   3427     if(U_FAILURE(errorCode) || length!=2 || src[0] != in[GENERIC] || src[1] != otherChar[GENERIC]) {
   3428       log_err("failure in u_shapeArabic(_testTwoForms: unshaping initial): %x\n", in[GENERIC]);
   3429     }
   3430   }
   3431 
   3432   /* Testing medial shaping */
   3433   src[0] = otherChar[0];
   3434   src[1] = in[GENERIC];
   3435   src[2] = otherChar[0];
   3436   errorCode=U_ZERO_ERROR;
   3437   if (in[MEDIAL] != 0) {
   3438     /* Testing characters that have an medial form */
   3439     length=u_shapeArabic(src, 3,
   3440                          dst, 3,
   3441                          U_SHAPE_LETTERS_SHAPE,
   3442                          &errorCode);
   3443     if(U_FAILURE(errorCode) || length!=3 || dst[0] != otherChar[INITIAL] || dst[1] != in[MEDIAL] || dst[2] != otherChar[FINAL]) {
   3444       log_err("failure in u_shapeArabic(_testAllForms: shaping medial): %x\n", in[GENERIC]);
   3445     }
   3446     errorCode=U_ZERO_ERROR;
   3447     length=u_shapeArabic(dst, 3,
   3448                          src, 3,
   3449                          U_SHAPE_LETTERS_UNSHAPE,
   3450                          &errorCode);
   3451     if(U_FAILURE(errorCode) || length!=3 || src[0] != otherChar[GENERIC] || src[1] != in[GENERIC] || src[2] != otherChar[GENERIC]) {
   3452       log_err("failure in u_shapeArabic(_testAllForms: unshaping medial): %x\n", in[GENERIC]);
   3453     }
   3454   } else {
   3455     /* Testing characters that do not have an medial form */
   3456     errorCode=U_ZERO_ERROR;
   3457     length=u_shapeArabic(src, 3,
   3458                          dst, 3,
   3459                          U_SHAPE_LETTERS_SHAPE,
   3460                          &errorCode);
   3461     if(U_FAILURE(errorCode) || length!=3 || dst[0] != otherChar[INITIAL] || dst[1] != in[FINAL] || dst[2] != otherChar[ISOLATED]) {
   3462       log_err("failure in u_shapeArabic(_testTwoForms: shaping medial): %x\n", in[GENERIC]);
   3463     }
   3464     errorCode=U_ZERO_ERROR;
   3465     length=u_shapeArabic(dst, 3,
   3466                          src, 3,
   3467                          U_SHAPE_LETTERS_UNSHAPE,
   3468                          &errorCode);
   3469     if(U_FAILURE(errorCode) || length!=3 || src[0] != otherChar[GENERIC] || src[1] != in[GENERIC] || src[2] != otherChar[GENERIC]) {
   3470       log_err("failure in u_shapeArabic(_testTwoForms: unshaping medial): %x\n", in[GENERIC]);
   3471     }
   3472   }
   3473 }
   3474 
   3475 static void
   3476 doArabicShapingTestForNewCharacters(void) {
   3477   static const UChar letterForms[][5]={
   3478     { 0x0679, 0xFB66, 0xFB67, 0xFB68, 0xFB69 },  /* TTEH */
   3479     { 0x067A, 0xFB5E, 0xFB5F, 0xFB60, 0xFB61 },  /* TTEHEH */
   3480     { 0x067B, 0xFB52, 0xFB53, 0xFB54, 0xFB55 },  /* BEEH */
   3481     { 0x0688, 0xFB88, 0xFB89, 0, 0 },            /* DDAL */
   3482     { 0x068C, 0xFB84, 0xFB85, 0, 0 },            /* DAHAL */
   3483     { 0x068D, 0xFB82, 0xFB83, 0, 0 },            /* DDAHAL */
   3484     { 0x068E, 0xFB86, 0xFB87, 0, 0 },            /* DUL */
   3485     { 0x0691, 0xFB8C, 0xFB8D, 0, 0 },            /* RREH */
   3486     { 0x06BA, 0xFB9E, 0xFB9F, 0, 0 },            /* NOON GHUNNA */
   3487     { 0x06BB, 0xFBA0, 0xFBA1, 0xFBA2, 0xFBA3 },  /* RNOON */
   3488     { 0x06BE, 0xFBAA, 0xFBAB, 0xFBAC, 0xFBAD },  /* HEH DOACHASHMEE */
   3489     { 0x06C0, 0xFBA4, 0xFBA5, 0, 0 },            /* HEH WITH YEH ABOVE */
   3490     { 0x06C1, 0xFBA6, 0xFBA7, 0xFBA8, 0xFBA9 },  /* HEH GOAL */
   3491     { 0x06C5, 0xFBE0, 0xFBE1, 0, 0 },            /* KIRGIHIZ OE */
   3492     { 0x06C6, 0xFBD9, 0xFBDA, 0, 0 },            /* OE */
   3493     { 0x06C7, 0xFBD7, 0xFBD8, 0, 0 },            /* U */
   3494     { 0x06C8, 0xFBDB, 0xFBDC, 0, 0 },            /* YU */
   3495     { 0x06C9, 0xFBE2, 0xFBE3, 0, 0 },            /* KIRGIZ YU */
   3496     { 0x06CB, 0xFBDE, 0xFBDF, 0, 0},             /* VE */
   3497     { 0x06D0, 0xFBE4, 0xFBE5, 0xFBE6, 0xFBE7 },  /* E */
   3498     { 0x06D2, 0xFBAE, 0xFBAF, 0, 0 },            /* YEH BARREE */
   3499     { 0x06D3, 0xFBB0, 0xFBB1, 0, 0 },            /* YEH BARREE WITH HAMZA ABOVE */
   3500     { 0x0622, 0xFE81, 0xFE82, 0, 0, },           /* ALEF WITH MADDA ABOVE */
   3501     { 0x0623, 0xFE83, 0xFE84, 0, 0, },           /* ALEF WITH HAMZA ABOVE */
   3502     { 0x0624, 0xFE85, 0xFE86, 0, 0, },           /* WAW WITH HAMZA ABOVE */
   3503     { 0x0625, 0xFE87, 0xFE88, 0, 0, },           /* ALEF WITH HAMZA BELOW */
   3504     { 0x0626, 0xFE89, 0xFE8A, 0xFE8B, 0xFE8C, }, /* YEH WITH HAMZA ABOVE */
   3505     { 0x0627, 0xFE8D, 0xFE8E, 0, 0, },           /* ALEF */
   3506     { 0x0628, 0xFE8F, 0xFE90, 0xFE91, 0xFE92, }, /* BEH */
   3507     { 0x0629, 0xFE93, 0xFE94, 0, 0, },           /* TEH MARBUTA */
   3508     { 0x062A, 0xFE95, 0xFE96, 0xFE97, 0xFE98, }, /* TEH */
   3509     { 0x062B, 0xFE99, 0xFE9A, 0xFE9B, 0xFE9C, }, /* THEH */
   3510     { 0x062C, 0xFE9D, 0xFE9E, 0xFE9F, 0xFEA0, }, /* JEEM */
   3511     { 0x062D, 0xFEA1, 0xFEA2, 0xFEA3, 0xFEA4, }, /* HAH */
   3512     { 0x062E, 0xFEA5, 0xFEA6, 0xFEA7, 0xFEA8, }, /* KHAH */
   3513     { 0x062F, 0xFEA9, 0xFEAA, 0, 0, },           /* DAL */
   3514     { 0x0630, 0xFEAB, 0xFEAC, 0, 0, },           /* THAL */
   3515     { 0x0631, 0xFEAD, 0xFEAE, 0, 0, },           /* REH */
   3516     { 0x0632, 0xFEAF, 0xFEB0, 0, 0, },           /* ZAIN */
   3517     { 0x0633, 0xFEB1, 0xFEB2, 0xFEB3, 0xFEB4, }, /* SEEN */
   3518     { 0x0634, 0xFEB5, 0xFEB6, 0xFEB7, 0xFEB8, }, /* SHEEN */
   3519     { 0x0635, 0xFEB9, 0xFEBA, 0xFEBB, 0xFEBC, }, /* SAD */
   3520     { 0x0636, 0xFEBD, 0xFEBE, 0xFEBF, 0xFEC0, }, /* DAD */
   3521     { 0x0637, 0xFEC1, 0xFEC2, 0xFEC3, 0xFEC4, }, /* TAH */
   3522     { 0x0638, 0xFEC5, 0xFEC6, 0xFEC7, 0xFEC8, }, /* ZAH */
   3523     { 0x0639, 0xFEC9, 0xFECA, 0xFECB, 0xFECC, }, /* AIN */
   3524     { 0x063A, 0xFECD, 0xFECE, 0xFECF, 0xFED0, }, /* GHAIN */
   3525     { 0x0641, 0xFED1, 0xFED2, 0xFED3, 0xFED4, }, /* FEH */
   3526     { 0x0642, 0xFED5, 0xFED6, 0xFED7, 0xFED8, }, /* QAF */
   3527     { 0x0643, 0xFED9, 0xFEDA, 0xFEDB, 0xFEDC, }, /* KAF */
   3528     { 0x0644, 0xFEDD, 0xFEDE, 0xFEDF, 0xFEE0, }, /* LAM */
   3529     { 0x0645, 0xFEE1, 0xFEE2, 0xFEE3, 0xFEE4, }, /* MEEM */
   3530     { 0x0646, 0xFEE5, 0xFEE6, 0xFEE7, 0xFEE8, }, /* NOON */
   3531     { 0x0647, 0xFEE9, 0xFEEA, 0xFEEB, 0xFEEC, }, /* HEH */
   3532     { 0x0648, 0xFEED, 0xFEEE, 0, 0, },           /* WAW */
   3533     { 0x0649, 0xFEEF, 0xFEF0, 0, 0, },           /* ALEF MAKSURA */
   3534     { 0x064A, 0xFEF1, 0xFEF2, 0xFEF3, 0xFEF4, }, /* YEH */
   3535     { 0x064E, 0xFE76, 0, 0, 0xFE77, },           /* FATHA */
   3536     { 0x064F, 0xFE78, 0, 0, 0xFE79, },           /* DAMMA */
   3537     { 0x0650, 0xFE7A, 0, 0, 0xFE7B, },           /* KASRA */
   3538     { 0x0651, 0xFE7C, 0, 0, 0xFE7D, },           /* SHADDA */
   3539     { 0x0652, 0xFE7E, 0, 0, 0xFE7F, },           /* SUKUN */
   3540     { 0x0679, 0xFB66, 0xFB67, 0xFB68, 0xFB69, }, /* TTEH */
   3541     { 0x067E, 0xFB56, 0xFB57, 0xFB58, 0xFB59, }, /* PEH */
   3542     { 0x0686, 0xFB7A, 0xFB7B, 0xFB7C, 0xFB7D, }, /* TCHEH */
   3543     { 0x0688, 0xFB88, 0xFB89, 0, 0, },           /* DDAL */
   3544     { 0x0691, 0xFB8C, 0xFB8D, 0, 0, },           /* RREH */
   3545     { 0x0698, 0xFB8A, 0xFB8B, 0, 0, },           /* JEH */
   3546     { 0x06A9, 0xFB8E, 0xFB8F, 0xFB90, 0xFB91, }, /* KEHEH */
   3547     { 0x06AF, 0xFB92, 0xFB93, 0xFB94, 0xFB95, }, /* GAF */
   3548     { 0x06BA, 0xFB9E, 0xFB9F, 0, 0, },           /* NOON GHUNNA */
   3549     { 0x06BE, 0xFBAA, 0xFBAB, 0xFBAC, 0xFBAD, }, /* HEH DOACHASHMEE */
   3550     { 0x06C0, 0xFBA4, 0xFBA5, 0, 0, },           /* HEH WITH YEH ABOVE */
   3551     { 0x06C1, 0xFBA6, 0xFBA7, 0xFBA8, 0xFBA9, }, /* HEH GOAL */
   3552     { 0x06CC, 0xFBFC, 0xFBFD, 0xFBFE, 0xFBFF, }, /* FARSI YEH */
   3553     { 0x06D2, 0xFBAE, 0xFBAF, 0, 0, },           /* YEH BARREE */
   3554     { 0x06D3, 0xFBB0, 0xFBB1, 0, 0, }};          /* YEH BARREE WITH HAMZA ABOVE */
   3555   int32_t i;
   3556   for (i = 0; i < UPRV_LENGTHOF(letterForms); ++i) {
   3557     _testPresentationForms(letterForms[i]);
   3558   }
   3559 }
   3560 
   3561 /* helpers ------------------------------------------------------------------ */
   3562 
   3563 static void initCharFromDirProps(void) {
   3564     static const UVersionInfo ucd401={ 4, 0, 1, 0 };
   3565     static UVersionInfo ucdVersion={ 0, 0, 0, 0 };
   3566 
   3567     /* lazy initialization */
   3568     if(ucdVersion[0]>0) {
   3569         return;
   3570     }
   3571 
   3572     u_getUnicodeVersion(ucdVersion);
   3573     if(memcmp(ucdVersion, ucd401, sizeof(UVersionInfo))>=0) {
   3574         /* Unicode 4.0.1 changes bidi classes for +-/ */
   3575         charFromDirProp[U_EUROPEAN_NUMBER_SEPARATOR]=0x2b; /* change ES character from / to + */
   3576     }
   3577 }
   3578 
   3579 /* return a string with characters according to the desired directional properties */
   3580 static UChar *
   3581 getStringFromDirProps(const uint8_t *dirProps, int32_t length, UChar *buffer) {
   3582     int32_t i;
   3583 
   3584     initCharFromDirProps();
   3585 
   3586     /* this part would have to be modified for UTF-x */
   3587     for(i=0; i<length; ++i) {
   3588         buffer[i]=charFromDirProp[dirProps[i]];
   3589     }
   3590     buffer[length]=0;
   3591     return buffer;
   3592 }
   3593 
   3594 static void printUnicode(const UChar *s, int32_t length, const UBiDiLevel *levels) {
   3595     int32_t i;
   3596 
   3597     log_verbose("{ ");
   3598     for(i=0; i<length; ++i) {
   3599         if(levels!=NULL) {
   3600             log_verbose("%4x.%u  ", s[i], levels[i]);
   3601         } else {
   3602             log_verbose("%4x    ", s[i]);
   3603         }
   3604     }
   3605     log_verbose(" }");
   3606 }
   3607 
   3608 /* new BIDI API */
   3609 
   3610 /* Reordering Mode BiDi --------------------------------------------------------- */
   3611 
   3612 static const UBiDiLevel paraLevels[] = { UBIDI_LTR, UBIDI_RTL };
   3613 
   3614 static UBool
   3615 assertSuccessful(const char* message, UErrorCode* rc) {
   3616     if (rc != NULL && U_FAILURE(*rc)) {
   3617         log_err("%s() failed with error %s.\n", message, myErrorName(*rc));
   3618         return FALSE;
   3619     }
   3620     return TRUE;
   3621 }
   3622 
   3623 static UBool
   3624 assertStringsEqual(const char* expected, const char* actual, const char* src,
   3625                    const char* mode, const char* option, UBiDi* pBiDi) {
   3626     if (uprv_strcmp(expected, actual)) {
   3627         char formatChars[MAXLEN];
   3628         log_err("\nActual and expected output mismatch.\n"
   3629             "%20s %s\n%20s %s\n%20s %s\n%20s %s\n%20s %d %s\n%20s %u\n%20s %d %s\n",
   3630             "Input:", src,
   3631             "Actual output:", actual,
   3632             "Expected output:", expected,
   3633             "Levels:", formatLevels(pBiDi, formatChars),
   3634             "Reordering mode:", ubidi_getReorderingMode(pBiDi), mode,
   3635             "Paragraph level:", ubidi_getParaLevel(pBiDi),
   3636             "Reordering option:", ubidi_getReorderingOptions(pBiDi), option);
   3637         return FALSE;
   3638     }
   3639     return TRUE;
   3640 }
   3641 
   3642 static UBiDi*
   3643 getBiDiObject(void) {
   3644     UBiDi* pBiDi = ubidi_open();
   3645     if (pBiDi == NULL) {
   3646         log_err("Unable to allocate a UBiDi object. Tests are skipped.\n");
   3647     }
   3648     return pBiDi;
   3649 }
   3650 
   3651 #define MAKE_ITEMS(val) val, #val
   3652 
   3653 static const struct {
   3654     UBiDiReorderingMode value;
   3655     const char* description;
   3656 }
   3657 modes[] = {
   3658     { MAKE_ITEMS(UBIDI_REORDER_GROUP_NUMBERS_WITH_R) },
   3659     { MAKE_ITEMS(UBIDI_REORDER_INVERSE_LIKE_DIRECT) },
   3660     { MAKE_ITEMS(UBIDI_REORDER_NUMBERS_SPECIAL) },
   3661     { MAKE_ITEMS(UBIDI_REORDER_INVERSE_FOR_NUMBERS_SPECIAL) },
   3662     { MAKE_ITEMS(UBIDI_REORDER_INVERSE_NUMBERS_AS_L) }
   3663 };
   3664 static const struct {
   3665     uint32_t value;
   3666     const char* description;
   3667 }
   3668 options[] = {
   3669     { MAKE_ITEMS(UBIDI_OPTION_INSERT_MARKS) },
   3670     { MAKE_ITEMS(0) }
   3671 };
   3672 
   3673 #define TC_COUNT                UPRV_LENGTHOF(textIn)
   3674 #define MODES_COUNT             UPRV_LENGTHOF(modes)
   3675 #define OPTIONS_COUNT           UPRV_LENGTHOF(options)
   3676 #define LEVELS_COUNT            UPRV_LENGTHOF(paraLevels)
   3677 
   3678 static const char* const textIn[] = {
   3679 /* (0) 123 */
   3680     "123",
   3681 /* (1) .123->4.5 */
   3682     ".123->4.5",
   3683 /* (2) 678 */
   3684     "678",
   3685 /* (3) .678->8.9 */
   3686     ".678->8.9",
   3687 /* (4) JIH1.2,3MLK */
   3688     "JIH1.2,3MLK",
   3689 /* (5) FE.>12-> */
   3690     "FE.>12->",
   3691 /* (6) JIH.>12->a */
   3692     "JIH.>12->a",
   3693 /* (7) CBA.>67->89=a */
   3694     "CBA.>67->89=a",
   3695 /* (8) CBA.123->xyz */
   3696     "CBA.123->xyz",
   3697 /* (9) .>12->xyz */
   3698     ".>12->xyz",
   3699 /* (10) a.>67->xyz */
   3700     "a.>67->xyz",
   3701 /* (11) 123JIH */
   3702     "123JIH",
   3703 /* (12) 123 JIH */
   3704     "123 JIH"
   3705 };
   3706 
   3707 static const char* const textOut[] = {
   3708 /* TC 0: 123 */
   3709     "123",                                                              /* (0) */
   3710 /* TC 1: .123->4.5 */
   3711     ".123->4.5",                                                        /* (1) */
   3712     "4.5<-123.",                                                        /* (2) */
   3713 /* TC 2: 678 */
   3714     "678",                                                              /* (3) */
   3715 /* TC 3: .678->8.9 */
   3716     ".8.9<-678",                                                        /* (4) */
   3717     "8.9<-678.",                                                        /* (5) */
   3718     ".678->8.9",                                                        /* (6) */
   3719 /* TC 4: MLK1.2,3JIH */
   3720     "KLM1.2,3HIJ",                                                      /* (7) */
   3721 /* TC 5: FE.>12-> */
   3722     "12<.EF->",                                                         /* (8) */
   3723     "<-12<.EF",                                                         /* (9) */
   3724     "EF.>@12->",                                                        /* (10) */
   3725 /* TC 6: JIH.>12->a */
   3726     "12<.HIJ->a",                                                       /* (11) */
   3727     "a<-12<.HIJ",                                                       /* (12) */
   3728     "HIJ.>@12->a",                                                      /* (13) */
   3729     "a&<-12<.HIJ",                                                      /* (14) */
   3730 /* TC 7: CBA.>67->89=a */
   3731     "ABC.>@67->89=a",                                                   /* (15) */
   3732     "a=89<-67<.ABC",                                                    /* (16) */
   3733     "a&=89<-67<.ABC",                                                   /* (17) */
   3734     "89<-67<.ABC=a",                                                    /* (18) */
   3735 /* TC 8: CBA.123->xyz */
   3736     "123.ABC->xyz",                                                     /* (19) */
   3737     "xyz<-123.ABC",                                                     /* (20) */
   3738     "ABC.@123->xyz",                                                    /* (21) */
   3739     "xyz&<-123.ABC",                                                    /* (22) */
   3740 /* TC 9: .>12->xyz */
   3741     ".>12->xyz",                                                        /* (23) */
   3742     "xyz<-12<.",                                                        /* (24) */
   3743     "xyz&<-12<.",                                                       /* (25) */
   3744 /* TC 10: a.>67->xyz */
   3745     "a.>67->xyz",                                                       /* (26) */
   3746     "a.>@67@->xyz",                                                     /* (27) */
   3747     "xyz<-67<.a",                                                       /* (28) */
   3748 /* TC 11: 123JIH */
   3749     "123HIJ",                                                           /* (29) */
   3750     "HIJ123",                                                           /* (30) */
   3751 /* TC 12: 123 JIH */
   3752     "123 HIJ",                                                          /* (31) */
   3753     "HIJ 123",                                                          /* (32) */
   3754 };
   3755 
   3756 #define NO                  UBIDI_MAP_NOWHERE
   3757 #define MAX_MAP_LENGTH      20
   3758 
   3759 static const int32_t forwardMap[][MAX_MAP_LENGTH] = {
   3760 /* TC 0: 123 */
   3761     { 0, 1, 2 },                                                        /* (0) */
   3762 /* TC 1: .123->4.5 */
   3763     { 0, 1, 2, 3, 4, 5, 6, 7, 8 },                                      /* (1) */
   3764     { 8, 5, 6, 7, 4, 3, 0, 1, 2 },                                      /* (2) */
   3765 /* TC 2: 678 */
   3766     { 0, 1, 2 },                                                        /* (3) */
   3767 /* TC 3: .678->8.9 */
   3768     { 0, 6, 7, 8, 5, 4, 1, 2, 3 },                                      /* (4) */
   3769     { 8, 5, 6, 7, 4, 3, 0, 1, 2 },                                      /* (5) */
   3770     { 0, 1, 2, 3, 4, 5, 6, 7, 8 },                                      /* (6) */
   3771 /* TC 4: MLK1.2,3JIH */
   3772     { 10, 9, 8, 3, 4, 5, 6, 7, 2, 1, 0 },                               /* (7) */
   3773 /* TC 5: FE.>12-> */
   3774     { 5, 4, 3, 2, 0, 1, 6, 7 },                                         /* (8) */
   3775     { 7, 6, 5, 4, 2, 3, 1, 0 },                                         /* (9) */
   3776     { 1, 0, 2, 3, 5, 6, 7, 8 },                                         /* (10) */
   3777 /* TC 6: JIH.>12->a */
   3778     { 6, 5, 4, 3, 2, 0, 1, 7, 8, 9 },                                   /* (11) */
   3779     { 9, 8, 7, 6, 5, 3, 4, 2, 1, 0 },                                   /* (12) */
   3780     { 2, 1, 0, 3, 4, 6, 7, 8, 9, 10 },                                  /* (13) */
   3781     { 10, 9, 8, 7, 6, 4, 5, 3, 2, 0 },                                  /* (14) */
   3782 /* TC 7: CBA.>67->89=a */
   3783     { 2, 1, 0, 3, 4, 6, 7, 8, 9, 10, 11, 12, 13 },                      /* (15) */
   3784     { 12, 11, 10, 9, 8, 6, 7, 5, 4, 2, 3, 1, 0 },                       /* (16) */
   3785     { 13, 12, 11, 10, 9, 7, 8, 6, 5, 3, 4, 2, 0 },                      /* (17) */
   3786     { 10, 9, 8, 7, 6, 4, 5, 3, 2, 0, 1, 11, 12 },                       /* (18) */
   3787 /* TC 8: CBA.123->xyz */
   3788     { 6, 5, 4, 3, 0, 1, 2, 7, 8, 9, 10, 11 },                           /* (19) */
   3789     { 11, 10, 9, 8, 5, 6, 7, 4, 3, 0, 1, 2 },                           /* (20) */
   3790     { 2, 1, 0, 3, 5, 6, 7, 8, 9, 10, 11, 12 },                          /* (21) */
   3791     { 12, 11, 10, 9, 6, 7, 8, 5, 4, 0, 1, 2 },                          /* (22) */
   3792 /* TC 9: .>12->xyz */
   3793     { 0, 1, 2, 3, 4, 5, 6, 7, 8 },                                      /* (23) */
   3794     { 8, 7, 5, 6, 4, 3, 0, 1, 2 },                                      /* (24) */
   3795     { 9, 8, 6, 7, 5, 4, 0, 1, 2 },                                      /* (25) */
   3796 /* TC 10: a.>67->xyz */
   3797     { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 },                                   /* (26) */
   3798     { 0, 1, 2, 4, 5, 7, 8, 9, 10, 11 },                                 /* (27) */
   3799     { 9, 8, 7, 5, 6, 4, 3, 0, 1, 2 },                                   /* (28) */
   3800 /* TC 11: 123JIH */
   3801     { 0, 1, 2, 5, 4, 3 },                                               /* (29) */
   3802     { 3, 4, 5, 2, 1, 0 },                                               /* (30) */
   3803 /* TC 12: 123 JIH */
   3804     { 0, 1, 2, 3, 6, 5, 4 },                                            /* (31) */
   3805     { 4, 5, 6, 3, 2, 1, 0 },                                            /* (32) */
   3806 };
   3807 
   3808 static const int32_t inverseMap[][MAX_MAP_LENGTH] = {
   3809 /* TC 0: 123 */
   3810     { 0, 1, 2 },                                                        /* (0) */
   3811 /* TC 1: .123->4.5 */
   3812     { 0, 1, 2, 3, 4, 5, 6, 7, 8 },                                      /* (1) */
   3813     { 6, 7, 8, 5, 4, 1, 2, 3, 0 },                                      /* (2) */
   3814 /* TC 2: 678 */
   3815     { 0, 1, 2 },                                                        /* (3) */
   3816 /* TC 3: .678->8.9 */
   3817     { 0, 6, 7, 8, 5, 4, 1, 2, 3 },                                      /* (4) */
   3818     { 6, 7, 8, 5, 4, 1, 2, 3, 0 },                                      /* (5) */
   3819     { 0, 1, 2, 3, 4, 5, 6, 7, 8 },                                      /* (6) */
   3820 /* TC 4: MLK1.2,3JIH */
   3821     { 10, 9, 8, 3, 4, 5, 6, 7, 2, 1, 0 },                               /* (7) */
   3822 /* TC 5: FE.>12-> */
   3823     { 4, 5, 3, 2, 1, 0, 6, 7 },                                         /* (8) */
   3824     { 7, 6, 4, 5, 3, 2, 1, 0 },                                         /* (9) */
   3825     { 1, 0, 2, 3, NO, 4, 5, 6, 7 },                                     /* (10) */
   3826 /* TC 6: JIH.>12->a */
   3827     { 5, 6, 4, 3, 2, 1, 0, 7, 8, 9 },                                   /* (11) */
   3828     { 9, 8, 7, 5, 6, 4, 3, 2, 1, 0 },                                   /* (12) */
   3829     { 2, 1, 0, 3, 4, NO, 5, 6, 7, 8, 9 },                               /* (13) */
   3830     { 9, NO, 8, 7, 5, 6, 4, 3, 2, 1, 0 },                               /* (14) */
   3831 /* TC 7: CBA.>67->89=a */
   3832     { 2, 1, 0, 3, 4, NO, 5, 6, 7, 8, 9, 10, 11, 12 },                   /* (15) */
   3833     { 12, 11, 9, 10, 8, 7, 5, 6, 4, 3, 2, 1, 0 },                       /* (16) */
   3834     { 12, NO, 11, 9, 10, 8, 7, 5, 6, 4, 3, 2, 1, 0 },                   /* (17) */
   3835     { 9, 10, 8, 7, 5, 6, 4, 3, 2, 1, 0, 11, 12 },                       /* (18) */
   3836 /* TC 8: CBA.123->xyz */
   3837     { 4, 5, 6, 3, 2, 1, 0, 7, 8, 9, 10, 11 },                           /* (19) */
   3838     { 9, 10, 11, 8, 7, 4, 5, 6, 3, 2, 1, 0 },                           /* (20) */
   3839     { 2, 1, 0, 3, NO, 4, 5, 6, 7, 8, 9, 10, 11 },                       /* (21) */
   3840     { 9, 10, 11, NO, 8, 7, 4, 5, 6, 3, 2, 1, 0 },                       /* (22) */
   3841 /* TC 9: .>12->xyz */
   3842     { 0, 1, 2, 3, 4, 5, 6, 7, 8 },                                      /* (23) */
   3843     { 6, 7, 8, 5, 4, 2, 3, 1, 0 },                                      /* (24) */
   3844     { 6, 7, 8, NO, 5, 4, 2, 3, 1, 0 },                                  /* (25) */
   3845 /* TC 10: a.>67->xyz */
   3846     { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 },                                   /* (26) */
   3847     { 0, 1, 2, NO, 3, 4, NO, 5, 6, 7, 8, 9 },                           /* (27) */
   3848     { 7, 8, 9, 6, 5, 3, 4, 2, 1, 0 },                                   /* (28) */
   3849 /* TC 11: 123JIH */
   3850     { 0, 1, 2, 5, 4, 3 },                                               /* (29) */
   3851     { 5, 4, 3, 0, 1, 2 },                                               /* (30) */
   3852 /* TC 12: 123 JIH */
   3853     { 0, 1, 2, 3, 6, 5, 4 },                                            /* (31) */
   3854     { 6, 5, 4, 3, 0, 1, 2 },                                            /* (32) */
   3855 };
   3856 
   3857 static const char outIndices[TC_COUNT][MODES_COUNT - 1][OPTIONS_COUNT]
   3858             [LEVELS_COUNT] = {
   3859     { /* TC 0: 123 */
   3860         {{ 0,  0}, { 0,  0}}, /* UBIDI_REORDER_GROUP_NUMBERS_WITH_R */
   3861         {{ 0,  0}, { 0,  0}}, /* UBIDI_REORDER_INVERSE_LIKE_DIRECT */
   3862         {{ 0,  0}, { 0,  0}}, /* UBIDI_REORDER_NUMBERS_SPECIAL */
   3863         {{ 0,  0}, { 0,  0}}  /* UBIDI_REORDER_INVERSE_FOR_NUMBERS_SPECIAL */
   3864     },
   3865     { /* TC 1: .123->4.5 */
   3866         {{ 1,  2}, { 1,  2}}, /* UBIDI_REORDER_GROUP_NUMBERS_WITH_R */
   3867         {{ 1,  2}, { 1,  2}}, /* UBIDI_REORDER_INVERSE_LIKE_DIRECT */
   3868         {{ 1,  2}, { 1,  2}}, /* UBIDI_REORDER_NUMBERS_SPECIAL */
   3869         {{ 1,  2}, { 1,  2}}  /* UBIDI_REORDER_INVERSE_FOR_NUMBERS_SPECIAL */
   3870     },
   3871     { /* TC 2: 678 */
   3872         {{ 3,  3}, { 3,  3}}, /* UBIDI_REORDER_GROUP_NUMBERS_WITH_R */
   3873         {{ 3,  3}, { 3,  3}}, /* UBIDI_REORDER_INVERSE_LIKE_DIRECT */
   3874         {{ 3,  3}, { 3,  3}}, /* UBIDI_REORDER_NUMBERS_SPECIAL */
   3875         {{ 3,  3}, { 3,  3}}  /* UBIDI_REORDER_INVERSE_FOR_NUMBERS_SPECIAL */
   3876     },
   3877     { /* TC 3: .678->8.9 */
   3878         {{ 6,  5}, { 6,  5}}, /* UBIDI_REORDER_GROUP_NUMBERS_WITH_R */
   3879         {{ 4,  5}, { 4,  5}}, /* UBIDI_REORDER_INVERSE_LIKE_DIRECT */
   3880         {{ 6,  5}, { 6,  5}}, /* UBIDI_REORDER_NUMBERS_SPECIAL */
   3881         {{ 6,  5}, { 6,  5}}  /* UBIDI_REORDER_INVERSE_FOR_NUMBERS_SPECIAL */
   3882     },
   3883     { /* TC 4: MLK1.2,3JIH */
   3884         {{ 7,  7}, { 7,  7}}, /* UBIDI_REORDER_GROUP_NUMBERS_WITH_R */
   3885         {{ 7,  7}, { 7,  7}}, /* UBIDI_REORDER_INVERSE_LIKE_DIRECT */
   3886         {{ 7,  7}, { 7,  7}}, /* UBIDI_REORDER_NUMBERS_SPECIAL */
   3887         {{ 7,  7}, { 7,  7}}  /* UBIDI_REORDER_INVERSE_FOR_NUMBERS_SPECIAL */
   3888     },
   3889     { /* TC 5: FE.>12-> */
   3890         {{ 8,  9}, { 8,  9}}, /* UBIDI_REORDER_GROUP_NUMBERS_WITH_R */
   3891         {{10,  9}, { 8,  9}}, /* UBIDI_REORDER_INVERSE_LIKE_DIRECT */
   3892         {{ 8,  9}, { 8,  9}}, /* UBIDI_REORDER_NUMBERS_SPECIAL */
   3893         {{10,  9}, { 8,  9}}  /* UBIDI_REORDER_INVERSE_FOR_NUMBERS_SPECIAL */
   3894     },
   3895     { /* TC 6: JIH.>12->a */
   3896         {{11, 12}, {11, 12}}, /* UBIDI_REORDER_GROUP_NUMBERS_WITH_R */
   3897         {{13, 14}, {11, 12}}, /* UBIDI_REORDER_INVERSE_LIKE_DIRECT */
   3898         {{11, 12}, {11, 12}}, /* UBIDI_REORDER_NUMBERS_SPECIAL */
   3899         {{13, 14}, {11, 12}}  /* UBIDI_REORDER_INVERSE_FOR_NUMBERS_SPECIAL */
   3900     },
   3901     { /* TC 7: CBA.>67->89=a */
   3902         {{18, 16}, {18, 16}}, /* UBIDI_REORDER_GROUP_NUMBERS_WITH_R */
   3903         {{18, 17}, {18, 16}}, /* UBIDI_REORDER_INVERSE_LIKE_DIRECT */
   3904         {{18, 16}, {18, 16}}, /* UBIDI_REORDER_NUMBERS_SPECIAL */
   3905         {{15, 17}, {18, 16}}  /* UBIDI_REORDER_INVERSE_FOR_NUMBERS_SPECIAL */
   3906     },
   3907     { /* TC 8: CBA.>124->xyz */
   3908         {{19, 20}, {19, 20}}, /* UBIDI_REORDER_GROUP_NUMBERS_WITH_R */
   3909         {{21, 22}, {19, 20}}, /* UBIDI_REORDER_INVERSE_LIKE_DIRECT */
   3910         {{19, 20}, {19, 20}}, /* UBIDI_REORDER_NUMBERS_SPECIAL */
   3911         {{21, 22}, {19, 20}}  /* UBIDI_REORDER_INVERSE_FOR_NUMBERS_SPECIAL */
   3912     },
   3913     { /* TC 9: .>12->xyz */
   3914         {{23, 24}, {23, 24}}, /* UBIDI_REORDER_GROUP_NUMBERS_WITH_R */
   3915         {{23, 25}, {23, 24}}, /* UBIDI_REORDER_INVERSE_LIKE_DIRECT */
   3916         {{23, 24}, {23, 24}}, /* UBIDI_REORDER_NUMBERS_SPECIAL */
   3917         {{23, 25}, {23, 24}}  /* UBIDI_REORDER_INVERSE_FOR_NUMBERS_SPECIAL */
   3918     },
   3919     { /* TC 10: a.>67->xyz */
   3920         {{26, 26}, {26, 26}}, /* UBIDI_REORDER_GROUP_NUMBERS_WITH_R */
   3921         {{26, 27}, {26, 28}}, /* UBIDI_REORDER_INVERSE_LIKE_DIRECT */
   3922         {{26, 28}, {26, 28}}, /* UBIDI_REORDER_NUMBERS_SPECIAL */
   3923         {{26, 27}, {26, 28}}  /* UBIDI_REORDER_INVERSE_FOR_NUMBERS_SPECIAL */
   3924     },
   3925     { /* TC 11: 124JIH */
   3926         {{30, 30}, {30, 30}}, /* UBIDI_REORDER_GROUP_NUMBERS_WITH_R */
   3927         {{29, 30}, {29, 30}}, /* UBIDI_REORDER_INVERSE_LIKE_DIRECT */
   3928         {{30, 30}, {30, 30}}, /* UBIDI_REORDER_NUMBERS_SPECIAL */
   3929         {{30, 30}, {30, 30}}  /* UBIDI_REORDER_INVERSE_FOR_NUMBERS_SPECIAL */
   3930     },
   3931     { /* TC 12: 124 JIH */
   3932         {{32, 32}, {32, 32}}, /* UBIDI_REORDER_GROUP_NUMBERS_WITH_R */
   3933         {{31, 32}, {31, 32}}, /* UBIDI_REORDER_INVERSE_LIKE_DIRECT */
   3934         {{31, 32}, {31, 32}}, /* UBIDI_REORDER_NUMBERS_SPECIAL */
   3935         {{31, 32}, {31, 32}}  /* UBIDI_REORDER_INVERSE_FOR_NUMBERS_SPECIAL */
   3936     }
   3937 };
   3938 
   3939 static UBool
   3940 assertRoundTrip(UBiDi *pBiDi, int32_t tc, int32_t outIndex, const char *srcChars,
   3941                 const char *destChars, const UChar *dest, int32_t destLen,
   3942                 int mode, int option, UBiDiLevel level) {
   3943 
   3944     static const char roundtrip[TC_COUNT][MODES_COUNT][OPTIONS_COUNT]
   3945                 [LEVELS_COUNT] = {
   3946         { /* TC 0: 123 */
   3947             {{ 1,  1}, { 1,  1}}, /* UBIDI_REORDER_GROUP_NUMBERS_WITH_R */
   3948             {{ 1,  1}, { 1,  1}}, /* UBIDI_REORDER_INVERSE_LIKE_DIRECT */
   3949             {{ 1,  1}, { 1,  1}}, /* UBIDI_REORDER_NUMBERS_SPECIAL */
   3950             {{ 1,  1}, { 1,  1}}, /* UBIDI_REORDER_INVERSE_FOR_NUMBERS_SPECIAL */
   3951             {{ 1,  1}, { 1,  1}}  /* UBIDI_REORDER_INVERSE_NUMBERS_AS_L */
   3952         },
   3953         { /* TC 1: .123->4.5 */
   3954             {{ 1,  1}, { 1,  1}}, /* UBIDI_REORDER_GROUP_NUMBERS_WITH_R */
   3955             {{ 1,  1}, { 1,  1}}, /* UBIDI_REORDER_INVERSE_LIKE_DIRECT */
   3956             {{ 1,  1}, { 1,  1}}, /* UBIDI_REORDER_NUMBERS_SPECIAL */
   3957             {{ 1,  1}, { 1,  1}}, /* UBIDI_REORDER_INVERSE_FOR_NUMBERS_SPECIAL */
   3958             {{ 1,  1}, { 1,  1}}  /* UBIDI_REORDER_INVERSE_NUMBERS_AS_L */
   3959         },
   3960         { /* TC 2: 678 */
   3961             {{ 1,  1}, { 1,  1}}, /* UBIDI_REORDER_GROUP_NUMBERS_WITH_R */
   3962             {{ 1,  1}, { 1,  1}}, /* UBIDI_REORDER_INVERSE_LIKE_DIRECT */
   3963             {{ 1,  1}, { 1,  1}}, /* UBIDI_REORDER_NUMBERS_SPECIAL */
   3964             {{ 1,  1}, { 1,  1}}, /* UBIDI_REORDER_INVERSE_FOR_NUMBERS_SPECIAL */
   3965             {{ 1,  1}, { 1,  1}}  /* UBIDI_REORDER_INVERSE_NUMBERS_AS_L */
   3966         },
   3967         { /* TC 3: .678->8.9 */
   3968             {{ 1,  1}, { 1,  1}}, /* UBIDI_REORDER_GROUP_NUMBERS_WITH_R */
   3969             {{ 1,  1}, { 1,  1}}, /* UBIDI_REORDER_INVERSE_LIKE_DIRECT */
   3970             {{ 1,  1}, { 1,  1}}, /* UBIDI_REORDER_NUMBERS_SPECIAL */
   3971             {{ 1,  1}, { 1,  1}}, /* UBIDI_REORDER_INVERSE_FOR_NUMBERS_SPECIAL */
   3972             {{ 0,  0}, { 1,  1}}  /* UBIDI_REORDER_INVERSE_NUMBERS_AS_L */
   3973         },
   3974         { /* TC 4: MLK1.2,3JIH */
   3975             {{ 1,  1}, { 1,  1}}, /* UBIDI_REORDER_GROUP_NUMBERS_WITH_R */
   3976             {{ 1,  1}, { 1,  1}}, /* UBIDI_REORDER_INVERSE_LIKE_DIRECT */
   3977             {{ 1,  1}, { 1,  1}}, /* UBIDI_REORDER_NUMBERS_SPECIAL */
   3978             {{ 1,  1}, { 1,  1}}, /* UBIDI_REORDER_INVERSE_FOR_NUMBERS_SPECIAL */
   3979             {{ 1,  1}, { 1,  1}}  /* UBIDI_REORDER_INVERSE_NUMBERS_AS_L */
   3980         },
   3981         { /* TC 5: FE.>12-> */
   3982             {{ 1,  1}, { 1,  1}}, /* UBIDI_REORDER_GROUP_NUMBERS_WITH_R */
   3983             {{ 1,  1}, { 1,  1}}, /* UBIDI_REORDER_INVERSE_LIKE_DIRECT */
   3984             {{ 0,  1}, { 1,  1}}, /* UBIDI_REORDER_NUMBERS_SPECIAL */
   3985             {{ 1,  1}, { 1,  1}}, /* UBIDI_REORDER_INVERSE_FOR_NUMBERS_SPECIAL */
   3986             {{ 1,  1}, { 1,  1}}  /* UBIDI_REORDER_INVERSE_NUMBERS_AS_L */
   3987         },
   3988         { /* TC 6: JIH.>12->a */
   3989             {{ 1,  1}, { 1,  1}}, /* UBIDI_REORDER_GROUP_NUMBERS_WITH_R */
   3990             {{ 1,  1}, { 1,  1}}, /* UBIDI_REORDER_INVERSE_LIKE_DIRECT */
   3991             {{ 0,  0}, { 1,  1}}, /* UBIDI_REORDER_NUMBERS_SPECIAL */
   3992             {{ 1,  1}, { 1,  1}}, /* UBIDI_REORDER_INVERSE_FOR_NUMBERS_SPECIAL */
   3993             {{ 1,  1}, { 1,  1}}  /* UBIDI_REORDER_INVERSE_NUMBERS_AS_L */
   3994         },
   3995         { /* TC 7: CBA.>67->89=a */
   3996             {{ 1,  1}, { 1,  1}}, /* UBIDI_REORDER_GROUP_NUMBERS_WITH_R */
   3997             {{ 1,  1}, { 1,  1}}, /* UBIDI_REORDER_INVERSE_LIKE_DIRECT */
   3998             {{ 0,  1}, { 1,  1}}, /* UBIDI_REORDER_NUMBERS_SPECIAL */
   3999             {{ 1,  1}, { 1,  1}}, /* UBIDI_REORDER_INVERSE_FOR_NUMBERS_SPECIAL */
   4000             {{ 0,  0}, { 1,  1}}  /* UBIDI_REORDER_INVERSE_NUMBERS_AS_L */
   4001         },
   4002         { /* TC 8: CBA.>123->xyz */
   4003             {{ 1,  1}, { 1,  1}}, /* UBIDI_REORDER_GROUP_NUMBERS_WITH_R */
   4004             {{ 1,  1}, { 1,  1}}, /* UBIDI_REORDER_INVERSE_LIKE_DIRECT */
   4005             {{ 0,  0}, { 1,  1}}, /* UBIDI_REORDER_NUMBERS_SPECIAL */
   4006             {{ 1,  1}, { 1,  1}}, /* UBIDI_REORDER_INVERSE_FOR_NUMBERS_SPECIAL */
   4007             {{ 1,  1}, { 1,  1}}  /* UBIDI_REORDER_INVERSE_NUMBERS_AS_L */
   4008         },
   4009         { /* TC 9: .>12->xyz */
   4010             {{ 1,  1}, { 1,  1}}, /* UBIDI_REORDER_GROUP_NUMBERS_WITH_R */
   4011             {{ 1,  1}, { 1,  1}}, /* UBIDI_REORDER_INVERSE_LIKE_DIRECT */
   4012             {{ 1,  0}, { 1,  1}}, /* UBIDI_REORDER_NUMBERS_SPECIAL */
   4013             {{ 1,  1}, { 1,  1}}, /* UBIDI_REORDER_INVERSE_FOR_NUMBERS_SPECIAL */
   4014             {{ 1,  1}, { 1,  1}}  /* UBIDI_REORDER_INVERSE_NUMBERS_AS_L */
   4015         },
   4016         { /* TC 10: a.>67->xyz */
   4017             {{ 1,  1}, { 1,  1}}, /* UBIDI_REORDER_GROUP_NUMBERS_WITH_R */
   4018             {{ 1,  1}, { 1,  1}}, /* UBIDI_REORDER_INVERSE_LIKE_DIRECT */
   4019             {{ 1,  1}, { 1,  1}}, /* UBIDI_REORDER_NUMBERS_SPECIAL */
   4020             {{ 1,  1}, { 1,  1}}, /* UBIDI_REORDER_INVERSE_FOR_NUMBERS_SPECIAL */
   4021             {{ 1,  0}, { 1,  1}}  /* UBIDI_REORDER_INVERSE_NUMBERS_AS_L */
   4022         },
   4023         { /* TC 11: 123JIH */
   4024             {{ 1,  1}, { 1,  1}}, /* UBIDI_REORDER_GROUP_NUMBERS_WITH_R */
   4025             {{ 1,  1}, { 1,  1}}, /* UBIDI_REORDER_INVERSE_LIKE_DIRECT */
   4026             {{ 1,  1}, { 1,  1}}, /* UBIDI_REORDER_NUMBERS_SPECIAL */
   4027             {{ 1,  1}, { 1,  1}}, /* UBIDI_REORDER_INVERSE_FOR_NUMBERS_SPECIAL */
   4028             {{ 1,  1}, { 1,  1}}  /* UBIDI_REORDER_INVERSE_NUMBERS_AS_L */
   4029         },
   4030         { /* TC 12: 123 JIH */
   4031             {{ 1,  1}, { 1,  1}}, /* UBIDI_REORDER_GROUP_NUMBERS_WITH_R */
   4032             {{ 1,  1}, { 1,  1}}, /* UBIDI_REORDER_INVERSE_LIKE_DIRECT */
   4033             {{ 1,  1}, { 1,  1}}, /* UBIDI_REORDER_NUMBERS_SPECIAL */
   4034             {{ 1,  1}, { 1,  1}}, /* UBIDI_REORDER_INVERSE_FOR_NUMBERS_SPECIAL */
   4035             {{ 1,  1}, { 1,  1}}  /* UBIDI_REORDER_INVERSE_NUMBERS_AS_L */
   4036         }
   4037     };
   4038 
   4039     #define SET_ROUND_TRIP_MODE(mode) \
   4040         ubidi_setReorderingMode(pBiDi, mode); \
   4041         desc = #mode; \
   4042         break;
   4043 
   4044     UErrorCode rc = U_ZERO_ERROR;
   4045     UChar dest2[MAXLEN];
   4046     int32_t destLen2;
   4047     const char* desc;
   4048     char destChars2[MAXLEN];
   4049     char destChars3[MAXLEN];
   4050 
   4051     switch (modes[mode].value) {
   4052         case UBIDI_REORDER_NUMBERS_SPECIAL:
   4053             SET_ROUND_TRIP_MODE(UBIDI_REORDER_INVERSE_FOR_NUMBERS_SPECIAL)
   4054         case UBIDI_REORDER_GROUP_NUMBERS_WITH_R:
   4055             SET_ROUND_TRIP_MODE(UBIDI_REORDER_GROUP_NUMBERS_WITH_R)
   4056         case UBIDI_REORDER_RUNS_ONLY:
   4057             SET_ROUND_TRIP_MODE(UBIDI_REORDER_RUNS_ONLY)
   4058         case UBIDI_REORDER_INVERSE_NUMBERS_AS_L:
   4059             SET_ROUND_TRIP_MODE(UBIDI_REORDER_DEFAULT)
   4060         case UBIDI_REORDER_INVERSE_LIKE_DIRECT:
   4061             SET_ROUND_TRIP_MODE(UBIDI_REORDER_DEFAULT)
   4062         case UBIDI_REORDER_INVERSE_FOR_NUMBERS_SPECIAL:
   4063             SET_ROUND_TRIP_MODE(UBIDI_REORDER_NUMBERS_SPECIAL)
   4064         default:
   4065             SET_ROUND_TRIP_MODE(UBIDI_REORDER_INVERSE_LIKE_DIRECT)
   4066     }
   4067     ubidi_setReorderingOptions(pBiDi, UBIDI_OPTION_REMOVE_CONTROLS);
   4068 
   4069     ubidi_setPara(pBiDi, dest, destLen, level, NULL, &rc);
   4070     assertSuccessful("ubidi_setPara", &rc);
   4071     *dest2 = 0;
   4072     destLen2 = ubidi_writeReordered(pBiDi, dest2, MAXLEN, UBIDI_DO_MIRRORING,
   4073                                     &rc);
   4074     assertSuccessful("ubidi_writeReordered", &rc);
   4075 
   4076     u16ToPseudo(destLen, dest, destChars3);
   4077     u16ToPseudo(destLen2, dest2, destChars2);
   4078     checkWhatYouCan(pBiDi, destChars3, destChars2);
   4079     if (strcmp(srcChars, destChars2)) {
   4080         if (roundtrip[tc][mode][option][level]) {
   4081             log_err("\nRound trip failed for case=%d mode=%d option=%d.\n"
   4082                     "%20s %s\n%20s %s\n%20s %s\n%20s %s\n%20s %s"
   4083                     "\n%20s %u\n", tc, mode, option,
   4084                     "Original text:", srcChars,
   4085                     "Round-tripped text:", destChars2,
   4086                     "Intermediate  text:", destChars3,
   4087                     "Reordering mode:", modes[mode].description,
   4088                     "Reordering option:", options[option].description,
   4089                     "Paragraph level:", level);
   4090         }
   4091         else {
   4092             log_verbose("\nExpected round trip failure for case=%d mode=%d option=%d.\n"
   4093                     "%20s %s\n%20s %s\n%20s %s\n%20s %s\n%20s %s"
   4094                     "\n%20s %u\n", tc, mode, option,
   4095                     "Original text:", srcChars,
   4096                     "Round-tripped text:", destChars2,
   4097                     "Intermediate  text:", destChars3,
   4098                     "Reordering mode:", modes[mode].description,
   4099                     "Reordering option:", options[option].description,
   4100                     "Paragraph level:", level);
   4101         }
   4102         return FALSE;
   4103     }
   4104     if (!checkResultLength(pBiDi, destChars, destChars2, destLen2,
   4105                            desc, "UBIDI_OPTION_REMOVE_CONTROLS", level)) {
   4106         return FALSE;
   4107     }
   4108     if (outIndex > -1 && !checkMaps(pBiDi, outIndex, srcChars, destChars,
   4109                                     desc, "UBIDI_OPTION_REMOVE_CONTROLS",
   4110                                     level, FALSE)) {
   4111         return FALSE;
   4112     }
   4113     return TRUE;
   4114 }
   4115 
   4116 static UBool
   4117 checkResultLength(UBiDi *pBiDi, const char *srcChars, const char *destChars,
   4118                   int32_t destLen, const char* mode,
   4119                   const char* option, UBiDiLevel level) {
   4120     int32_t actualLen;
   4121     if (strcmp(mode, "UBIDI_REORDER_INVERSE_NUMBERS_AS_L") == 0)
   4122         actualLen = strlen(destChars);
   4123     else
   4124         actualLen = ubidi_getResultLength(pBiDi);
   4125     if (actualLen != destLen) {
   4126         log_err("\nubidi_getResultLength failed.\n%20s %7d\n%20s %7d\n"
   4127                 "%20s %s\n%20s %s\n%20s %s\n%20s %s\n%20s %u\n",
   4128                 "Expected:", destLen, "Actual:", actualLen,
   4129                 "Input:", srcChars, "Output:", destChars,
   4130                 "Reordering mode:", mode, "Reordering option:", option,
   4131                 "Paragraph level:", level);
   4132         return FALSE;
   4133     }
   4134     return TRUE;
   4135 }
   4136 
   4137 static void
   4138 testReorderRunsOnly(void) {
   4139     static const struct {
   4140         const char* textIn;
   4141         const char* textOut[2][2];
   4142         const char noroundtrip[2];
   4143     } testCases[] = {
   4144         {"ab 234 896 de", {{"de 896 ab 234", "de 896 ab 234"},                   /*0*/
   4145                            {"ab 234 @896@ de", "de 896 ab 234"}}, {0, 0}},
   4146         {"abcGHI", {{"GHIabc", "GHIabc"}, {"GHIabc", "GHIabc"}}, {0, 0}},        /*1*/
   4147         {"a.>67->", {{"<-67<.a", "<-67<.a"}, {"<-67<.a", "<-67<.a"}}, {0, 0}},   /*2*/
   4148         {"-=%$123/ *", {{"* /%$123=-", "* /%$123=-"},                            /*3*/
   4149                         {"* /%$123=-", "* /%$123=-"}}, {0, 0}},
   4150         {"abc->12..>JKL", {{"JKL<..12<-abc", "JKL<..abc->12"},                   /*4*/
   4151                            {"JKL<..12<-abc", "JKL<..abc->12"}}, {0, 0}},
   4152         {"JKL->12..>abc", {{"abc<..JKL->12", "abc<..12<-JKL"},                   /*5*/
   4153                            {"abc<..JKL->12", "abc<..12<-JKL"}}, {0, 0}},
   4154         {"123->abc", {{"abc<-123", "abc<-123"},                                  /*6*/
   4155                       {"abc&<-123", "abc<-123"}}, {1, 0}},
   4156         {"123->JKL", {{"JKL<-123", "123->JKL"},                                  /*7*/
   4157                       {"JKL<-123", "JKL<-@123"}}, {0, 1}},
   4158         {"*>12.>34->JKL", {{"JKL<-34<.12<*", "12.>34->JKL<*"},                   /*8*/
   4159                            {"JKL<-34<.12<*", "JKL<-@34<.12<*"}}, {0, 1}},
   4160         {"*>67.>89->JKL", {{"67.>89->JKL<*", "67.>89->JKL<*"},                   /*9*/
   4161                            {"67.>89->JKL<*", "67.>89->JKL<*"}}, {0, 0}},
   4162         {"* /abc-=$%123", {{"$%123=-abc/ *", "abc-=$%123/ *"},                   /*10*/
   4163                            {"$%123=-abc/ *", "abc-=$%123/ *"}}, {0, 0}},
   4164         {"* /$%def-=123", {{"123=-def%$/ *", "def-=123%$/ *"},                   /*11*/
   4165                            {"123=-def%$/ *", "def-=123%$/ *"}}, {0, 0}},
   4166         {"-=GHI* /123%$", {{"GHI* /123%$=-", "123%$/ *GHI=-"},                   /*12*/
   4167                            {"GHI* /123%$=-", "123%$/ *GHI=-"}}, {0, 0}},
   4168         {"-=%$JKL* /123", {{"JKL* /%$123=-", "123/ *JKL$%=-"},                   /*13*/
   4169                            {"JKL* /%$123=-", "123/ *JKL$%=-"}}, {0, 0}},
   4170         {"ab =#CD *?450", {{"CD *?450#= ab", "450?* CD#= ab"},                   /*14*/
   4171                            {"CD *?450#= ab", "450?* CD#= ab"}}, {0, 0}},
   4172         {"ab 234 896 de", {{"de 896 ab 234", "de 896 ab 234"},                   /*15*/
   4173                            {"ab 234 @896@ de", "de 896 ab 234"}}, {0, 0}},
   4174         {"abc-=%$LMN* /123", {{"LMN* /%$123=-abc", "123/ *LMN$%=-abc"},          /*16*/
   4175                               {"LMN* /%$123=-abc", "123/ *LMN$%=-abc"}}, {0, 0}},
   4176         {"123->JKL&MN&P", {{"JKLMNP<-123", "123->JKLMNP"},                       /*17*/
   4177                            {"JKLMNP<-123", "JKLMNP<-@123"}}, {0, 1}},
   4178         {"123", {{"123", "123"},                /* just one run */               /*18*/
   4179                  {"123", "123"}}, {0, 0}}
   4180     };
   4181     UBiDi *pBiDi = getBiDiObject();
   4182     UBiDi *pL2VBiDi = getBiDiObject();
   4183     UChar src[MAXLEN], dest[MAXLEN], visual1[MAXLEN], visual2[MAXLEN];
   4184     char destChars[MAXLEN], vis1Chars[MAXLEN], vis2Chars[MAXLEN];
   4185     int32_t srcLen, destLen, vis1Len, vis2Len, option, i, j, nCases, paras;
   4186     UErrorCode rc = U_ZERO_ERROR;
   4187     UBiDiLevel level;
   4188 
   4189     log_verbose("\nEntering TestReorderRunsOnly\n\n");
   4190 
   4191     if(!pL2VBiDi) {
   4192         ubidi_close(pBiDi);             /* in case this one was allocated */
   4193         return;
   4194     }
   4195     ubidi_setReorderingMode(pBiDi, UBIDI_REORDER_RUNS_ONLY);
   4196     ubidi_setReorderingOptions(pL2VBiDi, UBIDI_OPTION_REMOVE_CONTROLS);
   4197 
   4198     for (option = 0; option < 2; option++) {
   4199         ubidi_setReorderingOptions(pBiDi, option==0 ? UBIDI_OPTION_REMOVE_CONTROLS
   4200                                                     : UBIDI_OPTION_INSERT_MARKS);
   4201         for (i = 0, nCases = UPRV_LENGTHOF(testCases); i < nCases; i++) {
   4202             srcLen = strlen(testCases[i].textIn);
   4203             pseudoToU16(srcLen, testCases[i].textIn, src);
   4204             for(j = 0; j < 2; j++) {
   4205                 log_verbose("Now doing test for option %d, case %d, level %d\n",
   4206                             i, option, j);
   4207                 level = paraLevels[j];
   4208                 ubidi_setPara(pBiDi, src, srcLen, level, NULL, &rc);
   4209                 assertSuccessful("ubidi_setPara", &rc);
   4210                 *dest = 0;
   4211                 destLen = ubidi_writeReordered(pBiDi, dest, MAXLEN, UBIDI_DO_MIRRORING, &rc);
   4212                 assertSuccessful("ubidi_writeReordered", &rc);
   4213                 u16ToPseudo(destLen, dest, destChars);
   4214                 checkWhatYouCan(pBiDi, testCases[i].textIn, destChars);
   4215                 assertStringsEqual(testCases[i].textOut[option][level], destChars,
   4216                         testCases[i].textIn, "UBIDI_REORDER_RUNS_ONLY",
   4217                         option==0 ? "0" : "UBIDI_OPTION_INSERT_MARKS",
   4218                         pBiDi);
   4219 
   4220                 if((option==0) && testCases[i].noroundtrip[level]) {
   4221                     continue;
   4222                 }
   4223                 ubidi_setPara(pL2VBiDi, src, srcLen, level, NULL, &rc);
   4224                 assertSuccessful("ubidi_setPara1", &rc);
   4225                 *visual1 = 0;
   4226                 vis1Len = ubidi_writeReordered(pL2VBiDi, visual1, MAXLEN, UBIDI_DO_MIRRORING, &rc);
   4227                 assertSuccessful("ubidi_writeReordered1", &rc);
   4228                 u16ToPseudo(vis1Len, visual1, vis1Chars);
   4229                 checkWhatYouCan(pL2VBiDi, testCases[i].textIn, vis1Chars);
   4230                 ubidi_setPara(pL2VBiDi, dest, destLen, level^1, NULL, &rc);
   4231                 assertSuccessful("ubidi_setPara2", &rc);
   4232                 *visual2 = 0;
   4233                 vis2Len = ubidi_writeReordered(pL2VBiDi, visual2, MAXLEN, UBIDI_DO_MIRRORING, &rc);
   4234                 assertSuccessful("ubidi_writeReordered2", &rc);
   4235                 u16ToPseudo(vis2Len, visual2, vis2Chars);
   4236                 checkWhatYouCan(pL2VBiDi, destChars, vis2Chars);
   4237                 assertStringsEqual(vis1Chars, vis2Chars,
   4238                         testCases[i].textIn, "UBIDI_REORDER_RUNS_ONLY (2)",
   4239                         option==0 ? "0" : "UBIDI_OPTION_INSERT_MARKS",
   4240                         pBiDi);
   4241             }
   4242         }
   4243     }
   4244 
   4245     /* test with null or empty text */
   4246     ubidi_setPara(pBiDi, src, 0, UBIDI_LTR, NULL, &rc);
   4247     assertSuccessful("ubidi_setPara3", &rc);
   4248     paras = ubidi_countParagraphs(pBiDi);
   4249     if (paras != 0) {
   4250         log_err("\nInvalid number of paras (should be 0): %d\n", paras);
   4251     }
   4252 
   4253     ubidi_close(pBiDi);
   4254     ubidi_close(pL2VBiDi);
   4255 
   4256     log_verbose("\nExiting TestReorderRunsOnly\n\n");
   4257 }
   4258 
   4259 static void
   4260 testReorderingMode(void) {
   4261 
   4262     UChar src[MAXLEN], dest[MAXLEN];
   4263     char destChars[MAXLEN];
   4264     UBiDi *pBiDi = NULL, *pBiDi2 = NULL, *pBiDi3 = NULL;
   4265     UErrorCode rc;
   4266     int tc, mode, option, level;
   4267     uint32_t optionValue, optionBack;
   4268     UBiDiReorderingMode modeValue, modeBack;
   4269     int32_t srcLen, destLen, idx;
   4270     const char *expectedChars;
   4271     UBool testOK = TRUE;
   4272 
   4273     log_verbose("\nEntering TestReorderingMode\n\n");
   4274 
   4275     pBiDi = getBiDiObject();
   4276     pBiDi2 = getBiDiObject();
   4277     pBiDi3 = getBiDiObject();
   4278     if(!pBiDi3) {
   4279         ubidi_close(pBiDi);             /* in case this one was allocated */
   4280         ubidi_close(pBiDi2);            /* in case this one was allocated */
   4281         return;
   4282     }
   4283 
   4284     ubidi_setInverse(pBiDi2, TRUE);
   4285 
   4286     for (tc = 0; tc < TC_COUNT; tc++) {
   4287         const char *srcChars = textIn[tc];
   4288         srcLen = strlen(srcChars);
   4289         pseudoToU16(srcLen, srcChars, src);
   4290 
   4291         for (mode = 0; mode < MODES_COUNT; mode++) {
   4292             modeValue = modes[mode].value;
   4293             ubidi_setReorderingMode(pBiDi, modeValue);
   4294             modeBack = ubidi_getReorderingMode(pBiDi);
   4295             if (modeValue != modeBack) {
   4296                 log_err("Error while setting reordering mode to %d, returned %d\n",
   4297                         modeValue, modeBack);
   4298             }
   4299 
   4300             for (option = 0; option < OPTIONS_COUNT; option++) {
   4301                 optionValue = options[option].value;
   4302                 ubidi_setReorderingOptions(pBiDi, optionValue);
   4303                 optionBack = ubidi_getReorderingOptions(pBiDi);
   4304                 if (optionValue != optionBack) {
   4305                     log_err("Error while setting reordering option to %d, returned %d\n",
   4306                             optionValue, optionBack);
   4307                 }
   4308 
   4309                 for (level = 0; level < LEVELS_COUNT; level++) {
   4310                     log_verbose("starting test %d mode=%d option=%d level=%d\n",
   4311                                 tc, modes[mode].value, options[option].value, level);
   4312                     rc = U_ZERO_ERROR;
   4313                     ubidi_setPara(pBiDi, src, srcLen, paraLevels[level], NULL, &rc);
   4314                     assertSuccessful("ubidi_setPara", &rc);
   4315 
   4316                     *dest = 0;
   4317                     destLen = ubidi_writeReordered(pBiDi, dest, MAXLEN,
   4318                                                    UBIDI_DO_MIRRORING, &rc);
   4319                     assertSuccessful("ubidi_writeReordered", &rc);
   4320                     u16ToPseudo(destLen, dest, destChars);
   4321                     if (!((modes[mode].value == UBIDI_REORDER_INVERSE_NUMBERS_AS_L) &&
   4322                           (options[option].value == UBIDI_OPTION_INSERT_MARKS))) {
   4323                         checkWhatYouCan(pBiDi, srcChars, destChars);
   4324                     }
   4325 
   4326                     if (modes[mode].value == UBIDI_REORDER_INVERSE_NUMBERS_AS_L) {
   4327                         idx = -1;
   4328                         expectedChars = inverseBasic(pBiDi2, srcChars, srcLen,
   4329                                 options[option].value, paraLevels[level], destChars);
   4330                     }
   4331                     else {
   4332                         idx = outIndices[tc][mode][option][level];
   4333                         expectedChars = textOut[idx];
   4334                     }
   4335                     if (!assertStringsEqual(expectedChars, destChars, srcChars,
   4336                                 modes[mode].description,
   4337                                 options[option].description,
   4338                                 pBiDi)) {
   4339                         testOK = FALSE;
   4340                     }
   4341                     if (options[option].value == UBIDI_OPTION_INSERT_MARKS &&
   4342                              !assertRoundTrip(pBiDi3, tc, idx, srcChars,
   4343                                               destChars, dest, destLen,
   4344                                               mode, option, paraLevels[level])) {
   4345                         testOK = FALSE;
   4346                     }
   4347                     else if (!checkResultLength(pBiDi, srcChars, destChars,
   4348                                 destLen, modes[mode].description,
   4349                                 options[option].description,
   4350                                 paraLevels[level])) {
   4351                         testOK = FALSE;
   4352                     }
   4353                     else if (idx > -1 && !checkMaps(pBiDi, idx, srcChars,
   4354                             destChars, modes[mode].description,
   4355                             options[option].description, paraLevels[level],
   4356                             TRUE)) {
   4357                         testOK = FALSE;
   4358                     }
   4359                 }
   4360             }
   4361         }
   4362     }
   4363     if (testOK == TRUE) {
   4364         log_verbose("\nReordering mode test OK\n");
   4365     }
   4366     ubidi_close(pBiDi3);
   4367     ubidi_close(pBiDi2);
   4368     ubidi_close(pBiDi);
   4369 
   4370     log_verbose("\nExiting TestReorderingMode\n\n");
   4371 }
   4372 
   4373 static const char* inverseBasic(UBiDi *pBiDi, const char *srcChars, int32_t srcLen,
   4374                                 uint32_t option, UBiDiLevel level, char *result) {
   4375     UErrorCode rc = U_ZERO_ERROR;
   4376     int32_t destLen;
   4377     UChar src[MAXLEN], dest2[MAXLEN];
   4378 
   4379     if (pBiDi == NULL || srcChars == NULL) {
   4380         return NULL;
   4381     }
   4382     ubidi_setReorderingOptions(pBiDi, option);
   4383     pseudoToU16(srcLen, srcChars, src);
   4384     ubidi_setPara(pBiDi, src, srcLen, level, NULL, &rc);
   4385     assertSuccessful("ubidi_setPara", &rc);
   4386 
   4387     *dest2 = 0;
   4388     destLen = ubidi_writeReordered(pBiDi, dest2, MAXLEN,
   4389                                    UBIDI_DO_MIRRORING, &rc);
   4390     assertSuccessful("ubidi_writeReordered", &rc);
   4391     u16ToPseudo(destLen, dest2, result);
   4392     if (!(option == UBIDI_OPTION_INSERT_MARKS)) {
   4393         checkWhatYouCan(pBiDi, srcChars, result);
   4394     }
   4395     return result;
   4396 }
   4397 
   4398 #define NULL_CHAR '\0'
   4399 
   4400 static void
   4401 testStreaming(void) {
   4402 #define MAXPORTIONS 10
   4403 
   4404     static const struct {
   4405         const char* textIn;
   4406         short int chunk;
   4407         short int nPortions[2];
   4408         char  portionLens[2][MAXPORTIONS];
   4409         const char* message[2];
   4410     } testData[] = {
   4411         {   "123\\u000A"
   4412             "abc45\\u000D"
   4413             "67890\\u000A"
   4414             "\\u000D"
   4415             "02468\\u000D"
   4416             "ghi",
   4417             6, { 6, 6 }, {{ 4, 6, 6, 1, 6, 3}, { 4, 6, 6, 1, 6, 3 }},
   4418             {"4, 6, 6, 1, 6, 3", "4, 6, 6, 1, 6, 3"}
   4419         },
   4420         {   "abcd\\u000Afgh\\u000D12345\\u000A456",
   4421             6, { 4, 4 }, {{ 5, 4, 6, 3 }, { 5, 4, 6, 3 }},
   4422             {"5, 4, 6, 3", "5, 4, 6, 3"}
   4423         },
   4424         {   "abcd\\u000Afgh\\u000D12345\\u000A45\\u000D",
   4425             6, { 4, 4 }, {{ 5, 4, 6, 3 }, { 5, 4, 6, 3 }},
   4426             {"5, 4, 6, 3", "5, 4, 6, 3"}
   4427         },
   4428         {   "abcde\\u000Afghi",
   4429             10, { 2, 2 }, {{ 6, 4 }, { 6, 4 }},
   4430             {"6, 4", "6, 4"}
   4431         }
   4432     };
   4433     UChar src[MAXLEN];
   4434     UBiDi *pBiDi = NULL;
   4435     UChar *pSrc;
   4436     UErrorCode rc = U_ZERO_ERROR;
   4437     int32_t srcLen, processedLen, chunk, len, nPortions;
   4438     int i, j, levelIndex;
   4439     UBiDiLevel level;
   4440     int nTests = UPRV_LENGTHOF(testData), nLevels = UPRV_LENGTHOF(paraLevels);
   4441     UBool mismatch, testOK = TRUE;
   4442    char processedLenStr[MAXPORTIONS * 5];
   4443 
   4444     log_verbose("\nEntering TestStreaming\n\n");
   4445 
   4446     pBiDi = getBiDiObject();
   4447 
   4448     ubidi_orderParagraphsLTR(pBiDi, TRUE);
   4449 
   4450     for (levelIndex = 0; levelIndex < nLevels; levelIndex++) {
   4451         for (i = 0; i < nTests; i++) {
   4452             srcLen = u_unescape(testData[i].textIn, src, MAXLEN);
   4453             chunk = testData[i].chunk;
   4454             nPortions = testData[i].nPortions[levelIndex];
   4455             level = paraLevels[levelIndex];
   4456             processedLenStr[0] = NULL_CHAR;
   4457             log_verbose("Testing level %d, case %d\n", level, i);
   4458 
   4459             mismatch = FALSE;
   4460 
   4461             ubidi_setReorderingOptions(pBiDi, UBIDI_OPTION_STREAMING);
   4462             for (j = 0, pSrc = src; j < MAXPORTIONS && srcLen > 0; j++) {
   4463 
   4464                 len = chunk < srcLen ? chunk : srcLen;
   4465                 ubidi_setPara(pBiDi, pSrc, len, level, NULL, &rc);
   4466                 if (!assertSuccessful("ubidi_setPara", &rc)) {
   4467                     break;
   4468                 }
   4469 
   4470                 processedLen = ubidi_getProcessedLength(pBiDi);
   4471                 if (processedLen == 0) {
   4472                     ubidi_setReorderingOptions(pBiDi, UBIDI_OPTION_DEFAULT);
   4473                     j--;
   4474                     continue;
   4475                 }
   4476                 ubidi_setReorderingOptions(pBiDi, UBIDI_OPTION_STREAMING);
   4477 
   4478                 mismatch |= (UBool)(j >= nPortions ||
   4479                            processedLen != testData[i].portionLens[levelIndex][j]);
   4480 
   4481                 sprintf(processedLenStr + j * 4, "%4d", processedLen);
   4482                 srcLen -= processedLen, pSrc += processedLen;
   4483             }
   4484 
   4485             if (mismatch || j != nPortions) {
   4486                 testOK = FALSE;
   4487                 log_err("\nProcessed lengths mismatch.\n"
   4488                     "\tParagraph level: %u\n"
   4489                     "\tInput string: %s\n"
   4490                     "\tActually processed portion lengths: { %s }\n"
   4491                     "\tExpected portion lengths          : { %s }\n",
   4492                     paraLevels[levelIndex], testData[i].textIn,
   4493                     processedLenStr, testData[i].message[levelIndex]);
   4494             }
   4495         }
   4496     }
   4497     ubidi_close(pBiDi);
   4498     if (testOK == TRUE) {
   4499         log_verbose("\nBiDi streaming test OK\n");
   4500     }
   4501     log_verbose("\nExiting TestStreaming\n\n");
   4502 }
   4503 
   4504 U_CDECL_BEGIN
   4505 
   4506 static UCharDirection U_CALLCONV
   4507 overrideBidiClass(const void *context, UChar32 c) {
   4508 
   4509 #define DEF U_BIDI_CLASS_DEFAULT
   4510 
   4511     static const UCharDirection customClasses[] = {
   4512        /* 0/8    1/9    2/A    3/B    4/C    5/D    6/E    7/F  */
   4513           DEF,   DEF,   DEF,   DEF,   DEF,   DEF,   DEF,   DEF, /* 00-07 */
   4514           DEF,   DEF,   DEF,   DEF,   DEF,   DEF,   DEF,   DEF, /* 08-0F */
   4515           DEF,   DEF,   DEF,   DEF,   DEF,   DEF,   DEF,   DEF, /* 10-17 */
   4516           DEF,   DEF,   DEF,   DEF,   DEF,   DEF,   DEF,   DEF, /* 18-1F */
   4517           DEF,   DEF,   DEF,   DEF,   DEF,   DEF,     R,   DEF, /* 20-27 */
   4518           DEF,   DEF,   DEF,   DEF,   DEF,   DEF,   DEF,   DEF, /* 28-2F */
   4519            EN,    EN,    EN,    EN,    EN,    EN,    AN,    AN, /* 30-37 */
   4520            AN,    AN,   DEF,   DEF,   DEF,   DEF,   DEF,   DEF, /* 38-3F */
   4521             L,    AL,    AL,    AL,    AL,    AL,    AL,     R, /* 40-47 */
   4522             R,     R,     R,     R,     R,     R,     R,     R, /* 48-4F */
   4523             R,     R,     R,     R,     R,     R,     R,     R, /* 50-57 */
   4524             R,     R,     R,   LRE,   DEF,   RLE,   PDF,     S, /* 58-5F */
   4525           NSM,   DEF,   DEF,   DEF,   DEF,   DEF,   DEF,   DEF, /* 60-67 */
   4526           DEF,   DEF,   DEF,   DEF,   DEF,   DEF,   DEF,   DEF, /* 68-6F */
   4527           DEF,   DEF,   DEF,   DEF,   DEF,   DEF,   DEF,   DEF, /* 70-77 */
   4528           DEF,   DEF,   DEF,   LRO,     B,   RLO,    BN,   DEF  /* 78-7F */
   4529     };
   4530     static const int nEntries = UPRV_LENGTHOF(customClasses);
   4531     const char *dummy = context;        /* just to avoid a compiler warning */
   4532     dummy++;
   4533 
   4534     return c >= nEntries ? U_BIDI_CLASS_DEFAULT : customClasses[c];
   4535 }
   4536 
   4537 U_CDECL_END
   4538 
   4539 static void verifyCallbackParams(UBiDiClassCallback* fn, const void* context,
   4540                                  UBiDiClassCallback* expectedFn,
   4541                                  const void* expectedContext,
   4542                                  int32_t sizeOfContext) {
   4543     if (fn != expectedFn) {
   4544         log_err("Class callback pointer is not set properly.\n");
   4545     }
   4546     if (context != expectedContext) {
   4547         log_err("Class callback context is not set properly.\n");
   4548     }
   4549     else if (context != NULL &&
   4550             memcmp(context, expectedContext, sizeOfContext)) {
   4551         log_err("Callback context content doesn't match the expected one.\n");
   4552     }
   4553 }
   4554 
   4555 static void
   4556 testClassOverride(void) {
   4557     static const char* const textSrc  = "JIH.>12->a \\u05D0\\u05D1 6 ABC78";
   4558     static const char* const textResult = "12<.HIJ->a 78CBA 6 \\u05D1\\u05D0";
   4559 
   4560     UChar src[MAXLEN], dest[MAXLEN];
   4561     UErrorCode rc = U_ZERO_ERROR;
   4562     UBiDi *pBiDi = NULL;
   4563     UBiDiClassCallback* oldFn = NULL;
   4564     UBiDiClassCallback* newFn = overrideBidiClass;
   4565     const void* oldContext = NULL;
   4566     int32_t srcLen, destLen, textSrcSize = (int32_t)uprv_strlen(textSrc);
   4567     char* destChars = NULL;
   4568 
   4569     log_verbose("\nEntering TestClassOverride\n\n");
   4570 
   4571     pBiDi = getBiDiObject();
   4572     if(!pBiDi) {
   4573         return;
   4574     }
   4575 
   4576     ubidi_getClassCallback(pBiDi, &oldFn, &oldContext);
   4577     verifyCallbackParams(oldFn, oldContext, NULL, NULL, 0);
   4578 
   4579     ubidi_setClassCallback(pBiDi, newFn, textSrc, &oldFn, &oldContext, &rc);
   4580     if (!assertSuccessful("ubidi_setClassCallback", &rc)) {
   4581         ubidi_close(pBiDi);
   4582         return;
   4583     }
   4584     verifyCallbackParams(oldFn, oldContext, NULL, NULL, 0);
   4585 
   4586     ubidi_getClassCallback(pBiDi, &oldFn, &oldContext);
   4587     verifyCallbackParams(oldFn, oldContext, newFn, textSrc, textSrcSize);
   4588 
   4589     ubidi_setClassCallback(pBiDi, newFn, textSrc, &oldFn, &oldContext, &rc);
   4590     if (!assertSuccessful("ubidi_setClassCallback", &rc)) {
   4591         ubidi_close(pBiDi);
   4592         return;
   4593     }
   4594     verifyCallbackParams(oldFn, oldContext, newFn, textSrc, textSrcSize);
   4595 
   4596     srcLen = u_unescape(textSrc, src, MAXLEN);
   4597     ubidi_setPara(pBiDi, src, srcLen, UBIDI_LTR, NULL, &rc);
   4598     assertSuccessful("ubidi_setPara", &rc);
   4599 
   4600     destLen = ubidi_writeReordered(pBiDi, dest, MAXLEN,
   4601                                    UBIDI_DO_MIRRORING, &rc);
   4602     assertSuccessful("ubidi_writeReordered", &rc);
   4603 
   4604     destChars = aescstrdup(dest, destLen);
   4605     if (uprv_strcmp(textResult, destChars)) {
   4606         log_err("\nActual and expected output mismatch.\n"
   4607             "%20s %s\n%20s %s\n%20s %s\n",
   4608             "Input:", textSrc, "Actual output:", destChars,
   4609             "Expected output:", textResult);
   4610     }
   4611     else {
   4612         log_verbose("\nClass override test OK\n");
   4613     }
   4614     ubidi_close(pBiDi);
   4615     log_verbose("\nExiting TestClassOverride\n\n");
   4616 }
   4617 
   4618 static char * formatMap(const int32_t * map, int len, char * buffer)
   4619 {
   4620     int32_t i, k;
   4621     char c;
   4622     for (i = 0; i < len; i++) {
   4623         k = map[i];
   4624         if (k < 0)
   4625             c = '-';
   4626         else if (k >= sizeof(columns))
   4627             c = '+';
   4628         else
   4629             c = columns[k];
   4630         buffer[i] = c;
   4631     }
   4632     buffer[len] = '\0';
   4633     return buffer;
   4634 }
   4635 
   4636 static UBool
   4637 checkMaps(UBiDi *pBiDi, int32_t stringIndex, const char *src, const char *dest,
   4638           const char *mode, const char* option, UBiDiLevel level, UBool forward)
   4639 {
   4640     int32_t actualLogicalMap[MAX_MAP_LENGTH];
   4641     int32_t actualVisualMap[MAX_MAP_LENGTH];
   4642     int32_t getIndexMap[MAX_MAP_LENGTH];
   4643     int32_t i, srcLen, resLen, idx;
   4644     const int32_t *expectedLogicalMap, *expectedVisualMap;
   4645     UErrorCode rc = U_ZERO_ERROR;
   4646     UBool testOK = TRUE;
   4647 
   4648     if (forward) {
   4649         expectedLogicalMap = forwardMap[stringIndex];
   4650         expectedVisualMap  = inverseMap[stringIndex];
   4651     }
   4652     else {
   4653         expectedLogicalMap = inverseMap[stringIndex];
   4654         expectedVisualMap  = forwardMap[stringIndex];
   4655     }
   4656     ubidi_getLogicalMap(pBiDi, actualLogicalMap, &rc);
   4657     if (!assertSuccessful("ubidi_getLogicalMap", &rc)) {
   4658         testOK = FALSE;
   4659     }
   4660     srcLen = ubidi_getProcessedLength(pBiDi);
   4661     if (memcmp(expectedLogicalMap, actualLogicalMap, srcLen * sizeof(int32_t))) {
   4662         char expChars[MAX_MAP_LENGTH];
   4663         char actChars[MAX_MAP_LENGTH];
   4664         log_err("\nubidi_getLogicalMap() returns unexpected map for output string "
   4665                 "index %d\n"
   4666                 "source: %s\n"
   4667                 "dest  : %s\n"
   4668                 "Scale : %s\n"
   4669                 "ExpMap: %s\n"
   4670                 "Actual: %s\n"
   4671                 "Paragraph level  : %d == %d\n"
   4672                 "Reordering mode  : %s == %d\n"
   4673                 "Reordering option: %s == %d\n"
   4674                 "Forward flag     : %d\n",
   4675                 stringIndex, src, dest, columns,
   4676                 formatMap(expectedLogicalMap, srcLen, expChars),
   4677                 formatMap(actualLogicalMap, srcLen, actChars),
   4678                 level, ubidi_getParaLevel(pBiDi),
   4679                 mode, ubidi_getReorderingMode(pBiDi),
   4680                 option, ubidi_getReorderingOptions(pBiDi),
   4681                 forward
   4682                 );
   4683         testOK = FALSE;
   4684     }
   4685     resLen = ubidi_getResultLength(pBiDi);
   4686     ubidi_getVisualMap(pBiDi, actualVisualMap, &rc);
   4687     assertSuccessful("ubidi_getVisualMap", &rc);
   4688     if (memcmp(expectedVisualMap, actualVisualMap, resLen * sizeof(int32_t))) {
   4689         char expChars[MAX_MAP_LENGTH];
   4690         char actChars[MAX_MAP_LENGTH];
   4691         log_err("\nubidi_getVisualMap() returns unexpected map for output string "
   4692                 "index %d\n"
   4693                 "source: %s\n"
   4694                 "dest  : %s\n"
   4695                 "Scale : %s\n"
   4696                 "ExpMap: %s\n"
   4697                 "Actual: %s\n"
   4698                 "Paragraph level  : %d == %d\n"
   4699                 "Reordering mode  : %s == %d\n"
   4700                 "Reordering option: %s == %d\n"
   4701                 "Forward flag     : %d\n",
   4702                 stringIndex, src, dest, columns,
   4703                 formatMap(expectedVisualMap, resLen, expChars),
   4704                 formatMap(actualVisualMap, resLen, actChars),
   4705                 level, ubidi_getParaLevel(pBiDi),
   4706                 mode, ubidi_getReorderingMode(pBiDi),
   4707                 option, ubidi_getReorderingOptions(pBiDi),
   4708                 forward
   4709                 );
   4710         testOK = FALSE;
   4711     }
   4712     for (i = 0; i < srcLen; i++) {
   4713         idx = ubidi_getVisualIndex(pBiDi, i, &rc);
   4714         assertSuccessful("ubidi_getVisualIndex", &rc);
   4715         getIndexMap[i] = idx;
   4716     }
   4717     if (memcmp(actualLogicalMap, getIndexMap, srcLen * sizeof(int32_t))) {
   4718         char actChars[MAX_MAP_LENGTH];
   4719         char gotChars[MAX_MAP_LENGTH];
   4720         log_err("\nMismatch between ubidi_getLogicalMap and ubidi_getVisualIndex for output string "
   4721                 "index %d\n"
   4722                 "source: %s\n"
   4723                 "dest  : %s\n"
   4724                 "Scale : %s\n"
   4725                 "ActMap: %s\n"
   4726                 "IdxMap: %s\n"
   4727                 "Paragraph level  : %d == %d\n"
   4728                 "Reordering mode  : %s == %d\n"
   4729                 "Reordering option: %s == %d\n"
   4730                 "Forward flag     : %d\n",
   4731                 stringIndex, src, dest, columns,
   4732                 formatMap(actualLogicalMap, srcLen, actChars),
   4733                 formatMap(getIndexMap, srcLen, gotChars),
   4734                 level, ubidi_getParaLevel(pBiDi),
   4735                 mode, ubidi_getReorderingMode(pBiDi),
   4736                 option, ubidi_getReorderingOptions(pBiDi),
   4737                 forward
   4738                 );
   4739         testOK = FALSE;
   4740     }
   4741     for (i = 0; i < resLen; i++) {
   4742         idx = ubidi_getLogicalIndex(pBiDi, i, &rc);
   4743         assertSuccessful("ubidi_getLogicalIndex", &rc);
   4744         getIndexMap[i] = idx;
   4745     }
   4746     if (memcmp(actualVisualMap, getIndexMap, resLen * sizeof(int32_t))) {
   4747         char actChars[MAX_MAP_LENGTH];
   4748         char gotChars[MAX_MAP_LENGTH];
   4749         log_err("\nMismatch between ubidi_getVisualMap and ubidi_getLogicalIndex for output string "
   4750                 "index %d\n"
   4751                 "source: %s\n"
   4752                 "dest  : %s\n"
   4753                 "Scale : %s\n"
   4754                 "ActMap: %s\n"
   4755                 "IdxMap: %s\n"
   4756                 "Paragraph level  : %d == %d\n"
   4757                 "Reordering mode  : %s == %d\n"
   4758                 "Reordering option: %s == %d\n"
   4759                 "Forward flag     : %d\n",
   4760                 stringIndex, src, dest, columns,
   4761                 formatMap(actualVisualMap, resLen, actChars),
   4762                 formatMap(getIndexMap, resLen, gotChars),
   4763                 level, ubidi_getParaLevel(pBiDi),
   4764                 mode, ubidi_getReorderingMode(pBiDi),
   4765                 option, ubidi_getReorderingOptions(pBiDi),
   4766                 forward
   4767                 );
   4768         testOK = FALSE;
   4769     }
   4770     return testOK;
   4771 }
   4772 
   4773 static UBool
   4774 assertIllegalArgument(const char* message, UErrorCode* rc) {
   4775     if (*rc != U_ILLEGAL_ARGUMENT_ERROR) {
   4776         log_err("%s() failed with error %s.\n", message, myErrorName(*rc));
   4777         return FALSE;
   4778     }
   4779     return TRUE;
   4780 }
   4781 
   4782 typedef struct {
   4783     const char* prologue;
   4784     const char* source;
   4785     const char* epilogue;
   4786     const char* expected;
   4787     UBiDiLevel paraLevel;
   4788 } contextCase;
   4789 
   4790 static const contextCase contextData[] = {
   4791     /*00*/  {"", "", "", "", UBIDI_LTR},
   4792     /*01*/  {"", ".-=JKL-+*", "", ".-=LKJ-+*", UBIDI_LTR},
   4793     /*02*/  {" ", ".-=JKL-+*", " ", ".-=LKJ-+*", UBIDI_LTR},
   4794     /*03*/  {"a", ".-=JKL-+*", "b", ".-=LKJ-+*", UBIDI_LTR},
   4795     /*04*/  {"D", ".-=JKL-+*", "", "LKJ=-.-+*", UBIDI_LTR},
   4796     /*05*/  {"", ".-=JKL-+*", " D", ".-=*+-LKJ", UBIDI_LTR},
   4797     /*06*/  {"", ".-=JKL-+*", " 2", ".-=*+-LKJ", UBIDI_LTR},
   4798     /*07*/  {"", ".-=JKL-+*", " 7", ".-=*+-LKJ", UBIDI_LTR},
   4799     /*08*/  {" G 1", ".-=JKL-+*", " H", "*+-LKJ=-.", UBIDI_LTR},
   4800     /*09*/  {"7", ".-=JKL-+*", " H", ".-=*+-LKJ", UBIDI_LTR},
   4801     /*10*/  {"", ".-=abc-+*", "", "*+-abc=-.", UBIDI_RTL},
   4802     /*11*/  {" ", ".-=abc-+*", " ", "*+-abc=-.", UBIDI_RTL},
   4803     /*12*/  {"D", ".-=abc-+*", "G", "*+-abc=-.", UBIDI_RTL},
   4804     /*13*/  {"x", ".-=abc-+*", "", "*+-.-=abc", UBIDI_RTL},
   4805     /*14*/  {"", ".-=abc-+*", " y", "abc-+*=-.", UBIDI_RTL},
   4806     /*15*/  {"", ".-=abc-+*", " 2", "abc-+*=-.", UBIDI_RTL},
   4807     /*16*/  {" x 1", ".-=abc-+*", " 2", ".-=abc-+*", UBIDI_RTL},
   4808     /*17*/  {" x 7", ".-=abc-+*", " 8", "*+-.-=abc", UBIDI_RTL},
   4809     /*18*/  {"x|", ".-=abc-+*", " 8", "*+-abc=-.", UBIDI_RTL},
   4810     /*19*/  {"G|y", ".-=abc-+*", " 8", "*+-.-=abc", UBIDI_RTL},
   4811     /*20*/  {"", ".-=", "", ".-=", UBIDI_DEFAULT_LTR},
   4812     /*21*/  {"D", ".-=", "", "=-.", UBIDI_DEFAULT_LTR},
   4813     /*22*/  {"G", ".-=", "", "=-.", UBIDI_DEFAULT_LTR},
   4814     /*23*/  {"xG", ".-=", "", ".-=", UBIDI_DEFAULT_LTR},
   4815     /*24*/  {"x|G", ".-=", "", "=-.", UBIDI_DEFAULT_LTR},
   4816     /*25*/  {"x|G", ".-=|-+*", "", "=-.|-+*", UBIDI_DEFAULT_LTR},
   4817 };
   4818 #define CONTEXT_COUNT       UPRV_LENGTHOF(contextData)
   4819 
   4820 static void
   4821 testContext(void) {
   4822 
   4823     UChar prologue[MAXLEN], epilogue[MAXLEN], src[MAXLEN], dest[MAXLEN];
   4824     char destChars[MAXLEN];
   4825     UBiDi *pBiDi = NULL;
   4826     UErrorCode rc;
   4827     int32_t proLength, epiLength, srcLen, destLen, tc;
   4828     contextCase cc;
   4829     UBool testOK = TRUE;
   4830 
   4831     log_verbose("\nEntering TestContext \n\n");
   4832 
   4833     /* test null BiDi object */
   4834     rc = U_ZERO_ERROR;
   4835     ubidi_setContext(pBiDi, NULL, 0, NULL, 0, &rc);
   4836     testOK &= assertIllegalArgument("Error when BiDi object is null", &rc);
   4837 
   4838     pBiDi = getBiDiObject();
   4839     ubidi_orderParagraphsLTR(pBiDi, TRUE);
   4840 
   4841     /* test proLength < -1 */
   4842     rc = U_ZERO_ERROR;
   4843     ubidi_setContext(pBiDi, NULL, -2, NULL, 0, &rc);
   4844     testOK &= assertIllegalArgument("Error when proLength < -1", &rc);
   4845     /* test epiLength < -1 */
   4846     rc = U_ZERO_ERROR;
   4847     ubidi_setContext(pBiDi, NULL, 0, NULL, -2, &rc);
   4848     testOK &= assertIllegalArgument("Error when epiLength < -1", &rc);
   4849     /* test prologue == NULL */
   4850     rc = U_ZERO_ERROR;
   4851     ubidi_setContext(pBiDi, NULL, 3, NULL, 0, &rc);
   4852     testOK &= assertIllegalArgument("Prologue is NULL", &rc);
   4853     /* test epilogue == NULL */
   4854     rc = U_ZERO_ERROR;
   4855     ubidi_setContext(pBiDi, NULL, 0, NULL, 4, &rc);
   4856     testOK &= assertIllegalArgument("Epilogue is NULL", &rc);
   4857 
   4858     for (tc = 0; tc < CONTEXT_COUNT; tc++) {
   4859         cc = contextData[tc];
   4860         proLength = strlen(cc.prologue);
   4861         pseudoToU16(proLength, cc.prologue, prologue);
   4862         epiLength = strlen(cc.epilogue);
   4863         pseudoToU16(epiLength, cc.epilogue, epilogue);
   4864         /* in the call below, prologue and epilogue are swapped to show
   4865            that the next call will override this call */
   4866         rc = U_ZERO_ERROR;
   4867         ubidi_setContext(pBiDi, epilogue, epiLength, prologue, proLength, &rc);
   4868         testOK &= assertSuccessful("swapped ubidi_setContext", &rc);
   4869         ubidi_setContext(pBiDi, prologue, -1, epilogue, -1, &rc);
   4870         testOK &= assertSuccessful("regular ubidi_setContext", &rc);
   4871         srcLen = strlen(cc.source);
   4872         pseudoToU16(srcLen, cc.source, src);
   4873         ubidi_setPara(pBiDi, src, srcLen, cc.paraLevel, NULL, &rc);
   4874         testOK &= assertSuccessful("ubidi_setPara", &rc);
   4875         destLen = ubidi_writeReordered(pBiDi, dest, MAXLEN, UBIDI_DO_MIRRORING, &rc);
   4876         assertSuccessful("ubidi_writeReordered", &rc);
   4877         u16ToPseudo(destLen, dest, destChars);
   4878         if (uprv_strcmp(cc.expected, destChars)) {
   4879             char formatChars[MAXLEN];
   4880             log_err("\nActual and expected output mismatch on case %d.\n"
   4881                 "%20s %s\n%20s %s\n%20s %s\n%20s %s\n%20s %s\n%20s %s\n%20s %d\n%20s %u\n%20s %d\n",
   4882                 tc,
   4883                 "Prologue:", cc.prologue,
   4884                 "Input:", cc.source,
   4885                 "Epilogue:", cc.epilogue,
   4886                 "Expected output:", cc.expected,
   4887                 "Actual output:", destChars,
   4888                 "Levels:", formatLevels(pBiDi, formatChars),
   4889                 "Reordering mode:", ubidi_getReorderingMode(pBiDi),
   4890                 "Paragraph level:", ubidi_getParaLevel(pBiDi),
   4891                 "Reordering option:", ubidi_getReorderingOptions(pBiDi));
   4892             testOK = FALSE;
   4893         }
   4894     }
   4895     if (testOK == TRUE) {
   4896         log_verbose("\nContext test OK\n");
   4897     }
   4898     ubidi_close(pBiDi);
   4899 
   4900     log_verbose("\nExiting TestContext \n\n");
   4901 }
   4902 
   4903 /* Ticket#11054 ubidi_setPara crash with heavily nested brackets */
   4904 static void
   4905 testBracketOverflow(void) {
   4906     static const char* TEXT = "(((((((((((((((((((((((((((((((((((((((((a)(A)))))))))))))))))))))))))))))))))))))))))";
   4907     UErrorCode status = U_ZERO_ERROR;
   4908     UBiDi* bidi;
   4909     UChar src[100];
   4910     int32_t len;
   4911 
   4912     bidi = ubidi_open();
   4913     len = uprv_strlen(TEXT);
   4914     pseudoToU16(len, TEXT, src);
   4915     ubidi_setPara(bidi, src, len, UBIDI_DEFAULT_LTR , NULL, &status);
   4916     if (U_FAILURE(status)) {
   4917         log_err("setPara failed with heavily nested brackets - %s", u_errorName(status));
   4918     }
   4919 
   4920     ubidi_close(bidi);
   4921 }
   4922 
   4923