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