1/* GENERATED SOURCE. DO NOT MODIFY. */
2// © 2016 and later: Unicode, Inc. and others.
3// License & terms of use: http://www.unicode.org/copyright.html#License
4/*
5 *******************************************************************************
6 * Copyright (C) 2013-2016, International Business Machines Corporation and
7 * others. All Rights Reserved.
8 *******************************************************************************
9 */
10package android.icu.dev.test.format;
11
12import java.io.ByteArrayInputStream;
13import java.io.ByteArrayOutputStream;
14import java.io.IOException;
15import java.io.ObjectInputStream;
16import java.io.ObjectOutputStream;
17import java.io.Serializable;
18import java.lang.reflect.Field;
19import java.text.FieldPosition;
20import java.util.ArrayList;
21import java.util.Collections;
22import java.util.Comparator;
23import java.util.HashMap;
24import java.util.HashSet;
25import java.util.List;
26import java.util.Locale;
27import java.util.Map;
28import java.util.Set;
29import java.util.TreeMap;
30
31import org.junit.Test;
32
33import android.icu.dev.test.TestFmwk;
34import android.icu.dev.test.serializable.SerializableTestUtility;
35import android.icu.impl.Pair;
36import android.icu.impl.Utility;
37import android.icu.math.BigDecimal;
38import android.icu.text.MeasureFormat;
39import android.icu.text.MeasureFormat.FormatWidth;
40import android.icu.text.NumberFormat;
41import android.icu.util.Currency;
42import android.icu.util.Measure;
43import android.icu.util.MeasureUnit;
44import android.icu.util.TimeUnit;
45import android.icu.util.TimeUnitAmount;
46import android.icu.util.ULocale;
47
48/**
49 * See https://sites.google.com/site/icusite/processes/release/tasks/standards?pli=1
50 * for information on how to update with each new release.
51 * @author markdavis
52 */
53public class MeasureUnitTest extends TestFmwk {
54
55    static class OrderedPair<F extends Comparable, S extends Comparable> extends Pair<F, S> implements Comparable<OrderedPair<F, S>> {
56
57        OrderedPair(F first, S second) {
58            super(first, second);
59        }
60
61        public static <F extends Comparable, S extends Comparable> OrderedPair<F, S> of(F first, S second) {
62            if (first == null || second == null) {
63                throw new IllegalArgumentException("OrderedPair.of requires non null values.");
64            }
65            return new OrderedPair<F, S>(first, second);
66        }
67
68        @Override
69        public int compareTo(OrderedPair<F, S> other) {
70            int result = first.compareTo(other.first);
71            if (result != 0) {
72                return result;
73            }
74            return second.compareTo(other.second);
75        }
76    }
77
78    private static final String[] DRAFT_VERSIONS = {"57", "58"};
79
80    private static final HashSet<String> DRAFT_VERSION_SET = new HashSet<String>();
81
82    private static final HashSet<String> TIME_CODES = new HashSet<String>();
83
84    private static final String[][] JAVA_VERSIONS = {
85        {"G_FORCE", "53"},
86        {"DEGREE", "53"},
87        {"ARC_MINUTE", "53"},
88        {"ARC_SECOND", "53"},
89        {"ACRE", "53"},
90        {"HECTARE", "53"},
91        {"SQUARE_FOOT", "53"},
92        {"SQUARE_KILOMETER", "53"},
93        {"SQUARE_METER", "53"},
94        {"SQUARE_MILE", "53"},
95        {"MILLISECOND", "53"},
96        {"CENTIMETER", "53"},
97        {"FOOT", "53"},
98        {"INCH", "53"},
99        {"KILOMETER", "53"},
100        {"LIGHT_YEAR", "53"},
101        {"METER", "53"},
102        {"MILE", "53"},
103        {"MILLIMETER", "53"},
104        {"PICOMETER", "53"},
105        {"YARD", "53"},
106        {"GRAM", "53"},
107        {"KILOGRAM", "53"},
108        {"OUNCE", "53"},
109        {"POUND", "53"},
110        {"HORSEPOWER", "53"},
111        {"KILOWATT", "53"},
112        {"WATT", "53"},
113        {"HECTOPASCAL", "53"},
114        {"INCH_HG", "53"},
115        {"MILLIBAR", "53"},
116        {"KILOMETER_PER_HOUR", "53"},
117        {"METER_PER_SECOND", "53"},
118        {"MILE_PER_HOUR", "53"},
119        {"CELSIUS", "53"},
120        {"FAHRENHEIT", "53"},
121        {"CUBIC_KILOMETER", "53"},
122        {"CUBIC_MILE", "53"},
123        {"LITER", "53"},
124        {"YEAR", "53"},
125        {"MONTH", "53"},
126        {"WEEK", "53"},
127        {"DAY", "53"},
128        {"HOUR", "53"},
129        {"MINUTE", "53"},
130        {"SECOND", "53"},
131        {"METER_PER_SECOND_SQUARED", "54"},
132        {"RADIAN", "54"},
133        {"SQUARE_CENTIMETER", "54"},
134        {"SQUARE_INCH", "54"},
135        {"SQUARE_YARD", "54"},
136        {"LITER_PER_KILOMETER", "54"},
137        {"MILE_PER_GALLON", "54"},
138        {"BIT", "54"},
139        {"BYTE", "54"},
140        {"GIGABIT", "54"},
141        {"GIGABYTE", "54"},
142        {"KILOBIT", "54"},
143        {"KILOBYTE", "54"},
144        {"MEGABIT", "54"},
145        {"MEGABYTE", "54"},
146        {"TERABIT", "54"},
147        {"TERABYTE", "54"},
148        {"MICROSECOND", "54"},
149        {"NANOSECOND", "54"},
150        {"AMPERE", "54"},
151        {"MILLIAMPERE", "54"},
152        {"OHM", "54"},
153        {"VOLT", "54"},
154        {"CALORIE", "54"},
155        {"FOODCALORIE", "54"},
156        {"JOULE", "54"},
157        {"KILOCALORIE", "54"},
158        {"KILOJOULE", "54"},
159        {"KILOWATT_HOUR", "54"},
160        {"GIGAHERTZ", "54"},
161        {"HERTZ", "54"},
162        {"KILOHERTZ", "54"},
163        {"MEGAHERTZ", "54"},
164        {"ASTRONOMICAL_UNIT", "54"},
165        {"DECIMETER", "54"},
166        {"FATHOM", "54"},
167        {"FURLONG", "54"},
168        {"MICROMETER", "54"},
169        {"NANOMETER", "54"},
170        {"NAUTICAL_MILE", "54"},
171        {"PARSEC", "54"},
172        {"LUX", "54"},
173        {"CARAT", "54"},
174        {"METRIC_TON", "54"},
175        {"MICROGRAM", "54"},
176        {"MILLIGRAM", "54"},
177        {"OUNCE_TROY", "54"},
178        {"STONE", "54"},
179        {"TON", "54"},
180        {"GIGAWATT", "54"},
181        {"MEGAWATT", "54"},
182        {"MILLIWATT", "54"},
183        {"MILLIMETER_OF_MERCURY", "54"},
184        {"POUND_PER_SQUARE_INCH", "54"},
185        {"KARAT", "54"},
186        {"KELVIN", "54"},
187        {"ACRE_FOOT", "54"},
188        {"BUSHEL", "54"},
189        {"CENTILITER", "54"},
190        {"CUBIC_CENTIMETER", "54"},
191        {"CUBIC_FOOT", "54"},
192        {"CUBIC_INCH", "54"},
193        {"CUBIC_METER", "54"},
194        {"CUBIC_YARD", "54"},
195        {"CUP", "54"},
196        {"DECILITER", "54"},
197        {"FLUID_OUNCE", "54"},
198        {"GALLON", "54"},
199        {"HECTOLITER", "54"},
200        {"MEGALITER", "54"},
201        {"MILLILITER", "54"},
202        {"PINT", "54"},
203        {"QUART", "54"},
204        {"TABLESPOON", "54"},
205        {"TEASPOON", "54"},
206        {"GENERIC_TEMPERATURE", "56"},
207        {"REVOLUTION_ANGLE", "56"},
208        {"LITER_PER_100KILOMETERS", "56"},
209        {"CENTURY", "56"},
210        {"MILE_SCANDINAVIAN", "56"},
211        {"KNOT", "56"},
212        {"CUP_METRIC", "56"},
213        {"PINT_METRIC", "56"},
214        {"MILLIGRAM_PER_DECILITER", "57"},
215        {"MILLIMOLE_PER_LITER", "57"},
216        {"PART_PER_MILLION", "57"},
217        {"MILE_PER_GALLON_IMPERIAL", "57"},
218        {"GALLON_IMPERIAL", "57"},
219        {"EAST", "58"},
220        {"NORTH", "58"},
221        {"SOUTH", "58"},
222        {"WEST", "58"},
223    };
224
225    private static final HashMap<String, String> JAVA_VERSION_MAP = new HashMap<String, String>();
226
227    static {
228        TIME_CODES.add("year");
229        TIME_CODES.add("month");
230        TIME_CODES.add("week");
231        TIME_CODES.add("day");
232        TIME_CODES.add("hour");
233        TIME_CODES.add("minute");
234        TIME_CODES.add("second");
235        for (String verNum : DRAFT_VERSIONS) {
236            DRAFT_VERSION_SET.add(verNum);
237        }
238        for (String[] funcNameAndVersion : JAVA_VERSIONS) {
239            JAVA_VERSION_MAP.put(funcNameAndVersion[0], funcNameAndVersion[1]);
240        }
241    }
242
243    /**
244     * @author markdavis
245     *
246     */
247    // TODO(junit): resolve
248//    public static void main(String[] args) {
249//        //generateConstants(); if (true) return;
250//
251//        // Ticket #12034 deadlock on multi-threaded static init of MeasureUnit.
252//        // The code below reliably deadlocks with ICU 56.
253//        // The test is here in main() rather than in a test function so it can be made to run
254//        // before anything else.
255//        Thread thread = new Thread()  {
256//            @Override
257//            public void run() {
258//                @SuppressWarnings("unused")
259//                Set<String> measureUnitTypes = MeasureUnit.getAvailableTypes();
260//            }
261//        };
262//        thread.start();
263//        @SuppressWarnings("unused")
264//        Currency cur = Currency.getInstance(ULocale.ENGLISH);
265//        try {thread.join();} catch(InterruptedException e) {};
266//        // System.out.println("Done with MeasureUnit thread test.");
267//
268//        new MeasureUnitTest().run(args);
269//    }
270
271/*
272    @Test
273    public void testZZZ() {
274        // various generateXXX calls go here, see
275        // http://site.icu-project.org/design/formatting/measureformat/updating-measure-unit
276        // use this test to run each of the ollowing in succession
277        //generateConstants("58"); // for MeasureUnit.java, update generated MeasureUnit constants
278        //generateBackwardCompatibilityTest("58.1"); // for MeasureUnitTest.java, create TestCompatible58_1
279        //generateCXXHConstants("58"); // for measunit.h, update generated createXXX methods
280        //generateCXXConstants(); // for measunit.cpp, update generated code
281        //generateCXXBackwardCompatibilityTest("58.1"); // for measfmttest.cpp, create TestCompatible58_1
282        updateJAVAVersions("58"); // for MeasureUnitTest.java, JAVA_VERSIONS
283    }
284*/
285
286    @Test
287    public void TestCompatible53_1() {
288        MeasureUnit[] units = {
289                MeasureUnit.G_FORCE,
290                MeasureUnit.DEGREE,
291                MeasureUnit.ARC_MINUTE,
292                MeasureUnit.ARC_SECOND,
293                MeasureUnit.ACRE,
294                MeasureUnit.HECTARE,
295                MeasureUnit.SQUARE_FOOT,
296                MeasureUnit.SQUARE_KILOMETER,
297                MeasureUnit.SQUARE_METER,
298                MeasureUnit.SQUARE_MILE,
299                MeasureUnit.MILLISECOND,
300                MeasureUnit.CENTIMETER,
301                MeasureUnit.FOOT,
302                MeasureUnit.INCH,
303                MeasureUnit.KILOMETER,
304                MeasureUnit.LIGHT_YEAR,
305                MeasureUnit.METER,
306                MeasureUnit.MILE,
307                MeasureUnit.MILLIMETER,
308                MeasureUnit.PICOMETER,
309                MeasureUnit.YARD,
310                MeasureUnit.GRAM,
311                MeasureUnit.KILOGRAM,
312                MeasureUnit.OUNCE,
313                MeasureUnit.POUND,
314                MeasureUnit.HORSEPOWER,
315                MeasureUnit.KILOWATT,
316                MeasureUnit.WATT,
317                MeasureUnit.HECTOPASCAL,
318                MeasureUnit.INCH_HG,
319                MeasureUnit.MILLIBAR,
320                MeasureUnit.KILOMETER_PER_HOUR,
321                MeasureUnit.METER_PER_SECOND,
322                MeasureUnit.MILE_PER_HOUR,
323                MeasureUnit.CELSIUS,
324                MeasureUnit.FAHRENHEIT,
325                MeasureUnit.CUBIC_KILOMETER,
326                MeasureUnit.CUBIC_MILE,
327                MeasureUnit.LITER,
328                MeasureUnit.YEAR,
329                MeasureUnit.MONTH,
330                MeasureUnit.WEEK,
331                MeasureUnit.DAY,
332                MeasureUnit.HOUR,
333                MeasureUnit.MINUTE,
334                MeasureUnit.SECOND,
335        };
336        assertEquals("", 46, units.length);
337    }
338
339    @Test
340    public void TestCompatible54_1() {
341        MeasureUnit[] units = {
342                MeasureUnit.G_FORCE,
343                MeasureUnit.METER_PER_SECOND_SQUARED,
344                MeasureUnit.ARC_MINUTE,
345                MeasureUnit.ARC_SECOND,
346                MeasureUnit.DEGREE,
347                MeasureUnit.RADIAN,
348                MeasureUnit.ACRE,
349                MeasureUnit.HECTARE,
350                MeasureUnit.SQUARE_CENTIMETER,
351                MeasureUnit.SQUARE_FOOT,
352                MeasureUnit.SQUARE_INCH,
353                MeasureUnit.SQUARE_KILOMETER,
354                MeasureUnit.SQUARE_METER,
355                MeasureUnit.SQUARE_MILE,
356                MeasureUnit.SQUARE_YARD,
357                MeasureUnit.LITER_PER_KILOMETER,
358                MeasureUnit.MILE_PER_GALLON,
359                MeasureUnit.BIT,
360                MeasureUnit.BYTE,
361                MeasureUnit.GIGABIT,
362                MeasureUnit.GIGABYTE,
363                MeasureUnit.KILOBIT,
364                MeasureUnit.KILOBYTE,
365                MeasureUnit.MEGABIT,
366                MeasureUnit.MEGABYTE,
367                MeasureUnit.TERABIT,
368                MeasureUnit.TERABYTE,
369                MeasureUnit.DAY,
370                MeasureUnit.HOUR,
371                MeasureUnit.MICROSECOND,
372                MeasureUnit.MILLISECOND,
373                MeasureUnit.MINUTE,
374                MeasureUnit.MONTH,
375                MeasureUnit.NANOSECOND,
376                MeasureUnit.SECOND,
377                MeasureUnit.WEEK,
378                MeasureUnit.YEAR,
379                MeasureUnit.AMPERE,
380                MeasureUnit.MILLIAMPERE,
381                MeasureUnit.OHM,
382                MeasureUnit.VOLT,
383                MeasureUnit.CALORIE,
384                MeasureUnit.FOODCALORIE,
385                MeasureUnit.JOULE,
386                MeasureUnit.KILOCALORIE,
387                MeasureUnit.KILOJOULE,
388                MeasureUnit.KILOWATT_HOUR,
389                MeasureUnit.GIGAHERTZ,
390                MeasureUnit.HERTZ,
391                MeasureUnit.KILOHERTZ,
392                MeasureUnit.MEGAHERTZ,
393                MeasureUnit.ASTRONOMICAL_UNIT,
394                MeasureUnit.CENTIMETER,
395                MeasureUnit.DECIMETER,
396                MeasureUnit.FATHOM,
397                MeasureUnit.FOOT,
398                MeasureUnit.FURLONG,
399                MeasureUnit.INCH,
400                MeasureUnit.KILOMETER,
401                MeasureUnit.LIGHT_YEAR,
402                MeasureUnit.METER,
403                MeasureUnit.MICROMETER,
404                MeasureUnit.MILE,
405                MeasureUnit.MILLIMETER,
406                MeasureUnit.NANOMETER,
407                MeasureUnit.NAUTICAL_MILE,
408                MeasureUnit.PARSEC,
409                MeasureUnit.PICOMETER,
410                MeasureUnit.YARD,
411                MeasureUnit.LUX,
412                MeasureUnit.CARAT,
413                MeasureUnit.GRAM,
414                MeasureUnit.KILOGRAM,
415                MeasureUnit.METRIC_TON,
416                MeasureUnit.MICROGRAM,
417                MeasureUnit.MILLIGRAM,
418                MeasureUnit.OUNCE,
419                MeasureUnit.OUNCE_TROY,
420                MeasureUnit.POUND,
421                MeasureUnit.STONE,
422                MeasureUnit.TON,
423                MeasureUnit.GIGAWATT,
424                MeasureUnit.HORSEPOWER,
425                MeasureUnit.KILOWATT,
426                MeasureUnit.MEGAWATT,
427                MeasureUnit.MILLIWATT,
428                MeasureUnit.WATT,
429                MeasureUnit.HECTOPASCAL,
430                MeasureUnit.INCH_HG,
431                MeasureUnit.MILLIBAR,
432                MeasureUnit.MILLIMETER_OF_MERCURY,
433                MeasureUnit.POUND_PER_SQUARE_INCH,
434                MeasureUnit.KARAT,
435                MeasureUnit.KILOMETER_PER_HOUR,
436                MeasureUnit.METER_PER_SECOND,
437                MeasureUnit.MILE_PER_HOUR,
438                MeasureUnit.CELSIUS,
439                MeasureUnit.FAHRENHEIT,
440                MeasureUnit.KELVIN,
441                MeasureUnit.ACRE_FOOT,
442                MeasureUnit.BUSHEL,
443                MeasureUnit.CENTILITER,
444                MeasureUnit.CUBIC_CENTIMETER,
445                MeasureUnit.CUBIC_FOOT,
446                MeasureUnit.CUBIC_INCH,
447                MeasureUnit.CUBIC_KILOMETER,
448                MeasureUnit.CUBIC_METER,
449                MeasureUnit.CUBIC_MILE,
450                MeasureUnit.CUBIC_YARD,
451                MeasureUnit.CUP,
452                MeasureUnit.DECILITER,
453                MeasureUnit.FLUID_OUNCE,
454                MeasureUnit.GALLON,
455                MeasureUnit.HECTOLITER,
456                MeasureUnit.LITER,
457                MeasureUnit.MEGALITER,
458                MeasureUnit.MILLILITER,
459                MeasureUnit.PINT,
460                MeasureUnit.QUART,
461                MeasureUnit.TABLESPOON,
462                MeasureUnit.TEASPOON,
463        };
464        assertEquals("",  121, units.length);
465    }
466
467    @Test
468    public void TestCompatible55_1() {
469        MeasureUnit[] units = {
470                MeasureUnit.G_FORCE,
471                MeasureUnit.METER_PER_SECOND_SQUARED,
472                MeasureUnit.ARC_MINUTE,
473                MeasureUnit.ARC_SECOND,
474                MeasureUnit.DEGREE,
475                MeasureUnit.RADIAN,
476                MeasureUnit.ACRE,
477                MeasureUnit.HECTARE,
478                MeasureUnit.SQUARE_CENTIMETER,
479                MeasureUnit.SQUARE_FOOT,
480                MeasureUnit.SQUARE_INCH,
481                MeasureUnit.SQUARE_KILOMETER,
482                MeasureUnit.SQUARE_METER,
483                MeasureUnit.SQUARE_MILE,
484                MeasureUnit.SQUARE_YARD,
485                MeasureUnit.LITER_PER_KILOMETER,
486                MeasureUnit.MILE_PER_GALLON,
487                MeasureUnit.BIT,
488                MeasureUnit.BYTE,
489                MeasureUnit.GIGABIT,
490                MeasureUnit.GIGABYTE,
491                MeasureUnit.KILOBIT,
492                MeasureUnit.KILOBYTE,
493                MeasureUnit.MEGABIT,
494                MeasureUnit.MEGABYTE,
495                MeasureUnit.TERABIT,
496                MeasureUnit.TERABYTE,
497                MeasureUnit.DAY,
498                MeasureUnit.HOUR,
499                MeasureUnit.MICROSECOND,
500                MeasureUnit.MILLISECOND,
501                MeasureUnit.MINUTE,
502                MeasureUnit.MONTH,
503                MeasureUnit.NANOSECOND,
504                MeasureUnit.SECOND,
505                MeasureUnit.WEEK,
506                MeasureUnit.YEAR,
507                MeasureUnit.AMPERE,
508                MeasureUnit.MILLIAMPERE,
509                MeasureUnit.OHM,
510                MeasureUnit.VOLT,
511                MeasureUnit.CALORIE,
512                MeasureUnit.FOODCALORIE,
513                MeasureUnit.JOULE,
514                MeasureUnit.KILOCALORIE,
515                MeasureUnit.KILOJOULE,
516                MeasureUnit.KILOWATT_HOUR,
517                MeasureUnit.GIGAHERTZ,
518                MeasureUnit.HERTZ,
519                MeasureUnit.KILOHERTZ,
520                MeasureUnit.MEGAHERTZ,
521                MeasureUnit.ASTRONOMICAL_UNIT,
522                MeasureUnit.CENTIMETER,
523                MeasureUnit.DECIMETER,
524                MeasureUnit.FATHOM,
525                MeasureUnit.FOOT,
526                MeasureUnit.FURLONG,
527                MeasureUnit.INCH,
528                MeasureUnit.KILOMETER,
529                MeasureUnit.LIGHT_YEAR,
530                MeasureUnit.METER,
531                MeasureUnit.MICROMETER,
532                MeasureUnit.MILE,
533                MeasureUnit.MILLIMETER,
534                MeasureUnit.NANOMETER,
535                MeasureUnit.NAUTICAL_MILE,
536                MeasureUnit.PARSEC,
537                MeasureUnit.PICOMETER,
538                MeasureUnit.YARD,
539                MeasureUnit.LUX,
540                MeasureUnit.CARAT,
541                MeasureUnit.GRAM,
542                MeasureUnit.KILOGRAM,
543                MeasureUnit.METRIC_TON,
544                MeasureUnit.MICROGRAM,
545                MeasureUnit.MILLIGRAM,
546                MeasureUnit.OUNCE,
547                MeasureUnit.OUNCE_TROY,
548                MeasureUnit.POUND,
549                MeasureUnit.STONE,
550                MeasureUnit.TON,
551                MeasureUnit.GIGAWATT,
552                MeasureUnit.HORSEPOWER,
553                MeasureUnit.KILOWATT,
554                MeasureUnit.MEGAWATT,
555                MeasureUnit.MILLIWATT,
556                MeasureUnit.WATT,
557                MeasureUnit.HECTOPASCAL,
558                MeasureUnit.INCH_HG,
559                MeasureUnit.MILLIBAR,
560                MeasureUnit.MILLIMETER_OF_MERCURY,
561                MeasureUnit.POUND_PER_SQUARE_INCH,
562                MeasureUnit.KARAT,
563                MeasureUnit.KILOMETER_PER_HOUR,
564                MeasureUnit.METER_PER_SECOND,
565                MeasureUnit.MILE_PER_HOUR,
566                MeasureUnit.CELSIUS,
567                MeasureUnit.FAHRENHEIT,
568                MeasureUnit.GENERIC_TEMPERATURE,
569                MeasureUnit.KELVIN,
570                MeasureUnit.ACRE_FOOT,
571                MeasureUnit.BUSHEL,
572                MeasureUnit.CENTILITER,
573                MeasureUnit.CUBIC_CENTIMETER,
574                MeasureUnit.CUBIC_FOOT,
575                MeasureUnit.CUBIC_INCH,
576                MeasureUnit.CUBIC_KILOMETER,
577                MeasureUnit.CUBIC_METER,
578                MeasureUnit.CUBIC_MILE,
579                MeasureUnit.CUBIC_YARD,
580                MeasureUnit.CUP,
581                MeasureUnit.DECILITER,
582                MeasureUnit.FLUID_OUNCE,
583                MeasureUnit.GALLON,
584                MeasureUnit.HECTOLITER,
585                MeasureUnit.LITER,
586                MeasureUnit.MEGALITER,
587                MeasureUnit.MILLILITER,
588                MeasureUnit.PINT,
589                MeasureUnit.QUART,
590                MeasureUnit.TABLESPOON,
591                MeasureUnit.TEASPOON,
592        };
593        assertEquals("",  122, units.length);
594    }
595
596    @Test
597    public void TestCompatible56_1() {
598        MeasureUnit[] units = {
599                MeasureUnit.G_FORCE,
600                MeasureUnit.METER_PER_SECOND_SQUARED,
601                MeasureUnit.ARC_MINUTE,
602                MeasureUnit.ARC_SECOND,
603                MeasureUnit.DEGREE,
604                MeasureUnit.RADIAN,
605                MeasureUnit.REVOLUTION_ANGLE,
606                MeasureUnit.ACRE,
607                MeasureUnit.HECTARE,
608                MeasureUnit.SQUARE_CENTIMETER,
609                MeasureUnit.SQUARE_FOOT,
610                MeasureUnit.SQUARE_INCH,
611                MeasureUnit.SQUARE_KILOMETER,
612                MeasureUnit.SQUARE_METER,
613                MeasureUnit.SQUARE_MILE,
614                MeasureUnit.SQUARE_YARD,
615                MeasureUnit.LITER_PER_100KILOMETERS,
616                MeasureUnit.LITER_PER_KILOMETER,
617                MeasureUnit.MILE_PER_GALLON,
618                MeasureUnit.BIT,
619                MeasureUnit.BYTE,
620                MeasureUnit.GIGABIT,
621                MeasureUnit.GIGABYTE,
622                MeasureUnit.KILOBIT,
623                MeasureUnit.KILOBYTE,
624                MeasureUnit.MEGABIT,
625                MeasureUnit.MEGABYTE,
626                MeasureUnit.TERABIT,
627                MeasureUnit.TERABYTE,
628                MeasureUnit.CENTURY,
629                MeasureUnit.DAY,
630                MeasureUnit.HOUR,
631                MeasureUnit.MICROSECOND,
632                MeasureUnit.MILLISECOND,
633                MeasureUnit.MINUTE,
634                MeasureUnit.MONTH,
635                MeasureUnit.NANOSECOND,
636                MeasureUnit.SECOND,
637                MeasureUnit.WEEK,
638                MeasureUnit.YEAR,
639                MeasureUnit.AMPERE,
640                MeasureUnit.MILLIAMPERE,
641                MeasureUnit.OHM,
642                MeasureUnit.VOLT,
643                MeasureUnit.CALORIE,
644                MeasureUnit.FOODCALORIE,
645                MeasureUnit.JOULE,
646                MeasureUnit.KILOCALORIE,
647                MeasureUnit.KILOJOULE,
648                MeasureUnit.KILOWATT_HOUR,
649                MeasureUnit.GIGAHERTZ,
650                MeasureUnit.HERTZ,
651                MeasureUnit.KILOHERTZ,
652                MeasureUnit.MEGAHERTZ,
653                MeasureUnit.ASTRONOMICAL_UNIT,
654                MeasureUnit.CENTIMETER,
655                MeasureUnit.DECIMETER,
656                MeasureUnit.FATHOM,
657                MeasureUnit.FOOT,
658                MeasureUnit.FURLONG,
659                MeasureUnit.INCH,
660                MeasureUnit.KILOMETER,
661                MeasureUnit.LIGHT_YEAR,
662                MeasureUnit.METER,
663                MeasureUnit.MICROMETER,
664                MeasureUnit.MILE,
665                MeasureUnit.MILE_SCANDINAVIAN,
666                MeasureUnit.MILLIMETER,
667                MeasureUnit.NANOMETER,
668                MeasureUnit.NAUTICAL_MILE,
669                MeasureUnit.PARSEC,
670                MeasureUnit.PICOMETER,
671                MeasureUnit.YARD,
672                MeasureUnit.LUX,
673                MeasureUnit.CARAT,
674                MeasureUnit.GRAM,
675                MeasureUnit.KILOGRAM,
676                MeasureUnit.METRIC_TON,
677                MeasureUnit.MICROGRAM,
678                MeasureUnit.MILLIGRAM,
679                MeasureUnit.OUNCE,
680                MeasureUnit.OUNCE_TROY,
681                MeasureUnit.POUND,
682                MeasureUnit.STONE,
683                MeasureUnit.TON,
684                MeasureUnit.GIGAWATT,
685                MeasureUnit.HORSEPOWER,
686                MeasureUnit.KILOWATT,
687                MeasureUnit.MEGAWATT,
688                MeasureUnit.MILLIWATT,
689                MeasureUnit.WATT,
690                MeasureUnit.HECTOPASCAL,
691                MeasureUnit.INCH_HG,
692                MeasureUnit.MILLIBAR,
693                MeasureUnit.MILLIMETER_OF_MERCURY,
694                MeasureUnit.POUND_PER_SQUARE_INCH,
695                MeasureUnit.KARAT,
696                MeasureUnit.KILOMETER_PER_HOUR,
697                MeasureUnit.KNOT,
698                MeasureUnit.METER_PER_SECOND,
699                MeasureUnit.MILE_PER_HOUR,
700                MeasureUnit.CELSIUS,
701                MeasureUnit.FAHRENHEIT,
702                MeasureUnit.GENERIC_TEMPERATURE,
703                MeasureUnit.KELVIN,
704                MeasureUnit.ACRE_FOOT,
705                MeasureUnit.BUSHEL,
706                MeasureUnit.CENTILITER,
707                MeasureUnit.CUBIC_CENTIMETER,
708                MeasureUnit.CUBIC_FOOT,
709                MeasureUnit.CUBIC_INCH,
710                MeasureUnit.CUBIC_KILOMETER,
711                MeasureUnit.CUBIC_METER,
712                MeasureUnit.CUBIC_MILE,
713                MeasureUnit.CUBIC_YARD,
714                MeasureUnit.CUP,
715                MeasureUnit.CUP_METRIC,
716                MeasureUnit.DECILITER,
717                MeasureUnit.FLUID_OUNCE,
718                MeasureUnit.GALLON,
719                MeasureUnit.HECTOLITER,
720                MeasureUnit.LITER,
721                MeasureUnit.MEGALITER,
722                MeasureUnit.MILLILITER,
723                MeasureUnit.PINT,
724                MeasureUnit.PINT_METRIC,
725                MeasureUnit.QUART,
726                MeasureUnit.TABLESPOON,
727                MeasureUnit.TEASPOON,
728        };
729        assertEquals("",  129, units.length);
730    }
731
732    @Test
733    public void TestCompatible57_1() {
734        MeasureUnit[] units = {
735                MeasureUnit.G_FORCE,
736                MeasureUnit.METER_PER_SECOND_SQUARED,
737                MeasureUnit.ARC_MINUTE,
738                MeasureUnit.ARC_SECOND,
739                MeasureUnit.DEGREE,
740                MeasureUnit.RADIAN,
741                MeasureUnit.REVOLUTION_ANGLE,
742                MeasureUnit.ACRE,
743                MeasureUnit.HECTARE,
744                MeasureUnit.SQUARE_CENTIMETER,
745                MeasureUnit.SQUARE_FOOT,
746                MeasureUnit.SQUARE_INCH,
747                MeasureUnit.SQUARE_KILOMETER,
748                MeasureUnit.SQUARE_METER,
749                MeasureUnit.SQUARE_MILE,
750                MeasureUnit.SQUARE_YARD,
751                MeasureUnit.KARAT,
752                MeasureUnit.MILLIGRAM_PER_DECILITER,
753                MeasureUnit.MILLIMOLE_PER_LITER,
754                MeasureUnit.PART_PER_MILLION,
755                MeasureUnit.LITER_PER_100KILOMETERS,
756                MeasureUnit.LITER_PER_KILOMETER,
757                MeasureUnit.MILE_PER_GALLON,
758                MeasureUnit.MILE_PER_GALLON_IMPERIAL,
759                MeasureUnit.BIT,
760                MeasureUnit.BYTE,
761                MeasureUnit.GIGABIT,
762                MeasureUnit.GIGABYTE,
763                MeasureUnit.KILOBIT,
764                MeasureUnit.KILOBYTE,
765                MeasureUnit.MEGABIT,
766                MeasureUnit.MEGABYTE,
767                MeasureUnit.TERABIT,
768                MeasureUnit.TERABYTE,
769                MeasureUnit.CENTURY,
770                MeasureUnit.DAY,
771                MeasureUnit.HOUR,
772                MeasureUnit.MICROSECOND,
773                MeasureUnit.MILLISECOND,
774                MeasureUnit.MINUTE,
775                MeasureUnit.MONTH,
776                MeasureUnit.NANOSECOND,
777                MeasureUnit.SECOND,
778                MeasureUnit.WEEK,
779                MeasureUnit.YEAR,
780                MeasureUnit.AMPERE,
781                MeasureUnit.MILLIAMPERE,
782                MeasureUnit.OHM,
783                MeasureUnit.VOLT,
784                MeasureUnit.CALORIE,
785                MeasureUnit.FOODCALORIE,
786                MeasureUnit.JOULE,
787                MeasureUnit.KILOCALORIE,
788                MeasureUnit.KILOJOULE,
789                MeasureUnit.KILOWATT_HOUR,
790                MeasureUnit.GIGAHERTZ,
791                MeasureUnit.HERTZ,
792                MeasureUnit.KILOHERTZ,
793                MeasureUnit.MEGAHERTZ,
794                MeasureUnit.ASTRONOMICAL_UNIT,
795                MeasureUnit.CENTIMETER,
796                MeasureUnit.DECIMETER,
797                MeasureUnit.FATHOM,
798                MeasureUnit.FOOT,
799                MeasureUnit.FURLONG,
800                MeasureUnit.INCH,
801                MeasureUnit.KILOMETER,
802                MeasureUnit.LIGHT_YEAR,
803                MeasureUnit.METER,
804                MeasureUnit.MICROMETER,
805                MeasureUnit.MILE,
806                MeasureUnit.MILE_SCANDINAVIAN,
807                MeasureUnit.MILLIMETER,
808                MeasureUnit.NANOMETER,
809                MeasureUnit.NAUTICAL_MILE,
810                MeasureUnit.PARSEC,
811                MeasureUnit.PICOMETER,
812                MeasureUnit.YARD,
813                MeasureUnit.LUX,
814                MeasureUnit.CARAT,
815                MeasureUnit.GRAM,
816                MeasureUnit.KILOGRAM,
817                MeasureUnit.METRIC_TON,
818                MeasureUnit.MICROGRAM,
819                MeasureUnit.MILLIGRAM,
820                MeasureUnit.OUNCE,
821                MeasureUnit.OUNCE_TROY,
822                MeasureUnit.POUND,
823                MeasureUnit.STONE,
824                MeasureUnit.TON,
825                MeasureUnit.GIGAWATT,
826                MeasureUnit.HORSEPOWER,
827                MeasureUnit.KILOWATT,
828                MeasureUnit.MEGAWATT,
829                MeasureUnit.MILLIWATT,
830                MeasureUnit.WATT,
831                MeasureUnit.HECTOPASCAL,
832                MeasureUnit.INCH_HG,
833                MeasureUnit.MILLIBAR,
834                MeasureUnit.MILLIMETER_OF_MERCURY,
835                MeasureUnit.POUND_PER_SQUARE_INCH,
836                MeasureUnit.KILOMETER_PER_HOUR,
837                MeasureUnit.KNOT,
838                MeasureUnit.METER_PER_SECOND,
839                MeasureUnit.MILE_PER_HOUR,
840                MeasureUnit.CELSIUS,
841                MeasureUnit.FAHRENHEIT,
842                MeasureUnit.GENERIC_TEMPERATURE,
843                MeasureUnit.KELVIN,
844                MeasureUnit.ACRE_FOOT,
845                MeasureUnit.BUSHEL,
846                MeasureUnit.CENTILITER,
847                MeasureUnit.CUBIC_CENTIMETER,
848                MeasureUnit.CUBIC_FOOT,
849                MeasureUnit.CUBIC_INCH,
850                MeasureUnit.CUBIC_KILOMETER,
851                MeasureUnit.CUBIC_METER,
852                MeasureUnit.CUBIC_MILE,
853                MeasureUnit.CUBIC_YARD,
854                MeasureUnit.CUP,
855                MeasureUnit.CUP_METRIC,
856                MeasureUnit.DECILITER,
857                MeasureUnit.FLUID_OUNCE,
858                MeasureUnit.GALLON,
859                MeasureUnit.GALLON_IMPERIAL,
860                MeasureUnit.HECTOLITER,
861                MeasureUnit.LITER,
862                MeasureUnit.MEGALITER,
863                MeasureUnit.MILLILITER,
864                MeasureUnit.PINT,
865                MeasureUnit.PINT_METRIC,
866                MeasureUnit.QUART,
867                MeasureUnit.TABLESPOON,
868                MeasureUnit.TEASPOON,
869        };
870        assertEquals("",  134, units.length);
871    }
872
873    @Test
874    public void TestCompatible58_1() {
875        MeasureUnit[] units = {
876                MeasureUnit.G_FORCE,
877                MeasureUnit.METER_PER_SECOND_SQUARED,
878                MeasureUnit.ARC_MINUTE,
879                MeasureUnit.ARC_SECOND,
880                MeasureUnit.DEGREE,
881                MeasureUnit.RADIAN,
882                MeasureUnit.REVOLUTION_ANGLE,
883                MeasureUnit.ACRE,
884                MeasureUnit.HECTARE,
885                MeasureUnit.SQUARE_CENTIMETER,
886                MeasureUnit.SQUARE_FOOT,
887                MeasureUnit.SQUARE_INCH,
888                MeasureUnit.SQUARE_KILOMETER,
889                MeasureUnit.SQUARE_METER,
890                MeasureUnit.SQUARE_MILE,
891                MeasureUnit.SQUARE_YARD,
892                MeasureUnit.KARAT,
893                MeasureUnit.MILLIGRAM_PER_DECILITER,
894                MeasureUnit.MILLIMOLE_PER_LITER,
895                MeasureUnit.PART_PER_MILLION,
896                MeasureUnit.LITER_PER_100KILOMETERS,
897                MeasureUnit.LITER_PER_KILOMETER,
898                MeasureUnit.MILE_PER_GALLON,
899                MeasureUnit.MILE_PER_GALLON_IMPERIAL,
900                MeasureUnit.EAST,
901                MeasureUnit.NORTH,
902                MeasureUnit.SOUTH,
903                MeasureUnit.WEST,
904                MeasureUnit.BIT,
905                MeasureUnit.BYTE,
906                MeasureUnit.GIGABIT,
907                MeasureUnit.GIGABYTE,
908                MeasureUnit.KILOBIT,
909                MeasureUnit.KILOBYTE,
910                MeasureUnit.MEGABIT,
911                MeasureUnit.MEGABYTE,
912                MeasureUnit.TERABIT,
913                MeasureUnit.TERABYTE,
914                MeasureUnit.CENTURY,
915                MeasureUnit.DAY,
916                MeasureUnit.HOUR,
917                MeasureUnit.MICROSECOND,
918                MeasureUnit.MILLISECOND,
919                MeasureUnit.MINUTE,
920                MeasureUnit.MONTH,
921                MeasureUnit.NANOSECOND,
922                MeasureUnit.SECOND,
923                MeasureUnit.WEEK,
924                MeasureUnit.YEAR,
925                MeasureUnit.AMPERE,
926                MeasureUnit.MILLIAMPERE,
927                MeasureUnit.OHM,
928                MeasureUnit.VOLT,
929                MeasureUnit.CALORIE,
930                MeasureUnit.FOODCALORIE,
931                MeasureUnit.JOULE,
932                MeasureUnit.KILOCALORIE,
933                MeasureUnit.KILOJOULE,
934                MeasureUnit.KILOWATT_HOUR,
935                MeasureUnit.GIGAHERTZ,
936                MeasureUnit.HERTZ,
937                MeasureUnit.KILOHERTZ,
938                MeasureUnit.MEGAHERTZ,
939                MeasureUnit.ASTRONOMICAL_UNIT,
940                MeasureUnit.CENTIMETER,
941                MeasureUnit.DECIMETER,
942                MeasureUnit.FATHOM,
943                MeasureUnit.FOOT,
944                MeasureUnit.FURLONG,
945                MeasureUnit.INCH,
946                MeasureUnit.KILOMETER,
947                MeasureUnit.LIGHT_YEAR,
948                MeasureUnit.METER,
949                MeasureUnit.MICROMETER,
950                MeasureUnit.MILE,
951                MeasureUnit.MILE_SCANDINAVIAN,
952                MeasureUnit.MILLIMETER,
953                MeasureUnit.NANOMETER,
954                MeasureUnit.NAUTICAL_MILE,
955                MeasureUnit.PARSEC,
956                MeasureUnit.PICOMETER,
957                MeasureUnit.YARD,
958                MeasureUnit.LUX,
959                MeasureUnit.CARAT,
960                MeasureUnit.GRAM,
961                MeasureUnit.KILOGRAM,
962                MeasureUnit.METRIC_TON,
963                MeasureUnit.MICROGRAM,
964                MeasureUnit.MILLIGRAM,
965                MeasureUnit.OUNCE,
966                MeasureUnit.OUNCE_TROY,
967                MeasureUnit.POUND,
968                MeasureUnit.STONE,
969                MeasureUnit.TON,
970                MeasureUnit.GIGAWATT,
971                MeasureUnit.HORSEPOWER,
972                MeasureUnit.KILOWATT,
973                MeasureUnit.MEGAWATT,
974                MeasureUnit.MILLIWATT,
975                MeasureUnit.WATT,
976                MeasureUnit.HECTOPASCAL,
977                MeasureUnit.INCH_HG,
978                MeasureUnit.MILLIBAR,
979                MeasureUnit.MILLIMETER_OF_MERCURY,
980                MeasureUnit.POUND_PER_SQUARE_INCH,
981                MeasureUnit.KILOMETER_PER_HOUR,
982                MeasureUnit.KNOT,
983                MeasureUnit.METER_PER_SECOND,
984                MeasureUnit.MILE_PER_HOUR,
985                MeasureUnit.CELSIUS,
986                MeasureUnit.FAHRENHEIT,
987                MeasureUnit.GENERIC_TEMPERATURE,
988                MeasureUnit.KELVIN,
989                MeasureUnit.ACRE_FOOT,
990                MeasureUnit.BUSHEL,
991                MeasureUnit.CENTILITER,
992                MeasureUnit.CUBIC_CENTIMETER,
993                MeasureUnit.CUBIC_FOOT,
994                MeasureUnit.CUBIC_INCH,
995                MeasureUnit.CUBIC_KILOMETER,
996                MeasureUnit.CUBIC_METER,
997                MeasureUnit.CUBIC_MILE,
998                MeasureUnit.CUBIC_YARD,
999                MeasureUnit.CUP,
1000                MeasureUnit.CUP_METRIC,
1001                MeasureUnit.DECILITER,
1002                MeasureUnit.FLUID_OUNCE,
1003                MeasureUnit.GALLON,
1004                MeasureUnit.GALLON_IMPERIAL,
1005                MeasureUnit.HECTOLITER,
1006                MeasureUnit.LITER,
1007                MeasureUnit.MEGALITER,
1008                MeasureUnit.MILLILITER,
1009                MeasureUnit.PINT,
1010                MeasureUnit.PINT_METRIC,
1011                MeasureUnit.QUART,
1012                MeasureUnit.TABLESPOON,
1013                MeasureUnit.TEASPOON,
1014        };
1015        assertEquals("",  138, units.length);
1016    }
1017
1018    @Test
1019    public void TestExamplesInDocs() {
1020        MeasureFormat fmtFr = MeasureFormat.getInstance(
1021                ULocale.FRENCH, FormatWidth.SHORT);
1022        Measure measure = new Measure(23, MeasureUnit.CELSIUS);
1023        assertEquals("23 °C", "23 °C", fmtFr.format(measure));
1024        Measure measureF = new Measure(70, MeasureUnit.FAHRENHEIT);
1025        assertEquals("70 °F", "70 °F", fmtFr.format(measureF));
1026        MeasureFormat fmtFrFull = MeasureFormat.getInstance(
1027                ULocale.FRENCH, FormatWidth.WIDE);
1028        assertEquals(
1029                "70 pied et 5,3 pouces",
1030                "70 pieds et 5,3 pouces",
1031                fmtFrFull.formatMeasures(
1032                        new Measure(70, MeasureUnit.FOOT),
1033                        new Measure(5.3, MeasureUnit.INCH)));
1034        assertEquals(
1035                "1 pied et 1 pouce",
1036                "1 pied et 1 pouce",
1037                fmtFrFull.formatMeasures(
1038                        new Measure(1, MeasureUnit.FOOT),
1039                        new Measure(1, MeasureUnit.INCH)));
1040        MeasureFormat fmtFrNarrow = MeasureFormat.getInstance(
1041                ULocale.FRENCH, FormatWidth.NARROW);
1042        assertEquals(
1043                "1′ 1″",
1044                "1′ 1″",
1045                fmtFrNarrow.formatMeasures(
1046                        new Measure(1, MeasureUnit.FOOT),
1047                        new Measure(1, MeasureUnit.INCH)));
1048        MeasureFormat fmtEn = MeasureFormat.getInstance(ULocale.ENGLISH, FormatWidth.WIDE);
1049        assertEquals(
1050                "1 inch, 2 feet",
1051                "1 inch, 2 feet",
1052                fmtEn.formatMeasures(
1053                        new Measure(1, MeasureUnit.INCH),
1054                        new Measure(2, MeasureUnit.FOOT)));
1055    }
1056
1057    @Test
1058    public void TestFormatPeriodEn() {
1059        TimeUnitAmount[] _19m = {new TimeUnitAmount(19.0, TimeUnit.MINUTE)};
1060        TimeUnitAmount[] _1h_23_5s = {
1061                new TimeUnitAmount(1.0, TimeUnit.HOUR),
1062                new TimeUnitAmount(23.5, TimeUnit.SECOND)};
1063        TimeUnitAmount[] _1h_23_5m = {
1064                new TimeUnitAmount(1.0, TimeUnit.HOUR),
1065                new TimeUnitAmount(23.5, TimeUnit.MINUTE)};
1066        TimeUnitAmount[] _1h_0m_23s = {
1067                new TimeUnitAmount(1.0, TimeUnit.HOUR),
1068                new TimeUnitAmount(0.0, TimeUnit.MINUTE),
1069                new TimeUnitAmount(23.0, TimeUnit.SECOND)};
1070        TimeUnitAmount[] _2y_5M_3w_4d = {
1071                new TimeUnitAmount(2.0, TimeUnit.YEAR),
1072                new TimeUnitAmount(5.0, TimeUnit.MONTH),
1073                new TimeUnitAmount(3.0, TimeUnit.WEEK),
1074                new TimeUnitAmount(4.0, TimeUnit.DAY)};
1075        TimeUnitAmount[] _1m_59_9996s = {
1076                new TimeUnitAmount(1.0, TimeUnit.MINUTE),
1077                new TimeUnitAmount(59.9996, TimeUnit.SECOND)};
1078        TimeUnitAmount[] _5h_17m = {
1079                new TimeUnitAmount(5.0, TimeUnit.HOUR),
1080                new TimeUnitAmount(17.0, TimeUnit.MINUTE)};
1081        TimeUnitAmount[] _neg5h_17m = {
1082                new TimeUnitAmount(-5.0, TimeUnit.HOUR),
1083                new TimeUnitAmount(17.0, TimeUnit.MINUTE)};
1084        TimeUnitAmount[] _19m_28s = {
1085                new TimeUnitAmount(19.0, TimeUnit.MINUTE),
1086                new TimeUnitAmount(28.0, TimeUnit.SECOND)};
1087        TimeUnitAmount[] _0h_0m_9s = {
1088                new TimeUnitAmount(0.0, TimeUnit.HOUR),
1089                new TimeUnitAmount(0.0, TimeUnit.MINUTE),
1090                new TimeUnitAmount(9.0, TimeUnit.SECOND)};
1091        TimeUnitAmount[] _0h_0m_17s = {
1092                new TimeUnitAmount(0.0, TimeUnit.HOUR),
1093                new TimeUnitAmount(0.0, TimeUnit.MINUTE),
1094                new TimeUnitAmount(17.0, TimeUnit.SECOND)};
1095        TimeUnitAmount[] _6h_56_92m = {
1096                new TimeUnitAmount(6.0, TimeUnit.HOUR),
1097                new TimeUnitAmount(56.92, TimeUnit.MINUTE)};
1098        TimeUnitAmount[] _3h_4s_5m = {
1099                new TimeUnitAmount(3.0, TimeUnit.HOUR),
1100                new TimeUnitAmount(4.0, TimeUnit.SECOND),
1101                new TimeUnitAmount(5.0, TimeUnit.MINUTE)};
1102        TimeUnitAmount[] _6_7h_56_92m = {
1103                new TimeUnitAmount(6.7, TimeUnit.HOUR),
1104                new TimeUnitAmount(56.92, TimeUnit.MINUTE)};
1105        TimeUnitAmount[] _3h_5h = {
1106                new TimeUnitAmount(3.0, TimeUnit.HOUR),
1107                new TimeUnitAmount(5.0, TimeUnit.HOUR)};
1108
1109        Object[][] fullData = {
1110                {_1m_59_9996s, "1 minute, 59.9996 seconds"},
1111                {_19m, "19 minutes"},
1112                {_1h_23_5s, "1 hour, 23.5 seconds"},
1113                {_1h_23_5m, "1 hour, 23.5 minutes"},
1114                {_1h_0m_23s, "1 hour, 0 minutes, 23 seconds"},
1115                {_2y_5M_3w_4d, "2 years, 5 months, 3 weeks, 4 days"}};
1116        Object[][] abbrevData = {
1117                {_1m_59_9996s, "1 min, 59.9996 sec"},
1118                {_19m, "19 min"},
1119                {_1h_23_5s, "1 hr, 23.5 sec"},
1120                {_1h_23_5m, "1 hr, 23.5 min"},
1121                {_1h_0m_23s, "1 hr, 0 min, 23 sec"},
1122                {_2y_5M_3w_4d, "2 yrs, 5 mths, 3 wks, 4 days"}};
1123        Object[][] narrowData = {
1124                {_1m_59_9996s, "1m 59.9996s"},
1125                {_19m, "19m"},
1126                {_1h_23_5s, "1h 23.5s"},
1127                {_1h_23_5m, "1h 23.5m"},
1128                {_1h_0m_23s, "1h 0m 23s"},
1129                {_2y_5M_3w_4d, "2y 5m 3w 4d"}};
1130
1131
1132        Object[][] numericData = {
1133                {_1m_59_9996s, "1:59.9996"},
1134                {_19m, "19m"},
1135                {_1h_23_5s, "1:00:23.5"},
1136                {_1h_0m_23s, "1:00:23"},
1137                {_1h_23_5m, "1:23.5"},
1138                {_5h_17m, "5:17"},
1139                {_neg5h_17m, "-5h 17m"},
1140                {_19m_28s, "19:28"},
1141                {_2y_5M_3w_4d, "2y 5m 3w 4d"},
1142                {_0h_0m_9s, "0:00:09"},
1143                {_6h_56_92m, "6:56.92"},
1144                {_6_7h_56_92m, "6:56.92"},
1145                {_3h_4s_5m, "3h 4s 5m"},
1146                {_3h_5h, "3h 5h"}};
1147        Object[][] fullDataDe = {
1148                {_1m_59_9996s, "1 Minute, 59,9996 Sekunden"},
1149                {_19m, "19 Minuten"},
1150                {_1h_23_5s, "1 Stunde, 23,5 Sekunden"},
1151                {_1h_23_5m, "1 Stunde, 23,5 Minuten"},
1152                {_1h_0m_23s, "1 Stunde, 0 Minuten und 23 Sekunden"},
1153                {_2y_5M_3w_4d, "2 Jahre, 5 Monate, 3 Wochen und 4 Tage"}};
1154        Object[][] numericDataDe = {
1155                {_1m_59_9996s, "1:59,9996"},
1156                {_19m, "19 Min."},
1157                {_1h_23_5s, "1:00:23,5"},
1158                {_1h_0m_23s, "1:00:23"},
1159                {_1h_23_5m, "1:23,5"},
1160                {_5h_17m, "5:17"},
1161                {_19m_28s, "19:28"},
1162                {_2y_5M_3w_4d, "2 J, 5 M, 3 W und 4 T"},
1163                {_0h_0m_17s, "0:00:17"},
1164                {_6h_56_92m, "6:56,92"},
1165                {_3h_5h, "3 Std., 5 Std."}};
1166
1167        NumberFormat nf = NumberFormat.getNumberInstance(ULocale.ENGLISH);
1168        nf.setMaximumFractionDigits(4);
1169        MeasureFormat mf = MeasureFormat.getInstance(ULocale.ENGLISH, FormatWidth.WIDE, nf);
1170        verifyFormatPeriod("en FULL", mf, fullData);
1171        mf = MeasureFormat.getInstance(ULocale.ENGLISH, FormatWidth.SHORT, nf);
1172        verifyFormatPeriod("en SHORT", mf, abbrevData);
1173        mf = MeasureFormat.getInstance(ULocale.ENGLISH, FormatWidth.NARROW, nf);
1174        verifyFormatPeriod("en NARROW", mf, narrowData);
1175        mf = MeasureFormat.getInstance(ULocale.ENGLISH, FormatWidth.NUMERIC, nf);
1176        verifyFormatPeriod("en NUMERIC", mf, numericData);
1177
1178        nf = NumberFormat.getNumberInstance(ULocale.GERMAN);
1179        nf.setMaximumFractionDigits(4);
1180        mf = MeasureFormat.getInstance(ULocale.GERMAN, FormatWidth.WIDE, nf);
1181        verifyFormatPeriod("de FULL", mf, fullDataDe);
1182        mf = MeasureFormat.getInstance(ULocale.GERMAN, FormatWidth.NUMERIC, nf);
1183        verifyFormatPeriod("de NUMERIC", mf, numericDataDe);
1184
1185        // Same tests, with Java Locale
1186        nf = NumberFormat.getNumberInstance(Locale.GERMAN);
1187        nf.setMaximumFractionDigits(4);
1188        mf = MeasureFormat.getInstance(Locale.GERMAN, FormatWidth.WIDE, nf);
1189        verifyFormatPeriod("de FULL(Java Locale)", mf, fullDataDe);
1190        mf = MeasureFormat.getInstance(Locale.GERMAN, FormatWidth.NUMERIC, nf);
1191        verifyFormatPeriod("de NUMERIC(Java Locale)", mf, numericDataDe);
1192
1193    }
1194
1195    private void verifyFormatPeriod(String desc, MeasureFormat mf, Object[][] testData) {
1196        StringBuilder builder = new StringBuilder();
1197        boolean failure = false;
1198        for (Object[] testCase : testData) {
1199            String actual = mf.format(testCase[0]);
1200            if (!testCase[1].equals(actual)) {
1201                builder.append(String.format("%s: Expected: '%s', got: '%s'\n", desc, testCase[1], actual));
1202                failure = true;
1203            }
1204        }
1205        if (failure) {
1206            errln(builder.toString());
1207        }
1208    }
1209
1210    @Test
1211    public void Test10219FractionalPlurals() {
1212        double[] values = {1.588, 1.011};
1213        String[][] expected = {
1214                {"1 minute", "1.5 minutes", "1.58 minutes"},
1215                {"1 minute", "1.0 minutes", "1.01 minutes"}
1216        };
1217        for (int j = 0; j < values.length; j++) {
1218            for (int i = 0; i < expected[j].length; i++) {
1219                NumberFormat nf = NumberFormat.getNumberInstance(ULocale.ENGLISH);
1220                nf.setRoundingMode(BigDecimal.ROUND_DOWN);
1221                nf.setMinimumFractionDigits(i);
1222                nf.setMaximumFractionDigits(i);
1223                MeasureFormat mf = MeasureFormat.getInstance(
1224                        ULocale.ENGLISH, FormatWidth.WIDE, nf);
1225                assertEquals("Test10219", expected[j][i], mf.format(new Measure(values[j], MeasureUnit.MINUTE)));
1226            }
1227        }
1228    }
1229
1230    @Test
1231    public void TestGreek() {
1232        String[] locales = {"el_GR", "el"};
1233        final MeasureUnit[] units = new MeasureUnit[]{
1234                MeasureUnit.SECOND,
1235                MeasureUnit.MINUTE,
1236                MeasureUnit.HOUR,
1237                MeasureUnit.DAY,
1238                MeasureUnit.WEEK,
1239                MeasureUnit.MONTH,
1240                MeasureUnit.YEAR};
1241        FormatWidth[] styles = new FormatWidth[] {FormatWidth.WIDE, FormatWidth.SHORT};
1242        int[] numbers = new int[] {1, 7};
1243        String[] expected = {
1244                // "el_GR" 1 wide
1245                "1 δευτερόλεπτο",
1246                "1 λεπτό",
1247                "1 ώρα",
1248                "1 ημέρα",
1249                "1 εβδομάδα",
1250                "1 μήνας",
1251                "1 έτος",
1252                // "el_GR" 1 short
1253                "1 δευτ.",
1254                "1 λεπ.",
1255                "1 ώρα",
1256                "1 ημέρα",
1257                "1 εβδ.",
1258                "1 μήν.",
1259                "1 έτ.",	        // year (one)
1260                // "el_GR" 7 wide
1261                "7 δευτερόλεπτα",
1262                "7 λεπτά",
1263                "7 ώρες",
1264                "7 ημέρες",
1265                "7 εβδομάδες",
1266                "7 μήνες",
1267                "7 έτη",
1268                // "el_GR" 7 short
1269                "7 δευτ.",
1270                "7 λεπ.",
1271                "7 ώρ.",		    // hour (other)
1272                "7 ημέρες",
1273                "7 εβδ.",
1274                "7 μήν.",
1275                "7 έτ.",            // year (other)
1276                // "el" 1 wide
1277                "1 δευτερόλεπτο",
1278                "1 λεπτό",
1279                "1 ώρα",
1280                "1 ημέρα",
1281                "1 εβδομάδα",
1282                "1 μήνας",
1283                "1 έτος",
1284                // "el" 1 short
1285                "1 δευτ.",
1286                "1 λεπ.",
1287                "1 ώρα",
1288                "1 ημέρα",
1289                "1 εβδ.",
1290                "1 μήν.",
1291                "1 έτ.",	        // year (one)
1292                // "el" 7 wide
1293                "7 δευτερόλεπτα",
1294                "7 λεπτά",
1295                "7 ώρες",
1296                "7 ημέρες",
1297                "7 εβδομάδες",
1298                "7 μήνες",
1299                "7 έτη",
1300                // "el" 7 short
1301                "7 δευτ.",
1302                "7 λεπ.",
1303                "7 ώρ.",		    // hour (other)
1304                "7 ημέρες",
1305                "7 εβδ.",
1306                "7 μήν.",
1307                "7 έτ."};           // year (other
1308        int counter = 0;
1309        String formatted;
1310        for ( int locIndex = 0; locIndex < locales.length; ++locIndex ) {
1311            for( int numIndex = 0; numIndex < numbers.length; ++numIndex ) {
1312                for ( int styleIndex = 0; styleIndex < styles.length; ++styleIndex ) {
1313                    for ( int unitIndex = 0; unitIndex < units.length; ++unitIndex ) {
1314                        Measure m = new Measure(numbers[numIndex], units[unitIndex]);
1315                        MeasureFormat fmt = MeasureFormat.getInstance(new ULocale(locales[locIndex]), styles[styleIndex]);
1316                        formatted = fmt.format(m);
1317                        assertEquals(
1318                                "locale: " + locales[locIndex]
1319                                        + ", style: " + styles[styleIndex]
1320                                                + ", units: " + units[unitIndex]
1321                                                        + ", value: " + numbers[numIndex],
1322                                                expected[counter], formatted);
1323                        ++counter;
1324                    }
1325                }
1326            }
1327        }
1328    }
1329
1330    @Test
1331    public void testAUnit() {
1332        String lastType = null;
1333        for (MeasureUnit expected : MeasureUnit.getAvailable()) {
1334            String type = expected.getType();
1335            String code = expected.getSubtype();
1336            if (!type.equals(lastType)) {
1337                logln(type);
1338                lastType = type;
1339            }
1340            MeasureUnit actual = MeasureUnit.internalGetInstance(type, code);
1341            assertSame("Identity check", expected, actual);
1342        }
1343    }
1344
1345    @Test
1346    public void testFormatSingleArg() {
1347        MeasureFormat mf = MeasureFormat.getInstance(ULocale.ENGLISH, FormatWidth.WIDE);
1348        assertEquals("", "5 meters", mf.format(new Measure(5, MeasureUnit.METER)));
1349    }
1350
1351    @Test
1352    public void testFormatMeasuresZeroArg() {
1353        MeasureFormat mf = MeasureFormat.getInstance(ULocale.ENGLISH, FormatWidth.WIDE);
1354        assertEquals("", "", mf.formatMeasures());
1355    }
1356
1357    @Test
1358    public void testFormatMeasuresOneArg() {
1359        MeasureFormat mf = MeasureFormat.getInstance(ULocale.ENGLISH, FormatWidth.WIDE);
1360        assertEquals("", "5 meters", mf.formatMeasures(new Measure(5, MeasureUnit.METER)));
1361    }
1362
1363
1364
1365    @Test
1366    public void testMultiples() {
1367        ULocale russia = new ULocale("ru");
1368        Object[][] data = new Object[][] {
1369                {ULocale.ENGLISH, FormatWidth.WIDE, "2 miles, 1 foot, 2.3 inches"},
1370                {ULocale.ENGLISH, FormatWidth.SHORT, "2 mi, 1 ft, 2.3 in"},
1371                {ULocale.ENGLISH, FormatWidth.NARROW, "2mi 1\u2032 2.3\u2033"},
1372                {russia, FormatWidth.WIDE,   "2 \u043C\u0438\u043B\u0438 1 \u0444\u0443\u0442 \u0438 2,3 \u0434\u044E\u0439\u043C\u0430"},
1373                {russia, FormatWidth.SHORT,  "2 \u043C\u0438\u043B\u0438 1 \u0444\u0443\u0442 \u0438 2,3 \u0434\u044E\u0439\u043C."},
1374                {russia, FormatWidth.NARROW, "2 \u043C\u0438\u043B\u044C 1 \u0444\u0443\u0442 2,3 \u0434\u044E\u0439\u043C\u0430"},
1375        };
1376        for (Object[] row : data) {
1377            MeasureFormat mf = MeasureFormat.getInstance(
1378                    (ULocale) row[0], (FormatWidth) row[1]);
1379            assertEquals(
1380                    "testMultiples",
1381                    row[2],
1382                    mf.formatMeasures(
1383                            new Measure(2, MeasureUnit.MILE),
1384                            new Measure(1, MeasureUnit.FOOT),
1385                            new Measure(2.3, MeasureUnit.INCH)));
1386        }
1387    }
1388
1389    @Test
1390    public void testManyLocaleDurations() {
1391        Measure hours   = new Measure(5, MeasureUnit.HOUR);
1392        Measure minutes = new Measure(37, MeasureUnit.MINUTE);
1393        ULocale ulocDanish       = new ULocale("da");
1394        ULocale ulocSpanish      = new ULocale("es");
1395        ULocale ulocFinnish      = new ULocale("fi");
1396        ULocale ulocIcelandic    = new ULocale("is");
1397        ULocale ulocNorwegianBok = new ULocale("nb");
1398        ULocale ulocNorwegianNyn = new ULocale("nn");
1399        ULocale ulocDutch        = new ULocale("nl");
1400        ULocale ulocSwedish      = new ULocale("sv");
1401        Object[][] data = new Object[][] {
1402            { ulocDanish,       FormatWidth.NARROW,  "5 t og 37 min" },
1403            { ulocDanish,       FormatWidth.NUMERIC, "5.37" },
1404            { ULocale.GERMAN,   FormatWidth.NARROW,  "5 Std., 37 Min." },
1405            { ULocale.GERMAN,   FormatWidth.NUMERIC, "5:37" },
1406            { ULocale.ENGLISH,  FormatWidth.NARROW,  "5h 37m" },
1407            { ULocale.ENGLISH,  FormatWidth.NUMERIC, "5:37" },
1408            { ulocSpanish,      FormatWidth.NARROW,  "5h 37min" },
1409            { ulocSpanish,      FormatWidth.NUMERIC, "5:37" },
1410            { ulocFinnish,      FormatWidth.NARROW,  "5t 37min" },
1411            { ulocFinnish,      FormatWidth.NUMERIC, "5.37" },
1412            { ULocale.FRENCH,   FormatWidth.NARROW,  "5h 37m" },
1413            { ULocale.FRENCH,   FormatWidth.NUMERIC, "05:37" },
1414            { ulocIcelandic,    FormatWidth.NARROW,  "5 klst. og 37 m\u00EDn." },
1415            { ulocIcelandic,    FormatWidth.NUMERIC, "5:37" },
1416            { ULocale.JAPANESE, FormatWidth.NARROW,  "5h37m" },
1417            { ULocale.JAPANESE, FormatWidth.NUMERIC, "5:37" },
1418            { ulocNorwegianBok, FormatWidth.NARROW,  "5t, 37m" },
1419            { ulocNorwegianBok, FormatWidth.NUMERIC, "5:37" },
1420            { ulocDutch,        FormatWidth.NARROW,  "5 u, 37 m" },
1421            { ulocDutch,        FormatWidth.NUMERIC, "5:37" },
1422            { ulocNorwegianNyn, FormatWidth.NARROW,  "5 h og 37 min" },
1423            { ulocNorwegianNyn, FormatWidth.NUMERIC, "5:37" },
1424            { ulocSwedish,      FormatWidth.NARROW,  "5h 37m" },
1425            { ulocSwedish,      FormatWidth.NUMERIC, "5:37" },
1426            { ULocale.CHINESE,  FormatWidth.NARROW,  "5\u5C0F\u65F637\u5206\u949F" },
1427            { ULocale.CHINESE,  FormatWidth.NUMERIC, "5:37" },
1428        };
1429        for (Object[] row : data) {
1430            MeasureFormat mf = null;
1431            try{
1432                mf = MeasureFormat.getInstance( (ULocale)row[0], (FormatWidth)row[1] );
1433            } catch(Exception e) {
1434                errln("Exception creating MeasureFormat for locale " + row[0] + ", width " +
1435                        row[1] + ": " + e);
1436                continue;
1437            }
1438            String result = mf.formatMeasures(hours, minutes);
1439            if (!result.equals(row[2])) {
1440                errln("MeasureFormat.formatMeasures for locale " + row[0] + ", width " +
1441                        row[1] + ", expected \"" + (String)row[2] + "\", got \"" + result + "\"" );
1442            }
1443        }
1444    }
1445
1446    @Test
1447    public void testSimplePer() {
1448        Object DONT_CARE = null;
1449        Object[][] data = new Object[][] {
1450                // per unit pattern
1451                {FormatWidth.WIDE, 1.0, MeasureUnit.SECOND, "1 pound per second", DONT_CARE, 0, 0},
1452                {FormatWidth.WIDE, 2.0, MeasureUnit.SECOND, "2 pounds per second", DONT_CARE, 0, 0},
1453                // compound pattern
1454                {FormatWidth.WIDE, 1.0, MeasureUnit.MINUTE, "1 pound per minute", DONT_CARE, 0, 0},
1455                {FormatWidth.WIDE, 2.0, MeasureUnit.MINUTE, "2 pounds per minute", DONT_CARE, 0, 0},
1456                // per unit
1457                {FormatWidth.SHORT, 1.0, MeasureUnit.SECOND, "1 lb/s", DONT_CARE, 0, 0},
1458                {FormatWidth.SHORT, 2.0, MeasureUnit.SECOND, "2 lb/s", DONT_CARE, 0, 0},
1459                // compound
1460                {FormatWidth.SHORT, 1.0, MeasureUnit.MINUTE, "1 lb/min", DONT_CARE, 0, 0},
1461                {FormatWidth.SHORT, 2.0, MeasureUnit.MINUTE, "2 lb/min", DONT_CARE, 0, 0},
1462                // per unit
1463                {FormatWidth.NARROW, 1.0, MeasureUnit.SECOND, "1#/s", DONT_CARE, 0, 0},
1464                {FormatWidth.NARROW, 2.0, MeasureUnit.SECOND, "2#/s", DONT_CARE, 0, 0},
1465                // compound
1466                {FormatWidth.NARROW, 1.0, MeasureUnit.MINUTE, "1#/min", DONT_CARE, 0, 0},
1467                {FormatWidth.NARROW, 2.0, MeasureUnit.MINUTE, "2#/min", DONT_CARE, 0, 0},
1468                // field positions
1469                {FormatWidth.SHORT, 23.3, MeasureUnit.SECOND, "23.3 lb/s", NumberFormat.Field.DECIMAL_SEPARATOR, 2, 3},
1470                {FormatWidth.SHORT, 23.3, MeasureUnit.SECOND, "23.3 lb/s", NumberFormat.Field.INTEGER, 0, 2},
1471                {FormatWidth.SHORT, 23.3, MeasureUnit.MINUTE, "23.3 lb/min", NumberFormat.Field.DECIMAL_SEPARATOR, 2, 3},
1472                {FormatWidth.SHORT, 23.3, MeasureUnit.MINUTE, "23.3 lb/min", NumberFormat.Field.INTEGER, 0, 2},
1473
1474        };
1475
1476        for (Object[] row : data) {
1477            FormatWidth formatWidth = (FormatWidth) row[0];
1478            Number amount = (Number) row[1];
1479            MeasureUnit perUnit = (MeasureUnit) row[2];
1480            String expected = row[3].toString();
1481            NumberFormat.Field field = (NumberFormat.Field) row[4];
1482            int startOffset = ((Integer) row[5]).intValue();
1483            int endOffset = ((Integer) row[6]).intValue();
1484            MeasureFormat mf = MeasureFormat.getInstance(
1485                    ULocale.ENGLISH, formatWidth);
1486            FieldPosition pos = field != null ? new FieldPosition(field) : new FieldPosition(0);
1487            String prefix = "Prefix: ";
1488            assertEquals(
1489                    "",
1490                    prefix + expected,
1491                    mf.formatMeasurePerUnit(
1492                            new Measure(amount, MeasureUnit.POUND),
1493                            perUnit,
1494                            new StringBuilder(prefix),
1495                            pos).toString());
1496            if (field != DONT_CARE) {
1497                assertEquals("startOffset", startOffset, pos.getBeginIndex() - prefix.length());
1498                assertEquals("endOffset", endOffset, pos.getEndIndex() - prefix.length());
1499            }
1500        }
1501    }
1502
1503    @Test
1504    public void testNumeratorPlurals() {
1505        ULocale polish = new ULocale("pl");
1506        Object[][] data = new Object[][] {
1507                {1, "1 stopa na sekundę"},
1508                {2, "2 stopy na sekundę"},
1509                {5, "5 stóp na sekundę"},
1510                {1.5, "1,5 stopy na sekundę"}};
1511
1512        for (Object[] row : data) {
1513            MeasureFormat mf = MeasureFormat.getInstance(polish, FormatWidth.WIDE);
1514            assertEquals(
1515                    "",
1516                    row[1],
1517                    mf.formatMeasurePerUnit(
1518                            new Measure((Number) row[0], MeasureUnit.FOOT),
1519                            MeasureUnit.SECOND,
1520                            new StringBuilder(),
1521                            new FieldPosition(0)).toString());
1522        }
1523    }
1524
1525    @Test
1526    public void testGram() {
1527        MeasureFormat mf = MeasureFormat.getInstance(ULocale.ENGLISH, FormatWidth.SHORT);
1528        assertEquals(
1529                "testGram",
1530                "1 g",
1531                mf.format(new Measure(1, MeasureUnit.GRAM)));
1532        assertEquals(
1533                "testGram",
1534                "1 G",
1535                mf.format(new Measure(1, MeasureUnit.G_FORCE)));
1536    }
1537
1538    @Test
1539    public void testCurrencies() {
1540        Measure USD_1 = new Measure(1.0, Currency.getInstance("USD"));
1541        Measure USD_2 = new Measure(2.0, Currency.getInstance("USD"));
1542        Measure USD_NEG_1 = new Measure(-1.0, Currency.getInstance("USD"));
1543        MeasureFormat mf = MeasureFormat.getInstance(ULocale.ENGLISH, FormatWidth.WIDE);
1544        assertEquals("Wide currency", "-1.00 US dollars", mf.format(USD_NEG_1));
1545        assertEquals("Wide currency", "1.00 US dollars", mf.format(USD_1));
1546        assertEquals("Wide currency", "2.00 US dollars", mf.format(USD_2));
1547        mf = MeasureFormat.getInstance(ULocale.ENGLISH, FormatWidth.SHORT);
1548        assertEquals("short currency", "-USD1.00", mf.format(USD_NEG_1));
1549        assertEquals("short currency", "USD1.00", mf.format(USD_1));
1550        assertEquals("short currency", "USD2.00", mf.format(USD_2));
1551        mf = MeasureFormat.getInstance(ULocale.ENGLISH, FormatWidth.NARROW);
1552        assertEquals("narrow currency", "-$1.00", mf.format(USD_NEG_1));
1553        assertEquals("narrow currency", "$1.00", mf.format(USD_1));
1554        assertEquals("narrow currency", "$2.00", mf.format(USD_2));
1555        mf = MeasureFormat.getInstance(ULocale.ENGLISH, FormatWidth.NUMERIC);
1556        assertEquals("numeric currency", "-$1.00", mf.format(USD_NEG_1));
1557        assertEquals("numeric currency", "$1.00", mf.format(USD_1));
1558        assertEquals("numeric currency", "$2.00", mf.format(USD_2));
1559
1560        mf = MeasureFormat.getInstance(ULocale.JAPAN, FormatWidth.WIDE);
1561        assertEquals("Wide currency", "-1.00\u7C73\u30C9\u30EB", mf.format(USD_NEG_1));
1562        assertEquals("Wide currency", "1.00\u7C73\u30C9\u30EB", mf.format(USD_1));
1563        assertEquals("Wide currency", "2.00\u7C73\u30C9\u30EB", mf.format(USD_2));
1564
1565        Measure CAD_1 = new Measure(1.0, Currency.getInstance("CAD"));
1566        mf = MeasureFormat.getInstance(ULocale.CANADA, FormatWidth.SHORT);
1567        assertEquals("short currency", "CAD1.00", mf.format(CAD_1));
1568    }
1569
1570    @Test
1571    public void testDisplayNames() {
1572        Object[][] data = new Object[][] {
1573            // Unit, locale, width, expected result
1574            { MeasureUnit.YEAR, "en", FormatWidth.WIDE, "years" },
1575            { MeasureUnit.YEAR, "ja", FormatWidth.WIDE, "年" },
1576            { MeasureUnit.YEAR, "es", FormatWidth.WIDE, "años" },
1577            { MeasureUnit.YEAR, "pt", FormatWidth.WIDE, "anos" },
1578            { MeasureUnit.YEAR, "pt-PT", FormatWidth.WIDE, "anos" },
1579            { MeasureUnit.AMPERE, "en", FormatWidth.WIDE, "amperes" },
1580            { MeasureUnit.AMPERE, "ja", FormatWidth.WIDE, "アンペア" },
1581            { MeasureUnit.AMPERE, "es", FormatWidth.WIDE, "amperios" },
1582            { MeasureUnit.AMPERE, "pt", FormatWidth.WIDE, "amperes" },
1583            { MeasureUnit.AMPERE, "pt-PT", FormatWidth.WIDE, "amperes" },
1584            { MeasureUnit.METER_PER_SECOND_SQUARED, "pt", FormatWidth.WIDE, "metros por segundo ao quadrado" },
1585            { MeasureUnit.METER_PER_SECOND_SQUARED, "pt-PT", FormatWidth.WIDE, "metros por segundo quadrado" },
1586            { MeasureUnit.SQUARE_KILOMETER, "pt", FormatWidth.NARROW, "km²" },
1587            { MeasureUnit.SQUARE_KILOMETER, "pt", FormatWidth.SHORT, "km²" },
1588            { MeasureUnit.SQUARE_KILOMETER, "pt", FormatWidth.WIDE, "quilômetros quadrados" },
1589            { MeasureUnit.SECOND, "pt-PT", FormatWidth.NARROW, "s" },
1590            { MeasureUnit.SECOND, "pt-PT", FormatWidth.SHORT, "s" },
1591            { MeasureUnit.SECOND, "pt-PT", FormatWidth.WIDE, "segundos" },
1592            { MeasureUnit.SECOND, "pt", FormatWidth.NARROW, "seg" },
1593            { MeasureUnit.SECOND, "pt", FormatWidth.SHORT, "segs" },
1594            { MeasureUnit.SECOND, "pt", FormatWidth.WIDE, "segundos" },
1595        };
1596
1597        for (Object[] test : data) {
1598            MeasureUnit unit = (MeasureUnit) test[0];
1599            ULocale locale = ULocale.forLanguageTag((String) test[1]);
1600            FormatWidth formatWidth = (FormatWidth) test[2];
1601            String expected = (String) test[3];
1602
1603            MeasureFormat mf = MeasureFormat.getInstance(locale, formatWidth);
1604            String actual = mf.getUnitDisplayName(unit);
1605            assertEquals(String.format("Unit Display Name for %s, %s, %s", unit, locale, formatWidth),
1606                    expected, actual);
1607        }
1608    }
1609
1610    @Test
1611    public void testFieldPosition() {
1612        MeasureFormat fmt = MeasureFormat.getInstance(
1613                ULocale.ENGLISH, FormatWidth.SHORT);
1614        FieldPosition pos = new FieldPosition(NumberFormat.Field.DECIMAL_SEPARATOR);
1615        fmt.format(new Measure(43.5, MeasureUnit.FOOT), new StringBuffer("123456: "), pos);
1616        assertEquals("beginIndex", 10, pos.getBeginIndex());
1617        assertEquals("endIndex", 11, pos.getEndIndex());
1618
1619        pos = new FieldPosition(NumberFormat.Field.DECIMAL_SEPARATOR);
1620        fmt.format(new Measure(43, MeasureUnit.FOOT), new StringBuffer(), pos);
1621        assertEquals("beginIndex", 0, pos.getBeginIndex());
1622        assertEquals("endIndex", 0, pos.getEndIndex());
1623    }
1624
1625    @Test
1626    public void testFieldPositionMultiple() {
1627        MeasureFormat fmt = MeasureFormat.getInstance(
1628                ULocale.ENGLISH, FormatWidth.SHORT);
1629        FieldPosition pos = new FieldPosition(NumberFormat.Field.INTEGER);
1630        String result = fmt.formatMeasures(
1631                new StringBuilder(),
1632                pos,
1633                new Measure(354, MeasureUnit.METER),
1634                new Measure(23, MeasureUnit.CENTIMETER)).toString();
1635        assertEquals("result", "354 m, 23 cm", result);
1636
1637        // According to javadocs for {@link Format#format} FieldPosition is set to
1638        // beginning and end of first such field encountered instead of the last
1639        // such field encountered.
1640        assertEquals("beginIndex", 0, pos.getBeginIndex());
1641        assertEquals("endIndex", 3, pos.getEndIndex());
1642
1643        pos = new FieldPosition(NumberFormat.Field.DECIMAL_SEPARATOR);
1644        result = fmt.formatMeasures(
1645                new StringBuilder("123456: "),
1646                pos,
1647                new Measure(354, MeasureUnit.METER),
1648                new Measure(23, MeasureUnit.CENTIMETER),
1649                new Measure(5.4, MeasureUnit.MILLIMETER)).toString();
1650        assertEquals("result", "123456: 354 m, 23 cm, 5.4 mm", result);
1651        assertEquals("beginIndex", 23, pos.getBeginIndex());
1652        assertEquals("endIndex", 24, pos.getEndIndex());
1653
1654        result = fmt.formatMeasures(
1655                new StringBuilder(),
1656                pos,
1657                new Measure(3, MeasureUnit.METER),
1658                new Measure(23, MeasureUnit.CENTIMETER),
1659                new Measure(5.4, MeasureUnit.MILLIMETER)).toString();
1660        assertEquals("result", "3 m, 23 cm, 5.4 mm", result);
1661        assertEquals("beginIndex", 13, pos.getBeginIndex());
1662        assertEquals("endIndex", 14, pos.getEndIndex());
1663
1664        pos = new FieldPosition(NumberFormat.Field.DECIMAL_SEPARATOR);
1665        result = fmt.formatMeasures(
1666                new StringBuilder("123456: "),
1667                pos,
1668                new Measure(3, MeasureUnit.METER),
1669                new Measure(23, MeasureUnit.CENTIMETER),
1670                new Measure(5, MeasureUnit.MILLIMETER)).toString();
1671        assertEquals("result", "123456: 3 m, 23 cm, 5 mm", result);
1672        assertEquals("beginIndex", 0, pos.getBeginIndex());
1673        assertEquals("endIndex", 0, pos.getEndIndex());
1674
1675        pos = new FieldPosition(NumberFormat.Field.INTEGER);
1676        result = fmt.formatMeasures(
1677                new StringBuilder("123456: "),
1678                pos,
1679                new Measure(57, MeasureUnit.MILLIMETER)).toString();
1680        assertEquals("result", "123456: 57 mm", result);
1681        assertEquals("beginIndex", 8, pos.getBeginIndex());
1682        assertEquals("endIndex", 10, pos.getEndIndex());
1683
1684    }
1685
1686    @Test
1687    public void testOldFormatWithList() {
1688        List<Measure> measures = new ArrayList<Measure>(2);
1689        measures.add(new Measure(5, MeasureUnit.ACRE));
1690        measures.add(new Measure(3000, MeasureUnit.SQUARE_FOOT));
1691        MeasureFormat fmt = MeasureFormat.getInstance(
1692                ULocale.ENGLISH, FormatWidth.WIDE);
1693        assertEquals("", "5 acres, 3,000 square feet", fmt.format(measures));
1694        assertEquals("", "5 acres", fmt.format(measures.subList(0, 1)));
1695        List<String> badList = new ArrayList<String>();
1696        badList.add("be");
1697        badList.add("you");
1698        try {
1699            fmt.format(badList);
1700            fail("Expected IllegalArgumentException.");
1701        } catch (IllegalArgumentException expected) {
1702           // Expected
1703        }
1704    }
1705
1706    @Test
1707    public void testOldFormatWithArray() {
1708        Measure[] measures = new Measure[] {
1709                new Measure(5, MeasureUnit.ACRE),
1710                new Measure(3000, MeasureUnit.SQUARE_FOOT),
1711        };
1712        MeasureFormat fmt = MeasureFormat.getInstance(
1713                ULocale.ENGLISH, FormatWidth.WIDE);
1714        assertEquals("", "5 acres, 3,000 square feet", fmt.format(measures));
1715    }
1716
1717    @Test
1718    public void testOldFormatBadArg() {
1719        MeasureFormat fmt = MeasureFormat.getInstance(
1720                ULocale.ENGLISH, FormatWidth.WIDE);
1721        try {
1722            fmt.format("be");
1723            fail("Expected IllegalArgumentExceptino.");
1724        } catch (IllegalArgumentException e) {
1725            // Expected
1726        }
1727    }
1728
1729    @Test
1730    public void testUnitPerUnitResolution() {
1731        // Ticket 11274
1732        MeasureFormat fmt = MeasureFormat.getInstance(Locale.ENGLISH, FormatWidth.SHORT);
1733
1734        // This fails unless we resolve to MeasureUnit.POUND_PER_SQUARE_INCH
1735        assertEquals("", "50 psi",
1736                fmt.formatMeasurePerUnit(
1737                        new Measure(50, MeasureUnit.POUND),
1738                        MeasureUnit.SQUARE_INCH,
1739                        new StringBuilder(),
1740                        new FieldPosition(0)).toString());
1741    }
1742
1743    @Test
1744    public void testEqHashCode() {
1745        MeasureFormat mf = MeasureFormat.getInstance(ULocale.CANADA, FormatWidth.SHORT);
1746        MeasureFormat mfeq = MeasureFormat.getInstance(ULocale.CANADA, FormatWidth.SHORT);
1747        MeasureFormat mfne = MeasureFormat.getInstance(ULocale.CANADA, FormatWidth.WIDE);
1748        MeasureFormat mfne2 = MeasureFormat.getInstance(ULocale.ENGLISH, FormatWidth.SHORT);
1749        verifyEqualsHashCode(mf, mfeq, mfne);
1750        verifyEqualsHashCode(mf, mfeq, mfne2);
1751    }
1752
1753    @Test
1754    public void testEqHashCodeOfMeasure() {
1755        Measure _3feetDouble = new Measure(3.0, MeasureUnit.FOOT);
1756        Measure _3feetInt = new Measure(3, MeasureUnit.FOOT);
1757        Measure _4feetInt = new Measure(4, MeasureUnit.FOOT);
1758        verifyEqualsHashCode(_3feetDouble, _3feetInt, _4feetInt);
1759    }
1760
1761    @Test
1762    public void testGetLocale() {
1763        MeasureFormat mf = MeasureFormat.getInstance(ULocale.GERMAN, FormatWidth.SHORT);
1764        assertEquals("", ULocale.GERMAN, mf.getLocale(ULocale.VALID_LOCALE));
1765    }
1766
1767    @Test
1768    public void TestSerial() {
1769        checkStreamingEquality(MeasureUnit.CELSIUS);
1770        checkStreamingEquality(MeasureFormat.getInstance(ULocale.FRANCE, FormatWidth.NARROW));
1771        checkStreamingEquality(Currency.getInstance("EUR"));
1772        checkStreamingEquality(MeasureFormat.getInstance(ULocale.GERMAN, FormatWidth.SHORT));
1773        checkStreamingEquality(MeasureFormat.getCurrencyFormat(ULocale.ITALIAN));
1774    }
1775
1776    @Test
1777    public void TestSerialFormatWidthEnum() {
1778        // FormatWidth enum values must map to the same ordinal values for all time in order for
1779        // serialization to work.
1780        assertEquals("FormatWidth.WIDE", 0, FormatWidth.WIDE.ordinal());
1781        assertEquals("FormatWidth.SHORT", 1, FormatWidth.SHORT.ordinal());
1782        assertEquals("FormatWidth.NARROW", 2, FormatWidth.NARROW.ordinal());
1783        assertEquals("FormatWidth.NUMERIC", 3, FormatWidth.NUMERIC.ordinal());
1784    }
1785
1786    @Test
1787    public void testCurrencyFormatStandInForMeasureFormat() {
1788        MeasureFormat mf = MeasureFormat.getCurrencyFormat(ULocale.ENGLISH);
1789        assertEquals(
1790                "70 feet, 5.3 inches",
1791                "70 feet, 5.3 inches",
1792                mf.formatMeasures(
1793                        new Measure(70, MeasureUnit.FOOT),
1794                        new Measure(5.3, MeasureUnit.INCH)));
1795        assertEquals("getLocale", ULocale.ENGLISH, mf.getLocale());
1796        assertEquals("getNumberFormat", ULocale.ENGLISH, mf.getNumberFormat().getLocale(ULocale.VALID_LOCALE));
1797        assertEquals("getWidth", MeasureFormat.FormatWidth.WIDE, mf.getWidth());
1798    }
1799
1800    @Test
1801    public void testCurrencyFormatLocale() {
1802        MeasureFormat mfu = MeasureFormat.getCurrencyFormat(ULocale.FRANCE);
1803        MeasureFormat mfj = MeasureFormat.getCurrencyFormat(Locale.FRANCE);
1804
1805        assertEquals("getCurrencyFormat ULocale/Locale", mfu, mfj);
1806    }
1807
1808    @Test
1809    public void testDoubleZero() {
1810        ULocale en = new ULocale("en");
1811        NumberFormat nf = NumberFormat.getInstance(en);
1812        nf.setMinimumFractionDigits(2);
1813        nf.setMaximumFractionDigits(2);
1814        MeasureFormat mf = MeasureFormat.getInstance(en, FormatWidth.WIDE, nf);
1815        assertEquals(
1816                "Positive Rounding",
1817                "4 hours, 23 minutes, 16.00 seconds",
1818                mf.formatMeasures(
1819                        new Measure(4.7, MeasureUnit.HOUR),
1820                        new Measure(23, MeasureUnit.MINUTE),
1821                        new Measure(16, MeasureUnit.SECOND)));
1822        assertEquals(
1823                "Negative Rounding",
1824                "-4 hours, 23 minutes, 16.00 seconds",
1825                mf.formatMeasures(
1826                        new Measure(-4.7, MeasureUnit.HOUR),
1827                        new Measure(23, MeasureUnit.MINUTE),
1828                        new Measure(16, MeasureUnit.SECOND)));
1829
1830    }
1831
1832    @Test
1833    public void testIndividualPluralFallback() {
1834        // See ticket #11986 "incomplete fallback in MeasureFormat".
1835        // In CLDR 28, fr_CA temperature-generic/short has only the "one" form,
1836        // and falls back to fr for the "other" form.
1837        MeasureFormat mf = MeasureFormat.getInstance(new ULocale("fr_CA"), FormatWidth.SHORT);
1838        Measure twoDeg = new Measure(2, MeasureUnit.GENERIC_TEMPERATURE);
1839        assertEquals("2 deg temp in fr_CA", "2°", mf.format(twoDeg));
1840    }
1841
1842    @Test
1843    public void testPopulateCache() {
1844        // Quick check that the lazily added additions to the MeasureUnit cache are present.
1845        assertTrue("MeasureUnit: unexpectedly few currencies defined", MeasureUnit.getAvailable("currency").size() > 50);
1846    }
1847
1848    @Test
1849    public void testParseObject() {
1850        MeasureFormat mf = MeasureFormat.getInstance(Locale.GERMAN, FormatWidth.NARROW);
1851        try {
1852            mf.parseObject("3m", null);
1853            fail("MeasureFormat.parseObject(String, ParsePosition) " +
1854                    "should throw an UnsupportedOperationException");
1855        } catch (UnsupportedOperationException expected) {
1856        }
1857    }
1858
1859    @Test
1860    public void testCLDRUnitAvailability() {
1861        Set<MeasureUnit> knownUnits = new HashSet<MeasureUnit>();
1862        Class cMeasureUnit, cTimeUnit;
1863        try {
1864            cMeasureUnit = Class.forName("android.icu.util.MeasureUnit");
1865            cTimeUnit = Class.forName("android.icu.util.TimeUnit");
1866        } catch (ClassNotFoundException e) {
1867            fail("Count not load MeasureUnit or TimeUnit class: " + e.getMessage());
1868            return;
1869        }
1870        for (Field field : cMeasureUnit.getFields()) {
1871            if (field.getGenericType() == cMeasureUnit || field.getGenericType() == cTimeUnit) {
1872                try {
1873                    MeasureUnit unit = (MeasureUnit) field.get(cMeasureUnit);
1874                    knownUnits.add(unit);
1875                } catch (IllegalArgumentException e) {
1876                    fail(e.getMessage());
1877                    return;
1878                } catch (IllegalAccessException e) {
1879                    fail(e.getMessage());
1880                    return;
1881                }
1882            }
1883        }
1884        for (String type : MeasureUnit.getAvailableTypes()) {
1885            if (type.equals("currency") || type.equals("compound")) {
1886                continue;
1887            }
1888            for (MeasureUnit unit : MeasureUnit.getAvailable(type)) {
1889                if (!knownUnits.contains(unit)) {
1890                    fail("Unit present in CLDR but not available via constant in MeasureUnit: " + unit);
1891                }
1892            }
1893        }
1894    }
1895
1896    // DO NOT DELETE THIS FUNCTION! It may appear as dead code, but we use this to generate code
1897    // for MeasureFormat during the release process.
1898    static Map<MeasureUnit, Pair<MeasureUnit, MeasureUnit>> getUnitsToPerParts() {
1899        TreeMap<String, List<MeasureUnit>> allUnits = getAllUnits();
1900        Map<MeasureUnit, Pair<String, String>> unitsToPerStrings =
1901                new HashMap<MeasureUnit, Pair<String, String>>();
1902        Map<String, MeasureUnit> namesToUnits = new HashMap<String, MeasureUnit>();
1903        for (Map.Entry<String, List<MeasureUnit>> entry : allUnits.entrySet()) {
1904            String type = entry.getKey();
1905            // Currency types are always atomic units, so we can skip these
1906            if (type.equals("currency")) {
1907                continue;
1908            }
1909            for (MeasureUnit unit : entry.getValue()) {
1910                String javaName = toJAVAName(unit);
1911                String[] nameParts = javaName.split("_PER_");
1912                if (nameParts.length == 1) {
1913                    namesToUnits.put(nameParts[0], unit);
1914                } else if (nameParts.length == 2) {
1915                    unitsToPerStrings.put(unit, Pair.of(nameParts[0], nameParts[1]));
1916                }
1917            }
1918        }
1919        Map<MeasureUnit, Pair<MeasureUnit, MeasureUnit>> unitsToPerUnits =
1920                new HashMap<MeasureUnit, Pair<MeasureUnit, MeasureUnit>>();
1921        for (Map.Entry<MeasureUnit, Pair<String, String>> entry : unitsToPerStrings.entrySet()) {
1922            Pair<String, String> perStrings = entry.getValue();
1923            MeasureUnit unit = namesToUnits.get(perStrings.first);
1924            MeasureUnit perUnit = namesToUnits.get(perStrings.second);
1925            if (unit != null && perUnit != null) {
1926                unitsToPerUnits.put(entry.getKey(), Pair.of(unit, perUnit));
1927            }
1928        }
1929        return unitsToPerUnits;
1930    }
1931
1932    // DO NOT DELETE THIS FUNCTION! It may appear as dead code, but we use this to generate code
1933    // for MeasureFormat during the release process.
1934    static void generateCXXHConstants(String thisVersion) {
1935        Map<String, MeasureUnit> seen = new HashMap<String, MeasureUnit>();
1936        System.out.println();
1937        TreeMap<String, List<MeasureUnit>> allUnits = getAllUnits();
1938        for (Map.Entry<String, List<MeasureUnit>> entry : allUnits.entrySet()) {
1939            String type = entry.getKey();
1940            if (type.equals("currency")) {
1941                continue;
1942            }
1943            for (MeasureUnit unit : entry.getValue()) {
1944                String code = unit.getSubtype();
1945                String name = toCamelCase(unit);
1946                String javaName = toJAVAName(unit);
1947                checkForDup(seen, name, unit);
1948                if (isDraft(javaName)) {
1949                    System.out.println("#ifndef U_HIDE_DRAFT_API");
1950                }
1951                System.out.println("    /**");
1952                System.out.println("     * Returns unit of " + type + ": " + code + ".");
1953                System.out.println("     * Caller owns returned value and must free it.");
1954                System.out.println("     * @param status ICU error code.");
1955                if (isDraft(javaName)) {
1956                    System.out.println("     * @draft ICU " + getVersion(javaName, thisVersion));
1957                } else {
1958                    System.out.println("     * @stable ICU " + getVersion(javaName, thisVersion));
1959                }
1960                System.out.println("     */");
1961                System.out.printf("    static MeasureUnit *create%s(UErrorCode &status);\n\n", name);
1962                if (isDraft(javaName)) {
1963                    System.out.println("#endif /* U_HIDE_DRAFT_API */");
1964                }
1965            }
1966        }
1967    }
1968
1969    private static void checkForDup(
1970            Map<String, MeasureUnit> seen, String name, MeasureUnit unit) {
1971        if (seen.containsKey(name)) {
1972            throw new RuntimeException("\nCollision!!" + unit + ", " + seen.get(name));
1973        } else {
1974            seen.put(name, unit);
1975        }
1976    }
1977
1978    // DO NOT DELETE THIS FUNCTION! It may appear as dead code, but we use this to generate code
1979    // for MeasureFormat during the release process.
1980    static void updateJAVAVersions(String thisVersion) {
1981        System.out.println();
1982        Map<String, MeasureUnit> seen = new HashMap<String, MeasureUnit>();
1983        TreeMap<String, List<MeasureUnit>> allUnits = getAllUnits();
1984        for (Map.Entry<String, List<MeasureUnit>> entry : allUnits.entrySet()) {
1985            String type = entry.getKey();
1986            if (type.equals("currency")) {
1987                continue;
1988            }
1989            for (MeasureUnit unit : entry.getValue()) {
1990                String javaName = toJAVAName(unit);
1991                checkForDup(seen, javaName, unit);
1992                if (!JAVA_VERSION_MAP.containsKey(javaName)) {
1993                    System.out.printf("        {\"%s\", \"%s\"},\n", javaName, thisVersion);
1994                }
1995            }
1996        }
1997    }
1998
1999    static TreeMap<String, List<MeasureUnit>> getAllUnits() {
2000        TreeMap<String, List<MeasureUnit>> allUnits = new TreeMap<String, List<MeasureUnit>>();
2001        for (String type : MeasureUnit.getAvailableTypes()) {
2002            ArrayList<MeasureUnit> units = new ArrayList<MeasureUnit>(MeasureUnit.getAvailable(type));
2003            Collections.sort(
2004                    units,
2005                    new Comparator<MeasureUnit>() {
2006
2007                        @Override
2008                        public int compare(MeasureUnit o1, MeasureUnit o2) {
2009                            return o1.getSubtype().compareTo(o2.getSubtype());
2010                        }
2011
2012                    });
2013            allUnits.put(type, units);
2014        }
2015        return allUnits;
2016    }
2017
2018    // DO NOT DELETE THIS FUNCTION! It may appear as dead code, but we use this to generate code
2019    // for MeasureFormat during the release process.
2020    static void generateCXXConstants() {
2021        System.out.println("");
2022        TreeMap<String, List<MeasureUnit>> allUnits = getAllUnits();
2023
2024        System.out.println("static const int32_t gOffsets[] = {");
2025        int index = 0;
2026        for (Map.Entry<String, List<MeasureUnit>> entry : allUnits.entrySet()) {
2027            System.out.printf("    %d,\n", index);
2028            index += entry.getValue().size();
2029        }
2030        System.out.printf("    %d\n", index);
2031        System.out.println("};");
2032        System.out.println();
2033        System.out.println("static const int32_t gIndexes[] = {");
2034        index = 0;
2035        for (Map.Entry<String, List<MeasureUnit>> entry : allUnits.entrySet()) {
2036            System.out.printf("    %d,\n", index);
2037            if (!entry.getKey().equals("currency")) {
2038                index += entry.getValue().size();
2039            }
2040        }
2041        System.out.printf("    %d\n", index);
2042        System.out.println("};");
2043        System.out.println();
2044        System.out.println("// Must be sorted alphabetically.");
2045        System.out.println("static const char * const gTypes[] = {");
2046        boolean first = true;
2047        for (Map.Entry<String, List<MeasureUnit>> entry : allUnits.entrySet()) {
2048            if (!first) {
2049                System.out.println(",");
2050            }
2051            System.out.print("    \"" + entry.getKey() + "\"");
2052            first = false;
2053        }
2054        System.out.println();
2055        System.out.println("};");
2056        System.out.println();
2057        System.out.println("// Must be grouped by type and sorted alphabetically within each type.");
2058        System.out.println("static const char * const gSubTypes[] = {");
2059        first = true;
2060        int offset = 0;
2061        int typeIdx = 0;
2062        Map<MeasureUnit, Integer> measureUnitToOffset = new HashMap<MeasureUnit, Integer>();
2063        Map<MeasureUnit, Pair<Integer, Integer>> measureUnitToTypeSubType =
2064                new HashMap<MeasureUnit, Pair<Integer, Integer>>();
2065        for (Map.Entry<String, List<MeasureUnit>> entry : allUnits.entrySet()) {
2066            int subTypeIdx = 0;
2067            for (MeasureUnit unit : entry.getValue()) {
2068                if (!first) {
2069                    System.out.println(",");
2070                }
2071                System.out.print("    \"" + unit.getSubtype() + "\"");
2072                first = false;
2073                measureUnitToOffset.put(unit, offset);
2074                measureUnitToTypeSubType.put(unit, Pair.of(typeIdx, subTypeIdx));
2075                offset++;
2076                subTypeIdx++;
2077            }
2078            typeIdx++;
2079        }
2080        System.out.println();
2081        System.out.println("};");
2082        System.out.println();
2083
2084        // Build unit per unit offsets to corresponding type sub types sorted by
2085        // unit first and then per unit.
2086        TreeMap<OrderedPair<Integer, Integer>, Pair<Integer, Integer>> unitPerUnitOffsetsToTypeSubType
2087                = new TreeMap<OrderedPair<Integer, Integer>, Pair<Integer, Integer>>();
2088        for (Map.Entry<MeasureUnit, Pair<MeasureUnit, MeasureUnit>> entry
2089                : getUnitsToPerParts().entrySet()) {
2090            Pair<MeasureUnit, MeasureUnit> unitPerUnit = entry.getValue();
2091            unitPerUnitOffsetsToTypeSubType.put(
2092                    OrderedPair.of(
2093                            measureUnitToOffset.get(unitPerUnit.first),
2094                            measureUnitToOffset.get(unitPerUnit.second)),
2095                    measureUnitToTypeSubType.get(entry.getKey()));
2096        }
2097
2098        System.out.println("// Must be sorted by first value and then second value.");
2099        System.out.println("static int32_t unitPerUnitToSingleUnit[][4] = {");
2100        first = true;
2101        for (Map.Entry<OrderedPair<Integer, Integer>, Pair<Integer, Integer>> entry
2102                : unitPerUnitOffsetsToTypeSubType.entrySet()) {
2103            if (!first) {
2104                System.out.println(",");
2105            }
2106            first = false;
2107            OrderedPair<Integer, Integer> unitPerUnitOffsets = entry.getKey();
2108            Pair<Integer, Integer> typeSubType = entry.getValue();
2109            System.out.printf("        {%d, %d, %d, %d}",
2110                    unitPerUnitOffsets.first,
2111                    unitPerUnitOffsets.second,
2112                    typeSubType.first,
2113                    typeSubType.second);
2114        }
2115        System.out.println();
2116        System.out.println("};");
2117        System.out.println();
2118
2119        Map<String, MeasureUnit> seen = new HashMap<String, MeasureUnit>();
2120        for (Map.Entry<String, List<MeasureUnit>> entry : allUnits.entrySet()) {
2121
2122            String type = entry.getKey();
2123            if (type.equals("currency")) {
2124                continue;
2125            }
2126            for (MeasureUnit unit : entry.getValue()) {
2127                String name = toCamelCase(unit);
2128                Pair<Integer, Integer> typeSubType = measureUnitToTypeSubType.get(unit);
2129                if (typeSubType == null) {
2130                    throw new IllegalStateException();
2131                }
2132                checkForDup(seen, name, unit);
2133                System.out.printf("MeasureUnit *MeasureUnit::create%s(UErrorCode &status) {\n", name);
2134                System.out.printf("    return MeasureUnit::create(%d, %d, status);\n",
2135                        typeSubType.first, typeSubType.second);
2136                System.out.println("}");
2137                System.out.println();
2138            }
2139        }
2140    }
2141
2142    private static String toCamelCase(MeasureUnit unit) {
2143        StringBuilder result = new StringBuilder();
2144        boolean caps = true;
2145        String code = unit.getSubtype();
2146        int len = code.length();
2147        for (int i = 0; i < len; i++) {
2148            char ch = code.charAt(i);
2149            if (ch == '-') {
2150                caps = true;
2151            } else if (caps) {
2152                result.append(Character.toUpperCase(ch));
2153                caps = false;
2154            } else {
2155                result.append(ch);
2156            }
2157        }
2158        return result.toString();
2159    }
2160
2161    static boolean isTypeHidden(String type) {
2162        return "currency".equals(type);
2163    }
2164
2165    // DO NOT DELETE THIS FUNCTION! It may appear as dead code, but we use this to generate code
2166    // for MeasureFormat during the release process.
2167    static void generateBackwardCompatibilityTest(String version) {
2168        Map<String, MeasureUnit> seen = new HashMap<String, MeasureUnit>();
2169        System.out.println();
2170        System.out.printf("    public void TestCompatible%s() {\n", version.replace(".", "_"));
2171        System.out.println("        MeasureUnit[] units = {");
2172        TreeMap<String, List<MeasureUnit>> allUnits = getAllUnits();
2173        int count = 0;
2174        for (Map.Entry<String, List<MeasureUnit>> entry : allUnits.entrySet()) {
2175            if (isTypeHidden(entry.getKey())) {
2176                continue;
2177            }
2178            for (MeasureUnit unit : entry.getValue()) {
2179                String javaName = toJAVAName(unit);
2180                checkForDup(seen, javaName, unit);
2181                System.out.printf("                MeasureUnit.%s,\n", javaName);
2182                count++;
2183            }
2184        }
2185        System.out.println("        };");
2186        System.out.printf("        assertEquals(\"\",  %d, units.length);\n", count);
2187        System.out.println("    }");
2188    }
2189
2190    // DO NOT DELETE THIS FUNCTION! It may appear as dead code, but we use this to generate code
2191    // for MeasureFormat during the release process.
2192    static void generateCXXBackwardCompatibilityTest(String version) {
2193        System.out.println();
2194        Map<String, MeasureUnit> seen = new HashMap<String, MeasureUnit>();
2195        System.out.printf("void MeasureFormatTest::TestCompatible%s() {\n", version.replace(".", "_"));
2196        System.out.println("    UErrorCode status = U_ZERO_ERROR;");
2197        System.out.println("    LocalPointer<MeasureUnit> measureUnit;");
2198        TreeMap<String, List<MeasureUnit>> allUnits = getAllUnits();
2199        for (Map.Entry<String, List<MeasureUnit>> entry : allUnits.entrySet()) {
2200            if (isTypeHidden(entry.getKey())) {
2201                continue;
2202            }
2203            for (MeasureUnit unit : entry.getValue()) {
2204                String camelCase = toCamelCase(unit);
2205                checkForDup(seen, camelCase, unit);
2206                System.out.printf("    measureUnit.adoptInstead(MeasureUnit::create%s(status));\n", camelCase);
2207            }
2208        }
2209        System.out.println("    assertSuccess(\"\", status);");
2210        System.out.println("}");
2211    }
2212
2213    static String toJAVAName(MeasureUnit unit) {
2214        String code = unit.getSubtype();
2215        String type = unit.getType();
2216        String name = code.toUpperCase(Locale.ENGLISH).replace("-", "_");
2217        if (type.equals("angle")) {
2218            if (code.equals("minute") || code.equals("second")) {
2219                name = "ARC_" + name;
2220            }
2221        }
2222        return name;
2223    }
2224
2225    // DO NOT DELETE THIS FUNCTION! It may appear as dead code, but we use this to generate code
2226    // for MeasureFormat during the release process.
2227    static void generateConstants(String thisVersion) {
2228        System.out.println();
2229        Map<String, MeasureUnit> seen = new HashMap<String, MeasureUnit>();
2230        TreeMap<String, List<MeasureUnit>> allUnits = getAllUnits();
2231        for (Map.Entry<String, List<MeasureUnit>> entry : allUnits.entrySet()) {
2232            String type = entry.getKey();
2233            if (isTypeHidden(type)) {
2234                continue;
2235            }
2236            for (MeasureUnit unit : entry.getValue()) {
2237                String name = toJAVAName(unit);
2238                String code = unit.getSubtype();
2239                checkForDup(seen, name, unit);
2240                System.out.println("    /**");
2241                System.out.println("     * Constant for unit of " + type +
2242                        ": " +
2243                        code);
2244                // Special case JAVA had old constants for time from before.
2245                if ("duration".equals(type) && TIME_CODES.contains(code)) {
2246                    System.out.println("     * @stable ICU 4.0");
2247                }
2248                else if (isDraft(name)) {
2249                    System.out.println("     * @draft ICU " + getVersion(name, thisVersion));
2250                    System.out.println("     * @provisional This API might change or be removed in a future release.");
2251                } else {
2252                    System.out.println("     * @stable ICU " + getVersion(name, thisVersion));
2253                }
2254                System.out.println("    */");
2255                if ("duration".equals(type) && TIME_CODES.contains(code)) {
2256                    System.out.println("    public static final TimeUnit " + name + " = (TimeUnit) MeasureUnit.internalGetInstance(\"" +
2257                            type +
2258                            "\", \"" +
2259                            code +
2260                            "\");");
2261                } else {
2262                    System.out.println("    public static final MeasureUnit " + name + " = MeasureUnit.internalGetInstance(\"" +
2263                            type +
2264                            "\", \"" +
2265                            code +
2266                            "\");");
2267                }
2268                System.out.println();
2269            }
2270        }
2271        System.out.println("    private static HashMap<Pair<MeasureUnit, MeasureUnit>, MeasureUnit>unitPerUnitToSingleUnit =");
2272        System.out.println("            new HashMap<Pair<MeasureUnit, MeasureUnit>, MeasureUnit>();");
2273        System.out.println();
2274        System.out.println("    static {");
2275        for (Map.Entry<MeasureUnit, Pair<MeasureUnit, MeasureUnit>> unitPerUnitEntry
2276                : getUnitsToPerParts().entrySet()) {
2277            Pair<MeasureUnit, MeasureUnit> unitPerUnit = unitPerUnitEntry.getValue();
2278            System.out.println("        unitPerUnitToSingleUnit.put(Pair.<MeasureUnit, MeasureUnit>of(MeasureUnit." + toJAVAName(unitPerUnit.first) + ", MeasureUnit." + toJAVAName(unitPerUnit.second) + "), MeasureUnit." + toJAVAName(unitPerUnitEntry.getKey()) + ");");
2279        }
2280        System.out.println("    }");
2281    }
2282
2283    private static String getVersion(String javaName, String thisVersion) {
2284        String version = JAVA_VERSION_MAP.get(javaName);
2285        if (version == null) {
2286            return thisVersion;
2287        }
2288        return version;
2289    }
2290
2291    private static boolean isDraft(String javaName) {
2292        String version = JAVA_VERSION_MAP.get(javaName);
2293        if (version == null) {
2294            return true;
2295        }
2296        return DRAFT_VERSION_SET.contains(version);
2297    }
2298
2299    public <T extends Serializable> void checkStreamingEquality(T item) {
2300        try {
2301          ByteArrayOutputStream byteOut = new ByteArrayOutputStream();
2302          ObjectOutputStream objectOutputStream = new ObjectOutputStream(byteOut);
2303          objectOutputStream.writeObject(item);
2304          objectOutputStream.close();
2305          byte[] contents = byteOut.toByteArray();
2306          logln("bytes: " + contents.length + "; " + item.getClass() + ": " + showBytes(contents));
2307          ByteArrayInputStream byteIn = new ByteArrayInputStream(contents);
2308          ObjectInputStream objectInputStream = new ObjectInputStream(byteIn);
2309          Object obj = objectInputStream.readObject();
2310          assertEquals("Streamed Object equals ", item, obj);
2311        } catch (IOException e) {
2312          e.printStackTrace();
2313          assertNull("Test Serialization " + item.getClass(), e);
2314        } catch (ClassNotFoundException e) {
2315          assertNull("Test Serialization " + item.getClass(), e);
2316        }
2317      }
2318
2319    /**
2320     * @param contents
2321     * @return
2322     */
2323    private String showBytes(byte[] contents) {
2324      StringBuilder b = new StringBuilder('[');
2325      for (int i = 0; i < contents.length; ++i) {
2326        int item = contents[i] & 0xFF;
2327        if (item >= 0x20 && item <= 0x7F) {
2328          b.append((char) item);
2329        } else {
2330          b.append('(').append(Utility.hex(item, 2)).append(')');
2331        }
2332      }
2333      return b.append(']').toString();
2334    }
2335
2336    private void verifyEqualsHashCode(Object o, Object eq, Object ne) {
2337        assertEquals("verifyEqualsHashCodeSame", o, o);
2338        assertEquals("verifyEqualsHashCodeEq", o, eq);
2339        assertNotEquals("verifyEqualsHashCodeNe", o, ne);
2340        assertNotEquals("verifyEqualsHashCodeEqTrans", eq, ne);
2341        assertEquals("verifyEqualsHashCodeHashEq", o.hashCode(), eq.hashCode());
2342
2343        // May be a flaky test, but generally should be true.
2344        // May need to comment this out later.
2345        assertNotEquals("verifyEqualsHashCodeHashNe", o.hashCode(), ne.hashCode());
2346    }
2347
2348    public static class MeasureUnitHandler implements SerializableTestUtility.Handler
2349    {
2350        @Override
2351        public Object[] getTestObjects()
2352        {
2353            MeasureUnit items[] = {
2354                    MeasureUnit.CELSIUS,
2355                    Currency.getInstance("EUR")
2356            };
2357            return items;
2358        }
2359        @Override
2360        public boolean hasSameBehavior(Object a, Object b)
2361        {
2362            MeasureUnit a1 = (MeasureUnit) a;
2363            MeasureUnit b1 = (MeasureUnit) b;
2364            return a1.getType().equals(b1.getType())
2365                    && a1.getSubtype().equals(b1.getSubtype());
2366        }
2367    }
2368
2369    public static class MeasureFormatHandler  implements SerializableTestUtility.Handler
2370    {
2371        @Override
2372        public Object[] getTestObjects()
2373        {
2374            MeasureFormat items[] = {
2375                    MeasureFormat.getInstance(ULocale.FRANCE, FormatWidth.SHORT),
2376                    MeasureFormat.getInstance(
2377                            ULocale.FRANCE,
2378                            FormatWidth.WIDE,
2379                            NumberFormat.getIntegerInstance(ULocale.CANADA_FRENCH)),
2380            };
2381            return items;
2382        }
2383        @Override
2384        public boolean hasSameBehavior(Object a, Object b)
2385        {
2386            MeasureFormat a1 = (MeasureFormat) a;
2387            MeasureFormat b1 = (MeasureFormat) b;
2388            return a1.getLocale().equals(b1.getLocale())
2389                    && a1.getWidth().equals(b1.getWidth())
2390                    && a1.getNumberFormat().equals(b1.getNumberFormat())
2391                    ;
2392        }
2393    }
2394}
2395