Home | History | Annotate | Download | only in bidi
      1 //  2016 and later: Unicode, Inc. and others.
      2 // License & terms of use: http://www.unicode.org/copyright.html#License
      3 /*
      4 *******************************************************************************
      5 *   Copyright (C) 2001-2010, International Business Machines
      6 *   Corporation and others.  All Rights Reserved.
      7 *******************************************************************************
      8 */
      9 
     10 package com.ibm.icu.dev.test.bidi;
     11 
     12 import java.util.Arrays;
     13 
     14 import org.junit.Test;
     15 
     16 import com.ibm.icu.text.Bidi;
     17 
     18 /**
     19  * Regression test for variants to the UBA.
     20  *
     21  * @author Lina Kemmel, Matitiahu Allouche
     22  */
     23 
     24 public class TestReorderingMode extends BidiFmwk {
     25 
     26     static final String[] textIn = {
     27     /* (0) 123 */
     28         "123",
     29     /* (1) .123->4.5 */
     30         ".123->4.5",
     31     /* (2) 678 */
     32         "678",
     33     /* (3) .678->8.9 */
     34         ".678->8.9",
     35     /* (4) JIH1.2,3MLK */
     36         "JIH1.2,3MLK",
     37     /* (5) FE.>12-> */
     38         "FE.>12->",
     39     /* (6) JIH.>12->a */
     40         "JIH.>12->a",
     41     /* (7) CBA.>67->89=a */
     42         "CBA.>67->89=a",
     43     /* (8) CBA.123->xyz */
     44         "CBA.123->xyz",
     45     /* (9) .>12->xyz */
     46         ".>12->xyz",
     47     /* (10) a.>67->xyz */
     48         "a.>67->xyz",
     49     /* (11) 123JIH */
     50         "123JIH",
     51     /* (12) 123 JIH */
     52         "123 JIH"
     53     };
     54 
     55     static final String[] textOut = {
     56     /* TC 0: 123 */
     57         "123",                                                              /* (0) */
     58     /* TC 1: .123->4.5 */
     59         ".123->4.5",                                                        /* (1) */
     60         "4.5<-123.",                                                        /* (2) */
     61     /* TC 2: 678 */
     62         "678",                                                              /* (3) */
     63     /* TC 3: .678->8.9 */
     64         ".8.9<-678",                                                        /* (4) */
     65         "8.9<-678.",                                                        /* (5) */
     66         ".678->8.9",                                                        /* (6) */
     67     /* TC 4: MLK1.2,3JIH */
     68         "KLM1.2,3HIJ",                                                      /* (7) */
     69     /* TC 5: FE.>12-> */
     70         "12<.EF->",                                                         /* (8) */
     71         "<-12<.EF",                                                         /* (9) */
     72         "EF.>@12->",                                                        /* (10) */
     73     /* TC 6: JIH.>12->a */
     74         "12<.HIJ->a",                                                       /* (11) */
     75         "a<-12<.HIJ",                                                       /* (12) */
     76         "HIJ.>@12->a",                                                      /* (13) */
     77         "a&<-12<.HIJ",                                                      /* (14) */
     78     /* TC 7: CBA.>67->89=a */
     79         "ABC.>@67->89=a",                                                   /* (15) */
     80         "a=89<-67<.ABC",                                                    /* (16) */
     81         "a&=89<-67<.ABC",                                                   /* (17) */
     82         "89<-67<.ABC=a",                                                    /* (18) */
     83     /* TC 8: CBA.123->xyz */
     84         "123.ABC->xyz",                                                     /* (19) */
     85         "xyz<-123.ABC",                                                     /* (20) */
     86         "ABC.@123->xyz",                                                    /* (21) */
     87         "xyz&<-123.ABC",                                                    /* (22) */
     88     /* TC 9: .>12->xyz */
     89         ".>12->xyz",                                                        /* (23) */
     90         "xyz<-12<.",                                                        /* (24) */
     91         "xyz&<-12<.",                                                       /* (25) */
     92     /* TC 10: a.>67->xyz */
     93         "a.>67->xyz",                                                       /* (26) */
     94         "a.>@67@->xyz",                                                     /* (27) */
     95         "xyz<-67<.a",                                                       /* (28) */
     96     /* TC 11: 123JIH */
     97         "123HIJ",                                                           /* (29) */
     98         "HIJ123",                                                           /* (30) */
     99     /* TC 12: 123 JIH */
    100         "123 HIJ",                                                          /* (31) */
    101         "HIJ 123",                                                          /* (32) */
    102     };
    103 
    104     static final int[][][][] outIndices = {
    105         { /* TC 0: 123 */
    106             {{ 0,  0}, { 0,  0}}, /* REORDER_GROUP_NUMBERS_WITH_R */
    107             {{ 0,  0}, { 0,  0}}, /* REORDER_INVERSE_LIKE_DIRECT */
    108             {{ 0,  0}, { 0,  0}}, /* REORDER_NUMBERS_SPECIAL */
    109             {{ 0,  0}, { 0,  0}}  /* REORDER_INVERSE_FOR_NUMBERS_SPECIAL */
    110         },
    111         { /* TC 1: .123->4.5 */
    112             {{ 1,  2}, { 1,  2}}, /* REORDER_GROUP_NUMBERS_WITH_R */
    113             {{ 1,  2}, { 1,  2}}, /* REORDER_INVERSE_LIKE_DIRECT */
    114             {{ 1,  2}, { 1,  2}}, /* REORDER_NUMBERS_SPECIAL */
    115             {{ 1,  2}, { 1,  2}}  /* REORDER_INVERSE_FOR_NUMBERS_SPECIAL */
    116         },
    117         { /* TC 2: 678 */
    118             {{ 3,  3}, { 3,  3}}, /* REORDER_GROUP_NUMBERS_WITH_R */
    119             {{ 3,  3}, { 3,  3}}, /* REORDER_INVERSE_LIKE_DIRECT */
    120             {{ 3,  3}, { 3,  3}}, /* REORDER_NUMBERS_SPECIAL */
    121             {{ 3,  3}, { 3,  3}}  /* REORDER_INVERSE_FOR_NUMBERS_SPECIAL */
    122         },
    123         { /* TC 3: .678->8.9 */
    124             {{ 6,  5}, { 6,  5}}, /* REORDER_GROUP_NUMBERS_WITH_R */
    125             {{ 4,  5}, { 4,  5}}, /* REORDER_INVERSE_LIKE_DIRECT */
    126             {{ 6,  5}, { 6,  5}}, /* REORDER_NUMBERS_SPECIAL */
    127             {{ 6,  5}, { 6,  5}}  /* REORDER_INVERSE_FOR_NUMBERS_SPECIAL */
    128         },
    129         { /* TC 4: MLK1.2,3JIH */
    130             {{ 7,  7}, { 7,  7}}, /* REORDER_GROUP_NUMBERS_WITH_R */
    131             {{ 7,  7}, { 7,  7}}, /* REORDER_INVERSE_LIKE_DIRECT */
    132             {{ 7,  7}, { 7,  7}}, /* REORDER_NUMBERS_SPECIAL */
    133             {{ 7,  7}, { 7,  7}}  /* REORDER_INVERSE_FOR_NUMBERS_SPECIAL */
    134         },
    135         { /* TC 5: FE.>12-> */
    136             {{ 8,  9}, { 8,  9}}, /* REORDER_GROUP_NUMBERS_WITH_R */
    137             {{10,  9}, { 8,  9}}, /* REORDER_INVERSE_LIKE_DIRECT */
    138             {{ 8,  9}, { 8,  9}}, /* REORDER_NUMBERS_SPECIAL */
    139             {{10,  9}, { 8,  9}}  /* REORDER_INVERSE_FOR_NUMBERS_SPECIAL */
    140         },
    141         { /* TC 6: JIH.>12->a */
    142             {{11, 12}, {11, 12}}, /* REORDER_GROUP_NUMBERS_WITH_R */
    143             {{13, 14}, {11, 12}}, /* REORDER_INVERSE_LIKE_DIRECT */
    144             {{11, 12}, {11, 12}}, /* REORDER_NUMBERS_SPECIAL */
    145             {{13, 14}, {11, 12}}  /* REORDER_INVERSE_FOR_NUMBERS_SPECIAL */
    146         },
    147         { /* TC 7: CBA.>67->89=a */
    148             {{18, 16}, {18, 16}}, /* REORDER_GROUP_NUMBERS_WITH_R */
    149             {{18, 17}, {18, 16}}, /* REORDER_INVERSE_LIKE_DIRECT */
    150             {{18, 16}, {18, 16}}, /* REORDER_NUMBERS_SPECIAL */
    151             {{15, 17}, {18, 16}}  /* REORDER_INVERSE_FOR_NUMBERS_SPECIAL */
    152         },
    153         { /* TC 8: CBA.>124->xyz */
    154             {{19, 20}, {19, 20}}, /* REORDER_GROUP_NUMBERS_WITH_R */
    155             {{21, 22}, {19, 20}}, /* REORDER_INVERSE_LIKE_DIRECT */
    156             {{19, 20}, {19, 20}}, /* REORDER_NUMBERS_SPECIAL */
    157             {{21, 22}, {19, 20}}  /* REORDER_INVERSE_FOR_NUMBERS_SPECIAL */
    158         },
    159         { /* TC 9: .>12->xyz */
    160             {{23, 24}, {23, 24}}, /* REORDER_GROUP_NUMBERS_WITH_R */
    161             {{23, 25}, {23, 24}}, /* REORDER_INVERSE_LIKE_DIRECT */
    162             {{23, 24}, {23, 24}}, /* REORDER_NUMBERS_SPECIAL */
    163             {{23, 25}, {23, 24}}  /* REORDER_INVERSE_FOR_NUMBERS_SPECIAL */
    164         },
    165         { /* TC 10: a.>67->xyz */
    166             {{26, 26}, {26, 26}}, /* REORDER_GROUP_NUMBERS_WITH_R */
    167             {{26, 27}, {26, 28}}, /* REORDER_INVERSE_LIKE_DIRECT */
    168             {{26, 28}, {26, 28}}, /* REORDER_NUMBERS_SPECIAL */
    169             {{26, 27}, {26, 28}}  /* REORDER_INVERSE_FOR_NUMBERS_SPECIAL */
    170         },
    171         { /* TC 11: 124JIH */
    172             {{30, 30}, {30, 30}}, /* REORDER_GROUP_NUMBERS_WITH_R */
    173             {{29, 30}, {29, 30}}, /* REORDER_INVERSE_LIKE_DIRECT */
    174             {{30, 30}, {30, 30}}, /* REORDER_NUMBERS_SPECIAL */
    175             {{30, 30}, {30, 30}}  /* REORDER_INVERSE_FOR_NUMBERS_SPECIAL */
    176         },
    177         { /* TC 12: 124 JIH */
    178             {{32, 32}, {32, 32}}, /* REORDER_GROUP_NUMBERS_WITH_R */
    179             {{31, 32}, {31, 32}}, /* REORDER_INVERSE_LIKE_DIRECT */
    180             {{31, 32}, {31, 32}}, /* REORDER_NUMBERS_SPECIAL */
    181             {{31, 32}, {31, 32}}  /* REORDER_INVERSE_FOR_NUMBERS_SPECIAL */
    182         }
    183     };
    184 
    185     static final short[] modes = {
    186         Bidi.REORDER_GROUP_NUMBERS_WITH_R,
    187         Bidi.REORDER_INVERSE_LIKE_DIRECT,
    188         Bidi.REORDER_NUMBERS_SPECIAL,
    189         Bidi.REORDER_INVERSE_FOR_NUMBERS_SPECIAL,
    190         Bidi.REORDER_INVERSE_NUMBERS_AS_L
    191     };
    192 
    193     static final int[] options = { Bidi.OPTION_INSERT_MARKS, 0 };
    194 
    195     static final byte[] paraLevels = { Bidi.LTR, Bidi.RTL };
    196 
    197     static final int TC_COUNT = textIn.length;
    198     static final int MODES_COUNT = modes.length;
    199     static final int OPTIONS_COUNT = options.length;
    200     static final int LEVELS_COUNT = paraLevels.length;
    201 
    202     @Test
    203     public void testReorderingMode() {
    204 
    205         String src, dest;
    206         Bidi bidi = new Bidi();
    207         Bidi bidi2 = new Bidi();
    208         Bidi bidi3 = new Bidi();
    209         int tc, mode, option, level;
    210         int modeValue, modeBack;
    211         int optionValue, optionBack;
    212         int index;
    213         String expected;
    214         boolean testOK = true;
    215 
    216         logln("\nEntering TestReorderingMode\n");
    217 
    218         bidi2.setInverse(true);
    219 
    220         for (tc = 0; tc < TC_COUNT; tc++) {
    221             src = textIn[tc];
    222 
    223             for (mode = 0; mode < MODES_COUNT; mode++) {
    224                 modeValue = modes[mode];
    225                 bidi.setReorderingMode(modeValue);
    226                 modeBack = bidi.getReorderingMode();
    227                 if (modeValue != modeBack) {
    228                     errln("Error while setting reordering mode to " +
    229                     modeValue + ", returned " + modeBack);
    230                 }
    231 
    232                 for (option = 0; option < OPTIONS_COUNT; option++) {
    233                     optionValue = options[option];
    234                     bidi.setReorderingOptions(optionValue);
    235                     optionBack = bidi.getReorderingOptions();
    236                     if (optionValue != optionBack) {
    237                         errln("Error while setting reordering options to " +
    238                         modeValue + ", returned " + modeBack);
    239                     }
    240 
    241                     for (level = 0; level < LEVELS_COUNT; level++) {
    242                         logln("starting test " + tc + " mode=" + modeValue +
    243                             " option=" + optionValue + " level=" + level);
    244                         bidi.setPara(pseudoToU16(src), paraLevels[level], null);
    245 
    246                         dest = bidi.writeReordered(Bidi.DO_MIRRORING);
    247                         dest = u16ToPseudo(dest);
    248                         if (!((modeValue == Bidi.REORDER_INVERSE_NUMBERS_AS_L) &&
    249                               (optionValue == Bidi.OPTION_INSERT_MARKS))) {
    250                             checkWhatYouCan(bidi, src, dest);
    251                         }
    252                         String modeDesc = modeToString(modeValue);
    253                         String optDesc = spOptionsToString(optionValue);
    254 
    255                         if (modeValue == Bidi.REORDER_INVERSE_NUMBERS_AS_L) {
    256                             index = -1;
    257                             expected = inverseBasic(bidi2, src, optionValue,
    258                                                     paraLevels[level]);
    259                         }
    260                         else {
    261                             index = outIndices[tc][mode][option][level];
    262                             expected = textOut[index];
    263                         }
    264                         if (!assertEquals("Actual and expected output mismatch",
    265                                           expected, dest, src, modeDesc, optDesc,
    266                                           String.valueOf(level))) {
    267                             testOK = false;
    268                             continue;
    269                         }
    270                         if ((optionValue == Bidi.OPTION_INSERT_MARKS) &&
    271                             !assertRoundTrip(bidi3, tc, index, src, dest,
    272                                              mode, option,
    273                                              paraLevels[level])) {
    274                             testOK = false;
    275                             continue;
    276                         }
    277                         if (!checkResultLength(bidi, src, dest, modeDesc, optDesc,
    278                                                paraLevels[level])) {
    279                             testOK = false;
    280                             continue;
    281                         }
    282                         if ((index > -1) &&
    283                             !checkMaps(bidi, index, src, dest, modeDesc, optDesc,
    284                                        paraLevels[level], true)) {
    285                             testOK = false;
    286                         }
    287                     }
    288                 }
    289             }
    290         }
    291         if (testOK) {
    292             logln("Reordering mode test OK");
    293         }
    294 
    295         logln("\nExiting TestReorderingMode\n");
    296     }
    297 
    298     String inverseBasic(Bidi bidi, String src, int option, byte level) {
    299         String dest2;
    300 
    301         if (bidi == null || src == null) {
    302             return null;
    303         }
    304         bidi.setReorderingOptions(option);
    305         bidi.setPara(pseudoToU16(src), level, null);
    306         dest2 = u16ToPseudo(bidi.writeReordered(Bidi.DO_MIRRORING));
    307         if (!(option == Bidi.OPTION_INSERT_MARKS)) {
    308             checkWhatYouCan(bidi, src, dest2);
    309         }
    310         return dest2;
    311     }
    312 
    313     static final byte roundtrip[][][][] =
    314     {
    315         { /* TC 0: 123 */
    316             {{ 1,  1}, { 1,  1}}, /* REORDER_GROUP_NUMBERS_WITH_R */
    317             {{ 1,  1}, { 1,  1}}, /* REORDER_INVERSE_LIKE_DIRECT */
    318             {{ 1,  1}, { 1,  1}}, /* REORDER_NUMBERS_SPECIAL */
    319             {{ 1,  1}, { 1,  1}}, /* REORDER_INVERSE_FOR_NUMBERS_SPECIAL */
    320             {{ 1,  1}, { 1,  1}}  /* REORDER_INVERSE_NUMBERS_AS_L */
    321         },
    322         { /* TC 1: .123->4.5 */
    323             {{ 1,  1}, { 1,  1}}, /* REORDER_GROUP_NUMBERS_WITH_R */
    324             {{ 1,  1}, { 1,  1}}, /* REORDER_INVERSE_LIKE_DIRECT */
    325             {{ 1,  1}, { 1,  1}}, /* REORDER_NUMBERS_SPECIAL */
    326             {{ 1,  1}, { 1,  1}}, /* REORDER_INVERSE_FOR_NUMBERS_SPECIAL */
    327             {{ 1,  1}, { 1,  1}}  /* REORDER_INVERSE_NUMBERS_AS_L */
    328         },
    329         { /* TC 2: 678 */
    330             {{ 1,  1}, { 1,  1}}, /* REORDER_GROUP_NUMBERS_WITH_R */
    331             {{ 1,  1}, { 1,  1}}, /* REORDER_INVERSE_LIKE_DIRECT */
    332             {{ 1,  1}, { 1,  1}}, /* REORDER_NUMBERS_SPECIAL */
    333             {{ 1,  1}, { 1,  1}}, /* REORDER_INVERSE_FOR_NUMBERS_SPECIAL */
    334             {{ 1,  1}, { 1,  1}}  /* REORDER_INVERSE_NUMBERS_AS_L */
    335         },
    336         { /* TC 3: .678->8.9 */
    337             {{ 1,  1}, { 1,  1}}, /* REORDER_GROUP_NUMBERS_WITH_R */
    338             {{ 1,  1}, { 1,  1}}, /* REORDER_INVERSE_LIKE_DIRECT */
    339             {{ 1,  1}, { 1,  1}}, /* REORDER_NUMBERS_SPECIAL */
    340             {{ 1,  1}, { 1,  1}}, /* REORDER_INVERSE_FOR_NUMBERS_SPECIAL */
    341             {{ 0,  0}, { 1,  1}}  /* REORDER_INVERSE_NUMBERS_AS_L */
    342         },
    343         { /* TC 4: MLK1.2,3JIH */
    344             {{ 1,  1}, { 1,  1}}, /* REORDER_GROUP_NUMBERS_WITH_R */
    345             {{ 1,  1}, { 1,  1}}, /* REORDER_INVERSE_LIKE_DIRECT */
    346             {{ 1,  1}, { 1,  1}}, /* REORDER_NUMBERS_SPECIAL */
    347             {{ 1,  1}, { 1,  1}}, /* REORDER_INVERSE_FOR_NUMBERS_SPECIAL */
    348             {{ 1,  1}, { 1,  1}}  /* REORDER_INVERSE_NUMBERS_AS_L */
    349         },
    350         { /* TC 5: FE.>12-> */
    351             {{ 1,  1}, { 1,  1}}, /* REORDER_GROUP_NUMBERS_WITH_R */
    352             {{ 1,  1}, { 1,  1}}, /* REORDER_INVERSE_LIKE_DIRECT */
    353             {{ 0,  1}, { 1,  1}}, /* REORDER_NUMBERS_SPECIAL */
    354             {{ 1,  1}, { 1,  1}}, /* REORDER_INVERSE_FOR_NUMBERS_SPECIAL */
    355             {{ 1,  1}, { 1,  1}}  /* REORDER_INVERSE_NUMBERS_AS_L */
    356         },
    357         { /* TC 6: JIH.>12->a */
    358             {{ 1,  1}, { 1,  1}}, /* REORDER_GROUP_NUMBERS_WITH_R */
    359             {{ 1,  1}, { 1,  1}}, /* REORDER_INVERSE_LIKE_DIRECT */
    360             {{ 0,  0}, { 1,  1}}, /* REORDER_NUMBERS_SPECIAL */
    361             {{ 1,  1}, { 1,  1}}, /* REORDER_INVERSE_FOR_NUMBERS_SPECIAL */
    362             {{ 1,  1}, { 1,  1}}  /* REORDER_INVERSE_NUMBERS_AS_L */
    363         },
    364         { /* TC 7: CBA.>67->89=a */
    365             {{ 1,  1}, { 1,  1}}, /* REORDER_GROUP_NUMBERS_WITH_R */
    366             {{ 1,  1}, { 1,  1}}, /* REORDER_INVERSE_LIKE_DIRECT */
    367             {{ 0,  1}, { 1,  1}}, /* REORDER_NUMBERS_SPECIAL */
    368             {{ 1,  1}, { 1,  1}}, /* REORDER_INVERSE_FOR_NUMBERS_SPECIAL */
    369             {{ 0,  0}, { 1,  1}}  /* REORDER_INVERSE_NUMBERS_AS_L */
    370         },
    371         { /* TC 8: CBA.>123->xyz */
    372             {{ 1,  1}, { 1,  1}}, /* REORDER_GROUP_NUMBERS_WITH_R */
    373             {{ 1,  1}, { 1,  1}}, /* REORDER_INVERSE_LIKE_DIRECT */
    374             {{ 0,  0}, { 1,  1}}, /* REORDER_NUMBERS_SPECIAL */
    375             {{ 1,  1}, { 1,  1}}, /* REORDER_INVERSE_FOR_NUMBERS_SPECIAL */
    376             {{ 1,  1}, { 1,  1}}  /* REORDER_INVERSE_NUMBERS_AS_L */
    377         },
    378         { /* TC 9: .>12->xyz */
    379             {{ 1,  1}, { 1,  1}}, /* REORDER_GROUP_NUMBERS_WITH_R */
    380             {{ 1,  1}, { 1,  1}}, /* REORDER_INVERSE_LIKE_DIRECT */
    381             {{ 1,  0}, { 1,  1}}, /* REORDER_NUMBERS_SPECIAL */
    382             {{ 1,  1}, { 1,  1}}, /* REORDER_INVERSE_FOR_NUMBERS_SPECIAL */
    383             {{ 1,  1}, { 1,  1}}  /* REORDER_INVERSE_NUMBERS_AS_L */
    384         },
    385         { /* TC 10: a.>67->xyz */
    386             {{ 1,  1}, { 1,  1}}, /* REORDER_GROUP_NUMBERS_WITH_R */
    387             {{ 1,  1}, { 1,  1}}, /* REORDER_INVERSE_LIKE_DIRECT */
    388             {{ 1,  1}, { 1,  1}}, /* REORDER_NUMBERS_SPECIAL */
    389             {{ 1,  1}, { 1,  1}}, /* REORDER_INVERSE_FOR_NUMBERS_SPECIAL */
    390             {{ 1,  0}, { 1,  1}}  /* REORDER_INVERSE_NUMBERS_AS_L */
    391         },
    392         { /* TC 11: 123JIH */
    393             {{ 1,  1}, { 1,  1}}, /* REORDER_GROUP_NUMBERS_WITH_R */
    394             {{ 1,  1}, { 1,  1}}, /* REORDER_INVERSE_LIKE_DIRECT */
    395             {{ 1,  1}, { 1,  1}}, /* REORDER_NUMBERS_SPECIAL */
    396             {{ 1,  1}, { 1,  1}}, /* REORDER_INVERSE_FOR_NUMBERS_SPECIAL */
    397             {{ 1,  1}, { 1,  1}}  /* REORDER_INVERSE_NUMBERS_AS_L */
    398         },
    399         { /* TC 12: 123 JIH */
    400             {{ 1,  1}, { 1,  1}}, /* REORDER_GROUP_NUMBERS_WITH_R */
    401             {{ 1,  1}, { 1,  1}}, /* REORDER_INVERSE_LIKE_DIRECT */
    402             {{ 1,  1}, { 1,  1}}, /* REORDER_NUMBERS_SPECIAL */
    403             {{ 1,  1}, { 1,  1}}, /* REORDER_INVERSE_FOR_NUMBERS_SPECIAL */
    404             {{ 1,  1}, { 1,  1}}  /* REORDER_INVERSE_NUMBERS_AS_L */
    405         }
    406     };
    407 
    408     private boolean assertRoundTrip(Bidi bidi, int tc, int outIndex,
    409                                     String src, String dest,
    410                                     int mode, int option, byte level) {
    411         String descMode, descOption;
    412         String dest2;
    413 
    414         switch (modes[mode]) {
    415             case Bidi.REORDER_NUMBERS_SPECIAL:
    416                 bidi.setReorderingMode(Bidi.REORDER_INVERSE_FOR_NUMBERS_SPECIAL);
    417                 break;
    418             case Bidi.REORDER_GROUP_NUMBERS_WITH_R:
    419                 bidi.setReorderingMode(Bidi.REORDER_GROUP_NUMBERS_WITH_R);
    420                 break;
    421             case Bidi.REORDER_RUNS_ONLY:
    422                 bidi.setReorderingMode(Bidi.REORDER_RUNS_ONLY);
    423                 break;
    424             case Bidi.REORDER_INVERSE_NUMBERS_AS_L:
    425                 bidi.setReorderingMode(Bidi.REORDER_DEFAULT);
    426                 break;
    427             case Bidi.REORDER_INVERSE_LIKE_DIRECT:
    428                 bidi.setReorderingMode(Bidi.REORDER_DEFAULT);
    429                 break;
    430             case Bidi.REORDER_INVERSE_FOR_NUMBERS_SPECIAL:
    431                 bidi.setReorderingMode(Bidi.REORDER_NUMBERS_SPECIAL);
    432                 break;
    433             default:
    434                 bidi.setReorderingMode(Bidi.REORDER_INVERSE_LIKE_DIRECT);
    435                 break;
    436         }
    437         bidi.setReorderingOptions(Bidi.OPTION_REMOVE_CONTROLS);
    438 
    439         bidi.setPara(pseudoToU16(dest), level, null);
    440         dest2 = bidi.writeReordered(Bidi.DO_MIRRORING);
    441 
    442         dest2 = u16ToPseudo(dest2);
    443         checkWhatYouCan(bidi, dest, dest2);
    444         descMode = modeToString(modes[mode]);
    445         descOption = spOptionsToString(options[option]);
    446         if (!src.equals(dest2)) {
    447             if (roundtrip[tc][mode][option][level] == 1) {
    448                 errln("\nRound trip failed for case=" + tc +
    449                       " mode=" + mode + " option=" + option +
    450                       "\nOriginal text:      " + src +
    451                       "\nRound-tripped text: " + dest2 +
    452                       "\nIntermediate text:  " + dest +
    453                       "\nReordering mode:    " + descMode +
    454                       "\nReordering option:  " + descOption +
    455                       "\nParagraph level:    " + level);
    456             } else {
    457                 logln("\nExpected round trip failure for case=" + tc +
    458                       " mode=" + mode + " option=" + option +
    459                       "\nOriginal text:      " + src +
    460                       "\nRound-tripped text: " + dest2 +
    461                       "\nIntermediate text:  " + dest +
    462                       "\nReordering mode:    " + descMode +
    463                       "\nReordering option:  " + descOption +
    464                       "\nParagraph level:    " + level);
    465             }
    466             return false;
    467         }
    468         if (!checkResultLength(bidi, dest, dest2, descMode,
    469                                "OPTION_REMOVE_CONTROLS", level)) {
    470             return false;
    471         }
    472         if ((outIndex > -1) &&
    473             !checkMaps(bidi, outIndex, src, dest, descMode,
    474                        "OPTION_REMOVE_CONTROLS", level, false)) {
    475             return false;
    476         }
    477         return true;
    478     }
    479 
    480     private boolean checkResultLength(Bidi bidi, String src, String dest,
    481                                    String mode, String option, byte level) {
    482         int actualLen;
    483         if (mode.equals("REORDER_INVERSE_NUMBERS_AS_L"))
    484             actualLen = dest.length();
    485         else
    486             actualLen = bidi.getResultLength();
    487         if (actualLen != dest.length()) {
    488             errln("\nBidi.getResultLength failed." +
    489                   "\nExpected:           " + dest.length() +
    490                   "\nActual:             " + actualLen +
    491                   "\nInput:              " + src +
    492                   "\nOutput:             " + dest +
    493                   "\nReordering mode:    " + mode +
    494                   "\nReordering option:  " + option +
    495                   "\nParagraph level:    " + level);
    496             return false;
    497         }
    498         return true;
    499     }
    500 
    501     static String formatMap(int[] map)
    502     {
    503         char[] buffer = new char[map.length];
    504         int i, k;
    505         char c;
    506         for (i = 0; i < map.length; i++) {
    507             k = map[i];
    508             if (k < 0)
    509                 c = '-';
    510             else if (k >= columns.length)
    511                 c = '+';
    512             else
    513                 c = columns[k];
    514             buffer[i] = c;
    515         }
    516         return new String(buffer);
    517     }
    518 
    519     static final int NO = Bidi.MAP_NOWHERE;
    520 
    521     static final int forwardMap[][] = {
    522     /* TC 0: 123 */
    523         { 0, 1, 2 },                                                    /* (0) */
    524     /* TC 1: .123->4.5 */
    525         { 0, 1, 2, 3, 4, 5, 6, 7, 8 },                                  /* (1) */
    526         { 8, 5, 6, 7, 4, 3, 0, 1, 2 },                                  /* (2) */
    527     /* TC 2: 678 */
    528         { 0, 1, 2 },                                                    /* (3) */
    529     /* TC 3: .678->8.9 */
    530         { 0, 6, 7, 8, 5, 4, 1, 2, 3 },                                  /* (4) */
    531         { 8, 5, 6, 7, 4, 3, 0, 1, 2 },                                  /* (5) */
    532         { 0, 1, 2, 3, 4, 5, 6, 7, 8 },                                  /* (6) */
    533     /* TC 4: MLK1.2,3JIH */
    534         { 10, 9, 8, 3, 4, 5, 6, 7, 2, 1, 0 },                           /* (7) */
    535     /* TC 5: FE.>12-> */
    536         { 5, 4, 3, 2, 0, 1, 6, 7 },                                     /* (8) */
    537         { 7, 6, 5, 4, 2, 3, 1, 0 },                                     /* (9) */
    538         { 1, 0, 2, 3, 5, 6, 7, 8 },                                     /* (10) */
    539     /* TC 6: JIH.>12->a */
    540         { 6, 5, 4, 3, 2, 0, 1, 7, 8, 9 },                               /* (11) */
    541         { 9, 8, 7, 6, 5, 3, 4, 2, 1, 0 },                               /* (12) */
    542         { 2, 1, 0, 3, 4, 6, 7, 8, 9, 10 },                              /* (13) */
    543         { 10, 9, 8, 7, 6, 4, 5, 3, 2, 0 },                              /* (14) */
    544     /* TC 7: CBA.>67->89=a */
    545         { 2, 1, 0, 3, 4, 6, 7, 8, 9, 10, 11, 12, 13 },                  /* (15) */
    546         { 12, 11, 10, 9, 8, 6, 7, 5, 4, 2, 3, 1, 0 },                   /* (16) */
    547         { 13, 12, 11, 10, 9, 7, 8, 6, 5, 3, 4, 2, 0 },                  /* (17) */
    548         { 10, 9, 8, 7, 6, 4, 5, 3, 2, 0, 1, 11, 12 },                   /* (18) */
    549     /* TC 8: CBA.123->xyz */
    550         { 6, 5, 4, 3, 0, 1, 2, 7, 8, 9, 10, 11 },                       /* (19) */
    551         { 11, 10, 9, 8, 5, 6, 7, 4, 3, 0, 1, 2 },                       /* (20) */
    552         { 2, 1, 0, 3, 5, 6, 7, 8, 9, 10, 11, 12 },                      /* (21) */
    553         { 12, 11, 10, 9, 6, 7, 8, 5, 4, 0, 1, 2 },                      /* (22) */
    554     /* TC 9: .>12->xyz */
    555         { 0, 1, 2, 3, 4, 5, 6, 7, 8 },                                  /* (23) */
    556         { 8, 7, 5, 6, 4, 3, 0, 1, 2 },                                  /* (24) */
    557         { 9, 8, 6, 7, 5, 4, 0, 1, 2 },                                  /* (25) */
    558     /* TC 10: a.>67->xyz */
    559         { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 },                               /* (26) */
    560         { 0, 1, 2, 4, 5, 7, 8, 9, 10, 11 },                             /* (27) */
    561         { 9, 8, 7, 5, 6, 4, 3, 0, 1, 2 },                               /* (28) */
    562     /* TC 11: 123JIH */
    563         { 0, 1, 2, 5, 4, 3 },                                           /* (29) */
    564         { 3, 4, 5, 2, 1, 0 },                                           /* (30) */
    565     /* TC 12: 123 JIH */
    566         { 0, 1, 2, 3, 6, 5, 4 },                                        /* (31) */
    567         { 4, 5, 6, 3, 2, 1, 0 },                                        /* (32) */
    568     };
    569     static final int inverseMap[][] = {
    570     /* TC 0: 123 */
    571         { 0, 1, 2 },                                                    /* (0) */
    572     /* TC 1: .123->4.5 */
    573         { 0, 1, 2, 3, 4, 5, 6, 7, 8 },                                  /* (1) */
    574         { 6, 7, 8, 5, 4, 1, 2, 3, 0 },                                  /* (2) */
    575     /* TC 2: 678 */
    576         { 0, 1, 2 },                                                    /* (3) */
    577     /* TC 3: .678->8.9 */
    578         { 0, 6, 7, 8, 5, 4, 1, 2, 3 },                                  /* (4) */
    579         { 6, 7, 8, 5, 4, 1, 2, 3, 0 },                                  /* (5) */
    580         { 0, 1, 2, 3, 4, 5, 6, 7, 8 },                                  /* (6) */
    581     /* TC 4: MLK1.2,3JIH */
    582         { 10, 9, 8, 3, 4, 5, 6, 7, 2, 1, 0 },                           /* (7) */
    583     /* TC 5: FE.>12-> */
    584         { 4, 5, 3, 2, 1, 0, 6, 7 },                                     /* (8) */
    585         { 7, 6, 4, 5, 3, 2, 1, 0 },                                     /* (9) */
    586         { 1, 0, 2, 3, NO, 4, 5, 6, 7 },                                 /* (10) */
    587     /* TC 6: JIH.>12->a */
    588         { 5, 6, 4, 3, 2, 1, 0, 7, 8, 9 },                               /* (11) */
    589         { 9, 8, 7, 5, 6, 4, 3, 2, 1, 0 },                               /* (12) */
    590         { 2, 1, 0, 3, 4, NO, 5, 6, 7, 8, 9 },                           /* (13) */
    591         { 9, NO, 8, 7, 5, 6, 4, 3, 2, 1, 0 },                           /* (14) */
    592     /* TC 7: CBA.>67->89=a */
    593         { 2, 1, 0, 3, 4, NO, 5, 6, 7, 8, 9, 10, 11, 12 },               /* (15) */
    594         { 12, 11, 9, 10, 8, 7, 5, 6, 4, 3, 2, 1, 0 },                   /* (16) */
    595         { 12, NO, 11, 9, 10, 8, 7, 5, 6, 4, 3, 2, 1, 0 },               /* (17) */
    596         { 9, 10, 8, 7, 5, 6, 4, 3, 2, 1, 0, 11, 12 },                   /* (18) */
    597     /* TC 8: CBA.123->xyz */
    598         { 4, 5, 6, 3, 2, 1, 0, 7, 8, 9, 10, 11 },                       /* (19) */
    599         { 9, 10, 11, 8, 7, 4, 5, 6, 3, 2, 1, 0 },                       /* (20) */
    600         { 2, 1, 0, 3, NO, 4, 5, 6, 7, 8, 9, 10, 11 },                   /* (21) */
    601         { 9, 10, 11, NO, 8, 7, 4, 5, 6, 3, 2, 1, 0 },                   /* (22) */
    602     /* TC 9: .>12->xyz */
    603         { 0, 1, 2, 3, 4, 5, 6, 7, 8 },                                  /* (23) */
    604         { 6, 7, 8, 5, 4, 2, 3, 1, 0 },                                  /* (24) */
    605         { 6, 7, 8, NO, 5, 4, 2, 3, 1, 0 },                              /* (25) */
    606     /* TC 10: a.>67->xyz */
    607         { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 },                               /* (26) */
    608         { 0, 1, 2, NO, 3, 4, NO, 5, 6, 7, 8, 9 },                       /* (27) */
    609         { 7, 8, 9, 6, 5, 3, 4, 2, 1, 0 },                               /* (28) */
    610     /* TC 11: 123JIH */
    611         { 0, 1, 2, 5, 4, 3 },                                           /* (29) */
    612         { 5, 4, 3, 0, 1, 2 },                                           /* (30) */
    613     /* TC 12: 123 JIH */
    614         { 0, 1, 2, 3, 6, 5, 4 },                                        /* (31) */
    615         { 6, 5, 4, 3, 0, 1, 2 },                                        /* (32) */
    616     };
    617 
    618     private boolean checkMaps(Bidi bidi, int stringIndex, String src, String dest,
    619             String mode, String option, byte level, boolean forward) {
    620 
    621         int[] actualLogicalMap;
    622         int[] actualVisualMap;
    623         int[] getIndexMap;
    624         int i, srcLen, resLen, index;
    625         int[] expectedLogicalMap, expectedVisualMap;
    626         boolean testOK = true;
    627 
    628         if (forward) {
    629             expectedLogicalMap = forwardMap[stringIndex];
    630             expectedVisualMap  = inverseMap[stringIndex];
    631         } else {
    632             expectedLogicalMap = inverseMap[stringIndex];
    633             expectedVisualMap  = forwardMap[stringIndex];
    634         }
    635         actualLogicalMap = bidi.getLogicalMap();
    636         srcLen = bidi.getProcessedLength();
    637         if (!Arrays.equals(expectedLogicalMap, actualLogicalMap)) {
    638             err("Bidi.getLogicalMap returned unexpected map for output " +
    639                 "string index " + stringIndex + "\n" +
    640                 "source: " + src + "\n" +
    641                 "dest  : " + dest + "\n" +
    642                 "Scale : " + columnString + "\n" +
    643                 "ExpMap: " + formatMap(expectedLogicalMap) + "\n" +
    644                 "Actual: " + formatMap(actualLogicalMap) + "\n" +
    645                 "Paragraph level  : " + level + " == " + bidi.getParaLevel() + "\n" +
    646                 "Reordering mode  : " + mode + " == " + bidi.getReorderingMode() + "\n" +
    647                 "Reordering option: " + option + " == " + bidi.getReorderingOptions() + "\n" +
    648                 "Forward flag     : " + forward + "\n");
    649             testOK = false;
    650         }
    651         resLen = bidi.getResultLength();
    652         actualVisualMap = bidi.getVisualMap();
    653         if (!Arrays.equals(expectedVisualMap, actualVisualMap)) {
    654             err("Bidi.getVisualMap returned unexpected map for output " +
    655                 "string index " + stringIndex + "\n" +
    656                 "source: " + src + "\n" +
    657                 "dest  : " + dest + "\n" +
    658                 "Scale : " + columnString + "\n" +
    659                 "ExpMap: " + formatMap(expectedVisualMap) + "\n" +
    660                 "Actual: " + formatMap(actualVisualMap) + "\n" +
    661                 "Paragraph level  : " + level + " == " + bidi.getParaLevel() + "\n" +
    662                 "Reordering mode  : " + mode + " == " + bidi.getReorderingMode() + "\n" +
    663                 "Reordering option: " + option + " == " + bidi.getReorderingOptions() + "\n" +
    664                 "Forward flag     : " + forward + "\n");
    665             testOK = false;
    666         }
    667         getIndexMap = new int[srcLen];
    668         for (i = 0; i < srcLen; i++) {
    669             index = bidi.getVisualIndex(i);
    670             getIndexMap[i] = index;
    671         }
    672         if (!Arrays.equals(actualLogicalMap, getIndexMap)) {
    673             err("Mismatch between getLogicalMap and getVisualIndex for output " +
    674                 "string index " + stringIndex + "\n" +
    675                 "source: " + src + "\n" +
    676                 "dest  : " + dest + "\n" +
    677                 "Scale : " + columnString + "\n" +
    678                 "ActMap: " + formatMap(actualLogicalMap) + "\n" +
    679                 "IdxMap: " + formatMap(getIndexMap) + "\n" +
    680                 "Paragraph level  : " + level + " == " + bidi.getParaLevel() + "\n" +
    681                 "Reordering mode  : " + mode + " == " + bidi.getReorderingMode() + "\n" +
    682                 "Reordering option: " + option + " == " + bidi.getReorderingOptions() + "\n" +
    683                 "Forward flag     : " + forward + "\n");
    684             testOK = false;
    685         }
    686         getIndexMap = new int[resLen];
    687         for (i = 0; i < resLen; i++) {
    688             index = bidi.getLogicalIndex(i);
    689             getIndexMap[i] = index;
    690         }
    691         if (!Arrays.equals(actualVisualMap, getIndexMap)) {
    692             err("Mismatch between getVisualMap and getLogicalIndex for output " +
    693                 "string index " + stringIndex + "\n" +
    694                 "source: " + src + "\n" +
    695                 "dest  : " + dest + "\n" +
    696                 "Scale : " + columnString + "\n" +
    697                 "ActMap: " + formatMap(actualVisualMap) + "\n" +
    698                 "IdxMap: " + formatMap(getIndexMap) + "\n" +
    699                 "Paragraph level  : " + level + " == " + bidi.getParaLevel() + "\n" +
    700                 "Reordering mode  : " + mode + " == " + bidi.getReorderingMode() + "\n" +
    701                 "Reordering option: " + option + " == " + bidi.getReorderingOptions() + "\n" +
    702                 "Forward flag     : " + forward + "\n");
    703             testOK = false;
    704         }
    705         return testOK;
    706     }
    707 }
    708