1 /*
2  * Copyright (C) 2015 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 android.text.format;
18 
19 import static android.text.format.Formatter.FLAG_IEC_UNITS;
20 import static android.text.format.Formatter.FLAG_SI_UNITS;
21 
22 import static org.junit.Assert.assertEquals;
23 
24 import android.content.Context;
25 import android.content.res.Configuration;
26 import android.content.res.Resources;
27 import android.platform.test.annotations.Presubmit;
28 import android.text.format.Formatter.BytesResult;
29 
30 import androidx.test.InstrumentationRegistry;
31 import androidx.test.filters.SmallTest;
32 import androidx.test.runner.AndroidJUnit4;
33 
34 import org.junit.After;
35 import org.junit.Before;
36 import org.junit.Test;
37 import org.junit.runner.RunWith;
38 
39 import java.math.BigDecimal;
40 import java.math.MathContext;
41 import java.util.Locale;
42 
43 @Presubmit
44 @SmallTest
45 @RunWith(AndroidJUnit4.class)
46 public class FormatterTest {
47     private Locale mOriginalLocale;
48     private Context mContext;
49 
50     @Before
setup()51     public void setup() {
52         mContext = InstrumentationRegistry.getContext();
53         mOriginalLocale = mContext.getResources()
54             .getConfiguration().locale;
55     }
56 
57     @After
tearDown()58     public void tearDown() {
59         if (mOriginalLocale != null) {
60             setLocale(mOriginalLocale);
61         }
62     }
63 
64     @Test
testFormatBytes()65     public void testFormatBytes() {
66         setLocale(Locale.US);
67 
68         checkFormatBytes(0, true, "0", 0);
69         checkFormatBytes(0, false, "0", 0);
70 
71         checkFormatBytes(1, true, "1", 1);
72         checkFormatBytes(1, false, "1", 1);
73 
74         checkFormatBytes(12, true, "12", 12);
75         checkFormatBytes(12, false, "12", 12);
76 
77         checkFormatBytes(123, true, "123", 123);
78         checkFormatBytes(123, false, "123", 123);
79 
80         checkFormatBytes(900, true, "900", 900);
81         checkFormatBytes(900, false, "900", 900);
82 
83         checkFormatBytes(901, true, "0.90", 900);
84         checkFormatBytes(901, false, "0.90", 900);
85 
86         checkFormatBytes(912, true, "0.91", 910);
87         checkFormatBytes(912, false, "0.91", 910);
88 
89         checkFormatBytes(9123, true, "9.1", 9100);
90         checkFormatBytes(9123, false, "9.12", 9120);
91 
92         checkFormatBytes(9123456, true, "9.1", 9100000);
93         checkFormatBytes(9123456, false, "9.12", 9120000);
94 
95         checkFormatBytes(-1, true, "-1", -1);
96         checkFormatBytes(-1, false, "-1", -1);
97 
98         checkFormatBytes(-914, true, "-0.91", -910);
99         checkFormatBytes(-914, false, "-0.91", -910);
100 
101         // Missing FLAG_CALCULATE_ROUNDED case.
102         BytesResult r = Formatter.formatBytes(mContext.getResources(), 1, 0);
103         assertEquals("1", r.value);
104         assertEquals(0, r.roundedBytes); // Didn't pass FLAG_CALCULATE_ROUNDED
105 
106         // Make sure it works on different locales.
107         setLocale(new Locale("es", "ES"));
108         checkFormatBytes(9123000, false, "9,12", 9120000);
109     }
110 
111     @Test
testFormatBytesSi()112     public void testFormatBytesSi() {
113         setLocale(Locale.US);
114 
115         checkFormatBytes(1_000, FLAG_SI_UNITS, "1.00", 1_000);
116         checkFormatBytes(1_024, FLAG_SI_UNITS, "1.02", 1_020);
117         checkFormatBytes(1_500, FLAG_SI_UNITS, "1.50", 1_500);
118         checkFormatBytes(12_582_912L, FLAG_SI_UNITS, "12.58", 12_580_000L);
119     }
120 
121     @Test
testFormatBytesIec()122     public void testFormatBytesIec() {
123         setLocale(Locale.US);
124 
125         checkFormatBytes(1_000, FLAG_IEC_UNITS, "0.98", 1_003);
126         checkFormatBytes(1_024, FLAG_IEC_UNITS, "1.00", 1_024);
127         checkFormatBytes(1_500, FLAG_IEC_UNITS, "1.46", 1_495);
128         checkFormatBytes(12_500_000L, FLAG_IEC_UNITS, "11.92", 12_499_025L);
129         checkFormatBytes(12_582_912L, FLAG_IEC_UNITS, "12.00", 12_582_912L);
130     }
131 
132     private static final long SECOND = 1000;
133     private static final long MINUTE = 60 * SECOND;
134     private static final long HOUR = 60 * MINUTE;
135     private static final long DAY = 24 * HOUR;
136 
137     @Test
testFormatShortElapsedTime()138     public void testFormatShortElapsedTime() {
139         setLocale(Locale.US);
140         assertEquals("3 days", Formatter.formatShortElapsedTime(mContext, 2 * DAY + 12 * HOUR));
141         assertEquals("2 days", Formatter.formatShortElapsedTime(mContext, 2 * DAY + 11 * HOUR));
142         assertEquals("2 days", Formatter.formatShortElapsedTime(mContext, 2 * DAY));
143         assertEquals("1 day, 23 hr",
144                 Formatter.formatShortElapsedTime(mContext, 1 * DAY + 23 * HOUR + 59 * MINUTE));
145         assertEquals("1 day",
146                 Formatter.formatShortElapsedTime(mContext, 1 * DAY + 59 * MINUTE));
147         assertEquals("1 day", Formatter.formatShortElapsedTime(mContext, 1 * DAY));
148         assertEquals("24 hr", Formatter.formatShortElapsedTime(mContext, 23 * HOUR + 30 * MINUTE));
149         assertEquals("3 hr", Formatter.formatShortElapsedTime(mContext, 2 * HOUR + 30 * MINUTE));
150         assertEquals("2 hr", Formatter.formatShortElapsedTime(mContext, 2 * HOUR));
151         assertEquals("1 hr", Formatter.formatShortElapsedTime(mContext, 1 * HOUR));
152         assertEquals("60 min",
153                 Formatter.formatShortElapsedTime(mContext, 59 * MINUTE + 30 * SECOND));
154         assertEquals("59 min",
155                 Formatter.formatShortElapsedTime(mContext, 59 * MINUTE));
156         assertEquals("3 min", Formatter.formatShortElapsedTime(mContext, 2 * MINUTE + 30 * SECOND));
157         assertEquals("2 min", Formatter.formatShortElapsedTime(mContext, 2 * MINUTE));
158         assertEquals("1 min, 59 sec",
159                 Formatter.formatShortElapsedTime(mContext, 1 * MINUTE + 59 * SECOND + 999));
160         assertEquals("1 min", Formatter.formatShortElapsedTime(mContext, 1 * MINUTE));
161         assertEquals("59 sec", Formatter.formatShortElapsedTime(mContext, 59 * SECOND + 999));
162         assertEquals("1 sec", Formatter.formatShortElapsedTime(mContext, 1 * SECOND));
163         assertEquals("0 sec", Formatter.formatShortElapsedTime(mContext, 1));
164         assertEquals("0 sec", Formatter.formatShortElapsedTime(mContext, 0));
165 
166         // Make sure it works on different locales.
167         setLocale(Locale.FRANCE);
168         assertEquals("2\u202fj", Formatter.formatShortElapsedTime(mContext, 2 * DAY));
169     }
170 
171     @Test
testFormatShortElapsedTimeRoundingUpToMinutes()172     public void testFormatShortElapsedTimeRoundingUpToMinutes() {
173         setLocale(Locale.US);
174         assertEquals("3 days", Formatter.formatShortElapsedTimeRoundingUpToMinutes(
175                 mContext, 2 * DAY + 12 * HOUR));
176         assertEquals("2 days", Formatter.formatShortElapsedTimeRoundingUpToMinutes(
177                 mContext, 2 * DAY + 11 * HOUR));
178         assertEquals("2 days", Formatter.formatShortElapsedTimeRoundingUpToMinutes(
179                 mContext, 2 * DAY));
180         assertEquals("1 day, 23 hr", Formatter.formatShortElapsedTimeRoundingUpToMinutes(
181                 mContext, 1 * DAY + 23 * HOUR + 59 * MINUTE));
182         assertEquals("1 day", Formatter.formatShortElapsedTimeRoundingUpToMinutes(
183                 mContext, 1 * DAY + 59 * MINUTE));
184         assertEquals("1 day", Formatter.formatShortElapsedTimeRoundingUpToMinutes(
185                 mContext, 1 * DAY));
186         assertEquals("24 hr", Formatter.formatShortElapsedTimeRoundingUpToMinutes(
187                 mContext, 23 * HOUR + 30 * MINUTE));
188         assertEquals("3 hr", Formatter.formatShortElapsedTimeRoundingUpToMinutes(
189                 mContext, 2 * HOUR + 30 * MINUTE));
190         assertEquals("2 hr", Formatter.formatShortElapsedTimeRoundingUpToMinutes(
191                 mContext, 2 * HOUR));
192         assertEquals("1 hr", Formatter.formatShortElapsedTimeRoundingUpToMinutes(
193                 mContext, 1 * HOUR));
194         assertEquals("1 hr", Formatter.formatShortElapsedTimeRoundingUpToMinutes(
195                 mContext, 59 * MINUTE + 30 * SECOND));
196         assertEquals("59 min", Formatter.formatShortElapsedTimeRoundingUpToMinutes(
197                 mContext, 59 * MINUTE));
198         assertEquals("3 min", Formatter.formatShortElapsedTimeRoundingUpToMinutes(
199                 mContext, 2 * MINUTE + 30 * SECOND));
200         assertEquals("2 min", Formatter.formatShortElapsedTimeRoundingUpToMinutes(
201                 mContext, 2 * MINUTE));
202         assertEquals("2 min", Formatter.formatShortElapsedTimeRoundingUpToMinutes(
203                 mContext, 1 * MINUTE + 59 * SECOND + 999));
204         assertEquals("1 min", Formatter.formatShortElapsedTimeRoundingUpToMinutes(
205                 mContext, 1 * MINUTE));
206         assertEquals("1 min", Formatter.formatShortElapsedTimeRoundingUpToMinutes(
207                 mContext, 59 * SECOND + 999));
208         assertEquals("1 min", Formatter.formatShortElapsedTimeRoundingUpToMinutes(
209                 mContext, 1 * SECOND));
210         assertEquals("1 min", Formatter.formatShortElapsedTimeRoundingUpToMinutes(
211                 mContext, 1));
212         assertEquals("0 min", Formatter.formatShortElapsedTimeRoundingUpToMinutes(
213                 mContext, 0));
214 
215         // Make sure it works on different locales.
216         setLocale(new Locale("ru", "RU"));
217         assertEquals("1 мин", Formatter.formatShortElapsedTimeRoundingUpToMinutes(
218                 mContext, 1 * SECOND));
219     }
220 
221     /**
222      * Regression test for http://b/71580745 and https://unicode-org.atlassian.net/browse/CLDR-10831
223      */
224     @Test
testFormatFileSize_zhCN()225     public void testFormatFileSize_zhCN() {
226         setLocale(Locale.forLanguageTag("zh-CN"));
227 
228         assertFormatFileSize_englishOutput();
229     }
230 
231     @Test
testFormatFileSize_enUS()232     public void testFormatFileSize_enUS() {
233         setLocale(Locale.US);
234 
235         assertFormatFileSize_englishOutput();
236     }
237 
assertFormatFileSize_englishOutput()238     private void assertFormatFileSize_englishOutput() {
239         final MathContext mc = MathContext.DECIMAL64;
240         final BigDecimal bd = new BigDecimal((long) 1000, mc);
241         // test null Context
242         assertEquals("", Formatter.formatFileSize(null, 0));
243         // test different long values with various length
244         assertEquals("0 B", Formatter.formatFileSize(mContext, 0));
245         assertEquals("1 B", Formatter.formatFileSize(mContext, 1));
246         assertEquals("9 B", Formatter.formatFileSize(mContext, 9));
247         assertEquals("10 B", Formatter.formatFileSize(mContext, 10));
248         assertEquals("99 B", Formatter.formatFileSize(mContext, 99));
249         assertEquals("100 B", Formatter.formatFileSize(mContext, 100));
250         assertEquals("900 B", Formatter.formatFileSize(mContext, 900));
251         assertEquals("0.90 kB", Formatter.formatFileSize(mContext, 901));
252 
253         assertEquals("1.00 kB", Formatter.formatFileSize(mContext, bd.pow(1).longValue()));
254         assertEquals("1.50 kB", Formatter.formatFileSize(mContext, bd.pow(1).longValue() * 3 / 2));
255         assertEquals("12.50 kB", Formatter.formatFileSize(mContext,
256                 bd.pow(1).longValue() * 25 / 2));
257 
258         assertEquals("1.00 MB", Formatter.formatFileSize(mContext, bd.pow(2).longValue()));
259 
260         assertEquals("1.00 GB", Formatter.formatFileSize(mContext, bd.pow(3).longValue()));
261 
262         assertEquals("1.00 TB", Formatter.formatFileSize(mContext, bd.pow(4).longValue()));
263 
264         assertEquals("1.00 PB", Formatter.formatFileSize(mContext, bd.pow(5).longValue()));
265 
266         assertEquals("1000 PB", Formatter.formatFileSize(mContext, bd.pow(6).longValue()));
267 
268         // test Negative value
269         assertEquals("-1 B", Formatter.formatFileSize(mContext, -1));
270     }
271 
checkFormatBytes(long bytes, boolean useShort, String expectedString, long expectedRounded)272     private void checkFormatBytes(long bytes, boolean useShort,
273             String expectedString, long expectedRounded) {
274         checkFormatBytes(bytes, (useShort ? Formatter.FLAG_SHORTER : 0),
275                 expectedString, expectedRounded);
276     }
277 
checkFormatBytes(long bytes, int flags, String expectedString, long expectedRounded)278     private void checkFormatBytes(long bytes, int flags,
279             String expectedString, long expectedRounded) {
280         BytesResult r = Formatter.formatBytes(mContext.getResources(), bytes,
281                 Formatter.FLAG_CALCULATE_ROUNDED | flags);
282         assertEquals(expectedString, r.value);
283         assertEquals(expectedRounded, r.roundedBytes);
284     }
285 
setLocale(Locale locale)286     private void setLocale(Locale locale) {
287         Resources res = mContext.getResources();
288         Configuration config = res.getConfiguration();
289         config.locale = locale;
290         res.updateConfiguration(config, res.getDisplayMetrics());
291 
292         Locale.setDefault(locale);
293     }
294 }
295