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