1/*
2 * Copyright (c) 2008, Oracle and/or its affiliates. All rights reserved.
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4 *
5 * This code is free software; you can redistribute it and/or modify it
6 * under the terms of the GNU General Public License version 2 only, as
7 * published by the Free Software Foundation.
8 *
9 * This code is distributed in the hope that it will be useful, but WITHOUT
10 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
11 * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
12 * version 2 for more details (a copy is included in the LICENSE file that
13 * accompanied this code).
14 *
15 * You should have received a copy of the GNU General Public License version
16 * 2 along with this work; if not, write to the Free Software Foundation,
17 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
18 *
19 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
20 * or visit www.oracle.com if you need additional information or have any
21 * questions.
22 */
23
24/**
25 * @test
26 * @bug      4114080 8186803
27 * @summary  Make sure the euro converters, which are derived from
28 * existing converters, only differ from their parents at the expected
29 * code point.
30 * @modules jdk.charsets
31 */
32
33import java.text.*;
34import java.util.*;
35import java.io.*;
36
37/* Author: Alan Liu
38 * 7/14/98
39 */
40public class EuroConverter {
41    public static void main(String args[]) throws Exception {
42        boolean pass = true;
43        char[] map = new char[256]; // map for the encoding
44        byte[] bytes = new byte[1]; // scratch
45        char[] chars = new char[1]; // scratch
46        for (int i=0; i<DATA.length; ) {
47            String euroEnc = DATA[i++];
48            String parentEnc = DATA[i++];
49            System.out.println("Checking encoder " + euroEnc + " against " + parentEnc);
50            String currentEnc = parentEnc;
51
52            try {
53                // Fill map with parent values
54                for (int j=-128; j<128; ++j) {
55                    bytes[0] = (byte)j;
56                    char parentValue = new String(bytes, parentEnc).charAt(0);
57                    // NOTE: 0x25 doesn't round trip on the EBCDIC code pages,
58                    // so we don't check that code point in the sanity check.
59                    if (j != 0x0025) {
60                        chars[0] = parentValue;
61                        int parentRoundTrip = new String(chars).getBytes(parentEnc)[0];
62                        // This is a sanity check -- we aren't really testing the parent
63                        // encoder here.
64                        if (parentRoundTrip != j) {
65                            pass = false;
66                            System.out.println("Error: Encoder " + parentEnc +
67                                           " fails round-trip: " + j +
68                                           " -> \\u" + Integer.toHexString(parentValue) +
69                                           " -> " + parentRoundTrip);
70                        }
71                    }
72                    map[(j+0x100)&0xFF] = parentValue;
73                }
74
75                // Modify map with new expected values.  Each pair has code point, parent value, euro value.
76                // Terminated by null.
77                while (DATA[i] != null) {
78                    int codePoint = Integer.valueOf(DATA[i++], 16).intValue();
79                    char expectedParentValue = DATA[i++].charAt(0);
80                    char expectedEuroValue = DATA[i++].charAt(0);
81                    // This is a sanity check -- we aren't really testing the parent
82                    // encoder here.
83                    if (map[codePoint] != expectedParentValue) {
84                        pass = false;
85                        System.out.println("Error: Encoder " + parentEnc +
86                                           " " + Integer.toHexString(codePoint) + " -> \\u" +
87                                           Integer.toHexString(map[codePoint]) + ", expected \\u" +
88                                           Integer.toHexString(expectedParentValue));
89                    }
90                    // Fill in new expected value
91                    map[codePoint] = expectedEuroValue;
92                }
93                ++i; // Skip over null at end of set
94
95                // Now verify the euro encoder
96                currentEnc = euroEnc;
97                for (int j=-128; j<128; ++j) {
98                    bytes[0] = (byte)j;
99                    char euroValue = new String(bytes, euroEnc).charAt(0);
100                    chars[0] = euroValue;
101                    // NOTE: 0x25 doesn't round trip on the EBCDIC code pages,
102                    // so we don't check that code point in the sanity check.
103                    if (j != 0x0025) {
104                        int euroRoundTrip = new String(chars).getBytes(euroEnc)[0];
105                        if (euroRoundTrip != j) {
106                            pass = false;
107                            System.out.println("Error: Encoder " + euroEnc +
108                                           " fails round-trip at " + j);
109                        }
110                    }
111                    // Compare against the map
112                    if (euroValue != map[(j+0x100)&0xFF]) {
113                        pass = false;
114                        System.out.println("Error: Encoder " + euroEnc +
115                                           " " + Integer.toHexString((j+0x100)&0xFF) + " -> \\u" +
116                                           Integer.toHexString(euroValue) + ", expected \\u" +
117                                           Integer.toHexString(map[(j+0x100)&0xFF]));
118                    }
119                }
120            } catch (UnsupportedEncodingException e) {
121                System.out.println("Unsupported encoding " + currentEnc);
122                pass = false;
123                while (i < DATA.length && DATA[i] != null) ++i;
124                ++i; // Skip over null
125            }
126        }
127        if (!pass) {
128            throw new RuntimeException("Bug 4114080 - Euro encoder test failed");
129        }
130    }
131    static String[] DATA = {
132        // New converter, parent converter, [ code point that changed, parent code point value,
133        // euro code point value ], null
134        // Any number of changed code points may be specified, including zero.
135        "ISO8859_15_FDIS", "ISO8859_1",
136            "A4", "\u00A4", "\u20AC",
137            "A6", "\u00A6", "\u0160",
138            "A8", "\u00A8", "\u0161",
139            "B4", "\u00B4", "\u017D",
140            "B8", "\u00B8", "\u017E",
141            "BC", "\u00BC", "\u0152",
142            "BD", "\u00BD", "\u0153",
143            "BE", "\u00BE", "\u0178",
144            null,
145        // 923 is IBM's name for ISO 8859-15; make sure they're identical
146        "Cp923", "ISO8859_15_FDIS", null,
147        "Cp858", "Cp850", "D5", "\u0131", "\u20AC", null,
148        "Cp1140", "Cp037", "9F", "\u00A4", "\u20AC", null,
149        "Cp1141", "Cp273", "9F", "\u00A4", "\u20AC", null,
150        "Cp1142", "Cp277", "5A", "\u00A4", "\u20AC", null,
151        "Cp1143", "Cp278", "5A", "\u00A4", "\u20AC", null,
152        "Cp1144", "Cp280", "9F", "\u00A4", "\u20AC", null,
153        "Cp1145", "Cp284", "9F", "\u00A4", "\u20AC", null,
154        "Cp1146", "Cp285", "9F", "\u00A4", "\u20AC", null,
155        "Cp1147", "Cp297", "9F", "\u00A4", "\u20AC", null,
156        "Cp1148", "Cp500", "9F", "\u00A4", "\u20AC", null,
157        "Cp1149", "Cp871", "9F", "\u00A4", "\u20AC", null,
158    };
159}
160