1 /* 2 * Copyright (c) 2023, 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 * @library ../ /test/lib 27 * @requires jdk.foreign.linker != "FALLBACK" 28 * @build NativeTestHelper 29 * @run testng/othervm --enable-native-access=ALL-UNNAMED TestNested 30 */ 31 32 import org.testng.annotations.DataProvider; 33 import org.testng.annotations.Test; 34 35 import java.lang.foreign.Arena; 36 import java.lang.foreign.FunctionDescriptor; 37 import java.lang.foreign.GroupLayout; 38 import java.lang.foreign.MemoryLayout; 39 import java.lang.foreign.MemorySegment; 40 import java.lang.foreign.SegmentAllocator; 41 import java.lang.foreign.StructLayout; 42 import java.lang.foreign.UnionLayout; 43 import java.lang.invoke.MethodHandle; 44 import java.util.List; 45 import java.util.Random; 46 import java.util.concurrent.atomic.AtomicReference; 47 48 public class TestNested extends NativeTestHelper { 49 50 static { 51 System.loadLibrary("Nested"); 52 } 53 54 @Test(dataProvider = "nestedLayouts") 55 public void testNested(GroupLayout layout) throws Throwable { 56 try (Arena arena = Arena.ofConfined()) { 57 Random random = new Random(0); 58 TestValue testValue = genTestValue(random, layout, arena); 59 60 String funcName = "test_" + layout.name().orElseThrow(); 61 FunctionDescriptor downcallDesc = FunctionDescriptor.of(layout, layout, C_POINTER); 62 FunctionDescriptor upcallDesc = FunctionDescriptor.of(layout, layout); 63 64 MethodHandle downcallHandle = downcallHandle(funcName, downcallDesc); 65 AtomicReference<Object[]> returnBox = new AtomicReference<>(); 66 MemorySegment stub = makeArgSaverCB(upcallDesc, arena, returnBox, 0); 67 68 MemorySegment returned = (MemorySegment) downcallHandle.invokeExact( 69 (SegmentAllocator) arena, (MemorySegment) testValue.value(), stub); 70 71 testValue.check().accept(returnBox.get()[0]); 72 testValue.check().accept(returned); 73 } 74 } 75 76 @DataProvider 77 public static Object[][] nestedLayouts() { 78 List<GroupLayout> layouts = List.of( 79 S1, U1, U17, S2, S3, S4, S5, S6, U2, S7, U3, U4, U5, U6, U7, S8, S9, U8, U9, U10, S10, 80 U11, S11, U12, S12, U13, U14, U15, S13, S14, U16, S15); 81 return layouts.stream().map(l -> new Object[]{l}).toArray(Object[][]::new); 82 } 83 84 static final StructLayout S1 = MemoryLayout.structLayout( 85 C_DOUBLE.withName("f0"), 86 C_LONG_LONG.withName("f1"), 87 C_DOUBLE.withName("f2"), 88 C_INT.withName("f3"), 89 MemoryLayout.paddingLayout(4) 90 ).withName("S1"); 91 static final UnionLayout U1 = MemoryLayout.unionLayout( 92 C_SHORT.withName("f0"), 93 C_LONG_LONG.withName("f1"), 94 C_SHORT.withName("f2"), 95 MemoryLayout.sequenceLayout(4, MemoryLayout.sequenceLayout(3, C_CHAR)).withName("f3"), 96 MemoryLayout.paddingLayout(16) 97 ).withName("U1"); 98 static final UnionLayout U17 = MemoryLayout.unionLayout( 99 C_CHAR.withName("f0"), 100 C_CHAR.withName("f1"), 101 C_LONG_LONG.withName("f2"), 102 C_DOUBLE.withName("f3") 103 ).withName("U17"); 104 static final StructLayout S2 = MemoryLayout.structLayout( 105 U17.withName("f0"), 106 MemoryLayout.sequenceLayout(4, C_LONG_LONG).withName("f1"), 107 C_SHORT.withName("f2"), 108 MemoryLayout.paddingLayout(6) 109 ).withName("S2"); 110 static final StructLayout S3 = MemoryLayout.structLayout( 111 C_FLOAT.withName("f0"), 112 C_INT.withName("f1"), 113 U1.withName("f2"), 114 S2.withName("f3") 115 ).withName("S3"); 116 static final StructLayout S4 = MemoryLayout.structLayout( 117 MemoryLayout.sequenceLayout(2, C_SHORT).withName("f0"), 118 MemoryLayout.paddingLayout(4), 119 S1.withName("f1") 120 ).withName("S4"); 121 static final StructLayout S5 = MemoryLayout.structLayout( 122 C_FLOAT.withName("f0"), 123 MemoryLayout.paddingLayout(4), 124 C_POINTER.withName("f1"), 125 S4.withName("f2") 126 ).withName("S5"); 127 static final StructLayout S6 = MemoryLayout.structLayout( 128 S5.withName("f0") 129 ).withName("S6"); 130 static final UnionLayout U2 = MemoryLayout.unionLayout( 131 C_FLOAT.withName("f0"), 132 C_SHORT.withName("f1"), 133 C_POINTER.withName("f2"), 134 C_FLOAT.withName("f3") 135 ).withName("U2"); 136 static final StructLayout S7 = MemoryLayout.structLayout( 137 C_DOUBLE.withName("f0"), 138 C_SHORT.withName("f1"), 139 C_SHORT.withName("f2"), 140 MemoryLayout.paddingLayout(4), 141 C_LONG_LONG.withName("f3") 142 ).withName("S7"); 143 static final UnionLayout U3 = MemoryLayout.unionLayout( 144 C_POINTER.withName("f0"), 145 U2.withName("f1"), 146 C_LONG_LONG.withName("f2"), 147 S7.withName("f3") 148 ).withName("U3"); 149 static final UnionLayout U4 = MemoryLayout.unionLayout( 150 C_FLOAT.withName("f0") 151 ).withName("U4"); 152 static final UnionLayout U5 = MemoryLayout.unionLayout( 153 U3.withName("f0"), 154 MemoryLayout.sequenceLayout(3, C_LONG_LONG).withName("f1"), 155 U4.withName("f2"), 156 C_FLOAT.withName("f3") 157 ).withName("U5"); 158 static final UnionLayout U6 = MemoryLayout.unionLayout( 159 C_SHORT.withName("f0"), 160 C_FLOAT.withName("f1"), 161 U5.withName("f2"), 162 C_SHORT.withName("f3") 163 ).withName("U6"); 164 static final UnionLayout U7 = MemoryLayout.unionLayout( 165 C_SHORT.withName("f0") 166 ).withName("U7"); 167 static final StructLayout S8 = MemoryLayout.structLayout( 168 MemoryLayout.sequenceLayout(3, C_DOUBLE).withName("f0"), 169 U7.withName("f1"), 170 MemoryLayout.paddingLayout(6), 171 C_POINTER.withName("f2"), 172 C_POINTER.withName("f3") 173 ).withName("S8"); 174 static final StructLayout S9 = MemoryLayout.structLayout( 175 C_CHAR.withName("f0"), 176 MemoryLayout.paddingLayout(7), 177 MemoryLayout.sequenceLayout(2, C_DOUBLE).withName("f1"), 178 C_CHAR.withName("f2"), 179 MemoryLayout.paddingLayout(7), 180 S8.withName("f3") 181 ).withName("S9"); 182 static final UnionLayout U8 = MemoryLayout.unionLayout( 183 C_LONG_LONG.withName("f0"), 184 C_POINTER.withName("f1"), 185 S9.withName("f2") 186 ).withName("U8"); 187 static final UnionLayout U9 = MemoryLayout.unionLayout( 188 C_INT.withName("f0"), 189 C_DOUBLE.withName("f1"), 190 MemoryLayout.sequenceLayout(2, C_SHORT).withName("f2"), 191 C_LONG_LONG.withName("f3") 192 ).withName("U9"); 193 static final UnionLayout U10 = MemoryLayout.unionLayout( 194 C_LONG_LONG.withName("f0"), 195 U9.withName("f1"), 196 C_CHAR.withName("f2"), 197 C_FLOAT.withName("f3") 198 ).withName("U10"); 199 static final StructLayout S10 = MemoryLayout.structLayout( 200 MemoryLayout.sequenceLayout(4, C_DOUBLE).withName("f0") 201 ).withName("S10"); 202 static final UnionLayout U11 = MemoryLayout.unionLayout( 203 MemoryLayout.sequenceLayout(3, S10).withName("f0") 204 ).withName("U11"); 205 static final StructLayout S11 = MemoryLayout.structLayout( 206 C_SHORT.withName("f0"), 207 C_CHAR.withName("f1"), 208 MemoryLayout.paddingLayout(1) 209 ).withName("S11"); 210 static final UnionLayout U12 = MemoryLayout.unionLayout( 211 C_FLOAT.withName("f0"), 212 S11.withName("f1"), 213 C_CHAR.withName("f2"), 214 C_CHAR.withName("f3") 215 ).withName("U12"); 216 static final StructLayout S12 = MemoryLayout.structLayout( 217 U12.withName("f0"), 218 C_FLOAT.withName("f1") 219 ).withName("S12"); 220 static final UnionLayout U13 = MemoryLayout.unionLayout( 221 C_FLOAT.withName("f0"), 222 S12.withName("f1") 223 ).withName("U13"); 224 static final UnionLayout U14 = MemoryLayout.unionLayout( 225 C_INT.withName("f0"), 226 MemoryLayout.sequenceLayout(2, C_POINTER).withName("f1"), 227 MemoryLayout.sequenceLayout(2, MemoryLayout.sequenceLayout(3, C_FLOAT)).withName("f2") 228 ).withName("U14"); 229 static final UnionLayout U15 = MemoryLayout.unionLayout( 230 C_POINTER.withName("f0"), 231 C_LONG_LONG.withName("f1"), 232 MemoryLayout.sequenceLayout(1, C_DOUBLE).withName("f2"), 233 C_LONG_LONG.withName("f3") 234 ).withName("U15"); 235 static final StructLayout S13 = MemoryLayout.structLayout( 236 C_INT.withName("f0"), 237 C_CHAR.withName("f1"), 238 MemoryLayout.paddingLayout(3), 239 C_POINTER.withName("f2"), 240 C_CHAR.withName("f3"), 241 MemoryLayout.paddingLayout(7) 242 ).withName("S13"); 243 static final StructLayout S14 = MemoryLayout.structLayout( 244 C_LONG_LONG.withName("f0") 245 ).withName("S14"); 246 static final UnionLayout U16 = MemoryLayout.unionLayout( 247 MemoryLayout.sequenceLayout(4, C_SHORT).withName("f0"), 248 C_INT.withName("f1"), 249 S13.withName("f2"), 250 S14.withName("f3") 251 ).withName("U16"); 252 static final StructLayout S15 = MemoryLayout.structLayout( 253 U16.withName("f0"), 254 C_FLOAT.withName("f1"), 255 C_INT.withName("f2"), 256 C_LONG_LONG.withName("f3") 257 ).withName("S15"); 258 }