Home | History | Annotate | Download | only in text
      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