1 // 2017 and later: Unicode, Inc. and others. 2 // License & terms of use: http://www.unicode.org/copyright.html#License 3 4 package com.ibm.icu.dev.test.shaping; 5 6 import java.util.Arrays; 7 import java.util.Collection; 8 import java.util.MissingResourceException; 9 10 import org.junit.Test; 11 import org.junit.experimental.runners.Enclosed; 12 import org.junit.runner.RunWith; 13 import org.junit.runners.Parameterized; 14 15 import com.ibm.icu.dev.test.TestFmwk; 16 import com.ibm.icu.text.ArabicShaping; 17 import com.ibm.icu.text.ArabicShapingException; 18 19 /** 20 * Regression test for Arabic shaping. 21 */ 22 @RunWith(Enclosed.class) 23 public class DataDrivenArabicShapingRegTest extends TestFmwk { 24 25 /* constants copied from ArabicShaping for convenience */ 26 27 public static final int LENGTH_GROW_SHRINK = 0; 28 public static final int LENGTH_FIXED_SPACES_NEAR = 1; 29 public static final int LENGTH_FIXED_SPACES_AT_END = 2; 30 public static final int LENGTH_FIXED_SPACES_AT_BEGINNING = 3; 31 32 public static final int TEXT_DIRECTION_LOGICAL = 0; 33 public static final int TEXT_DIRECTION_VISUAL_LTR = 4; 34 35 public static final int LETTERS_NOOP = 0; 36 public static final int LETTERS_SHAPE = 8; 37 public static final int LETTERS_SHAPE_TASHKEEL_ISOLATED = 0x18; 38 public static final int LETTERS_UNSHAPE = 0x10; 39 40 public static final int DIGITS_NOOP = 0; 41 public static final int DIGITS_EN2AN = 0x20; 42 public static final int DIGITS_AN2EN = 0x40; 43 public static final int DIGITS_EN2AN_INIT_LR = 0x60; 44 public static final int DIGITS_EN2AN_INIT_AL = 0x80; 45 // private static final int DIGITS_RESERVED = 0xa0; 46 47 public static final int DIGIT_TYPE_AN = 0; 48 public static final int DIGIT_TYPE_AN_EXTENDED = 0x100; 49 50 @RunWith(Parameterized.class) 51 public static class StandardDataTest extends TestFmwk { 52 private String source; 53 private int flags; 54 private String expected; 55 56 public StandardDataTest(String source, int flags, String expected) { 57 this.source = source; 58 this.flags = flags; 59 this.expected = expected; 60 } 61 62 @Parameterized.Parameters 63 public static Collection testData() { 64 String lamAlefSpecialVLTR = 65 "\u0020\u0646\u0622\u0644\u0627\u0020\u0646\u0623\u064E\u0644\u0627\u0020" + 66 "\u0646\u0627\u0670\u0644\u0627\u0020\u0646\u0622\u0653\u0644\u0627\u0020" + 67 "\u0646\u0625\u0655\u0644\u0627\u0020\u0646\u0622\u0654\u0644\u0627\u0020" + 68 "\uFEFC\u0639"; 69 String tashkeelSpecialVLTR = 70 "\u064A\u0628\u0631\u0639\u0020\u064A\u0628\u0651\u0631\u064E\u0639\u0020" + 71 "\u064C\u064A\u0628\u0631\u064F\u0639\u0020\u0628\u0670\u0631\u0670\u0639" + 72 "\u0020\u0628\u0653\u0631\u0653\u0639\u0020\u0628\u0654\u0631\u0654\u0639" + 73 "\u0020\u0628\u0655\u0631\u0655\u0639\u0020"; 74 String tashkeelShaddaRTL= 75 "\u0634\u0651\u0645\u0652\u0633"; 76 String tashkeelShaddaLTR= 77 "\u0633\u0652\u0645\u0651\u0634"; 78 String ArMathSym = 79 "\uD83B\uDE00\uD83B\uDE01\uD83B\uDE02\uD83B\uDE03\u0020\uD83B\uDE24\uD83B" + 80 "\uDE05\uD83B\uDE06\u0020\uD83B\uDE07\uD83B\uDE08\uD83B\uDE09\u0020\uD83B" + 81 "\uDE0A\uD83B\uDE0B\uD83B\uDE0C\uD83B\uDE0D\u0020\uD83B\uDE0E\uD83B\uDE0F" + 82 "\uD83B\uDE10\uD83B\uDE11\u0020\uD83B\uDE12\uD83B\uDE13\uD83B\uDE14\uD83B" + 83 "\uDE15\u0020\uD83B\uDE16\uD83B\uDE17\uD83B\uDE18\u0020\uD83B\uDE19\uD83B" + 84 "\uDE1A\uD83B\uDE1B"; 85 String ArMathSymLooped = 86 "\uD83B\uDE80\uD83B\uDE81\uD83B\uDE82\uD83B\uDE83\u0020\uD83B\uDE84\uD83B" + 87 "\uDE85\uD83B\uDE86\u0020\uD83B\uDE87\uD83B\uDE88\uD83B\uDE89\u0020\uD83B" + 88 "\uDE8B\uD83B\uDE8C\uD83B\uDE8D\u0020\uD83B\uDE8E\uD83B\uDE8F\uD83B\uDE90" + 89 "\uD83B\uDE91\u0020\uD83B\uDE92\uD83B\uDE93\uD83B\uDE94\uD83B\uDE95\u0020" + 90 "\uD83B\uDE96\uD83B\uDE97\uD83B\uDE98\u0020\uD83B\uDE99\uD83B\uDE9A\uD83B" + 91 "\uDE9B"; 92 String ArMathSymDoubleStruck = 93 "\uD83B\uDEA1\uD83B\uDEA2\uD83B\uDEA3\u0020\uD83B\uDEA5\uD83B\uDEA6\u0020" + 94 "\uD83B\uDEA7\uD83B\uDEA8\uD83B\uDEA9\u0020\uD83B\uDEAB\uD83B\uDEAC\uD83B" + 95 "\uDEAD\u0020\uD83B\uDEAE\uD83B\uDEAF\uD83B\uDEB0\uD83B\uDEB1\u0020\uD83B" + 96 "\uDEB2\uD83B\uDEB3\uD83B\uDEB4\uD83B\uDEB5\u0020\uD83B\uDEB6\uD83B\uDEB7" + 97 "\uD83B\uDEB8\u0020\uD83B\uDEB9\uD83B\uDEBA\uD83B\uDEBB"; 98 String ArMathSymInitial = 99 "\uD83B\uDE21\uD83B\uDE22\u0020\uD83B\uDE27\uD83B\uDE29\u0020\uD83B\uDE2A" + 100 "\uD83B\uDE2B\uD83B\uDE2C\uD83B\uDE2D\u0020\uD83B\uDE2E\uD83B\uDE2F\uD83B" + 101 "\uDE30\uD83B\uDE31\u0020\uD83B\uDE32\uD83B\uDE34\uD83B\uDE35\u0020\uD83B" + 102 "\uDE36\uD83B\uDE37\u0020\uD83B\uDE39\uD83B\uDE3B"; 103 String ArMathSymTailed = 104 "\uD83B\uDE42\uD83B\uDE47\uD83B\uDE49\uD83B\uDE4B\u0020\uD83B\uDE4D\uD83B" + 105 "\uDE4E\uD83B\uDE4F\u0020\uD83B\uDE51\uD83B\uDE52\uD83B\uDE54\uD83B\uDE57" + 106 "\u0020\uD83B\uDE59\uD83B\uDE5B\uD83B\uDE5D\uD83B\uDE5F"; 107 String ArMathSymStretched = 108 "\uD83B\uDE21\u0633\uD83B\uDE62\u0647"; 109 String logicalUnshape = 110 "\u0020\u0020\u0020\uFE8D\uFEF5\u0020\uFEE5\u0020\uFE8D\uFEF7\u0020\uFED7" + 111 "\uFEFC\u0020\uFEE1\u0020\uFE8D\uFEDF\uFECC\uFEAE\uFE91\uFEF4\uFE94\u0020" + 112 "\uFE8D\uFEDF\uFEA4\uFEAE\uFE93\u0020\u0020\u0020\u0020"; 113 String numSource = 114 "\u0031" + /* en:1 */ 115 "\u0627" + /* arabic:alef */ 116 "\u0032" + /* en:2 */ 117 "\u06f3" + /* an:3 */ 118 "\u0061" + /* latin:a */ 119 "\u0034"; /* en:4 */ 120 121 return Arrays.asList(new Object[][] { 122 /* lam alef special visual ltr */ 123 {lamAlefSpecialVLTR, 124 LETTERS_SHAPE | TEXT_DIRECTION_VISUAL_LTR | LENGTH_FIXED_SPACES_NEAR, 125 "\u0020\ufee5\u0020\ufef5\ufe8d\u0020\ufee5\u0020\ufe76\ufef7\ufe8d\u0020" + 126 "\ufee5\u0020\u0670\ufefb\ufe8d\u0020\ufee5\u0020\u0653\ufef5\ufe8d\u0020" + 127 "\ufee5\u0020\u0655\ufef9\ufe8d\u0020\ufee5\u0020\u0654\ufef5\ufe8d\u0020" + 128 "\ufefc\ufecb"}, 129 {lamAlefSpecialVLTR, 130 LETTERS_SHAPE | TEXT_DIRECTION_VISUAL_LTR | LENGTH_FIXED_SPACES_AT_END, 131 "\u0020\ufee5\ufef5\ufe8d\u0020\ufee5\ufe76\ufef7\ufe8d\u0020\ufee5\u0670" + 132 "\ufefb\ufe8d\u0020\ufee5\u0653\ufef5\ufe8d\u0020\ufee5\u0655\ufef9\ufe8d" + 133 "\u0020\ufee5\u0654\ufef5\ufe8d\u0020\ufefc\ufecb\u0020\u0020\u0020\u0020" + 134 "\u0020\u0020"}, 135 {lamAlefSpecialVLTR, 136 LETTERS_SHAPE | TEXT_DIRECTION_VISUAL_LTR | LENGTH_FIXED_SPACES_AT_BEGINNING, 137 "\u0020\u0020\u0020\u0020\u0020\u0020\u0020\ufee5\ufef5\ufe8d\u0020\ufee5" + 138 "\ufe76\ufef7\ufe8d\u0020\ufee5\u0670\ufefb\ufe8d\u0020\ufee5\u0653\ufef5" + 139 "\ufe8d\u0020\ufee5\u0655\ufef9\ufe8d\u0020\ufee5\u0654\ufef5\ufe8d\u0020" + 140 "\ufefc\ufecb"}, 141 {lamAlefSpecialVLTR, 142 LETTERS_SHAPE | TEXT_DIRECTION_VISUAL_LTR | LENGTH_GROW_SHRINK, 143 "\u0020\ufee5\ufef5\ufe8d\u0020\ufee5\ufe76\ufef7\ufe8d\u0020\ufee5\u0670" + 144 "\ufefb\ufe8d\u0020\ufee5\u0653\ufef5\ufe8d\u0020\ufee5\u0655\ufef9\ufe8d" + 145 "\u0020\ufee5\u0654\ufef5\ufe8d\u0020\ufefc\ufecb"}, 146 /* TASHKEEL */ 147 {lamAlefSpecialVLTR, 148 LETTERS_SHAPE_TASHKEEL_ISOLATED | TEXT_DIRECTION_VISUAL_LTR | 149 LENGTH_FIXED_SPACES_NEAR, 150 "\u0020\ufee5\u0020\ufef5\ufe8d\u0020\ufee5\u0020\ufe76\ufef7\ufe8d\u0020" + 151 "\ufee5\u0020\u0670\ufefb\ufe8d\u0020\ufee5\u0020\u0653\ufef5\ufe8d\u0020" + 152 "\ufee5\u0020\u0655\ufef9\ufe8d\u0020\ufee5\u0020\u0654\ufef5\ufe8d\u0020" + 153 "\ufefc\ufecb"}, 154 {lamAlefSpecialVLTR, 155 LETTERS_SHAPE_TASHKEEL_ISOLATED | TEXT_DIRECTION_VISUAL_LTR | 156 LENGTH_FIXED_SPACES_AT_END, 157 "\u0020\ufee5\ufef5\ufe8d\u0020\ufee5\ufe76\ufef7\ufe8d\u0020\ufee5\u0670" + 158 "\ufefb\ufe8d\u0020\ufee5\u0653\ufef5\ufe8d\u0020\ufee5\u0655\ufef9\ufe8d" + 159 "\u0020\ufee5\u0654\ufef5\ufe8d\u0020\ufefc\ufecb\u0020\u0020\u0020\u0020" + 160 "\u0020\u0020"}, 161 {lamAlefSpecialVLTR, 162 LETTERS_SHAPE_TASHKEEL_ISOLATED | TEXT_DIRECTION_VISUAL_LTR | 163 LENGTH_FIXED_SPACES_AT_BEGINNING, 164 "\u0020\u0020\u0020\u0020\u0020\u0020\u0020\ufee5\ufef5\ufe8d\u0020\ufee5" + 165 "\ufe76\ufef7\ufe8d\u0020\ufee5\u0670\ufefb\ufe8d\u0020\ufee5\u0653\ufef5" + 166 "\ufe8d\u0020\ufee5\u0655\ufef9\ufe8d\u0020\ufee5\u0654\ufef5\ufe8d\u0020" + 167 "\ufefc\ufecb"}, 168 {lamAlefSpecialVLTR, 169 LETTERS_SHAPE_TASHKEEL_ISOLATED | TEXT_DIRECTION_VISUAL_LTR | 170 LENGTH_GROW_SHRINK, 171 "\u0020\ufee5\ufef5\ufe8d\u0020\ufee5\ufe76\ufef7\ufe8d\u0020\ufee5\u0670" + 172 "\ufefb\ufe8d\u0020\ufee5\u0653\ufef5\ufe8d\u0020\ufee5\u0655\ufef9\ufe8d" + 173 "\u0020\ufee5\u0654\ufef5\ufe8d\u0020\ufefc\ufecb"}, 174 /* tashkeel special visual ltr */ 175 {tashkeelSpecialVLTR, 176 LETTERS_SHAPE | TEXT_DIRECTION_VISUAL_LTR | LENGTH_FIXED_SPACES_NEAR, 177 "\ufef2\ufe91\ufeae\ufecb\u0020\ufef2\ufe91\ufe7c\ufeae\ufe77\ufecb\u0020" + 178 "\ufe72\ufef2\ufe91\ufeae\ufe79\ufecb\u0020\ufe8f\u0670\ufeae\u0670\ufecb" + 179 "\u0020\ufe8f\u0653\ufeae\u0653\ufecb\u0020\ufe8f\u0654\ufeae\u0654\ufecb" + 180 "\u0020\ufe8f\u0655\ufeae\u0655\ufecb\u0020"}, 181 {tashkeelSpecialVLTR, 182 LETTERS_SHAPE_TASHKEEL_ISOLATED | TEXT_DIRECTION_VISUAL_LTR | 183 LENGTH_FIXED_SPACES_NEAR, 184 "\ufef2\ufe91\ufeae\ufecb\u0020\ufef2\ufe91\ufe7c\ufeae\ufe76\ufecb\u0020" + 185 "\ufe72\ufef2\ufe91\ufeae\ufe78\ufecb\u0020\ufe8f\u0670\ufeae\u0670\ufecb" + 186 "\u0020\ufe8f\u0653\ufeae\u0653\ufecb\u0020\ufe8f\u0654\ufeae\u0654\ufecb" + 187 "\u0020\ufe8f\u0655\ufeae\u0655\ufecb\u0020"}, 188 {tashkeelShaddaRTL, 189 ArabicShaping.LETTERS_SHAPE | ArabicShaping.TASHKEEL_BEGIN | 190 ArabicShaping.TEXT_DIRECTION_VISUAL_RTL, 191 "\u0020\ufeb7\ufe7d\ufee4\ufeb2"}, 192 {tashkeelShaddaRTL, 193 ArabicShaping.LETTERS_SHAPE | ArabicShaping.TASHKEEL_END | 194 ArabicShaping.TEXT_DIRECTION_VISUAL_RTL, 195 "\ufeb7\ufe7d\ufee4\ufeb2\u0020"}, 196 {tashkeelShaddaRTL, 197 ArabicShaping.LETTERS_SHAPE | ArabicShaping.TASHKEEL_RESIZE | 198 ArabicShaping.TEXT_DIRECTION_VISUAL_RTL, 199 "\ufeb7\ufe7d\ufee4\ufeb2"}, 200 {tashkeelShaddaRTL, 201 ArabicShaping.LETTERS_SHAPE | ArabicShaping.TASHKEEL_REPLACE_BY_TATWEEL | 202 ArabicShaping.TEXT_DIRECTION_VISUAL_RTL, 203 "\ufeb7\ufe7d\ufee4\u0640\ufeb2"}, 204 {tashkeelShaddaLTR, 205 ArabicShaping.LETTERS_SHAPE | ArabicShaping.TASHKEEL_BEGIN | 206 ArabicShaping.TEXT_DIRECTION_VISUAL_LTR, 207 "\u0020\ufeb2\ufee4\ufe7d\ufeb7"}, 208 {tashkeelShaddaLTR, 209 ArabicShaping.LETTERS_SHAPE | ArabicShaping.TASHKEEL_END | 210 ArabicShaping.TEXT_DIRECTION_VISUAL_LTR, 211 "\ufeb2\ufee4\ufe7d\ufeb7\u0020"}, 212 {tashkeelShaddaLTR, 213 ArabicShaping.LETTERS_SHAPE | ArabicShaping.TASHKEEL_RESIZE | 214 ArabicShaping.TEXT_DIRECTION_VISUAL_LTR, 215 "\ufeb2\ufee4\ufe7d\ufeb7"}, 216 {tashkeelShaddaLTR, 217 ArabicShaping.LETTERS_SHAPE | ArabicShaping.TASHKEEL_REPLACE_BY_TATWEEL | 218 ArabicShaping.TEXT_DIRECTION_VISUAL_LTR, 219 "\ufeb2\u0640\ufee4\ufe7d\ufeb7"}, 220 {ArMathSym, 221 ArabicShaping.LETTERS_SHAPE | ArabicShaping.TASHKEEL_BEGIN | 222 ArabicShaping.TEXT_DIRECTION_VISUAL_RTL, 223 "\uD83B\uDE00\uD83B\uDE01\uD83B\uDE02\uD83B\uDE03\u0020\uD83B\uDE24\uD83B" + 224 "\uDE05\uD83B\uDE06\u0020\uD83B\uDE07\uD83B\uDE08\uD83B\uDE09\u0020\uD83B" + 225 "\uDE0A\uD83B\uDE0B\uD83B\uDE0C\uD83B\uDE0D\u0020\uD83B\uDE0E\uD83B\uDE0F" + 226 "\uD83B\uDE10\uD83B\uDE11\u0020\uD83B\uDE12\uD83B\uDE13\uD83B\uDE14\uD83B" + 227 "\uDE15\u0020\uD83B\uDE16\uD83B\uDE17\uD83B\uDE18\u0020\uD83B\uDE19\uD83B" + 228 "\uDE1A\uD83B\uDE1B"}, 229 {ArMathSymLooped, 230 ArabicShaping.LETTERS_SHAPE | ArabicShaping.TASHKEEL_END | 231 ArabicShaping.TEXT_DIRECTION_VISUAL_RTL, 232 "\uD83B\uDE80\uD83B\uDE81\uD83B\uDE82\uD83B\uDE83\u0020\uD83B\uDE84\uD83B" + 233 "\uDE85\uD83B\uDE86\u0020\uD83B\uDE87\uD83B\uDE88\uD83B\uDE89\u0020\uD83B" + 234 "\uDE8B\uD83B\uDE8C\uD83B\uDE8D\u0020\uD83B\uDE8E\uD83B\uDE8F\uD83B\uDE90" + 235 "\uD83B\uDE91\u0020\uD83B\uDE92\uD83B\uDE93\uD83B\uDE94\uD83B\uDE95\u0020" + 236 "\uD83B\uDE96\uD83B\uDE97\uD83B\uDE98\u0020\uD83B\uDE99\uD83B\uDE9A\uD83B" + 237 "\uDE9B"}, 238 {ArMathSymDoubleStruck, 239 ArabicShaping.LETTERS_SHAPE | ArabicShaping.TASHKEEL_RESIZE| 240 ArabicShaping.TEXT_DIRECTION_VISUAL_RTL, 241 "\uD83B\uDEA1\uD83B\uDEA2\uD83B\uDEA3\u0020\uD83B\uDEA5\uD83B\uDEA6\u0020" + 242 "\uD83B\uDEA7\uD83B\uDEA8\uD83B\uDEA9\u0020\uD83B\uDEAB\uD83B\uDEAC\uD83B" + 243 "\uDEAD\u0020\uD83B\uDEAE\uD83B\uDEAF\uD83B\uDEB0\uD83B\uDEB1\u0020\uD83B" + 244 "\uDEB2\uD83B\uDEB3\uD83B\uDEB4\uD83B\uDEB5\u0020\uD83B\uDEB6\uD83B\uDEB7" + 245 "\uD83B\uDEB8\u0020\uD83B\uDEB9\uD83B\uDEBA\uD83B\uDEBB"}, 246 {ArMathSymInitial, 247 ArabicShaping.LETTERS_SHAPE | ArabicShaping.TASHKEEL_BEGIN | 248 ArabicShaping.TEXT_DIRECTION_VISUAL_LTR, 249 "\uD83B\uDE21\uD83B\uDE22\u0020\uD83B\uDE27\uD83B\uDE29\u0020\uD83B\uDE2A" + 250 "\uD83B\uDE2B\uD83B\uDE2C\uD83B\uDE2D\u0020\uD83B\uDE2E\uD83B\uDE2F\uD83B" + 251 "\uDE30\uD83B\uDE31\u0020\uD83B\uDE32\uD83B\uDE34\uD83B\uDE35\u0020\uD83B" + 252 "\uDE36\uD83B\uDE37\u0020\uD83B\uDE39\uD83B\uDE3B"}, 253 {ArMathSymTailed, 254 ArabicShaping.LETTERS_SHAPE | ArabicShaping.TASHKEEL_END | 255 ArabicShaping.TEXT_DIRECTION_VISUAL_LTR, 256 "\uD83B\uDE42\uD83B\uDE47\uD83B\uDE49\uD83B\uDE4B\u0020\uD83B\uDE4D\uD83B" + 257 "\uDE4E\uD83B\uDE4F\u0020\uD83B\uDE51\uD83B\uDE52\uD83B\uDE54\uD83B\uDE57" + 258 "\u0020\uD83B\uDE59\uD83B\uDE5B\uD83B\uDE5D\uD83B\uDE5F"}, 259 {ArMathSymStretched, 260 ArabicShaping.LETTERS_SHAPE|ArabicShaping.TASHKEEL_RESIZE | 261 ArabicShaping.TEXT_DIRECTION_VISUAL_LTR, 262 "\uD83B\uDE21\uFEB1\uD83B\uDE62\uFEE9"}, 263 /* logical unshape */ 264 {logicalUnshape, 265 LETTERS_UNSHAPE | TEXT_DIRECTION_LOGICAL | LENGTH_FIXED_SPACES_NEAR, 266 "\u0020\u0020\u0020\u0627\u0644\u0622\u0646\u0020\u0627\u0644\u0623\u0642" + 267 "\u0644\u0627\u0645\u0020\u0627\u0644\u0639\u0631\u0628\u064a\u0629\u0020" + 268 "\u0627\u0644\u062d\u0631\u0629\u0020\u0020\u0020\u0020"}, 269 {logicalUnshape, 270 LETTERS_UNSHAPE | TEXT_DIRECTION_LOGICAL | LENGTH_FIXED_SPACES_AT_END, 271 "\u0020\u0020\u0020\u0627\u0644\u0622\u0020\u0646\u0020\u0627\u0644\u0623" + 272 "\u0020\u0642\u0644\u0627\u0020\u0645\u0020\u0627\u0644\u0639\u0631\u0628" + 273 "\u064a\u0629\u0020\u0627\u0644\u062d\u0631\u0629\u0020"}, 274 {logicalUnshape, 275 LETTERS_UNSHAPE | TEXT_DIRECTION_LOGICAL | LENGTH_FIXED_SPACES_AT_BEGINNING, 276 "\u0627\u0644\u0622\u0020\u0646\u0020\u0627\u0644\u0623\u0020\u0642\u0644" + 277 "\u0627\u0020\u0645\u0020\u0627\u0644\u0639\u0631\u0628\u064a\u0629\u0020" + 278 "\u0627\u0644\u062d\u0631\u0629\u0020\u0020\u0020\u0020"}, 279 {logicalUnshape, 280 LETTERS_UNSHAPE | TEXT_DIRECTION_LOGICAL | LENGTH_GROW_SHRINK, 281 "\u0020\u0020\u0020\u0627\u0644\u0622\u0020\u0646\u0020\u0627\u0644\u0623" + 282 "\u0020\u0642\u0644\u0627\u0020\u0645\u0020\u0627\u0644\u0639\u0631\u0628" + 283 "\u064a\u0629\u0020\u0627\u0644\u062d\u0631\u0629\u0020\u0020\u0020\u0020"}, 284 /* numbers */ 285 {numSource, 286 DIGITS_EN2AN | DIGIT_TYPE_AN, 287 "\u0661\u0627\u0662\u06f3\u0061\u0664"}, 288 {numSource, 289 DIGITS_AN2EN | DIGIT_TYPE_AN_EXTENDED, 290 "\u0031\u0627\u0032\u0033\u0061\u0034"}, 291 {numSource, 292 DIGITS_EN2AN_INIT_LR | DIGIT_TYPE_AN, 293 "\u0031\u0627\u0662\u06f3\u0061\u0034" }, 294 {numSource, 295 DIGITS_EN2AN_INIT_AL | DIGIT_TYPE_AN_EXTENDED, 296 "\u06f1\u0627\u06f2\u06f3\u0061\u0034"}, 297 {numSource, 298 DIGITS_EN2AN_INIT_LR | DIGIT_TYPE_AN | TEXT_DIRECTION_VISUAL_LTR, 299 "\u0661\u0627\u0032\u06f3\u0061\u0034"}, 300 {numSource, 301 DIGITS_EN2AN_INIT_AL | DIGIT_TYPE_AN_EXTENDED | TEXT_DIRECTION_VISUAL_LTR, 302 "\u06f1\u0627\u0032\u06f3\u0061\u06f4"}, 303 /* no-op */ 304 {numSource, 0, numSource} 305 }); 306 } 307 308 @Test 309 public void TestStandard() { 310 Exception ex = null; 311 String actual = null; 312 ArabicShaping shaper = null; 313 314 try { 315 shaper = new ArabicShaping(flags); 316 actual = shaper.shape(source); 317 } 318 catch(MissingResourceException e){ 319 throw e; 320 } 321 catch (IllegalStateException ie){ 322 warnln("IllegalStateException: "+ ie.toString()); 323 return; 324 } 325 catch (Exception e) { 326 ex = e; 327 } 328 329 if (ex != null) { 330 err("Error: Shaper " + shaper + "\n throws exception '" + ex + "'\n for input '" + source); 331 } else if (!expected.equals(actual)) { 332 StringBuffer buf = new StringBuffer(); 333 buf.append("Error: Shaper: " + shaper + "\n Input: " + source + "\n Actual: " + actual + 334 "\n Expected: " + expected + "\n"); 335 336 for (int i = 0; i < Math.max(expected.length(), actual.length()); ++i) { 337 String temp = Integer.toString(i); 338 if (temp.length() < 2) { 339 temp = " ".concat(temp); 340 } 341 char trg = i < expected.length() ? expected.charAt(i) : '\uffff'; 342 char res = i < actual.length() ? actual.charAt(i) : '\uffff'; 343 344 buf.append("[" + temp + "] "); 345 buf.append(escapedString("" + trg) + " "); 346 buf.append(escapedString("" + res) + " "); 347 if (trg != res) { 348 buf.append("***"); 349 } 350 buf.append("\n"); 351 } 352 err(buf.toString()); 353 } 354 } 355 356 private static String escapedString(String str) { 357 if (str == null) { 358 return null; 359 } 360 361 StringBuffer buf = new StringBuffer(str.length() * 6); 362 for (int i = 0; i < str.length(); ++i) { 363 char ch = str.charAt(i); 364 buf.append("\\u"); 365 if (ch < 0x1000) { 366 buf.append('0'); 367 } 368 if (ch < 0x0100) { 369 buf.append('0'); 370 } 371 if (ch < 0x0010) { 372 buf.append('0'); 373 } 374 buf.append(Integer.toHexString(ch)); 375 } 376 return buf.toString(); 377 } 378 } 379 380 @RunWith(Parameterized.class) 381 public static class PreflightDataTest extends TestFmwk { 382 private String source; 383 private int flags; 384 private int length; 385 386 public PreflightDataTest(String source, int flags, int length) { 387 this.source = source; 388 this.flags = flags; 389 this.length = length; 390 } 391 392 @Parameterized.Parameters 393 public static Collection testData() { 394 return Arrays.asList(new Object[][] { 395 {"\u0644\u0627", LETTERS_SHAPE | LENGTH_GROW_SHRINK, 1}, 396 {"\u0644\u0627\u0031", 397 DIGITS_EN2AN | DIGIT_TYPE_AN_EXTENDED | LENGTH_GROW_SHRINK, 3}, 398 {"\u0644\u0644", LETTERS_SHAPE | LENGTH_GROW_SHRINK, 2}, 399 {"\ufef7", LETTERS_UNSHAPE | LENGTH_GROW_SHRINK, 2} 400 }); 401 } 402 403 @Test 404 public void TestPreflight() { 405 Exception ex = null; 406 char src[] = null; 407 int len = 0; 408 ArabicShaping shaper = null; 409 410 if (source != null) { 411 src = source.toCharArray(); 412 } 413 414 try { 415 shaper = new ArabicShaping(flags); 416 len = shaper.shape(src, 0, src.length, null, 0, 0); 417 } 418 catch (Exception e) { 419 ex = e; 420 } 421 422 if (ex != null) { 423 err("Error: Shaper " + shaper + "\n throws exception '" + ex + "'\n for input '" + source); 424 } else if (length != len) { 425 err("Error: Shaper " + shaper + "\n returns " + len + " characters for input '" + 426 source + "'\n Expected were " + length + " characters"); 427 } 428 } 429 } 430 431 @RunWith(Parameterized.class) 432 public static class ErrorDataTest extends TestFmwk { 433 private String source; 434 private int flags; 435 private Class error; 436 437 public ErrorDataTest(String source, int flags, Class error) { 438 this.source = source; 439 this.flags = flags; 440 this.error = error; 441 } 442 443 @Parameterized.Parameters 444 public static Collection testData() { 445 return Arrays.asList(new Object[][] { 446 /* bad data */ 447 {"\u0020\ufef7\u0644\u0020", LETTERS_UNSHAPE | LENGTH_FIXED_SPACES_NEAR, 448 ArabicShapingException.class}, 449 {"\u0020\ufef7", LETTERS_UNSHAPE | LENGTH_FIXED_SPACES_AT_END, 450 ArabicShapingException.class}, 451 {"\ufef7\u0020", LETTERS_UNSHAPE | LENGTH_FIXED_SPACES_AT_BEGINNING, 452 ArabicShapingException.class}, 453 /* bad options */ 454 {"\ufef7", 0xffffffff, IllegalArgumentException.class}, 455 {"\ufef7", LETTERS_UNSHAPE | LENGTH_GROW_SHRINK, ArabicShapingException.class}, 456 {null, LETTERS_UNSHAPE | LENGTH_FIXED_SPACES_AT_END, 457 IllegalArgumentException.class} 458 }); 459 } 460 461 @Test 462 public void TestError() { 463 Exception ex = null; 464 char src[] = null; 465 int len = 0; 466 ArabicShaping shaper = null; 467 468 if (source != null) { 469 src = source.toCharArray(); 470 len = src.length; 471 } 472 473 try { 474 shaper = new ArabicShaping(flags); 475 shaper.shape(src, 0, len); 476 } 477 catch (Exception e) { 478 ex = e; 479 } 480 481 if (!error.isInstance(ex)) { 482 err("Error: Shaper " + shaper + "\n throws exception '" + ex + "'\n for input '" + 483 source + "'\n Expected exception: " + error); 484 } 485 } 486 } 487 } 488