1 /* 2 * Copyright (c) 2000, 2012, 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 4429043 8002180 26 * @summary Test file mapping with FileChannel 27 * @run main/othervm MapTest 28 * @key randomness 29 */ 30 31 import java.io.*; 32 import java.nio.MappedByteBuffer; 33 import java.nio.channels.*; 34 import java.nio.channels.FileChannel.MapMode; 35 import java.nio.file.Files; 36 import static java.nio.file.StandardOpenOption.*; 37 import static java.nio.charset.StandardCharsets.*; 38 import java.util.Random; 39 40 41 /** 42 * Testing FileChannel's mapping capabilities. 43 */ 44 45 public class MapTest { 46 47 private static PrintStream out = System.out; 48 private static PrintStream err = System.err; 49 50 private static Random generator = new Random(); 51 52 private static int CHARS_PER_LINE = File.separatorChar == '/' ? 5 : 6; 53 54 private static File blah; 55 56 public static void main(String[] args) throws Exception { 57 blah = File.createTempFile("blah", null); 58 blah.deleteOnExit(); 59 initTestFile(blah); 60 try { 61 out.println("Test file " + blah + " initialized"); 62 testZero(); 63 out.println("Zero size: OK"); 64 testRead(); 65 out.println("Read: OK"); 66 testWrite(); 67 out.println("Write: OK"); 68 testHighOffset(); 69 out.println("High offset: OK"); 70 testExceptions(); 71 out.println("Exceptions: OK"); 72 } finally { 73 blah.delete(); 74 } 75 } 76 77 /** 78 * Creates file blah: 79 * 0000 80 * 0001 81 * 0002 82 * 0003 83 * . 84 * . 85 * . 86 * 3999 87 * 88 * Blah extends beyond a single page of memory so that the 89 * ability to index into a file of multiple pages is tested. 90 */ 91 private static void initTestFile(File blah) throws Exception { 92 try (BufferedWriter writer = Files.newBufferedWriter(blah.toPath(), ISO_8859_1)) { 93 for (int i=0; i<4000; i++) { 94 String number = new Integer(i).toString(); 95 for (int h=0; h<4-number.length(); h++) 96 writer.write("0"); 97 writer.write(""+i); 98 writer.newLine(); 99 } 100 } 101 } 102 103 /** 104 * Tests zero size file mapping 105 */ 106 private static void testZero() throws Exception { 107 try (FileInputStream fis = new FileInputStream(blah)) { 108 FileChannel fc = fis.getChannel(); 109 MappedByteBuffer b = fc.map(MapMode.READ_ONLY, 0, 0); 110 } 111 } 112 113 /** 114 * Maps blah file with a random offset and checks to see if read 115 * from the ByteBuffer gets the right line number 116 */ 117 private static void testRead() throws Exception { 118 StringBuilder sb = new StringBuilder(); 119 sb.setLength(4); 120 121 for (int x=0; x<1000; x++) { 122 try (FileInputStream fis = new FileInputStream(blah)) { 123 FileChannel fc = fis.getChannel(); 124 125 long offset = generator.nextInt(10000); 126 long expectedResult = offset / CHARS_PER_LINE; 127 offset = expectedResult * CHARS_PER_LINE; 128 129 MappedByteBuffer b = fc.map(MapMode.READ_ONLY, 130 offset, 100); 131 132 for (int i=0; i<4; i++) { 133 byte aByte = b.get(i); 134 sb.setCharAt(i, (char)aByte); 135 } 136 137 int result = Integer.parseInt(sb.toString()); 138 if (result != expectedResult) { 139 err.println("I expected "+expectedResult); 140 err.println("I got "+result); 141 throw new Exception("Read test failed"); 142 } 143 } 144 } 145 } 146 147 /** 148 * Maps blah file with a random offset and checks to see if data 149 * written out to the file can be read back in 150 */ 151 private static void testWrite() throws Exception { 152 StringBuilder sb = new StringBuilder(); 153 sb.setLength(4); 154 155 for (int x=0; x<1000; x++) { 156 try (RandomAccessFile raf = new RandomAccessFile(blah, "rw")) { 157 FileChannel fc = raf.getChannel(); 158 159 long offset = generator.nextInt(1000); 160 MappedByteBuffer b = fc.map(MapMode.READ_WRITE, 161 offset, 100); 162 163 for (int i=0; i<4; i++) { 164 b.put(i, (byte)('0' + i)); 165 } 166 167 for (int i=0; i<4; i++) { 168 byte aByte = b.get(i); 169 sb.setCharAt(i, (char)aByte); 170 } 171 if (!sb.toString().equals("0123")) 172 throw new Exception("Write test failed"); 173 } 174 } 175 } 176 177 private static void testHighOffset() throws Exception { 178 StringBuilder sb = new StringBuilder(); 179 sb.setLength(4); 180 181 for (int x=0; x<1000; x++) { 182 try (RandomAccessFile raf = new RandomAccessFile(blah, "rw")) { 183 FileChannel fc = raf.getChannel(); 184 long offset = 66000; 185 MappedByteBuffer b = fc.map(MapMode.READ_WRITE, 186 offset, 100); 187 } 188 } 189 } 190 191 /** 192 * Test exceptions specified by map method 193 */ 194 private static void testExceptions() throws Exception { 195 // check exceptions when channel opened for read access 196 try (FileChannel fc = FileChannel.open(blah.toPath(), READ)) { 197 testExceptions(fc); 198 199 checkException(fc, MapMode.READ_WRITE, 0L, fc.size(), 200 NonWritableChannelException.class); 201 202 checkException(fc, MapMode.READ_WRITE, -1L, fc.size(), 203 NonWritableChannelException.class, IllegalArgumentException.class); 204 205 checkException(fc, MapMode.READ_WRITE, 0L, -1L, 206 NonWritableChannelException.class, IllegalArgumentException.class); 207 208 checkException(fc, MapMode.PRIVATE, 0L, fc.size(), 209 NonWritableChannelException.class); 210 211 checkException(fc, MapMode.PRIVATE, -1L, fc.size(), 212 NonWritableChannelException.class, IllegalArgumentException.class); 213 214 checkException(fc, MapMode.PRIVATE, 0L, -1L, 215 NonWritableChannelException.class, IllegalArgumentException.class); 216 } 217 218 // check exceptions when channel opened for write access 219 try (FileChannel fc = FileChannel.open(blah.toPath(), WRITE)) { 220 testExceptions(fc); 221 222 checkException(fc, MapMode.READ_ONLY, 0L, fc.size(), 223 NonReadableChannelException.class); 224 225 checkException(fc, MapMode.READ_ONLY, -1L, fc.size(), 226 NonReadableChannelException.class, IllegalArgumentException.class); 227 228 /* 229 * implementation/spec mismatch, these tests disabled for now 230 */ 231 //checkException(fc, MapMode.READ_WRITE, 0L, fc.size(), 232 // NonWritableChannelException.class); 233 //checkException(fc, MapMode.PRIVATE, 0L, fc.size(), 234 // NonWritableChannelException.class); 235 } 236 237 // check exceptions when channel opened for read and write access 238 try (FileChannel fc = FileChannel.open(blah.toPath(), READ, WRITE)) { 239 testExceptions(fc); 240 } 241 } 242 243 private static void testExceptions(FileChannel fc) throws IOException { 244 checkException(fc, null, 0L, fc.size(), 245 NullPointerException.class); 246 247 checkException(fc, MapMode.READ_ONLY, -1L, fc.size(), 248 IllegalArgumentException.class); 249 250 checkException(fc, null, -1L, fc.size(), 251 IllegalArgumentException.class, NullPointerException.class); 252 253 checkException(fc, MapMode.READ_ONLY, 0L, -1L, 254 IllegalArgumentException.class); 255 256 checkException(fc, null, 0L, -1L, 257 IllegalArgumentException.class, NullPointerException.class); 258 259 checkException(fc, MapMode.READ_ONLY, 0L, Integer.MAX_VALUE + 1L, 260 IllegalArgumentException.class); 261 262 checkException(fc, null, 0L, Integer.MAX_VALUE + 1L, 263 IllegalArgumentException.class, NullPointerException.class); 264 265 checkException(fc, MapMode.READ_ONLY, Long.MAX_VALUE, 1L, 266 IllegalArgumentException.class); 267 268 checkException(fc, null, Long.MAX_VALUE, 1L, 269 IllegalArgumentException.class, NullPointerException.class); 270 271 } 272 273 /** 274 * Checks that FileChannel map throws one of the expected exceptions 275 * when invoked with the given inputs. 276 */ 277 private static void checkException(FileChannel fc, 278 MapMode mode, 279 long position, 280 long size, 281 Class<?>... expected) 282 throws IOException 283 { 284 Exception exc = null; 285 try { 286 fc.map(mode, position, size); 287 } catch (Exception actual) { 288 exc = actual; 289 } 290 if (exc != null) { 291 for (Class<?> clazz: expected) { 292 if (clazz.isInstance(exc)) { 293 return; 294 } 295 } 296 } 297 System.err.println("Expected one of"); 298 for (Class<?> clazz: expected) { 299 System.out.println(clazz); 300 } 301 if (exc == null) { 302 throw new RuntimeException("No expection thrown"); 303 } else { 304 throw new RuntimeException("Unexpected exception thrown", exc); 305 } 306 } 307 }