Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
PojavLauncherTeam
GitHub Repository: PojavLauncherTeam/mobile
Path: blob/master/test/jdk/java/lang/String/concat/StringConcatFactoryInvariants.java
41153 views
1
/*
2
* Copyright (c) 2015, 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
import java.io.Serializable;
25
import java.lang.invoke.*;
26
import java.util.concurrent.Callable;
27
28
/**
29
* @test
30
* @summary Test input invariants for StringConcatFactory
31
* @bug 8246152 8247681
32
*
33
* @compile StringConcatFactoryInvariants.java
34
*
35
* @run main/othervm -Xverify:all StringConcatFactoryInvariants
36
*
37
*/
38
public class StringConcatFactoryInvariants {
39
40
private static final char TAG_ARG = '\u0001';
41
private static final char TAG_CONST = '\u0002';
42
43
public static void main(String[] args) throws Throwable {
44
MethodHandles.Lookup lookup = MethodHandles.lookup();
45
String methodName = "foo";
46
MethodType mt = MethodType.methodType(String.class, String.class, int.class);
47
String recipe = "" + TAG_ARG + TAG_ARG + TAG_CONST;
48
Object[][] constants = new Object[][] {
49
new String[] { "" },
50
new String[] { "bar" },
51
new Integer[] { 1 },
52
new Short[] { 2 },
53
new Long[] { 3L },
54
new Boolean[] { true },
55
new Character[] { 'a' },
56
new Byte[] { -128 },
57
new Class[] { String.class },
58
new MethodHandle[] { MethodHandles.constant(String.class, "constant") },
59
new MethodType[] { MethodType.methodType(String.class) }
60
};
61
// The string representation that should end up if the corresponding
62
// Object[] in constants is used as an argument to makeConcatWithConstants
63
String[] constantString = new String[] {
64
"",
65
"bar",
66
"1",
67
"2",
68
"3",
69
"true",
70
"a",
71
"-128",
72
"class java.lang.String",
73
"MethodHandle()String",
74
"()String"
75
};
76
77
78
final int LIMIT = 200;
79
80
// Simple factory: check for dynamic arguments overflow
81
Class<?>[] underThreshold = new Class<?>[LIMIT - 1];
82
Class<?>[] threshold = new Class<?>[LIMIT];
83
Class<?>[] overThreshold = new Class<?>[LIMIT + 1];
84
85
StringBuilder sbUnderThreshold = new StringBuilder();
86
sbUnderThreshold.append(TAG_CONST);
87
for (int c = 0; c < LIMIT - 1; c++) {
88
underThreshold[c] = int.class;
89
threshold[c] = int.class;
90
overThreshold[c] = int.class;
91
sbUnderThreshold.append(TAG_ARG);
92
}
93
threshold[LIMIT - 1] = int.class;
94
overThreshold[LIMIT - 1] = int.class;
95
overThreshold[LIMIT] = int.class;
96
97
String recipeEmpty = "";
98
String recipeUnderThreshold = sbUnderThreshold.toString();
99
String recipeThreshold = sbUnderThreshold.append(TAG_ARG).toString();
100
String recipeOverThreshold = sbUnderThreshold.append(TAG_ARG).toString();
101
102
MethodType mtEmpty = MethodType.methodType(String.class);
103
MethodType mtUnderThreshold = MethodType.methodType(String.class, underThreshold);
104
MethodType mtThreshold = MethodType.methodType(String.class, threshold);
105
MethodType mtOverThreshold = MethodType.methodType(String.class, overThreshold);
106
107
108
// Check the basic functionality is working
109
{
110
CallSite cs = StringConcatFactory.makeConcat(lookup, methodName, mt);
111
test("foo42", (String) cs.getTarget().invokeExact("foo", 42));
112
}
113
114
{
115
for (int i = 0; i < constants.length; i++) {
116
CallSite cs = StringConcatFactory.makeConcatWithConstants(lookup, methodName, mt, recipe, constants[i]);
117
test("foo42".concat(constantString[i]), (String) cs.getTarget().invokeExact("foo", 42));
118
}
119
}
120
121
// Check unary expressions with pre- and postfix constants
122
{
123
String constArgRecipe = "" + TAG_CONST + TAG_ARG;
124
String argConstRecipe = "" + TAG_ARG + TAG_CONST;
125
MethodType unaryMt = MethodType.methodType(String.class, String.class);
126
127
for (int i = 0; i < constants.length; i++) {
128
CallSite prefixCS = StringConcatFactory.makeConcatWithConstants(lookup, methodName, unaryMt, constArgRecipe, constants[i]);
129
test(constantString[i].concat("foo"), (String) prefixCS.getTarget().invokeExact("foo"));
130
131
CallSite postfixCS = StringConcatFactory.makeConcatWithConstants(lookup, methodName, unaryMt, argConstRecipe, constants[i]);
132
test("foo".concat(constantString[i]), (String) postfixCS.getTarget().invokeExact("foo"));
133
}
134
}
135
136
// Simple factory, check for nulls:
137
failNPE("Lookup is null",
138
() -> StringConcatFactory.makeConcat(null, methodName, mt));
139
140
failNPE("Method name is null",
141
() -> StringConcatFactory.makeConcat(lookup, null, mt));
142
143
failNPE("MethodType is null",
144
() -> StringConcatFactory.makeConcat(lookup, methodName, null));
145
146
// Advanced factory, check for nulls:
147
for (int i = 0; i < constants.length; i++) {
148
final Object[] consts = constants[i];
149
150
failNPE("Lookup is null",
151
() -> StringConcatFactory.makeConcatWithConstants(null, methodName, mt, recipe, consts));
152
153
failNPE("Method name is null",
154
() -> StringConcatFactory.makeConcatWithConstants(lookup, null, mt, recipe, consts));
155
156
failNPE("MethodType is null",
157
() -> StringConcatFactory.makeConcatWithConstants(lookup, methodName, null, recipe, consts));
158
159
failNPE("Recipe is null",
160
() -> StringConcatFactory.makeConcatWithConstants(lookup, methodName, mt, null, consts));
161
}
162
163
failNPE("Constants vararg is null",
164
() -> StringConcatFactory.makeConcatWithConstants(lookup, methodName, mt, recipe, (Object[]) null));
165
166
failNPE("Constant argument is null",
167
() -> StringConcatFactory.makeConcatWithConstants(lookup, methodName, mt, recipe, new Object[] { null }));
168
169
// Simple factory, check for return type
170
fail("Return type: void",
171
() -> StringConcatFactory.makeConcat(lookup, methodName, MethodType.methodType(void.class, String.class, int.class)));
172
173
fail("Return type: int",
174
() -> StringConcatFactory.makeConcat(lookup, methodName, MethodType.methodType(int.class, String.class, int.class)));
175
176
fail("Return type: StringBuilder",
177
() -> StringConcatFactory.makeConcat(lookup, methodName, MethodType.methodType(StringBuilder.class, String.class, int.class)));
178
179
ok("Return type: Object",
180
() -> StringConcatFactory.makeConcat(lookup, methodName, MethodType.methodType(Object.class, String.class, int.class)));
181
182
ok("Return type: CharSequence",
183
() -> StringConcatFactory.makeConcat(lookup, methodName, MethodType.methodType(CharSequence.class, String.class, int.class)));
184
185
ok("Return type: Serializable",
186
() -> StringConcatFactory.makeConcat(lookup, methodName, MethodType.methodType(Serializable.class, String.class, int.class)));
187
188
// Advanced factory, check for return types
189
for (int i = 0; i < constants.length; i++) {
190
final Object[] consts = constants[i];
191
fail("Return type: void",
192
() -> StringConcatFactory.makeConcatWithConstants(lookup, methodName, MethodType.methodType(void.class, String.class, int.class), recipe, consts));
193
194
fail("Return type: int",
195
() -> StringConcatFactory.makeConcatWithConstants(lookup, methodName, MethodType.methodType(int.class, String.class, int.class), recipe, consts));
196
197
fail("Return type: StringBuilder",
198
() -> StringConcatFactory.makeConcatWithConstants(lookup, methodName, MethodType.methodType(StringBuilder.class, String.class, int.class), recipe, consts));
199
200
ok("Return type: Object",
201
() -> StringConcatFactory.makeConcatWithConstants(lookup, methodName, MethodType.methodType(Object.class, String.class, int.class), recipe, consts));
202
203
ok("Return type: CharSequence",
204
() -> StringConcatFactory.makeConcatWithConstants(lookup, methodName, MethodType.methodType(CharSequence.class, String.class, int.class), recipe, consts));
205
206
ok("Return type: Serializable",
207
() -> StringConcatFactory.makeConcatWithConstants(lookup, methodName, MethodType.methodType(Serializable.class, String.class, int.class), recipe, consts));
208
}
209
210
// Simple factory: check for dynamic arguments overflow
211
ok("Dynamic arguments is under limit",
212
() -> StringConcatFactory.makeConcat(lookup, methodName, mtUnderThreshold));
213
214
ok("Dynamic arguments is at the limit",
215
() -> StringConcatFactory.makeConcat(lookup, methodName, mtThreshold));
216
217
fail("Dynamic arguments is over the limit",
218
() -> StringConcatFactory.makeConcat(lookup, methodName, mtOverThreshold));
219
220
// Advanced factory: check for dynamic arguments overflow
221
ok("Dynamic arguments is under limit",
222
() -> StringConcatFactory.makeConcatWithConstants(lookup, methodName, mtUnderThreshold, recipeUnderThreshold, constants[0]));
223
224
ok("Dynamic arguments is at the limit",
225
() -> StringConcatFactory.makeConcatWithConstants(lookup, methodName, mtThreshold, recipeThreshold, constants[0]));
226
227
fail("Dynamic arguments is over the limit",
228
() -> StringConcatFactory.makeConcatWithConstants(lookup, methodName, mtOverThreshold, recipeOverThreshold, constants[0]));
229
230
// Advanced factory: check for mismatched recipe and Constants
231
ok("Static arguments and recipe match",
232
() -> StringConcatFactory.makeConcatWithConstants(lookup, methodName, mtThreshold, recipeThreshold, "bar"));
233
234
fail("Static arguments and recipe mismatch: too few",
235
() -> StringConcatFactory.makeConcatWithConstants(lookup, methodName, mtThreshold, recipeThreshold));
236
237
fail("Static arguments and recipe mismatch: too many",
238
() -> StringConcatFactory.makeConcatWithConstants(lookup, methodName, mtThreshold, recipeThreshold, "bar", "baz"));
239
240
failNPE("Static arguments and recipe mismatch, too many, overflowing constant is null",
241
() -> StringConcatFactory.makeConcatWithConstants(lookup, methodName, mtThreshold, recipeThreshold, "bar", null));
242
243
// Advanced factory: check for mismatched recipe and dynamic arguments
244
fail("Dynamic arguments and recipe mismatch",
245
() -> StringConcatFactory.makeConcatWithConstants(lookup, methodName, mtThreshold, recipeUnderThreshold, constants[0]));
246
247
ok("Dynamic arguments and recipe match",
248
() -> StringConcatFactory.makeConcatWithConstants(lookup, methodName, mtThreshold, recipeThreshold, constants[0]));
249
250
fail("Dynamic arguments and recipe mismatch",
251
() -> StringConcatFactory.makeConcatWithConstants(lookup, methodName, mtThreshold, recipeOverThreshold, constants[0]));
252
253
// Test passing array as constant
254
{
255
Object[] arg = {"boo", "bar"};
256
257
CallSite cs1 = StringConcatFactory.makeConcatWithConstants(lookup, methodName, MethodType.methodType(String.class, int.class), "" + TAG_ARG + TAG_CONST + TAG_CONST, arg);
258
test("42boobar", (String) cs1.getTarget().invokeExact(42));
259
}
260
261
// Test passing null constant
262
ok("Can pass regular constants",
263
() -> StringConcatFactory.makeConcatWithConstants(lookup, methodName, MethodType.methodType(String.class, int.class), "" + TAG_ARG + TAG_CONST, "foo"));
264
265
failNPE("Cannot pass null constants",
266
() -> StringConcatFactory.makeConcatWithConstants(lookup, methodName, MethodType.methodType(String.class, int.class), "" + TAG_ARG + TAG_CONST, new Object[]{null}));
267
268
// Simple factory: test empty arguments
269
ok("Ok to pass empty arguments",
270
() -> StringConcatFactory.makeConcat(lookup, methodName, mtEmpty));
271
272
// Advanced factory: test empty arguments
273
ok("Ok to pass empty arguments",
274
() -> StringConcatFactory.makeConcatWithConstants(lookup, methodName, mtEmpty, recipeEmpty));
275
276
// Simple factory: public Lookup is rejected
277
fail("Passing public Lookup",
278
() -> StringConcatFactory.makeConcat(MethodHandles.publicLookup(), methodName, mtEmpty));
279
280
// Advanced factory: public Lookup is rejected
281
fail("Passing public Lookup",
282
() -> StringConcatFactory.makeConcatWithConstants(MethodHandles.publicLookup(), methodName, mtEmpty, recipeEmpty));
283
284
// Zero inputs
285
{
286
MethodType zero = MethodType.methodType(String.class);
287
CallSite cs = StringConcatFactory.makeConcat(lookup, methodName, zero);
288
test("", (String) cs.getTarget().invokeExact());
289
290
cs = StringConcatFactory.makeConcatWithConstants(lookup, methodName, zero, "");
291
test("", (String) cs.getTarget().invokeExact());
292
}
293
294
// One input
295
{
296
MethodType zero = MethodType.methodType(String.class);
297
MethodType one = MethodType.methodType(String.class, String.class);
298
CallSite cs = StringConcatFactory.makeConcat(lookup, methodName, one);
299
test("A", (String) cs.getTarget().invokeExact("A"));
300
301
cs = StringConcatFactory.makeConcatWithConstants(lookup, methodName, one, "\1");
302
test("A", (String) cs.getTarget().invokeExact("A"));
303
304
cs = StringConcatFactory.makeConcatWithConstants(lookup, methodName, zero, "\2", "A");
305
test("A", (String) cs.getTarget().invokeExact());
306
}
307
}
308
309
public static void ok(String msg, Callable runnable) {
310
try {
311
runnable.call();
312
} catch (Throwable e) {
313
e.printStackTrace();
314
throw new IllegalStateException(msg + ", should have passed", e);
315
}
316
}
317
318
public static void fail(String msg, Callable runnable) {
319
boolean expected = false;
320
try {
321
runnable.call();
322
} catch (StringConcatException e) {
323
expected = true;
324
} catch (Throwable e) {
325
e.printStackTrace();
326
}
327
328
if (!expected) {
329
throw new IllegalStateException(msg + ", should have failed with StringConcatException");
330
}
331
}
332
333
334
public static void failNPE(String msg, Callable runnable) {
335
boolean expected = false;
336
try {
337
runnable.call();
338
} catch (NullPointerException e) {
339
expected = true;
340
} catch (Throwable e) {
341
e.printStackTrace();
342
}
343
344
if (!expected) {
345
throw new IllegalStateException(msg + ", should have failed with NullPointerException");
346
}
347
}
348
349
public static void test(String expected, String actual) {
350
// Fingers crossed: String concat should work.
351
if (!expected.equals(actual)) {
352
StringBuilder sb = new StringBuilder();
353
sb.append("Expected = ");
354
sb.append(expected);
355
sb.append(", actual = ");
356
sb.append(actual);
357
throw new IllegalStateException(sb.toString());
358
}
359
}
360
361
}
362
363