--- /dev/null 2019-12-04 18:44:18.020007537 +0000 +++ new/test/jdk/java/foreign/TestMemoryCopy.java 2019-12-09 18:15:54.324443874 +0000 @@ -0,0 +1,145 @@ +/* + * Copyright (c) 2019, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + * + */ + +/* + * @test + * @run testng TestMemoryCopy + */ + +import jdk.incubator.foreign.MemoryAddress; +import jdk.incubator.foreign.MemoryHandles; +import jdk.incubator.foreign.MemoryLayouts; +import jdk.incubator.foreign.MemorySegment; +import org.testng.annotations.DataProvider; +import org.testng.annotations.Test; + +import java.lang.invoke.VarHandle; +import java.util.ArrayList; +import java.util.Collections; +import java.util.List; +import java.util.function.IntFunction; +import java.util.stream.Collectors; +import java.util.stream.IntStream; + +import static org.testng.Assert.*; + +public class TestMemoryCopy { + + final static VarHandle BYTE_HANDLE = MemoryLayouts.JAVA_BYTE.varHandle(byte.class); + + @Test(dataProvider = "slices") + public void testCopy(SegmentSlice s1, SegmentSlice s2) { + MemoryAddress addr1 = s1.segment.baseAddress(); + MemoryAddress addr2 = s2.segment.baseAddress(); + int size = Math.min(s1.size(), s2.size()); + boolean overlap = SegmentSlice.overlap(s1, s2, size); + //prepare source and target segments + for (int i = 0 ; i < size ; i++) { + BYTE_HANDLE.set(addr1.offset(i), (byte)i); + BYTE_HANDLE.set(addr2.offset(i), (byte)0); + } + try { + MemoryAddress.copy(addr1, addr2, size); + assertFalse(overlap); + //check that copy actually worked + for (int i = 0 ; i < size ; i++) { + assertEquals((byte)i, BYTE_HANDLE.get(addr2.offset(i))); + } + + } catch (IllegalArgumentException ex) { + assertTrue(overlap); + } + } + + static class SegmentSlice { + + enum Kind { + NATIVE(MemorySegment::allocateNative), + ARRAY(i -> MemorySegment.ofArray(new byte[i])); + + final IntFunction segmentFactory; + + Kind(IntFunction segmentFactory) { + this.segmentFactory = segmentFactory; + } + + MemorySegment makeSegment(int elems) { + return segmentFactory.apply(elems); + } + } + + final Kind kind; + final int first; + final int last; + final MemorySegment segment; + + public SegmentSlice(Kind kind, int first, int last, MemorySegment segment) { + this.kind = kind; + this.first = first; + this.last = last; + this.segment = segment; + } + + List range(int size) { + return IntStream.range(first, last + 1) + .limit(size) + .boxed() + .collect(Collectors.toList()); + } + + static boolean overlap(SegmentSlice s1, SegmentSlice s2, int size) { + if (s1.kind != s2.kind) { + return false; + } + return !Collections.disjoint(s1.range(size), s2.range(size)); + } + + int size() { + return last - first + 1; + } + } + + @DataProvider(name = "slices") + static Object[][] slices() { + int[] sizes = { 16, 8, 4, 2, 1 }; + List slices = new ArrayList<>(); + for (SegmentSlice.Kind kind : SegmentSlice.Kind.values()) { + MemorySegment segment = kind.makeSegment(16); + //compute all slices + for (int size : sizes) { + for (int index = 0 ; index < 16 ; index += size) { + MemorySegment slice = segment.asSlice(index, size); + slices.add(new SegmentSlice(kind, index, index + size - 1, slice)); + } + } + } + Object[][] sliceArray = new Object[slices.size() * slices.size()][]; + for (int i = 0 ; i < slices.size() ; i++) { + for (int j = 0 ; j < slices.size() ; j++) { + sliceArray[i * slices.size() + j] = new Object[] { slices.get(i), slices.get(j) }; + } + } + return sliceArray; + } +}