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 * @enablePreview
27 * @requires jdk.foreign.linker != "UNSUPPORTED"
28 * @modules java.base/jdk.internal.foreign
29 * @run testng TestLinker
30 * @run testng/othervm/policy=security.policy
31 * -Djava.security.manager=default TestLinker
32 */
33
34 import jdk.internal.foreign.CABI;
35 import org.testng.annotations.DataProvider;
36 import org.testng.annotations.Test;
37
38 import java.lang.foreign.FunctionDescriptor;
39 import java.lang.foreign.Linker;
40 import java.lang.invoke.MethodHandle;
41 import java.util.ArrayList;
42 import java.util.Arrays;
43 import java.util.List;
44
45 import static java.lang.foreign.MemoryLayout.*;
46 import static java.lang.foreign.ValueLayout.JAVA_CHAR;
47 import static java.lang.foreign.ValueLayout.JAVA_SHORT;
48 import static org.testng.Assert.assertSame;
49 import static org.testng.Assert.assertNotSame;
50
51 public class TestLinker extends NativeTestHelper {
52
53 static final boolean IS_FALLBACK_LINKER = CABI.current() == CABI.FALLBACK;
54
55 record LinkRequest(FunctionDescriptor descriptor, Linker.Option... options) {}
56
57 @Test(dataProvider = "notSameCases")
58 public void testLinkerOptionsCache(LinkRequest l1, LinkRequest l2) {
59 Linker linker = Linker.nativeLinker();
60 MethodHandle mh1 = linker.downcallHandle(l1.descriptor(), l1.options());
61 MethodHandle mh2 = linker.downcallHandle(l2.descriptor(), l2.options());
62 // assert that these are 2 distinct link request. No caching allowed
63 assertNotSame(mh1, mh2);
64 }
65
66 @DataProvider
67 public static Object[][] notSameCases() {
68 FunctionDescriptor fd_II_V = FunctionDescriptor.ofVoid(C_INT, C_INT);
69 return new Object[][]{
74 }
75
76 @Test(dataProvider = "namedDescriptors")
77 public void testNamedLinkerCache(FunctionDescriptor f1, FunctionDescriptor f2) {
78 Linker linker = Linker.nativeLinker();
79 MethodHandle mh1 = linker.downcallHandle(f1);
80 MethodHandle mh2 = linker.downcallHandle(f2);
81 // assert that these are the same link request, even though layout names differ
82 assertSame(mh1, mh2);
83 }
84
85 @DataProvider
86 public static Object[][] namedDescriptors() {
87 List<Object[]> cases = new ArrayList<>(Arrays.asList(new Object[][]{
88 { FunctionDescriptor.ofVoid(C_INT),
89 FunctionDescriptor.ofVoid(C_INT.withName("x")) },
90 { FunctionDescriptor.ofVoid(structLayout(C_INT)),
91 FunctionDescriptor.ofVoid(structLayout(C_INT).withName("x")) },
92 { FunctionDescriptor.ofVoid(structLayout(C_INT)),
93 FunctionDescriptor.ofVoid(structLayout(C_INT.withName("x"))) },
94 { FunctionDescriptor.ofVoid(structLayout(C_INT, paddingLayout(4), C_LONG_LONG)),
95 FunctionDescriptor.ofVoid(structLayout(C_INT, paddingLayout(4), C_LONG_LONG.withName("x"))) },
96 { FunctionDescriptor.ofVoid(structLayout(C_INT, paddingLayout(4), C_LONG_LONG)),
97 FunctionDescriptor.ofVoid(structLayout(C_INT, paddingLayout(4).withName("x"), C_LONG_LONG)) },
98 { FunctionDescriptor.ofVoid(structLayout(sequenceLayout(1, C_INT))),
99 FunctionDescriptor.ofVoid(structLayout(sequenceLayout(1, C_INT).withName("x"))) },
100 { FunctionDescriptor.ofVoid(structLayout(sequenceLayout(1, C_INT))),
101 FunctionDescriptor.ofVoid(structLayout(sequenceLayout(1, C_INT.withName("x")))) },
102 { FunctionDescriptor.ofVoid(C_POINTER),
103 FunctionDescriptor.ofVoid(C_POINTER.withName("x")) },
104 { FunctionDescriptor.ofVoid(C_POINTER.withTargetLayout(C_INT)),
105 FunctionDescriptor.ofVoid(C_POINTER.withTargetLayout(C_INT.withName("x"))) },
106 { FunctionDescriptor.ofVoid(C_POINTER.withTargetLayout(C_INT)),
107 FunctionDescriptor.ofVoid(C_POINTER.withName("x").withTargetLayout(C_INT.withName("x"))) },
108 }));
109
110 if (!IS_FALLBACK_LINKER) {
111 cases.add(new Object[]{ FunctionDescriptor.ofVoid(unionLayout(C_INT)),
112 FunctionDescriptor.ofVoid(unionLayout(C_INT).withName("x")) });
113 cases.add(new Object[]{ FunctionDescriptor.ofVoid(unionLayout(C_INT)),
114 FunctionDescriptor.ofVoid(unionLayout(C_INT.withName("x"))) });
115 }
116
117 return cases.toArray(Object[][]::new);
118 }
119
120 @DataProvider
121 public static Object[][] invalidIndexCases() {
122 return new Object[][]{
123 { -1, },
124 { 42, },
125 };
126 }
127
128 @Test(dataProvider = "invalidIndexCases",
129 expectedExceptions = IllegalArgumentException.class,
130 expectedExceptionsMessageRegExp = ".*not in bounds for descriptor.*")
131 public void testInvalidOption(int invalidIndex) {
132 Linker.Option option = Linker.Option.firstVariadicArg(invalidIndex);
133 FunctionDescriptor desc = FunctionDescriptor.ofVoid();
134 Linker.nativeLinker().downcallHandle(desc, option); // throws
135 }
136
137 @Test(expectedExceptions = IllegalArgumentException.class,
138 expectedExceptionsMessageRegExp = ".*Unknown name.*")
139 public void testInvalidPreservedValueName() {
140 Linker.Option.captureCallState("foo"); // throws
141 }
142
143 }
|
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 * @modules java.base/jdk.internal.foreign
27 * @run testng TestLinker
28 * @run testng/othervm/policy=security.policy
29 * -Djava.security.manager=default TestLinker
30 */
31
32 import jdk.internal.foreign.CABI;
33 import org.testng.annotations.DataProvider;
34 import org.testng.annotations.Test;
35
36 import java.lang.foreign.FunctionDescriptor;
37 import java.lang.foreign.Linker;
38 import java.lang.foreign.MemoryLayout;
39 import java.lang.foreign.ValueLayout;
40 import java.lang.invoke.MethodHandle;
41 import java.util.ArrayList;
42 import java.util.Arrays;
43 import java.util.List;
44
45 import static java.lang.foreign.MemoryLayout.*;
46 import static java.lang.foreign.ValueLayout.JAVA_CHAR;
47 import static java.lang.foreign.ValueLayout.JAVA_SHORT;
48 import static org.testng.Assert.assertNotNull;
49 import static org.testng.Assert.assertSame;
50 import static org.testng.Assert.assertNotSame;
51 import static org.testng.Assert.assertTrue;
52
53 public class TestLinker extends NativeTestHelper {
54
55 static final boolean IS_FALLBACK_LINKER = CABI.current() == CABI.FALLBACK;
56
57 record LinkRequest(FunctionDescriptor descriptor, Linker.Option... options) {}
58
59 @Test(dataProvider = "notSameCases")
60 public void testLinkerOptionsCache(LinkRequest l1, LinkRequest l2) {
61 Linker linker = Linker.nativeLinker();
62 MethodHandle mh1 = linker.downcallHandle(l1.descriptor(), l1.options());
63 MethodHandle mh2 = linker.downcallHandle(l2.descriptor(), l2.options());
64 // assert that these are 2 distinct link request. No caching allowed
65 assertNotSame(mh1, mh2);
66 }
67
68 @DataProvider
69 public static Object[][] notSameCases() {
70 FunctionDescriptor fd_II_V = FunctionDescriptor.ofVoid(C_INT, C_INT);
71 return new Object[][]{
76 }
77
78 @Test(dataProvider = "namedDescriptors")
79 public void testNamedLinkerCache(FunctionDescriptor f1, FunctionDescriptor f2) {
80 Linker linker = Linker.nativeLinker();
81 MethodHandle mh1 = linker.downcallHandle(f1);
82 MethodHandle mh2 = linker.downcallHandle(f2);
83 // assert that these are the same link request, even though layout names differ
84 assertSame(mh1, mh2);
85 }
86
87 @DataProvider
88 public static Object[][] namedDescriptors() {
89 List<Object[]> cases = new ArrayList<>(Arrays.asList(new Object[][]{
90 { FunctionDescriptor.ofVoid(C_INT),
91 FunctionDescriptor.ofVoid(C_INT.withName("x")) },
92 { FunctionDescriptor.ofVoid(structLayout(C_INT)),
93 FunctionDescriptor.ofVoid(structLayout(C_INT).withName("x")) },
94 { FunctionDescriptor.ofVoid(structLayout(C_INT)),
95 FunctionDescriptor.ofVoid(structLayout(C_INT.withName("x"))) },
96 { FunctionDescriptor.ofVoid(structLayout(sequenceLayout(1, C_INT))),
97 FunctionDescriptor.ofVoid(structLayout(sequenceLayout(1, C_INT).withName("x"))) },
98 { FunctionDescriptor.ofVoid(structLayout(sequenceLayout(1, C_INT))),
99 FunctionDescriptor.ofVoid(structLayout(sequenceLayout(1, C_INT.withName("x")))) },
100 { FunctionDescriptor.ofVoid(C_POINTER),
101 FunctionDescriptor.ofVoid(C_POINTER.withName("x")) },
102 { FunctionDescriptor.ofVoid(C_POINTER.withTargetLayout(C_INT)),
103 FunctionDescriptor.ofVoid(C_POINTER.withTargetLayout(C_INT.withName("x"))) },
104 { FunctionDescriptor.ofVoid(C_POINTER.withTargetLayout(C_INT)),
105 FunctionDescriptor.ofVoid(C_POINTER.withName("x").withTargetLayout(C_INT.withName("x"))) },
106 }));
107
108 if (!IS_FALLBACK_LINKER) {
109 cases.add(new Object[]{ FunctionDescriptor.ofVoid(unionLayout(C_INT)),
110 FunctionDescriptor.ofVoid(unionLayout(C_INT).withName("x")) });
111 cases.add(new Object[]{ FunctionDescriptor.ofVoid(unionLayout(C_INT)),
112 FunctionDescriptor.ofVoid(unionLayout(C_INT.withName("x"))) });
113 }
114 if (C_LONG_LONG.byteAlignment() == 8) {
115 cases.add(new Object[]{ FunctionDescriptor.ofVoid(structLayout(C_INT, paddingLayout(4), C_LONG_LONG)),
116 FunctionDescriptor.ofVoid(structLayout(C_INT, paddingLayout(4), C_LONG_LONG.withName("x"))) });
117 cases.add(new Object[]{ FunctionDescriptor.ofVoid(structLayout(C_INT, paddingLayout(4), C_LONG_LONG)),
118 FunctionDescriptor.ofVoid(structLayout(C_INT, paddingLayout(4).withName("x"), C_LONG_LONG)) });
119 }
120
121 return cases.toArray(Object[][]::new);
122 }
123
124 @DataProvider
125 public static Object[][] invalidIndexCases() {
126 return new Object[][]{
127 { -1, },
128 { 42, },
129 };
130 }
131
132 @Test(dataProvider = "invalidIndexCases",
133 expectedExceptions = IllegalArgumentException.class,
134 expectedExceptionsMessageRegExp = ".*not in bounds for descriptor.*")
135 public void testInvalidOption(int invalidIndex) {
136 Linker.Option option = Linker.Option.firstVariadicArg(invalidIndex);
137 FunctionDescriptor desc = FunctionDescriptor.ofVoid();
138 Linker.nativeLinker().downcallHandle(desc, option); // throws
139 }
140
141 @Test(expectedExceptions = IllegalArgumentException.class,
142 expectedExceptionsMessageRegExp = ".*Unknown name.*")
143 public void testInvalidPreservedValueName() {
144 Linker.Option.captureCallState("foo"); // throws
145 }
146
147 @Test(dataProvider = "canonicalTypeNames")
148 public void testCanonicalLayouts(String typeName) {
149 MemoryLayout layout = LINKER.canonicalLayouts().get(typeName);
150 assertNotNull(layout);
151 assertTrue(layout instanceof ValueLayout);
152 }
153
154 @DataProvider
155 public static Object[][] canonicalTypeNames() {
156 return new Object[][]{
157 { "bool" },
158 { "char" },
159 { "short" },
160 { "int" },
161 { "long" },
162 { "long long" },
163 { "float" },
164 { "double" },
165 { "void*" },
166 { "size_t" },
167 { "wchar_t" },
168 };
169 }
170 }
|