Path: blob/master/test/jdk/java/foreign/TestLayouts.java
41145 views
/*1* Copyright (c) 2019, Oracle and/or its affiliates. All rights reserved.2* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.3*4* This code is free software; you can redistribute it and/or modify it5* under the terms of the GNU General Public License version 2 only, as6* published by the Free Software Foundation.7*8* This code is distributed in the hope that it will be useful, but WITHOUT9* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or10* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License11* version 2 for more details (a copy is included in the LICENSE file that12* accompanied this code).13*14* You should have received a copy of the GNU General Public License version15* 2 along with this work; if not, write to the Free Software Foundation,16* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.17*18* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA19* or visit www.oracle.com if you need additional information or have any20* questions.21*/2223/*24* @test25* @run testng TestLayouts26*/2728import jdk.incubator.foreign.*;2930import java.lang.invoke.VarHandle;31import java.nio.ByteOrder;32import java.util.function.LongFunction;33import java.util.stream.Stream;3435import org.testng.annotations.*;36import static org.testng.Assert.*;3738public class TestLayouts {3940@Test(dataProvider = "badLayoutSizes", expectedExceptions = IllegalArgumentException.class)41public void testBadLayoutSize(SizedLayoutFactory factory, long size) {42factory.make(size);43}4445@Test(dataProvider = "badAlignments", expectedExceptions = IllegalArgumentException.class)46public void testBadLayoutAlignment(MemoryLayout layout, long alignment) {47layout.withBitAlignment(alignment);48}4950@Test51public void testVLAInStruct() {52MemoryLayout layout = MemoryLayout.structLayout(53MemoryLayouts.JAVA_INT.withName("size"),54MemoryLayout.paddingLayout(32),55MemoryLayout.sequenceLayout(MemoryLayouts.JAVA_DOUBLE).withName("arr"));56assertFalse(layout.hasSize());57VarHandle size_handle = layout.varHandle(int.class, MemoryLayout.PathElement.groupElement("size"));58VarHandle array_elem_handle = layout.varHandle(double.class,59MemoryLayout.PathElement.groupElement("arr"),60MemoryLayout.PathElement.sequenceElement());61try (ResourceScope scope = ResourceScope.newConfinedScope()) {62MemorySegment segment = MemorySegment.allocateNative(63layout.map(l -> ((SequenceLayout)l).withElementCount(4), MemoryLayout.PathElement.groupElement("arr")), scope);64size_handle.set(segment, 4);65for (int i = 0 ; i < 4 ; i++) {66array_elem_handle.set(segment, i, (double)i);67}68//check69assertEquals(4, (int)size_handle.get(segment));70for (int i = 0 ; i < 4 ; i++) {71assertEquals((double)i, (double)array_elem_handle.get(segment, i));72}73}74}7576@Test77public void testVLAInSequence() {78MemoryLayout layout = MemoryLayout.structLayout(79MemoryLayouts.JAVA_INT.withName("size"),80MemoryLayout.paddingLayout(32),81MemoryLayout.sequenceLayout(1, MemoryLayout.sequenceLayout(MemoryLayouts.JAVA_DOUBLE)).withName("arr"));82assertFalse(layout.hasSize());83VarHandle size_handle = layout.varHandle(int.class, MemoryLayout.PathElement.groupElement("size"));84VarHandle array_elem_handle = layout.varHandle(double.class,85MemoryLayout.PathElement.groupElement("arr"),86MemoryLayout.PathElement.sequenceElement(0),87MemoryLayout.PathElement.sequenceElement());88try (ResourceScope scope = ResourceScope.newConfinedScope()) {89MemorySegment segment = MemorySegment.allocateNative(90layout.map(l -> ((SequenceLayout)l).withElementCount(4), MemoryLayout.PathElement.groupElement("arr"), MemoryLayout.PathElement.sequenceElement()), scope);91size_handle.set(segment, 4);92for (int i = 0 ; i < 4 ; i++) {93array_elem_handle.set(segment, i, (double)i);94}95//check96assertEquals(4, (int)size_handle.get(segment));97for (int i = 0 ; i < 4 ; i++) {98assertEquals((double)i, (double)array_elem_handle.get(segment, i));99}100}101}102103@Test104public void testIndexedSequencePath() {105MemoryLayout seq = MemoryLayout.sequenceLayout(10, MemoryLayouts.JAVA_INT);106try (ResourceScope scope = ResourceScope.newConfinedScope()) {107MemorySegment segment = MemorySegment.allocateNative(seq, scope);108VarHandle indexHandle = seq.varHandle(int.class, MemoryLayout.PathElement.sequenceElement());109// init segment110for (int i = 0 ; i < 10 ; i++) {111indexHandle.set(segment, (long)i, i);112}113//check statically indexed handles114for (int i = 0 ; i < 10 ; i++) {115VarHandle preindexHandle = seq.varHandle(int.class, MemoryLayout.PathElement.sequenceElement(i));116int expected = (int)indexHandle.get(segment, (long)i);117int found = (int)preindexHandle.get(segment);118assertEquals(expected, found);119}120}121}122123@Test(dataProvider = "unboundLayouts", expectedExceptions = UnsupportedOperationException.class)124public void testUnboundSize(MemoryLayout layout, long align) {125layout.bitSize();126}127128@Test(dataProvider = "unboundLayouts")129public void testUnboundAlignment(MemoryLayout layout, long align) {130assertEquals(align, layout.bitAlignment());131}132133@Test(dataProvider = "unboundLayouts")134public void testUnboundEquals(MemoryLayout layout, long align) {135assertTrue(layout.equals(layout));136}137138@Test(dataProvider = "unboundLayouts")139public void testUnboundHash(MemoryLayout layout, long align) {140layout.hashCode();141}142143@Test(expectedExceptions = IllegalArgumentException.class)144public void testBadUnboundSequenceLayoutResize() {145SequenceLayout seq = MemoryLayout.sequenceLayout(MemoryLayouts.JAVA_INT);146seq.withElementCount(-1);147}148149@Test(expectedExceptions = IllegalArgumentException.class)150public void testBadBoundSequenceLayoutResize() {151SequenceLayout seq = MemoryLayout.sequenceLayout(10, MemoryLayouts.JAVA_INT);152seq.withElementCount(-1);153}154155@Test156public void testEmptyGroup() {157MemoryLayout struct = MemoryLayout.structLayout();158assertEquals(struct.bitSize(), 0);159assertEquals(struct.bitAlignment(), 1);160161MemoryLayout union = MemoryLayout.unionLayout();162assertEquals(union.bitSize(), 0);163assertEquals(union.bitAlignment(), 1);164}165166@Test167public void testStructSizeAndAlign() {168MemoryLayout struct = MemoryLayout.structLayout(169MemoryLayout.paddingLayout(8),170MemoryLayouts.JAVA_BYTE,171MemoryLayouts.JAVA_CHAR,172MemoryLayouts.JAVA_INT,173MemoryLayouts.JAVA_LONG174);175assertEquals(struct.byteSize(), 1 + 1 + 2 + 4 + 8);176assertEquals(struct.byteAlignment(), MemoryLayouts.ADDRESS.byteAlignment());177}178179@Test(dataProvider="basicLayouts")180public void testPaddingNoAlign(MemoryLayout layout) {181assertEquals(MemoryLayout.paddingLayout(layout.bitSize()).bitAlignment(), 1);182}183184@Test(dataProvider="basicLayouts")185public void testStructPaddingAndAlign(MemoryLayout layout) {186MemoryLayout struct = MemoryLayout.structLayout(187layout, MemoryLayout.paddingLayout(128 - layout.bitSize()));188assertEquals(struct.bitAlignment(), layout.bitAlignment());189}190191@Test(dataProvider="basicLayouts")192public void testUnionPaddingAndAlign(MemoryLayout layout) {193MemoryLayout struct = MemoryLayout.unionLayout(194layout, MemoryLayout.paddingLayout(128 - layout.bitSize()));195assertEquals(struct.bitAlignment(), layout.bitAlignment());196}197198@Test199public void testUnionSizeAndAlign() {200MemoryLayout struct = MemoryLayout.unionLayout(201MemoryLayouts.JAVA_BYTE,202MemoryLayouts.JAVA_CHAR,203MemoryLayouts.JAVA_INT,204MemoryLayouts.JAVA_LONG205);206assertEquals(struct.byteSize(), 8);207assertEquals(struct.byteAlignment(), MemoryLayouts.ADDRESS.byteAlignment());208}209210@Test(dataProvider = "layoutKinds")211public void testPadding(LayoutKind kind) {212assertEquals(kind == LayoutKind.PADDING, kind.layout.isPadding());213}214215@Test(dataProvider="layoutsAndAlignments")216public void testAlignmentString(MemoryLayout layout, long bitAlign) {217long[] alignments = { 8, 16, 32, 64, 128 };218for (long a : alignments) {219if (layout.bitAlignment() == layout.bitSize()) {220assertFalse(layout.toString().contains("%"));221assertEquals(layout.withBitAlignment(a).toString().contains("%"), a != bitAlign);222}223}224}225226@DataProvider(name = "badLayoutSizes")227public Object[][] factoriesAndSizes() {228return new Object[][] {229{ SizedLayoutFactory.VALUE_BE, 0 },230{ SizedLayoutFactory.VALUE_BE, -1 },231{ SizedLayoutFactory.VALUE_LE, 0 },232{ SizedLayoutFactory.VALUE_LE, -1 },233{ SizedLayoutFactory.PADDING, 0 },234{ SizedLayoutFactory.PADDING, -1 },235{ SizedLayoutFactory.SEQUENCE, -1 }236};237}238239@DataProvider(name = "unboundLayouts")240public Object[][] unboundLayouts() {241return new Object[][] {242{ MemoryLayout.sequenceLayout(MemoryLayouts.JAVA_INT), 32 },243{ MemoryLayout.sequenceLayout(MemoryLayout.sequenceLayout(MemoryLayouts.JAVA_INT)), 32 },244{ MemoryLayout.sequenceLayout(4, MemoryLayout.sequenceLayout(MemoryLayouts.JAVA_INT)), 32 },245{ MemoryLayout.structLayout(MemoryLayout.sequenceLayout(MemoryLayouts.JAVA_INT)), 32 },246{ MemoryLayout.structLayout(MemoryLayout.sequenceLayout(MemoryLayout.sequenceLayout(MemoryLayouts.JAVA_INT))), 32 },247{ MemoryLayout.structLayout(MemoryLayout.sequenceLayout(4, MemoryLayout.sequenceLayout(MemoryLayouts.JAVA_INT))), 32 },248{ MemoryLayout.unionLayout(MemoryLayout.sequenceLayout(MemoryLayouts.JAVA_INT)), 32 },249{ MemoryLayout.unionLayout(MemoryLayout.sequenceLayout(MemoryLayout.sequenceLayout(MemoryLayouts.JAVA_INT))), 32 },250{ MemoryLayout.unionLayout(MemoryLayout.sequenceLayout(4, MemoryLayout.sequenceLayout(MemoryLayouts.JAVA_INT))), 32 },251};252}253254@DataProvider(name = "badAlignments")255public Object[][] layoutsAndBadAlignments() {256LayoutKind[] layoutKinds = LayoutKind.values();257Object[][] values = new Object[layoutKinds.length * 2][2];258for (int i = 0; i < layoutKinds.length ; i++) {259values[i * 2] = new Object[] { layoutKinds[i].layout, 3 }; // smaller than 8260values[(i * 2) + 1] = new Object[] { layoutKinds[i].layout, 18 }; // not a power of 2261}262return values;263}264265@DataProvider(name = "layoutKinds")266public Object[][] layoutsKinds() {267return Stream.of(LayoutKind.values())268.map(lk -> new Object[] { lk })269.toArray(Object[][]::new);270}271272enum SizedLayoutFactory {273VALUE_LE(size -> MemoryLayout.valueLayout(size, ByteOrder.LITTLE_ENDIAN)),274VALUE_BE(size -> MemoryLayout.valueLayout(size, ByteOrder.BIG_ENDIAN)),275PADDING(MemoryLayout::paddingLayout),276SEQUENCE(size -> MemoryLayout.sequenceLayout(size, MemoryLayouts.PAD_8));277278private final LongFunction<MemoryLayout> factory;279280SizedLayoutFactory(LongFunction<MemoryLayout> factory) {281this.factory = factory;282}283284MemoryLayout make(long size) {285return factory.apply(size);286}287}288289enum LayoutKind {290VALUE_LE(MemoryLayouts.BITS_8_LE),291VALUE_BE(MemoryLayouts.BITS_8_BE),292PADDING(MemoryLayouts.PAD_8),293SEQUENCE(MemoryLayout.sequenceLayout(1, MemoryLayouts.PAD_8)),294STRUCT(MemoryLayout.structLayout(MemoryLayouts.PAD_8, MemoryLayouts.PAD_8)),295UNION(MemoryLayout.unionLayout(MemoryLayouts.PAD_8, MemoryLayouts.PAD_8));296297final MemoryLayout layout;298299LayoutKind(MemoryLayout layout) {300this.layout = layout;301}302}303304@DataProvider(name = "basicLayouts")305public Object[][] basicLayouts() {306return Stream.of(basicLayouts)307.map(l -> new Object[] { l })308.toArray(Object[][]::new);309}310311@DataProvider(name = "layoutsAndAlignments")312public Object[][] layoutsAndAlignments() {313Object[][] layoutsAndAlignments = new Object[basicLayouts.length * 4][];314int i = 0;315//add basic layouts316for (MemoryLayout l : basicLayouts) {317layoutsAndAlignments[i++] = new Object[] { l, l.bitAlignment() };318}319//add basic layouts wrapped in a sequence with given size320for (MemoryLayout l : basicLayouts) {321layoutsAndAlignments[i++] = new Object[] { MemoryLayout.sequenceLayout(4, l), l.bitAlignment() };322}323//add basic layouts wrapped in a struct324for (MemoryLayout l : basicLayouts) {325layoutsAndAlignments[i++] = new Object[] { MemoryLayout.structLayout(l), l.bitAlignment() };326}327//add basic layouts wrapped in a union328for (MemoryLayout l : basicLayouts) {329layoutsAndAlignments[i++] = new Object[] { MemoryLayout.unionLayout(l), l.bitAlignment() };330}331return layoutsAndAlignments;332}333334static MemoryLayout[] basicLayouts = {335MemoryLayouts.JAVA_BYTE,336MemoryLayouts.JAVA_CHAR,337MemoryLayouts.JAVA_SHORT,338MemoryLayouts.JAVA_INT,339MemoryLayouts.JAVA_FLOAT,340MemoryLayouts.JAVA_LONG,341MemoryLayouts.JAVA_DOUBLE,342};343}344345346