File: PatternsTest.java

package info (click to toggle)
openjdk-25 25%2B36-1
  • links: PTS, VCS
  • area: main
  • in suites: forky, sid
  • size: 825,288 kB
  • sloc: java: 5,585,424; cpp: 1,333,938; xml: 1,321,242; ansic: 487,993; asm: 404,003; objc: 21,088; sh: 15,102; javascript: 13,265; python: 8,319; makefile: 2,520; perl: 357; awk: 351; pascal: 103; exp: 83; sed: 72; jsp: 24
file content (165 lines) | stat: -rw-r--r-- 7,577 bytes parent folder | download | duplicates (4)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
/*
 * Copyright (c) 2023, 2024, Oracle and/or its affiliates. All rights reserved.
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * This code is free software; you can redistribute it and/or modify it
 * under the terms of the GNU General Public License version 2 only, as
 * published by the Free Software Foundation.
 *
 * This code is distributed in the hope that it will be useful, but WITHOUT
 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
 * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
 * version 2 for more details (a copy is included in the LICENSE file that
 * accompanied this code).
 *
 * You should have received a copy of the GNU General Public License version
 * 2 along with this work; if not, write to the Free Software Foundation,
 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
 *
 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
 * or visit www.oracle.com if you need additional information or have any
 * questions.
 */

/*
 * @test
 * @bug 6285888 6801704 8325898
 * @summary Test the expected behavior for a wide range of patterns (both
 *          correct and incorrect). This test documents the behavior of incorrect
 *          ChoiceFormat patterns either throwing an exception, or discarding
 *          the incorrect portion of a pattern.
 * @run junit PatternsTest
 */

import org.junit.jupiter.api.Test;
import org.junit.jupiter.params.ParameterizedTest;
import org.junit.jupiter.params.provider.Arguments;
import org.junit.jupiter.params.provider.MethodSource;

import java.text.ChoiceFormat;

import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertThrows;
import static org.junit.jupiter.params.provider.Arguments.arguments;

public class PatternsTest {

    private static final String ERR1 =
            "Each interval must contain a number before a format";
    private static final String ERR2 =
            "Incorrect order of intervals, must be in ascending order";

    // Check that some valid patterns do not throw an exception. Check
    // them against the expected values they should be formatted as.
    @ParameterizedTest
    @MethodSource
    public void validPatternsTest(String pattern, String[] expectedValues) {
        var fmt = new ChoiceFormat(pattern);
        for (int i=1; i<=expectedValues.length; i++) {
            assertEquals(expectedValues[i-1], fmt.format(i),
                    String.format("ChoiceFormat formatted %s incorrectly:", i));
        }
    }

    // Valid patterns ranging from normal appearing to odd. These should not
    // throw an exception or discard any portions of the pattern.
    private static Arguments[] validPatternsTest() {
        return new Arguments[] {
                // Multi pattern with trailing empty string Format
                arguments("1#foo|2#bar|3#", new String[]{"foo", "bar", ""}),
                // Multi patten with trailing '|'
                arguments("1#foo|2#bar|", new String[]{"foo", "bar"}),
                // Using a '>' (not a Relation) within a Format
                arguments("1#foo|2#bar>", new String[]{"foo", "bar>"}),
                // Standard Multi Pattern
                arguments("1#foo|2#bar", new String[]{"foo", "bar"}),
                // Same numerical value Limits, different Relations
                arguments("1#foo|1<baz", new String[]{"foo", "baz"}),
                // Standard Single Pattern
                arguments("1#foo", new String[]{"foo"}),
                // Single pattern with empty string Format
                arguments("1#", new String[]{""})
        };
    }

    // Check that the incorrect pattern throws an IAE with the desired error msg
    // This also tests applyPattern, as the ChoiceFormat constructor calls applyPattern
    @ParameterizedTest
    @MethodSource
    public void invalidPatternsThrowsTest(String pattern, String errMsg) {
        var ex = assertThrows(IllegalArgumentException.class,
                () -> new ChoiceFormat(pattern));
        assertEquals(errMsg, ex.getMessage());
    }

    // Variety of patterns that break the ChoiceFormat pattern syntax and throw
    // an exception.
    private static Arguments[] invalidPatternsThrowsTest() {
        return new Arguments[] {
                arguments("#", ERR1), // Only relation
                arguments("#foo", ERR1), // No Limit
                arguments("0#foo|#|1#bar", ERR1), // Missing Relation in SubPattern
                arguments("#|", ERR1), // Missing Limit
                arguments("##|", ERR1), // Double Relations
                arguments("0#test|#", ERR1), // SubPattern missing Limit
                arguments("0#foo|3#bar|1#baz", ERR2), // Non-ascending Limits

                // No longer throw IAE after 6285888, as relational symbols
                // can now be used within the Format segment.
                // arguments("0#foo1#", ERR1), // SubPattern not separated by '|'
                // arguments("0#foo#", ERR1), // Using a Relation in a format
        };
    }

    // Check that the incorrect pattern discards the trailing incorrect portion.
    // These incorrect patterns should ideally throw an exception, but for
    // behavioral compatibility reasons do not.
    @ParameterizedTest
    @MethodSource
    public void invalidPatternsDiscardedTest(String brokenPattern, String actualPattern) {
        var cf1 = new ChoiceFormat(brokenPattern);
        var cf2 = new ChoiceFormat(actualPattern);
        assertEquals(cf2, cf1,
                String.format("Expected %s, but got %s", cf2.toPattern(), cf1.toPattern()));
    }

    // Variety of incorrect patterns with the actual expected pattern
    // after discarding occurs.
    private static Arguments[] invalidPatternsDiscardedTest() {
        return new Arguments[] {
                // Incomplete SubPattern (limit only) at end of Pattern
                arguments("1#bar|2", "1#bar"),
                // Incomplete SubPattern at the end of the Pattern
                arguments("0#foo|1#bar|baz", "0#foo|1#bar"),
                // Incomplete SubPattern with trailing | at the end of the Pattern
                // Prior to 6801704, it created the broken "0#foo|1#bar|1#"
                // which caused formatting 1 to return an empty string
                arguments("0#foo|1#bar|baz|", "0#foo|1#bar"),
                // Same as previous, with additional incomplete subPatterns
                arguments("0#foo|1#bar|baz|quux", "0#foo|1#bar"),

                // --- These throw an ArrayIndexOutOfBoundsException
                // when attempting to format with them as the incomplete patterns
                // are discarded, initializing the cFmt with empty limits and formats ---
                // SubPattern with only a Limit (which is interpreted as a Format)
                arguments("0", ""),
                // SubPattern with only a Format
                arguments("foo", ""),
                // empty string
                arguments("", "")
        };
    }

    // Calling format() with empty limits and formats
    // throws an ArrayIndexOutOfBoundsException
    @Test
    public void emptyLimitsAndFormatsTest() {
        var cf1 = new ChoiceFormat("");
        assertThrows(ArrayIndexOutOfBoundsException.class,
                () -> cf1.format(1));

        var cf2 = new ChoiceFormat(new double[]{}, new String[]{});
        assertThrows(ArrayIndexOutOfBoundsException.class,
                () -> cf2.format(2));
    }
}