Home | History | Annotate | Download | only in cintltst
      1 /********************************************************************
      2  * COPYRIGHT:
      3  * Copyright (c) 1997-2008, International Business Machines Corporation and
      4  * others. All Rights Reserved.
      5  ********************************************************************/
      6 /*   file name:  cbiditst.cpp
      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 #define LENGTHOF(array) (sizeof(array)/sizeof((array)[0]))
     28 
     29 /* prototypes ---------------------------------------------------------------*/
     30 
     31 void addComplexTest(TestNode** root);
     32 
     33 static void testCharFromDirProp(void);
     34 
     35 static void testBidi(void);
     36 
     37 static void doTests(UBiDi *pBiDi, UBiDi *pLine, UBool countRunsFirst);
     38 
     39 static void doMisc(void);
     40 
     41 static void doTest(UBiDi *pBiDi, int testNumber, const BiDiTestData *test,
     42                    int32_t lineStart, UBool countRunsFirst);
     43 
     44 static void _testReordering(UBiDi *pBiDi, int testNumber);
     45 
     46 static void testInverse(void);
     47 
     48 static void _testManyInverseBidi(UBiDi *pBiDi, UBiDiLevel direction);
     49 
     50 static void _testInverseBidi(UBiDi *pBiDi, const UChar *src, int32_t srcLength,
     51                              UBiDiLevel direction, UErrorCode *pErrorCode);
     52 
     53 static void _testWriteReverse(void);
     54 
     55 static void _testManyAddedPoints(void);
     56 
     57 static void _testMisc(void);
     58 
     59 static void doArabicShapingTest(void);
     60 
     61 static void doLamAlefSpecialVLTRArabicShapingTest(void);
     62 
     63 static void doTashkeelSpecialVLTRArabicShapingTest(void);
     64 
     65 static void doLOGICALArabicDeShapingTest(void);
     66 
     67 static void doArabicShapingTestForBug5421(void);
     68 
     69 static void testReorder(void);
     70 
     71 static void testFailureRecovery(void);
     72 
     73 static void testMultipleParagraphs(void);
     74 
     75 /* new BIDI API */
     76 static void testReorderingMode(void);
     77 static void testReorderRunsOnly(void);
     78 static void testStreaming(void);
     79 static void testClassOverride(void);
     80 static const char* inverseBasic(UBiDi *pBiDi, const char *src, int32_t srcLen,
     81                                 uint32_t option, UBiDiLevel level, char *result);
     82 static UBool assertRoundTrip(UBiDi *pBiDi, int32_t tc, int32_t outIndex,
     83                              const char *srcChars, const char *destChars,
     84                              const UChar *dest, int32_t destLen, int mode,
     85                              int option, UBiDiLevel level);
     86 static UBool checkResultLength(UBiDi *pBiDi, const char *srcChars,
     87                                const char *destChars,
     88                                int32_t destLen, const char *mode,
     89                                const char *option, UBiDiLevel level);
     90 static UBool checkMaps(UBiDi *pBiDi, int32_t stringIndex, const char *src,
     91                        const char *dest, const char *mode, const char* option,
     92                        UBiDiLevel level, UBool forward);
     93 
     94 /* helpers ------------------------------------------------------------------ */
     95 
     96 static const char *levelString="...............................................................";
     97 
     98 static void initCharFromDirProps(void);
     99 
    100 static UChar *
    101 getStringFromDirProps(const uint8_t *dirProps, int32_t length, UChar *buffer);
    102 
    103 static void printUnicode(const UChar *s, int32_t length, const UBiDiLevel *levels);
    104 
    105 /* regression tests ---------------------------------------------------------*/
    106 
    107 void
    108 addComplexTest(TestNode** root) {
    109     addTest(root, testCharFromDirProp, "complex/bidi/TestCharFromDirProp");
    110     addTest(root, testBidi, "complex/bidi/TestBidi");
    111     addTest(root, testInverse, "complex/bidi/TestInverse");
    112     addTest(root, testReorder,"complex/bidi/TestReorder");
    113     addTest(root, testFailureRecovery,"complex/bidi/TestFailureRecovery");
    114     addTest(root, testMultipleParagraphs,"complex/bidi/TestMultipleParagraphs");
    115     addTest(root, testReorderingMode, "complex/bidi/TestReorderingMode");
    116     addTest(root, testReorderRunsOnly, "complex/bidi/TestReorderRunsOnly");
    117     addTest(root, testStreaming, "complex/bidi/TestStreaming");
    118     addTest(root, testClassOverride, "complex/bidi/TestClassOverride");
    119 
    120     addTest(root, doArabicShapingTest, "complex/arabic-shaping/ArabicShapingTest");
    121     addTest(root, doLamAlefSpecialVLTRArabicShapingTest, "complex/arabic-shaping/lamalef");
    122     addTest(root, doTashkeelSpecialVLTRArabicShapingTest, "complex/arabic-shaping/tashkeel");
    123     addTest(root, doLOGICALArabicDeShapingTest, "complex/arabic-shaping/unshaping");
    124     addTest(root, doArabicShapingTestForBug5421, "complex/arabic-shaping/bug-5421");
    125 }
    126 
    127 static void
    128 testCharFromDirProp(void) {
    129     /* verify that the exemplar characters have the expected bidi classes */
    130     int32_t i;
    131 
    132     log_verbose("\nEntering TestCharFromDirProp\n\n");
    133     initCharFromDirProps();
    134 
    135     for(i=0; i<U_CHAR_DIRECTION_COUNT; ++i) {
    136         if(u_charDirection(charFromDirProp[i])!=(UCharDirection)i) {
    137             log_err("\nu_charDirection(charFromDirProp[%d]=U+%04x)==%d!=%d\n",
    138                     i, charFromDirProp[i], u_charDirection(charFromDirProp[i]), i);
    139         }
    140     }
    141     log_verbose("\nExiting TestCharFromDirProp\n\n");
    142 }
    143 
    144 static void
    145 testBidi(void) {
    146     UBiDi *pBiDi, *pLine=NULL;
    147     UErrorCode errorCode=U_ZERO_ERROR;
    148 
    149     log_verbose("\nEntering TestBidi\n\n");
    150 
    151     pBiDi=ubidi_openSized(MAXLEN, 0, &errorCode);
    152     if(pBiDi!=NULL) {
    153         pLine=ubidi_open();
    154         if(pLine!=NULL) {
    155             doTests(pBiDi, pLine, FALSE);
    156             doTests(pBiDi, pLine, TRUE);
    157         } else {
    158             log_err("ubidi_open() returned NULL, out of memory\n");
    159         }
    160     } else {
    161         log_err("ubidi_openSized() returned NULL, errorCode %s\n", myErrorName(errorCode));
    162     }
    163     doMisc();
    164 
    165     if(pLine!=NULL) {
    166         ubidi_close(pLine);
    167     }
    168     if(pBiDi!=NULL) {
    169         ubidi_close(pBiDi);
    170     }
    171 
    172     log_verbose("\nExiting TestBidi\n\n");
    173 }
    174 
    175 static void
    176 doTests(UBiDi *pBiDi, UBiDi *pLine, UBool countRunsFirst) {
    177     int testNumber;
    178     UChar string[MAXLEN];
    179     UErrorCode errorCode;
    180     int32_t lineStart;
    181     UBiDiLevel paraLevel;
    182 
    183     for(testNumber=0; testNumber<bidiTestCount; ++testNumber) {
    184         errorCode=U_ZERO_ERROR;
    185         getStringFromDirProps(tests[testNumber].text, tests[testNumber].length, string);
    186         paraLevel=tests[testNumber].paraLevel;
    187         ubidi_setPara(pBiDi, string, -1, paraLevel, NULL, &errorCode);
    188         if(U_SUCCESS(errorCode)) {
    189             log_verbose("ubidi_setPara(tests[%d], paraLevel %d) ok, direction %d paraLevel=%d\n",
    190                     testNumber, paraLevel, ubidi_getDirection(pBiDi), paraLevel);
    191             lineStart=tests[testNumber].lineStart;
    192             if(lineStart==-1) {
    193                 doTest(pBiDi, testNumber, tests+testNumber, 0, countRunsFirst);
    194             } else {
    195                 ubidi_setLine(pBiDi, lineStart, tests[testNumber].lineLimit, pLine, &errorCode);
    196                 if(U_SUCCESS(errorCode)) {
    197                     log_verbose("ubidi_setLine(%d, %d) ok, direction %d paraLevel=%d\n",
    198                             lineStart, tests[testNumber].lineLimit, ubidi_getDirection(pLine), ubidi_getParaLevel(pLine));
    199                     doTest(pLine, testNumber, tests+testNumber, lineStart, countRunsFirst);
    200                 } else {
    201                     log_err("ubidi_setLine(tests[%d], %d, %d) failed with errorCode %s\n",
    202                             testNumber, lineStart, tests[testNumber].lineLimit, myErrorName(errorCode));
    203                 }
    204             }
    205         } else {
    206             log_err("ubidi_setPara(tests[%d], paraLevel %d) failed with errorCode %s\n",
    207                     testNumber, paraLevel, myErrorName(errorCode));
    208         }
    209     }
    210 }
    211 
    212 static const char columns[] = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz";
    213 
    214 #define TABLE_SIZE  256
    215 static UBool   tablesInitialized = FALSE;
    216 static UChar   pseudoToUChar[TABLE_SIZE];
    217 static uint8_t UCharToPseudo[TABLE_SIZE];    /* used for Unicode chars < 0x0100 */
    218 static uint8_t UCharToPseud2[TABLE_SIZE];    /* used for Unicode chars >=0x0100 */
    219 
    220 static void buildPseudoTables(void)
    221 /*
    222     The rules for pseudo-Bidi are as follows:
    223     - [ == LRE
    224     - ] == RLE
    225     - { == LRO
    226     - } == RLO
    227     - ^ == PDF
    228     - @ == LRM
    229     - & == RLM
    230     - A-F == Arabic Letters 0631-0636
    231     - G-V == Hebrew letters 05d7-05e6
    232     - W-Z == Unassigned RTL 08d0-08d3
    233     - 0-5 == western digits 0030-0035
    234     - 6-9 == Arabic-Indic digits 0666-0669
    235     - ` == Combining Grave Accent 0300 (NSM)
    236     - ~ == Delete 007f (BN)
    237     - | == Paragraph Separator 2029 (B)
    238     - _ == Info Separator 1 001f (S)
    239     All other characters represent themselves as Latin-1, with the corresponding
    240     Bidi properties.
    241 */
    242 {
    243     int             i;
    244     UChar           uchar;
    245     uint8_t         c;
    246     /* initialize all tables to unknown */
    247     for (i=0; i < TABLE_SIZE; i++) {
    248         pseudoToUChar[i] = 0xFFFD;
    249         UCharToPseudo[i] = '?';
    250         UCharToPseud2[i] = '?';
    251     }
    252     /* initialize non letters or digits */
    253     pseudoToUChar[(uint8_t) 0 ] = 0x0000;    UCharToPseudo[0x00] = (uint8_t) 0 ;
    254     pseudoToUChar[(uint8_t)' '] = 0x0020;    UCharToPseudo[0x20] = (uint8_t)' ';
    255     pseudoToUChar[(uint8_t)'!'] = 0x0021;    UCharToPseudo[0x21] = (uint8_t)'!';
    256     pseudoToUChar[(uint8_t)'"'] = 0x0022;    UCharToPseudo[0x22] = (uint8_t)'"';
    257     pseudoToUChar[(uint8_t)'#'] = 0x0023;    UCharToPseudo[0x23] = (uint8_t)'#';
    258     pseudoToUChar[(uint8_t)'$'] = 0x0024;    UCharToPseudo[0x24] = (uint8_t)'$';
    259     pseudoToUChar[(uint8_t)'%'] = 0x0025;    UCharToPseudo[0x25] = (uint8_t)'%';
    260     pseudoToUChar[(uint8_t)'\'']= 0x0027;    UCharToPseudo[0x27] = (uint8_t)'\'';
    261     pseudoToUChar[(uint8_t)'('] = 0x0028;    UCharToPseudo[0x28] = (uint8_t)'(';
    262     pseudoToUChar[(uint8_t)')'] = 0x0029;    UCharToPseudo[0x29] = (uint8_t)')';
    263     pseudoToUChar[(uint8_t)'*'] = 0x002A;    UCharToPseudo[0x2A] = (uint8_t)'*';
    264     pseudoToUChar[(uint8_t)'+'] = 0x002B;    UCharToPseudo[0x2B] = (uint8_t)'+';
    265     pseudoToUChar[(uint8_t)','] = 0x002C;    UCharToPseudo[0x2C] = (uint8_t)',';
    266     pseudoToUChar[(uint8_t)'-'] = 0x002D;    UCharToPseudo[0x2D] = (uint8_t)'-';
    267     pseudoToUChar[(uint8_t)'.'] = 0x002E;    UCharToPseudo[0x2E] = (uint8_t)'.';
    268     pseudoToUChar[(uint8_t)'/'] = 0x002F;    UCharToPseudo[0x2F] = (uint8_t)'/';
    269     pseudoToUChar[(uint8_t)':'] = 0x003A;    UCharToPseudo[0x3A] = (uint8_t)':';
    270     pseudoToUChar[(uint8_t)';'] = 0x003B;    UCharToPseudo[0x3B] = (uint8_t)';';
    271     pseudoToUChar[(uint8_t)'<'] = 0x003C;    UCharToPseudo[0x3C] = (uint8_t)'<';
    272     pseudoToUChar[(uint8_t)'='] = 0x003D;    UCharToPseudo[0x3D] = (uint8_t)'=';
    273     pseudoToUChar[(uint8_t)'>'] = 0x003E;    UCharToPseudo[0x3E] = (uint8_t)'>';
    274     pseudoToUChar[(uint8_t)'?'] = 0x003F;    UCharToPseudo[0x3F] = (uint8_t)'?';
    275     pseudoToUChar[(uint8_t)'\\']= 0x005C;    UCharToPseudo[0x5C] = (uint8_t)'\\';
    276     /* initialize specially used characters */
    277     pseudoToUChar[(uint8_t)'`'] = 0x0300;    UCharToPseud2[0x00] = (uint8_t)'`';  /* NSM */
    278     pseudoToUChar[(uint8_t)'@'] = 0x200E;    UCharToPseud2[0x0E] = (uint8_t)'@';  /* LRM */
    279     pseudoToUChar[(uint8_t)'&'] = 0x200F;    UCharToPseud2[0x0F] = (uint8_t)'&';  /* RLM */
    280     pseudoToUChar[(uint8_t)'_'] = 0x001F;    UCharToPseudo[0x1F] = (uint8_t)'_';  /* S   */
    281     pseudoToUChar[(uint8_t)'|'] = 0x2029;    UCharToPseud2[0x29] = (uint8_t)'|';  /* B   */
    282     pseudoToUChar[(uint8_t)'['] = 0x202A;    UCharToPseud2[0x2A] = (uint8_t)'[';  /* LRE */
    283     pseudoToUChar[(uint8_t)']'] = 0x202B;    UCharToPseud2[0x2B] = (uint8_t)']';  /* RLE */
    284     pseudoToUChar[(uint8_t)'^'] = 0x202C;    UCharToPseud2[0x2C] = (uint8_t)'^';  /* PDF */
    285     pseudoToUChar[(uint8_t)'{'] = 0x202D;    UCharToPseud2[0x2D] = (uint8_t)'{';  /* LRO */
    286     pseudoToUChar[(uint8_t)'}'] = 0x202E;    UCharToPseud2[0x2E] = (uint8_t)'}';  /* RLO */
    287     pseudoToUChar[(uint8_t)'~'] = 0x007F;    UCharToPseudo[0x7F] = (uint8_t)'~';  /* BN  */
    288     /* initialize western digits */
    289     for (i = 0, uchar = 0x0030; i < 6; i++, uchar++) {
    290         c = (uint8_t)columns[i];
    291         pseudoToUChar[c] = uchar;
    292         UCharToPseudo[uchar & 0x00ff] = c;
    293     }
    294     /* initialize Hindi digits */
    295     for (i = 6, uchar = 0x0666; i < 10; i++, uchar++) {
    296         c = (uint8_t)columns[i];
    297         pseudoToUChar[c] = uchar;
    298         UCharToPseud2[uchar & 0x00ff] = c;
    299     }
    300     /* initialize Arabic letters */
    301     for (i = 10, uchar = 0x0631; i < 16; i++, uchar++) {
    302         c = (uint8_t)columns[i];
    303         pseudoToUChar[c] = uchar;
    304         UCharToPseud2[uchar & 0x00ff] = c;
    305     }
    306     /* initialize Hebrew letters */
    307     for (i = 16, uchar = 0x05D7; i < 32; i++, uchar++) {
    308         c = (uint8_t)columns[i];
    309         pseudoToUChar[c] = uchar;
    310         UCharToPseud2[uchar & 0x00ff] = c;
    311     }
    312     /* initialize Unassigned code points */
    313     for (i = 32, uchar=0x08D0; i < 36; i++, uchar++) {
    314         c = (uint8_t)columns[i];
    315         pseudoToUChar[c] = uchar;
    316         UCharToPseud2[uchar & 0x00ff] = c;
    317     }
    318     /* initialize Latin lower case letters */
    319     for (i = 36, uchar = 0x0061; i < 62; i++, uchar++) {
    320         c = (uint8_t)columns[i];
    321         pseudoToUChar[c] = uchar;
    322         UCharToPseudo[uchar & 0x00ff] = c;
    323     }
    324     tablesInitialized = TRUE;
    325 }
    326 
    327 /*----------------------------------------------------------------------*/
    328 
    329 static int pseudoToU16(const int length, const char * input, UChar * output)
    330 /*  This function converts a pseudo-Bidi string into a UChar string.
    331     It returns the length of the UChar string.
    332 */
    333 {
    334     int             i;
    335     if (!tablesInitialized) {
    336         buildPseudoTables();
    337     }
    338     for (i = 0; i < length; i++)
    339         output[i] = pseudoToUChar[(uint8_t)input[i]];
    340     return length;
    341 }
    342 
    343 /*----------------------------------------------------------------------*/
    344 
    345 static int u16ToPseudo(const int length, const UChar * input, char * output)
    346 /*  This function converts a UChar string into a pseudo-Bidi string.
    347     It returns the length of the pseudo-Bidi string.
    348 */
    349 {
    350     int             i;
    351     UChar           uchar;
    352     if (!tablesInitialized) {
    353         buildPseudoTables();
    354     }
    355     for (i = 0; i < length; i++)
    356     {
    357         uchar = input[i];
    358         output[i] = uchar < 0x0100 ? UCharToPseudo[uchar] :
    359                                         UCharToPseud2[uchar & 0x00ff];
    360     }
    361     output[length] = '\0';
    362     return length;
    363 }
    364 
    365 static char * formatLevels(UBiDi *bidi, char *buffer) {
    366     UErrorCode ec = U_ZERO_ERROR;
    367     const UBiDiLevel* gotLevels = ubidi_getLevels(bidi, &ec);
    368     int len = ubidi_getLength(bidi);
    369     char c;
    370     int i, k;
    371 
    372     if(U_FAILURE(ec)) {
    373         strcpy(buffer, "BAD LEVELS");
    374         return buffer;
    375     }
    376     for (i=0; i<len; i++) {
    377         k = gotLevels[i];
    378         if (k >= sizeof(columns))
    379             c = '+';
    380         else
    381             c = columns[k];
    382         buffer[i] = c;
    383     }
    384     buffer[len] = '\0';
    385     return buffer;
    386 }
    387 static const char *reorderingModeNames[] = {
    388     "UBIDI_REORDER_DEFAULT",
    389     "UBIDI_REORDER_NUMBERS_SPECIAL",
    390     "UBIDI_REORDER_GROUP_NUMBERS_WITH_R",
    391     "UBIDI_REORDER_RUNS_ONLY",
    392     "UBIDI_REORDER_INVERSE_NUMBERS_AS_L",
    393     "UBIDI_REORDER_INVERSE_LIKE_DIRECT",
    394     "UBIDI_REORDER_INVERSE_FOR_NUMBERS_SPECIAL"};
    395 
    396 static char *reorderingOptionNames(char *buffer, int options) {
    397     buffer[0] = 0;
    398     if (options & UBIDI_OPTION_INSERT_MARKS) {
    399         strcat(buffer, " UBIDI_OPTION_INSERT_MARKS");
    400     }
    401     if (options & UBIDI_OPTION_REMOVE_CONTROLS) {
    402         strcat(buffer, " UBIDI_OPTION_REMOVE_CONTROLS");
    403     }
    404     if (options & UBIDI_OPTION_STREAMING) {
    405         strcat(buffer, " UBIDI_OPTION_STREAMING");
    406     }
    407     return buffer;
    408 }
    409 
    410 static void printCaseInfo(UBiDi *bidi, const char *src, const char *dst)
    411 /* src and dst are char arrays encoded as pseudo Bidi */
    412 {
    413     /* Since calls to log_err with a \n within the pattern increment the
    414      * error count, new lines are issued via fputs, except when we want the
    415      * increment to happen.
    416      */
    417     UErrorCode errorCode=U_ZERO_ERROR;
    418     int32_t i, length = ubidi_getProcessedLength(bidi);
    419     const UBiDiLevel *levels;
    420     char levelChars[MAXLEN];
    421     UBiDiLevel lev;
    422     int32_t runCount;
    423     char buffer[100];
    424     log_err("========================================"); fputs("\n", stderr);
    425     levels = ubidi_getLevels(bidi, &errorCode);
    426     if (U_FAILURE(errorCode)) {
    427         strcpy(levelChars, "BAD LEVELS");
    428     } else {
    429         log_err("Processed length: %d", length); fputs("\n", stderr);
    430         for (i = 0; i < length; i++) {
    431             lev = levels[i];
    432             if (lev < sizeof(columns)) {
    433                 levelChars[i] = columns[lev];
    434             } else {
    435                 levelChars[i] = '+';
    436             }
    437         }
    438         levelChars[length] = 0;
    439     }
    440     log_err("Levels: %s", levelChars); fputs("\n", stderr);
    441     log_err("Source: %s", src); fputs("\n", stderr);
    442     log_err("Result: %s", dst); fputs("\n", stderr);
    443     log_err("Direction: %d", ubidi_getDirection(bidi)); fputs("\n", stderr);
    444     log_err("paraLevel: %d", ubidi_getParaLevel(bidi)); fputs("\n", stderr);
    445     i = ubidi_getReorderingMode(bidi);
    446     log_err("reorderingMode: %d = %s", i, reorderingModeNames[i]);
    447     fputs("\n", stderr);
    448     i = ubidi_getReorderingOptions(bidi);
    449     log_err("reorderingOptions: %d = %s", i, reorderingOptionNames(buffer, i));
    450     fputs("\n", stderr);
    451     runCount = ubidi_countRuns(bidi, &errorCode);
    452     if (U_FAILURE(errorCode)) {
    453         log_err( "BAD RUNS");
    454     } else {
    455         log_err("Runs: %d => logicalStart.length/level: ", runCount);
    456         for (i = 0; i < runCount; i++) {
    457             UBiDiDirection dir;
    458             int32_t start, len;
    459             dir = ubidi_getVisualRun(bidi, i, &start, &len);
    460             log_err(" %d.%d/%d", start, len, dir);
    461         }
    462     }
    463     fputs("\n", stderr);
    464 }
    465 
    466 static UBool matchingPair(UBiDi *bidi, int32_t i, char c1, char c2)
    467 {
    468     /* No test for []{} since they have special meaning for pseudo Bidi */
    469     static char mates1Chars[] = "<>()";
    470     static char mates2Chars[] = "><)(";
    471     UBiDiLevel level;
    472     int k, len;
    473 
    474     if (c1 == c2) {
    475         return TRUE;
    476     }
    477     /* For UBIDI_REORDER_RUNS_ONLY, it would not be correct to check levels[i],
    478        so we use the appropriate run's level, which is good for all cases.
    479      */
    480     ubidi_getLogicalRun(bidi, i, NULL, &level);
    481     if ((level & 1) == 0) {
    482         return FALSE;
    483     }
    484     len = strlen(mates1Chars);
    485     for (k = 0; k < len; k++) {
    486         if ((c1 == mates1Chars[k]) && (c2 == mates2Chars[k])) {
    487             return TRUE;
    488         }
    489     }
    490     return FALSE;
    491 }
    492 
    493 static UBool checkWhatYouCan(UBiDi *bidi, const char *srcChars, const char *dstChars)
    494 /* srcChars and dstChars are char arrays encoded as pseudo Bidi */
    495 {
    496     int32_t i, idx, logLimit, visLimit;
    497     UBool testOK, errMap, errDst;
    498     UErrorCode errorCode=U_ZERO_ERROR;
    499     int32_t visMap[MAXLEN];
    500     int32_t logMap[MAXLEN];
    501     char accumSrc[MAXLEN];
    502     char accumDst[MAXLEN];
    503     ubidi_getVisualMap(bidi, visMap, &errorCode);
    504     ubidi_getLogicalMap(bidi, logMap, &errorCode);
    505     if (U_FAILURE(errorCode)) {
    506         log_err("Error #1 invoking ICU within checkWhatYouCan\n");
    507         return FALSE;
    508     }
    509 
    510     testOK = TRUE;
    511     errMap = errDst = FALSE;
    512     logLimit = ubidi_getProcessedLength(bidi);
    513     visLimit = ubidi_getResultLength(bidi);
    514     memset(accumSrc, '?', logLimit);
    515     memset(accumDst, '?', visLimit);
    516 
    517     for (i = 0; i < logLimit; i++) {
    518         idx = ubidi_getVisualIndex(bidi, i, &errorCode);
    519         if (idx != logMap[i]) {
    520             errMap = TRUE;
    521         }
    522         if (idx == UBIDI_MAP_NOWHERE) {
    523             continue;
    524         }
    525         if (idx >= visLimit) {
    526             continue;
    527         }
    528         accumDst[idx] = srcChars[i];
    529         if (!matchingPair(bidi, i, srcChars[i], dstChars[idx])) {
    530             errDst = TRUE;
    531         }
    532     }
    533     accumDst[visLimit] = 0;
    534     if (U_FAILURE(errorCode)) {
    535         log_err("Error #2 invoking ICU within checkWhatYouCan\n");
    536         return FALSE;
    537     }
    538     if (errMap) {
    539         if (testOK) {
    540             printCaseInfo(bidi, srcChars, dstChars);
    541             testOK = FALSE;
    542         }
    543         log_err("Mismatch between getLogicalMap() and getVisualIndex()\n");
    544         log_err("Map    :");
    545         for (i = 0; i < logLimit; i++) {
    546             log_err(" %d", logMap[i]);
    547         }
    548         fputs("\n", stderr);
    549         log_err("Indexes:");
    550         for (i = 0; i < logLimit; i++) {
    551             log_err(" %d", ubidi_getVisualIndex(bidi, i, &errorCode));
    552         }
    553         fputs("\n", stderr);
    554     }
    555     if (errDst) {
    556         if (testOK) {
    557             printCaseInfo(bidi, srcChars, dstChars);
    558             testOK = FALSE;
    559         }
    560         log_err("Source does not map to Result\n");
    561         log_err("We got: %s", accumDst); fputs("\n", stderr);
    562     }
    563 
    564     errMap = errDst = FALSE;
    565     for (i = 0; i < visLimit; i++) {
    566         idx = ubidi_getLogicalIndex(bidi, i, &errorCode);
    567         if (idx != visMap[i]) {
    568             errMap = TRUE;
    569         }
    570         if (idx == UBIDI_MAP_NOWHERE) {
    571             continue;
    572         }
    573         if (idx >= logLimit) {
    574             continue;
    575         }
    576         accumSrc[idx] = dstChars[i];
    577         if (!matchingPair(bidi, idx, srcChars[idx], dstChars[i])) {
    578             errDst = TRUE;
    579         }
    580     }
    581     accumSrc[logLimit] = 0;
    582     if (U_FAILURE(errorCode)) {
    583         log_err("Error #3 invoking ICU within checkWhatYouCan\n");
    584         return FALSE;
    585     }
    586     if (errMap) {
    587         if (testOK) {
    588             printCaseInfo(bidi, srcChars, dstChars);
    589             testOK = FALSE;
    590         }
    591         log_err("Mismatch between getVisualMap() and getLogicalIndex()\n");
    592         log_err("Map    :");
    593         for (i = 0; i < visLimit; i++) {
    594             log_err(" %d", visMap[i]);
    595         }
    596         fputs("\n", stderr);
    597         log_err("Indexes:");
    598         for (i = 0; i < visLimit; i++) {
    599             log_err(" %d", ubidi_getLogicalIndex(bidi, i, &errorCode));
    600         }
    601         fputs("\n", stderr);
    602     }
    603     if (errDst) {
    604         if (testOK) {
    605             printCaseInfo(bidi, srcChars, dstChars);
    606             testOK = FALSE;
    607         }
    608         log_err("Result does not map to Source\n");
    609         log_err("We got: %s", accumSrc);
    610         fputs("\n", stderr);
    611     }
    612     return testOK;
    613 }
    614 
    615 static void
    616 testReorder(void) {
    617     static const char* const logicalOrder[] ={
    618             "del(KC)add(K.C.&)",
    619             "del(QDVT) add(BVDL)",
    620             "del(PQ)add(R.S.)T)U.&",
    621             "del(LV)add(L.V.) L.V.&",
    622             "day  0  R  DPDHRVR dayabbr",
    623             "day  1  H  DPHPDHDA dayabbr",
    624             "day  2   L  DPBLENDA dayabbr",
    625             "day  3  J  DPJQVM  dayabbr",
    626             "day  4   I  DPIQNF    dayabbr",
    627             "day  5  M  DPMEG  dayabbr",
    628             "helloDPMEG",
    629             "hello WXYZ"
    630     };
    631     static const char* const visualOrder[]={
    632             "del(CK)add(&.C.K)",
    633             "del(TVDQ) add(LDVB)",
    634             "del(QP)add(&.U(T(.S.R",
    635             "del(VL)add(&.V.L (.V.L",
    636             "day  0  RVRHDPD  R dayabbr",
    637             "day  1  ADHDPHPD  H dayabbr",
    638             "day  2   ADNELBPD  L dayabbr",
    639             "day  3  MVQJPD  J  dayabbr",
    640             "day  4   FNQIPD  I    dayabbr",
    641             "day  5  GEMPD  M  dayabbr",
    642             "helloGEMPD",
    643             "hello ZYXW"
    644     };
    645     static const char* const visualOrder1[]={
    646             ")K.C.&(dda)KC(led",
    647             ")BVDL(dda )QDVT(led",
    648             "R.S.(T(U.&(dda)PQ(led",
    649             "L.V.( L.V.&(dda)LV(led",
    650             "rbbayad R  DPDHRVR  0  yad",
    651             "rbbayad H  DPHPDHDA  1  yad",
    652             "rbbayad L  DPBLENDA   2  yad",
    653             "rbbayad  J  DPJQVM  3  yad",
    654             "rbbayad    I  DPIQNF   4  yad",
    655             "rbbayad  M  DPMEG  5  yad",
    656             "DPMEGolleh",
    657             "WXYZ olleh"
    658     };
    659 
    660     static const char* const visualOrder2[]={
    661             "@)@K.C.&@(dda)@KC@(led",
    662             "@)@BVDL@(dda )@QDVT@(led",
    663             "R.S.)T)U.&@(dda)@PQ@(led",
    664             "L.V.) L.V.&@(dda)@LV@(led",
    665             "rbbayad @R  DPDHRVR@  0  yad",
    666             "rbbayad @H  DPHPDHDA@  1  yad",
    667             "rbbayad @L  DPBLENDA@   2  yad",
    668             "rbbayad  @J  DPJQVM@  3  yad",
    669             "rbbayad    @I  DPIQNF@   4  yad",
    670             "rbbayad  @M  DPMEG@  5  yad",
    671             "DPMEGolleh",
    672             "WXYZ@ olleh"
    673     };
    674     static const char* const visualOrder3[]={
    675             ")K.C.&(KC)dda(led",
    676             ")BVDL(ddaQDVT) (led",
    677             "R.S.)T)U.&(PQ)dda(led",
    678             "L.V.) L.V.&(LV)dda(led",
    679             "rbbayad DPDHRVR   R  0 yad",
    680             "rbbayad DPHPDHDA   H  1 yad",
    681             "rbbayad DPBLENDA     L 2 yad",
    682             "rbbayad  DPJQVM   J  3 yad",
    683             "rbbayad    DPIQNF     I 4 yad",
    684             "rbbayad  DPMEG   M  5 yad",
    685             "DPMEGolleh",
    686             "WXYZ olleh"
    687     };
    688     static const char* const visualOrder4[]={
    689             "del(add(CK(.C.K)",
    690             "del( (TVDQadd(LDVB)",
    691             "del(add(QP(.U(T(.S.R",
    692             "del(add(VL(.V.L (.V.L",
    693             "day 0  R   RVRHDPD dayabbr",
    694             "day 1  H   ADHDPHPD dayabbr",
    695             "day 2 L     ADNELBPD dayabbr",
    696             "day 3  J   MVQJPD  dayabbr",
    697             "day 4 I     FNQIPD    dayabbr",
    698             "day 5  M   GEMPD  dayabbr",
    699             "helloGEMPD",
    700             "hello ZYXW"
    701     };
    702     char formatChars[MAXLEN];
    703     UErrorCode ec = U_ZERO_ERROR;
    704     UBiDi* bidi = ubidi_open();
    705     int i;
    706 
    707     log_verbose("\nEntering TestReorder\n\n");
    708 
    709     for(i=0;i<LENGTHOF(logicalOrder);i++){
    710         int32_t srcSize = (int32_t)strlen(logicalOrder[i]);
    711         int32_t destSize = srcSize*2;
    712         UChar src[MAXLEN];
    713         UChar dest[MAXLEN];
    714         char chars[MAXLEN];
    715         log_verbose("Testing L2V #1 for case %d\n", i);
    716         pseudoToU16(srcSize,logicalOrder[i],src);
    717         ec = U_ZERO_ERROR;
    718         ubidi_setPara(bidi,src,srcSize,UBIDI_DEFAULT_LTR ,NULL,&ec);
    719         if(U_FAILURE(ec)){
    720             log_err("ubidi_setPara(tests[%d], paraLevel %d) failed with errorCode %s\n",
    721                     i, UBIDI_DEFAULT_LTR, u_errorName(ec));
    722         }
    723         /* try pre-flighting */
    724         destSize = ubidi_writeReordered(bidi,dest,0,UBIDI_DO_MIRRORING,&ec);
    725         if(ec!=U_BUFFER_OVERFLOW_ERROR){
    726             log_err("Pre-flighting did not give expected error: Expected: U_BUFFER_OVERFLOW_ERROR. Got: %s \n",u_errorName(ec));
    727         }else if(destSize!=srcSize){
    728             log_err("Pre-flighting did not give expected size: Expected: %d. Got: %d \n",srcSize,destSize);
    729         }else{
    730             ec= U_ZERO_ERROR;
    731         }
    732         destSize=ubidi_writeReordered(bidi,dest,destSize+1,UBIDI_DO_MIRRORING,&ec);
    733         u16ToPseudo(destSize,dest,chars);
    734         if(destSize!=srcSize){
    735             log_err("ubidi_writeReordered() destSize and srcSize do not match\n");
    736         }else if(strcmp(visualOrder[i],chars)!=0){
    737             log_err("ubidi_writeReordered() did not give expected results for UBIDI_DO_MIRRORING.\n"
    738                     "Input   : %s\nExpected: %s\nGot     : %s\nLevels  : %s\nAt Index: %d\n",
    739                     logicalOrder[i],visualOrder[i],chars,formatLevels(bidi, formatChars),i);
    740         }
    741         checkWhatYouCan(bidi, logicalOrder[i], chars);
    742     }
    743 
    744     for(i=0;i<LENGTHOF(logicalOrder);i++){
    745         int32_t srcSize = (int32_t)strlen(logicalOrder[i]);
    746         int32_t destSize = srcSize*2;
    747         UChar src[MAXLEN];
    748         UChar dest[MAXLEN];
    749         char chars[MAXLEN];
    750         log_verbose("Testing L2V #2 for case %d\n", i);
    751         pseudoToU16(srcSize,logicalOrder[i],src);
    752         ec = U_ZERO_ERROR;
    753         ubidi_setPara(bidi,src,srcSize,UBIDI_DEFAULT_LTR ,NULL,&ec);
    754         if(U_FAILURE(ec)){
    755             log_err("ubidi_setPara(tests[%d], paraLevel %d) failed with errorCode %s\n",
    756                     i, UBIDI_DEFAULT_LTR, u_errorName(ec));
    757         }
    758         /* try pre-flighting */
    759         destSize = ubidi_writeReordered(bidi,dest,0,UBIDI_DO_MIRRORING+UBIDI_OUTPUT_REVERSE,&ec);
    760         if(ec!=U_BUFFER_OVERFLOW_ERROR){
    761             log_err("Pre-flighting did not give expected error: Expected: U_BUFFER_OVERFLOW_ERROR. Got: %s \n",u_errorName(ec));
    762         }else if(destSize!=srcSize){
    763             log_err("Pre-flighting did not give expected size: Expected: %d. Got: %d \n",srcSize,destSize);
    764         }else{
    765             ec= U_ZERO_ERROR;
    766         }
    767         destSize=ubidi_writeReordered(bidi,dest,destSize+1,UBIDI_DO_MIRRORING+UBIDI_OUTPUT_REVERSE,&ec);
    768         u16ToPseudo(destSize,dest,chars);
    769         if(destSize!=srcSize){
    770             log_err("ubidi_writeReordered() destSize and srcSize do not match\n");
    771         }else if(strcmp(visualOrder1[i],chars)!=0){
    772             log_err("ubidi_writeReordered() did not give expected results for UBIDI_DO_MIRRORING+UBIDI_OUTPUT_REVERSE.\n"
    773                     "Input   : %s\nExpected: %s\nGot     : %s\nLevels  : %s\nAt Index: %d\n",
    774                     logicalOrder[i],visualOrder1[i],chars,formatLevels(bidi, formatChars),i);
    775         }
    776     }
    777 
    778     for(i=0;i<LENGTHOF(logicalOrder);i++){
    779         int32_t srcSize = (int32_t)strlen(logicalOrder[i]);
    780         int32_t destSize = srcSize*2;
    781         UChar src[MAXLEN];
    782         UChar dest[MAXLEN];
    783         char chars[MAXLEN];
    784         log_verbose("Testing V2L #3 for case %d\n", i);
    785         pseudoToU16(srcSize,logicalOrder[i],src);
    786         ec = U_ZERO_ERROR;
    787         ubidi_setInverse(bidi,TRUE);
    788         ubidi_setPara(bidi,src,srcSize,UBIDI_DEFAULT_LTR ,NULL,&ec);
    789         if(U_FAILURE(ec)){
    790             log_err("ubidi_setPara(tests[%d], paraLevel %d) failed with errorCode %s\n",
    791                     i, UBIDI_DEFAULT_LTR, u_errorName(ec));
    792         }
    793                 /* try pre-flighting */
    794         destSize = ubidi_writeReordered(bidi,dest,0,UBIDI_INSERT_LRM_FOR_NUMERIC+UBIDI_OUTPUT_REVERSE,&ec);
    795         if(ec!=U_BUFFER_OVERFLOW_ERROR){
    796             log_err("Pre-flighting did not give expected error: Expected: U_BUFFER_OVERFLOW_ERROR. Got: %s \n",u_errorName(ec));
    797         }else{
    798             ec= U_ZERO_ERROR;
    799         }
    800         destSize=ubidi_writeReordered(bidi,dest,destSize+1,UBIDI_INSERT_LRM_FOR_NUMERIC+UBIDI_OUTPUT_REVERSE,&ec);
    801         u16ToPseudo(destSize,dest,chars);
    802         if(strcmp(visualOrder2[i],chars)!=0){
    803             log_err("ubidi_writeReordered() did not give expected results for UBIDI_INSERT_LRM_FOR_NUMERIC+UBIDI_OUTPUT_REVERSE.\n"
    804                     "Input   : %s\nExpected: %s\nGot     : %s\nLevels  : %s\nAt Index: %d\n",
    805                     logicalOrder[i],visualOrder2[i],chars,formatLevels(bidi, formatChars),i);
    806         }
    807     }
    808         /* Max Explicit level */
    809     for(i=0;i<LENGTHOF(logicalOrder);i++){
    810         int32_t srcSize = (int32_t)strlen(logicalOrder[i]);
    811         int32_t destSize = srcSize*2;
    812         UChar src[MAXLEN];
    813         UChar dest[MAXLEN];
    814         char chars[MAXLEN];
    815         UBiDiLevel levels[UBIDI_MAX_EXPLICIT_LEVEL]={1,2,3,4,5,6,7,8,9,10};
    816         log_verbose("Testing V2L #4 for case %d\n", i);
    817         pseudoToU16(srcSize,logicalOrder[i],src);
    818         ec = U_ZERO_ERROR;
    819         ubidi_setPara(bidi,src,srcSize,UBIDI_DEFAULT_LTR,levels,&ec);
    820         if(U_FAILURE(ec)){
    821             log_err("ubidi_setPara(tests[%d], paraLevel %d) failed with errorCode %s\n",
    822                     i, UBIDI_MAX_EXPLICIT_LEVEL, u_errorName(ec));
    823         }
    824                 /* try pre-flighting */
    825         destSize = ubidi_writeReordered(bidi,dest,0,UBIDI_OUTPUT_REVERSE,&ec);
    826         if(ec!=U_BUFFER_OVERFLOW_ERROR){
    827             log_err("Pre-flighting did not give expected error: Expected: U_BUFFER_OVERFLOW_ERROR. Got: %s \n",u_errorName(ec));
    828         }else if(destSize!=srcSize){
    829             log_err("Pre-flighting did not give expected size: Expected: %d. Got: %d \n",srcSize,destSize);
    830         }else{
    831             ec = U_ZERO_ERROR;
    832         }
    833         destSize=ubidi_writeReordered(bidi,dest,destSize+1,UBIDI_OUTPUT_REVERSE,&ec);
    834         u16ToPseudo(destSize,dest,chars);
    835         if(destSize!=srcSize){
    836             log_err("ubidi_writeReordered() destSize and srcSize do not match. Dest Size = %d Source Size = %d\n",destSize,srcSize );
    837         }else if(strcmp(visualOrder3[i],chars)!=0){
    838             log_err("ubidi_writeReordered() did not give expected results for UBIDI_OUTPUT_REVERSE.\n"
    839                     "Input   : %s\nExpected: %s\nGot     : %s\nLevels  : %s\nAt Index: %d\n",
    840                     logicalOrder[i],visualOrder3[i],chars,formatLevels(bidi, formatChars),i);
    841         }
    842     }
    843     for(i=0;i<LENGTHOF(logicalOrder);i++){
    844         int32_t srcSize = (int32_t)strlen(logicalOrder[i]);
    845         int32_t destSize = srcSize*2;
    846         UChar src[MAXLEN];
    847         UChar dest[MAXLEN];
    848         char chars[MAXLEN];
    849         UBiDiLevel levels[UBIDI_MAX_EXPLICIT_LEVEL]={1,2,3,4,5,6,7,8,9,10};
    850         log_verbose("Testing V2L #5 for case %d\n", i);
    851         pseudoToU16(srcSize,logicalOrder[i],src);
    852         ec = U_ZERO_ERROR;
    853         ubidi_setPara(bidi,src,srcSize,UBIDI_DEFAULT_LTR,levels,&ec);
    854         if(U_FAILURE(ec)){
    855             log_err("ubidi_setPara(tests[%d], paraLevel %d) failed with errorCode %s\n",
    856                     i, UBIDI_MAX_EXPLICIT_LEVEL, u_errorName(ec));
    857         }
    858         /* try pre-flighting */
    859         destSize = ubidi_writeReordered(bidi,dest,0,UBIDI_DO_MIRRORING+UBIDI_REMOVE_BIDI_CONTROLS,&ec);
    860         if(ec!=U_BUFFER_OVERFLOW_ERROR){
    861             log_err("Pre-flighting did not give expected error: Expected: U_BUFFER_OVERFLOW_ERROR. Got: %s \n",u_errorName(ec));
    862         }else{
    863             ec= U_ZERO_ERROR;
    864         }
    865         destSize=ubidi_writeReordered(bidi,dest,destSize+1,UBIDI_DO_MIRRORING+UBIDI_REMOVE_BIDI_CONTROLS,&ec);
    866         u16ToPseudo(destSize,dest,chars);
    867         if(strcmp(visualOrder4[i],chars)!=0){
    868             log_err("ubidi_writeReordered() did not give expected results for UBIDI_DO_MIRRORING+UBIDI_REMOVE_BIDI_CONTROLS.\n"
    869                     "Input   : %s\nExpected: %s\nGot     : %s\nLevels  : %s\nAt Index: %d\n",
    870                     logicalOrder[i],visualOrder4[i],chars,formatLevels(bidi, formatChars),i);
    871         }
    872     }
    873     ubidi_close(bidi);
    874 
    875     log_verbose("\nExiting TestReorder\n\n");
    876 }
    877 
    878 static void
    879 doTest(UBiDi *pBiDi, int testNumber, const BiDiTestData *test, int32_t lineStart, UBool countRunsFirst) {
    880     const uint8_t *dirProps=test->text+lineStart;
    881     const UBiDiLevel *levels=test->levels;
    882     const uint8_t *visualMap=test->visualMap;
    883     int32_t i, len=ubidi_getLength(pBiDi), logicalIndex, runCount = 0;
    884     UErrorCode errorCode=U_ZERO_ERROR;
    885     UBiDiLevel level, level2;
    886 
    887     if (countRunsFirst) {
    888         log_verbose("Calling ubidi_countRuns() first.\n");
    889 
    890         runCount = ubidi_countRuns(pBiDi, &errorCode);
    891 
    892         if(U_FAILURE(errorCode)) {
    893             log_err("ubidi_countRuns(tests[%d]): error %s\n", testNumber, myErrorName(errorCode));
    894             return;
    895         }
    896     } else {
    897         log_verbose("Calling ubidi_getLogicalMap() first.\n");
    898     }
    899 
    900     _testReordering(pBiDi, testNumber);
    901 
    902     for(i=0; i<len; ++i) {
    903         log_verbose("%3d %3d %.*s%-3s @%d\n",
    904                 i, ubidi_getLevelAt(pBiDi, i), ubidi_getLevelAt(pBiDi, i), levelString,
    905                 dirPropNames[dirProps[i]],
    906                 ubidi_getVisualIndex(pBiDi, i, &errorCode));
    907     }
    908 
    909     log_verbose("\n-----levels:");
    910     for(i=0; i<len; ++i) {
    911         if(i>0) {
    912             log_verbose(",");
    913         }
    914         log_verbose(" %d", ubidi_getLevelAt(pBiDi, i));
    915     }
    916 
    917     log_verbose("\n--reordered:");
    918     for(i=0; i<len; ++i) {
    919         if(i>0) {
    920             log_verbose(",");
    921         }
    922         log_verbose(" %d", ubidi_getVisualIndex(pBiDi, i, &errorCode));
    923     }
    924     log_verbose("\n");
    925 
    926     if(test->direction!=ubidi_getDirection(pBiDi)) {
    927         log_err("ubidi_getDirection(tests[%d]): wrong direction %d\n", testNumber, ubidi_getDirection(pBiDi));
    928     }
    929 
    930     if(test->resultLevel!=ubidi_getParaLevel(pBiDi)) {
    931         log_err("ubidi_getParaLevel(tests[%d]): wrong paragraph level %d\n", testNumber, ubidi_getParaLevel(pBiDi));
    932     }
    933 
    934     for(i=0; i<len; ++i) {
    935         if(levels[i]!=ubidi_getLevelAt(pBiDi, i)) {
    936             log_err("ubidi_getLevelAt(tests[%d], %d): wrong level %d, expected %d\n", testNumber, i, ubidi_getLevelAt(pBiDi, i), levels[i]);
    937             return;
    938         }
    939     }
    940 
    941     for(i=0; i<len; ++i) {
    942         logicalIndex=ubidi_getVisualIndex(pBiDi, i, &errorCode);
    943         if(U_FAILURE(errorCode)) {
    944             log_err("ubidi_getVisualIndex(tests[%d], %d): error %s\n", testNumber, i, myErrorName(errorCode));
    945             return;
    946         }
    947         if(visualMap[i]!=logicalIndex) {
    948             log_err("ubidi_getVisualIndex(tests[%d], %d): wrong index %d\n", testNumber, i, logicalIndex);
    949             return;
    950         }
    951     }
    952 
    953     if (! countRunsFirst) {
    954         runCount=ubidi_countRuns(pBiDi, &errorCode);
    955         if(U_FAILURE(errorCode)) {
    956             log_err("ubidi_countRuns(tests[%d]): error %s\n", testNumber, myErrorName(errorCode));
    957             return;
    958         }
    959     }
    960 
    961     for(logicalIndex=0; logicalIndex<len;) {
    962         level=ubidi_getLevelAt(pBiDi, logicalIndex);
    963         ubidi_getLogicalRun(pBiDi, logicalIndex, &logicalIndex, &level2);
    964         if(level!=level2) {
    965             log_err("ubidi_getLogicalRun(tests[%d], run ending at index %d): "
    966                     "wrong level %d instead of %d\n",
    967                     testNumber, logicalIndex, level, level2);
    968         }
    969         if(--runCount<0) {
    970             log_err("\nubidi_getLogicalRun(tests[%d]): wrong number of runs "
    971                     "compared to %d=ubidi_countRuns()\n",
    972                     testNumber, ubidi_countRuns(pBiDi, &errorCode));
    973             return;
    974         }
    975     }
    976     if(runCount!=0) {
    977         log_err("\nubidi_getLogicalRun(tests[%d]): wrong number of runs "
    978                 "compared to %d=ubidi_getRunCount()\n",
    979                 testNumber, ubidi_countRuns(pBiDi, &errorCode));
    980         return;
    981     }
    982 
    983     log_verbose("\n\n");
    984 }
    985 
    986 static void
    987 _testReordering(UBiDi *pBiDi, int testNumber) {
    988     int32_t
    989         logicalMap1[MAXLEN], logicalMap2[MAXLEN], logicalMap3[MAXLEN],
    990         visualMap1[MAXLEN], visualMap2[MAXLEN], visualMap3[MAXLEN], visualMap4[MAXLEN];
    991     UErrorCode errorCode=U_ZERO_ERROR;
    992     const UBiDiLevel *levels;
    993     int32_t i, length=ubidi_getLength(pBiDi),
    994                destLength=ubidi_getResultLength(pBiDi);
    995     int32_t runCount, visualIndex, logicalStart, runLength;
    996     UBool odd;
    997 
    998     if(length<=0) {
    999         return;
   1000     }
   1001 
   1002     /* get the logical and visual maps from the object */
   1003     ubidi_getLogicalMap(pBiDi, logicalMap1, &errorCode);
   1004     if(U_FAILURE(errorCode)) {
   1005         log_err("ubidi_getLogicalMap(tests[%d]): error %s\n", testNumber, myErrorName(errorCode));
   1006         return;
   1007     }
   1008 
   1009     ubidi_getVisualMap(pBiDi, visualMap1, &errorCode);
   1010     if(U_FAILURE(errorCode)) {
   1011         log_err("ubidi_getVisualMap(tests[%d]): error %s\n", testNumber, myErrorName(errorCode));
   1012         return;
   1013     }
   1014 
   1015     /* invert them both */
   1016     ubidi_invertMap(logicalMap1, visualMap2, length);
   1017     ubidi_invertMap(visualMap1, logicalMap2, destLength);
   1018 
   1019     /* get them from the levels array, too */
   1020     levels=ubidi_getLevels(pBiDi, &errorCode);
   1021 
   1022     if(U_FAILURE(errorCode)) {
   1023         log_err("ubidi_getLevels(tests[%d]): error %s\n", testNumber, myErrorName(errorCode));
   1024         return;
   1025     }
   1026 
   1027     ubidi_reorderLogical(levels, length, logicalMap3);
   1028     ubidi_reorderVisual(levels, length, visualMap3);
   1029 
   1030     /* get the visual map from the runs, too */
   1031     runCount=ubidi_countRuns(pBiDi, &errorCode);
   1032     if(U_FAILURE(errorCode)) {
   1033         log_err("ubidi_countRuns(tests[%d]): error %s\n", testNumber, myErrorName(errorCode));
   1034         return;
   1035     }
   1036     log_verbose("\n----%2d runs:", runCount);
   1037     visualIndex=0;
   1038     for(i=0; i<runCount; ++i) {
   1039         odd=(UBool)ubidi_getVisualRun(pBiDi, i, &logicalStart, &runLength);
   1040         log_verbose(" (%c @%d[%d])", odd ? 'R' : 'L', logicalStart, runLength);
   1041         if(UBIDI_LTR==odd) {
   1042             do { /* LTR */
   1043                 visualMap4[visualIndex++]=logicalStart++;
   1044             } while(--runLength>0);
   1045         } else {
   1046             logicalStart+=runLength;   /* logicalLimit */
   1047             do { /* RTL */
   1048                 visualMap4[visualIndex++]=--logicalStart;
   1049             } while(--runLength>0);
   1050         }
   1051     }
   1052     log_verbose("\n");
   1053 
   1054     /* print all the maps */
   1055     log_verbose("logical maps:\n");
   1056     for(i=0; i<length; ++i) {
   1057         log_verbose("%4d", logicalMap1[i]);
   1058     }
   1059     log_verbose("\n");
   1060     for(i=0; i<length; ++i) {
   1061         log_verbose("%4d", logicalMap2[i]);
   1062     }
   1063     log_verbose("\n");
   1064     for(i=0; i<length; ++i) {
   1065         log_verbose("%4d", logicalMap3[i]);
   1066     }
   1067 
   1068     log_verbose("\nvisual maps:\n");
   1069     for(i=0; i<destLength; ++i) {
   1070         log_verbose("%4d", visualMap1[i]);
   1071     }
   1072     log_verbose("\n");
   1073     for(i=0; i<destLength; ++i) {
   1074         log_verbose("%4d", visualMap2[i]);
   1075     }
   1076     log_verbose("\n");
   1077     for(i=0; i<length; ++i) {
   1078         log_verbose("%4d", visualMap3[i]);
   1079     }
   1080     log_verbose("\n");
   1081     for(i=0; i<length; ++i) {
   1082         log_verbose("%4d", visualMap4[i]);
   1083     }
   1084     log_verbose("\n");
   1085 
   1086     /* check that the indexes are the same between these and ubidi_getLogical/VisualIndex() */
   1087     for(i=0; i<length; ++i) {
   1088         if(logicalMap1[i]!=logicalMap2[i]) {
   1089             log_err("bidi reordering error in tests[%d]: logicalMap1[i]!=logicalMap2[i] at i=%d\n", testNumber, i);
   1090             break;
   1091         }
   1092         if(logicalMap1[i]!=logicalMap3[i]) {
   1093             log_err("bidi reordering error in tests[%d]: logicalMap1[i]!=logicalMap3[i] at i=%d\n", testNumber, i);
   1094             break;
   1095         }
   1096 
   1097         if(visualMap1[i]!=visualMap2[i]) {
   1098             log_err("bidi reordering error in tests[%d]: visualMap1[i]!=visualMap2[i] at i=%d\n", testNumber, i);
   1099             break;
   1100         }
   1101         if(visualMap1[i]!=visualMap3[i]) {
   1102             log_err("bidi reordering error in tests[%d]: visualMap1[i]!=visualMap3[i] at i=%d\n", testNumber, i);
   1103             break;
   1104         }
   1105         if(visualMap1[i]!=visualMap4[i]) {
   1106             log_err("bidi reordering error in tests[%d]: visualMap1[i]!=visualMap4[i] at i=%d\n", testNumber, i);
   1107             break;
   1108         }
   1109 
   1110         if(logicalMap1[i]!=ubidi_getVisualIndex(pBiDi, i, &errorCode)) {
   1111             log_err("bidi reordering error in tests[%d]: logicalMap1[i]!=ubidi_getVisualIndex(i) at i=%d\n", testNumber, i);
   1112             break;
   1113         }
   1114         if(U_FAILURE(errorCode)) {
   1115             log_err("ubidi_getVisualIndex(tests[%d], %d): error %s\n", testNumber, i, myErrorName(errorCode));
   1116             break;
   1117         }
   1118         if(visualMap1[i]!=ubidi_getLogicalIndex(pBiDi, i, &errorCode)) {
   1119             log_err("bidi reordering error in tests[%d]: visualMap1[i]!=ubidi_getLogicalIndex(i) at i=%d\n", testNumber, i);
   1120             break;
   1121         }
   1122         if(U_FAILURE(errorCode)) {
   1123             log_err("ubidi_getLogicalIndex(tests[%d], %d): error %s\n", testNumber, i, myErrorName(errorCode));
   1124             break;
   1125         }
   1126     }
   1127 }
   1128 
   1129 #define RETURN_IF_BAD_ERRCODE(x)    \
   1130     if (U_FAILURE(errorCode)) {      \
   1131         log_err("\nbad errorCode %d at %s\n", errorCode, (x));  \
   1132         return;     \
   1133     }               \
   1134 
   1135 
   1136 static void doMisc(void) {
   1137 /* Miscellaneous tests to exercize less popular code paths */
   1138     UBiDi *bidi, *bidiLine;
   1139     UChar src[MAXLEN], dest[MAXLEN];
   1140     int32_t srcLen, destLen, runCount, i;
   1141     UBiDiLevel level;
   1142     UBiDiDirection dir;
   1143     int32_t map[MAXLEN];
   1144     UErrorCode errorCode=U_ZERO_ERROR;
   1145     static const int32_t srcMap[6] = {0,1,-1,5,4};
   1146     static const int32_t dstMap[6] = {0,1,-1,-1,4,3};
   1147 
   1148     bidi = ubidi_openSized(120, 66, &errorCode);
   1149     if (bidi == NULL) {
   1150         log_err("Error with openSized(120, 66)\n");
   1151         return;
   1152     }
   1153     bidiLine = ubidi_open();
   1154     if (bidi == NULL) {
   1155         log_err("Error with open()\n");
   1156         return;
   1157     }
   1158 
   1159     destLen = ubidi_writeReverse(src, 0, dest, MAXLEN, 0, &errorCode);
   1160     if (destLen != 0) {
   1161         log_err("\nwriteReverse should return zero length, ",
   1162                 "returned %d instead\n", destLen);
   1163     }
   1164     RETURN_IF_BAD_ERRCODE("#1#");
   1165 
   1166     ubidi_setPara(bidi, src, 0, UBIDI_LTR, NULL, &errorCode);
   1167     destLen = ubidi_writeReordered(bidi, dest, MAXLEN, 0, &errorCode);
   1168     if (destLen != 0) {
   1169         log_err("\nwriteReordered should return zero length, ",
   1170                 "returned %d instead\n", destLen);
   1171     }
   1172     RETURN_IF_BAD_ERRCODE("#2#");
   1173 
   1174     srcLen = u_unescape("abc       ", src, MAXLEN);
   1175     ubidi_setPara(bidi, src, srcLen, UBIDI_RTL, NULL, &errorCode);
   1176     ubidi_setLine(bidi, 0, 6, bidiLine, &errorCode);
   1177     for (i = 3; i < 6; i++) {
   1178         level = ubidi_getLevelAt(bidiLine, i);
   1179         if (level != UBIDI_RTL) {
   1180             log_err("\nTrailing space at index %d should get paragraph level"
   1181                     "%d, got %d instead\n", i, UBIDI_RTL, level);
   1182         }
   1183     }
   1184     RETURN_IF_BAD_ERRCODE("#3#");
   1185 
   1186     srcLen = u_unescape("abc       def", src, MAXLEN);
   1187     ubidi_setPara(bidi, src, srcLen, UBIDI_RTL, NULL, &errorCode);
   1188     ubidi_setLine(bidi, 0, 6, bidiLine, &errorCode);
   1189     for (i = 3; i < 6; i++) {
   1190         level = ubidi_getLevelAt(bidiLine, i);
   1191         if (level != UBIDI_RTL) {
   1192             log_err("\nTrailing space at index %d should get paragraph level"
   1193                     "%d, got %d instead\n", i, UBIDI_RTL, level);
   1194         }
   1195     }
   1196     RETURN_IF_BAD_ERRCODE("#4#");
   1197 
   1198     srcLen = u_unescape("abcdefghi    ", src, MAXLEN);
   1199     ubidi_setPara(bidi, src, srcLen, UBIDI_RTL, NULL, &errorCode);
   1200     ubidi_setLine(bidi, 0, 6, bidiLine, &errorCode);
   1201     for (i = 3; i < 6; i++) {
   1202         level = ubidi_getLevelAt(bidiLine, i);
   1203         if (level != 2) {
   1204             log_err("\nTrailing char at index %d should get level 2, "
   1205                     "got %d instead\n", i, level);
   1206         }
   1207     }
   1208     RETURN_IF_BAD_ERRCODE("#5#");
   1209 
   1210     ubidi_setReorderingOptions(bidi, UBIDI_OPTION_REMOVE_CONTROLS);
   1211     srcLen = u_unescape("\\u200eabc       def", src, MAXLEN);
   1212     ubidi_setPara(bidi, src, srcLen, UBIDI_RTL, NULL, &errorCode);
   1213     ubidi_setLine(bidi, 0, 6, bidiLine, &errorCode);
   1214     destLen = ubidi_getResultLength(bidiLine);
   1215     if (destLen != 5) {
   1216         log_err("\nWrong result length, should be 5, got %d\n", destLen);
   1217     }
   1218     RETURN_IF_BAD_ERRCODE("#6#");
   1219 
   1220     srcLen = u_unescape("abcdefghi", src, MAXLEN);
   1221     ubidi_setPara(bidi, src, srcLen, UBIDI_LTR, NULL, &errorCode);
   1222     ubidi_setLine(bidi, 0, 6, bidiLine, &errorCode);
   1223     dir = ubidi_getDirection(bidiLine);
   1224     if (dir != UBIDI_LTR) {
   1225         log_err("\nWrong direction #1, should be %d, got %d\n",
   1226                 UBIDI_LTR, dir);
   1227     }
   1228     RETURN_IF_BAD_ERRCODE("#7#");
   1229 
   1230     ubidi_setPara(bidi, src, 0, UBIDI_LTR, NULL, &errorCode);
   1231     runCount = ubidi_countRuns(bidi, &errorCode);
   1232     if (runCount != 0) {
   1233         log_err("\nWrong number of runs #1, should be 0, got %d\n", runCount);
   1234     }
   1235     RETURN_IF_BAD_ERRCODE("#8#");
   1236 
   1237     srcLen = u_unescape("          ", src, MAXLEN);
   1238     ubidi_setPara(bidi, src, srcLen, UBIDI_RTL, NULL, &errorCode);
   1239     ubidi_setLine(bidi, 0, 6, bidiLine, &errorCode);
   1240     runCount = ubidi_countRuns(bidiLine, &errorCode);
   1241     if (runCount != 1) {
   1242         log_err("\nWrong number of runs #2, should be 1, got %d\n", runCount);
   1243     }
   1244     RETURN_IF_BAD_ERRCODE("#9#");
   1245 
   1246     srcLen = u_unescape("a\\u05d0        bc", src, MAXLEN);
   1247     ubidi_setPara(bidi, src, srcLen, UBIDI_RTL, NULL, &errorCode);
   1248     ubidi_setLine(bidi, 0, 6, bidiLine, &errorCode);
   1249     dir = ubidi_getDirection(bidi);
   1250     if (dir != UBIDI_MIXED) {
   1251         log_err("\nWrong direction #2, should be %d, got %d\n",
   1252                 UBIDI_MIXED, dir);
   1253     }
   1254     dir = ubidi_getDirection(bidiLine);
   1255     if (dir != UBIDI_MIXED) {
   1256         log_err("\nWrong direction #3, should be %d, got %d\n",
   1257                 UBIDI_MIXED, dir);
   1258     }
   1259     runCount = ubidi_countRuns(bidiLine, &errorCode);
   1260     if (runCount != 2) {
   1261         log_err("\nWrong number of runs #3, should be 2, got %d\n", runCount);
   1262     }
   1263     RETURN_IF_BAD_ERRCODE("#10#");
   1264 
   1265     ubidi_invertMap(srcMap, map, 5);
   1266     if (memcmp(dstMap, map, sizeof(dstMap))) {
   1267         log_err("\nUnexpected inverted Map, got ");
   1268         for (i = 0; i < 6; i++) {
   1269             log_err("%d ", map[i]);
   1270         }
   1271         log_err("\n");
   1272     }
   1273 
   1274     /* test REMOVE_BIDI_CONTROLS together with DO_MIRRORING */
   1275     srcLen = u_unescape("abc\\u200e", src, MAXLEN);
   1276     ubidi_setPara(bidi, src, srcLen, UBIDI_LTR, NULL, &errorCode);
   1277     destLen = ubidi_writeReordered(bidi, dest, MAXLEN,
   1278               UBIDI_REMOVE_BIDI_CONTROLS | UBIDI_DO_MIRRORING, &errorCode);
   1279     if (destLen != 3 || memcmp(dest, src, 3 * sizeof(UChar))) {
   1280         log_err("\nWrong result #1, should be 'abc', got '%s'\n",
   1281                 aescstrdup(dest, destLen));
   1282     }
   1283     RETURN_IF_BAD_ERRCODE("#11#");
   1284 
   1285     /* test inverse Bidi with marks and contextual orientation */
   1286     ubidi_setReorderingMode(bidi, UBIDI_REORDER_INVERSE_LIKE_DIRECT);
   1287     ubidi_setReorderingOptions(bidi, UBIDI_OPTION_INSERT_MARKS);
   1288     ubidi_setPara(bidi, src, 0, UBIDI_DEFAULT_RTL, NULL, &errorCode);
   1289     destLen = ubidi_writeReordered(bidi, dest, MAXLEN, 0, &errorCode);
   1290     if (destLen != 0) {
   1291         log_err("\nWrong result #2, length should be 0, got %d\n", destLen);
   1292     }
   1293     RETURN_IF_BAD_ERRCODE("#12#");
   1294     srcLen = u_unescape("   ", src, MAXLEN);
   1295     ubidi_setPara(bidi, src, srcLen, UBIDI_DEFAULT_RTL, NULL, &errorCode);
   1296     destLen = ubidi_writeReordered(bidi, dest, MAXLEN, 0, &errorCode);
   1297     if (destLen != 3 || memcmp(dest, src, destLen * sizeof(UChar))) {
   1298         log_err("\nWrong result #3, should be '   ', got '%s'\n",
   1299                 aescstrdup(dest, destLen));
   1300     }
   1301     RETURN_IF_BAD_ERRCODE("#13#");
   1302     srcLen = u_unescape("abc", src, MAXLEN);
   1303     ubidi_setPara(bidi, src, srcLen, UBIDI_DEFAULT_RTL, NULL, &errorCode);
   1304     destLen = ubidi_writeReordered(bidi, dest, MAXLEN, 0, &errorCode);
   1305     if (destLen != 3 || memcmp(dest, src, destLen * sizeof(UChar))) {
   1306         log_err("\nWrong result #4, should be 'abc', got '%s'\n",
   1307                 aescstrdup(dest, destLen));
   1308     }
   1309     RETURN_IF_BAD_ERRCODE("#14#");
   1310     srcLen = u_unescape("\\u05d0\\u05d1", src, MAXLEN);
   1311     ubidi_setPara(bidi, src, srcLen, UBIDI_DEFAULT_RTL, NULL, &errorCode);
   1312     destLen = ubidi_writeReordered(bidi, dest, MAXLEN, 0, &errorCode);
   1313     srcLen = u_unescape("\\u05d1\\u05d0", src, MAXLEN);
   1314     if (destLen != 2 || memcmp(dest, src, destLen * sizeof(UChar))) {
   1315         log_err("\nWrong result #5, should be '%s', got '%s'\n",
   1316                 aescstrdup(src, srcLen), aescstrdup(dest, destLen));
   1317     }
   1318     RETURN_IF_BAD_ERRCODE("#15#");
   1319     srcLen = u_unescape("abc \\u05d0\\u05d1", src, MAXLEN);
   1320     ubidi_setPara(bidi, src, srcLen, UBIDI_DEFAULT_RTL, NULL, &errorCode);
   1321     destLen = ubidi_writeReordered(bidi, dest, MAXLEN, 0, &errorCode);
   1322     srcLen = u_unescape("\\u05d1\\u05d0 abc", src, MAXLEN);
   1323     if (destLen != 6 || memcmp(dest, src, destLen * sizeof(UChar))) {
   1324         log_err("\nWrong result #6, should be '%s', got '%s'\n",
   1325                 aescstrdup(src, srcLen), aescstrdup(dest, destLen));
   1326     }
   1327     RETURN_IF_BAD_ERRCODE("#16#");
   1328     srcLen = u_unescape("\\u05d0\\u05d1 abc", src, MAXLEN);
   1329     ubidi_setPara(bidi, src, srcLen, UBIDI_DEFAULT_RTL, NULL, &errorCode);
   1330     destLen = ubidi_writeReordered(bidi, dest, MAXLEN, 0, &errorCode);
   1331     srcLen = u_unescape("\\u200fabc \\u05d1\\u05d0", src, MAXLEN);
   1332     if (destLen != 7 || memcmp(dest, src, destLen * sizeof(UChar))) {
   1333         log_err("\nWrong result #7, should be '%s', got '%s'\n",
   1334                 aescstrdup(src, srcLen), aescstrdup(dest, destLen));
   1335     }
   1336     RETURN_IF_BAD_ERRCODE("#17#");
   1337     srcLen = u_unescape("\\u05d0\\u05d1 abc .-=", src, MAXLEN);
   1338     ubidi_setPara(bidi, src, srcLen, UBIDI_DEFAULT_RTL, NULL, &errorCode);
   1339     destLen = ubidi_writeReordered(bidi, dest, MAXLEN, 0, &errorCode);
   1340     srcLen = u_unescape("\\u200f=-. abc \\u05d1\\u05d0", src, MAXLEN);
   1341     if (destLen != 11 || memcmp(dest, src, destLen * sizeof(UChar))) {
   1342         log_err("\nWrong result #8, should be '%s', got '%s'\n",
   1343                 aescstrdup(src, srcLen), aescstrdup(dest, destLen));
   1344     }
   1345     RETURN_IF_BAD_ERRCODE("#18#");
   1346     ubidi_orderParagraphsLTR(bidi, TRUE);
   1347     srcLen = u_unescape("\n\r   \n\rabc\n\\u05d0\\u05d1\rabc \\u05d2\\u05d3\n\r"
   1348                         "\\u05d4\\u05d5 abc\n\\u05d6\\u05d7 abc .-=\r\n"
   1349                         "-* \\u05d8\\u05d9 abc .-=", src, MAXLEN);
   1350     ubidi_setPara(bidi, src, srcLen, UBIDI_DEFAULT_RTL, NULL, &errorCode);
   1351     destLen = ubidi_writeReordered(bidi, dest, MAXLEN, 0, &errorCode);
   1352     srcLen = u_unescape("\n\r   \n\rabc\n\\u05d1\\u05d0\r\\u05d3\\u05d2 abc\n\r"
   1353                         "\\u200fabc \\u05d5\\u05d4\n\\u200f=-. abc \\u05d7\\u05d6\r\n"
   1354                         "\\u200f=-. abc \\u05d9\\u05d8 *-", src, MAXLEN);
   1355     if (destLen != 57 || memcmp(dest, src, destLen * sizeof(UChar))) {
   1356         log_err("\nWrong result #9, should be '%s', got '%s'\n",
   1357                 aescstrdup(src, srcLen), aescstrdup(dest, destLen));
   1358     }
   1359     RETURN_IF_BAD_ERRCODE("#19#");
   1360     srcLen = u_unescape("\\u05d0 \t", src, MAXLEN);
   1361     ubidi_setPara(bidi, src, srcLen, UBIDI_LTR, NULL, &errorCode);
   1362     destLen = ubidi_writeReordered(bidi, dest, MAXLEN, 0, &errorCode);
   1363     srcLen = u_unescape("\\u05D0\\u200e \t", src, MAXLEN);
   1364     if (destLen != 4 || memcmp(dest, src, destLen * sizeof(UChar))) {
   1365         log_err("\nWrong result #10, should be '%s', got '%s'\n",
   1366                 aescstrdup(src, srcLen), aescstrdup(dest, destLen));
   1367     }
   1368     RETURN_IF_BAD_ERRCODE("#20#");
   1369     srcLen = u_unescape("\\u05d0 123 \t\\u05d1 123 \\u05d2", src, MAXLEN);
   1370     ubidi_setPara(bidi, src, srcLen, UBIDI_LTR, NULL, &errorCode);
   1371     destLen = ubidi_writeReordered(bidi, dest, MAXLEN, 0, &errorCode);
   1372     srcLen = u_unescape("\\u05d0 \\u200e123\\u200e \t\\u05d2 123 \\u05d1", src, MAXLEN);
   1373     if (destLen != 16 || memcmp(dest, src, destLen * sizeof(UChar))) {
   1374         log_err("\nWrong result #11, should be '%s', got '%s'\n",
   1375                 aescstrdup(src, srcLen), aescstrdup(dest, destLen));
   1376     }
   1377     RETURN_IF_BAD_ERRCODE("#21#");
   1378     srcLen = u_unescape("\\u05d0 123 \\u0660\\u0661 ab", src, MAXLEN);
   1379     ubidi_setPara(bidi, src, srcLen, UBIDI_LTR, NULL, &errorCode);
   1380     destLen = ubidi_writeReordered(bidi, dest, MAXLEN, 0, &errorCode);
   1381     srcLen = u_unescape("\\u05d0 \\u200e123 \\u200e\\u0660\\u0661 ab", src, MAXLEN);
   1382     if (destLen != 13 || memcmp(dest, src, destLen * sizeof(UChar))) {
   1383         log_err("\nWrong result #12, should be '%s', got '%s'\n",
   1384                 aescstrdup(src, srcLen), aescstrdup(dest, destLen));
   1385     }
   1386     RETURN_IF_BAD_ERRCODE("#22#");
   1387     srcLen = u_unescape("ab \t", src, MAXLEN);
   1388     ubidi_setPara(bidi, src, srcLen, UBIDI_RTL, NULL, &errorCode);
   1389     destLen = ubidi_writeReordered(bidi, dest, MAXLEN, 0, &errorCode);
   1390     srcLen = u_unescape("\\u200f\t ab", src, MAXLEN);
   1391     if (destLen != 5 || memcmp(dest, src, destLen * sizeof(UChar))) {
   1392         log_err("\nWrong result #13, should be '%s', got '%s'\n",
   1393                 aescstrdup(src, srcLen), aescstrdup(dest, destLen));
   1394     }
   1395     RETURN_IF_BAD_ERRCODE("#23#");
   1396 
   1397     /* check exceeding para level */
   1398     ubidi_close(bidi);
   1399     bidi = ubidi_open();
   1400     srcLen = u_unescape("A\\u202a\\u05d0\\u202aC\\u202c\\u05d1\\u202cE", src, MAXLEN);
   1401     ubidi_setPara(bidi, src, srcLen, UBIDI_MAX_EXPLICIT_LEVEL - 1, NULL, &errorCode);
   1402     level = ubidi_getLevelAt(bidi, 2);
   1403     if (level != 61) {
   1404         log_err("\nWrong level at index 2\n, should be 61, got %d\n", level);
   1405     }
   1406     RETURN_IF_BAD_ERRCODE("#24#");
   1407 
   1408     /* check 1-char runs with RUNS_ONLY */
   1409     ubidi_setReorderingMode(bidi, UBIDI_REORDER_RUNS_ONLY);
   1410     srcLen = u_unescape("a \\u05d0 b \\u05d1 c \\u05d2 d ", src, MAXLEN);
   1411     ubidi_setPara(bidi, src, srcLen, UBIDI_LTR, NULL, &errorCode);
   1412     runCount = ubidi_countRuns(bidi, &errorCode);
   1413     if (runCount != 14) {
   1414         log_err("\nWrong number of runs #3, should be 14, got %d\n", runCount);
   1415     }
   1416     RETURN_IF_BAD_ERRCODE("#25#");
   1417 
   1418     ubidi_close(bidi);
   1419     ubidi_close(bidiLine);
   1420 }
   1421 
   1422 static void
   1423 testFailureRecovery(void) {
   1424     UErrorCode errorCode;
   1425     UBiDi *bidi, *bidiLine;
   1426     UChar src[MAXLEN];
   1427     int32_t srcLen;
   1428     UBiDiLevel level;
   1429     UBiDiReorderingMode rm;
   1430     static UBiDiLevel myLevels[3] = {6,5,4};
   1431 
   1432     log_verbose("\nEntering TestFailureRecovery\n\n");
   1433     errorCode = U_FILE_ACCESS_ERROR;
   1434     if (ubidi_writeReordered(NULL, NULL, 0, 0, &errorCode) != 0) {
   1435         log_err("ubidi_writeReordered did not return 0 when passed a failing UErrorCode\n");
   1436     }
   1437     if (ubidi_writeReverse(NULL, 0, NULL, 0, 0, &errorCode) != 0) {
   1438         log_err("ubidi_writeReverse did not return 0 when passed a failing UErrorCode\n");
   1439     }
   1440     errorCode = U_ZERO_ERROR;
   1441     if (ubidi_writeReordered(NULL, NULL, 0, 0, &errorCode) != 0 || errorCode != U_ILLEGAL_ARGUMENT_ERROR) {
   1442         log_err("ubidi_writeReordered did not fail as expected\n");
   1443     }
   1444 
   1445     bidi = ubidi_open();
   1446     srcLen = u_unescape("abc", src, MAXLEN);
   1447     errorCode = U_ZERO_ERROR;
   1448     ubidi_setPara(bidi, src, srcLen, UBIDI_DEFAULT_LTR - 1, NULL, &errorCode);
   1449     if (U_SUCCESS(errorCode)) {
   1450         log_err("\nubidi_setPara did not fail when passed too big para level\n");
   1451     }
   1452     errorCode = U_ZERO_ERROR;
   1453     if (ubidi_writeReverse(NULL, 0, NULL, 0, 0, &errorCode) != 0 || errorCode != U_ILLEGAL_ARGUMENT_ERROR) {
   1454         log_err("ubidi_writeReverse did not fail as expected\n");
   1455     }
   1456     bidiLine = ubidi_open();
   1457     errorCode = U_ZERO_ERROR;
   1458     ubidi_setLine(bidi, 0, 6, bidiLine, &errorCode);
   1459     if (U_SUCCESS(errorCode)) {
   1460         log_err("\nubidi_setLine did not fail when called before valid setPara()\n");
   1461     }
   1462     errorCode = U_ZERO_ERROR;
   1463     srcLen = u_unescape("abc", src, MAXLEN);
   1464     ubidi_setPara(bidi, src, srcLen, UBIDI_LTR + 4, NULL, &errorCode);
   1465     level = ubidi_getLevelAt(bidi, 3);
   1466     if (level != 0) {
   1467         log_err("\nubidi_getLevelAt did not fail when called with bad argument\n");
   1468     }
   1469     errorCode = U_ZERO_ERROR;
   1470     ubidi_close(bidi);
   1471     bidi = ubidi_openSized(-1, 0, &errorCode);
   1472     if (U_SUCCESS(errorCode)) {
   1473         log_err("\nubidi_openSized did not fail when called with bad argument\n");
   1474     }
   1475     ubidi_close(bidi);
   1476     bidi = ubidi_openSized(2, 1, &errorCode);
   1477     errorCode = U_ZERO_ERROR;
   1478     srcLen = u_unescape("abc", src, MAXLEN);
   1479     ubidi_setPara(bidi, src, srcLen, UBIDI_LTR, NULL, &errorCode);
   1480     if (U_SUCCESS(errorCode)) {
   1481         log_err("\nsetPara did not fail when called with text too long\n");
   1482     }
   1483     errorCode = U_ZERO_ERROR;
   1484     srcLen = u_unescape("=2", src, MAXLEN);
   1485     ubidi_setPara(bidi, src, srcLen, UBIDI_RTL, NULL, &errorCode);
   1486     ubidi_countRuns(bidi, &errorCode);
   1487     if (U_SUCCESS(errorCode)) {
   1488         log_err("\nsetPara did not fail when called for too many runs\n");
   1489     }
   1490     ubidi_close(bidi);
   1491     bidi = ubidi_open();
   1492     rm = ubidi_getReorderingMode(bidi);
   1493     ubidi_setReorderingMode(bidi, UBIDI_REORDER_DEFAULT - 1);
   1494     if (rm != ubidi_getReorderingMode(bidi)) {
   1495         log_err("\nsetReorderingMode with bad argument #1 should have no effect\n");
   1496     }
   1497     ubidi_setReorderingMode(bidi, 9999);
   1498     if (rm != ubidi_getReorderingMode(bidi)) {
   1499         log_err("\nsetReorderingMode with bad argument #2 should have no effect\n");
   1500     }
   1501 
   1502     /* Try a surrogate char */
   1503     errorCode = U_ZERO_ERROR;
   1504     srcLen = u_unescape("\\uD800\\uDC00", src, MAXLEN);
   1505     ubidi_setPara(bidi, src, srcLen, UBIDI_RTL, NULL, &errorCode);
   1506     if (ubidi_getDirection(bidi) != UBIDI_MIXED) {
   1507         log_err("\ngetDirection for 1st surrogate char should be MIXED\n");
   1508     }
   1509     errorCode = U_ZERO_ERROR;
   1510     srcLen = u_unescape("abc", src, MAXLEN);
   1511     ubidi_setPara(bidi, src, srcLen, 5, myLevels, &errorCode);
   1512     if (U_SUCCESS(errorCode)) {
   1513         log_err("\nsetPara did not fail when called with bad levels\n");
   1514     }
   1515     ubidi_close(bidi);
   1516     ubidi_close(bidiLine);
   1517 
   1518     log_verbose("\nExiting TestFailureRecovery\n\n");
   1519 }
   1520 
   1521 static void
   1522 testMultipleParagraphs(void) {
   1523     static const char* const text = "__ABC\\u001c"          /* Para #0 offset 0 */
   1524                                     "__\\u05d0DE\\u001c"    /*       1        6 */
   1525                                     "__123\\u001c"          /*       2       12 */
   1526                                     "\\u000d\\u000a"        /*       3       18 */
   1527                                     "FG\\u000d"             /*       4       20 */
   1528                                     "\\u000d"               /*       5       23 */
   1529                                     "HI\\u000d\\u000a"      /*       6       24 */
   1530                                     "\\u000d\\u000a"        /*       7       28 */
   1531                                     "\\u000a"               /*       8       30 */
   1532                                     "\\u000a"               /*       9       31 */
   1533                                     "JK\\u001c";            /*      10       32 */
   1534     static const int32_t paraCount=11;
   1535     static const int32_t paraBounds[]={0, 6, 12, 18, 20, 23, 24, 28, 30, 31, 32, 35};
   1536     static const UBiDiLevel paraLevels[]={UBIDI_LTR, UBIDI_RTL, UBIDI_DEFAULT_LTR, UBIDI_DEFAULT_RTL, 22, 23};
   1537     static const UBiDiLevel multiLevels[6][11] = {{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
   1538                                                   {1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1},
   1539                                                   {0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0},
   1540                                                   {0, 1, 1, 1, 0, 1, 0, 1, 1, 1, 0},
   1541                                                   {22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22},
   1542                                                   {23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23}};
   1543     static const char* const text2 = "\\u05d0 1-2\\u001c\\u0630 1-2\\u001c1-2";
   1544     static const UBiDiLevel levels2[] = {1,1,2,2,2,0, 1,1,2,1,2,0, 2,2,2};
   1545     static UBiDiLevel myLevels[10] = {0,0,0,0,0,0,0,0,0,0};
   1546     static const UChar multiparaTestString[] = {
   1547         0x5de, 0x5e0, 0x5e1, 0x5d4, 0x20,  0x5e1, 0x5e4, 0x5da,
   1548         0x20,  0xa,   0xa,   0x41,  0x72,  0x74,  0x69,  0x73,
   1549         0x74,  0x3a,  0x20,  0x5de, 0x5e0, 0x5e1, 0x5d4, 0x20,
   1550         0x5e1, 0x5e4, 0x5da, 0x20,  0xa,   0xa,   0x41,  0x6c,
   1551         0x62,  0x75,  0x6d,  0x3a,  0x20,  0x5de, 0x5e0, 0x5e1,
   1552         0x5d4, 0x20,  0x5e1, 0x5e4, 0x5da, 0x20,  0xa,   0xa,
   1553         0x54,  0x69,  0x6d,  0x65,  0x3a,  0x20,  0x32,  0x3a,
   1554         0x32,  0x37,  0xa,  0xa
   1555     };
   1556     static const UBiDiLevel multiparaTestLevels[] = {
   1557         1, 1, 1, 1, 1, 1, 1, 1,
   1558         1, 1, 0, 0, 0, 0, 0, 0,
   1559         0, 0, 0, 1, 1, 1, 1, 1,
   1560         1, 1, 1, 0, 0, 0, 0, 0,
   1561         0, 0, 0, 0, 0, 1, 1, 1,
   1562         1, 1, 1, 1, 1, 0, 0, 0,
   1563         0, 0, 0, 0, 0, 0, 0, 0,
   1564         0, 0, 0, 0
   1565     };
   1566     UBiDiLevel gotLevel;
   1567     const UBiDiLevel* gotLevels;
   1568     UBool orderParagraphsLTR;
   1569     UChar src[MAXLEN], dest[MAXLEN];
   1570     UErrorCode errorCode=U_ZERO_ERROR;
   1571     UBiDi* pBidi=ubidi_open();
   1572     UBiDi* pLine;
   1573     int32_t srcSize, count, paraStart, paraLimit, paraIndex, length;
   1574     int32_t srcLen, destLen;
   1575     int i, j, k;
   1576 
   1577     log_verbose("\nEntering TestMultipleParagraphs\n\n");
   1578     u_unescape(text, src, MAXLEN);
   1579     srcSize=u_strlen(src);
   1580     ubidi_setPara(pBidi, src, srcSize, UBIDI_LTR, NULL, &errorCode);
   1581     if(U_FAILURE(errorCode)){
   1582         log_err("ubidi_setPara failed, paraLevel=%d, errorCode %s\n",
   1583                 UBIDI_LTR, u_errorName(errorCode));
   1584         ubidi_close(pBidi);
   1585         return;
   1586     }
   1587     /* check paragraph count and boundaries */
   1588     if (paraCount!=(count=ubidi_countParagraphs(pBidi))) {
   1589         log_err("ubidi_countParagraphs returned %d, should be %d\n",
   1590                 count, paraCount);
   1591     }
   1592     for (i=0; i<paraCount; i++) {
   1593         ubidi_getParagraphByIndex(pBidi, i, &paraStart, &paraLimit, NULL, &errorCode);
   1594         if ((paraStart!=paraBounds[i]) || (paraLimit!=paraBounds[i+1])) {
   1595             log_err("Found boundaries of paragraph %d: %d-%d; expected: %d-%d\n",
   1596                     i, paraStart, paraLimit, paraBounds[i], paraBounds[i+1]);
   1597         }
   1598     }
   1599     errorCode=U_ZERO_ERROR;
   1600     /* check with last paragraph not terminated by B */
   1601     src[srcSize-1]='L';
   1602     ubidi_setPara(pBidi, src, srcSize, UBIDI_LTR, NULL, &errorCode);
   1603     if(U_FAILURE(errorCode)){
   1604         log_err("2nd ubidi_setPara failed, paraLevel=%d, errorCode %s\n",
   1605                 UBIDI_LTR, u_errorName(errorCode));
   1606         ubidi_close(pBidi);
   1607         return;
   1608     }
   1609     if (paraCount!=(count=ubidi_countParagraphs(pBidi))) {
   1610         log_err("2nd ubidi_countParagraphs returned %d, should be %d\n",
   1611                 count, paraCount);
   1612     }
   1613     i=paraCount-1;
   1614     ubidi_getParagraphByIndex(pBidi, i, &paraStart, &paraLimit, NULL, &errorCode);
   1615     if ((paraStart!=paraBounds[i]) || (paraLimit!=paraBounds[i+1])) {
   1616         log_err("2nd Found boundaries of paragraph %d: %d-%d; expected: %d-%d\n",
   1617                 i, paraStart, paraLimit, paraBounds[i], paraBounds[i+1]);
   1618     }
   1619     errorCode=U_ZERO_ERROR;
   1620     /* check paraLevel for all paragraphs under various paraLevel specs */
   1621     for (k=0; k<6; k++) {
   1622         ubidi_setPara(pBidi, src, srcSize, paraLevels[k], NULL, &errorCode);
   1623         for (i=0; i<paraCount; i++) {
   1624             paraIndex=ubidi_getParagraph(pBidi, paraBounds[i], NULL, NULL, &gotLevel, &errorCode);
   1625             if (paraIndex!=i) {
   1626                 log_err("For paraLevel=%d paragraph=%d, found paragraph index=%d expected=%d\n",
   1627                         paraLevels[k], i, paraIndex, i);
   1628             }
   1629             if (gotLevel!=multiLevels[k][i]) {
   1630                 log_err("For paraLevel=%d paragraph=%d, found level=%d expected %d\n",
   1631                         paraLevels[k], i, gotLevel, multiLevels[k][i]);
   1632             }
   1633         }
   1634         gotLevel=ubidi_getParaLevel(pBidi);
   1635         if (gotLevel!=multiLevels[k][0]) {
   1636             log_err("For paraLevel=%d getParaLevel=%d, expected %d\n",
   1637                     paraLevels[k], gotLevel, multiLevels[k][0]);
   1638         }
   1639     }
   1640     errorCode=U_ZERO_ERROR;
   1641     /* check that the result of ubidi_getParaLevel changes if the first
   1642      * paragraph has a different level
   1643      */
   1644     src[0]=0x05d2;                      /* Hebrew letter Gimel */
   1645     ubidi_setPara(pBidi, src, srcSize, UBIDI_DEFAULT_LTR, NULL, &errorCode);
   1646     gotLevel=ubidi_getParaLevel(pBidi);
   1647     if (gotLevel!=UBIDI_RTL) {
   1648         log_err("For paraLevel=UBIDI_DEFAULT_LTR getParaLevel=%d, expected=%d\n",
   1649                         gotLevel, UBIDI_RTL);
   1650     }
   1651     errorCode=U_ZERO_ERROR;
   1652     /* check that line cannot overlap paragraph boundaries */
   1653     pLine=ubidi_open();
   1654     i=paraBounds[1];
   1655     k=paraBounds[2]+1;
   1656     ubidi_setLine(pBidi, i, k, pLine, &errorCode);
   1657     if (U_SUCCESS(errorCode)) {
   1658         log_err("For line limits %d-%d got success %s\n",
   1659                 i, k, u_errorName(errorCode));
   1660     }
   1661     errorCode=U_ZERO_ERROR;
   1662     i=paraBounds[1];
   1663     k=paraBounds[2];
   1664     ubidi_setLine(pBidi, i, k, pLine, &errorCode);
   1665     if (U_FAILURE(errorCode)) {
   1666         log_err("For line limits %d-%d got error %s\n",
   1667                 i, k, u_errorName(errorCode));
   1668         errorCode=U_ZERO_ERROR;
   1669     }
   1670     /* check level of block separator at end of paragraph when orderParagraphsLTR==FALSE */
   1671     ubidi_setPara(pBidi, src, srcSize, UBIDI_RTL, NULL, &errorCode);
   1672     /* get levels through para Bidi block */
   1673     gotLevels=ubidi_getLevels(pBidi, &errorCode);
   1674     if (U_FAILURE(errorCode)) {
   1675         log_err("Error on Para getLevels %s\n", u_errorName(errorCode));
   1676         ubidi_close(pLine);
   1677         ubidi_close(pBidi);
   1678         return;
   1679     }
   1680     for (i=26; i<32; i++) {
   1681         if (gotLevels[i]!=UBIDI_RTL) {
   1682             log_err("For char %d(%04x), level=%d, expected=%d\n",
   1683                     i, src[i], gotLevels[i], UBIDI_RTL);
   1684         }
   1685     }
   1686     /* get levels through para Line block */
   1687     i=paraBounds[1];
   1688     k=paraBounds[2];
   1689     ubidi_setLine(pBidi, i, k, pLine, &errorCode);
   1690     if (U_FAILURE(errorCode)) {
   1691         log_err("For line limits %d-%d got error %s\n",
   1692                 i, k, u_errorName(errorCode));
   1693         ubidi_close(pLine);
   1694         ubidi_close(pBidi);
   1695         return;
   1696     }
   1697     paraIndex=ubidi_getParagraph(pLine, i, &paraStart, &paraLimit, &gotLevel, &errorCode);
   1698     gotLevels=ubidi_getLevels(pLine, &errorCode);
   1699     if (U_FAILURE(errorCode)) {
   1700         log_err("Error on Line getLevels %s\n", u_errorName(errorCode));
   1701         ubidi_close(pLine);
   1702         ubidi_close(pBidi);
   1703         return;
   1704     }
   1705     length=ubidi_getLength(pLine);
   1706     if ((gotLevel!=UBIDI_RTL) || (gotLevels[length-1]!=UBIDI_RTL)) {
   1707         log_err("For paragraph %d with limits %d-%d, paraLevel=%d expected=%d, "
   1708                 "level of separator=%d expected=%d\n",
   1709                 paraIndex, paraStart, paraLimit, gotLevel, UBIDI_RTL, gotLevels[length-1], UBIDI_RTL);
   1710     }
   1711     orderParagraphsLTR=ubidi_isOrderParagraphsLTR(pBidi);
   1712     if (orderParagraphsLTR) {
   1713         log_err("Found orderParagraphsLTR=%d expected=%d\n", orderParagraphsLTR, FALSE);
   1714     }
   1715     ubidi_orderParagraphsLTR(pBidi, TRUE);
   1716     orderParagraphsLTR=ubidi_isOrderParagraphsLTR(pBidi);
   1717     if (!orderParagraphsLTR) {
   1718         log_err("Found orderParagraphsLTR=%d expected=%d\n", orderParagraphsLTR, TRUE);
   1719     }
   1720     /* check level of block separator at end of paragraph when orderParagraphsLTR==TRUE */
   1721     ubidi_setPara(pBidi, src, srcSize, UBIDI_RTL, NULL, &errorCode);
   1722     /* get levels through para Bidi block */
   1723     gotLevels=ubidi_getLevels(pBidi, &errorCode);
   1724     for (i=26; i<32; i++) {
   1725         if (gotLevels[i]!=0) {
   1726             log_err("For char %d(%04x), level=%d, expected=%d\n",
   1727                     i, src[i], gotLevels[i], 0);
   1728         }
   1729     }
   1730     errorCode=U_ZERO_ERROR;
   1731     /* get levels through para Line block */
   1732     i=paraBounds[1];
   1733     k=paraBounds[2];
   1734     ubidi_setLine(pBidi, paraStart, paraLimit, pLine, &errorCode);
   1735     paraIndex=ubidi_getParagraph(pLine, i, &paraStart, &paraLimit, &gotLevel, &errorCode);
   1736     gotLevels=ubidi_getLevels(pLine, &errorCode);
   1737     length=ubidi_getLength(pLine);
   1738     if ((gotLevel!=UBIDI_RTL) || (gotLevels[length-1]!=0)) {
   1739         log_err("For paragraph %d with limits %d-%d, paraLevel=%d expected=%d, "
   1740                 "level of separator=%d expected=%d\n",
   1741                 paraIndex, paraStart, paraLimit, gotLevel, UBIDI_RTL, gotLevels[length-1], 0);
   1742         log_verbose("levels=");
   1743         for (count=0; count<length; count++) {
   1744             log_verbose(" %d", gotLevels[count]);
   1745         }
   1746         log_verbose("\n");
   1747     }
   1748 
   1749     /* test that the concatenation of separate invocations of the bidi code
   1750      * on each individual paragraph in order matches the levels array that
   1751      * results from invoking bidi once over the entire multiparagraph tests
   1752      * (with orderParagraphsLTR false, of course)
   1753      */
   1754     u_unescape(text, src, MAXLEN);      /* restore original content */
   1755     srcSize=u_strlen(src);
   1756     ubidi_orderParagraphsLTR(pBidi, FALSE);
   1757     ubidi_setPara(pBidi, src, srcSize, UBIDI_DEFAULT_RTL, NULL, &errorCode);
   1758     gotLevels=ubidi_getLevels(pBidi, &errorCode);
   1759     for (i=0; i<paraCount; i++) {
   1760         /* use pLine for individual paragraphs */
   1761         paraStart = paraBounds[i];
   1762         length = paraBounds[i+1] - paraStart;
   1763         ubidi_setPara(pLine, src+paraStart, length, UBIDI_DEFAULT_RTL, NULL, &errorCode);
   1764         for (j=0; j<length; j++) {
   1765             if ((k=ubidi_getLevelAt(pLine, j)) != (gotLevel=gotLevels[paraStart+j])) {
   1766                 log_err("Checking paragraph concatenation: for paragraph=%d, "
   1767                         "char=%d(%04x), level=%d, expected=%d\n",
   1768                         i, j, src[paraStart+j], k, gotLevel);
   1769             }
   1770         }
   1771     }
   1772 
   1773     /* ensure that leading numerics in a paragraph are not treated as arabic
   1774        numerals because of arabic text in a preceding paragraph
   1775      */
   1776     u_unescape(text2, src, MAXLEN);
   1777     srcSize=u_strlen(src);
   1778     ubidi_orderParagraphsLTR(pBidi, TRUE);
   1779     ubidi_setPara(pBidi, src, srcSize, UBIDI_RTL, NULL, &errorCode);
   1780     gotLevels=ubidi_getLevels(pBidi, &errorCode);
   1781     if (U_FAILURE(errorCode)) {
   1782         log_err("Can't get levels. %s\n", u_errorName(errorCode));
   1783         return;
   1784     }
   1785     for (i=0; i<srcSize; i++) {
   1786         if (gotLevels[i]!=levels2[i]) {
   1787             log_err("Checking leading numerics: for char %d(%04x), level=%d, expected=%d\n",
   1788                     i, src[i], gotLevels[i], levels2[i]);
   1789         }
   1790     }
   1791 
   1792     /* check handling of whitespace before end of paragraph separator when
   1793      * orderParagraphsLTR==TRUE, when last paragraph has, and lacks, a terminating B
   1794      */
   1795     u_memset(src, 0x0020, MAXLEN);
   1796     srcSize = 5;
   1797     ubidi_orderParagraphsLTR(pBidi, TRUE);
   1798     for (i=0x001c; i<=0x0020; i+=(0x0020-0x001c)) {
   1799         src[4]=(UChar)i;                /* with and without terminating B */
   1800         for (j=0x0041; j<=0x05d0; j+=(0x05d0-0x0041)) {
   1801             src[0]=(UChar)j;            /* leading 'A' or Alef */
   1802             for (gotLevel=4; gotLevel<=5; gotLevel++) {
   1803                 /* test even and odd paraLevel */
   1804                 ubidi_setPara(pBidi, src, srcSize, gotLevel, NULL, &errorCode);
   1805                 gotLevels=ubidi_getLevels(pBidi, &errorCode);
   1806                 for (k=1; k<=3; k++) {
   1807                     if (gotLevels[k]!=gotLevel) {
   1808                         log_err("Checking trailing spaces: for leading_char=%04x, "
   1809                                 "last_char=%04x, index=%d, level=%d, expected=%d\n",
   1810                                 src[0], src[4], k, gotLevels[k], gotLevel);
   1811                     }
   1812                 }
   1813             }
   1814         }
   1815     }
   1816 
   1817     /* check default orientation when inverse bidi and paragraph starts
   1818      * with LTR strong char and ends with RTL strong char, with and without
   1819      * a terminating B
   1820      */
   1821     ubidi_setReorderingMode(pBidi, UBIDI_REORDER_INVERSE_LIKE_DIRECT);
   1822     srcLen = u_unescape("abc \\u05d2\\u05d1\n", src, MAXLEN);
   1823     ubidi_setPara(pBidi, src, srcLen, UBIDI_DEFAULT_LTR, NULL, &errorCode);
   1824     destLen = ubidi_writeReordered(pBidi, dest, MAXLEN, 0, &errorCode);
   1825     srcLen = u_unescape("\\u05d1\\u05d2 abc\n", src, MAXLEN);
   1826     if (memcmp(src, dest, destLen * sizeof(UChar))) {
   1827         log_err("\nInvalid output #0, should be '%s', got '%s'\n",
   1828                 aescstrdup(src, srcLen), aescstrdup(dest, destLen));
   1829     }
   1830     srcLen = u_unescape("abc \\u05d2\\u05d1", src, MAXLEN);
   1831     ubidi_setPara(pBidi, src, srcLen, UBIDI_DEFAULT_LTR, NULL, &errorCode);
   1832     destLen = ubidi_writeReordered(pBidi, dest, MAXLEN, 0, &errorCode);
   1833     srcLen = u_unescape("\\u05d1\\u05d2 abc", src, MAXLEN);
   1834     if (memcmp(src, dest, destLen * sizeof(UChar))) {
   1835         log_err("\nInvalid output #1, should be '%s', got '%s'\n",
   1836                 aescstrdup(src, srcLen), aescstrdup(dest, destLen));
   1837     }
   1838 
   1839     /* check multiple paragraphs together with explicit levels
   1840      */
   1841     ubidi_setReorderingMode(pBidi, UBIDI_REORDER_DEFAULT);
   1842     srcLen = u_unescape("ab\\u05d1\\u05d2\n\\u05d3\\u05d4123", src, MAXLEN);
   1843     ubidi_setPara(pBidi, src, srcLen, UBIDI_LTR, myLevels, &errorCode);
   1844     destLen = ubidi_writeReordered(pBidi, dest, MAXLEN, 0, &errorCode);
   1845     srcLen = u_unescape("ab\\u05d2\\u05d1\\n123\\u05d4\\u05d3", src, MAXLEN);
   1846     if (memcmp(src, dest, destLen * sizeof(UChar))) {
   1847         log_err("\nInvalid output #2, should be '%s', got '%s'\n",
   1848                 aescstrdup(src, srcLen), aescstrdup(dest, destLen));
   1849     }
   1850     count = ubidi_countParagraphs(pBidi);
   1851     if (count != 2) {
   1852         log_err("\nInvalid number of paras, should be 2, got %d\n", count);
   1853     }
   1854 
   1855     ubidi_close(pLine);
   1856     ubidi_close(pBidi);
   1857     log_verbose("\nExiting TestMultipleParagraphs\n\n");
   1858 
   1859     /* check levels in multiple paragraphs with default para level
   1860      */
   1861     pBidi = ubidi_open();
   1862     errorCode = U_ZERO_ERROR;
   1863     ubidi_setPara(pBidi, multiparaTestString, LENGTHOF(multiparaTestString),
   1864                   UBIDI_DEFAULT_LTR, NULL, &errorCode);
   1865     if (U_FAILURE(errorCode)) {
   1866         log_err("ubidi_setPara failed for multiparaTestString\n");
   1867         ubidi_close(pBidi);
   1868         return;
   1869     }
   1870     gotLevels = ubidi_getLevels(pBidi, &errorCode);
   1871     if (U_FAILURE(errorCode)) {
   1872         log_err("ubidi_getLevels failed for multiparaTestString\n");
   1873         ubidi_close(pBidi);
   1874         return;
   1875     }
   1876     for (i = 0; i < LENGTHOF(multiparaTestString); i++) {
   1877         if (gotLevels[i] != multiparaTestLevels[i]) {
   1878             log_err("Error on level for multiparaTestString at index %d, "
   1879                     "expected=%d, actual=%d\n",
   1880                     i, multiparaTestLevels[i], gotLevels[i]);
   1881         }
   1882     }
   1883     ubidi_close(pBidi);
   1884 
   1885 }
   1886 
   1887 
   1888 /* inverse BiDi ------------------------------------------------------------- */
   1889 
   1890 static int countRoundtrips=0, countNonRoundtrips=0;
   1891 
   1892 #define STRING_TEST_CASE(s) { (s), LENGTHOF(s) }
   1893 
   1894 static void
   1895 testInverse(void) {
   1896     static const UChar
   1897         string0[]={ 0x6c, 0x61, 0x28, 0x74, 0x69, 0x6e, 0x20, 0x5d0, 0x5d1, 0x29, 0x5d2, 0x5d3 },
   1898         string1[]={ 0x6c, 0x61, 0x74, 0x20, 0x5d0, 0x5d1, 0x5d2, 0x20, 0x31, 0x32, 0x33 },
   1899         string2[]={ 0x6c, 0x61, 0x74, 0x20, 0x5d0, 0x28, 0x5d1, 0x5d2, 0x20, 0x31, 0x29, 0x32, 0x33 },
   1900         string3[]={ 0x31, 0x32, 0x33, 0x20, 0x5d0, 0x5d1, 0x5d2, 0x20, 0x34, 0x35, 0x36 },
   1901         string4[]={ 0x61, 0x62, 0x20, 0x61, 0x62, 0x20, 0x661, 0x662 };
   1902 
   1903     static const struct {
   1904         const UChar *s;
   1905         int32_t length;
   1906     } testCases[]={
   1907         STRING_TEST_CASE(string0),
   1908         STRING_TEST_CASE(string1),
   1909         STRING_TEST_CASE(string2),
   1910         STRING_TEST_CASE(string3),
   1911         STRING_TEST_CASE(string4)
   1912     };
   1913 
   1914     UBiDi *pBiDi;
   1915     UErrorCode errorCode;
   1916     int i;
   1917 
   1918     log_verbose("\nEntering TestInverse\n\n");
   1919     pBiDi=ubidi_open();
   1920     if(pBiDi==NULL) {
   1921         log_err("unable to open a UBiDi object (out of memory)\n");
   1922         return;
   1923     }
   1924 
   1925     log_verbose("inverse Bidi: testInverse(L) with %u test cases ---\n", LENGTHOF(testCases));
   1926      for(i=0; i<LENGTHOF(testCases); ++i) {
   1927         log_verbose("Testing case %d\n", i);
   1928         errorCode=U_ZERO_ERROR;
   1929         _testInverseBidi(pBiDi, testCases[i].s, testCases[i].length, 0, &errorCode);
   1930     }
   1931 
   1932     log_verbose("inverse Bidi: testInverse(R) with %u test cases ---\n", LENGTHOF(testCases));
   1933     for(i=0; i<LENGTHOF(testCases); ++i) {
   1934         log_verbose("Testing case %d\n", i);
   1935         errorCode=U_ZERO_ERROR;
   1936         _testInverseBidi(pBiDi, testCases[i].s, testCases[i].length, 1, &errorCode);
   1937     }
   1938 
   1939     _testManyInverseBidi(pBiDi, 0);
   1940     _testManyInverseBidi(pBiDi, 1);
   1941 
   1942     ubidi_close(pBiDi);
   1943 
   1944     log_verbose("inverse Bidi: rountrips: %5u\nnon-roundtrips: %5u\n", countRoundtrips, countNonRoundtrips);
   1945 
   1946     _testWriteReverse();
   1947 
   1948     _testManyAddedPoints();
   1949 
   1950     _testMisc();
   1951 
   1952     log_verbose("\nExiting TestInverse\n\n");
   1953 }
   1954 
   1955 #define COUNT_REPEAT_SEGMENTS 6
   1956 
   1957 static const UChar repeatSegments[COUNT_REPEAT_SEGMENTS][2]={
   1958     { 0x61, 0x62 },     /* L */
   1959     { 0x5d0, 0x5d1 },   /* R */
   1960     { 0x627, 0x628 },   /* AL */
   1961     { 0x31, 0x32 },     /* EN */
   1962     { 0x661, 0x662 },   /* AN */
   1963     { 0x20, 0x20 }      /* WS (N) */
   1964 };
   1965 
   1966 static void
   1967 _testManyInverseBidi(UBiDi *pBiDi, UBiDiLevel direction) {
   1968     UChar text[8]={ 0, 0, 0x20, 0, 0, 0x20, 0, 0 };
   1969     int i, j, k;
   1970     UErrorCode errorCode;
   1971 
   1972     log_verbose("inverse Bidi: testManyInverseBidi(%c) - test permutations of text snippets ---\n",
   1973                  direction==0 ? 'L' : 'R');
   1974     for(i=0; i<COUNT_REPEAT_SEGMENTS; ++i) {
   1975         text[0]=repeatSegments[i][0];
   1976         text[1]=repeatSegments[i][1];
   1977         for(j=0; j<COUNT_REPEAT_SEGMENTS; ++j) {
   1978             text[3]=repeatSegments[j][0];
   1979             text[4]=repeatSegments[j][1];
   1980             for(k=0; k<COUNT_REPEAT_SEGMENTS; ++k) {
   1981                 text[6]=repeatSegments[k][0];
   1982                 text[7]=repeatSegments[k][1];
   1983 
   1984                 errorCode=U_ZERO_ERROR;
   1985                 log_verbose("inverse Bidi: testManyInverseBidi()[%u %u %u]\n", i, j, k);
   1986                 _testInverseBidi(pBiDi, text, 8, direction, &errorCode);
   1987             }
   1988         }
   1989     }
   1990 }
   1991 
   1992 static void
   1993 _testInverseBidi(UBiDi *pBiDi, const UChar *src, int32_t srcLength,
   1994                 UBiDiLevel direction, UErrorCode *pErrorCode) {
   1995     UChar visualLTR[MAXLEN], logicalDest[MAXLEN], visualDest[MAXLEN];
   1996     int32_t ltrLength, logicalLength, visualLength;
   1997 
   1998     if(direction==0) {
   1999         log_verbose("inverse Bidi: testInverse(L)\n");
   2000 
   2001         /* convert visual to logical */
   2002         ubidi_setInverse(pBiDi, TRUE);
   2003         if (!ubidi_isInverse(pBiDi)) {
   2004             log_err("Error while doing ubidi_setInverse(TRUE)\n");
   2005         }
   2006         ubidi_setPara(pBiDi, src, srcLength, 0, NULL, pErrorCode);
   2007         if (src != ubidi_getText(pBiDi)) {
   2008             log_err("Wrong value returned by ubidi_getText\n");
   2009         }
   2010         logicalLength=ubidi_writeReordered(pBiDi, logicalDest, LENGTHOF(logicalDest),
   2011                                            UBIDI_DO_MIRRORING|UBIDI_INSERT_LRM_FOR_NUMERIC, pErrorCode);
   2012         log_verbose("  v ");
   2013         printUnicode(src, srcLength, ubidi_getLevels(pBiDi, pErrorCode));
   2014         log_verbose("\n");
   2015 
   2016         /* convert back to visual LTR */
   2017         ubidi_setInverse(pBiDi, FALSE);
   2018         if (ubidi_isInverse(pBiDi)) {
   2019             log_err("Error while doing ubidi_setInverse(FALSE)\n");
   2020         }
   2021         ubidi_setPara(pBiDi, logicalDest, logicalLength, 0, NULL, pErrorCode);
   2022         visualLength=ubidi_writeReordered(pBiDi, visualDest, LENGTHOF(visualDest),
   2023                                           UBIDI_DO_MIRRORING|UBIDI_REMOVE_BIDI_CONTROLS, pErrorCode);
   2024     } else {
   2025         log_verbose("inverse Bidi: testInverse(R)\n");
   2026 
   2027         /* reverse visual from RTL to LTR */
   2028         ltrLength=ubidi_writeReverse(src, srcLength, visualLTR, LENGTHOF(visualLTR), 0, pErrorCode);
   2029         log_verbose("  vr");
   2030         printUnicode(src, srcLength, NULL);
   2031         log_verbose("\n");
   2032 
   2033         /* convert visual RTL to logical */
   2034         ubidi_setInverse(pBiDi, TRUE);
   2035         ubidi_setPara(pBiDi, visualLTR, ltrLength, 0, NULL, pErrorCode);
   2036         logicalLength=ubidi_writeReordered(pBiDi, logicalDest, LENGTHOF(logicalDest),
   2037                                            UBIDI_DO_MIRRORING|UBIDI_INSERT_LRM_FOR_NUMERIC, pErrorCode);
   2038         log_verbose("  vl");
   2039         printUnicode(visualLTR, ltrLength, ubidi_getLevels(pBiDi, pErrorCode));
   2040         log_verbose("\n");
   2041 
   2042         /* convert back to visual RTL */
   2043         ubidi_setInverse(pBiDi, FALSE);
   2044         ubidi_setPara(pBiDi, logicalDest, logicalLength, 0, NULL, pErrorCode);
   2045         visualLength=ubidi_writeReordered(pBiDi, visualDest, LENGTHOF(visualDest),
   2046                                           UBIDI_DO_MIRRORING|UBIDI_REMOVE_BIDI_CONTROLS|UBIDI_OUTPUT_REVERSE, pErrorCode);
   2047     }
   2048     log_verbose("  l ");
   2049     printUnicode(logicalDest, logicalLength, ubidi_getLevels(pBiDi, pErrorCode));
   2050     log_verbose("\n");
   2051     log_verbose("  v ");
   2052     printUnicode(visualDest, visualLength, NULL);
   2053     log_verbose("\n");
   2054 
   2055     /* check and print results */
   2056     if(U_FAILURE(*pErrorCode)) {
   2057         log_err("inverse BiDi: *** error %s\n"
   2058                 "                 turn on verbose mode to see details\n", u_errorName(*pErrorCode));
   2059     } else if(srcLength==visualLength && memcmp(src, visualDest, srcLength*U_SIZEOF_UCHAR)==0) {
   2060         ++countRoundtrips;
   2061         log_verbose(" + roundtripped\n");
   2062     } else {
   2063         ++countNonRoundtrips;
   2064         log_verbose(" * did not roundtrip\n");
   2065         log_err("inverse BiDi: transformation visual->logical->visual did not roundtrip the text;\n"
   2066                 "                 turn on verbose mode to see details\n");
   2067     }
   2068 }
   2069 
   2070 static void
   2071 _testWriteReverse(void) {
   2072     /* U+064e and U+0650 are combining marks (Mn) */
   2073     static const UChar forward[]={
   2074         0x200f, 0x627, 0x64e, 0x650, 0x20, 0x28, 0x31, 0x29
   2075     }, reverseKeepCombining[]={
   2076         0x29, 0x31, 0x28, 0x20, 0x627, 0x64e, 0x650, 0x200f
   2077     }, reverseRemoveControlsKeepCombiningDoMirror[]={
   2078         0x28, 0x31, 0x29, 0x20, 0x627, 0x64e, 0x650
   2079     };
   2080     UChar reverse[10];
   2081     UErrorCode errorCode;
   2082     int32_t length;
   2083 
   2084     /* test ubidi_writeReverse() with "interesting" options */
   2085     errorCode=U_ZERO_ERROR;
   2086     length=ubidi_writeReverse(forward, LENGTHOF(forward),
   2087                               reverse, LENGTHOF(reverse),
   2088                               UBIDI_KEEP_BASE_COMBINING,
   2089                               &errorCode);
   2090     if(U_FAILURE(errorCode) || length!=LENGTHOF(reverseKeepCombining) || memcmp(reverse, reverseKeepCombining, length*U_SIZEOF_UCHAR)!=0) {
   2091         log_err("failure in ubidi_writeReverse(UBIDI_KEEP_BASE_COMBINING): length=%d (should be %d), error code %s\n",
   2092                 length, LENGTHOF(reverseKeepCombining), u_errorName(errorCode));
   2093     }
   2094 
   2095     memset(reverse, 0xa5, LENGTHOF(reverse)*U_SIZEOF_UCHAR);
   2096     errorCode=U_ZERO_ERROR;
   2097     length=ubidi_writeReverse(forward, LENGTHOF(forward),
   2098                               reverse, LENGTHOF(reverse),
   2099                               UBIDI_REMOVE_BIDI_CONTROLS|UBIDI_DO_MIRRORING|UBIDI_KEEP_BASE_COMBINING,
   2100                               &errorCode);
   2101     if(U_FAILURE(errorCode) || length!=LENGTHOF(reverseRemoveControlsKeepCombiningDoMirror) || memcmp(reverse, reverseRemoveControlsKeepCombiningDoMirror, length*U_SIZEOF_UCHAR)!=0) {
   2102         log_err("failure in ubidi_writeReverse(UBIDI_REMOVE_BIDI_CONTROLS|UBIDI_DO_MIRRORING|UBIDI_KEEP_BASE_COMBINING):\n"
   2103                 "    length=%d (should be %d), error code %s\n",
   2104                 length, LENGTHOF(reverseRemoveControlsKeepCombiningDoMirror), u_errorName(errorCode));
   2105     }
   2106 }
   2107 
   2108 static void _testManyAddedPoints(void) {
   2109     UErrorCode errorCode = U_ZERO_ERROR;
   2110     UBiDi *bidi = ubidi_open();
   2111     UChar text[90], dest[MAXLEN], expected[120];
   2112     int destLen, i;
   2113     for (i = 0; i < LENGTHOF(text); i+=3) {
   2114         text[i] = 0x0061; /* 'a' */
   2115         text[i+1] = 0x05d0;
   2116         text[i+2] = 0x0033; /* '3' */
   2117     }
   2118     ubidi_setReorderingMode(bidi, UBIDI_REORDER_INVERSE_LIKE_DIRECT);
   2119     ubidi_setReorderingOptions(bidi, UBIDI_OPTION_INSERT_MARKS);
   2120     ubidi_setPara(bidi, text, LENGTHOF(text), UBIDI_LTR, NULL, &errorCode);
   2121     destLen = ubidi_writeReordered(bidi, dest, MAXLEN, 0, &errorCode);
   2122     for (i = 0; i < LENGTHOF(expected); i+=4) {
   2123         expected[i] = 0x0061; /* 'a' */
   2124         expected[i+1] = 0x05d0;
   2125         expected[i+2] = 0x200e;
   2126         expected[i+3] = 0x0033; /* '3' */
   2127     }
   2128     if (memcmp(dest, expected, destLen * sizeof(UChar))) {
   2129         log_err("\nInvalid output with many added points, "
   2130                 "expected '%s', got '%s'\n",
   2131                 aescstrdup(expected, LENGTHOF(expected)),
   2132                 aescstrdup(dest, destLen));
   2133     }
   2134     ubidi_close(bidi);
   2135 }
   2136 
   2137 static void _testMisc(void) {
   2138     UErrorCode errorCode = U_ZERO_ERROR;
   2139     UBiDi *bidi = ubidi_open();
   2140     UChar src[3], dest[MAXLEN], expected[5];
   2141     int destLen;
   2142     ubidi_setInverse(bidi, TRUE);
   2143     src[0] = src[1] = src[2] = 0x0020;
   2144     ubidi_setPara(bidi, src, LENGTHOF(src), UBIDI_RTL, NULL, &errorCode);
   2145     destLen = ubidi_writeReordered(bidi, dest, MAXLEN,
   2146               UBIDI_OUTPUT_REVERSE | UBIDI_INSERT_LRM_FOR_NUMERIC,
   2147               &errorCode);
   2148     u_unescape("\\u200f   \\u200f", expected, 5);
   2149     if (memcmp(dest, expected, destLen * sizeof(UChar))) {
   2150         log_err("\nInvalid output with RLM at both sides, "
   2151                 "expected '%s', got '%s'\n",
   2152                 aescstrdup(expected, LENGTHOF(expected)),
   2153                 aescstrdup(dest, destLen));
   2154     }
   2155     ubidi_close(bidi);
   2156 }
   2157 
   2158 /* arabic shaping ----------------------------------------------------------- */
   2159 
   2160 static void
   2161 doArabicShapingTest(void) {
   2162     static const UChar
   2163     source[]={
   2164         0x31,   /* en:1 */
   2165         0x627,  /* arabic:alef */
   2166         0x32,   /* en:2 */
   2167         0x6f3,  /* an:3 */
   2168         0x61,   /* latin:a */
   2169         0x34,   /* en:4 */
   2170         0
   2171     }, en2an[]={
   2172         0x661, 0x627, 0x662, 0x6f3, 0x61, 0x664, 0
   2173     }, an2en[]={
   2174         0x31, 0x627, 0x32, 0x33, 0x61, 0x34, 0
   2175     }, logical_alen2an_init_lr[]={
   2176         0x31, 0x627, 0x662, 0x6f3, 0x61, 0x34, 0
   2177     }, logical_alen2an_init_al[]={
   2178         0x6f1, 0x627, 0x6f2, 0x6f3, 0x61, 0x34, 0
   2179     }, reverse_alen2an_init_lr[]={
   2180         0x661, 0x627, 0x32, 0x6f3, 0x61, 0x34, 0
   2181     }, reverse_alen2an_init_al[]={
   2182         0x6f1, 0x627, 0x32, 0x6f3, 0x61, 0x6f4, 0
   2183     };
   2184     UChar dest[8];
   2185     UErrorCode errorCode;
   2186     int32_t length;
   2187 
   2188     /* test number shaping */
   2189 
   2190     /* european->arabic */
   2191     errorCode=U_ZERO_ERROR;
   2192     length=u_shapeArabic(source, LENGTHOF(source),
   2193                          dest, LENGTHOF(dest),
   2194                          U_SHAPE_DIGITS_EN2AN|U_SHAPE_DIGIT_TYPE_AN,
   2195                          &errorCode);
   2196     if(U_FAILURE(errorCode) || length!=LENGTHOF(source) || memcmp(dest, en2an, length*U_SIZEOF_UCHAR)!=0) {
   2197         log_err("failure in u_shapeArabic(en2an)\n");
   2198     }
   2199 
   2200     /* arabic->european */
   2201     errorCode=U_ZERO_ERROR;
   2202     length=u_shapeArabic(source, -1,
   2203                          dest, LENGTHOF(dest),
   2204                          U_SHAPE_DIGITS_AN2EN|U_SHAPE_DIGIT_TYPE_AN_EXTENDED,
   2205                          &errorCode);
   2206     if(U_FAILURE(errorCode) || length!=u_strlen(source) || memcmp(dest, an2en, length*U_SIZEOF_UCHAR)!=0) {
   2207         log_err("failure in u_shapeArabic(an2en)\n");
   2208     }
   2209 
   2210     /* european->arabic with context, logical order, initial state not AL */
   2211     errorCode=U_ZERO_ERROR;
   2212     length=u_shapeArabic(source, LENGTHOF(source),
   2213                          dest, LENGTHOF(dest),
   2214                          U_SHAPE_DIGITS_ALEN2AN_INIT_LR|U_SHAPE_DIGIT_TYPE_AN,
   2215                          &errorCode);
   2216     if(U_FAILURE(errorCode) || length!=LENGTHOF(source) || memcmp(dest, logical_alen2an_init_lr, length*U_SIZEOF_UCHAR)!=0) {
   2217         log_err("failure in u_shapeArabic(logical_alen2an_init_lr)\n");
   2218     }
   2219 
   2220     /* european->arabic with context, logical order, initial state AL */
   2221     errorCode=U_ZERO_ERROR;
   2222     length=u_shapeArabic(source, LENGTHOF(source),
   2223                          dest, LENGTHOF(dest),
   2224                          U_SHAPE_DIGITS_ALEN2AN_INIT_AL|U_SHAPE_DIGIT_TYPE_AN_EXTENDED,
   2225                          &errorCode);
   2226     if(U_FAILURE(errorCode) || length!=LENGTHOF(source) || memcmp(dest, logical_alen2an_init_al, length*U_SIZEOF_UCHAR)!=0) {
   2227         log_err("failure in u_shapeArabic(logical_alen2an_init_al)\n");
   2228     }
   2229 
   2230     /* european->arabic with context, reverse order, initial state not AL */
   2231     errorCode=U_ZERO_ERROR;
   2232     length=u_shapeArabic(source, LENGTHOF(source),
   2233                          dest, LENGTHOF(dest),
   2234                          U_SHAPE_DIGITS_ALEN2AN_INIT_LR|U_SHAPE_DIGIT_TYPE_AN|U_SHAPE_TEXT_DIRECTION_VISUAL_LTR,
   2235                          &errorCode);
   2236     if(U_FAILURE(errorCode) || length!=LENGTHOF(source) || memcmp(dest, reverse_alen2an_init_lr, length*U_SIZEOF_UCHAR)!=0) {
   2237         log_err("failure in u_shapeArabic(reverse_alen2an_init_lr)\n");
   2238     }
   2239 
   2240     /* european->arabic with context, reverse order, initial state AL */
   2241     errorCode=U_ZERO_ERROR;
   2242     length=u_shapeArabic(source, LENGTHOF(source),
   2243                          dest, LENGTHOF(dest),
   2244                          U_SHAPE_DIGITS_ALEN2AN_INIT_AL|U_SHAPE_DIGIT_TYPE_AN_EXTENDED|U_SHAPE_TEXT_DIRECTION_VISUAL_LTR,
   2245                          &errorCode);
   2246     if(U_FAILURE(errorCode) || length!=LENGTHOF(source) || memcmp(dest, reverse_alen2an_init_al, length*U_SIZEOF_UCHAR)!=0) {
   2247         log_err("failure in u_shapeArabic(reverse_alen2an_init_al)\n");
   2248     }
   2249 
   2250     /* test noop */
   2251     errorCode=U_ZERO_ERROR;
   2252     length=u_shapeArabic(source, LENGTHOF(source),
   2253                          dest, LENGTHOF(dest),
   2254                          0,
   2255                          &errorCode);
   2256     if(U_FAILURE(errorCode) || length!=LENGTHOF(source) || memcmp(dest, source, length*U_SIZEOF_UCHAR)!=0) {
   2257         log_err("failure in u_shapeArabic(noop)\n");
   2258     }
   2259 
   2260     errorCode=U_ZERO_ERROR;
   2261     length=u_shapeArabic(source, 0,
   2262                          dest, LENGTHOF(dest),
   2263                          U_SHAPE_DIGITS_EN2AN|U_SHAPE_DIGIT_TYPE_AN,
   2264                          &errorCode);
   2265     if(U_FAILURE(errorCode) || length!=0) {
   2266         log_err("failure in u_shapeArabic(en2an, sourceLength=0), returned %d/%s\n", u_errorName(errorCode), LENGTHOF(source));
   2267     }
   2268 
   2269     /* preflight digit shaping */
   2270     errorCode=U_ZERO_ERROR;
   2271     length=u_shapeArabic(source, LENGTHOF(source),
   2272                          NULL, 0,
   2273                          U_SHAPE_DIGITS_EN2AN|U_SHAPE_DIGIT_TYPE_AN,
   2274                          &errorCode);
   2275     if(errorCode!=U_BUFFER_OVERFLOW_ERROR || length!=LENGTHOF(source)) {
   2276         log_err("failure in u_shapeArabic(en2an preflighting), returned %d/%s instead of %d/U_BUFFER_OVERFLOW_ERROR\n",
   2277                 length, u_errorName(errorCode), LENGTHOF(source));
   2278     }
   2279 
   2280     /* test illegal arguments */
   2281     errorCode=U_ZERO_ERROR;
   2282     length=u_shapeArabic(NULL, LENGTHOF(source),
   2283                          dest, LENGTHOF(dest),
   2284                          U_SHAPE_DIGITS_EN2AN|U_SHAPE_DIGIT_TYPE_AN,
   2285                          &errorCode);
   2286     if(errorCode!=U_ILLEGAL_ARGUMENT_ERROR) {
   2287         log_err("failure in u_shapeArabic(source=NULL), returned %s instead of U_ILLEGAL_ARGUMENT_ERROR\n", u_errorName(errorCode));
   2288     }
   2289 
   2290     errorCode=U_ZERO_ERROR;
   2291     length=u_shapeArabic(source, -2,
   2292                          dest, LENGTHOF(dest),
   2293                          U_SHAPE_DIGITS_EN2AN|U_SHAPE_DIGIT_TYPE_AN,
   2294                          &errorCode);
   2295     if(errorCode!=U_ILLEGAL_ARGUMENT_ERROR) {
   2296         log_err("failure in u_shapeArabic(sourceLength=-2), returned %s instead of U_ILLEGAL_ARGUMENT_ERROR\n", u_errorName(errorCode));
   2297     }
   2298 
   2299     errorCode=U_ZERO_ERROR;
   2300     length=u_shapeArabic(source, LENGTHOF(source),
   2301                          NULL, LENGTHOF(dest),
   2302                          U_SHAPE_DIGITS_EN2AN|U_SHAPE_DIGIT_TYPE_AN,
   2303                          &errorCode);
   2304     if(errorCode!=U_ILLEGAL_ARGUMENT_ERROR) {
   2305         log_err("failure in u_shapeArabic(dest=NULL), returned %s instead of U_ILLEGAL_ARGUMENT_ERROR\n", u_errorName(errorCode));
   2306     }
   2307 
   2308     errorCode=U_ZERO_ERROR;
   2309     length=u_shapeArabic(source, LENGTHOF(source),
   2310                          dest, -1,
   2311                          U_SHAPE_DIGITS_EN2AN|U_SHAPE_DIGIT_TYPE_AN,
   2312                          &errorCode);
   2313     if(errorCode!=U_ILLEGAL_ARGUMENT_ERROR) {
   2314         log_err("failure in u_shapeArabic(destSize=-1), returned %s instead of U_ILLEGAL_ARGUMENT_ERROR\n", u_errorName(errorCode));
   2315     }
   2316 
   2317     errorCode=U_ZERO_ERROR;
   2318     length=u_shapeArabic(source, LENGTHOF(source),
   2319                          dest, LENGTHOF(dest),
   2320                          U_SHAPE_DIGITS_RESERVED|U_SHAPE_DIGIT_TYPE_AN,
   2321                          &errorCode);
   2322     if(errorCode!=U_ILLEGAL_ARGUMENT_ERROR) {
   2323         log_err("failure in u_shapeArabic(U_SHAPE_DIGITS_RESERVED), returned %s instead of U_ILLEGAL_ARGUMENT_ERROR\n", u_errorName(errorCode));
   2324     }
   2325 
   2326     errorCode=U_ZERO_ERROR;
   2327     length=u_shapeArabic(source, LENGTHOF(source),
   2328                          dest, LENGTHOF(dest),
   2329                          U_SHAPE_DIGITS_EN2AN|U_SHAPE_DIGIT_TYPE_RESERVED,
   2330                          &errorCode);
   2331     if(errorCode!=U_ILLEGAL_ARGUMENT_ERROR) {
   2332         log_err("failure in u_shapeArabic(U_SHAPE_DIGIT_TYPE_RESERVED), returned %s instead of U_ILLEGAL_ARGUMENT_ERROR\n", u_errorName(errorCode));
   2333     }
   2334 
   2335     errorCode=U_ZERO_ERROR;
   2336     length=u_shapeArabic(source, LENGTHOF(source),
   2337                          (UChar *)(source+2), LENGTHOF(dest), /* overlap source and destination */
   2338                          U_SHAPE_DIGITS_EN2AN|U_SHAPE_DIGIT_TYPE_AN,
   2339                          &errorCode);
   2340     if(errorCode!=U_ILLEGAL_ARGUMENT_ERROR) {
   2341         log_err("failure in u_shapeArabic(U_SHAPE_DIGIT_TYPE_RESERVED), returned %s instead of U_ILLEGAL_ARGUMENT_ERROR\n", u_errorName(errorCode));
   2342     }
   2343 }
   2344 
   2345 static void
   2346 doLamAlefSpecialVLTRArabicShapingTest(void) {
   2347     static const UChar
   2348     source[]={
   2349 /*a*/   0x20 ,0x646,0x622,0x644,0x627,0x20,
   2350 /*b*/   0x646,0x623,0x64E,0x644,0x627,0x20,
   2351 /*c*/   0x646,0x627,0x670,0x644,0x627,0x20,
   2352 /*d*/   0x646,0x622,0x653,0x644,0x627,0x20,
   2353 /*e*/   0x646,0x625,0x655,0x644,0x627,0x20,
   2354 /*f*/   0x646,0x622,0x654,0x644,0x627,0x20,
   2355 /*g*/   0xFEFC,0x639
   2356     }, shape_near[]={
   2357         0x20,0xfee5,0x20,0xfef5,0xfe8d,0x20,0xfee5,0x20,0xfe76,0xfef7,0xfe8d,0x20,
   2358         0xfee5,0x20,0x670,0xfefb,0xfe8d,0x20,0xfee5,0x20,0x653,0xfef5,0xfe8d,0x20,
   2359         0xfee5,0x20,0x655,0xfef9,0xfe8d,0x20,0xfee5,0x20,0x654,0xfef5,0xfe8d,0x20,
   2360         0xfefc,0xfecb
   2361     }, shape_at_end[]={
   2362         0x20,0xfee5,0xfef5,0xfe8d,0x20,0xfee5,0xfe76,0xfef7,0xfe8d,0x20,0xfee5,0x670,
   2363         0xfefb,0xfe8d,0x20,0xfee5,0x653,0xfef5,0xfe8d,0x20,0xfee5,0x655,0xfef9,0xfe8d,
   2364         0x20,0xfee5,0x654,0xfef5,0xfe8d,0x20,0xfefc,0xfecb,0x20,0x20,0x20,0x20,0x20,0x20
   2365     }, shape_at_begin[]={
   2366         0x20,0x20,0x20,0x20,0x20,0x20,0x20,0xfee5,0xfef5,0xfe8d,0x20,0xfee5,0xfe76,
   2367         0xfef7,0xfe8d,0x20,0xfee5,0x670,0xfefb,0xfe8d,0x20,0xfee5,0x653,0xfef5,0xfe8d,
   2368         0x20,0xfee5,0x655,0xfef9,0xfe8d,0x20,0xfee5,0x654,0xfef5,0xfe8d,0x20,0xfefc,0xfecb
   2369     }, shape_grow_shrink[]={
   2370         0x20,0xfee5,0xfef5,0xfe8d,0x20,0xfee5,0xfe76,0xfef7,0xfe8d,0x20,0xfee5,
   2371         0x670,0xfefb,0xfe8d,0x20,0xfee5,0x653,0xfef5,0xfe8d,0x20,0xfee5,0x655,0xfef9,
   2372         0xfe8d,0x20,0xfee5,0x654,0xfef5,0xfe8d,0x20,0xfefc,0xfecb
   2373     }, shape_excepttashkeel_near[]={
   2374         0x20,0xfee5,0x20,0xfef5,0xfe8d,0x20,0xfee5,0x20,0xfe76,0xfef7,0xfe8d,0x20,
   2375         0xfee5,0x20,0x670,0xfefb,0xfe8d,0x20,0xfee5,0x20,0x653,0xfef5,0xfe8d,0x20,
   2376         0xfee5,0x20,0x655,0xfef9,0xfe8d,0x20,0xfee5,0x20,0x654,0xfef5,0xfe8d,0x20,
   2377         0xfefc,0xfecb
   2378     }, shape_excepttashkeel_at_end[]={
   2379         0x20,0xfee5,0xfef5,0xfe8d,0x20,0xfee5,0xfe76,0xfef7,0xfe8d,0x20,0xfee5,
   2380         0x670,0xfefb,0xfe8d,0x20,0xfee5,0x653,0xfef5,0xfe8d,0x20,0xfee5,0x655,0xfef9,
   2381         0xfe8d,0x20,0xfee5,0x654,0xfef5,0xfe8d,0x20,0xfefc,0xfecb,0x20,0x20,0x20,
   2382         0x20,0x20,0x20
   2383     }, shape_excepttashkeel_at_begin[]={
   2384         0x20,0x20,0x20,0x20,0x20,0x20,0x20,0xfee5,0xfef5,0xfe8d,0x20,0xfee5,0xfe76,
   2385         0xfef7,0xfe8d,0x20,0xfee5,0x670,0xfefb,0xfe8d,0x20,0xfee5,0x653,0xfef5,0xfe8d,
   2386         0x20,0xfee5,0x655,0xfef9,0xfe8d,0x20,0xfee5,0x654,0xfef5,0xfe8d,0x20,0xfefc,0xfecb
   2387     }, shape_excepttashkeel_grow_shrink[]={
   2388         0x20,0xfee5,0xfef5,0xfe8d,0x20,0xfee5,0xfe76,0xfef7,0xfe8d,0x20,0xfee5,0x670,
   2389         0xfefb,0xfe8d,0x20,0xfee5,0x653,0xfef5,0xfe8d,0x20,0xfee5,0x655,0xfef9,0xfe8d,
   2390         0x20,0xfee5,0x654,0xfef5,0xfe8d,0x20,0xfefc,0xfecb
   2391     };
   2392 
   2393     UChar dest[38];
   2394     UErrorCode errorCode;
   2395     int32_t length;
   2396 
   2397     errorCode=U_ZERO_ERROR;
   2398 
   2399     length=u_shapeArabic(source, LENGTHOF(source),
   2400                          dest, LENGTHOF(dest),
   2401                          U_SHAPE_LETTERS_SHAPE|U_SHAPE_LENGTH_FIXED_SPACES_NEAR|
   2402                          U_SHAPE_TEXT_DIRECTION_VISUAL_LTR,
   2403                          &errorCode);
   2404 
   2405     if(U_FAILURE(errorCode) || length!=LENGTHOF(shape_near) || memcmp(dest, shape_near, length*U_SIZEOF_UCHAR)!=0) {
   2406         log_err("failure in u_shapeArabic(LAMALEF shape_near)\n");
   2407     }
   2408 
   2409     errorCode=U_ZERO_ERROR;
   2410 
   2411     length=u_shapeArabic(source, LENGTHOF(source),
   2412                          dest, LENGTHOF(dest),
   2413                          U_SHAPE_LETTERS_SHAPE|U_SHAPE_LENGTH_FIXED_SPACES_AT_END|
   2414                          U_SHAPE_TEXT_DIRECTION_VISUAL_LTR,
   2415                          &errorCode);
   2416 
   2417     if(U_FAILURE(errorCode) || length!=LENGTHOF(shape_at_end) || memcmp(dest, shape_at_end, length*U_SIZEOF_UCHAR)!=0) {
   2418         log_err("failure in u_shapeArabic(LAMALEF shape_at_end)\n");
   2419     }
   2420 
   2421     errorCode=U_ZERO_ERROR;
   2422 
   2423     length=u_shapeArabic(source, LENGTHOF(source),
   2424                          dest, LENGTHOF(dest),
   2425                          U_SHAPE_LETTERS_SHAPE|U_SHAPE_LENGTH_FIXED_SPACES_AT_BEGINNING|
   2426                          U_SHAPE_TEXT_DIRECTION_VISUAL_LTR,
   2427                          &errorCode);
   2428 
   2429     if(U_FAILURE(errorCode) || length!=LENGTHOF(shape_at_begin) || memcmp(dest, shape_at_begin, length*U_SIZEOF_UCHAR)!=0) {
   2430         log_err("failure in u_shapeArabic(LAMALEF shape_at_begin)\n");
   2431     }
   2432 
   2433     errorCode=U_ZERO_ERROR;
   2434 
   2435     length=u_shapeArabic(source, LENGTHOF(source),
   2436                          dest, LENGTHOF(dest),
   2437                          U_SHAPE_LETTERS_SHAPE|U_SHAPE_LENGTH_GROW_SHRINK|
   2438                          U_SHAPE_TEXT_DIRECTION_VISUAL_LTR,
   2439                          &errorCode);
   2440 
   2441     if(U_FAILURE(errorCode) || memcmp(dest, shape_grow_shrink, length*U_SIZEOF_UCHAR)!=0) {
   2442         log_err("failure in u_shapeArabic(LAMALEF shape_grow_shrink)\n");
   2443     }
   2444 
   2445     /* ==================== U_SHAPE_LETTERS_SHAPE_TASHKEEL_ISOLATED ==================== */
   2446 
   2447     errorCode=U_ZERO_ERROR;
   2448 
   2449     length=u_shapeArabic(source, LENGTHOF(source),
   2450                          dest, LENGTHOF(dest),
   2451                          U_SHAPE_LETTERS_SHAPE_TASHKEEL_ISOLATED|U_SHAPE_LENGTH_FIXED_SPACES_NEAR|
   2452                          U_SHAPE_TEXT_DIRECTION_VISUAL_LTR,
   2453                          &errorCode);
   2454 
   2455     if(U_FAILURE(errorCode) || length!=LENGTHOF(shape_excepttashkeel_near) || memcmp(dest, shape_excepttashkeel_near, length*U_SIZEOF_UCHAR)!=0) {
   2456         log_err("failure in u_shapeArabic(LAMALEF shape_excepttashkeel_near)\n");
   2457     }
   2458 
   2459     errorCode=U_ZERO_ERROR;
   2460 
   2461     length=u_shapeArabic(source, LENGTHOF(source),
   2462                          dest, LENGTHOF(dest),
   2463                          U_SHAPE_LETTERS_SHAPE_TASHKEEL_ISOLATED|U_SHAPE_LENGTH_FIXED_SPACES_AT_END|
   2464                          U_SHAPE_TEXT_DIRECTION_VISUAL_LTR,
   2465                          &errorCode);
   2466 
   2467     if(U_FAILURE(errorCode) || length!=LENGTHOF(shape_excepttashkeel_at_end) || memcmp(dest,shape_excepttashkeel_at_end , length*U_SIZEOF_UCHAR)!=0) {
   2468         log_err("failure in u_shapeArabic(LAMALEF shape_excepttashkeel_at_end)\n");
   2469     }
   2470 
   2471     errorCode=U_ZERO_ERROR;
   2472 
   2473     length=u_shapeArabic(source, LENGTHOF(source),
   2474                          dest, LENGTHOF(dest),
   2475                          U_SHAPE_LETTERS_SHAPE_TASHKEEL_ISOLATED|U_SHAPE_LENGTH_FIXED_SPACES_AT_BEGINNING|
   2476                          U_SHAPE_TEXT_DIRECTION_VISUAL_LTR,
   2477                          &errorCode);
   2478 
   2479     if(U_FAILURE(errorCode) || length!=LENGTHOF(shape_excepttashkeel_at_begin) || memcmp(dest, shape_excepttashkeel_at_begin, length*U_SIZEOF_UCHAR)!=0) {
   2480         log_err("failure in u_shapeArabic(LAMALEF shape_excepttashkeel_at_begin)\n");
   2481     }
   2482 
   2483     errorCode=U_ZERO_ERROR;
   2484 
   2485     length=u_shapeArabic(source, LENGTHOF(source),
   2486                          dest, LENGTHOF(dest),
   2487                          U_SHAPE_LETTERS_SHAPE_TASHKEEL_ISOLATED|U_SHAPE_LENGTH_GROW_SHRINK|
   2488                          U_SHAPE_TEXT_DIRECTION_VISUAL_LTR,
   2489                          &errorCode);
   2490 
   2491     if(U_FAILURE(errorCode) || memcmp(dest, shape_excepttashkeel_grow_shrink, length*U_SIZEOF_UCHAR)!=0) {
   2492         log_err("failure in u_shapeArabic(LAMALEF shape_excepttashkeel_grow_shrink)\n");
   2493     }
   2494 }
   2495 
   2496 static void
   2497 doTashkeelSpecialVLTRArabicShapingTest(void) {
   2498     static const UChar
   2499     source[]={
   2500         0x64A,0x628,0x631,0x639,0x20,
   2501         0x64A,0x628,0x651,0x631,0x64E,0x639,0x20,
   2502         0x64C,0x64A,0x628,0x631,0x64F,0x639,0x20,
   2503         0x628,0x670,0x631,0x670,0x639,0x20,
   2504         0x628,0x653,0x631,0x653,0x639,0x20,
   2505         0x628,0x654,0x631,0x654,0x639,0x20,
   2506         0x628,0x655,0x631,0x655,0x639,0x20,
   2507     }, shape_near[]={
   2508         0xfef2,0xfe91,0xfeae,0xfecb,0x20,0xfef2,0xfe91,0xfe7c,0xfeae,0xfe77,0xfecb,
   2509         0x20,0xfe72,0xfef2,0xfe91,0xfeae,0xfe79,0xfecb,0x20,0xfe8f,0x670,0xfeae,0x670,
   2510         0xfecb,0x20,0xfe8f,0x653,0xfeae,0x653,0xfecb,0x20,0xfe8f,0x654,0xfeae,0x654,
   2511         0xfecb,0x20,0xfe8f,0x655,0xfeae,0x655,0xfecb,0x20
   2512     }, shape_excepttashkeel_near[]={
   2513         0xfef2,0xfe91,0xfeae,0xfecb,0x20,0xfef2,0xfe91,0xfe7c,0xfeae,0xfe76,0xfecb,0x20,
   2514         0xfe72,0xfef2,0xfe91,0xfeae,0xfe78,0xfecb,0x20,0xfe8f,0x670,0xfeae,0x670,0xfecb,
   2515         0x20,0xfe8f,0x653,0xfeae,0x653,0xfecb,0x20,0xfe8f,0x654,0xfeae,0x654,0xfecb,0x20,
   2516         0xfe8f,0x655,0xfeae,0x655,0xfecb,0x20
   2517     };
   2518 
   2519     UChar dest[43];
   2520     UErrorCode errorCode;
   2521     int32_t length;
   2522 
   2523     errorCode=U_ZERO_ERROR;
   2524 
   2525     length=u_shapeArabic(source, LENGTHOF(source),
   2526                          dest, LENGTHOF(dest),
   2527                          U_SHAPE_LETTERS_SHAPE|U_SHAPE_LENGTH_FIXED_SPACES_NEAR|
   2528                          U_SHAPE_TEXT_DIRECTION_VISUAL_LTR,
   2529                          &errorCode);
   2530 
   2531     if(U_FAILURE(errorCode) || length!=LENGTHOF(shape_near) || memcmp(dest, shape_near, length*U_SIZEOF_UCHAR)!=0) {
   2532         log_err("failure in u_shapeArabic(TASHKEEL shape_near)\n");
   2533     }
   2534 
   2535     errorCode=U_ZERO_ERROR;
   2536 
   2537     length=u_shapeArabic(source, LENGTHOF(source),
   2538                          dest, LENGTHOF(dest),
   2539                          U_SHAPE_LETTERS_SHAPE_TASHKEEL_ISOLATED|U_SHAPE_LENGTH_FIXED_SPACES_NEAR|
   2540                          U_SHAPE_TEXT_DIRECTION_VISUAL_LTR,
   2541                          &errorCode);
   2542 
   2543     if(U_FAILURE(errorCode) || length!=LENGTHOF(shape_excepttashkeel_near) || memcmp(dest, shape_excepttashkeel_near, length*U_SIZEOF_UCHAR)!=0) {
   2544         log_err("failure in u_shapeArabic(TASHKEEL shape_excepttashkeel_near)\n");
   2545     }
   2546 }
   2547 
   2548 static void
   2549 doLOGICALArabicDeShapingTest(void) {
   2550     static const UChar
   2551     source[]={
   2552         0x0020,0x0020,0x0020,0xFE8D,0xFEF5,0x0020,0xFEE5,0x0020,0xFE8D,0xFEF7,0x0020,
   2553         0xFED7,0xFEFC,0x0020,0xFEE1,0x0020,0xFE8D,0xFEDF,0xFECC,0xFEAE,0xFE91,0xFEF4,
   2554         0xFE94,0x0020,0xFE8D,0xFEDF,0xFEA4,0xFEAE,0xFE93,0x0020,0x0020,0x0020,0x0020
   2555     }, unshape_near[]={
   2556         0x20,0x20,0x20,0x627,0x644,0x622,0x646,0x20,0x627,0x644,0x623,0x642,0x644,0x627,
   2557         0x645,0x20,0x627,0x644,0x639,0x631,0x628,0x64a,0x629,0x20,0x627,0x644,0x62d,0x631,
   2558         0x629,0x20,0x20,0x20,0x20
   2559     }, unshape_at_end[]={
   2560         0x20,0x20,0x20,0x627,0x644,0x622,0x20,0x646,0x20,0x627,0x644,0x623,0x20,0x642,
   2561         0x644,0x627,0x20,0x645,0x20,0x627,0x644,0x639,0x631,0x628,0x64a,0x629,0x20,0x627,
   2562         0x644,0x62d,0x631,0x629,0x20
   2563     }, unshape_at_begin[]={
   2564         0x627,0x644,0x622,0x20,0x646,0x20,0x627,0x644,0x623,0x20,0x642,0x644,0x627,0x20,
   2565         0x645,0x20,0x627,0x644,0x639,0x631,0x628,0x64a,0x629,0x20,0x627,0x644,0x62d,0x631,
   2566         0x629,0x20,0x20,0x20,0x20
   2567     }, unshape_grow_shrink[]={
   2568         0x20,0x20,0x20,0x627,0x644,0x622,0x20,0x646,0x20,0x627,0x644,0x623,0x20,0x642,
   2569         0x644,0x627,0x20,0x645,0x20,0x627,0x644,0x639,0x631,0x628,0x64a,0x629,0x20,0x627,
   2570         0x644,0x62d,0x631,0x629,0x20,0x20,0x20,0x20
   2571     };
   2572 
   2573     UChar dest[36];
   2574     UErrorCode errorCode;
   2575     int32_t length;
   2576 
   2577     errorCode=U_ZERO_ERROR;
   2578 
   2579     length=u_shapeArabic(source, LENGTHOF(source),
   2580                          dest, LENGTHOF(dest),
   2581                          U_SHAPE_LETTERS_UNSHAPE|U_SHAPE_LENGTH_FIXED_SPACES_NEAR|
   2582                          U_SHAPE_TEXT_DIRECTION_LOGICAL,
   2583                          &errorCode);
   2584 
   2585     if(U_FAILURE(errorCode) || length!=LENGTHOF(unshape_near) || memcmp(dest, unshape_near, length*U_SIZEOF_UCHAR)!=0) {
   2586         log_err("failure in u_shapeArabic(unshape_near)\n");
   2587     }
   2588 
   2589     errorCode=U_ZERO_ERROR;
   2590 
   2591     length=u_shapeArabic(source, LENGTHOF(source),
   2592                          dest, LENGTHOF(dest),
   2593                          U_SHAPE_LETTERS_UNSHAPE|U_SHAPE_LENGTH_FIXED_SPACES_AT_END|
   2594                          U_SHAPE_TEXT_DIRECTION_LOGICAL,
   2595                          &errorCode);
   2596 
   2597     if(U_FAILURE(errorCode) || length!=LENGTHOF(unshape_at_end) || memcmp(dest, unshape_at_end, length*U_SIZEOF_UCHAR)!=0) {
   2598         log_err("failure in u_shapeArabic(unshape_at_end)\n");
   2599     }
   2600 
   2601     errorCode=U_ZERO_ERROR;
   2602 
   2603     length=u_shapeArabic(source, LENGTHOF(source),
   2604                          dest, LENGTHOF(dest),
   2605                          U_SHAPE_LETTERS_UNSHAPE|U_SHAPE_LENGTH_FIXED_SPACES_AT_BEGINNING|
   2606                          U_SHAPE_TEXT_DIRECTION_LOGICAL,
   2607                          &errorCode);
   2608 
   2609     if(U_FAILURE(errorCode) || length!=LENGTHOF(unshape_at_begin) || memcmp(dest, unshape_at_begin, length*U_SIZEOF_UCHAR)!=0) {
   2610         log_err("failure in u_shapeArabic(unshape_at_begin)\n");
   2611     }
   2612 
   2613     errorCode=U_ZERO_ERROR;
   2614 
   2615     length=u_shapeArabic(source, LENGTHOF(source),
   2616                          dest, LENGTHOF(dest),
   2617                          U_SHAPE_LETTERS_UNSHAPE|U_SHAPE_LENGTH_GROW_SHRINK|
   2618                          U_SHAPE_TEXT_DIRECTION_LOGICAL,
   2619                          &errorCode);
   2620 
   2621     if(U_FAILURE(errorCode) || memcmp(dest, unshape_grow_shrink, length*U_SIZEOF_UCHAR)!=0) {
   2622         log_err("failure in u_shapeArabic(unshape_grow_shrink)\n");
   2623     }
   2624 
   2625 }
   2626 
   2627 static void
   2628 doArabicShapingTestForBug5421(void) {
   2629     static const UChar
   2630     persian_letters_source[]={
   2631         0x0020, 0x0698, 0x067E, 0x0686, 0x06AF, 0x0020
   2632     }, persian_letters[]={
   2633         0x0020, 0xFB8B, 0xFB59, 0xFB7D, 0xFB94, 0x0020
   2634     }, tashkeel_aggregation_source[]={
   2635         0x0020, 0x0628, 0x0651, 0x064E, 0x062A, 0x0631, 0x0645, 0x0020,
   2636         0x0628, 0x064E, 0x0651, 0x062A, 0x0631, 0x0645, 0x0020
   2637     }, tashkeel_aggregation[]={
   2638         0x0020, 0xFE90, 0xFC60, 0xFE97, 0xFEAE, 0xFEE3,
   2639         0x0020, 0xFE90, 0xFC60, 0xFE97, 0xFEAE, 0xFEE3, 0x0020
   2640     }, untouched_presentation_source[]={
   2641         0x0020 ,0x0627, 0xfe90,0x0020
   2642     }, untouched_presentation[]={
   2643         0x0020,0xfe8D, 0xfe90,0x0020
   2644     }, untouched_presentation_r_source[]={
   2645         0x0020 ,0xfe90, 0x0627, 0x0020
   2646     }, untouched_presentation_r[]={
   2647         0x0020, 0xfe90,0xfe8D,0x0020
   2648     };
   2649 
   2650     UChar dest[38];
   2651     UErrorCode errorCode;
   2652     int32_t length;
   2653 
   2654     errorCode=U_ZERO_ERROR;
   2655 
   2656     length=u_shapeArabic(persian_letters_source, LENGTHOF(persian_letters_source),
   2657                          dest, LENGTHOF(dest),
   2658                          U_SHAPE_LETTERS_SHAPE|U_SHAPE_TEXT_DIRECTION_VISUAL_LTR,
   2659                          &errorCode);
   2660 
   2661     if(U_FAILURE(errorCode) || length!=LENGTHOF(persian_letters) || memcmp(dest, persian_letters, length*U_SIZEOF_UCHAR)!=0) {
   2662         log_err("failure in u_shapeArabic(persian_letters)\n");
   2663     }
   2664 
   2665     errorCode=U_ZERO_ERROR;
   2666 
   2667     length=u_shapeArabic(tashkeel_aggregation_source, LENGTHOF(tashkeel_aggregation_source),
   2668                          dest, LENGTHOF(dest),
   2669                          U_SHAPE_AGGREGATE_TASHKEEL|U_SHAPE_PRESERVE_PRESENTATION|
   2670                          U_SHAPE_LETTERS_SHAPE_TASHKEEL_ISOLATED|U_SHAPE_TEXT_DIRECTION_VISUAL_LTR,
   2671                          &errorCode);
   2672 
   2673     if(U_FAILURE(errorCode) || length!=LENGTHOF(tashkeel_aggregation) || memcmp(dest, tashkeel_aggregation, length*U_SIZEOF_UCHAR)!=0) {
   2674         log_err("failure in u_shapeArabic(tashkeel_aggregation)\n");
   2675     }
   2676 
   2677     errorCode=U_ZERO_ERROR;
   2678 
   2679     length=u_shapeArabic(untouched_presentation_source, LENGTHOF(untouched_presentation_source),
   2680                          dest, LENGTHOF(dest),
   2681                          U_SHAPE_PRESERVE_PRESENTATION|
   2682                          U_SHAPE_LETTERS_SHAPE|U_SHAPE_TEXT_DIRECTION_VISUAL_LTR,
   2683                          &errorCode);
   2684 
   2685     if(U_FAILURE(errorCode) || length!=LENGTHOF(untouched_presentation) || memcmp(dest, untouched_presentation, length*U_SIZEOF_UCHAR)!=0) {
   2686         log_err("failure in u_shapeArabic(untouched_presentation)\n");
   2687     }
   2688 
   2689     errorCode=U_ZERO_ERROR;
   2690 
   2691     length=u_shapeArabic(untouched_presentation_r_source, LENGTHOF(untouched_presentation_r_source),
   2692                          dest, LENGTHOF(dest),
   2693                          U_SHAPE_PRESERVE_PRESENTATION|
   2694                          U_SHAPE_LETTERS_SHAPE|U_SHAPE_TEXT_DIRECTION_LOGICAL,
   2695                          &errorCode);
   2696 
   2697     if(U_FAILURE(errorCode) || length!=LENGTHOF(untouched_presentation_r) || memcmp(dest, untouched_presentation_r, length*U_SIZEOF_UCHAR)!=0) {
   2698         log_err("failure in u_shapeArabic(untouched_presentation_r)\n");
   2699     }
   2700 }
   2701 
   2702 /* helpers ------------------------------------------------------------------ */
   2703 
   2704 static void initCharFromDirProps(void) {
   2705     static const UVersionInfo ucd401={ 4, 0, 1, 0 };
   2706     static UVersionInfo ucdVersion={ 0, 0, 0, 0 };
   2707 
   2708     /* lazy initialization */
   2709     if(ucdVersion[0]>0) {
   2710         return;
   2711     }
   2712 
   2713     u_getUnicodeVersion(ucdVersion);
   2714     if(memcmp(ucdVersion, ucd401, sizeof(UVersionInfo))>=0) {
   2715         /* Unicode 4.0.1 changes bidi classes for +-/ */
   2716         charFromDirProp[U_EUROPEAN_NUMBER_SEPARATOR]=0x2b; /* change ES character from / to + */
   2717     }
   2718 }
   2719 
   2720 /* return a string with characters according to the desired directional properties */
   2721 static UChar *
   2722 getStringFromDirProps(const uint8_t *dirProps, int32_t length, UChar *buffer) {
   2723     int32_t i;
   2724 
   2725     initCharFromDirProps();
   2726 
   2727     /* this part would have to be modified for UTF-x */
   2728     for(i=0; i<length; ++i) {
   2729         buffer[i]=charFromDirProp[dirProps[i]];
   2730     }
   2731     buffer[length]=0;
   2732     return buffer;
   2733 }
   2734 
   2735 static void printUnicode(const UChar *s, int32_t length, const UBiDiLevel *levels) {
   2736     int32_t i;
   2737 
   2738     log_verbose("{ ");
   2739     for(i=0; i<length; ++i) {
   2740         if(levels!=NULL) {
   2741             log_verbose("%4x.%u  ", s[i], levels[i]);
   2742         } else {
   2743             log_verbose("%4x    ", s[i]);
   2744         }
   2745     }
   2746     log_verbose(" }");
   2747 }
   2748 
   2749 /* new BIDI API */
   2750 
   2751 /* Reordering Mode BiDi --------------------------------------------------------- */
   2752 
   2753 static const UBiDiLevel paraLevels[] = { UBIDI_LTR, UBIDI_RTL };
   2754 
   2755 static UBool
   2756 assertSuccessful(const char* message, UErrorCode* rc) {
   2757     if (rc != NULL && U_FAILURE(*rc)) {
   2758         log_err("%s() failed with error %s.\n", message, myErrorName(*rc));
   2759         return FALSE;
   2760     }
   2761     return TRUE;
   2762 }
   2763 
   2764 static UBool
   2765 assertStringsEqual(const char* expected, const char* actual, const char* src,
   2766                    const char* mode, const char* option, UBiDi* pBiDi) {
   2767     if (uprv_strcmp(expected, actual)) {
   2768         char formatChars[MAXLEN];
   2769         log_err("\nActual and expected output mismatch.\n"
   2770             "%20s %s\n%20s %s\n%20s %s\n%20s %s\n%20s %d %s\n%20s %u\n%20s %d %s\n",
   2771             "Input:", src,
   2772             "Actual output:", actual,
   2773             "Expected output:", expected,
   2774             "Levels:", formatLevels(pBiDi, formatChars),
   2775             "Reordering mode:", ubidi_getReorderingMode(pBiDi), mode,
   2776             "Paragraph level:", ubidi_getParaLevel(pBiDi),
   2777             "Reordering option:", ubidi_getReorderingOptions(pBiDi), option);
   2778         return FALSE;
   2779     }
   2780     return TRUE;
   2781 }
   2782 
   2783 static UBiDi*
   2784 getBiDiObject(void) {
   2785     UBiDi* pBiDi = ubidi_open();
   2786     if (pBiDi == NULL) {
   2787         log_err("Unable to allocate a UBiDi object. Tests are skipped.\n");
   2788     }
   2789     return pBiDi;
   2790 }
   2791 
   2792 #define MAKE_ITEMS(val) val, #val
   2793 
   2794 static const struct {
   2795     UBiDiReorderingMode value;
   2796     const char* description;
   2797 }
   2798 modes[] = {
   2799     { MAKE_ITEMS(UBIDI_REORDER_GROUP_NUMBERS_WITH_R) },
   2800     { MAKE_ITEMS(UBIDI_REORDER_INVERSE_LIKE_DIRECT) },
   2801     { MAKE_ITEMS(UBIDI_REORDER_NUMBERS_SPECIAL) },
   2802     { MAKE_ITEMS(UBIDI_REORDER_INVERSE_FOR_NUMBERS_SPECIAL) },
   2803     { MAKE_ITEMS(UBIDI_REORDER_INVERSE_NUMBERS_AS_L) }
   2804 };
   2805 static const struct {
   2806     uint32_t value;
   2807     const char* description;
   2808 }
   2809 options[] = {
   2810     { MAKE_ITEMS(UBIDI_OPTION_INSERT_MARKS) },
   2811     { MAKE_ITEMS(0) }
   2812 };
   2813 
   2814 #define TC_COUNT                LENGTHOF(textIn)
   2815 #define MODES_COUNT             LENGTHOF(modes)
   2816 #define OPTIONS_COUNT           LENGTHOF(options)
   2817 #define LEVELS_COUNT            LENGTHOF(paraLevels)
   2818 
   2819 static const char* const textIn[] = {
   2820 /* (0) 123 */
   2821     "123",
   2822 /* (1) .123->4.5 */
   2823     ".123->4.5",
   2824 /* (2) 678 */
   2825     "678",
   2826 /* (3) .678->8.9 */
   2827     ".678->8.9",
   2828 /* (4) JIH1.2,3MLK */
   2829     "JIH1.2,3MLK",
   2830 /* (5) FE.>12-> */
   2831     "FE.>12->",
   2832 /* (6) JIH.>12->a */
   2833     "JIH.>12->a",
   2834 /* (7) CBA.>67->89=a */
   2835     "CBA.>67->89=a",
   2836 /* (8) CBA.123->xyz */
   2837     "CBA.123->xyz",
   2838 /* (9) .>12->xyz */
   2839     ".>12->xyz",
   2840 /* (10) a.>67->xyz */
   2841     "a.>67->xyz",
   2842 /* (11) 123JIH */
   2843     "123JIH",
   2844 /* (12) 123 JIH */
   2845     "123 JIH"
   2846 };
   2847 
   2848 static const char* const textOut[] = {
   2849 /* TC 0: 123 */
   2850     "123",                                                              /* (0) */
   2851 /* TC 1: .123->4.5 */
   2852     ".123->4.5",                                                        /* (1) */
   2853     "4.5<-123.",                                                        /* (2) */
   2854 /* TC 2: 678 */
   2855     "678",                                                              /* (3) */
   2856 /* TC 3: .678->8.9 */
   2857     ".8.9<-678",                                                        /* (4) */
   2858     "8.9<-678.",                                                        /* (5) */
   2859     ".678->8.9",                                                        /* (6) */
   2860 /* TC 4: MLK1.2,3JIH */
   2861     "KLM1.2,3HIJ",                                                      /* (7) */
   2862 /* TC 5: FE.>12-> */
   2863     "12<.EF->",                                                         /* (8) */
   2864     "<-12<.EF",                                                         /* (9) */
   2865     "EF.>@12->",                                                        /* (10) */
   2866 /* TC 6: JIH.>12->a */
   2867     "12<.HIJ->a",                                                       /* (11) */
   2868     "a<-12<.HIJ",                                                       /* (12) */
   2869     "HIJ.>@12->a",                                                      /* (13) */
   2870     "a&<-12<.HIJ",                                                      /* (14) */
   2871 /* TC 7: CBA.>67->89=a */
   2872     "ABC.>@67->89=a",                                                   /* (15) */
   2873     "a=89<-67<.ABC",                                                    /* (16) */
   2874     "a&=89<-67<.ABC",                                                   /* (17) */
   2875     "89<-67<.ABC=a",                                                    /* (18) */
   2876 /* TC 8: CBA.123->xyz */
   2877     "123.ABC->xyz",                                                     /* (19) */
   2878     "xyz<-123.ABC",                                                     /* (20) */
   2879     "ABC.@123->xyz",                                                    /* (21) */
   2880     "xyz&<-123.ABC",                                                    /* (22) */
   2881 /* TC 9: .>12->xyz */
   2882     ".>12->xyz",                                                        /* (23) */
   2883     "xyz<-12<.",                                                        /* (24) */
   2884     "xyz&<-12<.",                                                       /* (25) */
   2885 /* TC 10: a.>67->xyz */
   2886     "a.>67->xyz",                                                       /* (26) */
   2887     "a.>@67@->xyz",                                                     /* (27) */
   2888     "xyz<-67<.a",                                                       /* (28) */
   2889 /* TC 11: 123JIH */
   2890     "123HIJ",                                                           /* (29) */
   2891     "HIJ123",                                                           /* (30) */
   2892 /* TC 12: 123 JIH */
   2893     "123 HIJ",                                                          /* (31) */
   2894     "HIJ 123",                                                          /* (32) */
   2895 };
   2896 
   2897 #define NO                  UBIDI_MAP_NOWHERE
   2898 #define MAX_MAP_LENGTH      20
   2899 
   2900 static const int32_t forwardMap[][MAX_MAP_LENGTH] = {
   2901 /* TC 0: 123 */
   2902     { 0, 1, 2 },                                                        /* (0) */
   2903 /* TC 1: .123->4.5 */
   2904     { 0, 1, 2, 3, 4, 5, 6, 7, 8 },                                      /* (1) */
   2905     { 8, 5, 6, 7, 4, 3, 0, 1, 2 },                                      /* (2) */
   2906 /* TC 2: 678 */
   2907     { 0, 1, 2 },                                                        /* (3) */
   2908 /* TC 3: .678->8.9 */
   2909     { 0, 6, 7, 8, 5, 4, 1, 2, 3 },                                      /* (4) */
   2910     { 8, 5, 6, 7, 4, 3, 0, 1, 2 },                                      /* (5) */
   2911     { 0, 1, 2, 3, 4, 5, 6, 7, 8 },                                      /* (6) */
   2912 /* TC 4: MLK1.2,3JIH */
   2913     { 10, 9, 8, 3, 4, 5, 6, 7, 2, 1, 0 },                               /* (7) */
   2914 /* TC 5: FE.>12-> */
   2915     { 5, 4, 3, 2, 0, 1, 6, 7 },                                         /* (8) */
   2916     { 7, 6, 5, 4, 2, 3, 1, 0 },                                         /* (9) */
   2917     { 1, 0, 2, 3, 5, 6, 7, 8 },                                         /* (10) */
   2918 /* TC 6: JIH.>12->a */
   2919     { 6, 5, 4, 3, 2, 0, 1, 7, 8, 9 },                                   /* (11) */
   2920     { 9, 8, 7, 6, 5, 3, 4, 2, 1, 0 },                                   /* (12) */
   2921     { 2, 1, 0, 3, 4, 6, 7, 8, 9, 10 },                                  /* (13) */
   2922     { 10, 9, 8, 7, 6, 4, 5, 3, 2, 0 },                                  /* (14) */
   2923 /* TC 7: CBA.>67->89=a */
   2924     { 2, 1, 0, 3, 4, 6, 7, 8, 9, 10, 11, 12, 13 },                      /* (15) */
   2925     { 12, 11, 10, 9, 8, 6, 7, 5, 4, 2, 3, 1, 0 },                       /* (16) */
   2926     { 13, 12, 11, 10, 9, 7, 8, 6, 5, 3, 4, 2, 0 },                      /* (17) */
   2927     { 10, 9, 8, 7, 6, 4, 5, 3, 2, 0, 1, 11, 12 },                       /* (18) */
   2928 /* TC 8: CBA.123->xyz */
   2929     { 6, 5, 4, 3, 0, 1, 2, 7, 8, 9, 10, 11 },                           /* (19) */
   2930     { 11, 10, 9, 8, 5, 6, 7, 4, 3, 0, 1, 2 },                           /* (20) */
   2931     { 2, 1, 0, 3, 5, 6, 7, 8, 9, 10, 11, 12 },                          /* (21) */
   2932     { 12, 11, 10, 9, 6, 7, 8, 5, 4, 0, 1, 2 },                          /* (22) */
   2933 /* TC 9: .>12->xyz */
   2934     { 0, 1, 2, 3, 4, 5, 6, 7, 8 },                                      /* (23) */
   2935     { 8, 7, 5, 6, 4, 3, 0, 1, 2 },                                      /* (24) */
   2936     { 9, 8, 6, 7, 5, 4, 0, 1, 2 },                                      /* (25) */
   2937 /* TC 10: a.>67->xyz */
   2938     { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 },                                   /* (26) */
   2939     { 0, 1, 2, 4, 5, 7, 8, 9, 10, 11 },                                 /* (27) */
   2940     { 9, 8, 7, 5, 6, 4, 3, 0, 1, 2 },                                   /* (28) */
   2941 /* TC 11: 123JIH */
   2942     { 0, 1, 2, 5, 4, 3 },                                               /* (29) */
   2943     { 3, 4, 5, 2, 1, 0 },                                               /* (30) */
   2944 /* TC 12: 123 JIH */
   2945     { 0, 1, 2, 3, 6, 5, 4 },                                            /* (31) */
   2946     { 4, 5, 6, 3, 2, 1, 0 },                                            /* (32) */
   2947 };
   2948 
   2949 static const int32_t inverseMap[][MAX_MAP_LENGTH] = {
   2950 /* TC 0: 123 */
   2951     { 0, 1, 2 },                                                        /* (0) */
   2952 /* TC 1: .123->4.5 */
   2953     { 0, 1, 2, 3, 4, 5, 6, 7, 8 },                                      /* (1) */
   2954     { 6, 7, 8, 5, 4, 1, 2, 3, 0 },                                      /* (2) */
   2955 /* TC 2: 678 */
   2956     { 0, 1, 2 },                                                        /* (3) */
   2957 /* TC 3: .678->8.9 */
   2958     { 0, 6, 7, 8, 5, 4, 1, 2, 3 },                                      /* (4) */
   2959     { 6, 7, 8, 5, 4, 1, 2, 3, 0 },                                      /* (5) */
   2960     { 0, 1, 2, 3, 4, 5, 6, 7, 8 },                                      /* (6) */
   2961 /* TC 4: MLK1.2,3JIH */
   2962     { 10, 9, 8, 3, 4, 5, 6, 7, 2, 1, 0 },                               /* (7) */
   2963 /* TC 5: FE.>12-> */
   2964     { 4, 5, 3, 2, 1, 0, 6, 7 },                                         /* (8) */
   2965     { 7, 6, 4, 5, 3, 2, 1, 0 },                                         /* (9) */
   2966     { 1, 0, 2, 3, NO, 4, 5, 6, 7 },                                     /* (10) */
   2967 /* TC 6: JIH.>12->a */
   2968     { 5, 6, 4, 3, 2, 1, 0, 7, 8, 9 },                                   /* (11) */
   2969     { 9, 8, 7, 5, 6, 4, 3, 2, 1, 0 },                                   /* (12) */
   2970     { 2, 1, 0, 3, 4, NO, 5, 6, 7, 8, 9 },                               /* (13) */
   2971     { 9, NO, 8, 7, 5, 6, 4, 3, 2, 1, 0 },                               /* (14) */
   2972 /* TC 7: CBA.>67->89=a */
   2973     { 2, 1, 0, 3, 4, NO, 5, 6, 7, 8, 9, 10, 11, 12 },                   /* (15) */
   2974     { 12, 11, 9, 10, 8, 7, 5, 6, 4, 3, 2, 1, 0 },                       /* (16) */
   2975     { 12, NO, 11, 9, 10, 8, 7, 5, 6, 4, 3, 2, 1, 0 },                   /* (17) */
   2976     { 9, 10, 8, 7, 5, 6, 4, 3, 2, 1, 0, 11, 12 },                       /* (18) */
   2977 /* TC 8: CBA.123->xyz */
   2978     { 4, 5, 6, 3, 2, 1, 0, 7, 8, 9, 10, 11 },                           /* (19) */
   2979     { 9, 10, 11, 8, 7, 4, 5, 6, 3, 2, 1, 0 },                           /* (20) */
   2980     { 2, 1, 0, 3, NO, 4, 5, 6, 7, 8, 9, 10, 11 },                       /* (21) */
   2981     { 9, 10, 11, NO, 8, 7, 4, 5, 6, 3, 2, 1, 0 },                       /* (22) */
   2982 /* TC 9: .>12->xyz */
   2983     { 0, 1, 2, 3, 4, 5, 6, 7, 8 },                                      /* (23) */
   2984     { 6, 7, 8, 5, 4, 2, 3, 1, 0 },                                      /* (24) */
   2985     { 6, 7, 8, NO, 5, 4, 2, 3, 1, 0 },                                  /* (25) */
   2986 /* TC 10: a.>67->xyz */
   2987     { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 },                                   /* (26) */
   2988     { 0, 1, 2, NO, 3, 4, NO, 5, 6, 7, 8, 9 },                           /* (27) */
   2989     { 7, 8, 9, 6, 5, 3, 4, 2, 1, 0 },                                   /* (28) */
   2990 /* TC 11: 123JIH */
   2991     { 0, 1, 2, 5, 4, 3 },                                               /* (29) */
   2992     { 5, 4, 3, 0, 1, 2 },                                               /* (30) */
   2993 /* TC 12: 123 JIH */
   2994     { 0, 1, 2, 3, 6, 5, 4 },                                            /* (31) */
   2995     { 6, 5, 4, 3, 0, 1, 2 },                                            /* (32) */
   2996 };
   2997 
   2998 static const char outIndices[TC_COUNT][MODES_COUNT - 1][OPTIONS_COUNT]
   2999             [LEVELS_COUNT] = {
   3000     { /* TC 0: 123 */
   3001         {{ 0,  0}, { 0,  0}}, /* UBIDI_REORDER_GROUP_NUMBERS_WITH_R */
   3002         {{ 0,  0}, { 0,  0}}, /* UBIDI_REORDER_INVERSE_LIKE_DIRECT */
   3003         {{ 0,  0}, { 0,  0}}, /* UBIDI_REORDER_NUMBERS_SPECIAL */
   3004         {{ 0,  0}, { 0,  0}}  /* UBIDI_REORDER_INVERSE_FOR_NUMBERS_SPECIAL */
   3005     },
   3006     { /* TC 1: .123->4.5 */
   3007         {{ 1,  2}, { 1,  2}}, /* UBIDI_REORDER_GROUP_NUMBERS_WITH_R */
   3008         {{ 1,  2}, { 1,  2}}, /* UBIDI_REORDER_INVERSE_LIKE_DIRECT */
   3009         {{ 1,  2}, { 1,  2}}, /* UBIDI_REORDER_NUMBERS_SPECIAL */
   3010         {{ 1,  2}, { 1,  2}}  /* UBIDI_REORDER_INVERSE_FOR_NUMBERS_SPECIAL */
   3011     },
   3012     { /* TC 2: 678 */
   3013         {{ 3,  3}, { 3,  3}}, /* UBIDI_REORDER_GROUP_NUMBERS_WITH_R */
   3014         {{ 3,  3}, { 3,  3}}, /* UBIDI_REORDER_INVERSE_LIKE_DIRECT */
   3015         {{ 3,  3}, { 3,  3}}, /* UBIDI_REORDER_NUMBERS_SPECIAL */
   3016         {{ 3,  3}, { 3,  3}}  /* UBIDI_REORDER_INVERSE_FOR_NUMBERS_SPECIAL */
   3017     },
   3018     { /* TC 3: .678->8.9 */
   3019         {{ 6,  5}, { 6,  5}}, /* UBIDI_REORDER_GROUP_NUMBERS_WITH_R */
   3020         {{ 4,  5}, { 4,  5}}, /* UBIDI_REORDER_INVERSE_LIKE_DIRECT */
   3021         {{ 6,  5}, { 6,  5}}, /* UBIDI_REORDER_NUMBERS_SPECIAL */
   3022         {{ 6,  5}, { 6,  5}}  /* UBIDI_REORDER_INVERSE_FOR_NUMBERS_SPECIAL */
   3023     },
   3024     { /* TC 4: MLK1.2,3JIH */
   3025         {{ 7,  7}, { 7,  7}}, /* UBIDI_REORDER_GROUP_NUMBERS_WITH_R */
   3026         {{ 7,  7}, { 7,  7}}, /* UBIDI_REORDER_INVERSE_LIKE_DIRECT */
   3027         {{ 7,  7}, { 7,  7}}, /* UBIDI_REORDER_NUMBERS_SPECIAL */
   3028         {{ 7,  7}, { 7,  7}}  /* UBIDI_REORDER_INVERSE_FOR_NUMBERS_SPECIAL */
   3029     },
   3030     { /* TC 5: FE.>12-> */
   3031         {{ 8,  9}, { 8,  9}}, /* UBIDI_REORDER_GROUP_NUMBERS_WITH_R */
   3032         {{10,  9}, { 8,  9}}, /* UBIDI_REORDER_INVERSE_LIKE_DIRECT */
   3033         {{ 8,  9}, { 8,  9}}, /* UBIDI_REORDER_NUMBERS_SPECIAL */
   3034         {{10,  9}, { 8,  9}}  /* UBIDI_REORDER_INVERSE_FOR_NUMBERS_SPECIAL */
   3035     },
   3036     { /* TC 6: JIH.>12->a */
   3037         {{11, 12}, {11, 12}}, /* UBIDI_REORDER_GROUP_NUMBERS_WITH_R */
   3038         {{13, 14}, {11, 12}}, /* UBIDI_REORDER_INVERSE_LIKE_DIRECT */
   3039         {{11, 12}, {11, 12}}, /* UBIDI_REORDER_NUMBERS_SPECIAL */
   3040         {{13, 14}, {11, 12}}  /* UBIDI_REORDER_INVERSE_FOR_NUMBERS_SPECIAL */
   3041     },
   3042     { /* TC 7: CBA.>67->89=a */
   3043         {{18, 16}, {18, 16}}, /* UBIDI_REORDER_GROUP_NUMBERS_WITH_R */
   3044         {{18, 17}, {18, 16}}, /* UBIDI_REORDER_INVERSE_LIKE_DIRECT */
   3045         {{18, 16}, {18, 16}}, /* UBIDI_REORDER_NUMBERS_SPECIAL */
   3046         {{15, 17}, {18, 16}}  /* UBIDI_REORDER_INVERSE_FOR_NUMBERS_SPECIAL */
   3047     },
   3048     { /* TC 8: CBA.>124->xyz */
   3049         {{19, 20}, {19, 20}}, /* UBIDI_REORDER_GROUP_NUMBERS_WITH_R */
   3050         {{21, 22}, {19, 20}}, /* UBIDI_REORDER_INVERSE_LIKE_DIRECT */
   3051         {{19, 20}, {19, 20}}, /* UBIDI_REORDER_NUMBERS_SPECIAL */
   3052         {{21, 22}, {19, 20}}  /* UBIDI_REORDER_INVERSE_FOR_NUMBERS_SPECIAL */
   3053     },
   3054     { /* TC 9: .>12->xyz */
   3055         {{23, 24}, {23, 24}}, /* UBIDI_REORDER_GROUP_NUMBERS_WITH_R */
   3056         {{23, 25}, {23, 24}}, /* UBIDI_REORDER_INVERSE_LIKE_DIRECT */
   3057         {{23, 24}, {23, 24}}, /* UBIDI_REORDER_NUMBERS_SPECIAL */
   3058         {{23, 25}, {23, 24}}  /* UBIDI_REORDER_INVERSE_FOR_NUMBERS_SPECIAL */
   3059     },
   3060     { /* TC 10: a.>67->xyz */
   3061         {{26, 26}, {26, 26}}, /* UBIDI_REORDER_GROUP_NUMBERS_WITH_R */
   3062         {{26, 27}, {26, 28}}, /* UBIDI_REORDER_INVERSE_LIKE_DIRECT */
   3063         {{26, 28}, {26, 28}}, /* UBIDI_REORDER_NUMBERS_SPECIAL */
   3064         {{26, 27}, {26, 28}}  /* UBIDI_REORDER_INVERSE_FOR_NUMBERS_SPECIAL */
   3065     },
   3066     { /* TC 11: 124JIH */
   3067         {{30, 30}, {30, 30}}, /* UBIDI_REORDER_GROUP_NUMBERS_WITH_R */
   3068         {{29, 30}, {29, 30}}, /* UBIDI_REORDER_INVERSE_LIKE_DIRECT */
   3069         {{30, 30}, {30, 30}}, /* UBIDI_REORDER_NUMBERS_SPECIAL */
   3070         {{30, 30}, {30, 30}}  /* UBIDI_REORDER_INVERSE_FOR_NUMBERS_SPECIAL */
   3071     },
   3072     { /* TC 12: 124 JIH */
   3073         {{32, 32}, {32, 32}}, /* UBIDI_REORDER_GROUP_NUMBERS_WITH_R */
   3074         {{31, 32}, {31, 32}}, /* UBIDI_REORDER_INVERSE_LIKE_DIRECT */
   3075         {{31, 32}, {31, 32}}, /* UBIDI_REORDER_NUMBERS_SPECIAL */
   3076         {{31, 32}, {31, 32}}  /* UBIDI_REORDER_INVERSE_FOR_NUMBERS_SPECIAL */
   3077     }
   3078 };
   3079 
   3080 static UBool
   3081 assertRoundTrip(UBiDi *pBiDi, int32_t tc, int32_t outIndex, const char *srcChars,
   3082                 const char *destChars, const UChar *dest, int32_t destLen,
   3083                 int mode, int option, UBiDiLevel level) {
   3084 
   3085     static const char roundtrip[TC_COUNT][MODES_COUNT][OPTIONS_COUNT]
   3086                 [LEVELS_COUNT] = {
   3087         { /* TC 0: 123 */
   3088             {{ 1,  1}, { 1,  1}}, /* UBIDI_REORDER_GROUP_NUMBERS_WITH_R */
   3089             {{ 1,  1}, { 1,  1}}, /* UBIDI_REORDER_INVERSE_LIKE_DIRECT */
   3090             {{ 1,  1}, { 1,  1}}, /* UBIDI_REORDER_NUMBERS_SPECIAL */
   3091             {{ 1,  1}, { 1,  1}}, /* UBIDI_REORDER_INVERSE_FOR_NUMBERS_SPECIAL */
   3092             {{ 1,  1}, { 1,  1}}  /* UBIDI_REORDER_INVERSE_NUMBERS_AS_L */
   3093         },
   3094         { /* TC 1: .123->4.5 */
   3095             {{ 1,  1}, { 1,  1}}, /* UBIDI_REORDER_GROUP_NUMBERS_WITH_R */
   3096             {{ 1,  1}, { 1,  1}}, /* UBIDI_REORDER_INVERSE_LIKE_DIRECT */
   3097             {{ 1,  1}, { 1,  1}}, /* UBIDI_REORDER_NUMBERS_SPECIAL */
   3098             {{ 1,  1}, { 1,  1}}, /* UBIDI_REORDER_INVERSE_FOR_NUMBERS_SPECIAL */
   3099             {{ 1,  1}, { 1,  1}}  /* UBIDI_REORDER_INVERSE_NUMBERS_AS_L */
   3100         },
   3101         { /* TC 2: 678 */
   3102             {{ 1,  1}, { 1,  1}}, /* UBIDI_REORDER_GROUP_NUMBERS_WITH_R */
   3103             {{ 1,  1}, { 1,  1}}, /* UBIDI_REORDER_INVERSE_LIKE_DIRECT */
   3104             {{ 1,  1}, { 1,  1}}, /* UBIDI_REORDER_NUMBERS_SPECIAL */
   3105             {{ 1,  1}, { 1,  1}}, /* UBIDI_REORDER_INVERSE_FOR_NUMBERS_SPECIAL */
   3106             {{ 1,  1}, { 1,  1}}  /* UBIDI_REORDER_INVERSE_NUMBERS_AS_L */
   3107         },
   3108         { /* TC 3: .678->8.9 */
   3109             {{ 1,  1}, { 1,  1}}, /* UBIDI_REORDER_GROUP_NUMBERS_WITH_R */
   3110             {{ 1,  1}, { 1,  1}}, /* UBIDI_REORDER_INVERSE_LIKE_DIRECT */
   3111             {{ 1,  1}, { 1,  1}}, /* UBIDI_REORDER_NUMBERS_SPECIAL */
   3112             {{ 1,  1}, { 1,  1}}, /* UBIDI_REORDER_INVERSE_FOR_NUMBERS_SPECIAL */
   3113             {{ 0,  0}, { 1,  1}}  /* UBIDI_REORDER_INVERSE_NUMBERS_AS_L */
   3114         },
   3115         { /* TC 4: MLK1.2,3JIH */
   3116             {{ 1,  1}, { 1,  1}}, /* UBIDI_REORDER_GROUP_NUMBERS_WITH_R */
   3117             {{ 1,  1}, { 1,  1}}, /* UBIDI_REORDER_INVERSE_LIKE_DIRECT */
   3118             {{ 1,  1}, { 1,  1}}, /* UBIDI_REORDER_NUMBERS_SPECIAL */
   3119             {{ 1,  1}, { 1,  1}}, /* UBIDI_REORDER_INVERSE_FOR_NUMBERS_SPECIAL */
   3120             {{ 1,  1}, { 1,  1}}  /* UBIDI_REORDER_INVERSE_NUMBERS_AS_L */
   3121         },
   3122         { /* TC 5: FE.>12-> */
   3123             {{ 1,  1}, { 1,  1}}, /* UBIDI_REORDER_GROUP_NUMBERS_WITH_R */
   3124             {{ 1,  1}, { 1,  1}}, /* UBIDI_REORDER_INVERSE_LIKE_DIRECT */
   3125             {{ 0,  1}, { 1,  1}}, /* UBIDI_REORDER_NUMBERS_SPECIAL */
   3126             {{ 1,  1}, { 1,  1}}, /* UBIDI_REORDER_INVERSE_FOR_NUMBERS_SPECIAL */
   3127             {{ 1,  1}, { 1,  1}}  /* UBIDI_REORDER_INVERSE_NUMBERS_AS_L */
   3128         },
   3129         { /* TC 6: JIH.>12->a */
   3130             {{ 1,  1}, { 1,  1}}, /* UBIDI_REORDER_GROUP_NUMBERS_WITH_R */
   3131             {{ 1,  1}, { 1,  1}}, /* UBIDI_REORDER_INVERSE_LIKE_DIRECT */
   3132             {{ 0,  0}, { 1,  1}}, /* UBIDI_REORDER_NUMBERS_SPECIAL */
   3133             {{ 1,  1}, { 1,  1}}, /* UBIDI_REORDER_INVERSE_FOR_NUMBERS_SPECIAL */
   3134             {{ 1,  1}, { 1,  1}}  /* UBIDI_REORDER_INVERSE_NUMBERS_AS_L */
   3135         },
   3136         { /* TC 7: CBA.>67->89=a */
   3137             {{ 1,  1}, { 1,  1}}, /* UBIDI_REORDER_GROUP_NUMBERS_WITH_R */
   3138             {{ 1,  1}, { 1,  1}}, /* UBIDI_REORDER_INVERSE_LIKE_DIRECT */
   3139             {{ 0,  1}, { 1,  1}}, /* UBIDI_REORDER_NUMBERS_SPECIAL */
   3140             {{ 1,  1}, { 1,  1}}, /* UBIDI_REORDER_INVERSE_FOR_NUMBERS_SPECIAL */
   3141             {{ 0,  0}, { 1,  1}}  /* UBIDI_REORDER_INVERSE_NUMBERS_AS_L */
   3142         },
   3143         { /* TC 8: CBA.>123->xyz */
   3144             {{ 1,  1}, { 1,  1}}, /* UBIDI_REORDER_GROUP_NUMBERS_WITH_R */
   3145             {{ 1,  1}, { 1,  1}}, /* UBIDI_REORDER_INVERSE_LIKE_DIRECT */
   3146             {{ 0,  0}, { 1,  1}}, /* UBIDI_REORDER_NUMBERS_SPECIAL */
   3147             {{ 1,  1}, { 1,  1}}, /* UBIDI_REORDER_INVERSE_FOR_NUMBERS_SPECIAL */
   3148             {{ 1,  1}, { 1,  1}}  /* UBIDI_REORDER_INVERSE_NUMBERS_AS_L */
   3149         },
   3150         { /* TC 9: .>12->xyz */
   3151             {{ 1,  1}, { 1,  1}}, /* UBIDI_REORDER_GROUP_NUMBERS_WITH_R */
   3152             {{ 1,  1}, { 1,  1}}, /* UBIDI_REORDER_INVERSE_LIKE_DIRECT */
   3153             {{ 1,  0}, { 1,  1}}, /* UBIDI_REORDER_NUMBERS_SPECIAL */
   3154             {{ 1,  1}, { 1,  1}}, /* UBIDI_REORDER_INVERSE_FOR_NUMBERS_SPECIAL */
   3155             {{ 1,  1}, { 1,  1}}  /* UBIDI_REORDER_INVERSE_NUMBERS_AS_L */
   3156         },
   3157         { /* TC 10: a.>67->xyz */
   3158             {{ 1,  1}, { 1,  1}}, /* UBIDI_REORDER_GROUP_NUMBERS_WITH_R */
   3159             {{ 1,  1}, { 1,  1}}, /* UBIDI_REORDER_INVERSE_LIKE_DIRECT */
   3160             {{ 1,  1}, { 1,  1}}, /* UBIDI_REORDER_NUMBERS_SPECIAL */
   3161             {{ 1,  1}, { 1,  1}}, /* UBIDI_REORDER_INVERSE_FOR_NUMBERS_SPECIAL */
   3162             {{ 1,  0}, { 1,  1}}  /* UBIDI_REORDER_INVERSE_NUMBERS_AS_L */
   3163         },
   3164         { /* TC 11: 123JIH */
   3165             {{ 1,  1}, { 1,  1}}, /* UBIDI_REORDER_GROUP_NUMBERS_WITH_R */
   3166             {{ 1,  1}, { 1,  1}}, /* UBIDI_REORDER_INVERSE_LIKE_DIRECT */
   3167             {{ 1,  1}, { 1,  1}}, /* UBIDI_REORDER_NUMBERS_SPECIAL */
   3168             {{ 1,  1}, { 1,  1}}, /* UBIDI_REORDER_INVERSE_FOR_NUMBERS_SPECIAL */
   3169             {{ 1,  1}, { 1,  1}}  /* UBIDI_REORDER_INVERSE_NUMBERS_AS_L */
   3170         },
   3171         { /* TC 12: 123 JIH */
   3172             {{ 1,  1}, { 1,  1}}, /* UBIDI_REORDER_GROUP_NUMBERS_WITH_R */
   3173             {{ 1,  1}, { 1,  1}}, /* UBIDI_REORDER_INVERSE_LIKE_DIRECT */
   3174             {{ 1,  1}, { 1,  1}}, /* UBIDI_REORDER_NUMBERS_SPECIAL */
   3175             {{ 1,  1}, { 1,  1}}, /* UBIDI_REORDER_INVERSE_FOR_NUMBERS_SPECIAL */
   3176             {{ 1,  1}, { 1,  1}}  /* UBIDI_REORDER_INVERSE_NUMBERS_AS_L */
   3177         }
   3178     };
   3179 
   3180     #define SET_ROUND_TRIP_MODE(mode) \
   3181         ubidi_setReorderingMode(pBiDi, mode); \
   3182         desc = #mode; \
   3183         break;
   3184 
   3185     UErrorCode rc = U_ZERO_ERROR;
   3186     UChar dest2[MAXLEN];
   3187     int32_t destLen2;
   3188     const char* desc;
   3189     char destChars2[MAXLEN];
   3190     char destChars3[MAXLEN];
   3191 
   3192     switch (modes[mode].value) {
   3193         case UBIDI_REORDER_NUMBERS_SPECIAL:
   3194             SET_ROUND_TRIP_MODE(UBIDI_REORDER_INVERSE_FOR_NUMBERS_SPECIAL)
   3195         case UBIDI_REORDER_GROUP_NUMBERS_WITH_R:
   3196             SET_ROUND_TRIP_MODE(UBIDI_REORDER_GROUP_NUMBERS_WITH_R)
   3197         case UBIDI_REORDER_RUNS_ONLY:
   3198             SET_ROUND_TRIP_MODE(UBIDI_REORDER_RUNS_ONLY)
   3199         case UBIDI_REORDER_INVERSE_NUMBERS_AS_L:
   3200             SET_ROUND_TRIP_MODE(UBIDI_REORDER_DEFAULT)
   3201         case UBIDI_REORDER_INVERSE_LIKE_DIRECT:
   3202             SET_ROUND_TRIP_MODE(UBIDI_REORDER_DEFAULT)
   3203         case UBIDI_REORDER_INVERSE_FOR_NUMBERS_SPECIAL:
   3204             SET_ROUND_TRIP_MODE(UBIDI_REORDER_NUMBERS_SPECIAL)
   3205         default:
   3206             SET_ROUND_TRIP_MODE(UBIDI_REORDER_INVERSE_LIKE_DIRECT)
   3207     }
   3208     ubidi_setReorderingOptions(pBiDi, UBIDI_OPTION_REMOVE_CONTROLS);
   3209 
   3210     ubidi_setPara(pBiDi, dest, destLen, level, NULL, &rc);
   3211     assertSuccessful("ubidi_setPara", &rc);
   3212     *dest2 = 0;
   3213     destLen2 = ubidi_writeReordered(pBiDi, dest2, MAXLEN, UBIDI_DO_MIRRORING,
   3214                                     &rc);
   3215     assertSuccessful("ubidi_writeReordered", &rc);
   3216 
   3217     u16ToPseudo(destLen, dest, destChars3);
   3218     u16ToPseudo(destLen2, dest2, destChars2);
   3219     checkWhatYouCan(pBiDi, destChars3, destChars2);
   3220     if (strcmp(srcChars, destChars2)) {
   3221         if (roundtrip[tc][mode][option][level]) {
   3222             log_err("\nRound trip failed for case=%d mode=%d option=%d.\n"
   3223                     "%20s %s\n%20s %s\n%20s %s\n%20s %s\n%20s %s"
   3224                     "\n%20s %u\n", tc, mode, option,
   3225                     "Original text:", srcChars,
   3226                     "Round-tripped text:", destChars2,
   3227                     "Intermediate  text:", destChars3,
   3228                     "Reordering mode:", modes[mode].description,
   3229                     "Reordering option:", options[option].description,
   3230                     "Paragraph level:", level);
   3231         }
   3232         else {
   3233             log_verbose("\nExpected round trip failure for case=%d mode=%d option=%d.\n"
   3234                     "%20s %s\n%20s %s\n%20s %s\n%20s %s\n%20s %s"
   3235                     "\n%20s %u\n", tc, mode, option,
   3236                     "Original text:", srcChars,
   3237                     "Round-tripped text:", destChars2,
   3238                     "Intermediate  text:", destChars3,
   3239                     "Reordering mode:", modes[mode].description,
   3240                     "Reordering option:", options[option].description,
   3241                     "Paragraph level:", level);
   3242         }
   3243         return FALSE;
   3244     }
   3245     if (!checkResultLength(pBiDi, destChars, destChars2, destLen2,
   3246                            desc, "UBIDI_OPTION_REMOVE_CONTROLS", level)) {
   3247         return FALSE;
   3248     }
   3249     if (outIndex > -1 && !checkMaps(pBiDi, outIndex, srcChars, destChars,
   3250                                     desc, "UBIDI_OPTION_REMOVE_CONTROLS",
   3251                                     level, FALSE)) {
   3252         return FALSE;
   3253     }
   3254     return TRUE;
   3255 }
   3256 
   3257 static UBool
   3258 checkResultLength(UBiDi *pBiDi, const char *srcChars, const char *destChars,
   3259                   int32_t destLen, const char* mode,
   3260                   const char* option, UBiDiLevel level) {
   3261     int32_t actualLen;
   3262     if (strcmp(mode, "UBIDI_REORDER_INVERSE_NUMBERS_AS_L") == 0)
   3263         actualLen = strlen(destChars);
   3264     else
   3265         actualLen = ubidi_getResultLength(pBiDi);
   3266     if (actualLen != destLen) {
   3267         log_err("\nubidi_getResultLength failed.\n%20s %7d\n%20s %7d\n"
   3268                 "%20s %s\n%20s %s\n%20s %s\n%20s %s\n%20s %u\n",
   3269                 "Expected:", destLen, "Actual:", actualLen,
   3270                 "Input:", srcChars, "Output:", destChars,
   3271                 "Reordering mode:", mode, "Reordering option:", option,
   3272                 "Paragraph level:", level);
   3273         return FALSE;
   3274     }
   3275     return TRUE;
   3276 }
   3277 
   3278 static void
   3279 testReorderRunsOnly(void) {
   3280     static const struct {
   3281         const char* textIn;
   3282         const char* textOut[2][2];
   3283         const char noroundtrip[2];
   3284     } testCases[] = {
   3285         {"ab 234 896 de", {{"de 896 ab 234", "de 896 ab 234"},                   /*0*/
   3286                            {"ab 234 @896@ de", "de 896 ab 234"}}, {0, 0}},
   3287         {"abcGHI", {{"GHIabc", "GHIabc"}, {"GHIabc", "GHIabc"}}, {0, 0}},        /*1*/
   3288         {"a.>67->", {{"<-67<.a", "<-67<.a"}, {"<-67<.a", "<-67<.a"}}, {0, 0}},   /*2*/
   3289         {"-=%$123/ *", {{"* /%$123=-", "* /%$123=-"},                            /*3*/
   3290                         {"* /%$123=-", "* /%$123=-"}}, {0, 0}},
   3291         {"abc->12..>JKL", {{"JKL<..12<-abc", "JKL<..abc->12"},                   /*4*/
   3292                            {"JKL<..12<-abc", "JKL<..abc->12"}}, {0, 0}},
   3293         {"JKL->12..>abc", {{"abc<..JKL->12", "abc<..12<-JKL"},                   /*5*/
   3294                            {"abc<..JKL->12", "abc<..12<-JKL"}}, {0, 0}},
   3295         {"123->abc", {{"abc<-123", "abc<-123"},                                  /*6*/
   3296                       {"abc&<-123", "abc<-123"}}, {1, 0}},
   3297         {"123->JKL", {{"JKL<-123", "123->JKL"},                                  /*7*/
   3298                       {"JKL<-123", "JKL<-@123"}}, {0, 1}},
   3299         {"*>12.>34->JKL", {{"JKL<-34<.12<*", "12.>34->JKL<*"},                   /*8*/
   3300                            {"JKL<-34<.12<*", "JKL<-@34<.12<*"}}, {0, 1}},
   3301         {"*>67.>89->JKL", {{"67.>89->JKL<*", "67.>89->JKL<*"},                   /*9*/
   3302                            {"67.>89->JKL<*", "67.>89->JKL<*"}}, {0, 0}},
   3303         {"* /abc-=$%123", {{"$%123=-abc/ *", "abc-=$%123/ *"},                   /*10*/
   3304                            {"$%123=-abc/ *", "abc-=$%123/ *"}}, {0, 0}},
   3305         {"* /$%def-=123", {{"123=-def%$/ *", "def-=123%$/ *"},                   /*11*/
   3306                            {"123=-def%$/ *", "def-=123%$/ *"}}, {0, 0}},
   3307         {"-=GHI* /123%$", {{"GHI* /123%$=-", "123%$/ *GHI=-"},                   /*12*/
   3308                            {"GHI* /123%$=-", "123%$/ *GHI=-"}}, {0, 0}},
   3309         {"-=%$JKL* /123", {{"JKL* /%$123=-", "123/ *JKL$%=-"},                   /*13*/
   3310                            {"JKL* /%$123=-", "123/ *JKL$%=-"}}, {0, 0}},
   3311         {"ab =#CD *?450", {{"CD *?450#= ab", "450?* CD#= ab"},                   /*14*/
   3312                            {"CD *?450#= ab", "450?* CD#= ab"}}, {0, 0}},
   3313         {"ab 234 896 de", {{"de 896 ab 234", "de 896 ab 234"},                   /*15*/
   3314                            {"ab 234 @896@ de", "de 896 ab 234"}}, {0, 0}},
   3315         {"abc-=%$LMN* /123", {{"LMN* /%$123=-abc", "123/ *LMN$%=-abc"},          /*16*/
   3316                               {"LMN* /%$123=-abc", "123/ *LMN$%=-abc"}}, {0, 0}},
   3317         {"123->JKL&MN&P", {{"JKLMNP<-123", "123->JKLMNP"},                       /*17*/
   3318                            {"JKLMNP<-123", "JKLMNP<-@123"}}, {0, 1}},
   3319         {"123", {{"123", "123"},                /* just one run */               /*18*/
   3320                  {"123", "123"}}, {0, 0}}
   3321     };
   3322     UBiDi *pBiDi = getBiDiObject();
   3323     UBiDi *pL2VBiDi = getBiDiObject();
   3324     UChar src[MAXLEN], dest[MAXLEN], visual1[MAXLEN], visual2[MAXLEN];
   3325     char destChars[MAXLEN], vis1Chars[MAXLEN], vis2Chars[MAXLEN];
   3326     int32_t srcLen, destLen, vis1Len, vis2Len, option, i, j, nCases, paras;
   3327     UErrorCode rc = U_ZERO_ERROR;
   3328     UBiDiLevel level;
   3329 
   3330     log_verbose("\nEntering TestReorderRunsOnly\n\n");
   3331 
   3332     if(!pL2VBiDi) {
   3333         ubidi_close(pBiDi);             /* in case this one was allocated */
   3334         return;
   3335     }
   3336     ubidi_setReorderingMode(pBiDi, UBIDI_REORDER_RUNS_ONLY);
   3337     ubidi_setReorderingOptions(pL2VBiDi, UBIDI_OPTION_REMOVE_CONTROLS);
   3338 
   3339     for (option = 0; option < 2; option++) {
   3340         ubidi_setReorderingOptions(pBiDi, option==0 ? UBIDI_OPTION_REMOVE_CONTROLS
   3341                                                     : UBIDI_OPTION_INSERT_MARKS);
   3342         for (i = 0, nCases = LENGTHOF(testCases); i < nCases; i++) {
   3343             srcLen = strlen(testCases[i].textIn);
   3344             pseudoToU16(srcLen, testCases[i].textIn, src);
   3345             for(j = 0; j < 2; j++) {
   3346                 log_verbose("Now doing test for option %d, case %d, level %d\n",
   3347                             i, option, j);
   3348                 level = paraLevels[j];
   3349                 ubidi_setPara(pBiDi, src, srcLen, level, NULL, &rc);
   3350                 assertSuccessful("ubidi_setPara", &rc);
   3351                 *dest = 0;
   3352                 destLen = ubidi_writeReordered(pBiDi, dest, MAXLEN, UBIDI_DO_MIRRORING, &rc);
   3353                 assertSuccessful("ubidi_writeReordered", &rc);
   3354                 u16ToPseudo(destLen, dest, destChars);
   3355                 checkWhatYouCan(pBiDi, testCases[i].textIn, destChars);
   3356                 assertStringsEqual(testCases[i].textOut[option][level], destChars,
   3357                         testCases[i].textIn, "UBIDI_REORDER_RUNS_ONLY",
   3358                         option==0 ? "0" : "UBIDI_OPTION_INSERT_MARKS",
   3359                         pBiDi);
   3360 
   3361                 if((option==0) && testCases[i].noroundtrip[level]) {
   3362                     continue;
   3363                 }
   3364                 ubidi_setPara(pL2VBiDi, src, srcLen, level, NULL, &rc);
   3365                 assertSuccessful("ubidi_setPara1", &rc);
   3366                 *visual1 = 0;
   3367                 vis1Len = ubidi_writeReordered(pL2VBiDi, visual1, MAXLEN, UBIDI_DO_MIRRORING, &rc);
   3368                 assertSuccessful("ubidi_writeReordered1", &rc);
   3369                 u16ToPseudo(vis1Len, visual1, vis1Chars);
   3370                 checkWhatYouCan(pL2VBiDi, testCases[i].textIn, vis1Chars);
   3371                 ubidi_setPara(pL2VBiDi, dest, destLen, level^1, NULL, &rc);
   3372                 assertSuccessful("ubidi_setPara2", &rc);
   3373                 *visual2 = 0;
   3374                 vis2Len = ubidi_writeReordered(pL2VBiDi, visual2, MAXLEN, UBIDI_DO_MIRRORING, &rc);
   3375                 assertSuccessful("ubidi_writeReordered2", &rc);
   3376                 u16ToPseudo(vis2Len, visual2, vis2Chars);
   3377                 checkWhatYouCan(pL2VBiDi, destChars, vis2Chars);
   3378                 assertStringsEqual(vis1Chars, vis2Chars,
   3379                         testCases[i].textIn, "UBIDI_REORDER_RUNS_ONLY (2)",
   3380                         option==0 ? "0" : "UBIDI_OPTION_INSERT_MARKS",
   3381                         pBiDi);
   3382             }
   3383         }
   3384     }
   3385 
   3386     /* test with null or empty text */
   3387     ubidi_setPara(pBiDi, src, 0, UBIDI_LTR, NULL, &rc);
   3388     assertSuccessful("ubidi_setPara3", &rc);
   3389     paras = ubidi_countParagraphs(pBiDi);
   3390     if (paras != 0) {
   3391         log_err("\nInvalid number of paras (should be 0): %d\n", paras);
   3392     }
   3393 
   3394     ubidi_close(pBiDi);
   3395     ubidi_close(pL2VBiDi);
   3396 
   3397     log_verbose("\nExiting TestReorderRunsOnly\n\n");
   3398 }
   3399 
   3400 static void
   3401 testReorderingMode(void) {
   3402 
   3403     UChar src[MAXLEN], dest[MAXLEN];
   3404     char destChars[MAXLEN];
   3405     UBiDi *pBiDi = NULL, *pBiDi2 = NULL, *pBiDi3 = NULL;
   3406     UErrorCode rc;
   3407     int tc, mode, option, level;
   3408     uint32_t optionValue, optionBack;
   3409     UBiDiReorderingMode modeValue, modeBack;
   3410     int32_t srcLen, destLen, index;
   3411     const char *expectedChars;
   3412     UBool testOK = TRUE;
   3413 
   3414     log_verbose("\nEntering TestReorderingMode\n\n");
   3415 
   3416     pBiDi = getBiDiObject();
   3417     pBiDi2 = getBiDiObject();
   3418     pBiDi3 = getBiDiObject();
   3419     if(!pBiDi3) {
   3420         ubidi_close(pBiDi);             /* in case this one was allocated */
   3421         ubidi_close(pBiDi2);            /* in case this one was allocated */
   3422         return;
   3423     }
   3424 
   3425     ubidi_setInverse(pBiDi2, TRUE);
   3426 
   3427     for (tc = 0; tc < TC_COUNT; tc++) {
   3428         const char *srcChars = textIn[tc];
   3429         srcLen = strlen(srcChars);
   3430         pseudoToU16(srcLen, srcChars, src);
   3431 
   3432         for (mode = 0; mode < MODES_COUNT; mode++) {
   3433             modeValue = modes[mode].value;
   3434             ubidi_setReorderingMode(pBiDi, modeValue);
   3435             modeBack = ubidi_getReorderingMode(pBiDi);
   3436             if (modeValue != modeBack) {
   3437                 log_err("Error while setting reordering mode to %d, returned %d\n",
   3438                         modeValue, modeBack);
   3439             }
   3440 
   3441             for (option = 0; option < OPTIONS_COUNT; option++) {
   3442                 optionValue = options[option].value;
   3443                 ubidi_setReorderingOptions(pBiDi, optionValue);
   3444                 optionBack = ubidi_getReorderingOptions(pBiDi);
   3445                 if (optionValue != optionBack) {
   3446                     log_err("Error while setting reordering option to %d, returned %d\n",
   3447                             optionValue, optionBack);
   3448                 }
   3449 
   3450                 for (level = 0; level < LEVELS_COUNT; level++) {
   3451                     log_verbose("starting test %d mode=%d option=%d level=%d\n",
   3452                                 tc, modes[mode].value, options[option].value, level);
   3453                     rc = U_ZERO_ERROR;
   3454                     ubidi_setPara(pBiDi, src, srcLen, paraLevels[level], NULL, &rc);
   3455                     assertSuccessful("ubidi_setPara", &rc);
   3456 
   3457                     *dest = 0;
   3458                     destLen = ubidi_writeReordered(pBiDi, dest, MAXLEN,
   3459                                                    UBIDI_DO_MIRRORING, &rc);
   3460                     assertSuccessful("ubidi_writeReordered", &rc);
   3461                     u16ToPseudo(destLen, dest, destChars);
   3462                     if (!((modes[mode].value == UBIDI_REORDER_INVERSE_NUMBERS_AS_L) &&
   3463                           (options[option].value == UBIDI_OPTION_INSERT_MARKS))) {
   3464                         checkWhatYouCan(pBiDi, srcChars, destChars);
   3465                     }
   3466 
   3467                     if (modes[mode].value == UBIDI_REORDER_INVERSE_NUMBERS_AS_L) {
   3468                         index = -1;
   3469                         expectedChars = inverseBasic(pBiDi2, srcChars, srcLen,
   3470                                 options[option].value, paraLevels[level], destChars);
   3471                     }
   3472                     else {
   3473                         index = outIndices[tc][mode][option][level];
   3474                         expectedChars = textOut[index];
   3475                     }
   3476                     if (!assertStringsEqual(expectedChars, destChars, srcChars,
   3477                                 modes[mode].description,
   3478                                 options[option].description,
   3479                                 pBiDi)) {
   3480                         testOK = FALSE;
   3481                     }
   3482                     if (options[option].value == UBIDI_OPTION_INSERT_MARKS &&
   3483                              !assertRoundTrip(pBiDi3, tc, index, srcChars,
   3484                                               destChars, dest, destLen,
   3485                                               mode, option, paraLevels[level])) {
   3486                         testOK = FALSE;
   3487                     }
   3488                     else if (!checkResultLength(pBiDi, srcChars, destChars,
   3489                                 destLen, modes[mode].description,
   3490                                 options[option].description,
   3491                                 paraLevels[level])) {
   3492                         testOK = FALSE;
   3493                     }
   3494                     else if (index > -1 && !checkMaps(pBiDi, index, srcChars,
   3495                             destChars, modes[mode].description,
   3496                             options[option].description, paraLevels[level],
   3497                             TRUE)) {
   3498                         testOK = FALSE;
   3499                     }
   3500                 }
   3501             }
   3502         }
   3503     }
   3504     if (testOK == TRUE) {
   3505         log_verbose("\nReordering mode test OK\n");
   3506     }
   3507     ubidi_close(pBiDi3);
   3508     ubidi_close(pBiDi2);
   3509     ubidi_close(pBiDi);
   3510 
   3511     log_verbose("\nExiting TestReorderingMode\n\n");
   3512 }
   3513 
   3514 static const char* inverseBasic(UBiDi *pBiDi, const char *srcChars, int32_t srcLen,
   3515                                 uint32_t option, UBiDiLevel level, char *result) {
   3516     UErrorCode rc = U_ZERO_ERROR;
   3517     int32_t destLen;
   3518     UChar src[MAXLEN], dest2[MAXLEN];
   3519 
   3520     if (pBiDi == NULL || src == NULL) {
   3521         return NULL;
   3522     }
   3523     ubidi_setReorderingOptions(pBiDi, option);
   3524     pseudoToU16(srcLen, srcChars, src);
   3525     ubidi_setPara(pBiDi, src, srcLen, level, NULL, &rc);
   3526     assertSuccessful("ubidi_setPara", &rc);
   3527 
   3528     *dest2 = 0;
   3529     destLen = ubidi_writeReordered(pBiDi, dest2, MAXLEN,
   3530                                    UBIDI_DO_MIRRORING, &rc);
   3531     assertSuccessful("ubidi_writeReordered", &rc);
   3532     u16ToPseudo(destLen, dest2, result);
   3533     if (!(option == UBIDI_OPTION_INSERT_MARKS)) {
   3534         checkWhatYouCan(pBiDi, srcChars, result);
   3535     }
   3536     return result;
   3537 }
   3538 
   3539 #define NULL_CHAR '\0'
   3540 
   3541 static void
   3542 testStreaming(void) {
   3543 #define MAXPORTIONS 10
   3544 
   3545     static const struct {
   3546         const char* textIn;
   3547         short int chunk;
   3548         short int nPortions[2];
   3549         char  portionLens[2][MAXPORTIONS];
   3550         const char* message[2];
   3551     } testData[] = {
   3552         {   "123\\u000A"
   3553             "abc45\\u000D"
   3554             "67890\\u000A"
   3555             "\\u000D"
   3556             "02468\\u000D"
   3557             "ghi",
   3558             6, { 6, 6 }, {{ 6, 4, 6, 1, 6, 3}, { 4, 6, 6, 1, 6, 3 }},
   3559             {"6, 4, 6, 1, 6, 3", "4, 6, 6, 1, 6, 3"}
   3560         },
   3561         {   "abcd\\u000Afgh\\u000D12345\\u000A456",
   3562             6, { 4, 4 }, {{ 6, 3, 6, 3 }, { 5, 4, 6, 3 }},
   3563             {"6, 3, 6, 3", "5, 4, 6, 3"}
   3564         },
   3565         {   "abcd\\u000Afgh\\u000D12345\\u000A45\\u000D",
   3566             6, { 4, 4 }, {{ 6, 3, 6, 3 }, { 5, 4, 6, 3 }},
   3567             {"6, 3, 6, 3", "5, 4, 6, 3"}
   3568         },
   3569         {   "abcde\\u000Afghi",
   3570             10, { 1, 2 }, {{ 10 }, { 6, 4 }},
   3571             {"10", "6, 4"}
   3572         }
   3573     };
   3574     UChar src[MAXLEN];
   3575     UBiDi *pBiDi = NULL;
   3576     UChar *pSrc;
   3577     UErrorCode rc = U_ZERO_ERROR;
   3578     int32_t srcLen, processedLen, chunk, len, nPortions;
   3579     int i, j, levelIndex;
   3580     UBiDiLevel level;
   3581     int nTests = LENGTHOF(testData), nLevels = LENGTHOF(paraLevels);
   3582     UBool mismatch, testOK = TRUE;
   3583     char processedLenStr[MAXPORTIONS * 5];
   3584 
   3585     log_verbose("\nEntering TestStreaming\n\n");
   3586 
   3587     pBiDi = getBiDiObject();
   3588 
   3589     ubidi_orderParagraphsLTR(pBiDi, TRUE);
   3590 
   3591     for (levelIndex = 0; levelIndex < nLevels; levelIndex++) {
   3592         for (i = 0; i < nTests; i++) {
   3593             srcLen = u_unescape(testData[i].textIn, src, MAXLEN);
   3594             chunk = testData[i].chunk;
   3595             nPortions = testData[i].nPortions[levelIndex];
   3596             level = paraLevels[levelIndex];
   3597             *processedLenStr = NULL_CHAR;
   3598             log_verbose("Testing level %d, case %d\n", level, i);
   3599 
   3600             mismatch = FALSE;
   3601 
   3602             ubidi_setReorderingOptions(pBiDi, UBIDI_OPTION_STREAMING);
   3603             for (j = 0, pSrc = src; j < MAXPORTIONS && srcLen > 0; j++) {
   3604 
   3605                 len = chunk < srcLen ? chunk : srcLen;
   3606                 ubidi_setPara(pBiDi, pSrc, len, level, NULL, &rc);
   3607                 if (!assertSuccessful("ubidi_setPara", &rc)) {
   3608                     break;
   3609                 }
   3610 
   3611                 processedLen = ubidi_getProcessedLength(pBiDi);
   3612                 if (processedLen == 0) {
   3613                     ubidi_setReorderingOptions(pBiDi, UBIDI_OPTION_DEFAULT);
   3614                     j--;
   3615                     continue;
   3616                 }
   3617                 ubidi_setReorderingOptions(pBiDi, UBIDI_OPTION_STREAMING);
   3618 
   3619                 mismatch = (UBool)(j >= nPortions ||
   3620                            processedLen != testData[i].portionLens[levelIndex][j]);
   3621 
   3622                 sprintf(processedLenStr + j * 4, "%4d", processedLen);
   3623                 srcLen -= processedLen, pSrc += processedLen;
   3624             }
   3625 
   3626             if (mismatch || j != nPortions) {
   3627                 testOK = FALSE;
   3628                 log_err("\nProcessed lengths mismatch.\n"
   3629                     "\tParagraph level: %u\n"
   3630                     "\tInput string: %s\n"
   3631                     "\tActually processed portion lengths: { %s }\n"
   3632                     "\tExpected portion lengths          : { %s }\n",
   3633                     paraLevels[levelIndex], testData[i].textIn,
   3634                     processedLenStr, testData[i].message[levelIndex]);
   3635             }
   3636         }
   3637     }
   3638     ubidi_close(pBiDi);
   3639     if (testOK == TRUE) {
   3640         log_verbose("\nBiDi streaming test OK\n");
   3641     }
   3642     log_verbose("\nExiting TestStreaming\n\n");
   3643 }
   3644 
   3645 U_CDECL_BEGIN
   3646 
   3647 static UCharDirection U_CALLCONV
   3648 overrideBidiClass(const void *context, UChar32 c) {
   3649 
   3650 #define DEF U_BIDI_CLASS_DEFAULT
   3651 
   3652     static const UCharDirection customClasses[] = {
   3653        /* 0/8    1/9    2/A    3/B    4/C    5/D    6/E    7/F  */
   3654           DEF,   DEF,   DEF,   DEF,   DEF,   DEF,   DEF,   DEF, /* 00-07 */
   3655           DEF,   DEF,   DEF,   DEF,   DEF,   DEF,   DEF,   DEF, /* 08-0F */
   3656           DEF,   DEF,   DEF,   DEF,   DEF,   DEF,   DEF,   DEF, /* 10-17 */
   3657           DEF,   DEF,   DEF,   DEF,   DEF,   DEF,   DEF,   DEF, /* 18-1F */
   3658           DEF,   DEF,   DEF,   DEF,   DEF,   DEF,     R,   DEF, /* 20-27 */
   3659           DEF,   DEF,   DEF,   DEF,   DEF,   DEF,   DEF,   DEF, /* 28-2F */
   3660            EN,    EN,    EN,    EN,    EN,    EN,    AN,    AN, /* 30-37 */
   3661            AN,    AN,   DEF,   DEF,   DEF,   DEF,   DEF,   DEF, /* 38-3F */
   3662             L,    AL,    AL,    AL,    AL,    AL,    AL,     R, /* 40-47 */
   3663             R,     R,     R,     R,     R,     R,     R,     R, /* 48-4F */
   3664             R,     R,     R,     R,     R,     R,     R,     R, /* 50-57 */
   3665             R,     R,     R,   LRE,   DEF,   RLE,   PDF,     S, /* 58-5F */
   3666           NSM,   DEF,   DEF,   DEF,   DEF,   DEF,   DEF,   DEF, /* 60-67 */
   3667           DEF,   DEF,   DEF,   DEF,   DEF,   DEF,   DEF,   DEF, /* 68-6F */
   3668           DEF,   DEF,   DEF,   DEF,   DEF,   DEF,   DEF,   DEF, /* 70-77 */
   3669           DEF,   DEF,   DEF,   LRO,     B,   RLO,    BN,   DEF  /* 78-7F */
   3670     };
   3671     static const int nEntries = LENGTHOF(customClasses);
   3672     const char *dummy = context;        /* just to avoid a compiler warning */
   3673     dummy++;
   3674 
   3675     return c >= nEntries ? U_BIDI_CLASS_DEFAULT : customClasses[c];
   3676 }
   3677 
   3678 U_CDECL_END
   3679 
   3680 static void verifyCallbackParams(UBiDiClassCallback* fn, const void* context,
   3681                                  UBiDiClassCallback* expectedFn,
   3682                                  const void* expectedContext,
   3683                                  int32_t sizeOfContext) {
   3684     if (fn != expectedFn) {
   3685         log_err("Class callback pointer is not set properly.\n");
   3686     }
   3687     if (context != expectedContext) {
   3688         log_err("Class callback context is not set properly.\n");
   3689     }
   3690     else if (context != NULL &&
   3691             memcmp(context, expectedContext, sizeOfContext)) {
   3692         log_err("Callback context content doesn't match the expected one.\n");
   3693     }
   3694 }
   3695 
   3696 static void
   3697 testClassOverride(void) {
   3698     static const char* const textSrc  = "JIH.>12->a \\u05D0\\u05D1 6 ABC78";
   3699     static const char* const textResult = "12<.HIJ->a 78CBA 6 \\u05D1\\u05D0";
   3700 
   3701     UChar src[MAXLEN], dest[MAXLEN];
   3702     UErrorCode rc = U_ZERO_ERROR;
   3703     UBiDi *pBiDi = NULL;
   3704     UBiDiClassCallback* oldFn = NULL;
   3705     UBiDiClassCallback* newFn = overrideBidiClass;
   3706     const void* oldContext = NULL;
   3707     int32_t srcLen, destLen, textSrcSize = (int32_t)uprv_strlen(textSrc);
   3708     char* destChars = NULL;
   3709 
   3710     log_verbose("\nEntering TestClassOverride\n\n");
   3711 
   3712     pBiDi = getBiDiObject();
   3713     if(!pBiDi) {
   3714         return;
   3715     }
   3716 
   3717     ubidi_getClassCallback(pBiDi, &oldFn, &oldContext);
   3718     verifyCallbackParams(oldFn, oldContext, NULL, NULL, 0);
   3719 
   3720     ubidi_setClassCallback(pBiDi, newFn, textSrc, &oldFn, &oldContext, &rc);
   3721     if (!assertSuccessful("ubidi_setClassCallback", &rc)) {
   3722         ubidi_close(pBiDi);
   3723         return;
   3724     }
   3725     verifyCallbackParams(oldFn, oldContext, NULL, NULL, 0);
   3726 
   3727     ubidi_getClassCallback(pBiDi, &oldFn, &oldContext);
   3728     verifyCallbackParams(oldFn, oldContext, newFn, textSrc, textSrcSize);
   3729 
   3730     ubidi_setClassCallback(pBiDi, newFn, textSrc, &oldFn, &oldContext, &rc);
   3731     if (!assertSuccessful("ubidi_setClassCallback", &rc)) {
   3732         ubidi_close(pBiDi);
   3733         return;
   3734     }
   3735     verifyCallbackParams(oldFn, oldContext, newFn, textSrc, textSrcSize);
   3736 
   3737     srcLen = u_unescape(textSrc, src, MAXLEN);
   3738     ubidi_setPara(pBiDi, src, srcLen, UBIDI_LTR, NULL, &rc);
   3739     assertSuccessful("ubidi_setPara", &rc);
   3740 
   3741     destLen = ubidi_writeReordered(pBiDi, dest, MAXLEN,
   3742                                    UBIDI_DO_MIRRORING, &rc);
   3743     assertSuccessful("ubidi_writeReordered", &rc);
   3744 
   3745     destChars = aescstrdup(dest, destLen);
   3746     if (uprv_strcmp(textResult, destChars)) {
   3747         log_err("\nActual and expected output mismatch.\n"
   3748             "%20s %s\n%20s %s\n%20s %s\n",
   3749             "Input:", textSrc, "Actual output:", destChars,
   3750             "Expected output:", textResult);
   3751     }
   3752     else {
   3753         log_verbose("\nClass override test OK\n");
   3754     }
   3755     ubidi_close(pBiDi);
   3756     log_verbose("\nExiting TestClassOverride\n\n");
   3757 }
   3758 
   3759 static char * formatMap(const int32_t * map, int len, char * buffer)
   3760 {
   3761     int32_t i, k;
   3762     char c;
   3763     for (i = 0; i < len; i++) {
   3764         k = map[i];
   3765         if (k < 0)
   3766             c = '-';
   3767         else if (k >= sizeof(columns))
   3768             c = '+';
   3769         else
   3770             c = columns[k];
   3771         buffer[i] = c;
   3772     }
   3773     buffer[len] = '\0';
   3774     return buffer;
   3775 }
   3776 
   3777 static UBool
   3778 checkMaps(UBiDi *pBiDi, int32_t stringIndex, const char *src, const char *dest,
   3779           const char *mode, const char* option, UBiDiLevel level, UBool forward)
   3780 {
   3781     int32_t actualLogicalMap[MAX_MAP_LENGTH];
   3782     int32_t actualVisualMap[MAX_MAP_LENGTH];
   3783     int32_t getIndexMap[MAX_MAP_LENGTH];
   3784     int32_t i, srcLen, resLen, index;
   3785     const int32_t *expectedLogicalMap, *expectedVisualMap;
   3786     UErrorCode rc = U_ZERO_ERROR;
   3787     UBool testOK = TRUE;
   3788 
   3789     if (forward) {
   3790         expectedLogicalMap = forwardMap[stringIndex];
   3791         expectedVisualMap  = inverseMap[stringIndex];
   3792     }
   3793     else {
   3794         expectedLogicalMap = inverseMap[stringIndex];
   3795         expectedVisualMap  = forwardMap[stringIndex];
   3796     }
   3797     ubidi_getLogicalMap(pBiDi, actualLogicalMap, &rc);
   3798     if (!assertSuccessful("ubidi_getLogicalMap", &rc)) {
   3799         testOK = FALSE;
   3800     }
   3801     srcLen = ubidi_getProcessedLength(pBiDi);
   3802     if (memcmp(expectedLogicalMap, actualLogicalMap, srcLen * sizeof(int32_t))) {
   3803         char expChars[MAX_MAP_LENGTH];
   3804         char actChars[MAX_MAP_LENGTH];
   3805         log_err("\nubidi_getLogicalMap() returns unexpected map for output string "
   3806                 "index %d\n"
   3807                 "source: %s\n"
   3808                 "dest  : %s\n"
   3809                 "Scale : %s\n"
   3810                 "ExpMap: %s\n"
   3811                 "Actual: %s\n"
   3812                 "Paragraph level  : %d == %d\n"
   3813                 "Reordering mode  : %s == %d\n"
   3814                 "Reordering option: %s == %d\n"
   3815                 "Forward flag     : %d\n",
   3816                 stringIndex, src, dest, columns,
   3817                 formatMap(expectedLogicalMap, srcLen, expChars),
   3818                 formatMap(actualLogicalMap, srcLen, actChars),
   3819                 level, ubidi_getParaLevel(pBiDi),
   3820                 mode, ubidi_getReorderingMode(pBiDi),
   3821                 option, ubidi_getReorderingOptions(pBiDi),
   3822                 forward
   3823                 );
   3824         testOK = FALSE;
   3825     }
   3826     resLen = ubidi_getResultLength(pBiDi);
   3827     ubidi_getVisualMap(pBiDi, actualVisualMap, &rc);
   3828     assertSuccessful("ubidi_getVisualMap", &rc);
   3829     if (memcmp(expectedVisualMap, actualVisualMap, resLen * sizeof(int32_t))) {
   3830         char expChars[MAX_MAP_LENGTH];
   3831         char actChars[MAX_MAP_LENGTH];
   3832         log_err("\nubidi_getVisualMap() returns unexpected map for output string "
   3833                 "index %d\n"
   3834                 "source: %s\n"
   3835                 "dest  : %s\n"
   3836                 "Scale : %s\n"
   3837                 "ExpMap: %s\n"
   3838                 "Actual: %s\n"
   3839                 "Paragraph level  : %d == %d\n"
   3840                 "Reordering mode  : %s == %d\n"
   3841                 "Reordering option: %s == %d\n"
   3842                 "Forward flag     : %d\n",
   3843                 stringIndex, src, dest, columns,
   3844                 formatMap(expectedVisualMap, resLen, expChars),
   3845                 formatMap(actualVisualMap, resLen, actChars),
   3846                 level, ubidi_getParaLevel(pBiDi),
   3847                 mode, ubidi_getReorderingMode(pBiDi),
   3848                 option, ubidi_getReorderingOptions(pBiDi),
   3849                 forward
   3850                 );
   3851         testOK = FALSE;
   3852     }
   3853     for (i = 0; i < srcLen; i++) {
   3854         index = ubidi_getVisualIndex(pBiDi, i, &rc);
   3855         assertSuccessful("ubidi_getVisualIndex", &rc);
   3856         getIndexMap[i] = index;
   3857     }
   3858     if (memcmp(actualLogicalMap, getIndexMap, srcLen * sizeof(int32_t))) {
   3859         char actChars[MAX_MAP_LENGTH];
   3860         char gotChars[MAX_MAP_LENGTH];
   3861         log_err("\nMismatch between ubidi_getLogicalMap and ubidi_getVisualIndex for output string "
   3862                 "index %d\n"
   3863                 "source: %s\n"
   3864                 "dest  : %s\n"
   3865                 "Scale : %s\n"
   3866                 "ActMap: %s\n"
   3867                 "IdxMap: %s\n"
   3868                 "Paragraph level  : %d == %d\n"
   3869                 "Reordering mode  : %s == %d\n"
   3870                 "Reordering option: %s == %d\n"
   3871                 "Forward flag     : %d\n",
   3872                 stringIndex, src, dest, columns,
   3873                 formatMap(actualLogicalMap, srcLen, actChars),
   3874                 formatMap(getIndexMap, srcLen, gotChars),
   3875                 level, ubidi_getParaLevel(pBiDi),
   3876                 mode, ubidi_getReorderingMode(pBiDi),
   3877                 option, ubidi_getReorderingOptions(pBiDi),
   3878                 forward
   3879                 );
   3880         testOK = FALSE;
   3881     }
   3882     for (i = 0; i < resLen; i++) {
   3883         index = ubidi_getLogicalIndex(pBiDi, i, &rc);
   3884         assertSuccessful("ubidi_getLogicalIndex", &rc);
   3885         getIndexMap[i] = index;
   3886     }
   3887     if (memcmp(actualVisualMap, getIndexMap, resLen * sizeof(int32_t))) {
   3888         char actChars[MAX_MAP_LENGTH];
   3889         char gotChars[MAX_MAP_LENGTH];
   3890         log_err("\nMismatch between ubidi_getVisualMap and ubidi_getLogicalIndex for output string "
   3891                 "index %d\n"
   3892                 "source: %s\n"
   3893                 "dest  : %s\n"
   3894                 "Scale : %s\n"
   3895                 "ActMap: %s\n"
   3896                 "IdxMap: %s\n"
   3897                 "Paragraph level  : %d == %d\n"
   3898                 "Reordering mode  : %s == %d\n"
   3899                 "Reordering option: %s == %d\n"
   3900                 "Forward flag     : %d\n",
   3901                 stringIndex, src, dest, columns,
   3902                 formatMap(actualVisualMap, resLen, actChars),
   3903                 formatMap(getIndexMap, resLen, gotChars),
   3904                 level, ubidi_getParaLevel(pBiDi),
   3905                 mode, ubidi_getReorderingMode(pBiDi),
   3906                 option, ubidi_getReorderingOptions(pBiDi),
   3907                 forward
   3908                 );
   3909         testOK = FALSE;
   3910     }
   3911     return testOK;
   3912 }
   3913 
   3914