1/*
2 * Copyright (c) 2016, 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
24import jdk.internal.misc.Unsafe;
25
26/*
27 * @test
28 * @summary Test Unsafe.copySwapMemory
29 * @modules java.base/jdk.internal.misc
30 */
31public class CopySwap extends CopyCommon {
32    private CopySwap() {
33    }
34
35    /**
36     * Run positive tests
37     *
38     * @throws RuntimeException if an error is found
39     */
40    private void testPositive() {
41        testSmallCopy(true);
42    }
43
44    /**
45     * Run negative tests, testing corner cases and the various exceptions
46     *
47     * @throws RuntimeException if an error is found
48     */
49    private void testNegative() {
50        long bufRaw = 0;
51
52        try {
53            bufRaw = UNSAFE.allocateMemory(1024);
54            long buf = CopyCommon.alignUp(bufRaw, CopyCommon.BASE_ALIGNMENT);
55            short[] arr = new short[16];
56
57            // Check various illegal element sizes
58            for (int elemSize = 2; elemSize <= 8; elemSize <<= 1) {
59                long[] illegalSizes = { -1, 1, elemSize - 1, elemSize + 1, elemSize * 2 - 1 };
60                for (long size : illegalSizes) {
61                    try {
62                        // Check that illegal elemSize throws an IAE
63                        UNSAFE.copySwapMemory(null, buf, null, buf, size, elemSize);
64                        throw new RuntimeException("copySwapMemory failed to throw IAE for size=" + size + " elemSize=" + elemSize);
65                    } catch (IllegalArgumentException e) {
66                        // good
67                    }
68                }
69            }
70
71            try {
72                // Check that negative srcOffset throws an IAE
73                UNSAFE.copySwapMemory(arr, -1, arr, UNSAFE.arrayBaseOffset(arr.getClass()), 16, 2);
74                throw new RuntimeException("copySwapMemory failed to throw IAE for srcOffset=-1");
75            } catch (IllegalArgumentException e) {
76                // good
77            }
78
79            try {
80                // Check that negative dstOffset throws an IAE
81                UNSAFE.copySwapMemory(arr, UNSAFE.arrayBaseOffset(arr.getClass()), arr, -1, 16, 2);
82                throw new RuntimeException("copySwapMemory failed to throw IAE for destOffset=-1");
83            } catch (IllegalArgumentException e) {
84                // good
85            }
86
87            long illegalElemSizes[] = { 0, 1, 3, 5, 6, 7, 9, 10, -1 };
88            for (long elemSize : illegalElemSizes) {
89                try {
90                    // Check that elemSize 1 throws an IAE
91                    UNSAFE.copySwapMemory(null, buf, null, buf, 16, elemSize);
92                    throw new RuntimeException("copySwapMemory failed to throw NPE");
93                } catch (IllegalArgumentException e) {
94                    // good
95                }
96            }
97
98            try {
99                // Check that a reference array destination throws IAE
100                UNSAFE.copySwapMemory(null, buf, new Object[16], UNSAFE.arrayBaseOffset(Object[].class), 16, 8);
101                throw new RuntimeException("copySwapMemory failed to throw NPE");
102            } catch (IllegalArgumentException e) {
103                // good
104            }
105
106            // Check that invalid source & dest pointers throw IAEs (only relevant on 32-bit platforms)
107            if (UNSAFE.addressSize() == 4) {
108                long invalidPtr = (long)1 << 35; // Pick a random bit in upper 32 bits
109
110                try {
111                    // Check that an invalid (not 32-bit clean) source pointer throws IAE
112                    UNSAFE.copySwapMemory(null, invalidPtr, null, buf, 16, 2);
113                    throw new RuntimeException("copySwapMemory failed to throw IAE for srcOffset 0x" +
114                                               Long.toHexString(invalidPtr));
115                } catch (IllegalArgumentException e) {
116                    // good
117                }
118
119                try {
120                    // Check that an invalid (not 32-bit clean) source pointer throws IAE
121                    UNSAFE.copySwapMemory(null, buf, null, invalidPtr, 16, 2);
122                    throw new RuntimeException("copySwapMemory failed to throw IAE for destOffset 0x" +
123                                               Long.toHexString(invalidPtr));
124                } catch (IllegalArgumentException e) {
125                    // good
126                }
127            }
128        } finally {
129            if (bufRaw != 0) {
130                UNSAFE.freeMemory(bufRaw);
131            }
132        }
133    }
134
135    /**
136     * Run all tests
137     *
138     * @throws RuntimeException if an error is found
139     */
140    private void test() {
141        testPositive();
142        testNegative();
143    }
144
145    public static void main(String[] args) {
146        CopySwap cs = new CopySwap();
147        cs.test();
148    }
149}
150