1/*
2 * Copyright (c) 2007, 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/* @test
25 * @bug 6565543
26 * @summary Minimal test for unsafe.copyMemory() and unsafe.setMemory()
27 * @modules java.base/sun.nio.ch
28 *          jdk.unsupported
29 * @key randomness
30 */
31
32import java.util.*;
33import java.lang.reflect.*;
34import java.nio.*;
35
36import sun.misc.Unsafe;
37
38import sun.nio.ch.DirectBuffer;
39
40public class CopyMemory {
41
42    private final static int BUFFER_SIZE = 1024;
43    private final static int N = 16 * 1024;
44
45    private final static int FILLER = 0x55;
46    private final static int FILLER2 = 0x33;
47
48    private final static Random random = new Random();
49
50    private static void set(byte[] b, int ofs, int len, int value) {
51        for (int i = 0; i < len; i++) {
52            b[ofs + i] = (byte)value;
53        }
54    }
55
56    private static void check(byte[] b, int ofs, int len, int value) {
57        for (int i = 0; i < len; i++) {
58            int r = b[ofs + i] & 0xff;
59            if (r != value) {
60                throw new RuntimeException("mismatch");
61            }
62        }
63    }
64
65    private static void set(Unsafe unsafe, long addr, int ofs, int len, int value) {
66        for (int i = 0; i < len; i++) {
67            unsafe.putByte(null, addr + ofs + i, (byte)value);
68        }
69    }
70
71    private static void check(Unsafe unsafe, long addr, int ofs, int len, int value) {
72        for (int i = 0; i < len; i++) {
73            int r = unsafe.getByte(null, addr + ofs + i) & 0xff;
74            if (r != value) {
75                throw new RuntimeException("mismatch");
76            }
77        }
78    }
79
80    private static final List<ByteBuffer> buffers = new ArrayList<ByteBuffer>();
81
82    private static long getMemory(int n) {
83        ByteBuffer b = ByteBuffer.allocateDirect(n);
84        if (b instanceof DirectBuffer == false) {
85            throw new RuntimeException("Not a direct buffer");
86        }
87        buffers.add(b); // make sure the buffer does not get GCed
88        return ((DirectBuffer)b).address();
89    }
90
91    private static void testSetByteArray(Unsafe unsafe) throws Exception {
92        System.out.println("Testing setMemory() for byte[]...");
93        byte[] b = new byte[BUFFER_SIZE];
94        for (int i = 0; i < N; i++) {
95            set(b, 0, BUFFER_SIZE, FILLER);
96            int ofs = random.nextInt(BUFFER_SIZE / 2);
97            int len = random.nextInt(BUFFER_SIZE / 2);
98            int val = random.nextInt(256);
99            unsafe.setMemory(b, Unsafe.ARRAY_BYTE_BASE_OFFSET + ofs, len, (byte)val);
100            check(b, 0, ofs - 1, FILLER);
101            check(b, ofs, len, val);
102            check(b, ofs + len, BUFFER_SIZE - (ofs + len), FILLER);
103        }
104    }
105
106    private static void testSetRawMemory(Unsafe unsafe) throws Exception {
107        System.out.println("Testing setMemory() for raw memory...");
108        long b = getMemory(BUFFER_SIZE);
109        for (int i = 0; i < N; i++) {
110            set(unsafe, b, 0, BUFFER_SIZE, FILLER);
111            int ofs = random.nextInt(BUFFER_SIZE / 2);
112            int len = random.nextInt(BUFFER_SIZE / 2);
113            int val = random.nextInt(256);
114            unsafe.setMemory(null, b + ofs, len, (byte)val);
115            check(unsafe, b, 0, ofs - 1, FILLER);
116            check(unsafe, b, ofs, len, val);
117            check(unsafe, b, ofs + len, BUFFER_SIZE - (ofs + len), FILLER);
118        }
119    }
120
121    private static void testCopyByteArrayToByteArray(Unsafe unsafe) throws Exception {
122        System.out.println("Testing copyMemory() for byte[] to byte[]...");
123        byte[] b1 = new byte[BUFFER_SIZE];
124        byte[] b2 = new byte[BUFFER_SIZE];
125        for (int i = 0; i < N; i++) {
126            set(b1, 0, BUFFER_SIZE, FILLER);
127            set(b2, 0, BUFFER_SIZE, FILLER2);
128            int ofs = random.nextInt(BUFFER_SIZE / 2);
129            int len = random.nextInt(BUFFER_SIZE / 2);
130            int val = random.nextInt(256);
131            set(b1, ofs, len, val);
132            int ofs2 = random.nextInt(BUFFER_SIZE / 2);
133            unsafe.copyMemory(b1, Unsafe.ARRAY_BYTE_BASE_OFFSET + ofs,
134                b2, Unsafe.ARRAY_BYTE_BASE_OFFSET + ofs2, len);
135            check(b2, 0, ofs2 - 1, FILLER2);
136            check(b2, ofs2, len, val);
137            check(b2, ofs2 + len, BUFFER_SIZE - (ofs2 + len), FILLER2);
138        }
139    }
140
141    private static void testCopyByteArrayToRawMemory(Unsafe unsafe) throws Exception {
142        System.out.println("Testing copyMemory() for byte[] to raw memory...");
143        byte[] b1 = new byte[BUFFER_SIZE];
144        long b2 = getMemory(BUFFER_SIZE);
145        for (int i = 0; i < N; i++) {
146            set(b1, 0, BUFFER_SIZE, FILLER);
147            set(unsafe, b2, 0, BUFFER_SIZE, FILLER2);
148            int ofs = random.nextInt(BUFFER_SIZE / 2);
149            int len = random.nextInt(BUFFER_SIZE / 2);
150            int val = random.nextInt(256);
151            set(b1, ofs, len, val);
152            int ofs2 = random.nextInt(BUFFER_SIZE / 2);
153            unsafe.copyMemory(b1, Unsafe.ARRAY_BYTE_BASE_OFFSET + ofs,
154                null, b2 + ofs2, len);
155            check(unsafe, b2, 0, ofs2 - 1, FILLER2);
156            check(unsafe, b2, ofs2, len, val);
157            check(unsafe, b2, ofs2 + len, BUFFER_SIZE - (ofs2 + len), FILLER2);
158        }
159    }
160
161    private static void testCopyRawMemoryToByteArray(Unsafe unsafe) throws Exception {
162        System.out.println("Testing copyMemory() for raw memory to byte[]...");
163        long b1 = getMemory(BUFFER_SIZE);
164        byte[] b2 = new byte[BUFFER_SIZE];
165        for (int i = 0; i < N; i++) {
166            set(unsafe, b1, 0, BUFFER_SIZE, FILLER);
167            set(b2, 0, BUFFER_SIZE, FILLER2);
168            int ofs = random.nextInt(BUFFER_SIZE / 2);
169            int len = random.nextInt(BUFFER_SIZE / 2);
170            int val = random.nextInt(256);
171            set(unsafe, b1, ofs, len, val);
172            int ofs2 = random.nextInt(BUFFER_SIZE / 2);
173            unsafe.copyMemory(null, b1 + ofs,
174                b2, Unsafe.ARRAY_BYTE_BASE_OFFSET + ofs2, len);
175            check(b2, 0, ofs2 - 1, FILLER2);
176            check(b2, ofs2, len, val);
177            check(b2, ofs2 + len, BUFFER_SIZE - (ofs2 + len), FILLER2);
178        }
179    }
180
181    private static void testCopyRawMemoryToRawMemory(Unsafe unsafe) throws Exception {
182        System.out.println("Testing copyMemory() for raw memory to raw memory...");
183        long b1 = getMemory(BUFFER_SIZE);
184        long b2 = getMemory(BUFFER_SIZE);
185        for (int i = 0; i < N; i++) {
186            set(unsafe, b1, 0, BUFFER_SIZE, FILLER);
187            set(unsafe, b2, 0, BUFFER_SIZE, FILLER2);
188            int ofs = random.nextInt(BUFFER_SIZE / 2);
189            int len = random.nextInt(BUFFER_SIZE / 2);
190            int val = random.nextInt(256);
191            set(unsafe, b1, ofs, len, val);
192            int ofs2 = random.nextInt(BUFFER_SIZE / 2);
193            unsafe.copyMemory(null, b1 + ofs,
194                null, b2 + ofs2, len);
195            check(unsafe, b2, 0, ofs2 - 1, FILLER2);
196            check(unsafe, b2, ofs2, len, val);
197            check(unsafe, b2, ofs2 + len, BUFFER_SIZE - (ofs2 + len), FILLER2);
198        }
199    }
200
201    private static Unsafe getUnsafe() throws Exception {
202        Field f = Unsafe.class.getDeclaredField("theUnsafe");
203        f.setAccessible(true);
204        return (Unsafe)f.get(null);
205    }
206
207    public static void main(String[] args) throws Exception {
208        Unsafe unsafe = getUnsafe();
209
210        testSetByteArray(unsafe);
211        testSetRawMemory(unsafe);
212        testCopyByteArrayToByteArray(unsafe);
213        testCopyByteArrayToRawMemory(unsafe);
214        testCopyRawMemoryToByteArray(unsafe);
215        testCopyRawMemoryToRawMemory(unsafe);
216
217        System.out.println("OK");
218    }
219
220}
221