package error import environment.RuntimeEnvironment import error.Severity.CRITICAL import error.Severity.ERROR import error.Severity.WARNING import org.assertj.core.api.Assertions.assertThat import org.junit.jupiter.api.AfterEach import org.junit.jupiter.api.BeforeEach import org.junit.jupiter.api.Test import java.io.ByteArrayOutputStream import java.io.PrintStream class ErrorManagerTest { companion object { private const val TERMINATED = "terminated" private const val MESSAGE = "message" } private val indicatorSet = mutableSetOf() private val errorOutputStream: ByteArrayOutputStream = ByteArrayOutputStream() private val outputStream: ByteArrayOutputStream = ByteArrayOutputStream() private fun createErrorManagerWithIndicators(): ErrorManager { RuntimeEnvironment.errorTerminationFunction = { indicatorSet.add(TERMINATED) } RuntimeEnvironment.errorOutput = PrintStream(errorOutputStream) RuntimeEnvironment.output = PrintStream(outputStream) RuntimeEnvironment.warningOutputDecorator = { it } RuntimeEnvironment.errorOutputDecorator = { it } RuntimeEnvironment.criticalOutputDecorator = { it } return ErrorManager() } private fun createLispException(severity: Severity) = object : LispException() { override val severity = severity override val message get() = MESSAGE } private fun assertTerminated() { assertThat(indicatorSet).contains(TERMINATED) } private fun assertNotTerminated() { assertThat(indicatorSet).doesNotContain(TERMINATED) } private fun assertWarningMessageNotWritten() { assertThat(outputStream.toByteArray()).isEmpty() } private fun assertWarningMessageWritten() { assertThat(outputStream.toByteArray()).isNotEmpty() } private fun assertErrorMessageNotWritten() { assertThat(errorOutputStream.toByteArray()).isEmpty() } private fun assertErrorMessageWritten() { assertThat(errorOutputStream.toByteArray()).isNotEmpty() } @BeforeEach fun setUp() { indicatorSet.clear() errorOutputStream.reset() outputStream.reset() RuntimeEnvironment.reset() } @AfterEach fun tearDown() { RuntimeEnvironment.reset() } @Test fun `terminates on a critical exception`() { val errorManager = createErrorManagerWithIndicators() errorManager.handle(createLispException(CRITICAL)) assertTerminated() } @Test fun `does not terminate on a warning`() { val errorManager = createErrorManagerWithIndicators() errorManager.handle(createLispException(WARNING)) assertNotTerminated() } @Test fun `does not terminate on a non-critical exception`() { val errorManager = createErrorManagerWithIndicators() errorManager.handle(createLispException(ERROR)) assertNotTerminated() } @Test fun `output is used to display a warning message`() { val errorManager = createErrorManagerWithIndicators() errorManager.handle(createLispException(WARNING)) assertNotTerminated() assertErrorMessageNotWritten() assertWarningMessageWritten() } @Test fun `error output is used to display an error message`() { val errorManager = createErrorManagerWithIndicators() errorManager.handle(createLispException(ERROR)) assertNotTerminated() assertWarningMessageNotWritten() assertErrorMessageWritten() } @Test fun `no message is displayed before an error`() { createErrorManagerWithIndicators() assertNotTerminated() assertErrorMessageNotWritten() } @Test fun `uses output function to display messages with termination`() { val errorManager = createErrorManagerWithIndicators() errorManager.handle(createLispException(CRITICAL)) assertTerminated() assertErrorMessageWritten() } @Test fun `severity enum test coverage`() { for (severity in Severity.values()) Severity.valueOf(severity.toString()) } }