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