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