package stream

import org.assertj.core.api.Assertions.assertThat
import org.junit.jupiter.api.Assertions.assertThrows
import org.junit.jupiter.api.BeforeEach
import org.junit.jupiter.api.Test
import org.junit.jupiter.api.TestInstance
import org.junit.jupiter.api.TestInstance.Lifecycle.PER_CLASS
import testutil.TestUtilities.createIOExceptionThrowingOutputStream
import java.io.ByteArrayOutputStream

@TestInstance(PER_CLASS)
class SafeOutputStreamTest {

    private lateinit var safe: SafeOutputStream
    private lateinit var safeWithException: SafeOutputStream
    private lateinit var output: ByteArrayOutputStream

    @BeforeEach
    fun setUp() {
        output = ByteArrayOutputStream()
        safe = SafeOutputStream(output)
        safeWithException = SafeOutputStream(createIOExceptionThrowingOutputStream())
    }

    @Test
    fun `write works`() {
        safe.write("write".toByteArray())
        assertThat(output.toString()).isEqualTo("write")
    }

    @Test
    fun `flush works`() {
        safe.flush()
    }

    @Test
    fun `close works`() {
        safe.close()
    }

    @Test
    fun `write throws correct exception`() {
        assertThrows(LispIOException::class.java) { safeWithException.write("write".toByteArray()) }
    }

    @Test
    fun `flush throws correct exception`() {
        assertThrows(LispIOException::class.java) { safeWithException.flush() }
    }

    @Test
    fun `close throws correct exception`() {
        assertThrows(LispIOException::class.java) { safeWithException.close() }
    }
}