1 /* 2 * Copyright (c) 2020, 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 * @run testng/othervm --enable-native-access=ALL-UNNAMED TestFunctionDescriptor 27 */ 28 29 import java.lang.foreign.FunctionDescriptor; 30 import java.lang.foreign.MemoryLayout; 31 import java.lang.foreign.MemorySegment; 32 import java.lang.invoke.MethodType; 33 import java.util.List; 34 import java.util.Optional; 35 import org.testng.annotations.Test; 36 37 import static org.testng.Assert.assertEquals; 38 import static org.testng.Assert.assertFalse; 39 import static org.testng.Assert.assertNotEquals; 40 import static org.testng.Assert.assertTrue; 41 42 public class TestFunctionDescriptor extends NativeTestHelper { 43 44 static final String DUMMY_ATTR = "dummy"; 45 46 @Test 47 public void testOf() { 48 FunctionDescriptor fd = FunctionDescriptor.of(C_INT, C_DOUBLE, C_LONG_LONG); 49 50 assertEquals(fd.argumentLayouts(), List.of(C_DOUBLE, C_LONG_LONG)); 51 Optional<MemoryLayout> returnLayoutOp = fd.returnLayout(); 52 assertTrue(returnLayoutOp.isPresent()); 53 assertEquals(returnLayoutOp.get(), C_INT); 54 } 55 56 @Test 57 public void testOfVoid() { 58 FunctionDescriptor fd = FunctionDescriptor.ofVoid(C_DOUBLE, C_LONG_LONG); 59 60 assertEquals(fd.argumentLayouts(), List.of(C_DOUBLE, C_LONG_LONG)); 61 Optional<MemoryLayout> returnLayoutOp = fd.returnLayout(); 62 assertFalse(returnLayoutOp.isPresent()); 63 } 64 65 @Test 66 public void testAppendArgumentLayouts() { 67 FunctionDescriptor fd = FunctionDescriptor.of(C_INT, C_DOUBLE, C_LONG_LONG); 68 fd = fd.appendArgumentLayouts(C_POINTER); 69 70 assertEquals(fd.argumentLayouts(), List.of(C_DOUBLE, C_LONG_LONG, C_POINTER)); 71 Optional<MemoryLayout> returnLayoutOp = fd.returnLayout(); 72 assertTrue(returnLayoutOp.isPresent()); 73 assertEquals(returnLayoutOp.get(), C_INT); 74 } 75 76 @Test 77 public void testChangeReturnLayout() { 78 FunctionDescriptor fd = FunctionDescriptor.of(C_INT, C_DOUBLE, C_LONG_LONG); 79 fd = fd.changeReturnLayout(C_INT); 80 81 assertEquals(fd.argumentLayouts(), List.of(C_DOUBLE, C_LONG_LONG)); 82 Optional<MemoryLayout> returnLayoutOp = fd.returnLayout(); 83 assertTrue(returnLayoutOp.isPresent()); 84 assertEquals(returnLayoutOp.get(), C_INT); 85 } 86 87 @Test 88 public void testDropReturnLayout() { 89 FunctionDescriptor fd = FunctionDescriptor.of(C_INT, C_DOUBLE, C_LONG_LONG); 90 fd = fd.dropReturnLayout(); 91 92 assertEquals(fd.argumentLayouts(), List.of(C_DOUBLE, C_LONG_LONG)); 93 Optional<MemoryLayout> returnLayoutOp = fd.returnLayout(); 94 assertFalse(returnLayoutOp.isPresent()); 95 } 96 97 @Test 98 public void testEquals() { 99 FunctionDescriptor fd = FunctionDescriptor.of(C_INT, C_INT, C_INT); 100 assertEquals(fd, fd); 101 FunctionDescriptor fdReturnSomethingElse = FunctionDescriptor.of(C_LONG_LONG, C_INT, C_INT); 102 FunctionDescriptor fdOtherArguments = FunctionDescriptor.of(C_INT, C_INT); 103 assertFalse(fd.equals(fdReturnSomethingElse)); 104 assertFalse(fd.equals(fdOtherArguments)); 105 assertFalse(fd.equals(null)); 106 assertFalse(fd.equals("A")); 107 } 108 109 @Test 110 public void testCarrierMethodType() { 111 FunctionDescriptor fd = FunctionDescriptor.of(C_INT, 112 C_INT, 113 MemoryLayout.structLayout(C_INT, C_INT), 114 MemoryLayout.sequenceLayout(3, C_INT)); 115 MethodType cmt = fd.toMethodType(); 116 assertEquals(cmt, MethodType.methodType(int.class, int.class, MemorySegment.class, MemorySegment.class)); 117 } 118 119 @Test(expectedExceptions = IllegalArgumentException.class) 120 public void testBadCarrierMethodType() { 121 FunctionDescriptor fd = FunctionDescriptor.of(C_INT, 122 C_INT, 123 MemoryLayout.structLayout(C_INT, C_INT), 124 MemoryLayout.sequenceLayout(3, C_INT), 125 MemoryLayout.paddingLayout(4)); 126 fd.toMethodType(); // should throw 127 } 128 129 @Test(expectedExceptions = IllegalArgumentException.class) 130 public void testIllegalInsertArgNegIndex() { 131 FunctionDescriptor fd = FunctionDescriptor.of(C_INT); 132 fd.insertArgumentLayouts(-1, C_INT); 133 } 134 135 @Test(expectedExceptions = IllegalArgumentException.class) 136 public void testIllegalInsertArgOutOfBounds() { 137 FunctionDescriptor fd = FunctionDescriptor.of(C_INT); 138 fd.insertArgumentLayouts(2, C_INT); 139 } 140 141 @Test(expectedExceptions = IllegalArgumentException.class) 142 public void testBadPaddingInVoidFunction() { 143 FunctionDescriptor.ofVoid(MemoryLayout.paddingLayout(1)); 144 } 145 146 @Test(expectedExceptions = IllegalArgumentException.class) 147 public void testBadPaddingInNonVoidFunction() { 148 FunctionDescriptor.of(MemoryLayout.paddingLayout(1)); 149 } 150 151 @Test(expectedExceptions = IllegalArgumentException.class) 152 public void testBadPaddingInAppendArgLayouts() { 153 FunctionDescriptor.ofVoid().appendArgumentLayouts(MemoryLayout.paddingLayout(1)); 154 } 155 156 @Test(expectedExceptions = IllegalArgumentException.class) 157 public void testBadPaddingInInsertArgLayouts() { 158 FunctionDescriptor.ofVoid().insertArgumentLayouts(0, MemoryLayout.paddingLayout(1)); 159 } 160 161 @Test(expectedExceptions = IllegalArgumentException.class) 162 public void testBadPaddingInChangeRetLayout() { 163 FunctionDescriptor.ofVoid().changeReturnLayout(MemoryLayout.paddingLayout(1)); 164 } 165 166 }