1 /* 2 * Copyright (c) 2011, 2013, 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 7006126 8020669 8024788 8019526 26 * @build BytesAndLines PassThroughFileSystem 27 * @run testng BytesAndLines 28 * @summary Unit test for methods for Files readAllBytes, readAllLines and 29 * and write methods. 30 * @key randomness 31 */ 32 33 import java.nio.ByteBuffer; 34 import java.nio.CharBuffer; 35 import java.nio.file.Files; 36 import java.nio.file.Path; 37 import java.nio.file.Paths; 38 import java.nio.file.OpenOption; 39 import static java.nio.file.StandardOpenOption.*; 40 import java.nio.charset.Charset; 41 import java.nio.charset.CharacterCodingException; 42 import java.nio.charset.MalformedInputException; 43 import java.nio.charset.UnmappableCharacterException; 44 import static java.nio.charset.StandardCharsets.*; 45 import java.util.Arrays; 46 import java.util.ArrayList; 47 import java.util.Collections; 48 import java.util.List; 49 import java.util.Random; 50 import java.util.concurrent.Callable; 51 import java.io.IOException; 52 53 import org.testng.annotations.AfterClass; 54 import org.testng.annotations.BeforeClass; 55 import org.testng.annotations.Test; 56 import static org.testng.Assert.*; 57 58 @Test(groups = "unit") 59 public class BytesAndLines { 60 61 // data for text files 62 private static final String EN_STRING = "The quick brown fox jumps over the lazy dog"; 63 private static final String JA_STRING = "\u65e5\u672c\u8a9e\u6587\u5b57\u5217"; 64 65 // used for random byte content 66 private static Random RAND = new Random(); 67 68 // file used by most tests 69 private Path tmpfile; 70 71 @BeforeClass 72 void setup() throws IOException { 73 tmpfile = Files.createTempFile("blah", null); 74 } 75 76 @AfterClass 77 void cleanup() throws IOException { 78 Files.deleteIfExists(tmpfile); 79 } 80 81 /** 82 * Returns a byte[] of the given size with random content 83 */ 84 private byte[] genBytes(int size) { 85 byte[] arr = new byte[size]; 86 RAND.nextBytes(arr); 87 return arr; 88 } 89 90 /** 91 * Exercise NullPointerException 92 */ 93 public void testNulls() { 94 Path file = Paths.get("foo"); 95 byte[] bytes = new byte[100]; 96 List<String> lines = Collections.emptyList(); 97 98 checkNullPointerException(() -> Files.readAllBytes(null)); 99 100 checkNullPointerException(() -> Files.write(null, bytes)); 101 checkNullPointerException(() -> Files.write(file, (byte[])null)); 102 checkNullPointerException(() -> Files.write(file, bytes, (OpenOption[])null)); 103 checkNullPointerException(() -> Files.write(file, bytes, new OpenOption[] { null } )); 104 105 checkNullPointerException(() -> Files.readAllLines(null)); 106 checkNullPointerException(() -> Files.readAllLines(file, (Charset)null)); 107 checkNullPointerException(() -> Files.readAllLines(null, Charset.defaultCharset())); 108 109 checkNullPointerException(() -> Files.write(null, lines)); 110 checkNullPointerException(() -> Files.write(file, (List<String>)null)); 111 checkNullPointerException(() -> Files.write(file, lines, (OpenOption[])null)); 112 checkNullPointerException(() -> Files.write(file, lines, new OpenOption[] { null } )); 113 checkNullPointerException(() -> Files.write(null, lines, Charset.defaultCharset())); 114 checkNullPointerException(() -> Files.write(file, null, Charset.defaultCharset())); 115 checkNullPointerException(() -> Files.write(file, lines, (Charset)null)); 116 checkNullPointerException(() -> Files.write(file, lines, Charset.defaultCharset(), (OpenOption[])null)); 117 checkNullPointerException(() -> Files.write(file, lines, Charset.defaultCharset(), new OpenOption[] { null } )); 118 } 119 120 private void checkNullPointerException(Callable<?> c) { 121 try { 122 c.call(); 123 fail("NullPointerException expected"); 124 } catch (NullPointerException ignore) { 125 } catch (Exception e) { 126 fail(e + " not expected"); 127 } 128 } 129 130 /** 131 * Exercise Files.readAllBytes(Path) on varied file sizes 132 */ 133 public void testReadAllBytes() throws IOException { 134 int size = 0; 135 while (size <= 16*1024) { 136 testReadAllBytes(size); 137 size += 512; 138 } 139 } 140 141 private void testReadAllBytes(int size) throws IOException { 142 // write bytes to file (random content) 143 byte[] expected = genBytes(size); 144 Files.write(tmpfile, expected); 145 146 // check expected bytes are read 147 byte[] read = Files.readAllBytes(tmpfile); 148 assertTrue(Arrays.equals(read, expected), "Bytes read not the same as written"); 149 } 150 151 /** 152 * Linux specific test to exercise Files.readAllBytes on /proc. This is 153 * special because file sizes are reported as 0 even though the file 154 * has content. 155 */ 156 public void testReadAllBytesOnProcFS() throws IOException { 157 // read from procfs 158 if (System.getProperty("os.name").equals("Linux")) { 159 Path statFile = Paths.get("/proc/self/stat"); 160 byte[] data = Files.readAllBytes(statFile); 161 assertTrue(data.length > 0, "Files.readAllBytes('" + statFile + "') failed to read"); 162 } 163 } 164 165 /** 166 * Exercise Files.readAllBytes(Path) on custom file system. This is special 167 * because readAllBytes was originally implemented to use FileChannel 168 * and so may not be supported by custom file system providers. 169 */ 170 public void testReadAllBytesOnCustomFS() throws IOException { 171 Path myfile = PassThroughFileSystem.create().getPath("myfile"); 172 try { 173 int size = 0; 174 while (size <= 1024) { 175 byte[] b1 = genBytes(size); 176 Files.write(myfile, b1); 177 byte[] b2 = Files.readAllBytes(myfile); 178 assertTrue(Arrays.equals(b1, b2), "bytes not equal"); 179 size += 512; 180 } 181 } finally { 182 Files.deleteIfExists(myfile); 183 } 184 } 185 186 /** 187 * Exercise Files.write(Path, byte[], OpenOption...) on various sizes 188 */ 189 public void testWriteBytes() throws IOException { 190 int size = 0; 191 while (size < 16*1024) { 192 testWriteBytes(size, false); 193 testWriteBytes(size, true); 194 size += 512; 195 } 196 } 197 198 private void testWriteBytes(int size, boolean append) throws IOException { 199 byte[] bytes = genBytes(size); 200 Path result = Files.write(tmpfile, bytes); 201 assertTrue(result == tmpfile); 202 if (append) { 203 Files.write(tmpfile, bytes, APPEND); 204 assertTrue(Files.size(tmpfile) == size*2); 205 } 206 207 byte[] expected; 208 if (append) { 209 expected = new byte[size << 1]; 210 System.arraycopy(bytes, 0, expected, 0, bytes.length); 211 System.arraycopy(bytes, 0, expected, bytes.length, bytes.length); 212 } else { 213 expected = bytes; 214 } 215 216 byte[] read = Files.readAllBytes(tmpfile); 217 assertTrue(Arrays.equals(read, expected), "Bytes read not the same as written"); 218 } 219 220 /** 221 * Exercise Files.readAllLines(Path, Charset) 222 */ 223 public void testReadAllLines() throws IOException { 224 // zero lines 225 Files.write(tmpfile, new byte[0]); 226 List<String> lines = Files.readAllLines(tmpfile, US_ASCII); 227 assertTrue(lines.isEmpty(), "No line expected"); 228 229 // one line 230 byte[] hi = { (byte)'h', (byte)'i' }; 231 Files.write(tmpfile, hi); 232 lines = Files.readAllLines(tmpfile, US_ASCII); 233 assertTrue(lines.size() == 1, "One line expected"); 234 assertTrue(lines.get(0).equals("hi"), "'Hi' expected"); 235 236 // two lines using platform's line separator 237 List<String> expected = Arrays.asList("hi", "there"); 238 Files.write(tmpfile, expected, US_ASCII); 239 assertTrue(Files.size(tmpfile) > 0, "File is empty"); 240 lines = Files.readAllLines(tmpfile, US_ASCII); 241 assertTrue(lines.equals(expected), "Unexpected lines"); 242 243 // MalformedInputException 244 byte[] bad = { (byte)0xff, (byte)0xff }; 245 Files.write(tmpfile, bad); 246 try { 247 Files.readAllLines(tmpfile, US_ASCII); 248 fail("MalformedInputException expected"); 249 } catch (MalformedInputException ignore) { } 250 } 251 252 /** 253 * Linux specific test to exercise Files.readAllLines(Path) on /proc. This 254 * is special because file sizes are reported as 0 even though the file 255 * has content. 256 */ 257 public void testReadAllLinesOnProcFS() throws IOException { 258 if (System.getProperty("os.name").equals("Linux")) { 259 Path statFile = Paths.get("/proc/self/stat"); 260 List<String> lines = Files.readAllLines(statFile); 261 assertTrue(lines.size() > 0, "Files.readAllLines('" + statFile + "') failed to read"); 262 } 263 } 264 265 /** 266 * Exercise Files.readAllLines(Path) 267 */ 268 public void testReadAllLinesUTF8() throws IOException { 269 Files.write(tmpfile, encodeAsUTF8(EN_STRING + "\n" + JA_STRING)); 270 271 List<String> lines = Files.readAllLines(tmpfile); 272 assertTrue(lines.size() == 2, "Read " + lines.size() + " lines instead of 2"); 273 assertTrue(lines.get(0).equals(EN_STRING)); 274 assertTrue(lines.get(1).equals(JA_STRING)); 275 276 // a sample of malformed sequences 277 testReadAllLinesMalformedUTF8((byte)0xFF); // one-byte sequence 278 testReadAllLinesMalformedUTF8((byte)0xC0, (byte)0x80); // invalid first byte 279 testReadAllLinesMalformedUTF8((byte)0xC2, (byte)0x00); // invalid second byte 280 } 281 282 private byte[] encodeAsUTF8(String s) throws CharacterCodingException { 283 // not using s.getBytes here so as to catch unmappable characters 284 ByteBuffer bb = UTF_8.newEncoder().encode(CharBuffer.wrap(s)); 285 byte[] result = new byte[bb.limit()]; 286 bb.get(result); 287 assertTrue(bb.remaining() == 0); 288 return result; 289 } 290 291 private void testReadAllLinesMalformedUTF8(byte... bytes) throws IOException { 292 Files.write(tmpfile, bytes); 293 try { 294 Files.readAllLines(tmpfile); 295 fail("MalformedInputException expected"); 296 } catch (MalformedInputException ignore) { } 297 } 298 299 /** 300 * Exercise Files.write(Path, Iterable<? extends CharSequence>, Charset, OpenOption...) 301 */ 302 public void testWriteLines() throws IOException { 303 // zero lines 304 Path result = Files.write(tmpfile, Collections.<String>emptyList(), US_ASCII); 305 assert(Files.size(tmpfile) == 0); 306 assert(result == tmpfile); 307 308 // two lines 309 List<String> lines = Arrays.asList("hi", "there"); 310 Files.write(tmpfile, lines, US_ASCII); 311 List<String> actual = Files.readAllLines(tmpfile, US_ASCII); 312 assertTrue(actual.equals(lines), "Unexpected lines"); 313 314 // append two lines 315 Files.write(tmpfile, lines, US_ASCII, APPEND); 316 List<String> expected = new ArrayList<>(); 317 expected.addAll(lines); 318 expected.addAll(lines); 319 assertTrue(expected.size() == 4, "List should have 4 elements"); 320 actual = Files.readAllLines(tmpfile, US_ASCII); 321 assertTrue(actual.equals(expected), "Unexpected lines"); 322 323 // UnmappableCharacterException 324 try { 325 String s = "\u00A0\u00A1"; 326 Files.write(tmpfile, Arrays.asList(s), US_ASCII); 327 fail("UnmappableCharacterException expected"); 328 } catch (UnmappableCharacterException ignore) { } 329 } 330 331 /** 332 * Exercise Files.write(Path, Iterable<? extends CharSequence>, OpenOption...) 333 */ 334 public void testWriteLinesUTF8() throws IOException { 335 List<String> lines = Arrays.asList(EN_STRING, JA_STRING); 336 Files.write(tmpfile, lines); 337 List<String> actual = Files.readAllLines(tmpfile, UTF_8); 338 assertTrue(actual.equals(lines), "Unexpected lines"); 339 } 340 }