Path: blob/master/test/jdk/java/nio/channels/FileChannel/MapTest.java
41154 views
/*1* Copyright (c) 2000, 2019, Oracle and/or its affiliates. All rights reserved.2* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.3*4* This code is free software; you can redistribute it and/or modify it5* under the terms of the GNU General Public License version 2 only, as6* published by the Free Software Foundation.7*8* This code is distributed in the hope that it will be useful, but WITHOUT9* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or10* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License11* version 2 for more details (a copy is included in the LICENSE file that12* accompanied this code).13*14* You should have received a copy of the GNU General Public License version15* 2 along with this work; if not, write to the Free Software Foundation,16* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.17*18* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA19* or visit www.oracle.com if you need additional information or have any20* questions.21*/2223/* @test24* @bug 4429043 800218025* @summary Test file mapping with FileChannel26* @run main/othervm/timeout=240 MapTest27* @key randomness28*/2930import java.io.*;31import java.nio.MappedByteBuffer;32import java.nio.channels.*;33import java.nio.channels.FileChannel.MapMode;34import java.nio.file.Files;35import static java.nio.file.StandardOpenOption.*;36import static java.nio.charset.StandardCharsets.*;37import java.util.Random;383940/**41* Testing FileChannel's mapping capabilities.42*/4344public class MapTest {4546private static PrintStream out = System.out;47private static PrintStream err = System.err;4849private static Random generator = new Random();5051private static int CHARS_PER_LINE = File.separatorChar == '/' ? 5 : 6;5253private static File blah;5455public static void main(String[] args) throws Exception {56blah = File.createTempFile("blah", null);57blah.deleteOnExit();58initTestFile(blah);59try {60out.println("Test file " + blah + " initialized");61testZero();62out.println("Zero size: OK");63testRead();64out.println("Read: OK");65testWrite();66out.println("Write: OK");67testHighOffset();68out.println("High offset: OK");69testForce();70out.println("Force: OK");71testExceptions();72out.println("Exceptions: OK");73} finally {74blah.delete();75}76}7778/**79* Creates file blah:80* 000081* 000182* 000283* 000384* .85* .86* .87* 399988*89* Blah extends beyond a single page of memory so that the90* ability to index into a file of multiple pages is tested.91*/92private static void initTestFile(File blah) throws Exception {93try (BufferedWriter writer = Files.newBufferedWriter(blah.toPath(), ISO_8859_1)) {94for (int i=0; i<4000; i++) {95String number = new Integer(i).toString();96for (int h=0; h<4-number.length(); h++)97writer.write("0");98writer.write(""+i);99writer.newLine();100}101}102}103104/**105* Tests zero size file mapping106*/107private static void testZero() throws Exception {108try (FileInputStream fis = new FileInputStream(blah)) {109FileChannel fc = fis.getChannel();110MappedByteBuffer b = fc.map(MapMode.READ_ONLY, 0, 0);111}112}113114/**115* Maps blah file with a random offset and checks to see if read116* from the ByteBuffer gets the right line number117*/118private static void testRead() throws Exception {119StringBuilder sb = new StringBuilder();120sb.setLength(4);121122for (int x=0; x<1000; x++) {123try (FileInputStream fis = new FileInputStream(blah)) {124FileChannel fc = fis.getChannel();125126long offset = generator.nextInt(10000);127long expectedResult = offset / CHARS_PER_LINE;128offset = expectedResult * CHARS_PER_LINE;129130MappedByteBuffer b = fc.map(MapMode.READ_ONLY,131offset, 100);132133for (int i=0; i<4; i++) {134byte aByte = b.get(i);135sb.setCharAt(i, (char)aByte);136}137138int result = Integer.parseInt(sb.toString());139if (result != expectedResult) {140err.println("I expected "+expectedResult);141err.println("I got "+result);142throw new Exception("Read test failed");143}144}145}146}147148/**149* Maps blah file with a random offset and checks to see if data150* written out to the file can be read back in151*/152private static void testWrite() throws Exception {153StringBuilder sb = new StringBuilder();154sb.setLength(4);155156for (int x=0; x<1000; x++) {157try (RandomAccessFile raf = new RandomAccessFile(blah, "rw")) {158FileChannel fc = raf.getChannel();159160long offset = generator.nextInt(1000);161MappedByteBuffer b = fc.map(MapMode.READ_WRITE,162offset, 100);163164for (int i=0; i<4; i++) {165b.put(i, (byte)('0' + i));166}167168for (int i=0; i<4; i++) {169byte aByte = b.get(i);170sb.setCharAt(i, (char)aByte);171}172if (!sb.toString().equals("0123"))173throw new Exception("Write test failed");174}175}176}177178private static void testHighOffset() throws Exception {179StringBuilder sb = new StringBuilder();180sb.setLength(4);181182for (int x=0; x<1000; x++) {183try (RandomAccessFile raf = new RandomAccessFile(blah, "rw")) {184FileChannel fc = raf.getChannel();185long offset = 66000;186MappedByteBuffer b = fc.map(MapMode.READ_WRITE,187offset, 100);188}189}190}191192/**193* Maps blah file, writes some data and forcing writeback of194* the data exercising various valid and invalid writeback ranges.195*/196private static void testForce() throws Exception {197for (int x=0; x<50; x++) {198try (RandomAccessFile raf = new RandomAccessFile(blah, "rw")) {199FileChannel fc = raf.getChannel();200final int BLOCK_SIZE = 64;201final int BLOCK_COUNT = (4096 * 2)/ BLOCK_SIZE;202int offset = 0;203MappedByteBuffer b = fc.map(MapMode.READ_WRITE,2040, BLOCK_SIZE * (BLOCK_COUNT + 1));205206for (int blocks = 0; blocks < BLOCK_COUNT; blocks++) {207for (int i = 0; i < BLOCK_SIZE; i++) {208b.put(offset + i, (byte)('0' + i));209}210b.force(offset, BLOCK_SIZE);211offset += BLOCK_SIZE;212}213214Exception exc = null;215try {216// start and end are out of range217b.force(offset + BLOCK_SIZE, BLOCK_SIZE);218} catch (IndexOutOfBoundsException e) {219exc = e;220}221if (exc == null) {222throw new RuntimeException("expected Exception for force beyond buffer extent");223}224225exc = null;226try {227// start is in range but end is out of range228b.force(offset, 2 * BLOCK_SIZE);229} catch (IndexOutOfBoundsException e) {230exc = e;231}232if (exc == null) {233throw new RuntimeException("expected Exception for force beyond write limit");234}235}236}237}238239/**240* Test exceptions specified by map method241*/242private static void testExceptions() throws Exception {243// check exceptions when channel opened for read access244try (FileChannel fc = FileChannel.open(blah.toPath(), READ)) {245testExceptions(fc);246247checkException(fc, MapMode.READ_WRITE, 0L, fc.size(),248NonWritableChannelException.class);249250checkException(fc, MapMode.READ_WRITE, -1L, fc.size(),251NonWritableChannelException.class, IllegalArgumentException.class);252253checkException(fc, MapMode.READ_WRITE, 0L, -1L,254NonWritableChannelException.class, IllegalArgumentException.class);255256checkException(fc, MapMode.PRIVATE, 0L, fc.size(),257NonWritableChannelException.class);258259checkException(fc, MapMode.PRIVATE, -1L, fc.size(),260NonWritableChannelException.class, IllegalArgumentException.class);261262checkException(fc, MapMode.PRIVATE, 0L, -1L,263NonWritableChannelException.class, IllegalArgumentException.class);264}265266// check exceptions when channel opened for write access267try (FileChannel fc = FileChannel.open(blah.toPath(), WRITE)) {268testExceptions(fc);269270checkException(fc, MapMode.READ_ONLY, 0L, fc.size(),271NonReadableChannelException.class);272273checkException(fc, MapMode.READ_ONLY, -1L, fc.size(),274NonReadableChannelException.class, IllegalArgumentException.class);275276/*277* implementation/spec mismatch, these tests disabled for now278*/279//checkException(fc, MapMode.READ_WRITE, 0L, fc.size(),280// NonWritableChannelException.class);281//checkException(fc, MapMode.PRIVATE, 0L, fc.size(),282// NonWritableChannelException.class);283}284285// check exceptions when channel opened for read and write access286try (FileChannel fc = FileChannel.open(blah.toPath(), READ, WRITE)) {287testExceptions(fc);288}289}290291private static void testExceptions(FileChannel fc) throws IOException {292checkException(fc, null, 0L, fc.size(),293NullPointerException.class);294295checkException(fc, MapMode.READ_ONLY, -1L, fc.size(),296IllegalArgumentException.class);297298checkException(fc, null, -1L, fc.size(),299IllegalArgumentException.class, NullPointerException.class);300301checkException(fc, MapMode.READ_ONLY, 0L, -1L,302IllegalArgumentException.class);303304checkException(fc, null, 0L, -1L,305IllegalArgumentException.class, NullPointerException.class);306307checkException(fc, MapMode.READ_ONLY, 0L, Integer.MAX_VALUE + 1L,308IllegalArgumentException.class);309310checkException(fc, null, 0L, Integer.MAX_VALUE + 1L,311IllegalArgumentException.class, NullPointerException.class);312313checkException(fc, MapMode.READ_ONLY, Long.MAX_VALUE, 1L,314IllegalArgumentException.class);315316checkException(fc, null, Long.MAX_VALUE, 1L,317IllegalArgumentException.class, NullPointerException.class);318319}320321/**322* Checks that FileChannel map throws one of the expected exceptions323* when invoked with the given inputs.324*/325private static void checkException(FileChannel fc,326MapMode mode,327long position,328long size,329Class<?>... expected)330throws IOException331{332Exception exc = null;333try {334fc.map(mode, position, size);335} catch (Exception actual) {336exc = actual;337}338if (exc != null) {339for (Class<?> clazz: expected) {340if (clazz.isInstance(exc)) {341return;342}343}344}345System.err.println("Expected one of");346for (Class<?> clazz: expected) {347System.out.println(clazz);348}349if (exc == null) {350throw new RuntimeException("No expection thrown");351} else {352throw new RuntimeException("Unexpected exception thrown", exc);353}354}355}356357358