1aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin/* GENERATED SOURCE. DO NOT MODIFY. */ 2f86f25d102340da66b9c7cb6b2d5ecdc0de43ecfFredrik Roubert// © 2016 and later: Unicode, Inc. and others. 3f86f25d102340da66b9c7cb6b2d5ecdc0de43ecfFredrik Roubert// License & terms of use: http://www.unicode.org/copyright.html#License 4aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin/* 5aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin ******************************************************************************* 6aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin * Copyright (C) 2007-2015, International Business Machines Corporation and 7aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin * others. All Rights Reserved. 8aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin ******************************************************************************* 9aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin */ 10aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffinpackage android.icu.dev.test.format; 11aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin 12aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffinimport java.io.ByteArrayInputStream; 13aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffinimport java.io.ByteArrayOutputStream; 14aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffinimport java.io.IOException; 15aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffinimport java.io.ObjectInputStream; 16aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffinimport java.io.ObjectOutputStream; 17aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffinimport java.io.Serializable; 18aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffinimport java.text.ParseException; 19aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffinimport java.util.ArrayList; 20aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffinimport java.util.Arrays; 21aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffinimport java.util.Collection; 22aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffinimport java.util.Collections; 23aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffinimport java.util.Comparator; 24aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffinimport java.util.EnumSet; 25aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffinimport java.util.HashMap; 26aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffinimport java.util.HashSet; 27aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffinimport java.util.LinkedHashSet; 28aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffinimport java.util.List; 29aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffinimport java.util.Locale; 30aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffinimport java.util.Map; 31aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffinimport java.util.Map.Entry; 32aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffinimport java.util.Set; 33aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffinimport java.util.TreeMap; 34aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffinimport java.util.TreeSet; 35aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin 36f86f25d102340da66b9c7cb6b2d5ecdc0de43ecfFredrik Roubertimport org.junit.Test; 37f86f25d102340da66b9c7cb6b2d5ecdc0de43ecfFredrik Roubert 38aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffinimport android.icu.dev.test.TestFmwk; 39f86f25d102340da66b9c7cb6b2d5ecdc0de43ecfFredrik Roubertimport android.icu.dev.test.serializable.SerializableTestUtility; 40aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffinimport android.icu.dev.util.CollectionUtilities; 41aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffinimport android.icu.impl.Relation; 42aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffinimport android.icu.impl.Utility; 43aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffinimport android.icu.text.NumberFormat; 44aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffinimport android.icu.text.PluralRules; 45aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffinimport android.icu.text.PluralRules.FixedDecimal; 46aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffinimport android.icu.text.PluralRules.FixedDecimalRange; 47aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffinimport android.icu.text.PluralRules.FixedDecimalSamples; 48aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffinimport android.icu.text.PluralRules.KeywordStatus; 49aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffinimport android.icu.text.PluralRules.PluralType; 50aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffinimport android.icu.text.PluralRules.SampleType; 51aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffinimport android.icu.text.UFieldPosition; 52aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffinimport android.icu.util.Output; 53aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffinimport android.icu.util.ULocale; 54aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin 55aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin/** 56aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin * @author dougfelt (Doug Felt) 57aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin * @author markdavis (Mark Davis) [for fractional support] 58aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin */ 59aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffinpublic class PluralRulesTest extends TestFmwk { 60aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin 61aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin PluralRulesFactory factory = PluralRulesFactory.NORMAL; 62aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin 63f86f25d102340da66b9c7cb6b2d5ecdc0de43ecfFredrik Roubert @Test 64aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin public void testOverUnderflow() { 65aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin logln(String.valueOf(Long.MAX_VALUE + 1d)); 66aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin for (double[] testDouble : new double[][] { 67aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin { 1E18, 0, 0, 1E18 }, // check overflow 68aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin { 10000000000000.1d, 1, 1, 10000000000000d }, { -0.00001d, 1, 5, 0 }, { 1d, 0, 0, 1 }, 69aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin { 1.1d, 1, 1, 1 }, { 12345d, 0, 0, 12345 }, { 12345.678912d, 678912, 6, 12345 }, 70aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin { 12345.6789123d, 678912, 6, 12345 }, // we only go out 6 digits 71aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin { 1E18, 0, 0, 1E18 }, // check overflow 72aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin { 1E19, 0, 0, 1E18 }, // check overflow 73aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin }) { 74aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin FixedDecimal fd = new FixedDecimal(testDouble[0]); 75aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin assertEquals(testDouble[0] + "=doubleValue()", testDouble[0], fd.doubleValue()); 76aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin assertEquals(testDouble[0] + " decimalDigits", (int) testDouble[1], fd.decimalDigits); 77aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin assertEquals(testDouble[0] + " visibleDecimalDigitCount", (int) testDouble[2], fd.visibleDecimalDigitCount); 78aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin assertEquals(testDouble[0] + " decimalDigitsWithoutTrailingZeros", (int) testDouble[1], 79aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin fd.decimalDigitsWithoutTrailingZeros); 80aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin assertEquals(testDouble[0] + " visibleDecimalDigitCountWithoutTrailingZeros", (int) testDouble[2], 81aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin fd.visibleDecimalDigitCountWithoutTrailingZeros); 82aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin assertEquals(testDouble[0] + " integerValue", (long) testDouble[3], fd.integerValue); 83aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin } 84aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin 85aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin for (ULocale locale : new ULocale[] { ULocale.ENGLISH, new ULocale("cy"), new ULocale("ar") }) { 86aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin PluralRules rules = factory.forLocale(locale); 87aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin 88aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin assertEquals(locale + " NaN", "other", rules.select(Double.NaN)); 89aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin assertEquals(locale + " ∞", "other", rules.select(Double.POSITIVE_INFINITY)); 90aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin assertEquals(locale + " -∞", "other", rules.select(Double.NEGATIVE_INFINITY)); 91aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin } 92aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin } 93aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin 94f86f25d102340da66b9c7cb6b2d5ecdc0de43ecfFredrik Roubert @Test 95aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin public void testSyntaxRestrictions() { 96aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin Object[][] shouldFail = { 97aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin { "a:n in 3..10,13..19" }, 98aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin 99aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin // = and != always work 100aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin { "a:n=1" }, 101aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin { "a:n=1,3" }, 102aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin { "a:n!=1" }, 103aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin { "a:n!=1,3" }, 104aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin 105aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin // with spacing 106aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin { "a: n = 1" }, 107aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin { "a: n = 1, 3" }, 108aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin { "a: n != 1" }, 109aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin { "a: n != 1, 3" }, 110aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin { "a: n ! = 1" }, 111aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin { "a: n ! = 1, 3" }, 112aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin { "a: n = 1 , 3" }, 113aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin { "a: n != 1 , 3" }, 114aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin { "a: n ! = 1 , 3" }, 115aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin { "a: n = 1 .. 3" }, 116aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin { "a: n != 1 .. 3" }, 117aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin { "a: n ! = 1 .. 3" }, 118aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin 119aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin // more complicated 120aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin { "a:n in 3 .. 10 , 13 .. 19" }, 121aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin 122aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin // singles have special exceptions 123aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin { "a: n is 1" }, 124aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin { "a: n is not 1" }, 125aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin { "a: n not is 1", ParseException.class }, // hacked to fail 126aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin { "a: n in 1" }, 127aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin { "a: n not in 1" }, 128aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin 129aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin // multiples also have special exceptions 130aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin // TODO enable the following once there is an update to CLDR 131aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin // {"a: n is 1,3", ParseException.class}, 132aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin { "a: n is not 1,3", ParseException.class }, // hacked to fail 133aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin { "a: n not is 1,3", ParseException.class }, // hacked to fail 134aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin { "a: n in 1,3" }, 135aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin { "a: n not in 1,3" }, 136aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin 137aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin // disallow not with = 138aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin { "a: n not= 1", ParseException.class }, // hacked to fail 139aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin { "a: n not= 1,3", ParseException.class }, // hacked to fail 140aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin 141aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin // disallow double negatives 142aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin { "a: n ! is not 1", ParseException.class }, 143aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin { "a: n ! is not 1", ParseException.class }, 144aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin { "a: n not not in 1", ParseException.class }, 145aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin { "a: n is not not 1", NumberFormatException.class }, 146aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin 147aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin // disallow screwy cases 148aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin { null, NullPointerException.class }, { "djkl;", ParseException.class }, 149aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin { "a: n = 1 .", ParseException.class }, { "a: n = 1 ..", ParseException.class }, 150aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin { "a: n = 1 2", ParseException.class }, { "a: n = 1 ,", ParseException.class }, 151aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin { "a:n in 3 .. 10 , 13 .. 19 ,", ParseException.class }, }; 152aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin for (Object[] shouldFailTest : shouldFail) { 153aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin String rules = (String) shouldFailTest[0]; 154aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin Class exception = shouldFailTest.length < 2 ? null : (Class) shouldFailTest[1]; 155aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin Class actualException = null; 156aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin try { 157aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin PluralRules.parseDescription(rules); 158aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin } catch (Exception e) { 159aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin actualException = e.getClass(); 160aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin } 161aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin assertEquals("Exception " + rules, exception, actualException); 162aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin } 163aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin } 164aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin 165f86f25d102340da66b9c7cb6b2d5ecdc0de43ecfFredrik Roubert @Test 166aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin public void testSamples() { 167aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin String description = "one: n is 3 or f is 5 @integer 3,19, @decimal 3.50 ~ 3.53, …; other: @decimal 99.0~99.2, 999.0, …"; 168aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin PluralRules test = PluralRules.createRules(description); 169aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin 170aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin checkNewSamples(description, test, "one", PluralRules.SampleType.INTEGER, "@integer 3, 19", true, 171aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin new FixedDecimal(3)); 172aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin checkNewSamples(description, test, "one", PluralRules.SampleType.DECIMAL, "@decimal 3.50~3.53, …", false, 173aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin new FixedDecimal(3.5, 2)); 174aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin checkOldSamples(description, test, "one", SampleType.INTEGER, 3d, 19d); 175aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin checkOldSamples(description, test, "one", SampleType.DECIMAL, 3.5d, 3.51d, 3.52d, 3.53d); 176aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin 177aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin checkNewSamples(description, test, "other", PluralRules.SampleType.INTEGER, "", true, null); 178aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin checkNewSamples(description, test, "other", PluralRules.SampleType.DECIMAL, "@decimal 99.0~99.2, 999.0, …", 179aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin false, new FixedDecimal(99d, 1)); 180aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin checkOldSamples(description, test, "other", SampleType.INTEGER); 181aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin checkOldSamples(description, test, "other", SampleType.DECIMAL, 99d, 99.1, 99.2d, 999d); 182aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin } 183aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin 184aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin public void checkOldSamples(String description, PluralRules rules, String keyword, SampleType sampleType, 185aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin Double... expected) { 186aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin Collection<Double> oldSamples = rules.getSamples(keyword, sampleType); 187aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin if (!assertEquals("getOldSamples; " + keyword + "; " + description, new HashSet(Arrays.asList(expected)), 188aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin oldSamples)) { 189aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin rules.getSamples(keyword, sampleType); 190aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin } 191aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin } 192aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin 193aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin public void checkNewSamples(String description, PluralRules test, String keyword, SampleType sampleType, 194aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin String samplesString, boolean isBounded, FixedDecimal firstInRange) { 195aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin String title = description + ", " + sampleType; 196aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin FixedDecimalSamples samples = test.getDecimalSamples(keyword, sampleType); 197aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin if (samples != null) { 198aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin assertEquals("samples; " + title, samplesString, samples.toString()); 199aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin assertEquals("bounded; " + title, isBounded, samples.bounded); 200aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin assertEquals("first; " + title, firstInRange, samples.samples.iterator().next().start); 201aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin } 202aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin assertEquals("limited: " + title, isBounded, test.isLimited(keyword, sampleType)); 203aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin } 204aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin 205aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin private static final String[] parseTestData = { "a: n is 1", "a:1", "a: n mod 10 is 2", "a:2,12,22", 206aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin "a: n is not 1", "a:0,2,3,4,5", "a: n mod 3 is not 1", "a:0,2,3,5,6,8,9", "a: n in 2..5", "a:2,3,4,5", 207aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin "a: n within 2..5", "a:2,3,4,5", "a: n not in 2..5", "a:0,1,6,7,8", "a: n not within 2..5", "a:0,1,6,7,8", 208aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin "a: n mod 10 in 2..5", "a:2,3,4,5,12,13,14,15,22,23,24,25", "a: n mod 10 within 2..5", 209aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin "a:2,3,4,5,12,13,14,15,22,23,24,25", "a: n mod 10 is 2 and n is not 12", "a:2,22,32,42", 210aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin "a: n mod 10 in 2..3 or n mod 10 is 5", "a:2,3,5,12,13,15,22,23,25", 211aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin "a: n mod 10 within 2..3 or n mod 10 is 5", "a:2,3,5,12,13,15,22,23,25", "a: n is 1 or n is 4 or n is 23", 212aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin "a:1,4,23", "a: n mod 2 is 1 and n is not 3 and n in 1..11", "a:1,5,7,9,11", 213aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin "a: n mod 2 is 1 and n is not 3 and n within 1..11", "a:1,5,7,9,11", 214aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin "a: n mod 2 is 1 or n mod 5 is 1 and n is not 6", "a:1,3,5,7,9,11,13,15,16", 215aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin "a: n in 2..5; b: n in 5..8; c: n mod 2 is 1", "a:2,3,4,5;b:6,7,8;c:1,9,11", 216aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin "a: n within 2..5; b: n within 5..8; c: n mod 2 is 1", "a:2,3,4,5;b:6,7,8;c:1,9,11", 217aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin "a: n in 2,4..6; b: n within 7..9,11..12,20", "a:2,4,5,6;b:7,8,9,11,12,20", 218aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin "a: n in 2..8,12 and n not in 4..6", "a:2,3,7,8,12", "a: n mod 10 in 2,3,5..7 and n is not 12", 219aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin "a:2,3,5,6,7,13,15,16,17", "a: n in 2..6,3..7", "a:2,3,4,5,6,7", }; 220aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin 221aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin private String[] getTargetStrings(String targets) { 222aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin List list = new ArrayList(50); 223aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin String[] valSets = Utility.split(targets, ';'); 224aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin for (int i = 0; i < valSets.length; ++i) { 225aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin String[] temp = Utility.split(valSets[i], ':'); 226aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin String key = temp[0].trim(); 227aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin String[] vals = Utility.split(temp[1], ','); 228aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin for (int j = 0; j < vals.length; ++j) { 229aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin String valString = vals[j].trim(); 230aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin int val = Integer.parseInt(valString); 231aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin while (list.size() <= val) { 232aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin list.add(null); 233aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin } 234aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin if (list.get(val) != null) { 235aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin fail("test data error, key: " + list.get(val) + " already set for: " + val); 236aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin } 237aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin list.set(val, key); 238aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin } 239aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin } 240aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin 241aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin String[] result = (String[]) list.toArray(new String[list.size()]); 242aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin for (int i = 0; i < result.length; ++i) { 243aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin if (result[i] == null) { 244aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin result[i] = "other"; 245aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin } 246aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin } 247aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin return result; 248aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin } 249aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin 250aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin private void checkTargets(PluralRules rules, String[] targets) { 251aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin for (int i = 0; i < targets.length; ++i) { 252aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin assertEquals("value " + i, targets[i], rules.select(i)); 253aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin } 254aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin } 255aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin 256f86f25d102340da66b9c7cb6b2d5ecdc0de43ecfFredrik Roubert @Test 257aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin public void testParseEmpty() throws ParseException { 258aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin PluralRules rules = PluralRules.parseDescription("a:n"); 259aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin assertEquals("empty", "a", rules.select(0)); 260aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin } 261aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin 262f86f25d102340da66b9c7cb6b2d5ecdc0de43ecfFredrik Roubert @Test 263aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin public void testParsing() { 264aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin for (int i = 0; i < parseTestData.length; i += 2) { 265aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin String pattern = parseTestData[i]; 266aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin String expected = parseTestData[i + 1]; 267aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin 268aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin logln("pattern[" + i + "] " + pattern); 269aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin try { 270aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin PluralRules rules = PluralRules.createRules(pattern); 271aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin String[] targets = getTargetStrings(expected); 272aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin checkTargets(rules, targets); 273aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin } catch (Exception e) { 274aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin e.printStackTrace(); 275aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin throw new RuntimeException(e.getMessage()); 276aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin } 277aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin } 278aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin } 279aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin 280aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin private static String[][] operandTestData = { { "a: n 3", "FAIL" }, 281aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin { "a: n=1,2; b: n != 3..5; c:n!=5", "a:1,2; b:6,7; c:3,4" }, 282aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin { "a: n=1,2; b: n!=3..5; c:n!=5", "a:1,2; b:6,7; c:3,4" }, 283aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin { "a: t is 1", "a:1.1,1.1000,99.100; other:1.2,1.0" }, { "a: f is 1", "a:1.1; other:1.1000,99.100" }, 284aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin { "a: i is 2; b:i is 3", "b: 3.5; a: 2.5" }, { "a: f is 0; b:f is 50", "a: 1.00; b: 1.50" }, 285aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin { "a: v is 1; b:v is 2", "a: 1.0; b: 1.00" }, { "one: n is 1 AND v is 0", "one: 1 ; other: 1.00,1.0" }, // English 286aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin // rules 287aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin { "one: v is 0 and i mod 10 is 1 or f mod 10 is 1", "one: 1, 1.1, 3.1; other: 1.0, 3.2, 5" }, // Last 288aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin // visible 289aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin // digit 290aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin { "one: j is 0", "one: 0; other: 0.0, 1.0, 3" }, // Last visible digit 291aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin // one → n is 1; few → n in 2..4; 292aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin }; 293aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin 294f86f25d102340da66b9c7cb6b2d5ecdc0de43ecfFredrik Roubert @Test 295aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin public void testOperands() { 296aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin for (String[] pair : operandTestData) { 297aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin String pattern = pair[0].trim(); 298aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin String categoriesAndExpected = pair[1].trim(); 299aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin 300aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin // logln("pattern[" + i + "] " + pattern); 301aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin boolean FAIL_EXPECTED = categoriesAndExpected.equalsIgnoreCase("fail"); 302aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin try { 303aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin logln(pattern); 304aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin PluralRules rules = PluralRules.createRules(pattern); 305aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin if (FAIL_EXPECTED) { 306aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin assertNull("Should fail with 'null' return.", rules); 307aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin } else { 308aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin logln(rules == null ? "null rules" : rules.toString()); 309aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin checkCategoriesAndExpected(pattern, categoriesAndExpected, rules); 310aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin } 311aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin } catch (Exception e) { 312aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin if (!FAIL_EXPECTED) { 313aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin e.printStackTrace(); 314aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin throw new RuntimeException(e.getMessage()); 315aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin } 316aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin } 317aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin } 318aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin } 319aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin 320f86f25d102340da66b9c7cb6b2d5ecdc0de43ecfFredrik Roubert @Test 321aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin public void testUniqueRules() { 322aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin main: for (ULocale locale : factory.getAvailableULocales()) { 323aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin PluralRules rules = factory.forLocale(locale); 324aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin Map<String, PluralRules> keywordToRule = new HashMap<String, PluralRules>(); 325aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin Collection<FixedDecimalSamples> samples = new LinkedHashSet<FixedDecimalSamples>(); 326aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin 327aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin for (String keyword : rules.getKeywords()) { 328aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin for (SampleType sampleType : SampleType.values()) { 329aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin FixedDecimalSamples samples2 = rules.getDecimalSamples(keyword, sampleType); 330aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin if (samples2 != null) { 331aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin samples.add(samples2); 332aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin } 333aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin } 334aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin if (keyword.equals("other")) { 335aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin continue; 336aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin } 337aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin String rules2 = keyword + ":" + rules.getRules(keyword); 338aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin PluralRules singleRule = PluralRules.createRules(rules2); 339aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin if (singleRule == null) { 340aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin errln("Can't generate single rule for " + rules2); 341aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin PluralRules.createRules(rules2); // for debugging 342aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin continue main; 343aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin } 344aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin keywordToRule.put(keyword, singleRule); 345aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin } 346aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin Map<FixedDecimal, String> collisionTest = new TreeMap(); 347aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin for (FixedDecimalSamples sample3 : samples) { 348aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin Set<FixedDecimalRange> samples2 = sample3.getSamples(); 349aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin if (samples2 == null) { 350aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin continue; 351aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin } 352aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin for (FixedDecimalRange sample : samples2) { 353aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin for (int i = 0; i < 1; ++i) { 354aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin FixedDecimal item = i == 0 ? sample.start : sample.end; 355aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin collisionTest.clear(); 356aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin for (Entry<String, PluralRules> entry : keywordToRule.entrySet()) { 357aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin PluralRules rule = entry.getValue(); 358aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin String foundKeyword = rule.select(item); 359aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin if (foundKeyword.equals("other")) { 360aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin continue; 361aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin } 362aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin String old = collisionTest.get(item); 363aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin if (old != null) { 364aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin errln(locale + "\tNon-unique rules: " + item + " => " + old + " & " + foundKeyword); 365aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin rule.select(item); 366aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin } else { 367aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin collisionTest.put(item, foundKeyword); 368aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin } 369aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin } 370aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin } 371aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin } 372aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin } 373aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin } 374aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin } 375aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin 376aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin private void checkCategoriesAndExpected(String title1, String categoriesAndExpected, PluralRules rules) { 377aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin for (String categoryAndExpected : categoriesAndExpected.split("\\s*;\\s*")) { 378aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin String[] categoryFromExpected = categoryAndExpected.split("\\s*:\\s*"); 379aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin String expected = categoryFromExpected[0]; 380aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin for (String value : categoryFromExpected[1].split("\\s*,\\s*")) { 381aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin if (value.startsWith("@") || value.equals("…") || value.equals("null")) { 382aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin continue; 383aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin } 384aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin String[] values = value.split("\\s*~\\s*"); 385aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin checkValue(title1, rules, expected, values[0]); 386aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin if (values.length > 1) { 387aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin checkValue(title1, rules, expected, values[1]); 388aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin } 389aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin } 390aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin } 391aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin } 392aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin 393aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin public void checkValue(String title1, PluralRules rules, String expected, String value) { 394aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin double number = Double.parseDouble(value); 395aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin int decimalPos = value.indexOf('.') + 1; 396aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin int countVisibleFractionDigits; 397aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin int fractionaldigits; 398aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin if (decimalPos == 0) { 399aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin countVisibleFractionDigits = fractionaldigits = 0; 400aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin } else { 401aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin countVisibleFractionDigits = value.length() - decimalPos; 402aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin fractionaldigits = Integer.parseInt(value.substring(decimalPos)); 403aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin } 404aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin String result = rules.select(number, countVisibleFractionDigits, fractionaldigits); 405aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin ULocale locale = null; 406aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin assertEquals(getAssertMessage(title1, locale, rules, expected) + "; value: " + value, expected, result); 407aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin } 408aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin 409aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin private static String[][] equalityTestData = { 410aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin // once we add fractions, we had to retract the "test all possibilities" for equality, 411aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin // so we only have a limited set of equality tests now. 412aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin { "c: n%11!=5", "c: n mod 11 is not 5" }, { "c: n is not 7", "c: n != 7" }, { "a:n in 2;", "a: n = 2" }, 413aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin { "b:n not in 5;", "b: n != 5" }, 414aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin 415aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin // { "a: n is 5", 416aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin // "a: n in 2..6 and n not in 2..4 and n is not 6" }, 417aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin // { "a: n in 2..3", 418aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin // "a: n is 2 or n is 3", 419aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin // "a: n is 3 and n in 2..5 or n is 2" }, 420aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin // { "a: n is 12; b:n mod 10 in 2..3", 421aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin // "b: n mod 10 in 2..3 and n is not 12; a: n in 12..12", 422aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin // "b: n is 13; a: n is 12; b: n mod 10 is 2 or n mod 10 is 3" }, 423aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin }; 424aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin 425aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin private static String[][] inequalityTestData = { { "a: n mod 8 is 3", "a: n mod 7 is 3" }, 426aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin { "a: n mod 3 is 2 and n is not 5", "a: n mod 6 is 2 or n is 8 or n is 11" }, 427aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin // the following are currently inequal, but we may make them equal in the future. 428aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin { "a: n in 2..5", "a: n in 2..4,5" }, }; 429aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin 430aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin private void compareEquality(String id, Object[] objects, boolean shouldBeEqual) { 431aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin for (int i = 0; i < objects.length; ++i) { 432aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin Object lhs = objects[i]; 433aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin int start = shouldBeEqual ? i : i + 1; 434aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin for (int j = start; j < objects.length; ++j) { 435aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin Object rhs = objects[j]; 436aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin if (rhs == null || shouldBeEqual != lhs.equals(rhs)) { 437aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin String msg = shouldBeEqual ? "should be equal" : "should not be equal"; 438aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin fail(id + " " + msg + " (" + i + ", " + j + "):\n " + lhs + "\n " + rhs); 439aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin } 440aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin // assertEquals("obj " + i + " and " + j, lhs, rhs); 441aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin } 442aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin } 443aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin } 444aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin 445aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin private void compareEqualityTestSets(String[][] sets, boolean shouldBeEqual) { 446aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin for (int i = 0; i < sets.length; ++i) { 447aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin String[] patterns = sets[i]; 448aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin PluralRules[] rules = new PluralRules[patterns.length]; 449aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin for (int j = 0; j < patterns.length; ++j) { 450aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin rules[j] = PluralRules.createRules(patterns[j]); 451aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin } 452aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin compareEquality("test " + i, rules, shouldBeEqual); 453aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin } 454aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin } 455aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin 456f86f25d102340da66b9c7cb6b2d5ecdc0de43ecfFredrik Roubert @Test 457aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin public void testEquality() { 458aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin compareEqualityTestSets(equalityTestData, true); 459aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin } 460aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin 461f86f25d102340da66b9c7cb6b2d5ecdc0de43ecfFredrik Roubert @Test 462aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin public void testInequality() { 463aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin compareEqualityTestSets(inequalityTestData, false); 464aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin } 465aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin 466f86f25d102340da66b9c7cb6b2d5ecdc0de43ecfFredrik Roubert @Test 467aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin public void testBuiltInRules() { 468aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin // spot check 469aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin PluralRules rules = factory.forLocale(ULocale.US); 470aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin assertEquals("us 0", PluralRules.KEYWORD_OTHER, rules.select(0)); 471aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin assertEquals("us 1", PluralRules.KEYWORD_ONE, rules.select(1)); 472aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin assertEquals("us 2", PluralRules.KEYWORD_OTHER, rules.select(2)); 473aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin 474aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin rules = factory.forLocale(ULocale.JAPAN); 475aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin assertEquals("ja 0", PluralRules.KEYWORD_OTHER, rules.select(0)); 476aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin assertEquals("ja 1", PluralRules.KEYWORD_OTHER, rules.select(1)); 477aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin assertEquals("ja 2", PluralRules.KEYWORD_OTHER, rules.select(2)); 478aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin 479aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin rules = factory.forLocale(ULocale.createCanonical("ru")); 480aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin assertEquals("ru 0", PluralRules.KEYWORD_MANY, rules.select(0)); 481aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin assertEquals("ru 1", PluralRules.KEYWORD_ONE, rules.select(1)); 482aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin assertEquals("ru 2", PluralRules.KEYWORD_FEW, rules.select(2)); 483aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin } 484aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin 485f86f25d102340da66b9c7cb6b2d5ecdc0de43ecfFredrik Roubert @Test 486aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin public void testFunctionalEquivalent() { 487aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin // spot check 488aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin ULocale unknown = ULocale.createCanonical("zz_ZZ"); 489aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin ULocale un_equiv = PluralRules.getFunctionalEquivalent(unknown, null); 490aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin assertEquals("unknown locales have root", ULocale.ROOT, un_equiv); 491aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin 492aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin ULocale jp_equiv = PluralRules.getFunctionalEquivalent(ULocale.JAPAN, null); 493aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin ULocale cn_equiv = PluralRules.getFunctionalEquivalent(ULocale.CHINA, null); 494aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin assertEquals("japan and china equivalent locales", jp_equiv, cn_equiv); 495aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin 496aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin boolean[] available = new boolean[1]; 497aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin ULocale russia = ULocale.createCanonical("ru_RU"); 498aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin ULocale ru_ru_equiv = PluralRules.getFunctionalEquivalent(russia, available); 499aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin assertFalse("ru_RU not listed", available[0]); 500aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin 501aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin ULocale russian = ULocale.createCanonical("ru"); 502aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin ULocale ru_equiv = PluralRules.getFunctionalEquivalent(russian, available); 503aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin assertTrue("ru listed", available[0]); 504aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin assertEquals("ru and ru_RU equivalent locales", ru_ru_equiv, ru_equiv); 505aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin } 506aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin 507f86f25d102340da66b9c7cb6b2d5ecdc0de43ecfFredrik Roubert @Test 508aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin public void testAvailableULocales() { 509aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin ULocale[] locales = factory.getAvailableULocales(); 510aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin Set localeSet = new HashSet(); 511aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin localeSet.addAll(Arrays.asList(locales)); 512aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin 513aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin assertEquals("locales are unique in list", locales.length, localeSet.size()); 514aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin } 515aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin 516aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin /* 517aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin * Test the method public static PluralRules parseDescription(String description) 518aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin */ 519f86f25d102340da66b9c7cb6b2d5ecdc0de43ecfFredrik Roubert @Test 520aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin public void TestParseDescription() { 521aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin try { 522aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin if (PluralRules.DEFAULT != PluralRules.parseDescription("")) { 523aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin errln("PluralRules.parseDescription(String) was suppose " 524aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin + "to return PluralRules.DEFAULT when String is of " + "length 0."); 525aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin } 526aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin } catch (ParseException e) { 527aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin errln("PluralRules.parseDescription(String) was not suppose " + "to return an exception."); 528aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin } 529aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin } 530aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin 531aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin /* 532aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin * Tests the method public static PluralRules createRules(String description) 533aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin */ 534f86f25d102340da66b9c7cb6b2d5ecdc0de43ecfFredrik Roubert @Test 535aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin public void TestCreateRules() { 536aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin try { 537aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin if (PluralRules.createRules(null) != null) { 538aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin errln("PluralRules.createRules(String) was suppose to " 539aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin + "return null for an invalid String descrtiption."); 540aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin } 541aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin } catch (Exception e) { 542aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin } 543aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin } 544aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin 545aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin /* 546aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin * Tests the method public int hashCode() 547aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin */ 548f86f25d102340da66b9c7cb6b2d5ecdc0de43ecfFredrik Roubert @Test 549aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin public void TestHashCode() { 550aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin // Bad test, breaks whenever PluralRules implementation changes. 551aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin // PluralRules pr = PluralRules.DEFAULT; 552aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin // if (106069776 != pr.hashCode()) { 553aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin // errln("PluralRules.hashCode() was suppose to return 106069776 " + "when PluralRules.DEFAULT."); 554aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin // } 555aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin } 556aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin 557aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin /* 558aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin * Tests the method public boolean equals(PluralRules rhs) 559aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin */ 560f86f25d102340da66b9c7cb6b2d5ecdc0de43ecfFredrik Roubert @Test 561aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin public void TestEquals() { 562aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin PluralRules pr = PluralRules.DEFAULT; 563aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin 564aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin if (pr.equals((PluralRules) null)) { 565aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin errln("PluralRules.equals(PluralRules) was supposed to return false " + "when passing null."); 566aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin } 567aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin } 568aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin 569aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin private void assertRuleValue(String rule, double value) { 570aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin assertRuleKeyValue("a:" + rule, "a", value); 571aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin } 572aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin 573aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin private void assertRuleKeyValue(String rule, String key, double value) { 574aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin PluralRules pr = PluralRules.createRules(rule); 575aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin assertEquals(rule, value, pr.getUniqueKeywordValue(key)); 576aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin } 577aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin 578aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin /* 579aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin * Tests getUniqueKeywordValue() 580aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin */ 581f86f25d102340da66b9c7cb6b2d5ecdc0de43ecfFredrik Roubert @Test 582aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin public void TestGetUniqueKeywordValue() { 583aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin assertRuleKeyValue("a: n is 1", "not_defined", PluralRules.NO_UNIQUE_VALUE); // key not defined 584aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin assertRuleValue("n within 2..2", 2); 585aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin assertRuleValue("n is 1", 1); 586aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin assertRuleValue("n in 2..2", 2); 587aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin assertRuleValue("n in 3..4", PluralRules.NO_UNIQUE_VALUE); 588aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin assertRuleValue("n within 3..4", PluralRules.NO_UNIQUE_VALUE); 589aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin assertRuleValue("n is 2 or n is 2", 2); 590aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin assertRuleValue("n is 2 and n is 2", 2); 591aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin assertRuleValue("n is 2 or n is 3", PluralRules.NO_UNIQUE_VALUE); 592aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin assertRuleValue("n is 2 and n is 3", PluralRules.NO_UNIQUE_VALUE); 593aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin assertRuleValue("n is 2 or n in 2..3", PluralRules.NO_UNIQUE_VALUE); 594aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin assertRuleValue("n is 2 and n in 2..3", 2); 595aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin assertRuleKeyValue("a: n is 1", "other", PluralRules.NO_UNIQUE_VALUE); // key matches default rule 596aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin assertRuleValue("n in 2,3", PluralRules.NO_UNIQUE_VALUE); 597aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin assertRuleValue("n in 2,3..6 and n not in 2..3,5..6", 4); 598aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin } 599aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin 600aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin /** 601aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin * The version in PluralFormatUnitTest is not really a test, and it's in the wrong place anyway, so I'm putting a 602aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin * variant of it here. 603aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin */ 604f86f25d102340da66b9c7cb6b2d5ecdc0de43ecfFredrik Roubert @Test 605aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin public void TestGetSamples() { 606aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin Set<ULocale> uniqueRuleSet = new HashSet<ULocale>(); 607aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin for (ULocale locale : factory.getAvailableULocales()) { 608aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin uniqueRuleSet.add(PluralRules.getFunctionalEquivalent(locale, null)); 609aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin } 610aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin for (ULocale locale : uniqueRuleSet) { 611aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin PluralRules rules = factory.forLocale(locale); 612aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin logln("\nlocale: " + (locale == ULocale.ROOT ? "root" : locale.toString()) + ", rules: " + rules); 613aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin Set<String> keywords = rules.getKeywords(); 614aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin for (String keyword : keywords) { 615aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin Collection<Double> list = rules.getSamples(keyword); 616aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin logln("keyword: " + keyword + ", samples: " + list); 617aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin // with fractions, the samples can be empty and thus the list null. In that case, however, there will be 618aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin // FixedDecimal values. 619aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin // So patch the test for that. 620aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin if (list.size() == 0) { 621aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin // when the samples (meaning integer samples) are null, then then integerSamples must be, and the 622aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin // decimalSamples must not be 623aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin FixedDecimalSamples integerSamples = rules.getDecimalSamples(keyword, SampleType.INTEGER); 624aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin FixedDecimalSamples decimalSamples = rules.getDecimalSamples(keyword, SampleType.DECIMAL); 625aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin assertTrue(getAssertMessage("List is not null", locale, rules, keyword), integerSamples == null 626aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin && decimalSamples != null && decimalSamples.samples.size() != 0); 627aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin } else { 628aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin if (!assertTrue(getAssertMessage("Test getSamples.isEmpty", locale, rules, keyword), 629aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin !list.isEmpty())) { 630aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin rules.getSamples(keyword); 631aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin } 632aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin if (rules.toString().contains(": j")) { 633aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin // hack until we remove j 634aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin } else { 635aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin for (double value : list) { 636aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin assertEquals(getAssertMessage("Match keyword", locale, rules, keyword) + "; value '" 637aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin + value + "'", keyword, rules.select(value)); 638aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin } 639aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin } 640aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin } 641aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin } 642aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin 643aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin assertNull(locale + ", list is null", rules.getSamples("@#$%^&*")); 644aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin assertNull(locale + ", list is null", rules.getSamples("@#$%^&*", SampleType.DECIMAL)); 645aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin } 646aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin } 647aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin 648aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin public String getAssertMessage(String message, ULocale locale, PluralRules rules, String keyword) { 649aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin String ruleString = ""; 650aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin if (keyword != null) { 651aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin if (keyword.equals("other")) { 652aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin for (String keyword2 : rules.getKeywords()) { 653aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin ruleString += " NOR " + rules.getRules(keyword2).split("@")[0]; 654aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin } 655aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin } else { 656aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin String rule = rules.getRules(keyword); 657aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin ruleString = rule == null ? null : rule.split("@")[0]; 658aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin } 659aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin ruleString = "; rule: '" + keyword + ": " + ruleString + "'"; 660aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin // !keyword.equals("other") ? "'; keyword: '" + keyword + "'; rule: '" + rules.getRules(keyword) + "'" 661aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin // : "'; keyword: '" + keyword + "'; rules: '" + rules.toString() + "'"; 662aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin } 663aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin return message + (locale == null ? "" : "; locale: '" + locale + "'") + ruleString; 664aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin } 665aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin 666aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin /** 667aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin * Returns the empty set if the keyword is not defined, null if there are an unlimited number of values for the 668aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin * keyword, or the set of values that trigger the keyword. 669aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin */ 670f86f25d102340da66b9c7cb6b2d5ecdc0de43ecfFredrik Roubert @Test 671aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin public void TestGetAllKeywordValues() { 672aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin // data is pairs of strings, the rule, and the expected values as arguments 673aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin String[] data = { 674aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin "other: ; a: n mod 3 is 0", 675aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin "a: null", 676aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin "a: n in 2..5 and n within 5..8", 677aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin "a: 5", 678aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin "a: n in 2..5", 679aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin "a: 2,3,4,5; other: null", 680aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin "a: n not in 2..5", 681aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin "a: null; other: null", 682aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin "a: n within 2..5", 683aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin "a: 2,3,4,5; other: null", 684aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin "a: n not within 2..5", 685aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin "a: null; other: null", 686aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin "a: n in 2..5 or n within 6..8", 687aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin "a: 2,3,4,5,6,7,8", // ignore 'other' here on out, always null 688aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin "a: n in 2..5 and n within 6..8", 689aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin "a: null", 690aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin // we no longer support 'degenerate' rules 691aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin // "a: n within 2..5 and n within 6..8", "a:", // our sampling catches these 692aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin // "a: n within 2..5 and n within 5..8", "a: 5", // '' 693aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin // "a: n within 1..2 and n within 2..3 or n within 3..4 and n within 4..5", "a: 2,4", 694aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin // "a: n mod 3 is 0 and n within 0..5", "a: 0,3", 695aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin "a: n within 1..2 and n within 2..3 or n within 3..4 and n within 4..5 or n within 5..6 and n within 6..7", 696aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin "a: 2,4,6", // but not this... 697aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin "a: n mod 3 is 0 and n within 1..2", "a: null", "a: n mod 3 is 0 and n within 0..6", "a: 0,3,6", 698aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin "a: n mod 3 is 0 and n in 3..12", "a: 3,6,9,12", "a: n in 2,4..6 and n is not 5", "a: 2,4,6", }; 699aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin for (int i = 0; i < data.length; i += 2) { 700aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin String ruleDescription = data[i]; 701aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin String result = data[i + 1]; 702aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin 703aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin PluralRules p = PluralRules.createRules(ruleDescription); 704aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin if (p == null) { // for debugging 705aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin PluralRules.createRules(ruleDescription); 706aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin } 707aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin for (String ruleResult : result.split(";")) { 708aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin String[] ruleAndValues = ruleResult.split(":"); 709aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin String keyword = ruleAndValues[0].trim(); 710aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin String valueList = ruleAndValues.length < 2 ? null : ruleAndValues[1]; 711aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin if (valueList != null) { 712aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin valueList = valueList.trim(); 713aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin } 714aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin Collection<Double> values; 715aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin if (valueList == null || valueList.length() == 0) { 716aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin values = Collections.EMPTY_SET; 717aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin } else if ("null".equals(valueList)) { 718aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin values = null; 719aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin } else { 720aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin values = new TreeSet<Double>(); 721aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin for (String value : valueList.split(",")) { 722aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin values.add(Double.parseDouble(value)); 723aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin } 724aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin } 725aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin 726aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin Collection<Double> results = p.getAllKeywordValues(keyword); 727aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin assertEquals(keyword + " in " + ruleDescription, values, results == null ? null : new HashSet(results)); 728aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin 729aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin if (results != null) { 730aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin try { 731aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin results.add(PluralRules.NO_UNIQUE_VALUE); 732aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin fail("returned set is modifiable"); 733aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin } catch (UnsupportedOperationException e) { 734aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin // pass 735aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin } 736aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin } 737aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin } 738aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin } 739aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin } 740aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin 741f86f25d102340da66b9c7cb6b2d5ecdc0de43ecfFredrik Roubert @Test 742aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin public void TestOrdinal() { 743aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin PluralRules pr = factory.forLocale(ULocale.ENGLISH, PluralType.ORDINAL); 744aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin assertEquals("PluralRules(en-ordinal).select(2)", "two", pr.select(2)); 745aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin } 746aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin 747f86f25d102340da66b9c7cb6b2d5ecdc0de43ecfFredrik Roubert @Test 748aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin public void TestBasicFraction() { 749aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin String[][] tests = { { "en", "one: j is 1" }, { "1", "0", "1", "one" }, { "1", "2", "1.00", "other" }, }; 750aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin ULocale locale = null; 751aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin NumberFormat nf = null; 752aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin PluralRules pr = null; 753aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin 754aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin for (String[] row : tests) { 755aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin switch (row.length) { 756aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin case 2: 757aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin locale = ULocale.forLanguageTag(row[0]); 758aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin nf = NumberFormat.getInstance(locale); 759aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin pr = PluralRules.createRules(row[1]); 760aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin break; 761aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin case 4: 762aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin double n = Double.parseDouble(row[0]); 763aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin int minFracDigits = Integer.parseInt(row[1]); 764aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin nf.setMinimumFractionDigits(minFracDigits); 765aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin String expectedFormat = row[2]; 766aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin String expectedKeyword = row[3]; 767aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin 768aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin UFieldPosition pos = new UFieldPosition(); 769aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin String formatted = nf.format(1.0, new StringBuffer(), pos).toString(); 770aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin int countVisibleFractionDigits = pos.getCountVisibleFractionDigits(); 771aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin long fractionDigits = pos.getFractionDigits(); 772aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin String keyword = pr.select(n, countVisibleFractionDigits, fractionDigits); 773aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin assertEquals("Formatted " + n + "\t" + minFracDigits, expectedFormat, formatted); 774aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin assertEquals("Keyword " + n + "\t" + minFracDigits, expectedKeyword, keyword); 775aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin break; 776aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin default: 777aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin throw new RuntimeException(); 778aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin } 779aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin } 780aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin } 781aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin 782f86f25d102340da66b9c7cb6b2d5ecdc0de43ecfFredrik Roubert @Test 783aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin public void TestLimitedAndSamplesConsistency() { 784aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin for (ULocale locale : PluralRules.getAvailableULocales()) { 785aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin ULocale loc2 = PluralRules.getFunctionalEquivalent(locale, null); 786aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin if (!loc2.equals(locale)) { 787aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin continue; // only need "unique" rules 788aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin } 789aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin for (PluralType type : PluralType.values()) { 790aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin PluralRules rules = PluralRules.forLocale(locale, type); 791aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin for (SampleType sampleType : SampleType.values()) { 792aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin if (type == PluralType.ORDINAL) { 793aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin logKnownIssue("10783", "Fix issues with isLimited vs computeLimited on ordinals"); 794aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin continue; 795aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin } 796aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin for (String keyword : rules.getKeywords()) { 797aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin boolean isLimited = rules.isLimited(keyword, sampleType); 798aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin boolean computeLimited = rules.computeLimited(keyword, sampleType); 799aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin if (!keyword.equals("other")) { 800aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin assertEquals(getAssertMessage("computeLimited == isLimited", locale, rules, keyword), 801aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin computeLimited, isLimited); 802aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin } 803aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin Collection<Double> samples = rules.getSamples(keyword, sampleType); 804aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin assertNotNull(getAssertMessage("Samples must not be null", locale, rules, keyword), samples); 805aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin /* FixedDecimalSamples decimalSamples = */rules.getDecimalSamples(keyword, sampleType); 806aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin // assertNotNull(getAssertMessage("Decimal samples must be null if unlimited", locale, rules, 807aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin // keyword), decimalSamples); 808aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin } 809aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin } 810aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin } 811aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin } 812aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin } 813aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin 814f86f25d102340da66b9c7cb6b2d5ecdc0de43ecfFredrik Roubert @Test 815aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin public void TestKeywords() { 816aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin Set<String> possibleKeywords = new LinkedHashSet(Arrays.asList("zero", "one", "two", "few", "many", "other")); 817aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin Object[][][] tests = { 818aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin // format is locale, explicits, then triples of keyword, status, unique value. 819aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin { { "en", null }, { "one", KeywordStatus.UNIQUE, 1.0d }, { "other", KeywordStatus.UNBOUNDED, null } }, 820aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin { { "pl", null }, { "one", KeywordStatus.UNIQUE, 1.0d }, { "few", KeywordStatus.UNBOUNDED, null }, 821aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin { "many", KeywordStatus.UNBOUNDED, null }, 822aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin { "other", KeywordStatus.SUPPRESSED, null, KeywordStatus.UNBOUNDED, null } // note that it is 823aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin // suppressed in 824aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin // INTEGER but not 825aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin // DECIMAL 826aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin }, { { "en", new HashSet<Double>(Arrays.asList(1.0d)) }, // check that 1 is suppressed 827aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin { "one", KeywordStatus.SUPPRESSED, null }, { "other", KeywordStatus.UNBOUNDED, null } }, }; 828aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin Output<Double> uniqueValue = new Output<Double>(); 829aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin for (Object[][] test : tests) { 830aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin ULocale locale = new ULocale((String) test[0][0]); 831aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin // NumberType numberType = (NumberType) test[1]; 832aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin Set<Double> explicits = (Set<Double>) test[0][1]; 833aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin PluralRules pluralRules = factory.forLocale(locale); 834aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin LinkedHashSet<String> remaining = new LinkedHashSet(possibleKeywords); 835aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin for (int i = 1; i < test.length; ++i) { 836aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin Object[] row = test[i]; 837aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin String keyword = (String) row[0]; 838aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin KeywordStatus statusExpected = (KeywordStatus) row[1]; 839aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin Double uniqueExpected = (Double) row[2]; 840aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin remaining.remove(keyword); 841aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin KeywordStatus status = pluralRules.getKeywordStatus(keyword, 0, explicits, uniqueValue); 842aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin assertEquals(getAssertMessage("Unique Value", locale, pluralRules, keyword), uniqueExpected, 843aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin uniqueValue.value); 844aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin assertEquals(getAssertMessage("Keyword Status", locale, pluralRules, keyword), statusExpected, status); 845aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin if (row.length > 3) { 846aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin statusExpected = (KeywordStatus) row[3]; 847aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin uniqueExpected = (Double) row[4]; 848aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin status = pluralRules.getKeywordStatus(keyword, 0, explicits, uniqueValue, SampleType.DECIMAL); 849aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin assertEquals(getAssertMessage("Unique Value - decimal", locale, pluralRules, keyword), 850aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin uniqueExpected, uniqueValue.value); 851aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin assertEquals(getAssertMessage("Keyword Status - decimal", locale, pluralRules, keyword), 852aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin statusExpected, status); 853aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin } 854aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin } 855aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin for (String keyword : remaining) { 856aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin KeywordStatus status = pluralRules.getKeywordStatus(keyword, 0, null, uniqueValue); 857aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin assertEquals("Invalid keyword " + keyword, status, KeywordStatus.INVALID); 858aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin assertNull("Invalid keyword " + keyword, uniqueValue.value); 859aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin } 860aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin } 861aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin } 862aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin 863aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin enum StandardPluralCategories { 864aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin zero, one, two, few, many, other; 865aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin /** 866aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin * 867aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin */ 868aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin private static final Set<StandardPluralCategories> ALL = Collections.unmodifiableSet(EnumSet 869aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin .allOf(StandardPluralCategories.class)); 870aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin 871aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin /** 872aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin * Return a mutable set 873aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin * 874aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin * @param source 875aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin * @return 876aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin */ 877aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin static final EnumSet<StandardPluralCategories> getSet(Collection<String> source) { 878aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin EnumSet<StandardPluralCategories> result = EnumSet.noneOf(StandardPluralCategories.class); 879aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin for (String s : source) { 880aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin result.add(StandardPluralCategories.valueOf(s)); 881aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin } 882aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin return result; 883aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin } 884aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin 885aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin static final Comparator<Set<StandardPluralCategories>> SHORTEST_FIRST = new Comparator<Set<StandardPluralCategories>>() { 886aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin public int compare(Set<StandardPluralCategories> arg0, Set<StandardPluralCategories> arg1) { 887aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin int diff = arg0.size() - arg1.size(); 888aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin if (diff != 0) { 889aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin return diff; 890aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin } 891aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin // otherwise first... 892aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin // could be optimized, but we don't care here. 893aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin for (StandardPluralCategories value : ALL) { 894aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin if (arg0.contains(value)) { 895aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin if (!arg1.contains(value)) { 896aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin return 1; 897aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin } 898aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin } else if (arg1.contains(value)) { 899aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin return -1; 900aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin } 901aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin 902aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin } 903aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin return 0; 904aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin } 905aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin 906aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin }; 907aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin } 908aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin 909f86f25d102340da66b9c7cb6b2d5ecdc0de43ecfFredrik Roubert @Test 910aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin public void TestLocales() { 911aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin if (false) { 912aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin generateLOCALE_SNAPSHOT(); 913aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin } 914aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin for (String test : LOCALE_SNAPSHOT) { 915aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin test = test.trim(); 916aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin String[] parts = test.split("\\s*;\\s*"); 917aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin for (String localeString : parts[0].split("\\s*,\\s*")) { 918aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin ULocale locale = new ULocale(localeString); 919aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin if (factory.hasOverride(locale)) { 920aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin continue; // skip for now 921aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin } 922aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin PluralRules rules = factory.forLocale(locale); 923aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin for (int i = 1; i < parts.length; ++i) { 924aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin checkCategoriesAndExpected(localeString, parts[i], rules); 925aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin } 926aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin } 927aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin } 928aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin } 929aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin 930aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin private static final Comparator<PluralRules> PLURAL_RULE_COMPARATOR = new Comparator<PluralRules>() { 931aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin public int compare(PluralRules o1, PluralRules o2) { 932aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin return o1.compareTo(o2); 933aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin } 934aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin }; 935aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin 936aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin private void generateLOCALE_SNAPSHOT() { 937aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin Comparator c = new CollectionUtilities.CollectionComparator<Comparable>(); 938aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin Relation<Set<StandardPluralCategories>, PluralRules> setsToRules = Relation.of( 939aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin new TreeMap<Set<StandardPluralCategories>, Set<PluralRules>>(c), TreeSet.class, PLURAL_RULE_COMPARATOR); 940aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin Relation<PluralRules, ULocale> data = Relation.of( 941aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin new TreeMap<PluralRules, Set<ULocale>>(PLURAL_RULE_COMPARATOR), TreeSet.class); 942aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin for (ULocale locale : PluralRules.getAvailableULocales()) { 943aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin PluralRules pr = PluralRules.forLocale(locale); 944aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin EnumSet<StandardPluralCategories> set = getCanonicalSet(pr.getKeywords()); 945aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin setsToRules.put(set, pr); 946aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin data.put(pr, locale); 947aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin } 948aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin for (Entry<Set<StandardPluralCategories>, Set<PluralRules>> entry1 : setsToRules.keyValuesSet()) { 949aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin Set<StandardPluralCategories> set = entry1.getKey(); 950aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin Set<PluralRules> rules = entry1.getValue(); 951aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin System.out.println("\n // " + set); 952aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin for (PluralRules rule : rules) { 953aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin Set<ULocale> locales = data.get(rule); 954aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin System.out.print(" \"" + CollectionUtilities.join(locales, ",")); 955aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin for (StandardPluralCategories spc : set) { 956aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin String keyword = spc.toString(); 957aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin FixedDecimalSamples samples = rule.getDecimalSamples(keyword, SampleType.INTEGER); 958aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin System.out.print("; " + spc + ": " + samples); 959aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin } 960aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin System.out.println("\","); 961aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin } 962aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin } 963aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin } 964aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin 965aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin /** 966aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin * @param keywords 967aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin * @return 968aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin */ 969aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin private EnumSet<StandardPluralCategories> getCanonicalSet(Set<String> keywords) { 970aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin EnumSet<StandardPluralCategories> result = EnumSet.noneOf(StandardPluralCategories.class); 971aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin for (String s : keywords) { 972aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin result.add(StandardPluralCategories.valueOf(s)); 973aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin } 974aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin return result; 975aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin } 976aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin 977aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin static final String[] LOCALE_SNAPSHOT = { 978aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin // [other] 979aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin "bm,bo,dz,id,ig,ii,in,ja,jbo,jv,jw,kde,kea,km,ko,lkt,lo,ms,my,nqo,root,sah,ses,sg,th,to,vi,wo,yo,zh; other: @integer 0~15, 100, 1000, 10000, 100000, 1000000, …", 980aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin 981aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin // [one, other] 982aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin "am,bn,fa,gu,hi,kn,mr,zu; one: @integer 0, 1; other: @integer 2~17, 100, 1000, 10000, 100000, 1000000, …", 983aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin "ff,fr,hy,kab; one: @integer 0, 1; other: @integer 2~17, 100, 1000, 10000, 100000, 1000000, …", 984aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin "ast,ca,de,en,et,fi,fy,gl,it,ji,nl,sv,sw,ur,yi; one: @integer 1; other: @integer 0, 2~16, 100, 1000, 10000, 100000, 1000000, …", 985aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin "pt; one: @integer 1; other: @integer 0, 2~16, 100, 1000, 10000, 100000, 1000000, …", 986aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin "si; one: @integer 0, 1; other: @integer 2~17, 100, 1000, 10000, 100000, 1000000, …", 987aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin "ak,bh,guw,ln,mg,nso,pa,ti,wa; one: @integer 0, 1; other: @integer 2~17, 100, 1000, 10000, 100000, 1000000, …", 988aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin "tzm; one: @integer 0, 1, 11~24; other: @integer 2~10, 100~106, 1000, 10000, 100000, 1000000, …", 989aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin "af,asa,az,bem,bez,bg,brx,cgg,chr,ckb,dv,ee,el,eo,es,eu,fo,fur,gsw,ha,haw,hu,jgo,jmc,ka,kaj,kcg,kk,kkj,kl,ks,ksb,ku,ky,lb,lg,mas,mgo,ml,mn,nah,nb,nd,ne,nn,nnh,no,nr,ny,nyn,om,or,os,pap,ps,rm,rof,rwk,saq,seh,sn,so,sq,ss,ssy,st,syr,ta,te,teo,tig,tk,tn,tr,ts,ug,uz,ve,vo,vun,wae,xh,xog; one: @integer 1; other: @integer 0, 2~16, 100, 1000, 10000, 100000, 1000000, …", 990aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin "pt_PT; one: @integer 1; other: @integer 0, 2~16, 100, 1000, 10000, 100000, 1000000, …", 991aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin "da; one: @integer 1; other: @integer 0, 2~16, 100, 1000, 10000, 100000, 1000000, …", 992aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin "is; one: @integer 1, 21, 31, 41, 51, 61, 71, 81, 101, 1001, …; other: @integer 0, 2~16, 100, 1000, 10000, 100000, 1000000, …", 993aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin "mk; one: @integer 1, 11, 21, 31, 41, 51, 61, 71, 101, 1001, …; other: @integer 0, 2~10, 12~17, 100, 1000, 10000, 100000, 1000000, …", 994aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin "fil,tl; one: @integer 0~3, 5, 7, 8, 10~13, 15, 17, 18, 20, 21, 100, 1000, 10000, 100000, 1000000, …; other: @integer 4, 6, 9, 14, 16, 19, 24, 26, 104, 1004, …", 995aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin 996aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin // [zero, one, other] 997aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin "lag; zero: @integer 0; one: @integer 1; other: @integer 2~17, 100, 1000, 10000, 100000, 1000000, …", 998aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin "lv,prg; zero: @integer 0, 10~20, 30, 40, 50, 60, 100, 1000, 10000, 100000, 1000000, …; one: @integer 1, 21, 31, 41, 51, 61, 71, 81, 101, 1001, …; other: @integer 2~9, 22~29, 102, 1002, …", 999aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin "ksh; zero: @integer 0; one: @integer 1; other: @integer 2~17, 100, 1000, 10000, 100000, 1000000, …", 1000aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin 1001aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin // [one, two, other] 1002aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin "iu,kw,naq,se,sma,smi,smj,smn,sms; one: @integer 1; two: @integer 2; other: @integer 0, 3~17, 100, 1000, 10000, 100000, 1000000, …", 1003aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin 1004aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin // [one, few, other] 1005aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin "shi; one: @integer 0, 1; few: @integer 2~10; other: @integer 11~26, 100, 1000, 10000, 100000, 1000000, …", 1006aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin "mo,ro; one: @integer 1; few: @integer 0, 2~16, 101, 1001, …; other: @integer 20~35, 100, 1000, 10000, 100000, 1000000, …", 1007aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin "bs,hr,sh,sr; one: @integer 1, 21, 31, 41, 51, 61, 71, 81, 101, 1001, …; few: @integer 2~4, 22~24, 32~34, 42~44, 52~54, 62, 102, 1002, …; other: @integer 0, 5~19, 100, 1000, 10000, 100000, 1000000, …", 1008aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin 1009aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin // [one, two, few, other] 1010aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin "gd; one: @integer 1, 11; two: @integer 2, 12; few: @integer 3~10, 13~19; other: @integer 0, 20~34, 100, 1000, 10000, 100000, 1000000, …", 1011aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin "sl; one: @integer 1, 101, 201, 301, 401, 501, 601, 701, 1001, …; two: @integer 2, 102, 202, 302, 402, 502, 602, 702, 1002, …; few: @integer 3, 4, 103, 104, 203, 204, 303, 304, 403, 404, 503, 504, 603, 604, 703, 704, 1003, …; other: @integer 0, 5~19, 100, 1000, 10000, 100000, 1000000, …", 1012aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin 1013aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin // [one, two, many, other] 1014aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin "he,iw; one: @integer 1; two: @integer 2; many: @integer 20, 30, 40, 50, 60, 70, 80, 90, 100, 1000, 10000, 100000, 1000000, …; other: @integer 0, 3~17, 101, 1001, …", 1015aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin 1016aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin // [one, few, many, other] 1017aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin "cs,sk; one: @integer 1; few: @integer 2~4; many: null; other: @integer 0, 5~19, 100, 1000, 10000, 100000, 1000000, …", 1018aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin "be; one: @integer 1, 21, 31, 41, 51, 61, 71, 81, 101, 1001, …; few: @integer 2~4, 22~24, 32~34, 42~44, 52~54, 62, 102, 1002, …; many: @integer 0, 5~19, 100, 1000, 10000, 100000, 1000000, …; other: null", 1019aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin "lt; one: @integer 1, 21, 31, 41, 51, 61, 71, 81, 101, 1001, …; few: @integer 2~9, 22~29, 102, 1002, …; many: null; other: @integer 0, 10~20, 30, 40, 50, 60, 100, 1000, 10000, 100000, 1000000, …", 1020aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin "mt; one: @integer 1; few: @integer 0, 2~10, 102~107, 1002, …; many: @integer 11~19, 111~117, 1011, …; other: @integer 20~35, 100, 1000, 10000, 100000, 1000000, …", 1021aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin "pl; one: @integer 1; few: @integer 2~4, 22~24, 32~34, 42~44, 52~54, 62, 102, 1002, …; many: @integer 0, 5~19, 100, 1000, 10000, 100000, 1000000, …; other: null", 1022aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin "ru,uk; one: @integer 1, 21, 31, 41, 51, 61, 71, 81, 101, 1001, …; few: @integer 2~4, 22~24, 32~34, 42~44, 52~54, 62, 102, 1002, …; many: @integer 0, 5~19, 100, 1000, 10000, 100000, 1000000, …; other: null", 1023aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin 1024aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin // [one, two, few, many, other] 1025aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin "br; one: @integer 1, 21, 31, 41, 51, 61, 81, 101, 1001, …; two: @integer 2, 22, 32, 42, 52, 62, 82, 102, 1002, …; few: @integer 3, 4, 9, 23, 24, 29, 33, 34, 39, 43, 44, 49, 103, 1003, …; many: @integer 1000000, …; other: @integer 0, 5~8, 10~20, 100, 1000, 10000, 100000, …", 1026aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin "ga; one: @integer 1; two: @integer 2; few: @integer 3~6; many: @integer 7~10; other: @integer 0, 11~25, 100, 1000, 10000, 100000, 1000000, …", 1027aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin "gv; one: @integer 1, 11, 21, 31, 41, 51, 61, 71, 101, 1001, …; two: @integer 2, 12, 22, 32, 42, 52, 62, 72, 102, 1002, …; few: @integer 0, 20, 40, 60, 80, 100, 120, 140, 1000, 10000, 100000, 1000000, …; many: null; other: @integer 3~10, 13~19, 23, 103, 1003, …", 1028aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin 1029aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin // [zero, one, two, few, many, other] 1030aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin "ar; zero: @integer 0; one: @integer 1; two: @integer 2; few: @integer 3~10, 103~110, 1003, …; many: @integer 11~26, 111, 1011, …; other: @integer 100~102, 200~202, 300~302, 400~402, 500~502, 600, 1000, 10000, 100000, 1000000, …", 1031aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin "cy; zero: @integer 0; one: @integer 1; two: @integer 2; few: @integer 3; many: @integer 6; other: @integer 4, 5, 7~20, 100, 1000, 10000, 100000, 1000000, …", }; 1032aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin 1033aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin private <T extends Serializable> T serializeAndDeserialize(T original, Output<Integer> size) { 1034aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin try { 1035aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin ByteArrayOutputStream baos = new ByteArrayOutputStream(); 1036aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin ObjectOutputStream ostream = new ObjectOutputStream(baos); 1037aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin ostream.writeObject(original); 1038aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin ostream.flush(); 1039aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin byte bytes[] = baos.toByteArray(); 1040aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin size.value = bytes.length; 1041aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin ObjectInputStream istream = new ObjectInputStream(new ByteArrayInputStream(bytes)); 1042aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin T reconstituted = (T) istream.readObject(); 1043aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin return reconstituted; 1044aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin } catch (IOException e) { 1045aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin throw new RuntimeException(e); 1046aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin } catch (ClassNotFoundException e) { 1047aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin throw new RuntimeException(e); 1048aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin } 1049aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin } 1050aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin 1051f86f25d102340da66b9c7cb6b2d5ecdc0de43ecfFredrik Roubert @Test 1052aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin public void TestSerialization() { 1053aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin Output<Integer> size = new Output<Integer>(); 1054aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin int max = 0; 1055aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin for (ULocale locale : PluralRules.getAvailableULocales()) { 1056aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin PluralRules item = PluralRules.forLocale(locale); 1057aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin PluralRules item2 = serializeAndDeserialize(item, size); 1058aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin logln(locale + "\tsize:\t" + size.value); 1059aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin max = Math.max(max, size.value); 1060aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin if (!assertEquals(locale + "\tPlural rules before and after serialization", item, item2)) { 1061aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin // for debugging 1062aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin PluralRules item3 = serializeAndDeserialize(item, size); 1063aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin item.equals(item3); 1064aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin } 1065aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin } 1066aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin logln("max \tsize:\t" + max); 1067aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin } 1068aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin 1069f86f25d102340da66b9c7cb6b2d5ecdc0de43ecfFredrik Roubert public static class FixedDecimalHandler implements SerializableTestUtility.Handler { 1070aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin public Object[] getTestObjects() { 1071aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin FixedDecimal items[] = { new FixedDecimal(3d), new FixedDecimal(3d, 2), new FixedDecimal(3.1d, 1), 1072aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin new FixedDecimal(3.1d, 2), }; 1073aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin return items; 1074aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin } 1075aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin 1076aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin public boolean hasSameBehavior(Object a, Object b) { 1077aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin FixedDecimal a1 = (FixedDecimal) a; 1078aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin FixedDecimal b1 = (FixedDecimal) b; 1079aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin return a1.equals(b1); 1080aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin } 1081aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin } 1082aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin 1083f86f25d102340da66b9c7cb6b2d5ecdc0de43ecfFredrik Roubert @Test 1084aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin public void TestSerial() { 1085aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin PluralRules s = PluralRules.forLocale(ULocale.ENGLISH); 1086aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin checkStreamingEquality(s); 1087aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin } 1088aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin 1089aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin public void checkStreamingEquality(PluralRules s) { 1090aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin try { 1091aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin ByteArrayOutputStream byteOut = new ByteArrayOutputStream(); 1092aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin ObjectOutputStream objectOutputStream = new ObjectOutputStream(byteOut); 1093aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin objectOutputStream.writeObject(s); 1094aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin objectOutputStream.close(); 1095aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin byte[] contents = byteOut.toByteArray(); 1096aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin logln(s.getClass() + ": " + showBytes(contents)); 1097aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin ByteArrayInputStream byteIn = new ByteArrayInputStream(contents); 1098aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin ObjectInputStream objectInputStream = new ObjectInputStream(byteIn); 1099aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin Object obj = objectInputStream.readObject(); 1100aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin assertEquals("Streamed Object equals ", s, obj); 1101aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin } catch (Exception e) { 1102aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin assertNull("TestSerial", e); 1103aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin } 1104aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin } 1105aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin 1106aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin /** 1107aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin * @param contents 1108aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin * @return 1109aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin */ 1110aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin private String showBytes(byte[] contents) { 1111aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin StringBuilder b = new StringBuilder('['); 1112aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin for (int i = 0; i < contents.length; ++i) { 1113aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin int item = contents[i] & 0xFF; 1114aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin if (item >= 0x20 && item <= 0x7F) { 1115aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin b.append((char) item); 1116aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin } else { 1117aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin b.append('(').append(Utility.hex(item, 2)).append(')'); 1118aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin } 1119aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin } 1120aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin return b.append(']').toString(); 1121aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin } 1122aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin 1123f86f25d102340da66b9c7cb6b2d5ecdc0de43ecfFredrik Roubert @Test 1124aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin public void testJavaLocaleFactory() { 1125aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin PluralRules rulesU0 = PluralRules.forLocale(ULocale.FRANCE); 1126aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin PluralRules rulesJ0 = PluralRules.forLocale(Locale.FRANCE); 1127aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin assertEquals("forLocale()", rulesU0, rulesJ0); 1128aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin 1129aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin PluralRules rulesU1 = PluralRules.forLocale(ULocale.FRANCE, PluralType.ORDINAL); 1130aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin PluralRules rulesJ1 = PluralRules.forLocale(Locale.FRANCE, PluralType.ORDINAL); 1131aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin assertEquals("forLocale() with type", rulesU1, rulesJ1); 1132aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin } 1133aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin} 1134