Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
PojavLauncherTeam
GitHub Repository: PojavLauncherTeam/mobile
Path: blob/master/test/jdk/java/foreign/TestLayoutPaths.java
41145 views
1
/*
2
* Copyright (c) 2019, 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
/*
26
* @test
27
* @run testng TestLayoutPaths
28
*/
29
30
import jdk.incubator.foreign.GroupLayout;
31
import jdk.incubator.foreign.MemoryLayouts;
32
import jdk.incubator.foreign.MemoryLayout;
33
import jdk.incubator.foreign.MemoryLayout.PathElement;
34
import jdk.incubator.foreign.MemorySegment;
35
import jdk.incubator.foreign.ResourceScope;
36
import jdk.incubator.foreign.SequenceLayout;
37
38
import org.testng.SkipException;
39
import org.testng.annotations.*;
40
41
import java.lang.invoke.MethodHandle;
42
import java.nio.ByteOrder;
43
import java.util.ArrayList;
44
import java.util.List;
45
46
import static jdk.incubator.foreign.MemoryLayout.PathElement.groupElement;
47
import static jdk.incubator.foreign.MemoryLayout.PathElement.sequenceElement;
48
import static jdk.incubator.foreign.MemoryLayouts.JAVA_INT;
49
import static org.testng.Assert.*;
50
51
public class TestLayoutPaths {
52
53
@Test(expectedExceptions = IllegalArgumentException.class)
54
public void testBadBitSelectFromSeq() {
55
SequenceLayout seq = MemoryLayout.sequenceLayout(JAVA_INT);
56
seq.bitOffset(groupElement("foo"));
57
}
58
59
@Test(expectedExceptions = IllegalArgumentException.class)
60
public void testBadByteSelectFromSeq() {
61
SequenceLayout seq = MemoryLayout.sequenceLayout(JAVA_INT);
62
seq.byteOffset(groupElement("foo"));
63
}
64
65
@Test(expectedExceptions = IllegalArgumentException.class)
66
public void testBadBitSelectFromStruct() {
67
GroupLayout g = MemoryLayout.structLayout(JAVA_INT);
68
g.bitOffset(sequenceElement());
69
}
70
71
@Test(expectedExceptions = IllegalArgumentException.class)
72
public void testBadByteSelectFromStruct() {
73
GroupLayout g = MemoryLayout.structLayout(JAVA_INT);
74
g.byteOffset(sequenceElement());
75
}
76
77
@Test(expectedExceptions = IllegalArgumentException.class)
78
public void testBadBitSelectFromValue() {
79
SequenceLayout seq = MemoryLayout.sequenceLayout(JAVA_INT);
80
seq.bitOffset(sequenceElement(), sequenceElement());
81
}
82
83
@Test(expectedExceptions = IllegalArgumentException.class)
84
public void testBadByteSelectFromValue() {
85
SequenceLayout seq = MemoryLayout.sequenceLayout(JAVA_INT);
86
seq.byteOffset(sequenceElement(), sequenceElement());
87
}
88
89
@Test(expectedExceptions = IllegalArgumentException.class)
90
public void testUnknownBitStructField() {
91
GroupLayout g = MemoryLayout.structLayout(JAVA_INT);
92
g.bitOffset(groupElement("foo"));
93
}
94
95
@Test(expectedExceptions = IllegalArgumentException.class)
96
public void testUnknownByteStructField() {
97
GroupLayout g = MemoryLayout.structLayout(JAVA_INT);
98
g.byteOffset(groupElement("foo"));
99
}
100
101
@Test(expectedExceptions = IllegalArgumentException.class)
102
public void testBitOutOfBoundsSeqIndex() {
103
SequenceLayout seq = MemoryLayout.sequenceLayout(5, JAVA_INT);
104
seq.bitOffset(sequenceElement(6));
105
}
106
107
@Test(expectedExceptions = IllegalArgumentException.class)
108
public void testByteOutOfBoundsSeqIndex() {
109
SequenceLayout seq = MemoryLayout.sequenceLayout(5, JAVA_INT);
110
seq.byteOffset(sequenceElement(6));
111
}
112
113
@Test(expectedExceptions = IllegalArgumentException.class)
114
public void testNegativeSeqIndex() {
115
sequenceElement(-2);
116
}
117
118
@Test(expectedExceptions = IllegalArgumentException.class)
119
public void testBitNegativeSeqIndex() {
120
SequenceLayout seq = MemoryLayout.sequenceLayout(5, JAVA_INT);
121
seq.bitOffset(sequenceElement(-2));
122
}
123
124
@Test(expectedExceptions = IllegalArgumentException.class)
125
public void testByteNegativeSeqIndex() {
126
SequenceLayout seq = MemoryLayout.sequenceLayout(5, JAVA_INT);
127
seq.byteOffset(sequenceElement(-2));
128
}
129
130
@Test(expectedExceptions = IllegalArgumentException.class)
131
public void testOutOfBoundsSeqRange() {
132
SequenceLayout seq = MemoryLayout.sequenceLayout(5, JAVA_INT);
133
seq.bitOffset(sequenceElement(6, 2));
134
}
135
136
@Test(expectedExceptions = IllegalArgumentException.class)
137
public void testNegativeSeqRange() {
138
sequenceElement(-2, 2);
139
}
140
141
@Test(expectedExceptions = IllegalArgumentException.class)
142
public void testBitNegativeSeqRange() {
143
SequenceLayout seq = MemoryLayout.sequenceLayout(5, JAVA_INT);
144
seq.bitOffset(sequenceElement(-2, 2));
145
}
146
147
@Test(expectedExceptions = IllegalArgumentException.class)
148
public void testByteNegativeSeqRange() {
149
SequenceLayout seq = MemoryLayout.sequenceLayout(5, JAVA_INT);
150
seq.byteOffset(sequenceElement(-2, 2));
151
}
152
153
@Test(expectedExceptions = IllegalArgumentException.class)
154
public void testIncompleteAccess() {
155
SequenceLayout seq = MemoryLayout.sequenceLayout(5, MemoryLayout.structLayout(JAVA_INT));
156
seq.varHandle(int.class, sequenceElement());
157
}
158
159
@Test(expectedExceptions = IllegalArgumentException.class)
160
public void testBitOffsetHandleBadRange() {
161
SequenceLayout seq = MemoryLayout.sequenceLayout(5, MemoryLayout.structLayout(JAVA_INT));
162
seq.bitOffsetHandle(sequenceElement(0, 1)); // ranges not accepted
163
}
164
165
@Test(expectedExceptions = IllegalArgumentException.class)
166
public void testByteOffsetHandleBadRange() {
167
SequenceLayout seq = MemoryLayout.sequenceLayout(5, MemoryLayout.structLayout(JAVA_INT));
168
seq.byteOffsetHandle(sequenceElement(0, 1)); // ranges not accepted
169
}
170
171
@Test(expectedExceptions = UnsupportedOperationException.class)
172
public void testBadMultiple() {
173
GroupLayout g = MemoryLayout.structLayout(MemoryLayout.paddingLayout(3), JAVA_INT.withName("foo"));
174
g.byteOffset(groupElement("foo"));
175
}
176
177
@Test(expectedExceptions = UnsupportedOperationException.class)
178
public void testBitOffsetBadUnboundedSequenceTraverse() {
179
MemoryLayout layout = MemoryLayout.sequenceLayout(MemoryLayout.sequenceLayout(JAVA_INT));
180
layout.bitOffset(sequenceElement(1), sequenceElement(0));
181
}
182
183
@Test(expectedExceptions = UnsupportedOperationException.class)
184
public void testByteOffsetBadUnboundedSequenceTraverse() {
185
MemoryLayout layout = MemoryLayout.sequenceLayout(MemoryLayout.sequenceLayout(JAVA_INT));
186
layout.byteOffset(sequenceElement(1), sequenceElement(0));
187
}
188
189
@Test(expectedExceptions = UnsupportedOperationException.class)
190
public void testBitOffsetHandleBadUnboundedSequenceTraverse() {
191
MemoryLayout layout = MemoryLayout.sequenceLayout(MemoryLayout.sequenceLayout(JAVA_INT));
192
layout.bitOffsetHandle(sequenceElement(1), sequenceElement(0));
193
}
194
195
@Test(expectedExceptions = UnsupportedOperationException.class)
196
public void testByteOffsetHandleBadUnboundedSequenceTraverse() {
197
MemoryLayout layout = MemoryLayout.sequenceLayout(MemoryLayout.sequenceLayout(JAVA_INT));
198
layout.byteOffsetHandle(sequenceElement(1), sequenceElement(0));
199
}
200
201
@Test(expectedExceptions = UnsupportedOperationException.class)
202
public void testBadByteOffsetNoMultipleOf8() {
203
MemoryLayout layout = MemoryLayout.structLayout(MemoryLayout.paddingLayout(7), JAVA_INT.withName("x"));
204
layout.byteOffset(groupElement("x"));
205
}
206
207
@Test(expectedExceptions = UnsupportedOperationException.class)
208
public void testBadByteOffsetHandleNoMultipleOf8() throws Throwable {
209
MemoryLayout layout = MemoryLayout.structLayout(MemoryLayout.paddingLayout(7), JAVA_INT.withName("x"));
210
MethodHandle handle = layout.byteOffsetHandle(groupElement("x"));
211
handle.invoke();
212
}
213
214
@Test
215
public void testBadContainerAlign() {
216
GroupLayout g = MemoryLayout.structLayout(JAVA_INT.withBitAlignment(16).withName("foo")).withBitAlignment(8);
217
try {
218
g.bitOffset(groupElement("foo"));
219
g.byteOffset(groupElement("foo"));
220
} catch (Throwable ex) {
221
throw new AssertionError(ex); // should be ok!
222
}
223
try {
224
g.varHandle(int.class, groupElement("foo")); //ok
225
assertTrue(false); //should fail!
226
} catch (UnsupportedOperationException ex) {
227
//ok
228
} catch (Throwable ex) {
229
throw new AssertionError(ex); //should fail!
230
}
231
}
232
233
@Test
234
public void testBadAlignOffset() {
235
GroupLayout g = MemoryLayout.structLayout(MemoryLayouts.PAD_8, JAVA_INT.withBitAlignment(16).withName("foo"));
236
try {
237
g.bitOffset(groupElement("foo"));
238
g.byteOffset(groupElement("foo"));
239
} catch (Throwable ex) {
240
throw new AssertionError(ex); // should be ok!
241
}
242
try {
243
g.varHandle(int.class, groupElement("foo")); //ok
244
assertTrue(false); //should fail!
245
} catch (UnsupportedOperationException ex) {
246
//ok
247
} catch (Throwable ex) {
248
throw new AssertionError(ex); //should fail!
249
}
250
}
251
252
@Test
253
public void testBadSequencePathInOffset() {
254
SequenceLayout seq = MemoryLayout.sequenceLayout(10, JAVA_INT);
255
// bad path elements
256
for (PathElement e : List.of( sequenceElement(), sequenceElement(0, 2) )) {
257
try {
258
seq.bitOffset(e);
259
fail();
260
} catch (IllegalArgumentException ex) {
261
assertTrue(true);
262
}
263
try {
264
seq.byteOffset(e);
265
fail();
266
} catch (IllegalArgumentException ex) {
267
assertTrue(true);
268
}
269
}
270
}
271
272
@Test
273
public void testBadSequencePathInSelect() {
274
SequenceLayout seq = MemoryLayout.sequenceLayout(10, JAVA_INT);
275
for (PathElement e : List.of( sequenceElement(0), sequenceElement(0, 2) )) {
276
try {
277
seq.select(e);
278
fail();
279
} catch (IllegalArgumentException ex) {
280
assertTrue(true);
281
}
282
}
283
}
284
285
@Test
286
public void testBadSequencePathInMap() {
287
SequenceLayout seq = MemoryLayout.sequenceLayout(10, JAVA_INT);
288
for (PathElement e : List.of( sequenceElement(0), sequenceElement(0, 2) )) {
289
try {
290
seq.map(l -> l, e);
291
fail();
292
} catch (IllegalArgumentException ex) {
293
assertTrue(true);
294
}
295
}
296
}
297
298
@Test
299
public void testStructPaths() {
300
long[] offsets = { 0, 8, 24, 56 };
301
GroupLayout g = MemoryLayout.structLayout(
302
MemoryLayouts.JAVA_BYTE.withName("1"),
303
MemoryLayouts.JAVA_CHAR.withName("2"),
304
MemoryLayouts.JAVA_FLOAT.withName("3"),
305
MemoryLayouts.JAVA_LONG.withName("4")
306
);
307
308
// test select
309
310
for (int i = 1 ; i <= 4 ; i++) {
311
MemoryLayout selected = g.select(groupElement(String.valueOf(i)));
312
assertTrue(selected == g.memberLayouts().get(i - 1));
313
}
314
315
// test offset
316
317
for (int i = 1 ; i <= 4 ; i++) {
318
long bitOffset = g.bitOffset(groupElement(String.valueOf(i)));
319
assertEquals(offsets[i - 1], bitOffset);
320
long byteOffset = g.byteOffset(groupElement(String.valueOf(i)));
321
assertEquals((offsets[i - 1]) >>> 3, byteOffset);
322
}
323
324
// test map
325
326
for (int i = 1 ; i <= 4 ; i++) {
327
GroupLayout g2 = (GroupLayout)g.map(l -> MemoryLayouts.JAVA_DOUBLE, groupElement(String.valueOf(i)));
328
assertTrue(g2.isStruct());
329
for (int j = 0 ; j < 4 ; j++) {
330
if (j == i - 1) {
331
assertEquals(g2.memberLayouts().get(j), MemoryLayouts.JAVA_DOUBLE);
332
} else {
333
assertEquals(g2.memberLayouts().get(j), g.memberLayouts().get(j));
334
}
335
}
336
}
337
}
338
339
@Test
340
public void testUnionPaths() {
341
long[] offsets = { 0, 0, 0, 0 };
342
GroupLayout g = MemoryLayout.unionLayout(
343
MemoryLayouts.JAVA_BYTE.withName("1"),
344
MemoryLayouts.JAVA_CHAR.withName("2"),
345
MemoryLayouts.JAVA_FLOAT.withName("3"),
346
MemoryLayouts.JAVA_LONG.withName("4")
347
);
348
349
// test select
350
351
for (int i = 1 ; i <= 4 ; i++) {
352
MemoryLayout selected = g.select(groupElement(String.valueOf(i)));
353
assertTrue(selected == g.memberLayouts().get(i - 1));
354
}
355
356
// test offset
357
358
for (int i = 1 ; i <= 4 ; i++) {
359
long bitOffset = g.bitOffset(groupElement(String.valueOf(i)));
360
assertEquals(offsets[i - 1], bitOffset);
361
long byteOffset = g.byteOffset(groupElement(String.valueOf(i)));
362
assertEquals((offsets[i - 1]) >>> 3, byteOffset);
363
}
364
365
// test map
366
367
for (int i = 1 ; i <= 4 ; i++) {
368
GroupLayout g2 = (GroupLayout)g.map(l -> MemoryLayouts.JAVA_DOUBLE, groupElement(String.valueOf(i)));
369
assertTrue(g2.isUnion());
370
for (int j = 0 ; j < 4 ; j++) {
371
if (j == i - 1) {
372
assertEquals(g2.memberLayouts().get(j), MemoryLayouts.JAVA_DOUBLE);
373
} else {
374
assertEquals(g2.memberLayouts().get(j), g.memberLayouts().get(j));
375
}
376
}
377
}
378
}
379
380
@Test
381
public void testSequencePaths() {
382
long[] offsets = { 0, 8, 16, 24 };
383
SequenceLayout g = MemoryLayout.sequenceLayout(4, MemoryLayouts.JAVA_BYTE);
384
385
// test select
386
387
MemoryLayout selected = g.select(sequenceElement());
388
assertTrue(selected == MemoryLayouts.JAVA_BYTE);
389
390
// test offset
391
392
for (int i = 0 ; i < 4 ; i++) {
393
long bitOffset = g.bitOffset(sequenceElement(i));
394
assertEquals(offsets[i], bitOffset);
395
long byteOffset = g.byteOffset(sequenceElement(i));
396
assertEquals((offsets[i]) >>> 3, byteOffset);
397
}
398
399
// test map
400
401
SequenceLayout seq2 = (SequenceLayout)g.map(l -> MemoryLayouts.JAVA_DOUBLE, sequenceElement());
402
assertTrue(seq2.elementLayout() == MemoryLayouts.JAVA_DOUBLE);
403
}
404
405
@Test(dataProvider = "testLayouts")
406
public void testOffsetHandle(MemoryLayout layout, PathElement[] pathElements, long[] indexes,
407
long expectedBitOffset) throws Throwable {
408
MethodHandle bitOffsetHandle = layout.bitOffsetHandle(pathElements);
409
bitOffsetHandle = bitOffsetHandle.asSpreader(long[].class, indexes.length);
410
long actualBitOffset = (long) bitOffsetHandle.invokeExact(indexes);
411
assertEquals(actualBitOffset, expectedBitOffset);
412
if (expectedBitOffset % 8 == 0) {
413
MethodHandle byteOffsetHandle = layout.byteOffsetHandle(pathElements);
414
byteOffsetHandle = byteOffsetHandle.asSpreader(long[].class, indexes.length);
415
long actualByteOffset = (long) byteOffsetHandle.invokeExact(indexes);
416
assertEquals(actualByteOffset, expectedBitOffset / 8);
417
}
418
}
419
420
@DataProvider
421
public static Object[][] testLayouts() {
422
List<Object[]> testCases = new ArrayList<>();
423
424
testCases.add(new Object[] {
425
MemoryLayout.sequenceLayout(10, JAVA_INT),
426
new PathElement[] { sequenceElement() },
427
new long[] { 4 },
428
JAVA_INT.bitSize() * 4
429
});
430
testCases.add(new Object[] {
431
MemoryLayout.sequenceLayout(10, MemoryLayout.structLayout(JAVA_INT, JAVA_INT.withName("y"))),
432
new PathElement[] { sequenceElement(), groupElement("y") },
433
new long[] { 4 },
434
(JAVA_INT.bitSize() * 2) * 4 + JAVA_INT.bitSize()
435
});
436
testCases.add(new Object[] {
437
MemoryLayout.sequenceLayout(10, MemoryLayout.structLayout(MemoryLayout.paddingLayout(5), JAVA_INT.withName("y"))),
438
new PathElement[] { sequenceElement(), groupElement("y") },
439
new long[] { 4 },
440
(JAVA_INT.bitSize() + 5) * 4 + 5
441
});
442
testCases.add(new Object[] {
443
MemoryLayout.sequenceLayout(10, JAVA_INT),
444
new PathElement[] { sequenceElement() },
445
new long[] { 4 },
446
JAVA_INT.bitSize() * 4
447
});
448
testCases.add(new Object[] {
449
MemoryLayout.structLayout(
450
MemoryLayout.sequenceLayout(10, JAVA_INT).withName("data")
451
),
452
new PathElement[] { groupElement("data"), sequenceElement() },
453
new long[] { 4 },
454
JAVA_INT.bitSize() * 4
455
});
456
457
MemoryLayout complexLayout = MemoryLayout.structLayout(
458
MemoryLayout.sequenceLayout(10,
459
MemoryLayout.sequenceLayout(10,
460
MemoryLayout.structLayout(
461
JAVA_INT.withName("x"),
462
JAVA_INT.withName("y")
463
)
464
)
465
).withName("data")
466
);
467
468
testCases.add(new Object[] {
469
complexLayout,
470
new PathElement[] { groupElement("data"), sequenceElement(), sequenceElement(), groupElement("x") },
471
new long[] { 0, 1 },
472
(JAVA_INT.bitSize() * 2)
473
});
474
testCases.add(new Object[] {
475
complexLayout,
476
new PathElement[] { groupElement("data"), sequenceElement(), sequenceElement(), groupElement("x") },
477
new long[] { 1, 0 },
478
(JAVA_INT.bitSize() * 2) * 10
479
});
480
testCases.add(new Object[] {
481
complexLayout,
482
new PathElement[] { groupElement("data"), sequenceElement(), sequenceElement(), groupElement("y") },
483
new long[] { 0, 1 },
484
(JAVA_INT.bitSize() * 2) + JAVA_INT.bitSize()
485
});
486
testCases.add(new Object[] {
487
complexLayout,
488
new PathElement[] { groupElement("data"), sequenceElement(), sequenceElement(), groupElement("y") },
489
new long[] { 1, 0 },
490
(JAVA_INT.bitSize() * 2) * 10 + JAVA_INT.bitSize()
491
});
492
493
return testCases.toArray(Object[][]::new);
494
}
495
496
@Test(dataProvider = "testLayouts")
497
public void testSliceHandle(MemoryLayout layout, PathElement[] pathElements, long[] indexes,
498
long expectedBitOffset) throws Throwable {
499
if (expectedBitOffset % 8 != 0)
500
throw new SkipException("Offset not a multiple of 8");
501
502
MemoryLayout selected = layout.select(pathElements);
503
MethodHandle sliceHandle = layout.sliceHandle(pathElements);
504
sliceHandle = sliceHandle.asSpreader(long[].class, indexes.length);
505
506
try (ResourceScope scope = ResourceScope.newConfinedScope()) {
507
MemorySegment segment = MemorySegment.allocateNative(layout, scope);
508
MemorySegment slice = (MemorySegment) sliceHandle.invokeExact(segment, indexes);
509
assertEquals(slice.address().segmentOffset(segment), expectedBitOffset / 8);
510
assertEquals(slice.byteSize(), selected.byteSize());
511
}
512
}
513
514
@Test(expectedExceptions = UnsupportedOperationException.class)
515
public void testSliceHandleUOEInvalidSize() {
516
MemoryLayout layout = MemoryLayout.structLayout(
517
MemoryLayout.valueLayout(32, ByteOrder.nativeOrder()).withName("x"),
518
MemoryLayout.valueLayout(31, ByteOrder.nativeOrder()).withName("y") // size not a multiple of 8
519
);
520
521
layout.sliceHandle(groupElement("y")); // should throw
522
}
523
524
@Test(expectedExceptions = UnsupportedOperationException.class)
525
public void testSliceHandleUOEInvalidOffsetEager() throws Throwable {
526
MemoryLayout layout = MemoryLayout.structLayout(
527
MemoryLayout.paddingLayout(5),
528
MemoryLayout.valueLayout(32, ByteOrder.nativeOrder()).withName("y") // offset not a multiple of 8
529
);
530
531
layout.sliceHandle(groupElement("y")); // should throw
532
}
533
534
@Test(expectedExceptions = UnsupportedOperationException.class)
535
public void testSliceHandleUOEInvalidOffsetLate() throws Throwable {
536
MemoryLayout layout = MemoryLayout.sequenceLayout(3,
537
MemoryLayout.structLayout(
538
MemoryLayout.paddingLayout(4),
539
MemoryLayout.valueLayout(32, ByteOrder.nativeOrder()).withName("y") // offset not a multiple of 8
540
)
541
);
542
543
MethodHandle sliceHandle;
544
try {
545
sliceHandle = layout.sliceHandle(sequenceElement(), groupElement("y")); // should work
546
} catch (UnsupportedOperationException uoe) {
547
fail("Unexpected exception", uoe);
548
return;
549
}
550
551
try (ResourceScope scope = ResourceScope.newConfinedScope()) {
552
MemorySegment segment = MemorySegment.allocateNative(layout, scope);
553
554
try {
555
sliceHandle.invokeExact(segment, 1); // should work
556
} catch (UnsupportedOperationException uoe) {
557
fail("Unexpected exception", uoe);
558
return;
559
}
560
561
sliceHandle.invokeExact(segment, 0); // should throw
562
}
563
}
564
}
565
566
567