1 /*
  2  * Copyright (c) 2021, 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 import jdk.incubator.foreign.MemoryAddress;
 25 import jdk.incubator.foreign.MemorySegment;
 26 import jdk.incubator.foreign.ResourceScope;
 27 import org.testng.annotations.Test;
 28 
 29 import java.util.concurrent.atomic.AtomicInteger;
 30 
 31 import static org.testng.Assert.*;
 32 
 33 import static test.jextract.funcpointers.func_h.*;
 34 import test.jextract.funcpointers.*;
 35 
 36 /*
 37  * @test id=classes
 38  * @library ..
 39  * @modules jdk.incubator.jextract
 40  * @run driver JtregJextract -l Func -t test.jextract.funcpointers -- func.h
 41  * @run testng/othervm --enable-native-access=jdk.incubator.jextract,ALL-UNNAMED TestFuncPointerInvokers
 42  */
 43 /*
 44  * @test id=sources
 45  * @library ..
 46  * @modules jdk.incubator.jextract
 47  * @run driver JtregJextractSources -l Func -t test.jextract.funcpointers -- func.h
 48  * @run testng/othervm --enable-native-access=jdk.incubator.jextract,ALL-UNNAMED TestFuncPointerInvokers
 49  */
 50 public class TestFuncPointerInvokers {
 51     @Test
 52     public void testStructFieldTypedef() {
 53         try (ResourceScope scope = ResourceScope.newConfinedScope()) {
 54             AtomicInteger val = new AtomicInteger(-1);
 55             MemorySegment bar = Bar.allocate(scope);
 56             Bar.foo$set(bar, Foo.allocate((i) -> val.set(i), scope).address());
 57             Bar.foo(bar, scope).apply(42);
 58             assertEquals(val.get(), 42);
 59         }
 60     }
 61 
 62     @Test
 63     public void testStructFieldFITypedef() {
 64         try (ResourceScope scope = ResourceScope.newConfinedScope()) {
 65             AtomicInteger val = new AtomicInteger(-1);
 66             MemorySegment bar = Bar.allocate(scope);
 67             Bar.foo$set(bar, Foo.allocate((i) -> val.set(i), scope).address());
 68             Foo.ofAddress(Bar.foo$get(bar), scope).apply(42);
 69             assertEquals(val.get(), 42);
 70         }
 71     }
 72 
 73     @Test
 74     public void testGlobalTypedef() {
 75         try (ResourceScope scope = ResourceScope.newConfinedScope()) {
 76             AtomicInteger val = new AtomicInteger(-1);
 77             f$set(Foo.allocate((i) -> val.set(i), scope).address());
 78             f().apply(42);
 79             assertEquals(val.get(), 42);
 80         }
 81     }
 82 
 83     @Test
 84     public void testGlobalFITypedef() {
 85         try (ResourceScope scope = ResourceScope.newConfinedScope()) {
 86             AtomicInteger val = new AtomicInteger(-1);
 87             f$set(Foo.allocate((i) -> val.set(i), scope).address());
 88             Foo.ofAddress(f$get(), scope).apply(42);
 89             assertEquals(val.get(), 42);
 90         }
 91     }
 92 
 93     @Test
 94     public void testStructFieldFunctionPointer() {
 95         try (ResourceScope scope = ResourceScope.newConfinedScope()) {
 96             AtomicInteger val = new AtomicInteger(-1);
 97             MemorySegment baz = Baz.allocate(scope);
 98             Baz.fp$set(baz, Baz.fp.allocate((i) -> val.set(i), scope).address());
 99             Baz.fp(baz, scope).apply(42);
100             assertEquals(val.get(), 42);
101         }
102     }
103 
104     @Test
105     public void testStructFieldFIFunctionPointer() {
106         try (ResourceScope scope = ResourceScope.newConfinedScope()) {
107             AtomicInteger val = new AtomicInteger(-1);
108             MemorySegment baz = Baz.allocate(scope);
109             Baz.fp$set(baz, Baz.fp.allocate((i) -> val.set(i), scope).address());
110             Baz.fp.ofAddress(Baz.fp$get(baz), scope).apply(42);
111             assertEquals(val.get(), 42);
112         }
113     }
114 
115     @Test
116     public void testGlobalFunctionPointer() {
117         try (ResourceScope scope = ResourceScope.newConfinedScope()) {
118             AtomicInteger val = new AtomicInteger(-1);
119             fp$set(fp.allocate((i) -> val.set(i), scope).address());
120             fp().apply(42);
121             assertEquals(val.get(), 42);
122         }
123     }
124 
125     @Test
126     public void testGlobalFIFunctionPointer() {
127         try (ResourceScope scope = ResourceScope.newConfinedScope()) {
128             AtomicInteger val = new AtomicInteger(-1);
129             fp$set(fp.allocate((i) -> val.set(i), scope).address());
130             fp.ofAddress(fp$get(), scope).apply(42);
131             assertEquals(val.get(), 42);
132         }
133     }
134 
135     @Test
136     public void testGlobalFIFunctionPointerAddress() {
137         try (ResourceScope scope = ResourceScope.newConfinedScope()) {
138             fp_addr$set(fp_addr.allocate((addr) -> MemoryAddress.ofLong(addr.toRawLongValue() + 1), scope).address());
139             assertEquals(fp_addr.ofAddress(fp_addr$get(), scope).apply(MemoryAddress.ofLong(42)), MemoryAddress.ofLong(43));
140         }
141     }
142 }