jdk

Форк
0
/
TestClassNameWarning.java 
241 строка · 8.1 Кб
1
/*
2
 * Copyright (c) 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 8170708
27
 * @summary javap -m <module> cannot read a module-info.class
28
 * @library /tools/lib
29
 * @enablePreview
30
 * @modules
31
 *      jdk.compiler/com.sun.tools.javac.api
32
 *      jdk.compiler/com.sun.tools.javac.main
33
 *      jdk.jdeps/com.sun.tools.javap
34
 * @build toolbox.JavacTask toolbox.JavapTask toolbox.ToolBox toolbox.TestRunner
35
 * @run main TestClassNameWarning
36
 */
37

38
import java.lang.constant.ClassDesc;
39
import java.nio.file.Files;
40
import java.nio.file.Path;
41
import java.nio.file.Paths;
42
import java.util.Arrays;
43
import java.util.List;
44
import java.util.regex.Pattern;
45
import java.util.stream.Collectors;
46

47

48
import java.lang.classfile.*;
49
import toolbox.JavacTask;
50
import toolbox.JavapTask;
51
import toolbox.Task;
52
import toolbox.TestRunner;
53
import toolbox.ToolBox;
54

55
public class TestClassNameWarning extends TestRunner {
56
    public static void main(String... args) throws Exception {
57
        new TestClassNameWarning().runTests(m -> new Object[] { Paths.get(m.getName()) });
58
    }
59

60
    private ToolBox tb = new ToolBox();
61

62
    TestClassNameWarning() {
63
        super(System.err);
64
    }
65

66
    /**
67
     * Baseline test for normal classes.
68
     */
69
    @Test
70
    public void testStandardClass(Path base) throws Exception {
71
        Path src = base.resolve("src");
72
        Path classes = Files.createDirectories(base.resolve("classes"));
73
        tb.writeJavaFiles(src, "class A { }");
74

75
        new JavacTask(tb)
76
                .outdir(classes.toString())
77
                .files(tb.findJavaFiles(src))
78
                .run()
79
                .writeAll();
80

81
        List<String> log = new JavapTask(tb)
82
                .classpath(classes.toString())
83
                .classes("A")
84
                .run()
85
                .writeAll()
86
                .getOutputLines(Task.OutputKind.DIRECT);
87

88
        checkOutput(log, false, "^(Warning|Error)");
89
        checkOutput(log, true, "class A");
90
    }
91

92
    /**
93
     * Test that module-info can be used to name the .class file
94
     * for a module declaration (i.e. ACC_MODULE, this_class == 0)
95
     * This is the primary test case for the bug as reported.
96
     */
97
    @Test
98
    public void testStandardModuleInfo(Path base) throws Exception {
99
        Path src = base.resolve("src");
100
        Path classes = Files.createDirectories(base.resolve("classes"));
101
        tb.writeJavaFiles(src, "module m { }");
102

103
        new JavacTask(tb)
104
                .outdir(classes.toString())
105
                .files(tb.findJavaFiles(src))
106
                .run()
107
                .writeAll();
108

109
        List<String> log = new JavapTask(tb)
110
                .options("--module-path", classes.toString(),
111
                        "--module", "m")
112
                .classes("module-info")
113
                .run()
114
                .writeAll()
115
                .getOutputLines(Task.OutputKind.DIRECT);
116

117
        checkOutput(log, false, "^(Warning|Error)");
118
        checkOutput(log, true, "module m");
119
    }
120

121
    /**
122
     * Test module-info can still be used to find a weirdly named
123
     * class equivalent to "class module-info { }" if that were legal in JLS.
124
     * Such a class file would arguably be legal in certain selected contexts.
125
     */
126
    @Test
127
    public void testLegacyModuleInfo(Path base) throws Exception {
128
        Path src = base.resolve("src");
129
        Path classes = Files.createDirectories(base.resolve("classes"));
130
        tb.writeJavaFiles(src, "class module_info { }");
131

132
        new JavacTask(tb)
133
                .outdir(classes.toString())
134
                .files(tb.findJavaFiles(src))
135
                .run()
136
                .writeAll();
137

138
        byte[] bytes = Files.readAllBytes(classes.resolve("module_info.class"));
139
        byte[] searchBytes = "module_info".getBytes("UTF-8");
140
        byte[] replaceBytes = "module-info".getBytes("UTF-8");
141
        for (int i = 0; i < bytes.length - searchBytes.length; i++) {
142
            if (Arrays.equals(bytes, i, i + searchBytes.length,
143
                    searchBytes, 0, searchBytes.length)) {
144
                System.arraycopy(replaceBytes, 0, bytes, i, replaceBytes.length);
145
            }
146
        }
147
        Files.write(classes.resolve("module-info.class"), bytes);
148

149
        List<String> log = new JavapTask(tb)
150
                .classpath(classes.toString())
151
                .options("-bootclasspath", "") // hide all system classes
152
                .classes("module-info")
153
                .run()
154
                .writeAll()
155
                .getOutputLines(Task.OutputKind.DIRECT);
156

157
        checkOutput(log, false, "^(Warning|Error)");
158
        checkOutput(log, true, "class module-info");
159
    }
160

161
    /**
162
     * Test an invalid class, with this_class == 0.
163
     */
164
    @Test
165
    public void testNoNameClass(Path base) throws Exception {
166
        Path src = base.resolve("src");
167
        Path classes = Files.createDirectories(base.resolve("classes"));
168
        tb.writeJavaFiles(src, "class A { }");
169

170
        new JavacTask(tb)
171
                .outdir(classes.toString())
172
                .files(tb.findJavaFiles(src))
173
                .run()
174
                .writeAll();
175
        ClassModel cm = ClassFile.of().parse(classes.resolve("A.class"));
176
        ClassFile.of().buildTo(
177
                classes.resolve("Z.class"),
178
                ClassDesc.of("0"), cb -> {
179
                    for (ClassElement ce : cm) {
180
                        cb.with(ce);
181
                    }
182
                }
183
        );
184

185
        List<String> log = new JavapTask(tb)
186
                .classpath(classes.toString())
187
                .classes("Z")
188
                .run()
189
                .writeAll()
190
                .getOutputLines(Task.OutputKind.DIRECT);
191

192
        checkOutput(log, true, "Warning:.*Z.class does not contain class Z");
193
    }
194

195
    /**
196
     * Test a class with unexpected contents.
197
     * This is the arguably the most common negative case.
198
     */
199
    @Test
200
    public void testWrongNameClass(Path base) throws Exception {
201
        Path src = base.resolve("src");
202
        Path classes = Files.createDirectories(base.resolve("classes"));
203
        tb.writeJavaFiles(src, "class A { }");
204

205
        new JavacTask(tb)
206
                .outdir(classes.toString())
207
                .files(tb.findJavaFiles(src))
208
                .run()
209
                .writeAll();
210

211
        Files.move(classes.resolve("A.class"), classes.resolve("B.class"));
212

213
        List<String> log = new JavapTask(tb)
214
                .classpath(classes.toString())
215
                .classes("B")
216
                .run()
217
                .writeAll()
218
                .getOutputLines(Task.OutputKind.DIRECT);
219

220
        checkOutput(log, true, "Warning:.*B.class does not contain class B");
221
    }
222

223
    /**
224
     * Check that the output does, or does not, contain lines matching a regex.
225
     */
226
    private void checkOutput(List<String> log, boolean expect, String regex) {
227
        Pattern p = Pattern.compile(regex);
228
        List<String> matches = log.stream()
229
                .filter(line -> p.matcher(line).find())
230
                .collect(Collectors.toList());
231
        if (expect) {
232
            if (matches.isEmpty()) {
233
                error("expected output not found: " + regex);
234
            }
235
        } else {
236
            if (!matches.isEmpty()) {
237
                error("unexpected output found: " + matches);
238
            }
239
        }
240
    }
241
}
242

Использование cookies

Мы используем файлы cookie в соответствии с Политикой конфиденциальности и Политикой использования cookies.

Нажимая кнопку «Принимаю», Вы даете АО «СберТех» согласие на обработку Ваших персональных данных в целях совершенствования нашего веб-сайта и Сервиса GitVerse, а также повышения удобства их использования.

Запретить использование cookies Вы можете самостоятельно в настройках Вашего браузера.