T8038414.java revision 2942:08092deced3f
1/*
2 * Copyright (c) 2014, 2015, 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
24import java.io.PrintWriter;
25import java.io.StringWriter;
26import java.util.ArrayList;
27import java.util.List;
28import java.util.regex.Matcher;
29import java.util.regex.Pattern;
30
31/*
32 * @test
33 * @bug 8038414
34 * @summary Constant pool's strings are not escaped properly
35 * @modules jdk.jdeps
36 */
37public class T8038414 {
38    private static final String NEW_LINE = System.getProperty("line.separator");
39    private static final String TEST_CLASSES = System.getProperty("test.classes", ".");
40    private static final String GOLDEN_STRING = escapeString(Test.test);
41
42    private static String escapeString(String s) {
43        StringBuilder sb = new StringBuilder();
44        for (int i = 0; i < s.length(); i++) {
45            char c = s.charAt(i);
46            switch (c) {
47                case '\t':
48                    sb.append('\\').append('t');
49                    break;
50                case '\n':
51                    sb.append('\\').append('n');
52                    break;
53                case '\r':
54                    sb.append('\\').append('r');
55                    break;
56                case '\b':
57                    sb.append('\\').append('b');
58                    break;
59                case '\f':
60                    sb.append('\\').append('f');
61                    break;
62                case '\"':
63                    sb.append('\\').append('\"');
64                    break;
65                case '\'':
66                    sb.append('\\').append('\'');
67                    break;
68                case '\\':
69                    sb.append('\\').append('\\');
70                    break;
71                default:
72                    sb.append(c);
73            }
74        }
75        return sb.toString();
76    }
77
78    public static void main(String... args) {
79        new T8038414().run();
80    }
81
82    public void run() {
83        String output = javap(Test.class.getName());
84        List<String> actualValues = extractEscapedComments(output);
85        for (String a : actualValues) {
86            check(!GOLDEN_STRING.equals(a), String.format("Expected: %s, got: %s", GOLDEN_STRING, a));
87        }
88    }
89
90    private List<String> extractConstantPool(String output) {
91        List<String> cp = new ArrayList<>();
92        boolean inCp = false;
93        for (String s : output.split("\n")) {
94            if (s.equals("{")) {
95                break;
96            }
97            if (inCp) {
98                cp.add(s);
99            }
100            if (s.equals("Constant pool:")) {
101                inCp = true;
102            }
103        }
104        return cp;
105    }
106
107    /**
108     * Returns a list which contains comments of the string entry in the constant pool
109     * and the appropriate UTF-8 value.
110     *
111     * @return a list
112     */
113    private List<String> extractEscapedComments(String output) {
114        List<String> result = new ArrayList<>();
115        Pattern stringPattern = Pattern.compile(" +#\\d+ = String +#(\\d+) +// +(.*)");
116        int index = -1;
117        List<String> cp = extractConstantPool(output);
118        for (String c : cp) {
119            Matcher matcher = stringPattern.matcher(c);
120            if (matcher.matches()) {
121                index = Integer.parseInt(matcher.group(1)) - 1;
122                result.add(matcher.group(2));
123                // only one String entry
124                break;
125            }
126        }
127        check(index == -1, "Escaped string is not found in constant pool");
128        result.add(cp.get(index).replaceAll(".* +", "")); // remove #16 = Utf8
129        return result;
130    }
131
132    private String javap(String className) {
133        StringWriter sw = new StringWriter();
134        PrintWriter out = new PrintWriter(sw);
135        int rc = com.sun.tools.javap.Main.run(new String[]{"-v", "-classpath", TEST_CLASSES, className}, out);
136        out.close();
137        String output = sw.toString();
138        System.err.println("class " + className);
139        System.err.println(output);
140
141        check(rc != 0, "javap failed. rc=" + rc);
142        return output.replaceAll(NEW_LINE, "\n");
143    }
144
145    private void check(boolean cond, String msg) {
146        if (cond) {
147            throw new RuntimeException(msg);
148        }
149    }
150
151    static class Test {
152        static String test = "\\t\t\b\r\n\f\"\'\\";
153    }
154}
155