/
githubmirror
/
panama-vector
Обзор
Документация
Войти
/
githubmirror
/
panama-vector
Код
Запросы
0
Пакеты
0
Релизы
0
Аналитика
Безопасность
master
test/jdk/java/foreign/critical/TestCritical.java
200 строк
9 KB
SendaoYan
8345155: Add /native to native test in FFM
06 фев 2025, 12:33
06 фев 2025, 12:33
acb46dd
Код
Авторство
О чём код?
/* * Copyright (c) 2023, 2025, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License version 2 only, as * published by the Free Software Foundation. * * This code is distributed in the hope that it will be useful, but WITHOUT * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License * version 2 for more details (a copy is included in the LICENSE file that * accompanied this code). * * You should have received a copy of the GNU General Public License version * 2 along with this work; if not, write to the Free Software Foundation, * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. * * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA * or visit www.oracle.com if you need additional information or have any * questions. */ /* * @test * @library ../ /test/lib * * @run testng/othervm/native --enable-native-access=ALL-UNNAMED TestCritical */ import org.testng.annotations.DataProvider; import org.testng.annotations.Test; import java.lang.foreign.Arena; import java.lang.foreign.FunctionDescriptor; import java.lang.foreign.Linker; import java.lang.foreign.MemoryLayout; import java.lang.foreign.MemorySegment; import java.lang.foreign.SegmentAllocator; import java.lang.foreign.SequenceLayout; import java.lang.foreign.StructLayout; import java.lang.foreign.ValueLayout; import java.lang.invoke.MethodHandle; import java.lang.invoke.VarHandle; import java.util.ArrayList; import java.util.List; import java.util.function.IntFunction; import java.util.stream.Collectors; import java.util.stream.Stream; import static org.testng.Assert.assertEquals; public class TestCritical extends NativeTestHelper { static final MemoryLayout CAPTURE_STATE_LAYOUT = Linker.Option.captureStateLayout(); static final VarHandle ERRNO_HANDLE = CAPTURE_STATE_LAYOUT.varHandle(MemoryLayout.PathElement.groupElement("errno")); static { System.loadLibrary("Critical"); } @Test public void testEmpty() throws Throwable { MethodHandle handle = downcallHandle("empty", FunctionDescriptor.ofVoid(), Linker.Option.critical(false)); handle.invokeExact(); } @Test public void testIdentity() throws Throwable { MethodHandle handle = downcallHandle("identity", FunctionDescriptor.of(C_INT, C_INT), Linker.Option.critical(false)); int result = (int) handle.invokeExact(42); assertEquals(result, 42); } @Test public void testWithReturnBuffer() throws Throwable { StructLayout bigLayout = MemoryLayout.structLayout( C_LONG_LONG.withName("x"), C_LONG_LONG.withName("y")); MethodHandle handle = downcallHandle("with_return_buffer", FunctionDescriptor.of(bigLayout), Linker.Option.critical(false)); VarHandle vhX = bigLayout.varHandle(MemoryLayout.PathElement.groupElement("x")); VarHandle vhY = bigLayout.varHandle(MemoryLayout.PathElement.groupElement("y")); try (Arena arena = Arena.ofConfined()) { MemorySegment result = (MemorySegment) handle.invokeExact((SegmentAllocator) arena); long x = (long) vhX.get(result, 0L); assertEquals(x, 10); long y = (long) vhY.get(result, 0L); assertEquals(y, 11); } } public record AllowHeapCase(IntFunction<MemorySegment> newArraySegment, ValueLayout elementLayout, String fName, FunctionDescriptor fDesc, boolean readOnly, boolean captureErrno) {} @Test(dataProvider = "allowHeapCases") public void testAllowHeap(AllowHeapCase testCase) throws Throwable { List<Linker.Option> options = new ArrayList<>(); options.add(Linker.Option.critical(true)); if (testCase.captureErrno()) { options.add(Linker.Option.captureCallState("errno")); } MethodHandle handle = downcallHandle(testCase.fName(), testCase.fDesc(), options.toArray(Linker.Option[]::new)); int elementCount = 10; MemorySegment heapSegment = testCase.newArraySegment().apply(elementCount); if (testCase.readOnly()) { heapSegment = heapSegment.asReadOnly(); } SequenceLayout sequence = MemoryLayout.sequenceLayout(elementCount, testCase.elementLayout()); try (Arena arena = Arena.ofConfined()) { TestValue[] tvs = genTestArgs(testCase.fDesc(), arena); List<Object> args = Stream.of(tvs).map(TestValue::value).collect(Collectors.toCollection(ArrayList::new)); MemorySegment captureSegment = testCase.captureErrno() ? MemorySegment.ofArray(new int[((int) CAPTURE_STATE_LAYOUT.byteSize() + 3) / 4]) : null; // inject our custom last three arguments args.set(args.size() - 1, (int) sequence.byteSize()); TestValue sourceSegment = genTestValue(sequence, arena); args.set(args.size() - 2, sourceSegment.value()); args.set(args.size() - 3, heapSegment); if (testCase.captureErrno()) { args.add(0, captureSegment); } if (handle.type().parameterType(0) == SegmentAllocator.class) { args.add(0, arena); } Object o = handle.invokeWithArguments(args); if (o != null) { tvs[0].check(o); } // check that writes went through to array sourceSegment.check(heapSegment); if (testCase.captureErrno()) { int errno = (int) ERRNO_HANDLE.get(captureSegment, 0L); assertEquals(errno, 42); } } } @DataProvider public Object[][] allowHeapCases() { FunctionDescriptor voidDesc = FunctionDescriptor.ofVoid(C_POINTER, C_POINTER, C_INT); FunctionDescriptor intDesc = voidDesc.changeReturnLayout(C_INT).insertArgumentLayouts(0, C_INT); StructLayout L2 = MemoryLayout.structLayout( C_LONG_LONG.withName("x"), C_LONG_LONG.withName("y") ); FunctionDescriptor L2Desc = voidDesc.changeReturnLayout(L2).insertArgumentLayouts(0, L2); StructLayout L3 = MemoryLayout.structLayout( C_LONG_LONG.withName("x"), C_LONG_LONG.withName("y"), C_LONG_LONG.withName("z") ); FunctionDescriptor L3Desc = voidDesc.changeReturnLayout(L3).insertArgumentLayouts(0, L3); FunctionDescriptor stackDesc = voidDesc.insertArgumentLayouts(0, C_LONG_LONG, C_LONG_LONG, C_LONG_LONG, C_LONG_LONG, C_LONG_LONG, C_LONG_LONG, C_LONG_LONG, C_LONG_LONG, C_CHAR, C_SHORT, C_INT); List<AllowHeapCase> cases = new ArrayList<>(); for (boolean doCapture : new boolean[]{ true, false }) { for (HeapSegmentFactory hsf : HeapSegmentFactory.values()) { cases.add(new AllowHeapCase(hsf.newArray, hsf.elementLayout, "test_allow_heap_void", voidDesc, false, doCapture)); cases.add(new AllowHeapCase(hsf.newArray, hsf.elementLayout, "test_allow_heap_int", intDesc, false, doCapture)); cases.add(new AllowHeapCase(hsf.newArray, hsf.elementLayout, "test_allow_heap_return_buffer", L2Desc, false, doCapture)); cases.add(new AllowHeapCase(hsf.newArray, hsf.elementLayout, "test_allow_heap_imr", L3Desc, false, doCapture)); cases.add(new AllowHeapCase(hsf.newArray, hsf.elementLayout, "test_allow_heap_void_stack", stackDesc, false, doCapture)); // readOnly cases.add(new AllowHeapCase(hsf.newArray, hsf.elementLayout, "test_allow_heap_void", voidDesc, true, doCapture)); } } return cases.stream().map(e -> new Object[]{ e }).toArray(Object[][]::new); } private enum HeapSegmentFactory { BYTE(i -> MemorySegment.ofArray(new byte[i]), ValueLayout.JAVA_BYTE), SHORT(i -> MemorySegment.ofArray(new short[i]), ValueLayout.JAVA_SHORT), CHAR(i -> MemorySegment.ofArray(new char[i]), ValueLayout.JAVA_CHAR), INT(i -> MemorySegment.ofArray(new int[i]), ValueLayout.JAVA_INT), LONG(i -> MemorySegment.ofArray(new long[i]), ValueLayout.JAVA_LONG), FLOAT(i -> MemorySegment.ofArray(new float[i]), ValueLayout.JAVA_FLOAT), DOUBLE(i -> MemorySegment.ofArray(new double[i]), ValueLayout.JAVA_DOUBLE); IntFunction<MemorySegment> newArray; ValueLayout elementLayout; private HeapSegmentFactory(IntFunction<MemorySegment> newArray, ValueLayout elementLayout) { this.newArray = newArray; this.elementLayout = elementLayout; } } }