1/* GENERATED SOURCE. DO NOT MODIFY. */
2// © 2017 and later: Unicode, Inc. and others.
3// License & terms of use: http://www.unicode.org/copyright.html#License
4package android.icu.dev.test.number;
5
6import static org.junit.Assert.assertEquals;
7import static org.junit.Assert.assertTrue;
8
9import org.junit.Test;
10
11import android.icu.impl.SimpleFormatterImpl;
12import android.icu.impl.number.ConstantAffixModifier;
13import android.icu.impl.number.ConstantMultiFieldModifier;
14import android.icu.impl.number.CurrencySpacingEnabledModifier;
15import android.icu.impl.number.Modifier;
16import android.icu.impl.number.NumberStringBuilder;
17import android.icu.impl.number.SimpleModifier;
18import android.icu.text.DecimalFormatSymbols;
19import android.icu.text.NumberFormat;
20import android.icu.util.ULocale;
21import android.icu.testsharding.MainTestShard;
22
23@MainTestShard
24public class ModifierTest {
25    @Test
26    public void testConstantAffixModifier() {
27        assertModifierEquals(ConstantAffixModifier.EMPTY, 0, false, "|", "n");
28
29        Modifier mod1 = new ConstantAffixModifier("a��", "b", NumberFormat.Field.PERCENT, true);
30        assertModifierEquals(mod1, 3, true, "a��|b", "%%%n%");
31    }
32
33    @Test
34    public void testConstantMultiFieldModifier() {
35        NumberStringBuilder prefix = new NumberStringBuilder();
36        NumberStringBuilder suffix = new NumberStringBuilder();
37        Modifier mod1 = new ConstantMultiFieldModifier(prefix, suffix, true);
38        assertModifierEquals(mod1, 0, true, "|", "n");
39
40        prefix.append("a��", NumberFormat.Field.PERCENT);
41        suffix.append("b", NumberFormat.Field.CURRENCY);
42        Modifier mod2 = new ConstantMultiFieldModifier(prefix, suffix, true);
43        assertModifierEquals(mod2, 3, true, "a��|b", "%%%n$");
44
45        // Make sure the first modifier is still the same (that it stayed constant)
46        assertModifierEquals(mod1, 0, true, "|", "n");
47    }
48
49    @Test
50    public void testSimpleModifier() {
51        String[] patterns = { "{0}", "X{0}Y", "XX{0}YYY", "{0}YY", "XX��XX{0}" };
52        Object[][] outputs = { { "", 0, 0 }, { "a��bcde", 0, 0 }, { "a��bcde", 4, 4 }, { "a��bcde", 3, 5 } };
53        int[] prefixLens = { 0, 1, 2, 0, 6 };
54        String[][] expectedCharFields = { { "|", "n" }, { "X|Y", "%n%" }, { "XX|YYY", "%%n%%%" }, { "|YY", "n%%" },
55                { "XX��XX|", "%%%%%%n" } };
56        String[][] expecteds = { { "", "XY", "XXYYY", "YY", "XX��XX" },
57                { "a��bcde", "XYa��bcde", "XXYYYa��bcde", "YYa��bcde", "XX��XXa��bcde" },
58                { "a��bcde", "a��bXYcde", "a��bXXYYYcde", "a��bYYcde", "a��bXX��XXcde" },
59                { "a��bcde", "a��XbcYde", "a��XXbcYYYde", "a��bcYYde", "a��XX��XXbcde" } };
60        for (int i = 0; i < patterns.length; i++) {
61            String pattern = patterns[i];
62            String compiledPattern = SimpleFormatterImpl
63                    .compileToStringMinMaxArguments(pattern, new StringBuilder(), 1, 1);
64            Modifier mod = new SimpleModifier(compiledPattern, NumberFormat.Field.PERCENT, false);
65            assertModifierEquals(mod, prefixLens[i], false, expectedCharFields[i][0], expectedCharFields[i][1]);
66
67            // Test strange insertion positions
68            for (int j = 0; j < outputs.length; j++) {
69                NumberStringBuilder output = new NumberStringBuilder();
70                output.append((String) outputs[j][0], null);
71                mod.apply(output, (Integer) outputs[j][1], (Integer) outputs[j][2]);
72                String expected = expecteds[j][i];
73                String actual = output.toString();
74                assertEquals(expected, actual);
75            }
76        }
77    }
78
79    @Test
80    public void testCurrencySpacingEnabledModifier() {
81        DecimalFormatSymbols symbols = DecimalFormatSymbols.getInstance(ULocale.ENGLISH);
82        NumberStringBuilder prefix = new NumberStringBuilder();
83        NumberStringBuilder suffix = new NumberStringBuilder();
84        Modifier mod1 = new CurrencySpacingEnabledModifier(prefix, suffix, true, symbols);
85        assertModifierEquals(mod1, 0, true, "|", "n");
86
87        prefix.append("USD", NumberFormat.Field.CURRENCY);
88        Modifier mod2 = new CurrencySpacingEnabledModifier(prefix, suffix, true, symbols);
89        assertModifierEquals(mod2, 3, true, "USD|", "$$$n");
90
91        // Test the default currency spacing rules
92        NumberStringBuilder sb = new NumberStringBuilder();
93        sb.append("123", NumberFormat.Field.INTEGER);
94        NumberStringBuilder sb1 = new NumberStringBuilder(sb);
95        assertModifierEquals(mod2, sb1, 3, true, "USD\u00A0123", "$$$niii");
96
97        // Compare with the unsafe code path
98        NumberStringBuilder sb2 = new NumberStringBuilder(sb);
99        sb2.insert(0, "USD", NumberFormat.Field.CURRENCY);
100        CurrencySpacingEnabledModifier.applyCurrencySpacing(sb2, 0, 3, 6, 0, symbols);
101        assertTrue(sb1.toDebugString() + " vs " + sb2.toDebugString(), sb1.contentEquals(sb2));
102
103        // Test custom patterns
104        // The following line means that the last char of the number should be a | (rather than a digit)
105        symbols.setPatternForCurrencySpacing(DecimalFormatSymbols.CURRENCY_SPC_SURROUNDING_MATCH, true, "[|]");
106        suffix.append("XYZ", NumberFormat.Field.CURRENCY);
107        Modifier mod3 = new CurrencySpacingEnabledModifier(prefix, suffix, true, symbols);
108        assertModifierEquals(mod3, 3, true, "USD|\u00A0XYZ", "$$$nn$$$");
109    }
110
111    @Test
112    public void testCurrencySpacingPatternStability() {
113        // This test checks for stability of the currency spacing patterns in CLDR.
114        // For efficiency, ICU caches the most common currency spacing UnicodeSets.
115        // If this test starts failing, please update the method #getUnicodeSet() in
116        // BOTH CurrencySpacingEnabledModifier.java AND in C++.
117        DecimalFormatSymbols dfs = DecimalFormatSymbols.getInstance(new ULocale("en-US"));
118        assertEquals(
119                "[:^S:]",
120                dfs.getPatternForCurrencySpacing(DecimalFormatSymbols.CURRENCY_SPC_CURRENCY_MATCH, true));
121        assertEquals(
122                "[:^S:]",
123                dfs.getPatternForCurrencySpacing(DecimalFormatSymbols.CURRENCY_SPC_CURRENCY_MATCH, false));
124        assertEquals(
125                "[:digit:]",
126                dfs.getPatternForCurrencySpacing(DecimalFormatSymbols.CURRENCY_SPC_SURROUNDING_MATCH, true));
127        assertEquals(
128                "[:digit:]",
129                dfs.getPatternForCurrencySpacing(DecimalFormatSymbols.CURRENCY_SPC_SURROUNDING_MATCH, false));
130    }
131
132    private void assertModifierEquals(
133            Modifier mod,
134            int expectedPrefixLength,
135            boolean expectedStrong,
136            String expectedChars,
137            String expectedFields) {
138        NumberStringBuilder sb = new NumberStringBuilder();
139        sb.appendCodePoint('|', null);
140        assertModifierEquals(mod, sb, expectedPrefixLength, expectedStrong, expectedChars, expectedFields);
141    }
142
143    private void assertModifierEquals(
144            Modifier mod,
145            NumberStringBuilder sb,
146            int expectedPrefixLength,
147            boolean expectedStrong,
148            String expectedChars,
149            String expectedFields) {
150        int oldCount = sb.codePointCount();
151        mod.apply(sb, 0, oldCount);
152        assertEquals("Prefix length on " + sb, expectedPrefixLength, mod.getPrefixLength());
153        assertEquals("Strong on " + sb, expectedStrong, mod.isStrong());
154        if (!(mod instanceof CurrencySpacingEnabledModifier)) {
155            assertEquals("Code point count equals actual code point count",
156                    sb.codePointCount() - oldCount, mod.getCodePointCount());
157        }
158        assertEquals("<NumberStringBuilder [" + expectedChars + "] [" + expectedFields + "]>", sb.toDebugString());
159    }
160}
161