Path: blob/master/test/jdk/java/foreign/TestMismatch.java
41145 views
/*1* Copyright (c) 2020, 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 TestMismatch26*/2728import java.lang.invoke.VarHandle;29import java.util.ArrayList;30import java.util.List;31import java.util.concurrent.atomic.AtomicReference;32import java.util.function.IntFunction;3334import jdk.incubator.foreign.MemoryLayouts;35import jdk.incubator.foreign.MemorySegment;36import jdk.incubator.foreign.ResourceScope;37import org.testng.annotations.DataProvider;38import org.testng.annotations.Test;39import static java.lang.System.out;40import static org.testng.Assert.assertEquals;41import static org.testng.Assert.assertThrows;4243public class TestMismatch {4445final static VarHandle BYTE_HANDLE = MemoryLayouts.JAVA_BYTE.varHandle(byte.class);4647// stores a increasing sequence of values into the memory of the given segment48static MemorySegment initializeSegment(MemorySegment segment) {49for (int i = 0 ; i < segment.byteSize() ; i++) {50BYTE_HANDLE.set(segment.asSlice(i), (byte)i);51}52return segment;53}5455@Test(dataProvider = "slices")56public void testSameValues(MemorySegment ss1, MemorySegment ss2) {57out.format("testSameValues s1:%s, s2:%s\n", ss1, ss2);58MemorySegment s1 = initializeSegment(ss1);59MemorySegment s2 = initializeSegment(ss2);6061if (s1.byteSize() == s2.byteSize()) {62assertEquals(s1.mismatch(s2), -1); // identical63assertEquals(s2.mismatch(s1), -1);64} else if (s1.byteSize() > s2.byteSize()) {65assertEquals(s1.mismatch(s2), s2.byteSize()); // proper prefix66assertEquals(s2.mismatch(s1), s2.byteSize());67} else {68assert s1.byteSize() < s2.byteSize();69assertEquals(s1.mismatch(s2), s1.byteSize()); // proper prefix70assertEquals(s2.mismatch(s1), s1.byteSize());71}72}7374@Test(dataProvider = "slices")75public void testDifferentValues(MemorySegment s1, MemorySegment s2) {76out.format("testDifferentValues s1:%s, s2:%s\n", s1, s2);77s1 = initializeSegment(s1);78s2 = initializeSegment(s2);7980for (long i = s2.byteSize() -1 ; i >= 0; i--) {81long expectedMismatchOffset = i;82BYTE_HANDLE.set(s2.asSlice(i), (byte) 0xFF);8384if (s1.byteSize() == s2.byteSize()) {85assertEquals(s1.mismatch(s2), expectedMismatchOffset);86assertEquals(s2.mismatch(s1), expectedMismatchOffset);87} else if (s1.byteSize() > s2.byteSize()) {88assertEquals(s1.mismatch(s2), expectedMismatchOffset);89assertEquals(s2.mismatch(s1), expectedMismatchOffset);90} else {91assert s1.byteSize() < s2.byteSize();92var off = Math.min(s1.byteSize(), expectedMismatchOffset);93assertEquals(s1.mismatch(s2), off); // proper prefix94assertEquals(s2.mismatch(s1), off);95}96}97}9899@Test100public void testEmpty() {101var s1 = MemorySegment.ofArray(new byte[0]);102assertEquals(s1.mismatch(s1), -1);103try (ResourceScope scope = ResourceScope.newConfinedScope()) {104var nativeSegment = MemorySegment.allocateNative(4, 4, scope);105var s2 = nativeSegment.asSlice(0, 0);106assertEquals(s1.mismatch(s2), -1);107assertEquals(s2.mismatch(s1), -1);108}109}110111@Test112public void testLarge() {113// skip if not on 64 bits114if (MemoryLayouts.ADDRESS.byteSize() > 32) {115try (ResourceScope scope = ResourceScope.newConfinedScope()) {116var s1 = MemorySegment.allocateNative((long) Integer.MAX_VALUE + 10L, 8, scope);117var s2 = MemorySegment.allocateNative((long) Integer.MAX_VALUE + 10L, 8, scope);118assertEquals(s1.mismatch(s1), -1);119assertEquals(s1.mismatch(s2), -1);120assertEquals(s2.mismatch(s1), -1);121122testLargeAcrossMaxBoundary(s1, s2);123124testLargeMismatchAcrossMaxBoundary(s1, s2);125}126}127}128129private void testLargeAcrossMaxBoundary(MemorySegment s1, MemorySegment s2) {130for (long i = s2.byteSize() -1 ; i >= Integer.MAX_VALUE - 10L; i--) {131var s3 = s1.asSlice(0, i);132var s4 = s2.asSlice(0, i);133assertEquals(s3.mismatch(s3), -1);134assertEquals(s3.mismatch(s4), -1);135assertEquals(s4.mismatch(s3), -1);136}137}138139private void testLargeMismatchAcrossMaxBoundary(MemorySegment s1, MemorySegment s2) {140for (long i = s2.byteSize() -1 ; i >= Integer.MAX_VALUE - 10L; i--) {141BYTE_HANDLE.set(s2.asSlice(i), (byte) 0xFF);142long expectedMismatchOffset = i;143assertEquals(s1.mismatch(s2), expectedMismatchOffset);144assertEquals(s2.mismatch(s1), expectedMismatchOffset);145}146}147148static final Class<IllegalStateException> ISE = IllegalStateException.class;149static final Class<UnsupportedOperationException> UOE = UnsupportedOperationException.class;150151@Test152public void testClosed() {153MemorySegment s1, s2;154try (ResourceScope scope = ResourceScope.newConfinedScope()) {155s1 = MemorySegment.allocateNative(4, 1, scope);156s2 = MemorySegment.allocateNative(4, 1, scope);157}158assertThrows(ISE, () -> s1.mismatch(s1));159assertThrows(ISE, () -> s1.mismatch(s2));160assertThrows(ISE, () -> s2.mismatch(s1));161}162163@Test164public void testThreadAccess() throws Exception {165try (ResourceScope scope = ResourceScope.newConfinedScope()) {166var segment = MemorySegment.allocateNative(4, 1, scope);167{168AtomicReference<RuntimeException> exception = new AtomicReference<>();169Runnable action = () -> {170try {171MemorySegment.ofArray(new byte[4]).mismatch(segment);172} catch (RuntimeException e) {173exception.set(e);174}175};176Thread thread = new Thread(action);177thread.start();178thread.join();179180RuntimeException e = exception.get();181if (!(e instanceof IllegalStateException)) {182throw e;183}184}185{186AtomicReference<RuntimeException> exception = new AtomicReference<>();187Runnable action = () -> {188try {189segment.mismatch(MemorySegment.ofArray(new byte[4]));190} catch (RuntimeException e) {191exception.set(e);192}193};194Thread thread = new Thread(action);195thread.start();196thread.join();197198RuntimeException e = exception.get();199if (!(e instanceof IllegalStateException)) {200throw e;201}202}203}204}205206enum SegmentKind {207NATIVE(i -> MemorySegment.allocateNative(i, ResourceScope.newImplicitScope())),208ARRAY(i -> MemorySegment.ofArray(new byte[i]));209210final IntFunction<MemorySegment> segmentFactory;211212SegmentKind(IntFunction<MemorySegment> segmentFactory) {213this.segmentFactory = segmentFactory;214}215216MemorySegment makeSegment(int elems) {217return segmentFactory.apply(elems);218}219}220221@DataProvider(name = "slices")222static Object[][] slices() {223int[] sizes = { 16, 8, 1 };224List<MemorySegment> aSlices = new ArrayList<>();225List<MemorySegment> bSlices = new ArrayList<>();226for (List<MemorySegment> slices : List.of(aSlices, bSlices)) {227for (SegmentKind kind : SegmentKind.values()) {228MemorySegment segment = kind.makeSegment(16);229//compute all slices230for (int size : sizes) {231for (int index = 0 ; index < 16 ; index += size) {232MemorySegment slice = segment.asSlice(index, size);233slices.add(slice);234}235}236}237}238assert aSlices.size() == bSlices.size();239Object[][] sliceArray = new Object[aSlices.size() * bSlices.size()][];240for (int i = 0 ; i < aSlices.size() ; i++) {241for (int j = 0 ; j < bSlices.size() ; j++) {242sliceArray[i * aSlices.size() + j] = new Object[] { aSlices.get(i), bSlices.get(j) };243}244}245return sliceArray;246}247}248249250