1 /* 2 * Copyright (c) 2021, 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 * @enablePreview 27 * @run testng/othervm TestSegmentOverlap 28 */ 29 30 import java.io.File; 31 import java.io.IOException; 32 import java.lang.foreign.Arena; 33 import java.nio.channels.FileChannel; 34 import java.nio.file.Files; 35 import java.nio.file.Path; 36 import java.nio.file.StandardOpenOption; 37 import java.util.List; 38 import java.util.function.Supplier; 39 import java.lang.foreign.MemorySegment; 40 41 import org.testng.annotations.Test; 42 import org.testng.annotations.DataProvider; 43 import static java.lang.System.out; 44 import static org.testng.Assert.*; 45 46 public class TestSegmentOverlap { 47 48 static Path tempPath; 49 50 static { 51 try { 52 File file = File.createTempFile("buffer", "txt"); 53 file.deleteOnExit(); 54 tempPath = file.toPath(); 55 Files.write(file.toPath(), new byte[16], StandardOpenOption.WRITE); 56 57 } catch (IOException ex) { 58 throw new ExceptionInInitializerError(ex); 59 } 60 } 61 62 @DataProvider(name = "segmentFactories") 63 public Object[][] segmentFactories() { 64 List<Supplier<MemorySegment>> l = List.of( 65 () -> Arena.ofAuto().allocate(16, 1), 66 () -> { 67 try (FileChannel fileChannel = FileChannel.open(tempPath, StandardOpenOption.READ, StandardOpenOption.WRITE)) { 68 return fileChannel.map(FileChannel.MapMode.READ_WRITE, 0L, 16L, Arena.ofAuto()); 69 } catch (IOException e) { 70 throw new RuntimeException(e); 71 } 72 }, 73 () -> MemorySegment.ofArray(new byte[] { 0x00, 0x01, 0x02, 0x03 } ), 74 () -> MemorySegment.ofArray(new char[] {'a', 'b', 'c', 'd' } ), 75 () -> MemorySegment.ofArray(new double[] { 1d, 2d, 3d, 4d} ), 76 () -> MemorySegment.ofArray(new float[] { 1.0f, 2.0f, 3.0f, 4.0f } ), 77 () -> MemorySegment.ofArray(new int[] { 1, 2, 3, 4 }), 78 () -> MemorySegment.ofArray(new long[] { 1L, 2L, 3L, 4L } ), 79 () -> MemorySegment.ofArray(new short[] { 1, 2, 3, 4 } ) 80 ); 81 return l.stream().map(s -> new Object[] { s }).toArray(Object[][]::new); 82 } 83 84 @Test(dataProvider="segmentFactories") 85 public void testBasic(Supplier<MemorySegment> segmentSupplier) { 86 var s1 = segmentSupplier.get(); 87 var s2 = segmentSupplier.get(); 88 var sOther = s1.isNative() ? OtherSegmentFactory.HEAP.factory.get() 89 : OtherSegmentFactory.NATIVE.factory.get(); 90 out.format("testBasic s1:%s, s2:%s, sOther:%s\n", s1, s2, sOther); 91 assertTrue(s1.asOverlappingSlice(s2).isEmpty()); 92 assertTrue(s2.asOverlappingSlice(s1).isEmpty()); 93 assertTrue(s1.asOverlappingSlice(sOther).isEmpty()); 94 } 95 96 @Test(dataProvider="segmentFactories") 97 public void testIdentical(Supplier<MemorySegment> segmentSupplier) { 98 var s1 = segmentSupplier.get(); 99 var s2 = s1.asReadOnly(); 100 out.format("testIdentical s1:%s, s2:%s\n", s1, s2); 101 assertEquals(s1.asOverlappingSlice(s2).get().byteSize(), s1.byteSize()); 102 assertEquals(s1.asOverlappingSlice(s2).get().scope(), s1.scope()); 103 104 assertEquals(s2.asOverlappingSlice(s1).get().byteSize(), s2.byteSize()); 105 assertEquals(s2.asOverlappingSlice(s1).get().scope(), s2.scope()); 106 107 if (s1.isNative()) { 108 assertEquals(s1.asOverlappingSlice(s2).get().address(), s1.address()); 109 assertEquals(s2.asOverlappingSlice(s1).get().address(), s2.address()); 110 } 111 } 112 113 @Test(dataProvider="segmentFactories") 114 public void testSlices(Supplier<MemorySegment> segmentSupplier) { 115 MemorySegment s1 = segmentSupplier.get(); 116 MemorySegment s2 = segmentSupplier.get(); 117 for (int offset = 0 ; offset < 4 ; offset++) { 118 MemorySegment slice = s1.asSlice(offset); 119 out.format("testSlices s1:%s, s2:%s, slice:%s, offset:%d\n", s1, s2, slice, offset); 120 assertEquals(s1.asOverlappingSlice(slice).get().byteSize(), s1.byteSize() - offset); 121 assertEquals(s1.asOverlappingSlice(slice).get().scope(), s1.scope()); 122 123 assertEquals(slice.asOverlappingSlice(s1).get().byteSize(), slice.byteSize()); 124 assertEquals(slice.asOverlappingSlice(s1).get().scope(), slice.scope()); 125 126 if (s1.isNative()) { 127 assertEquals(s1.asOverlappingSlice(slice).get().address(), s1.address() + offset); 128 assertEquals(slice.asOverlappingSlice(s1).get().address(), slice.address()); 129 } 130 assertTrue(s2.asOverlappingSlice(slice).isEmpty()); 131 } 132 } 133 134 enum OtherSegmentFactory { 135 NATIVE(() -> Arena.ofAuto().allocate(16, 1)), 136 HEAP(() -> MemorySegment.ofArray(new byte[]{16})); 137 138 final Supplier<MemorySegment> factory; 139 140 OtherSegmentFactory(Supplier<MemorySegment> segmentFactory) { 141 this.factory = segmentFactory; 142 } 143 } 144 }