package interpreter;

import com.github.stony.interpreter.Interpreter;
import org.junit.Assert;

import java.io.*;
import java.net.URISyntaxException;

/**
 * Barebones framework to test story files. Testing classes should extend this.
 *
 * The idea is to test the output
 */
class InterpreterTest {
    /**
     * InterpreterTest should not be instantiated directly, only extended.
     */
    protected InterpreterTest() {
    }

    /**
     * Asserts if the output of the finished story is equal to the output parameter.
     *
     * @param filePath resource file path.
     * @param output expected output.
     * @throws IOException when the file doesn't exist or a read error occured.
     * @throws URISyntaxException when the file path doesn't convert to a valid URI.
     */
    protected void assertOutputEquals(String filePath, String output) throws IOException, URISyntaxException {
        final InputStream inputStream = new ByteArrayInputStream(new byte[0]);
        final OutputStream outputStream = new ByteArrayOutputStream();
        final Interpreter interpreter = new Interpreter(readFileData(filePath), inputStream, outputStream);
        assertOutputEquals(interpreter, output);
    }

    /**
     * Asserts if the output of the finished story is equal to the output parameter.
     *
     * @param interpreter interpreter with a ByteArrayOutputStream as the output stream.
     * @param output expected output.
     * @throws IOException if converting the output stream to a UTF-8 string failed.
     * @throws IllegalArgumentException when the interpreter output stream is not an instance of ByteArrayOutputStream.
     */
    protected void assertOutputEquals(Interpreter interpreter, String output) throws IOException {
        final OutputStream outputStream = interpreter.getOutputStream();
        if (!(outputStream instanceof ByteArrayOutputStream)) {
            throw new IllegalArgumentException("Interpreter output stream must be a ByteArrayOutputStream.");
        }

        while (!interpreter.isFinished()) {
            interpreter.executeInstruction();
        }

        Assert.assertEquals(output, ((ByteArrayOutputStream) outputStream).toString("UTF-8"));
    }

    /**
     * Returns the content of a resource file as a byte array.
     *
     * @param filePath path to the resource file.
     * @return content of the resource file.
     * @throws IOException when the file doesn't exist or a read error occured.
     * @throws URISyntaxException when the file path doesn't convert to a valid URI.
     */
    @SuppressWarnings("TryFinallyCanBeTryWithResources")
    protected byte[] readFileData(String filePath) throws IOException, URISyntaxException {
        final File file = new File(getClass().getResource(filePath).toURI());
        final RandomAccessFile randomAccessFile = new RandomAccessFile(file, "r");
        try {
            byte[] bytes = new byte[(int) randomAccessFile.length()];
            randomAccessFile.readFully(bytes);
            return bytes;
        } finally {
            randomAccessFile.close();
        }
    }
}

@@ -143,16 +143,37 @@
 ception;
+%0Aimport java.net.URL;
 %0A%0A/**%0A *
@@ -620,32 +620,39 @@
 xpected output.%0A
+     *%0A
      * @throws I
@@ -642,34 +642,44 @@
 %0A     * @throws 
-IO
+FileNotFound
 Exception when t
@@ -691,35 +691,65 @@
 le doesn't exist
- or
+.%0A     * @throws IOException when
  a read error oc
@@ -2438,32 +2438,39 @@
  resource file.%0A
+     *%0A
      * @throws I
@@ -2460,34 +2460,44 @@
 %0A     * @throws 
-IO
+FileNotFound
 Exception when t
@@ -2517,19 +2517,49 @@
 't exist
- or
+.%0A     * @throws IOException when
  a read 
@@ -2648,32 +2648,53 @@
 t to a valid URI
+ -- should not happen
 .%0A     */%0A    @S
@@ -2854,29 +2854,18 @@
 nal 
-File file = new File(
+URL url = 
 getC
@@ -2892,16 +2892,173 @@
 ilePath)
+;%0A        if (url == null) %7B%0A            throw new FileNotFoundException(%22Invalid file path: %22 + filePath);%0A        %7D%0A%0A        final File file = new File(url
 .toURI()

Correct the exception thrown when the file doesn't exist in tests, in order to match the documentation.