package de.fxnn.brainfuck.tape;

import java.io.ByteArrayInputStream;
import java.io.DataInput;
import java.io.DataInputStream;

import com.google.common.io.ByteArrayDataOutput;
import com.google.common.io.ByteStreams;
import org.junit.Assert;
import org.junit.Before;
import org.junit.Test;

public class InfiniteSignedIntegerTapeTest {

  InfiniteSignedIntegerTape sut;

  ByteArrayDataOutput output;

  DataInput input;

  @Before
  public void setUp() {
    sut = new InfiniteSignedIntegerTape(TapeEofBehaviour.THROWS);
    output = ByteStreams.newDataOutput();
    input = new DataInputStream(new ByteArrayInputStream(new byte[0]));
  }

  @Test
  public void testInitiallyZero() {

    Assert.assertTrue(sut.isZero());

  }

  @Test
  public void testNotZeroAfterIncrement() {

    sut.increment();

    Assert.assertFalse(sut.isZero());

  }

  @Test
  public void testNotZeroAfterDecrement() {

    sut.decrement();

    Assert.assertFalse(sut.isZero());

  }

  @Test
  public void testMovement() throws Exception {

    sut.write(1);
    sut.moveForward();
    sut.write(2);
    sut.moveBackward();

    Assert.assertEquals(1, (int) sut.read());

  }

  @Test
  public void testMovementOverSegmentBorders() throws Exception {

    sut.write(1);
    sut.moveBackward();
    sut.write(2);
    sut.moveForward();

    Assert.assertEquals(1, (int) sut.read());

  }

  @Test
  public void testOutputInitially() throws Exception {

    sut.readTo(output);

    Assert.assertArrayEquals(new byte[]{0, 0, 0, 0}, output.toByteArray());

  }

  @Test
  public void testOutputAfterIncrement() throws Exception {

    sut.increment();
    sut.readTo(output);

    Assert.assertArrayEquals(new byte[]{0, 0, 0, 1}, output.toByteArray());

  }

  @Test
  public void testOutputAfterDecrement() throws Exception {

    sut.decrement();
    sut.readTo(output);

    Assert.assertArrayEquals(new byte[]{-1, -1, -1, -1}, output.toByteArray());

  }

  @Test(expected = TapeIOException.class)
  public void testInputAfterEof_throws() throws Exception {

    givenEofBehaviour(TapeEofBehaviour.THROWS);

    sut.writeFrom(input);

  }

  @Test
  public void testInputAfterEof_writesZero() throws Exception {

    givenEofBehaviour(TapeEofBehaviour.READS_ZERO);

    sut.writeFrom(input);

    Assert.assertEquals(0, (int) sut.read());

  }

  @Test
  public void testInputAfterEof_writesMinusOne() throws Exception {

    givenEofBehaviour(TapeEofBehaviour.READS_MINUS_ONE);

    sut.writeFrom(input);

    Assert.assertEquals(-1, (int) sut.read());

  }

  protected void givenEofBehaviour(TapeEofBehaviour eofBehaviour) {
    sut = new InfiniteSignedIntegerTape(eofBehaviour);
  }

}
@@ -120,16 +120,71 @@
 tStream;
+%0Aimport java.io.DataOutput;%0Aimport java.io.IOException;
 %0A%0Aimport
@@ -341,16 +341,143 @@
 .Test;%0A%0A
+import static org.mockito.Matchers.anyInt;%0Aimport static org.mockito.Mockito.doThrow;%0Aimport static org.mockito.Mockito.mock;%0A%0A
 public c
@@ -550,25 +550,16 @@
 sut;%0A%0A  
-ByteArray
 DataOutp
@@ -1679,35 +1679,34 @@
 0, 0, 0%7D, output
-.to
+As
 ByteArray());%0A%0A 
@@ -1875,35 +1875,34 @@
 0, 0, 1%7D, output
-.to
+As
 ByteArray());%0A%0A 
@@ -2087,11 +2087,10 @@
 tput
-.to
+As
 Byte
@@ -2709,16 +2709,482 @@
 ;%0A%0A  %7D%0A%0A
+  @Test(expected = TapeIOException.class)%0A  public void testIoExceptionOnInput() throws Exception %7B%0A%0A    input = mock(DataInput.class);%0A    doThrow(IOException.class).when(input).readInt();%0A%0A    sut.writeFrom(input);%0A%0A  %7D%0A%0A  @Test(expected = TapeIOException.class)%0A  public void testIoExceptionOnOutput() throws Exception %7B%0A%0A    output = mock(ByteArrayDataOutput.class);%0A    doThrow(IOException.class).when(output).writeInt(anyInt());%0A%0A    sut.readTo(output);%0A%0A  %7D%0A%0A
   protec
@@ -3303,9 +3303,112 @@
 );%0A  %7D%0A%0A
+  protected byte%5B%5D outputAsByteArray() %7B%0A    return ((ByteArrayDataOutput) output).toByteArray();%0A  %7D%0A%0A
 %7D

improve test coverage