/* * Copyright (c) 2011, 2013, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License version 2 only, as * published by the Free Software Foundation. * * This code is distributed in the hope that it will be useful, but WITHOUT * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License * version 2 for more details (a copy is included in the LICENSE file that * accompanied this code). * * You should have received a copy of the GNU General Public License version * 2 along with this work; if not, write to the Free Software Foundation, * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. * * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA * or visit www.oracle.com if you need additional information or have any * questions. */ /* @test * @bug 7006126 8020669 8024788 8019526 * @build BytesAndLines PassThroughFileSystem * @run testng BytesAndLines * @summary Unit test for methods for Files readAllBytes, readAllLines and * and write methods. * @key randomness */ import java.nio.ByteBuffer; import java.nio.CharBuffer; import java.nio.file.Files; import java.nio.file.Path; import java.nio.file.Paths; import java.nio.file.OpenOption; import static java.nio.file.StandardOpenOption.*; import java.nio.charset.Charset; import java.nio.charset.CharacterCodingException; import java.nio.charset.MalformedInputException; import java.nio.charset.UnmappableCharacterException; import static java.nio.charset.StandardCharsets.*; import java.util.Arrays; import java.util.ArrayList; import java.util.Collections; import java.util.List; import java.util.Random; import java.util.concurrent.Callable; import java.io.IOException; import org.testng.annotations.AfterClass; import org.testng.annotations.BeforeClass; import org.testng.annotations.Test; import static org.testng.Assert.*; @Test(groups = "unit") public class BytesAndLines { // data for text files private static final String EN_STRING = "The quick brown fox jumps over the lazy dog"; private static final String JA_STRING = "\u65e5\u672c\u8a9e\u6587\u5b57\u5217"; // used for random byte content private static Random RAND = new Random(); // file used by most tests private Path tmpfile; @BeforeClass void setup() throws IOException { tmpfile = Files.createTempFile("blah", null); } @AfterClass void cleanup() throws IOException { Files.deleteIfExists(tmpfile); } /** * Returns a byte[] of the given size with random content */ private byte[] genBytes(int size) { byte[] arr = new byte[size]; RAND.nextBytes(arr); return arr; } /** * Exercise NullPointerException */ public void testNulls() { Path file = Paths.get("foo"); byte[] bytes = new byte[100]; List<String> lines = Collections.emptyList(); checkNullPointerException(() -> Files.readAllBytes(null)); checkNullPointerException(() -> Files.write(null, bytes)); checkNullPointerException(() -> Files.write(file, (byte[])null)); checkNullPointerException(() -> Files.write(file, bytes, (OpenOption[])null)); checkNullPointerException(() -> Files.write(file, bytes, new OpenOption[] { null } )); checkNullPointerException(() -> Files.readAllLines(null)); checkNullPointerException(() -> Files.readAllLines(file, (Charset)null)); checkNullPointerException(() -> Files.readAllLines(null, Charset.defaultCharset())); checkNullPointerException(() -> Files.write(null, lines)); checkNullPointerException(() -> Files.write(file, (List<String>)null)); checkNullPointerException(() -> Files.write(file, lines, (OpenOption[])null)); checkNullPointerException(() -> Files.write(file, lines, new OpenOption[] { null } )); checkNullPointerException(() -> Files.write(null, lines, Charset.defaultCharset())); checkNullPointerException(() -> Files.write(file, null, Charset.defaultCharset())); checkNullPointerException(() -> Files.write(file, lines, (Charset)null)); checkNullPointerException(() -> Files.write(file, lines, Charset.defaultCharset(), (OpenOption[])null)); checkNullPointerException(() -> Files.write(file, lines, Charset.defaultCharset(), new OpenOption[] { null } )); } private void checkNullPointerException(Callable<?> c) { try { c.call(); fail("NullPointerException expected"); } catch (NullPointerException ignore) { } catch (Exception e) { fail(e + " not expected"); } } /** * Exercise Files.readAllBytes(Path) on varied file sizes */ public void testReadAllBytes() throws IOException { int size = 0; while (size <= 16*1024) { testReadAllBytes(size); size += 512; } } private void testReadAllBytes(int size) throws IOException { // write bytes to file (random content) byte[] expected = genBytes(size); Files.write(tmpfile, expected); // check expected bytes are read byte[] read = Files.readAllBytes(tmpfile); assertTrue(Arrays.equals(read, expected), "Bytes read not the same as written"); } /** * Linux specific test to exercise Files.readAllBytes on /proc. This is * special because file sizes are reported as 0 even though the file * has content. */ public void testReadAllBytesOnProcFS() throws IOException { // read from procfs if (System.getProperty("os.name").equals("Linux")) { Path statFile = Paths.get("/proc/self/stat"); byte[] data = Files.readAllBytes(statFile); assertTrue(data.length > 0, "Files.readAllBytes('" + statFile + "') failed to read"); } } /** * Exercise Files.readAllBytes(Path) on custom file system. This is special * because readAllBytes was originally implemented to use FileChannel * and so may not be supported by custom file system providers. */ public void testReadAllBytesOnCustomFS() throws IOException { Path myfile = PassThroughFileSystem.create().getPath("myfile"); try { int size = 0; while (size <= 1024) { byte[] b1 = genBytes(size); Files.write(myfile, b1); byte[] b2 = Files.readAllBytes(myfile); assertTrue(Arrays.equals(b1, b2), "bytes not equal"); size += 512; } } finally { Files.deleteIfExists(myfile); } } /** * Exercise Files.write(Path, byte[], OpenOption...) on various sizes */ public void testWriteBytes() throws IOException { int size = 0; while (size < 16*1024) { testWriteBytes(size, false); testWriteBytes(size, true); size += 512; } } private void testWriteBytes(int size, boolean append) throws IOException { byte[] bytes = genBytes(size); Path result = Files.write(tmpfile, bytes); assertTrue(result == tmpfile); if (append) { Files.write(tmpfile, bytes, APPEND); assertTrue(Files.size(tmpfile) == size*2); } byte[] expected; if (append) { expected = new byte[size << 1]; System.arraycopy(bytes, 0, expected, 0, bytes.length); System.arraycopy(bytes, 0, expected, bytes.length, bytes.length); } else { expected = bytes; } byte[] read = Files.readAllBytes(tmpfile); assertTrue(Arrays.equals(read, expected), "Bytes read not the same as written"); } /** * Exercise Files.readAllLines(Path, Charset) */ public void testReadAllLines() throws IOException { // zero lines Files.write(tmpfile, new byte[0]); List<String> lines = Files.readAllLines(tmpfile, US_ASCII); assertTrue(lines.isEmpty(), "No line expected"); // one line byte[] hi = { (byte)'h', (byte)'i' }; Files.write(tmpfile, hi); lines = Files.readAllLines(tmpfile, US_ASCII); assertTrue(lines.size() == 1, "One line expected"); assertTrue(lines.get(0).equals("hi"), "'Hi' expected"); // two lines using platform's line separator List<String> expected = Arrays.asList("hi", "there"); Files.write(tmpfile, expected, US_ASCII); assertTrue(Files.size(tmpfile) > 0, "File is empty"); lines = Files.readAllLines(tmpfile, US_ASCII); assertTrue(lines.equals(expected), "Unexpected lines"); // MalformedInputException byte[] bad = { (byte)0xff, (byte)0xff }; Files.write(tmpfile, bad); try { Files.readAllLines(tmpfile, US_ASCII); fail("MalformedInputException expected"); } catch (MalformedInputException ignore) { } } /** * Linux specific test to exercise Files.readAllLines(Path) on /proc. This * is special because file sizes are reported as 0 even though the file * has content. */ public void testReadAllLinesOnProcFS() throws IOException { if (System.getProperty("os.name").equals("Linux")) { Path statFile = Paths.get("/proc/self/stat"); List<String> lines = Files.readAllLines(statFile); assertTrue(lines.size() > 0, "Files.readAllLines('" + statFile + "') failed to read"); } } /** * Exercise Files.readAllLines(Path) */ public void testReadAllLinesUTF8() throws IOException { Files.write(tmpfile, encodeAsUTF8(EN_STRING + "\n" + JA_STRING)); List<String> lines = Files.readAllLines(tmpfile); assertTrue(lines.size() == 2, "Read " + lines.size() + " lines instead of 2"); assertTrue(lines.get(0).equals(EN_STRING)); assertTrue(lines.get(1).equals(JA_STRING)); // a sample of malformed sequences testReadAllLinesMalformedUTF8((byte)0xFF); // one-byte sequence testReadAllLinesMalformedUTF8((byte)0xC0, (byte)0x80); // invalid first byte testReadAllLinesMalformedUTF8((byte)0xC2, (byte)0x00); // invalid second byte } private byte[] encodeAsUTF8(String s) throws CharacterCodingException { // not using s.getBytes here so as to catch unmappable characters ByteBuffer bb = UTF_8.newEncoder().encode(CharBuffer.wrap(s)); byte[] result = new byte[bb.limit()]; bb.get(result); assertTrue(bb.remaining() == 0); return result; } private void testReadAllLinesMalformedUTF8(byte... bytes) throws IOException { Files.write(tmpfile, bytes); try { Files.readAllLines(tmpfile); fail("MalformedInputException expected"); } catch (MalformedInputException ignore) { } } /** * Exercise Files.write(Path, Iterable<? extends CharSequence>, Charset, OpenOption...) */ public void testWriteLines() throws IOException { // zero lines Path result = Files.write(tmpfile, Collections.<String>emptyList(), US_ASCII); assert(Files.size(tmpfile) == 0); assert(result == tmpfile); // two lines List<String> lines = Arrays.asList("hi", "there"); Files.write(tmpfile, lines, US_ASCII); List<String> actual = Files.readAllLines(tmpfile, US_ASCII); assertTrue(actual.equals(lines), "Unexpected lines"); // append two lines Files.write(tmpfile, lines, US_ASCII, APPEND); List<String> expected = new ArrayList<>(); expected.addAll(lines); expected.addAll(lines); assertTrue(expected.size() == 4, "List should have 4 elements"); actual = Files.readAllLines(tmpfile, US_ASCII); assertTrue(actual.equals(expected), "Unexpected lines"); // UnmappableCharacterException try { String s = "\u00A0\u00A1"; Files.write(tmpfile, Arrays.asList(s), US_ASCII); fail("UnmappableCharacterException expected"); } catch (UnmappableCharacterException ignore) { } } /** * Exercise Files.write(Path, Iterable<? extends CharSequence>, OpenOption...) */ public void testWriteLinesUTF8() throws IOException { List<String> lines = Arrays.asList(EN_STRING, JA_STRING); Files.write(tmpfile, lines); List<String> actual = Files.readAllLines(tmpfile, UTF_8); assertTrue(actual.equals(lines), "Unexpected lines"); } }