1 /* 2 * Copyright (C) 2010 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17 package libcore.java.text; 18 19 import java.io.ByteArrayInputStream; 20 import java.io.ByteArrayOutputStream; 21 import java.io.ObjectInputStream; 22 import java.io.ObjectOutputStream; 23 import java.text.DecimalFormatSymbols; 24 import java.util.Currency; 25 import java.util.Locale; 26 27 public class DecimalFormatSymbolsTest extends junit.framework.TestCase { 28 public void test_getInstance_unknown_or_invalid_locale() throws Exception { 29 // http://b/17374604: this test passes on the host but fails on the target. 30 // ICU uses setlocale(3) to determine its default locale, and glibc (on my box at least) 31 // returns "en_US.UTF-8". bionic before L returned NULL and in L returns "C.UTF-8", both 32 // of which get treated as "en_US_POSIX". What that means for this test is that you get 33 // "INF" for infinity instead of "\u221e". 34 // On the RI, this test fails for a different reason: their DecimalFormatSymbols.equals 35 // appears to be broken. It could be that they're accidentally checking the Locale field? 36 checkLocaleIsEquivalentToRoot(new Locale("xx", "XX")); 37 checkLocaleIsEquivalentToRoot(new Locale("not exist language", "not exist country")); 38 } 39 private void checkLocaleIsEquivalentToRoot(Locale locale) { 40 DecimalFormatSymbols dfs = DecimalFormatSymbols.getInstance(locale); 41 assertEquals(DecimalFormatSymbols.getInstance(Locale.ROOT), dfs); 42 } 43 44 // http://code.google.com/p/android/issues/detail?id=14495 45 public void testSerialization() throws Exception { 46 DecimalFormatSymbols originalDfs = DecimalFormatSymbols.getInstance(Locale.GERMANY); 47 48 // Serialize... 49 ByteArrayOutputStream out = new ByteArrayOutputStream(); 50 new ObjectOutputStream(out).writeObject(originalDfs); 51 byte[] bytes = out.toByteArray(); 52 53 // Deserialize... 54 ObjectInputStream in = new ObjectInputStream(new ByteArrayInputStream(bytes)); 55 DecimalFormatSymbols deserializedDfs = (DecimalFormatSymbols) in.readObject(); 56 assertEquals(-1, in.read()); 57 58 // The two objects should claim to be equal. 59 assertEquals(originalDfs, deserializedDfs); 60 } 61 62 // https://code.google.com/p/android/issues/detail?id=79925 63 public void testSetSameCurrency() throws Exception { 64 DecimalFormatSymbols dfs = new DecimalFormatSymbols(Locale.US); 65 dfs.setCurrency(Currency.getInstance("USD")); 66 assertEquals("$", dfs.getCurrencySymbol()); 67 dfs.setCurrencySymbol("poop"); 68 assertEquals("poop", dfs.getCurrencySymbol()); 69 dfs.setCurrency(Currency.getInstance("USD")); 70 assertEquals("$", dfs.getCurrencySymbol()); 71 } 72 73 public void testSetNulInternationalCurrencySymbol() throws Exception { 74 Currency usd = Currency.getInstance("USD"); 75 76 DecimalFormatSymbols dfs = new DecimalFormatSymbols(Locale.US); 77 dfs.setCurrency(usd); 78 assertEquals(usd, dfs.getCurrency()); 79 assertEquals("$", dfs.getCurrencySymbol()); 80 assertEquals("USD", dfs.getInternationalCurrencySymbol()); 81 82 // Setting the international currency symbol to null sets the currency to null too, 83 // but not the currency symbol. 84 dfs.setInternationalCurrencySymbol(null); 85 assertEquals(null, dfs.getCurrency()); 86 assertEquals("$", dfs.getCurrencySymbol()); 87 assertEquals(null, dfs.getInternationalCurrencySymbol()); 88 } 89 90 // https://code.google.com/p/android/issues/detail?id=170718 91 public void testSerializationOfMultiCharNegativeAndPercentage() throws Exception { 92 DecimalFormatSymbols dfs = new DecimalFormatSymbols(Locale.forLanguageTag("ar-AR")); 93 // TODO(narayan): Investigate. 94 // assertTrue(dfs.getMinusSignString().length() > 1); 95 // assertTrue(dfs.getPercentString().length() > 1); 96 97 // Serialize... 98 ByteArrayOutputStream out = new ByteArrayOutputStream(); 99 new ObjectOutputStream(out).writeObject(dfs); 100 byte[] bytes = out.toByteArray(); 101 102 // Deserialize... 103 ObjectInputStream in = new ObjectInputStream(new ByteArrayInputStream(bytes)); 104 DecimalFormatSymbols deserializedDfs = (DecimalFormatSymbols) in.readObject(); 105 assertEquals(-1, in.read()); 106 107 assertEquals(dfs.getMinusSign(), deserializedDfs.getMinusSign()); 108 assertEquals(dfs.getPercent(), deserializedDfs.getPercent()); 109 } 110 111 // http://b/18785260 112 public void testMultiCharMinusSignAndPercentage() { 113 DecimalFormatSymbols dfs; 114 115 // There have during the years been numerous bugs and workarounds around the decimal format 116 // symbols used for Arabic and Farsi. Most of the problems have had to do with bidi control 117 // characters and the Unicode bidi algorithm, which have not worked well together with code 118 // assuming that these symbols can be represented as a single Java char. 119 // 120 // This test case exists to verify that java.text.DecimalFormatSymbols in Android gets some 121 // kind of sensible values for these symbols (and not, as bugs have caused in the past, 122 // empty strings or only bidi control characters without any actual symbols). 123 // 124 // It is expected that the symbols may change with future CLDR updates. 125 126 dfs = new DecimalFormatSymbols(Locale.forLanguageTag("ar")); 127 assertEquals('', dfs.getPercent()); 128 assertEquals('-', dfs.getMinusSign()); 129 130 dfs = new DecimalFormatSymbols(Locale.forLanguageTag("fa")); 131 assertEquals('', dfs.getPercent()); 132 assertEquals('', dfs.getMinusSign()); 133 } 134 135 136 /** 137 * This class exists to allow the test to access the protected methods 138 * getIcuDecimalFormatSymbols and fromIcuInstance on the real DecimalFormatSymbols class. 139 */ 140 private static class DFSForTests extends DecimalFormatSymbols { 141 public DFSForTests(Locale locale) { 142 super(locale); 143 } 144 145 @Override 146 public android.icu.text.DecimalFormatSymbols getIcuDecimalFormatSymbols() { 147 return super.getIcuDecimalFormatSymbols(); 148 } 149 150 protected static DecimalFormatSymbols fromIcuInstance( 151 android.icu.text.DecimalFormatSymbols dfs) { 152 return DecimalFormatSymbols.fromIcuInstance(dfs); 153 } 154 } 155 156 public void compareDfs(DecimalFormatSymbols dfs, 157 android.icu.text.DecimalFormatSymbols icuSymb) { 158 // Check currency code is the same because ICU returns its own currency class. 159 assertEquals(dfs.getCurrency().getCurrencyCode(), icuSymb.getCurrency().getCurrencyCode()); 160 assertEquals(dfs.getCurrencySymbol(), icuSymb.getCurrencySymbol()); 161 assertEquals(dfs.getDecimalSeparator(), icuSymb.getDecimalSeparator()); 162 assertEquals(dfs.getDigit(), icuSymb.getDigit()); 163 assertEquals(dfs.getExponentSeparator(), icuSymb.getExponentSeparator()); 164 assertEquals(dfs.getGroupingSeparator(), icuSymb.getGroupingSeparator()); 165 assertEquals(dfs.getInfinity(), icuSymb.getInfinity()); 166 assertEquals(dfs.getInternationalCurrencySymbol(), 167 icuSymb.getInternationalCurrencySymbol()); 168 assertEquals(dfs.getMinusSign(), icuSymb.getMinusSign()); 169 assertEquals(dfs.getMonetaryDecimalSeparator(), icuSymb.getMonetaryDecimalSeparator()); 170 assertEquals(dfs.getPatternSeparator(), icuSymb.getPatternSeparator()); 171 assertEquals(dfs.getPercent(), icuSymb.getPercent()); 172 assertEquals(dfs.getPerMill(), icuSymb.getPerMill()); 173 assertEquals(dfs.getZeroDigit(), icuSymb.getZeroDigit()); 174 } 175 176 // Test the methods to convert to and from the ICU DecimalFormatSymbols 177 public void testToIcuDecimalFormatSymbols() { 178 DFSForTests dfs = new DFSForTests(Locale.US); 179 android.icu.text.DecimalFormatSymbols icuSymb = dfs.getIcuDecimalFormatSymbols(); 180 compareDfs(dfs, icuSymb); 181 } 182 183 public void testFromIcuDecimalFormatSymbols() { 184 android.icu.text.DecimalFormatSymbols icuSymb = new android.icu.text.DecimalFormatSymbols(); 185 DecimalFormatSymbols dfs = DFSForTests.fromIcuInstance(icuSymb); 186 compareDfs(dfs, icuSymb); 187 } 188 189 // http://b/36562145 190 public void testMaybeStripMarkers() { 191 final char ltr = '\u200E'; 192 final char rtl = '\u200F'; 193 final char alm = '\u061C'; 194 final char fallback = 'F'; 195 assertEquals(fallback, DecimalFormatSymbols.maybeStripMarkers("", fallback)); 196 assertEquals(fallback, DecimalFormatSymbols.maybeStripMarkers("XY", fallback)); 197 assertEquals(fallback, DecimalFormatSymbols.maybeStripMarkers("" + ltr, fallback)); 198 assertEquals(fallback, DecimalFormatSymbols.maybeStripMarkers("" + rtl, fallback)); 199 assertEquals(fallback, DecimalFormatSymbols.maybeStripMarkers("" + alm, fallback)); 200 assertEquals(fallback, 201 DecimalFormatSymbols.maybeStripMarkers("X" + ltr + rtl + alm + "Y", fallback)); 202 assertEquals(fallback, 203 DecimalFormatSymbols.maybeStripMarkers("" + ltr + rtl + alm, fallback)); 204 assertEquals(fallback, DecimalFormatSymbols.maybeStripMarkers(alm + "XY" + rtl, fallback)); 205 assertEquals('X', DecimalFormatSymbols.maybeStripMarkers("X", fallback)); 206 assertEquals('X', DecimalFormatSymbols.maybeStripMarkers("X" + ltr, fallback)); 207 assertEquals('X', DecimalFormatSymbols.maybeStripMarkers("X" + rtl, fallback)); 208 assertEquals('X', DecimalFormatSymbols.maybeStripMarkers(alm + "X", fallback)); 209 assertEquals('X', DecimalFormatSymbols.maybeStripMarkers(alm + "X" + rtl, fallback)); 210 } 211 } 212