Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
PojavLauncherTeam
GitHub Repository: PojavLauncherTeam/mobile
Path: blob/master/test/jdk/java/foreign/TestNulls.java
41145 views
1
/*
2
* Copyright (c) 2020, 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
* @requires ((os.arch == "amd64" | os.arch == "x86_64") & sun.arch.data.model == "64") | os.arch == "aarch64"
27
* @modules java.base/jdk.internal.ref
28
* jdk.incubator.foreign
29
* @run testng/othervm
30
* --enable-native-access=ALL-UNNAMED
31
* TestNulls
32
*/
33
34
import jdk.incubator.foreign.*;
35
import jdk.internal.ref.CleanerFactory;
36
import org.testng.annotations.DataProvider;
37
import org.testng.annotations.NoInjection;
38
import org.testng.annotations.Test;
39
40
import java.lang.constant.Constable;
41
import java.lang.invoke.MethodHandle;
42
import java.lang.invoke.MethodHandles;
43
import java.lang.invoke.MethodType;
44
import java.lang.invoke.VarHandle;
45
import java.lang.ref.Cleaner;
46
import java.lang.reflect.Array;
47
import java.lang.reflect.InvocationTargetException;
48
import java.lang.reflect.Method;
49
import java.lang.reflect.Modifier;
50
import java.nio.ByteBuffer;
51
import java.nio.ByteOrder;
52
import java.nio.channels.FileChannel;
53
import java.nio.charset.Charset;
54
import java.nio.file.Path;
55
import java.util.*;
56
import java.util.concurrent.atomic.AtomicReference;
57
import java.util.function.Consumer;
58
import java.util.function.Supplier;
59
import java.util.function.UnaryOperator;
60
import java.util.stream.Collectors;
61
import java.util.stream.Stream;
62
63
import static org.testng.Assert.*;
64
import static org.testng.Assert.fail;
65
66
/**
67
* This test makes sure that public API classes (listed in {@link TestNulls#CLASSES}) throws NPEs whenever
68
* nulls are provided. The test looks at all the public methods in all the listed classes, and injects
69
* values automatically. If an API takes a reference, the test will try to inject nulls. For APIs taking
70
* either reference arrays, or collections, the framework will also generate additional <em>replacements</em>
71
* (e.g. other than just replacing the array, or collection with null), such as an array or collection
72
* with null elements. The test can be customized by adding/removing classes to the {@link #CLASSES} array,
73
* by adding/removing default mappings for standard carrier types (see {@link #DEFAULT_VALUES} or by
74
* adding/removing custom replacements (see {@link #REPLACEMENT_VALUES}).
75
*/
76
public class TestNulls {
77
78
static final Class<?>[] CLASSES = new Class<?>[] {
79
MemorySegment.class,
80
MemoryAddress.class,
81
MemoryLayout.class,
82
MemoryLayout.PathElement.class,
83
SequenceLayout.class,
84
ValueLayout.class,
85
GroupLayout.class,
86
Addressable.class,
87
SymbolLookup.class,
88
MemoryAccess.class,
89
MemoryLayouts.class,
90
MemoryHandles.class,
91
CLinker.class,
92
CLinker.VaList.class,
93
CLinker.VaList.Builder.class,
94
FunctionDescriptor.class,
95
SegmentAllocator.class,
96
ResourceScope.class
97
};
98
99
static final Set<String> EXCLUDE_LIST = Set.of(
100
"jdk.incubator.foreign.MemoryLayout/withAttribute(java.lang.String,java.lang.constant.Constable)/1/0",
101
"jdk.incubator.foreign.MemoryAddress/asSegment(long,java.lang.Runnable,java.lang.Object)/1/0",
102
"jdk.incubator.foreign.MemoryAddress/asSegment(long,java.lang.Runnable,java.lang.Object)/2/0",
103
"jdk.incubator.foreign.MemoryAddress/asSegment(long,java.lang.Runnable,jdk.incubator.foreign.ResourceScope)/1/0",
104
"jdk.incubator.foreign.SequenceLayout/withAttribute(java.lang.String,java.lang.constant.Constable)/1/0",
105
"jdk.incubator.foreign.ValueLayout/withAttribute(java.lang.String,java.lang.constant.Constable)/1/0",
106
"jdk.incubator.foreign.GroupLayout/withAttribute(java.lang.String,java.lang.constant.Constable)/1/0",
107
"jdk.incubator.foreign.MemoryHandles/insertCoordinates(java.lang.invoke.VarHandle,int,java.lang.Object[])/2/1",
108
"jdk.incubator.foreign.FunctionDescriptor/withAttribute(java.lang.String,java.lang.constant.Constable)/1/0"
109
);
110
111
static final Set<String> OBJECT_METHODS = Stream.of(Object.class.getMethods())
112
.map(Method::getName)
113
.collect(Collectors.toSet());
114
115
static final Map<Class<?>, Object> DEFAULT_VALUES = new HashMap<>();
116
117
static <Z> void addDefaultMapping(Class<Z> carrier, Z value) {
118
DEFAULT_VALUES.put(carrier, value);
119
}
120
121
static {
122
addDefaultMapping(char.class, (char)0);
123
addDefaultMapping(byte.class, (byte)0);
124
addDefaultMapping(short.class, (short)0);
125
addDefaultMapping(int.class, 0);
126
addDefaultMapping(float.class, 0f);
127
addDefaultMapping(long.class, 0L);
128
addDefaultMapping(double.class, 0d);
129
addDefaultMapping(boolean.class, true);
130
addDefaultMapping(ByteOrder.class, ByteOrder.nativeOrder());
131
addDefaultMapping(Thread.class, Thread.currentThread());
132
addDefaultMapping(Cleaner.class, CleanerFactory.cleaner());
133
addDefaultMapping(ByteBuffer.class, ByteBuffer.wrap(new byte[10]));
134
addDefaultMapping(Path.class, Path.of("nonExistent"));
135
addDefaultMapping(FileChannel.MapMode.class, FileChannel.MapMode.PRIVATE);
136
addDefaultMapping(UnaryOperator.class, UnaryOperator.identity());
137
addDefaultMapping(String.class, "Hello!");
138
addDefaultMapping(Constable.class, "Hello!");
139
addDefaultMapping(Class.class, String.class);
140
addDefaultMapping(Runnable.class, () -> {});
141
addDefaultMapping(Object.class, new Object());
142
addDefaultMapping(VarHandle.class, MemoryHandles.varHandle(int.class, ByteOrder.nativeOrder()));
143
addDefaultMapping(MethodHandle.class, MethodHandles.identity(int.class));
144
addDefaultMapping(List.class, List.of());
145
addDefaultMapping(Charset.class, Charset.defaultCharset());
146
addDefaultMapping(Consumer.class, x -> {});
147
addDefaultMapping(MethodType.class, MethodType.methodType(void.class));
148
addDefaultMapping(MemoryAddress.class, MemoryAddress.ofLong(1));
149
addDefaultMapping(Addressable.class, MemoryAddress.ofLong(1));
150
addDefaultMapping(MemoryLayout.class, MemoryLayouts.JAVA_INT);
151
addDefaultMapping(ValueLayout.class, MemoryLayouts.JAVA_INT);
152
addDefaultMapping(GroupLayout.class, MemoryLayout.structLayout(MemoryLayouts.JAVA_INT));
153
addDefaultMapping(SequenceLayout.class, MemoryLayout.sequenceLayout(MemoryLayouts.JAVA_INT));
154
addDefaultMapping(MemorySegment.class, MemorySegment.ofArray(new byte[10]));
155
addDefaultMapping(FunctionDescriptor.class, FunctionDescriptor.ofVoid());
156
addDefaultMapping(CLinker.class, CLinker.getInstance());
157
addDefaultMapping(CLinker.VaList.class, VaListHelper.vaList);
158
addDefaultMapping(CLinker.VaList.Builder.class, VaListHelper.vaListBuilder);
159
addDefaultMapping(ResourceScope.class, ResourceScope.newImplicitScope());
160
addDefaultMapping(SegmentAllocator.class, (size, align) -> null);
161
addDefaultMapping(Supplier.class, () -> null);
162
addDefaultMapping(ResourceScope.Handle.class, ResourceScope.globalScope().acquire());
163
addDefaultMapping(ClassLoader.class, TestNulls.class.getClassLoader());
164
addDefaultMapping(SymbolLookup.class, CLinker.systemLookup());
165
}
166
167
static class VaListHelper {
168
static final CLinker.VaList vaList;
169
static final CLinker.VaList.Builder vaListBuilder;
170
171
static {
172
AtomicReference<CLinker.VaList.Builder> builderRef = new AtomicReference<>();
173
vaList = CLinker.VaList.make(b -> {
174
builderRef.set(b);
175
b.vargFromLong(CLinker.C_LONG_LONG, 42L);
176
}, ResourceScope.newImplicitScope());
177
vaListBuilder = builderRef.get();
178
}
179
}
180
181
static final Map<Class<?>, Object[]> REPLACEMENT_VALUES = new HashMap<>();
182
183
@SafeVarargs
184
static <Z> void addReplacements(Class<Z> carrier, Z... value) {
185
REPLACEMENT_VALUES.put(carrier, value);
186
}
187
188
static {
189
addReplacements(Collection.class, null, Stream.of(new Object[] { null }).collect(Collectors.toList()));
190
addReplacements(List.class, null, Stream.of(new Object[] { null }).collect(Collectors.toList()));
191
addReplacements(Set.class, null, Stream.of(new Object[] { null }).collect(Collectors.toSet()));
192
}
193
194
@Test(dataProvider = "cases")
195
public void testNulls(String testName, @NoInjection Method meth, Object receiver, Object[] args) {
196
try {
197
meth.invoke(receiver, args);
198
fail("Method invocation completed normally");
199
} catch (InvocationTargetException ex) {
200
Class<?> cause = ex.getCause().getClass();
201
assertEquals(cause, NullPointerException.class, "got " + cause.getName() + " - expected NullPointerException");
202
} catch (Throwable ex) {
203
fail("Unexpected exception: " + ex);
204
}
205
}
206
207
@DataProvider(name = "cases")
208
static Iterator<Object[]> cases() {
209
List<Object[]> cases = new ArrayList<>();
210
for (Class<?> clazz : CLASSES) {
211
for (Method m : clazz.getMethods()) {
212
if (OBJECT_METHODS.contains(m.getName())) continue;
213
boolean isStatic = (m.getModifiers() & Modifier.STATIC) != 0;
214
List<Integer> refIndices = new ArrayList<>();
215
for (int i = 0; i < m.getParameterCount(); i++) {
216
Class<?> param = m.getParameterTypes()[i];
217
if (!param.isPrimitive()) {
218
refIndices.add(i);
219
}
220
}
221
for (int i : refIndices) {
222
Object[] replacements = replacements(m.getParameterTypes()[i]);
223
for (int r = 0 ; r < replacements.length ; r++) {
224
String testName = clazz.getName() + "/" + shortSig(m) + "/" + i + "/" + r;
225
if (EXCLUDE_LIST.contains(testName)) continue;
226
Object[] args = new Object[m.getParameterCount()];
227
for (int j = 0; j < args.length; j++) {
228
args[j] = defaultValue(m.getParameterTypes()[j]);
229
}
230
args[i] = replacements[r];
231
Object receiver = isStatic ? null : defaultValue(clazz);
232
cases.add(new Object[]{testName, m, receiver, args});
233
}
234
}
235
}
236
}
237
return cases.iterator();
238
};
239
240
static String shortSig(Method m) {
241
StringJoiner sj = new StringJoiner(",", m.getName() + "(", ")");
242
for (Class<?> parameterType : m.getParameterTypes()) {
243
sj.add(parameterType.getTypeName());
244
}
245
return sj.toString();
246
}
247
248
static Object defaultValue(Class<?> carrier) {
249
if (carrier.isArray()) {
250
return Array.newInstance(carrier.componentType(), 0);
251
}
252
Object value = DEFAULT_VALUES.get(carrier);
253
if (value == null) {
254
throw new UnsupportedOperationException(carrier.getName());
255
}
256
return value;
257
}
258
259
static Object[] replacements(Class<?> carrier) {
260
if (carrier.isArray() && !carrier.getComponentType().isPrimitive()) {
261
Object arr = Array.newInstance(carrier.componentType(), 1);
262
Array.set(arr, 0, null);
263
return new Object[] { null, arr };
264
}
265
return REPLACEMENT_VALUES.getOrDefault(carrier, new Object[] { null });
266
}
267
}
268
269