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 TestLayouts
28 */
29
30 import java.lang.foreign.*;
31
32 import java.lang.invoke.VarHandle;
33 import java.nio.ByteOrder;
34 import java.util.ArrayList;
35 import java.util.List;
36 import java.util.function.LongFunction;
37 import java.util.stream.Stream;
38
39 import org.testng.annotations.*;
40
41 import static java.lang.foreign.ValueLayout.*;
42 import static org.testng.Assert.*;
43
44 public class TestLayouts {
45
46 @Test(dataProvider = "badAlignments", expectedExceptions = IllegalArgumentException.class)
81 MemoryLayout other = layout.withByteAlignment(16).withByteAlignment(layout.byteAlignment());
82 assertTrue(layout.equals(other));
83
84 }
85
86 public void testTargetLayoutEquals() {
87 MemoryLayout differentTargetLayout = ADDRESS.withTargetLayout(JAVA_CHAR);
88 assertFalse(ADDRESS.equals(differentTargetLayout));
89 var equalButNotSame = ADDRESS.withTargetLayout(JAVA_INT).withTargetLayout(JAVA_CHAR);
90 assertTrue(differentTargetLayout.equals(equalButNotSame));
91 }
92
93 @Test
94 public void testIndexedSequencePath() {
95 MemoryLayout seq = MemoryLayout.sequenceLayout(10, ValueLayout.JAVA_INT);
96 try (Arena arena = Arena.ofConfined()) {
97 MemorySegment segment = arena.allocate(seq);;
98 VarHandle indexHandle = seq.varHandle(MemoryLayout.PathElement.sequenceElement());
99 // init segment
100 for (int i = 0 ; i < 10 ; i++) {
101 indexHandle.set(segment, (long)i, i);
102 }
103 //check statically indexed handles
104 for (int i = 0 ; i < 10 ; i++) {
105 VarHandle preindexHandle = seq.varHandle(MemoryLayout.PathElement.sequenceElement(i));
106 int expected = (int)indexHandle.get(segment, (long)i);
107 int found = (int)preindexHandle.get(segment);
108 assertEquals(expected, found);
109 }
110 }
111 }
112
113 @Test(expectedExceptions = IllegalArgumentException.class)
114 public void testBadBoundSequenceLayoutResize() {
115 SequenceLayout seq = MemoryLayout.sequenceLayout(10, ValueLayout.JAVA_INT);
116 seq.withElementCount(-1);
117 }
118
119 @Test(expectedExceptions = IllegalArgumentException.class)
120 public void testReshape() {
121 SequenceLayout layout = MemoryLayout.sequenceLayout(10, JAVA_INT);
122 layout.reshape();
123 }
124
125 @Test(dataProvider = "basicLayoutsAndAddressAndGroups", expectedExceptions = IllegalArgumentException.class)
126 public void testGroupIllegalAlignmentNotPowerOfTwo(MemoryLayout layout) {
127 layout.withByteAlignment(9);
184 }
185
186 @Test
187 public void testUnionSizeAndAlign() {
188 MemoryLayout struct = MemoryLayout.unionLayout(
189 ValueLayout.JAVA_BYTE,
190 ValueLayout.JAVA_CHAR,
191 ValueLayout.JAVA_INT,
192 ValueLayout.JAVA_LONG
193 );
194 assertEquals(struct.byteSize(), 8);
195 assertEquals(struct.byteAlignment(), ADDRESS.byteSize());
196 }
197
198 @Test
199 public void testSequenceBadCount() {
200 assertThrows(IllegalArgumentException.class, // negative
201 () -> MemoryLayout.sequenceLayout(-2, JAVA_SHORT));
202 }
203
204 @Test(dataProvider = "basicLayouts")
205 public void testSequenceInferredCount(MemoryLayout layout) {
206 assertEquals(MemoryLayout.sequenceLayout(layout),
207 MemoryLayout.sequenceLayout(Long.MAX_VALUE / layout.byteSize(), layout));
208 }
209
210 public void testSequenceNegativeElementCount() {
211 assertThrows(IllegalArgumentException.class, // negative
212 () -> MemoryLayout.sequenceLayout(-1, JAVA_SHORT));
213 }
214
215 @Test
216 public void testSequenceOverflow() {
217 assertThrows(IllegalArgumentException.class, // negative
218 () -> MemoryLayout.sequenceLayout(Long.MAX_VALUE, JAVA_SHORT));
219 assertThrows(IllegalArgumentException.class, // flip back to positive
220 () -> MemoryLayout.sequenceLayout(Long.MAX_VALUE/3, JAVA_LONG));
221 assertThrows(IllegalArgumentException.class, // flip back to positive
222 () -> MemoryLayout.sequenceLayout(0, JAVA_LONG).withElementCount(Long.MAX_VALUE));
223 }
224
225 @Test
226 public void testStructOverflow() {
227 assertThrows(IllegalArgumentException.class, // negative
228 () -> MemoryLayout.structLayout(MemoryLayout.sequenceLayout(Long.MAX_VALUE, JAVA_BYTE),
229 MemoryLayout.sequenceLayout(Long.MAX_VALUE, JAVA_BYTE)));
283 if (a >= layout.byteAlignment()) {
284 assertEquals(layout.withByteAlignment(a).toString().contains("%"), a != byteAlign);
285 }
286 }
287 }
288 }
289
290 @Test(dataProvider="layoutsAndAlignments")
291 public void testBadByteAlignment(MemoryLayout layout, long byteAlign) {
292 long[] alignments = { 1, 2, 4, 8, 16 };
293 for (long a : alignments) {
294 if (a < byteAlign && !(layout instanceof ValueLayout)) {
295 assertThrows(IllegalArgumentException.class, () -> layout.withByteAlignment(a));
296 }
297 }
298 }
299
300 @Test(dataProvider="layoutsAndAlignments", expectedExceptions = IllegalArgumentException.class)
301 public void testBadSequenceElementAlignmentTooBig(MemoryLayout layout, long byteAlign) {
302 layout = layout.withByteAlignment(layout.byteSize() * 2); // hyper-align
303 MemoryLayout.sequenceLayout(layout);
304 }
305
306 @Test(dataProvider="layoutsAndAlignments")
307 public void testBadSequenceElementSizeNotMultipleOfAlignment(MemoryLayout layout, long byteAlign) {
308 boolean shouldFail = layout.byteSize() % layout.byteAlignment() != 0;
309 try {
310 MemoryLayout.sequenceLayout(layout);
311 assertFalse(shouldFail);
312 } catch (IllegalArgumentException ex) {
313 assertTrue(shouldFail);
314 }
315 }
316
317 @Test(dataProvider="layoutsAndAlignments")
318 public void testBadSpliteratorElementSizeNotMultipleOfAlignment(MemoryLayout layout, long byteAlign) {
319 boolean shouldFail = layout.byteSize() % layout.byteAlignment() != 0;
320 try (Arena arena = Arena.ofConfined()) {
321 MemorySegment segment = arena.allocate(layout);
322 segment.spliterator(layout);
323 assertFalse(shouldFail);
324 } catch (IllegalArgumentException ex) {
325 assertTrue(shouldFail);
326 }
327 }
328
329 @Test(dataProvider="layoutsAndAlignments")
330 public void testBadElementsElementSizeNotMultipleOfAlignment(MemoryLayout layout, long byteAlign) {
331 boolean shouldFail = layout.byteSize() % layout.byteAlignment() != 0;
332 try (Arena arena = Arena.ofConfined()) {
333 MemorySegment segment = arena.allocate(layout);
334 segment.elements(layout);
335 assertFalse(shouldFail);
336 } catch (IllegalArgumentException ex) {
337 assertTrue(shouldFail);
338 }
339 }
340
341 @Test(dataProvider="layoutsAndAlignments")
342 public void testArrayElementVarHandleBadAlignment(MemoryLayout layout, long byteAlign) {
343 if (layout instanceof ValueLayout) {
344 assertThrows(UnsupportedOperationException.class, () ->
345 ((ValueLayout) layout).withByteAlignment(byteAlign * 2).arrayElementVarHandle());
346 }
347 }
348
349 @Test(dataProvider="layoutsAndAlignments", expectedExceptions = IllegalArgumentException.class)
350 public void testBadStruct(MemoryLayout layout, long byteAlign) {
351 layout = layout.withByteAlignment(layout.byteSize() * 2); // hyper-align
352 MemoryLayout.structLayout(layout, layout);
353 }
354
355 @Test(expectedExceptions = IllegalArgumentException.class)
356 public void testSequenceElement() {
357 SequenceLayout layout = MemoryLayout.sequenceLayout(10, JAVA_INT);
358 // Step must be != 0
359 PathElement.sequenceElement(3, 0);
360 }
361
362 @DataProvider(name = "badAlignments")
363 public Object[][] layoutsAndBadAlignments() {
364 LayoutKind[] layoutKinds = LayoutKind.values();
365 Object[][] values = new Object[layoutKinds.length * 2][2];
366 for (int i = 0; i < layoutKinds.length ; i++) {
367 values[i * 2] = new Object[] { layoutKinds[i].layout, 0 }; // smaller than 1
368 values[(i * 2) + 1] = new Object[] { layoutKinds[i].layout, 5 }; // not a power of 2
369 }
370 return values;
371 }
372
373 @DataProvider(name = "layoutKinds")
374 public Object[][] layoutsKinds() {
375 return Stream.of(LayoutKind.values())
376 .map(lk -> new Object[] { lk })
377 .toArray(Object[][]::new);
378 }
379
380 enum SizedLayoutFactory {
381 VALUE_LE(size -> valueLayoutForSize((int)size).withOrder(ByteOrder.LITTLE_ENDIAN)),
479 @DataProvider(name = "validCarriers")
480 public Object[][] validCarriers() {
481 return Stream.of(
482 boolean.class,
483 byte.class,
484 char.class,
485 short.class,
486 int.class,
487 long.class,
488 float.class,
489 double.class,
490 MemorySegment.class
491 )
492 .map(l -> new Object[]{l})
493 .toArray(Object[][]::new);
494 }
495
496 static Stream<MemoryLayout> groupLayoutStream() {
497 return Stream.of(
498 MemoryLayout.sequenceLayout(10, JAVA_INT),
499 MemoryLayout.sequenceLayout(JAVA_INT),
500 MemoryLayout.structLayout(JAVA_INT, MemoryLayout.paddingLayout(4), JAVA_LONG),
501 MemoryLayout.unionLayout(JAVA_LONG, JAVA_DOUBLE)
502 );
503 }
504
505 static ValueLayout[] basicLayouts = {
506 ValueLayout.JAVA_BYTE,
507 ValueLayout.JAVA_CHAR,
508 ValueLayout.JAVA_SHORT,
509 ValueLayout.JAVA_INT,
510 ValueLayout.JAVA_FLOAT,
511 ValueLayout.JAVA_LONG,
512 ValueLayout.JAVA_DOUBLE,
513 };
514
515 static MemoryLayout[] basicLayoutsNoLongDouble = Stream.of(basicLayouts)
516 .filter(l -> l.carrier() != long.class && l.carrier() != double.class)
517 .toArray(MemoryLayout[]::new);
518 }
|
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 TestLayouts
27 */
28
29 import java.lang.foreign.*;
30
31 import java.lang.invoke.VarHandle;
32 import java.nio.ByteOrder;
33 import java.util.ArrayList;
34 import java.util.List;
35 import java.util.function.LongFunction;
36 import java.util.stream.Stream;
37
38 import org.testng.annotations.*;
39
40 import static java.lang.foreign.ValueLayout.*;
41 import static org.testng.Assert.*;
42
43 public class TestLayouts {
44
45 @Test(dataProvider = "badAlignments", expectedExceptions = IllegalArgumentException.class)
80 MemoryLayout other = layout.withByteAlignment(16).withByteAlignment(layout.byteAlignment());
81 assertTrue(layout.equals(other));
82
83 }
84
85 public void testTargetLayoutEquals() {
86 MemoryLayout differentTargetLayout = ADDRESS.withTargetLayout(JAVA_CHAR);
87 assertFalse(ADDRESS.equals(differentTargetLayout));
88 var equalButNotSame = ADDRESS.withTargetLayout(JAVA_INT).withTargetLayout(JAVA_CHAR);
89 assertTrue(differentTargetLayout.equals(equalButNotSame));
90 }
91
92 @Test
93 public void testIndexedSequencePath() {
94 MemoryLayout seq = MemoryLayout.sequenceLayout(10, ValueLayout.JAVA_INT);
95 try (Arena arena = Arena.ofConfined()) {
96 MemorySegment segment = arena.allocate(seq);;
97 VarHandle indexHandle = seq.varHandle(MemoryLayout.PathElement.sequenceElement());
98 // init segment
99 for (int i = 0 ; i < 10 ; i++) {
100 indexHandle.set(segment, 0L, (long)i, i);
101 }
102 //check statically indexed handles
103 for (int i = 0 ; i < 10 ; i++) {
104 VarHandle preindexHandle = seq.varHandle(MemoryLayout.PathElement.sequenceElement(i));
105 int expected = (int)indexHandle.get(segment, 0L, (long)i);
106 int found = (int)preindexHandle.get(segment, 0L);
107 assertEquals(expected, found);
108 }
109 }
110 }
111
112 @Test(expectedExceptions = IllegalArgumentException.class)
113 public void testBadBoundSequenceLayoutResize() {
114 SequenceLayout seq = MemoryLayout.sequenceLayout(10, ValueLayout.JAVA_INT);
115 seq.withElementCount(-1);
116 }
117
118 @Test(expectedExceptions = IllegalArgumentException.class)
119 public void testReshape() {
120 SequenceLayout layout = MemoryLayout.sequenceLayout(10, JAVA_INT);
121 layout.reshape();
122 }
123
124 @Test(dataProvider = "basicLayoutsAndAddressAndGroups", expectedExceptions = IllegalArgumentException.class)
125 public void testGroupIllegalAlignmentNotPowerOfTwo(MemoryLayout layout) {
126 layout.withByteAlignment(9);
183 }
184
185 @Test
186 public void testUnionSizeAndAlign() {
187 MemoryLayout struct = MemoryLayout.unionLayout(
188 ValueLayout.JAVA_BYTE,
189 ValueLayout.JAVA_CHAR,
190 ValueLayout.JAVA_INT,
191 ValueLayout.JAVA_LONG
192 );
193 assertEquals(struct.byteSize(), 8);
194 assertEquals(struct.byteAlignment(), ADDRESS.byteSize());
195 }
196
197 @Test
198 public void testSequenceBadCount() {
199 assertThrows(IllegalArgumentException.class, // negative
200 () -> MemoryLayout.sequenceLayout(-2, JAVA_SHORT));
201 }
202
203 @Test
204 public void testSequenceNegativeElementCount() {
205 assertThrows(IllegalArgumentException.class, // negative
206 () -> MemoryLayout.sequenceLayout(-1, JAVA_SHORT));
207 }
208
209 @Test
210 public void testSequenceOverflow() {
211 assertThrows(IllegalArgumentException.class, // negative
212 () -> MemoryLayout.sequenceLayout(Long.MAX_VALUE, JAVA_SHORT));
213 assertThrows(IllegalArgumentException.class, // flip back to positive
214 () -> MemoryLayout.sequenceLayout(Long.MAX_VALUE/3, JAVA_LONG));
215 assertThrows(IllegalArgumentException.class, // flip back to positive
216 () -> MemoryLayout.sequenceLayout(0, JAVA_LONG).withElementCount(Long.MAX_VALUE));
217 }
218
219 @Test
220 public void testStructOverflow() {
221 assertThrows(IllegalArgumentException.class, // negative
222 () -> MemoryLayout.structLayout(MemoryLayout.sequenceLayout(Long.MAX_VALUE, JAVA_BYTE),
223 MemoryLayout.sequenceLayout(Long.MAX_VALUE, JAVA_BYTE)));
277 if (a >= layout.byteAlignment()) {
278 assertEquals(layout.withByteAlignment(a).toString().contains("%"), a != byteAlign);
279 }
280 }
281 }
282 }
283
284 @Test(dataProvider="layoutsAndAlignments")
285 public void testBadByteAlignment(MemoryLayout layout, long byteAlign) {
286 long[] alignments = { 1, 2, 4, 8, 16 };
287 for (long a : alignments) {
288 if (a < byteAlign && !(layout instanceof ValueLayout)) {
289 assertThrows(IllegalArgumentException.class, () -> layout.withByteAlignment(a));
290 }
291 }
292 }
293
294 @Test(dataProvider="layoutsAndAlignments", expectedExceptions = IllegalArgumentException.class)
295 public void testBadSequenceElementAlignmentTooBig(MemoryLayout layout, long byteAlign) {
296 layout = layout.withByteAlignment(layout.byteSize() * 2); // hyper-align
297 MemoryLayout.sequenceLayout(1, layout);
298 }
299
300 @Test(dataProvider="layoutsAndAlignments")
301 public void testBadSequenceElementSizeNotMultipleOfAlignment(MemoryLayout layout, long byteAlign) {
302 boolean shouldFail = layout.byteSize() % layout.byteAlignment() != 0;
303 try {
304 MemoryLayout.sequenceLayout(1, layout);
305 assertFalse(shouldFail);
306 } catch (IllegalArgumentException ex) {
307 assertTrue(shouldFail);
308 }
309 }
310
311 @Test(dataProvider="layoutsAndAlignments")
312 public void testBadSpliteratorElementSizeNotMultipleOfAlignment(MemoryLayout layout, long byteAlign) {
313 boolean shouldFail = layout.byteSize() % layout.byteAlignment() != 0;
314 try (Arena arena = Arena.ofConfined()) {
315 MemorySegment segment = arena.allocate(layout);
316 segment.spliterator(layout);
317 assertFalse(shouldFail);
318 } catch (IllegalArgumentException ex) {
319 assertTrue(shouldFail);
320 }
321 }
322
323 @Test(dataProvider="layoutsAndAlignments")
324 public void testBadElementsElementSizeNotMultipleOfAlignment(MemoryLayout layout, long byteAlign) {
325 boolean shouldFail = layout.byteSize() % layout.byteAlignment() != 0;
326 try (Arena arena = Arena.ofConfined()) {
327 MemorySegment segment = arena.allocate(layout);
328 segment.elements(layout);
329 assertFalse(shouldFail);
330 } catch (IllegalArgumentException ex) {
331 assertTrue(shouldFail);
332 }
333 }
334
335 @Test(dataProvider="layoutsAndAlignments", expectedExceptions = IllegalArgumentException.class)
336 public void testBadStruct(MemoryLayout layout, long byteAlign) {
337 layout = layout.withByteAlignment(layout.byteSize() * 2); // hyper-align
338 MemoryLayout.structLayout(layout, layout);
339 }
340
341 @Test(expectedExceptions = IllegalArgumentException.class)
342 public void testSequenceElement() {
343 SequenceLayout layout = MemoryLayout.sequenceLayout(10, JAVA_INT);
344 // Step must be != 0
345 PathElement.sequenceElement(3, 0);
346 }
347
348 @Test
349 public void testVarHandleCaching() {
350 assertSame(JAVA_INT.varHandle(), JAVA_INT.varHandle());
351 assertSame(JAVA_INT.withName("foo").varHandle(), JAVA_INT.varHandle());
352
353 assertNotSame(JAVA_INT_UNALIGNED.varHandle(), JAVA_INT.varHandle());
354 assertNotSame(ADDRESS.withTargetLayout(JAVA_INT).varHandle(), ADDRESS.varHandle());
355 }
356
357 @Test(expectedExceptions=IllegalArgumentException.class,
358 expectedExceptionsMessageRegExp=".*Negative offset.*")
359 public void testScaleNegativeOffset() {
360 JAVA_INT.scale(-1, 0);
361 }
362
363 @Test(expectedExceptions=IllegalArgumentException.class,
364 expectedExceptionsMessageRegExp=".*Negative index.*")
365 public void testScaleNegativeIndex() {
366 JAVA_INT.scale(0, -1);
367 }
368
369 @Test(expectedExceptions=ArithmeticException.class)
370 public void testScaleAddOverflow() {
371 JAVA_INT.scale(Long.MAX_VALUE, 1);
372 }
373
374 @Test(expectedExceptions=ArithmeticException.class)
375 public void testScaleMultiplyOverflow() {
376 JAVA_INT.scale(0, Long.MAX_VALUE);
377 }
378
379 @DataProvider(name = "badAlignments")
380 public Object[][] layoutsAndBadAlignments() {
381 LayoutKind[] layoutKinds = LayoutKind.values();
382 Object[][] values = new Object[layoutKinds.length * 2][2];
383 for (int i = 0; i < layoutKinds.length ; i++) {
384 values[i * 2] = new Object[] { layoutKinds[i].layout, 0 }; // smaller than 1
385 values[(i * 2) + 1] = new Object[] { layoutKinds[i].layout, 5 }; // not a power of 2
386 }
387 return values;
388 }
389
390 @DataProvider(name = "layoutKinds")
391 public Object[][] layoutsKinds() {
392 return Stream.of(LayoutKind.values())
393 .map(lk -> new Object[] { lk })
394 .toArray(Object[][]::new);
395 }
396
397 enum SizedLayoutFactory {
398 VALUE_LE(size -> valueLayoutForSize((int)size).withOrder(ByteOrder.LITTLE_ENDIAN)),
496 @DataProvider(name = "validCarriers")
497 public Object[][] validCarriers() {
498 return Stream.of(
499 boolean.class,
500 byte.class,
501 char.class,
502 short.class,
503 int.class,
504 long.class,
505 float.class,
506 double.class,
507 MemorySegment.class
508 )
509 .map(l -> new Object[]{l})
510 .toArray(Object[][]::new);
511 }
512
513 static Stream<MemoryLayout> groupLayoutStream() {
514 return Stream.of(
515 MemoryLayout.sequenceLayout(10, JAVA_INT),
516 MemoryLayout.structLayout(JAVA_INT, MemoryLayout.paddingLayout(4), JAVA_LONG),
517 MemoryLayout.unionLayout(JAVA_LONG, JAVA_DOUBLE)
518 );
519 }
520
521 static ValueLayout[] basicLayouts = {
522 ValueLayout.JAVA_BYTE,
523 ValueLayout.JAVA_CHAR,
524 ValueLayout.JAVA_SHORT,
525 ValueLayout.JAVA_INT,
526 ValueLayout.JAVA_FLOAT,
527 ValueLayout.JAVA_LONG,
528 ValueLayout.JAVA_DOUBLE,
529 };
530
531 static MemoryLayout[] basicLayoutsNoLongDouble = Stream.of(basicLayouts)
532 .filter(l -> l.carrier() != long.class && l.carrier() != double.class)
533 .toArray(MemoryLayout[]::new);
534 }
|