1/* 2 * Copyright (C) 2009 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 17package libcore.java.util; 18 19import java.math.BigDecimal; 20import java.util.Calendar; 21import java.util.GregorianCalendar; 22import java.util.Locale; 23import java.util.TimeZone; 24 25public class FormatterTest extends junit.framework.TestCase { 26 public void test_numberLocalization() throws Exception { 27 Locale arabic = new Locale("ar"); 28 29 // Check the fast path for %d: 30 assertEquals("12 \u0661\u0662\u0663\u0664\u0665\u0666\u0667\u0668\u0669\u0660 34", 31 String.format(arabic, "12 %d 34", 1234567890)); 32 // And the slow path too: 33 assertEquals("12 \u0661\u066c\u0662\u0663\u0664\u066c\u0665\u0666\u0667\u066c\u0668\u0669\u0660 34", 34 String.format(arabic, "12 %,d 34", 1234567890)); 35 // And three localized floating point formats: 36 assertEquals("12 \u0661\u066b\u0662\u0663\u0660\u0627\u0633+\u0660\u0660 34", 37 String.format(arabic, "12 %.3e 34", 1.23)); 38 assertEquals("12 \u0661\u066b\u0662\u0663\u0660 34", 39 String.format(arabic, "12 %.3f 34", 1.23)); 40 assertEquals("12 \u0661\u066b\u0662\u0663 34", 41 String.format(arabic, "12 %.3g 34", 1.23)); 42 // And date/time formatting (we assume that all time/date number formatting is done by the 43 // same code, so this is representative): 44 Calendar c = Calendar.getInstance(TimeZone.getTimeZone("GMT-08:00")); 45 c.setTimeInMillis(0); 46 assertEquals("12 \u0661\u0666:\u0660\u0660:\u0660\u0660 34", 47 String.format(arabic, "12 %tT 34", c)); 48 // These shouldn't get localized: 49 assertEquals("1234", String.format(arabic, "1234")); 50 assertEquals("1234", String.format(arabic, "%s", "1234")); 51 assertEquals("1234", String.format(arabic, "%s", 1234)); 52 assertEquals("2322", String.format(arabic, "%o", 1234)); 53 assertEquals("4d2", String.format(arabic, "%x", 1234)); 54 assertEquals("0x1.0p0", String.format(arabic, "%a", 1.0)); 55 } 56 57 // http://b/27566754 58 public void test_internationalizedExponent() { 59 assertEquals("1E+02", String.format(Locale.ENGLISH, "%.0E", 100.0)); 60 assertEquals("1e+02", String.format(Locale.ENGLISH, "%.0e", 100.0)); 61 62 assertEquals("\u0661\u0627\u0633+\u0660\u0662", String.format(new Locale("ar"), "%.0E", 100.0)); 63 assertEquals("\u0661\u0627\u0633+\u0660\u0662", String.format(new Locale("ar"), "%.0e", 100.0)); 64 65 assertEquals("1\u00d710^+02", String.format(new Locale("et"), "%.0E", 100.0)); 66 assertEquals("1\u00d710^+02", String.format(new Locale("et"), "%.0e", 100.0)); 67 } 68 69 // http://b/2301938 70 public void test_uppercaseConversions() throws Exception { 71 // In most locales, the upper-case equivalent of "i" is "I". 72 assertEquals("JAKOB ARJOUNI", String.format(Locale.US, "%S", "jakob arjouni")); 73 // In Turkish-language locales, there's a dotted capital "i". 74 assertEquals("JAKOB ARJOUN\u0130", String.format(new Locale("tr", "TR"), "%S", "jakob arjouni")); 75 } 76 77 // Creating a NumberFormat is expensive, so we like to reuse them, but we need to be careful 78 // because they're mutable. 79 public void test_NumberFormat_reuse() throws Exception { 80 assertEquals("7.000000 7", String.format("%.6f %d", 7.0, 7)); 81 } 82 83 public void test_grouping() throws Exception { 84 // The interesting case is -123, where you might naively output "-,123" if you're just 85 // inserting a separator every three characters. The cases where there are three digits 86 // before the first separator may also be interesting. 87 assertEquals("-1", String.format("%,d", -1)); 88 assertEquals("-12", String.format("%,d", -12)); 89 assertEquals("-123", String.format("%,d", -123)); 90 assertEquals("-1,234", String.format("%,d", -1234)); 91 assertEquals("-12,345", String.format("%,d", -12345)); 92 assertEquals("-123,456", String.format("%,d", -123456)); 93 assertEquals("-1,234,567", String.format("%,d", -1234567)); 94 assertEquals("-12,345,678", String.format("%,d", -12345678)); 95 assertEquals("-123,456,789", String.format("%,d", -123456789)); 96 assertEquals("1", String.format("%,d", 1)); 97 assertEquals("12", String.format("%,d", 12)); 98 assertEquals("123", String.format("%,d", 123)); 99 assertEquals("1,234", String.format("%,d", 1234)); 100 assertEquals("12,345", String.format("%,d", 12345)); 101 assertEquals("123,456", String.format("%,d", 123456)); 102 assertEquals("1,234,567", String.format("%,d", 1234567)); 103 assertEquals("12,345,678", String.format("%,d", 12345678)); 104 assertEquals("123,456,789", String.format("%,d", 123456789)); 105 } 106 107 public void test_formatNull() throws Exception { 108 // We fast-path %s and %d (with no configuration) but need to make sure we handle the 109 // special case of the null argument... 110 assertEquals("null", String.format(Locale.US, "%s", (String) null)); 111 assertEquals("null", String.format(Locale.US, "%d", (Integer) null)); 112 // ...without screwing up conversions that don't take an argument. 113 assertEquals("%", String.format(Locale.US, "%%")); 114 } 115 116 // Alleged regression tests for historical bugs. (It's unclear whether the bugs were in 117 // BigDecimal or Formatter.) 118 public void test_BigDecimalFormatting() throws Exception { 119 BigDecimal[] input = new BigDecimal[] { 120 new BigDecimal("20.00000"), 121 new BigDecimal("20.000000"), 122 new BigDecimal(".2"), 123 new BigDecimal("2"), 124 new BigDecimal("-2"), 125 new BigDecimal("200000000000000000000000"), 126 new BigDecimal("20000000000000000000000000000000000000000000000000") 127 }; 128 String[] output = new String[] { 129 "20.00", 130 "20.00", 131 "0.20", 132 "2.00", 133 "-2.00", 134 "200000000000000000000000.00", 135 "20000000000000000000000000000000000000000000000000.00" 136 }; 137 for (int i = 0; i < input.length; ++i) { 138 String result = String.format("%.2f", input[i]); 139 assertEquals("input=\"" + input[i] + "\", " + ",expected=" + output[i] + ",actual=" + result, 140 output[i], result); 141 } 142 } 143 144 // https://code.google.com/p/android/issues/detail?id=42936 145 public void test42936() throws Exception { 146 assertEquals("0.00000000000000", String.format("%.15g",0.0d)); 147 } 148 149 // https://code.google.com/p/android/issues/detail?id=53983 150 public void test53983() throws Exception { 151 checkFormat("00", "H", 00); 152 checkFormat( "0", "k", 00); 153 checkFormat("12", "I", 00); 154 checkFormat("12", "l", 00); 155 156 checkFormat("01", "H", 01); 157 checkFormat( "1", "k", 01); 158 checkFormat("01", "I", 01); 159 checkFormat( "1", "l", 01); 160 161 checkFormat("12", "H", 12); 162 checkFormat("12", "k", 12); 163 checkFormat("12", "I", 12); 164 checkFormat("12", "l", 12); 165 166 checkFormat("13", "H", 13); 167 checkFormat("13", "k", 13); 168 checkFormat("01", "I", 13); 169 checkFormat( "1", "l", 13); 170 171 checkFormat("00", "H", 24); 172 checkFormat( "0", "k", 24); 173 checkFormat("12", "I", 24); 174 checkFormat("12", "l", 24); 175 } 176 177 private static void checkFormat(String expected, String pattern, int hour) { 178 TimeZone utc = TimeZone.getTimeZone("UTC"); 179 180 Calendar c = new GregorianCalendar(utc); 181 c.set(2013, Calendar.JANUARY, 1, hour, 00); 182 183 assertEquals(expected, String.format(Locale.US, "%t" + pattern, c)); 184 assertEquals(expected, String.format(Locale.US, "%T" + pattern, c)); 185 } 186} 187