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