1 /* 2 * Copyright (c) 2019, 2020, 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 /* 26 * @test 27 * @run testng/othervm --enable-native-access=ALL-UNNAMED TestArrays 28 */ 29 30 import jdk.incubator.foreign.MemoryAddress; 31 import jdk.incubator.foreign.MemoryLayout; 32 import jdk.incubator.foreign.MemoryLayout.PathElement; 33 import jdk.incubator.foreign.MemoryLayouts; 34 import jdk.incubator.foreign.MemorySegment; 35 import jdk.incubator.foreign.ResourceScope; 36 import jdk.incubator.foreign.SequenceLayout; 37 38 import java.lang.invoke.VarHandle; 39 import java.util.function.BiConsumer; 40 import java.util.function.BiFunction; 41 import java.util.function.Consumer; 42 import java.util.function.Function; 43 44 import org.testng.annotations.*; 45 46 import static org.testng.Assert.*; 47 48 public class TestArrays { 49 50 static SequenceLayout bytes = MemoryLayout.sequenceLayout(100, 51 MemoryLayouts.JAVA_BYTE 52 ); 53 54 static SequenceLayout chars = MemoryLayout.sequenceLayout(100, 55 MemoryLayouts.JAVA_CHAR 56 ); 57 58 static SequenceLayout shorts = MemoryLayout.sequenceLayout(100, 59 MemoryLayouts.JAVA_SHORT 60 ); 61 62 static SequenceLayout ints = MemoryLayout.sequenceLayout(100, 63 MemoryLayouts.JAVA_INT 64 ); 65 66 static SequenceLayout floats = MemoryLayout.sequenceLayout(100, 67 MemoryLayouts.JAVA_FLOAT 68 ); 69 70 static SequenceLayout longs = MemoryLayout.sequenceLayout(100, 71 MemoryLayouts.JAVA_LONG 72 ); 73 74 static SequenceLayout doubles = MemoryLayout.sequenceLayout(100, 75 MemoryLayouts.JAVA_DOUBLE 76 ); 77 78 static VarHandle byteHandle = bytes.varHandle(byte.class, PathElement.sequenceElement()); 79 static VarHandle charHandle = chars.varHandle(char.class, PathElement.sequenceElement()); 80 static VarHandle shortHandle = shorts.varHandle(short.class, PathElement.sequenceElement()); 81 static VarHandle intHandle = ints.varHandle(int.class, PathElement.sequenceElement()); 82 static VarHandle floatHandle = floats.varHandle(float.class, PathElement.sequenceElement()); 83 static VarHandle longHandle = longs.varHandle(long.class, PathElement.sequenceElement()); 84 static VarHandle doubleHandle = doubles.varHandle(double.class, PathElement.sequenceElement()); 85 initBytes(MemorySegment base, SequenceLayout seq, BiConsumer<MemorySegment, Long> handleSetter)86 static void initBytes(MemorySegment base, SequenceLayout seq, BiConsumer<MemorySegment, Long> handleSetter) { 87 for (long i = 0; i < seq.elementCount().getAsLong() ; i++) { 88 handleSetter.accept(base, i); 89 } 90 } 91 checkBytes(MemorySegment base, SequenceLayout layout, Function<MemorySegment, Object> arrayFactory, BiFunction<MemorySegment, Long, Object> handleGetter)92 static void checkBytes(MemorySegment base, SequenceLayout layout, Function<MemorySegment, Object> arrayFactory, BiFunction<MemorySegment, Long, Object> handleGetter) { 93 int nelems = (int)layout.elementCount().getAsLong(); 94 Object arr = arrayFactory.apply(base); 95 for (int i = 0; i < nelems; i++) { 96 Object found = handleGetter.apply(base, (long) i); 97 Object expected = java.lang.reflect.Array.get(arr, i); 98 assertEquals(expected, found); 99 } 100 } 101 102 @Test(dataProvider = "arrays") testArrays(Consumer<MemorySegment> init, Consumer<MemorySegment> checker, MemoryLayout layout)103 public void testArrays(Consumer<MemorySegment> init, Consumer<MemorySegment> checker, MemoryLayout layout) { 104 MemorySegment segment = MemorySegment.allocateNative(layout, ResourceScope.newImplicitScope()); 105 init.accept(segment); 106 assertFalse(segment.isReadOnly()); 107 checker.accept(segment); 108 } 109 110 @Test(dataProvider = "elemLayouts", 111 expectedExceptions = IllegalStateException.class) testTooBigForArray(MemoryLayout layout, Function<MemorySegment, Object> arrayFactory)112 public void testTooBigForArray(MemoryLayout layout, Function<MemorySegment, Object> arrayFactory) { 113 MemoryLayout seq = MemoryLayout.sequenceLayout((Integer.MAX_VALUE * layout.byteSize()) + 1, layout); 114 //do not really allocate here, as it's way too much memory 115 MemorySegment segment = MemoryAddress.NULL.asSegment(seq.byteSize(), ResourceScope.globalScope()); 116 arrayFactory.apply(segment); 117 } 118 119 @Test(dataProvider = "elemLayouts", 120 expectedExceptions = IllegalStateException.class) testBadSize(MemoryLayout layout, Function<MemorySegment, Object> arrayFactory)121 public void testBadSize(MemoryLayout layout, Function<MemorySegment, Object> arrayFactory) { 122 if (layout.byteSize() == 1) throw new IllegalStateException(); //make it fail 123 try (ResourceScope scope = ResourceScope.newConfinedScope()) { 124 MemorySegment segment = MemorySegment.allocateNative(layout.byteSize() + 1, layout.byteSize(), scope); 125 arrayFactory.apply(segment); 126 } 127 } 128 129 @Test(dataProvider = "elemLayouts", 130 expectedExceptions = IllegalStateException.class) testArrayFromClosedSegment(MemoryLayout layout, Function<MemorySegment, Object> arrayFactory)131 public void testArrayFromClosedSegment(MemoryLayout layout, Function<MemorySegment, Object> arrayFactory) { 132 MemorySegment segment = MemorySegment.allocateNative(layout, ResourceScope.newConfinedScope()); 133 segment.scope().close(); 134 arrayFactory.apply(segment); 135 } 136 137 @DataProvider(name = "arrays") nativeAccessOps()138 public Object[][] nativeAccessOps() { 139 Consumer<MemorySegment> byteInitializer = 140 (base) -> initBytes(base, bytes, (addr, pos) -> byteHandle.set(addr, pos, (byte)(long)pos)); 141 Consumer<MemorySegment> charInitializer = 142 (base) -> initBytes(base, chars, (addr, pos) -> charHandle.set(addr, pos, (char)(long)pos)); 143 Consumer<MemorySegment> shortInitializer = 144 (base) -> initBytes(base, shorts, (addr, pos) -> shortHandle.set(addr, pos, (short)(long)pos)); 145 Consumer<MemorySegment> intInitializer = 146 (base) -> initBytes(base, ints, (addr, pos) -> intHandle.set(addr, pos, (int)(long)pos)); 147 Consumer<MemorySegment> floatInitializer = 148 (base) -> initBytes(base, floats, (addr, pos) -> floatHandle.set(addr, pos, (float)(long)pos)); 149 Consumer<MemorySegment> longInitializer = 150 (base) -> initBytes(base, longs, (addr, pos) -> longHandle.set(addr, pos, (long)pos)); 151 Consumer<MemorySegment> doubleInitializer = 152 (base) -> initBytes(base, doubles, (addr, pos) -> doubleHandle.set(addr, pos, (double)(long)pos)); 153 154 Consumer<MemorySegment> byteChecker = 155 (base) -> checkBytes(base, bytes, MemorySegment::toByteArray, (addr, pos) -> (byte)byteHandle.get(addr, pos)); 156 Consumer<MemorySegment> shortChecker = 157 (base) -> checkBytes(base, shorts, MemorySegment::toShortArray, (addr, pos) -> (short)shortHandle.get(addr, pos)); 158 Consumer<MemorySegment> charChecker = 159 (base) -> checkBytes(base, chars, MemorySegment::toCharArray, (addr, pos) -> (char)charHandle.get(addr, pos)); 160 Consumer<MemorySegment> intChecker = 161 (base) -> checkBytes(base, ints, MemorySegment::toIntArray, (addr, pos) -> (int)intHandle.get(addr, pos)); 162 Consumer<MemorySegment> floatChecker = 163 (base) -> checkBytes(base, floats, MemorySegment::toFloatArray, (addr, pos) -> (float)floatHandle.get(addr, pos)); 164 Consumer<MemorySegment> longChecker = 165 (base) -> checkBytes(base, longs, MemorySegment::toLongArray, (addr, pos) -> (long)longHandle.get(addr, pos)); 166 Consumer<MemorySegment> doubleChecker = 167 (base) -> checkBytes(base, doubles, MemorySegment::toDoubleArray, (addr, pos) -> (double)doubleHandle.get(addr, pos)); 168 169 return new Object[][]{ 170 {byteInitializer, byteChecker, bytes}, 171 {charInitializer, charChecker, chars}, 172 {shortInitializer, shortChecker, shorts}, 173 {intInitializer, intChecker, ints}, 174 {floatInitializer, floatChecker, floats}, 175 {longInitializer, longChecker, longs}, 176 {doubleInitializer, doubleChecker, doubles} 177 }; 178 } 179 180 @DataProvider(name = "elemLayouts") elemLayouts()181 public Object[][] elemLayouts() { 182 return new Object[][] { 183 { MemoryLayouts.JAVA_BYTE, (Function<MemorySegment, Object>) MemorySegment::toByteArray }, 184 { MemoryLayouts.JAVA_SHORT, (Function<MemorySegment, Object>) MemorySegment::toShortArray }, 185 { MemoryLayouts.JAVA_CHAR, (Function<MemorySegment, Object>) MemorySegment::toCharArray }, 186 { MemoryLayouts.JAVA_INT, (Function<MemorySegment, Object>) MemorySegment::toIntArray }, 187 { MemoryLayouts.JAVA_FLOAT, (Function<MemorySegment, Object>) MemorySegment::toFloatArray }, 188 { MemoryLayouts.JAVA_LONG, (Function<MemorySegment, Object>) MemorySegment::toLongArray }, 189 { MemoryLayouts.JAVA_DOUBLE, (Function<MemorySegment, Object>) MemorySegment::toDoubleArray } 190 }; 191 } 192 } 193