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