Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
PojavLauncherTeam
GitHub Repository: PojavLauncherTeam/mobile
Path: blob/master/test/jdk/java/lang/StringBuffer/TestSynchronization.java
41149 views
1
/*
2
* Copyright (c) 2012, 2013, 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
/* @test
25
* @bug 6206780
26
* @summary Test that all public unsynchronized methods of StringBuffer are either directly or indirectly synchronized
27
*/
28
import java.lang.reflect.Constructor;
29
import java.lang.reflect.InvocationTargetException;
30
import java.lang.reflect.Method;
31
import java.lang.reflect.Modifier;
32
import java.util.ArrayList;
33
import java.util.Arrays;
34
import java.util.List;
35
36
/**
37
* TestSynchronization tests whether synchronized methods calls on an object
38
* result in synchronized calls. Note that this may not test all cases desired.
39
* It only tests whether some synchronization has occurred on the object during
40
* the call chain, and can't tell whether the object was locked across all
41
* operations that have been performed on the object.
42
*/
43
public class TestSynchronization {
44
45
/**
46
* Define parameters used in methods of StringBuffer - admittedly a bit of
47
* hack but 'purpose-built' for StringBuffer. Something more general could
48
* probably be developed if the test needs to be more widely adopted.
49
* <p/>
50
* boolean char char[] int double float long Object CharSequence String
51
* StringBuffer StringBuilder
52
* <p/>
53
*/
54
private static final boolean BOOLEAN_VAL = true;
55
private static final char CHAR_VAL = 'x';
56
private static final char[] CHAR_ARRAY_VAL = {'c', 'h', 'a', 'r', 'a', 'r',
57
'r', 'a', 'y'};
58
private static final int INT_VAL = 1;
59
private static final double DOUBLE_VAL = 1.0d;
60
private static final float FLOAT_VAL = 1.0f;
61
private static final long LONG_VAL = 1L;
62
private static final Object OBJECT_VAL = new Object();
63
private static final String STRING_VAL = "String value";
64
private static final StringBuilder STRING_BUILDER_VAL =
65
new StringBuilder("StringBuilder value");
66
private static final StringBuffer STRING_BUFFER_VAL =
67
new StringBuffer("StringBuffer value");
68
private static final CharSequence[] CHAR_SEQUENCE_VAL = {STRING_VAL,
69
STRING_BUILDER_VAL, STRING_BUFFER_VAL};
70
71
public static void main(String... args) throws Exception {
72
// First, test the tester
73
testClass(MyTestClass.class, /*
74
* self-test
75
*/ true);
76
// Finally, test StringBuffer
77
testClass(StringBuffer.class, /*
78
* self-test
79
*/ false);
80
}
81
82
/**
83
* Test all the public, unsynchronized methods of the given class. If
84
* isSelfTest is true, this is a self-test to ensure that the test program
85
* itself is working correctly. Should help ensure correctness of this
86
* program if it changes.
87
* <p/>
88
* @param aClass - the class to test
89
* @param isSelfTest - true if this is the special self-test class
90
* @throws SecurityException
91
*/
92
private static void testClass(Class<?> aClass, boolean isSelfTest) throws
93
Exception {
94
// Get all unsynchronized public methods via reflection. We don't need
95
// to test synchronized methods. By definition. they are already doing
96
// the right thing.
97
List<Method> methods = Arrays.asList(aClass.getDeclaredMethods());
98
for (Method m : methods) {
99
// skip synthetic methods, like default interface methods and lambdas
100
if (m.isSynthetic()) {
101
continue;
102
}
103
int modifiers = m.getModifiers();
104
if (Modifier.isPublic(modifiers)
105
&& !Modifier.isSynchronized(modifiers)) {
106
try {
107
testMethod(aClass, m);
108
} catch (TestFailedException e) {
109
if (isSelfTest) {
110
String methodName = e.getMethod().getName();
111
switch (methodName) {
112
case "should_pass":
113
throw new RuntimeException(
114
"Test failed: self-test failed. The 'should_pass' method did not pass the synchronization test. Check the test code.");
115
case "should_fail":
116
break;
117
default:
118
throw new RuntimeException(
119
"Test failed: something is amiss with the test. A TestFailedException was generated on a call to "
120
+ methodName + " which we didn't expect to test in the first place.");
121
}
122
} else {
123
throw new RuntimeException("Test failed: the method "
124
+ e.getMethod().toString()
125
+ " should be synchronized, but isn't.");
126
}
127
}
128
}
129
}
130
}
131
132
private static void invokeMethod(Class<?> aClass, final Method m,
133
final Object[] args) throws TestFailedException, Exception {
134
//System.out.println( "Invoking " + m.toString() + " with parameters " + Arrays.toString(args));
135
final Constructor<?> objConstructor;
136
Object obj = null;
137
138
objConstructor = aClass.getConstructor(String.class);
139
obj = objConstructor.newInstance("LeftPalindrome-emordnilaP-thgiR");
140
141
// test method m for synchronization
142
if (!isSynchronized(m, obj, args)) {
143
throw new TestFailedException(m);
144
}
145
}
146
147
private static void testMethod(Class<?> aClass, Method m) throws
148
Exception {
149
/*
150
* Construct call with arguments of the correct type. Note that the
151
* values are somewhat irrelevant. If the call actually succeeds, it
152
* means we aren't synchronized and the test has failed.
153
*/
154
Class<?>[] pTypes = m.getParameterTypes();
155
List<Integer> charSequenceArgs = new ArrayList<>();
156
Object[] args = new Object[pTypes.length];
157
for (int i = 0; i < pTypes.length; i++) {
158
// determine the type and create the corresponding actual argument
159
Class<?> pType = pTypes[i];
160
if (pType.equals(boolean.class)) {
161
args[i] = BOOLEAN_VAL;
162
} else if (pType.equals(char.class)) {
163
args[i] = CHAR_VAL;
164
} else if (pType.equals(int.class)) {
165
args[i] = INT_VAL;
166
} else if (pType.equals(double.class)) {
167
args[i] = DOUBLE_VAL;
168
} else if (pType.equals(float.class)) {
169
args[i] = FLOAT_VAL;
170
} else if (pType.equals(long.class)) {
171
args[i] = LONG_VAL;
172
} else if (pType.equals(Object.class)) {
173
args[i] = OBJECT_VAL;
174
} else if (pType.equals(StringBuilder.class)) {
175
args[i] = STRING_BUILDER_VAL;
176
} else if (pType.equals(StringBuffer.class)) {
177
args[i] = STRING_BUFFER_VAL;
178
} else if (pType.equals(String.class)) {
179
args[i] = STRING_VAL;
180
} else if (pType.isArray() && pType.getComponentType().equals(char.class)) {
181
args[i] = CHAR_ARRAY_VAL;
182
} else if (pType.equals(CharSequence.class)) {
183
charSequenceArgs.add(new Integer(i));
184
} else {
185
throw new RuntimeException("Test Failed: not accounting for method call with parameter type of " + pType.getName() + " You must update the test.");
186
}
187
}
188
/*
189
* If there are no CharSequence args, we can simply invoke our method
190
* and test it
191
*/
192
if (charSequenceArgs.isEmpty()) {
193
invokeMethod(aClass, m, args);
194
} else {
195
/*
196
* Iterate through the different CharSequence types and invoke the
197
* method for each type.
198
*/
199
if (charSequenceArgs.size() > 1) {
200
throw new RuntimeException("Test Failed: the test cannot handle a method with multiple CharSequence arguments. You must update the test to handle the method "
201
+ m.toString());
202
}
203
for (int j = 0; j < CHAR_SEQUENCE_VAL.length; j++) {
204
args[charSequenceArgs.get(0)] = CHAR_SEQUENCE_VAL[j];
205
invokeMethod(aClass, m, args);
206
}
207
}
208
}
209
210
@SuppressWarnings("serial")
211
private static class TestFailedException extends Exception {
212
213
final Method m;
214
215
public Method getMethod() {
216
return m;
217
}
218
219
public TestFailedException(Method m) {
220
this.m = m;
221
}
222
}
223
224
static class InvokeTask implements Runnable {
225
226
private final Method m;
227
private final Object target;
228
private final Object[] args;
229
230
InvokeTask(Method m, Object target, Object... args) {
231
this.m = m;
232
this.target = target;
233
this.args = args;
234
}
235
236
@Override
237
public void run() {
238
try {
239
m.invoke(target, args);
240
} catch (IllegalAccessException | IllegalArgumentException |
241
InvocationTargetException e) {
242
e.printStackTrace();
243
}
244
}
245
}
246
247
/**
248
* isSynchronized tests whether the given method is synchronized or not by
249
* invoking it in a thread and testing the thread state after starting the
250
* thread
251
* <p/>
252
* @param m the method to test
253
* @param target the object the method is executed on
254
* @param args the arguments passed to the method
255
* @return true iff the method is synchronized
256
*/
257
private static boolean isSynchronized(Method m, Object target,
258
Object... args) {
259
Thread t = new Thread(new InvokeTask(m, target, args));
260
261
Boolean isSynchronized = null;
262
263
synchronized (target) {
264
t.start();
265
266
while (isSynchronized == null) {
267
switch (t.getState()) {
268
case NEW:
269
case RUNNABLE:
270
case WAITING:
271
case TIMED_WAITING:
272
Thread.yield();
273
break;
274
case BLOCKED:
275
isSynchronized = true;
276
break;
277
case TERMINATED:
278
isSynchronized = false;
279
break;
280
}
281
}
282
}
283
284
try {
285
t.join();
286
} catch (InterruptedException ex) {
287
ex.printStackTrace();
288
}
289
290
return isSynchronized;
291
}
292
293
/*
294
* This class is used to test the synchronization tester above. It has a
295
* method, should_pass, that is unsynchronized but calls a synchronized
296
* method. It has another method, should_fail, which isn't synchronized and
297
* doesn't call a synchronized method. The former should pass and the latter
298
* should fail.
299
*/
300
private static class MyTestClass {
301
302
@SuppressWarnings("unused")
303
public MyTestClass(String s) {
304
}
305
306
@SuppressWarnings("unused")
307
public void should_pass() {
308
// call sync method
309
sync_shouldnt_be_tested();
310
}
311
312
@SuppressWarnings("unused")
313
public void should_fail() {
314
}
315
316
public synchronized void sync_shouldnt_be_tested() {
317
}
318
}
319
}
320
321