/*
 * 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.
 */

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");
    }
}
