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 TestSegmentOffset
28 */
29
30 import java.lang.foreign.Arena;
31 import java.lang.foreign.MemorySegment;
32
33 import org.testng.annotations.DataProvider;
34 import org.testng.annotations.Test;
35
36 import java.util.ArrayList;
37 import java.util.List;
38 import java.util.function.IntFunction;
39 import static java.lang.System.out;
40 import static java.lang.foreign.ValueLayout.JAVA_BYTE;
41 import static org.testng.Assert.*;
42
43 public class TestSegmentOffset {
44
45 @Test(dataProvider = "slices")
46 public void testOffset(SegmentSlice s1, SegmentSlice s2) {
47 if (s1.contains(s2)) {
48 // check that a segment and its overlapping segment point to same elements
49 long offset = s1.segment.segmentOffset(s2.segment);
50 for (int i = 0; i < s2.size(); i++) {
51 out.format("testOffset s1:%s, s2:%s, offset:%d, i:%s\n", s1, s2, offset, i);
52 byte expected = s2.segment.get(JAVA_BYTE, i);
53 byte found = s1.segment.get(JAVA_BYTE, i + offset);
54 assertEquals(found, expected);
55 }
56 } else if (s1.kind != s2.kind) {
57 // check that offset from s1 to s2 fails
58 try {
59 long offset = s1.segment.segmentOffset(s2.segment);
60 out.format("testOffset s1:%s, s2:%s, offset:%d\n", s1, s2, offset);
61 fail("offset unexpectedly passed!");
62 } catch (UnsupportedOperationException ex) {
63 assertTrue(ex.getMessage().contains("Cannot compute offset from native to heap (or vice versa)."));
64 }
65 } else if (!s2.contains(s1)) {
66 // disjoint segments - check that offset is out of bounds
67 long offset = s1.segment.segmentOffset(s2.segment);
68 for (int i = 0; i < s2.size(); i++) {
69 out.format("testOffset s1:%s, s2:%s, offset:%d, i:%s\n", s1, s2, offset, i);
70 s2.segment.get(JAVA_BYTE, i);
71 try {
72 s1.segment.get(JAVA_BYTE, i + offset);
73 fail("Offset on a disjoint segment is not out of bounds!");
74 } catch (IndexOutOfBoundsException ex) {
75 assertTrue(true);
76 }
77 }
78 }
79 }
80
81 static class SegmentSlice {
82
83 enum Kind {
84 NATIVE(i -> Arena.ofAuto().allocate(i, 1)),
85 ARRAY(i -> MemorySegment.ofArray(new byte[i]));
86
87 final IntFunction<MemorySegment> segmentFactory;
99 final int first;
100 final int last;
101 final MemorySegment segment;
102
103 public SegmentSlice(Kind kind, int first, int last, MemorySegment segment) {
104 this.kind = kind;
105 this.first = first;
106 this.last = last;
107 this.segment = segment;
108 }
109
110 boolean contains(SegmentSlice other) {
111 return kind == other.kind &&
112 first <= other.first &&
113 last >= other.last;
114 }
115
116 int size() {
117 return last - first + 1;
118 }
119 }
120
121 @DataProvider(name = "slices")
122 static Object[][] slices() {
123 int[] sizes = { 16, 8, 4, 2, 1 };
124 List<SegmentSlice> slices = new ArrayList<>();
125 for (SegmentSlice.Kind kind : SegmentSlice.Kind.values()) {
126 // init root segment
127 MemorySegment segment = kind.makeSegment(16);
128 for (int i = 0 ; i < 16 ; i++) {
129 segment.set(JAVA_BYTE, i, (byte)i);
130 }
131 // compute all slices
132 for (int size : sizes) {
133 for (int index = 0 ; index < 16 ; index += size) {
134 MemorySegment slice = segment.asSlice(index, size);
135 slices.add(new SegmentSlice(kind, index, index + size - 1, slice));
136 }
137 }
138 }
|
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 TestSegmentOffset
27 */
28
29 import java.lang.foreign.Arena;
30 import java.lang.foreign.MemorySegment;
31
32 import org.testng.SkipException;
33 import org.testng.annotations.DataProvider;
34 import org.testng.annotations.Test;
35
36 import java.util.ArrayList;
37 import java.util.List;
38 import java.util.function.IntFunction;
39 import static java.lang.System.out;
40 import static java.lang.foreign.ValueLayout.JAVA_BYTE;
41 import static org.testng.Assert.*;
42
43 public class TestSegmentOffset {
44
45 @Test(dataProvider = "slices")
46 public void testOffset(SegmentSlice s1, SegmentSlice s2) {
47 if (s1.kind != s2.kind) {
48 throw new SkipException("Slices of different segment kinds");
49 }
50 if (s1.contains(s2)) {
51 // check that a segment and its overlapping segment point to same elements
52 long offset = s1.offset(s2);
53 for (int i = 0; i < s2.size(); i++) {
54 out.format("testOffset s1:%s, s2:%s, offset:%d, i:%s\n", s1, s2, offset, i);
55 byte expected = s2.segment.get(JAVA_BYTE, i);
56 byte found = s1.segment.get(JAVA_BYTE, i + offset);
57 assertEquals(found, expected);
58 }
59 } else if (!s2.contains(s1)) {
60 // disjoint segments - check that offset is out of bounds
61 long offset = s1.offset(s2);
62 for (int i = 0; i < s2.size(); i++) {
63 out.format("testOffset s1:%s, s2:%s, offset:%d, i:%s\n", s1, s2, offset, i);
64 s2.segment.get(JAVA_BYTE, i);
65 try {
66 s1.segment.get(JAVA_BYTE, i + offset);
67 fail("Offset on a disjoint segment is not out of bounds!");
68 } catch (IndexOutOfBoundsException ex) {
69 assertTrue(true);
70 }
71 }
72 }
73 }
74
75 static class SegmentSlice {
76
77 enum Kind {
78 NATIVE(i -> Arena.ofAuto().allocate(i, 1)),
79 ARRAY(i -> MemorySegment.ofArray(new byte[i]));
80
81 final IntFunction<MemorySegment> segmentFactory;
93 final int first;
94 final int last;
95 final MemorySegment segment;
96
97 public SegmentSlice(Kind kind, int first, int last, MemorySegment segment) {
98 this.kind = kind;
99 this.first = first;
100 this.last = last;
101 this.segment = segment;
102 }
103
104 boolean contains(SegmentSlice other) {
105 return kind == other.kind &&
106 first <= other.first &&
107 last >= other.last;
108 }
109
110 int size() {
111 return last - first + 1;
112 }
113
114 long offset(SegmentSlice that) {
115 return that.segment.address() - segment.address();
116 }
117 }
118
119 @DataProvider(name = "slices")
120 static Object[][] slices() {
121 int[] sizes = { 16, 8, 4, 2, 1 };
122 List<SegmentSlice> slices = new ArrayList<>();
123 for (SegmentSlice.Kind kind : SegmentSlice.Kind.values()) {
124 // init root segment
125 MemorySegment segment = kind.makeSegment(16);
126 for (int i = 0 ; i < 16 ; i++) {
127 segment.set(JAVA_BYTE, i, (byte)i);
128 }
129 // compute all slices
130 for (int size : sizes) {
131 for (int index = 0 ; index < 16 ; index += size) {
132 MemorySegment slice = segment.asSlice(index, size);
133 slices.add(new SegmentSlice(kind, index, index + size - 1, slice));
134 }
135 }
136 }
|