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