package prolog.builtins import org.junit.jupiter.api.Assertions.assertEquals import org.junit.jupiter.api.Assertions.assertInstanceOf import org.junit.jupiter.api.Assertions.assertTrue import org.junit.jupiter.api.BeforeEach import org.junit.jupiter.api.Disabled import org.junit.jupiter.api.Test import org.junit.jupiter.params.ParameterizedTest import org.junit.jupiter.params.provider.ValueSource import prolog.ast.arithmetic.Float import prolog.ast.terms.Atom import prolog.ast.terms.CompoundTerm import java.io.ByteArrayOutputStream import java.io.PrintStream import prolog.ast.arithmetic.Integer import prolog.ast.terms.Variable import java.io.ByteArrayInputStream class IoOperatorsTests { private var outStream = ByteArrayOutputStream() @BeforeEach fun setup() { outStream = ByteArrayOutputStream() System.setOut(PrintStream(outStream)) } @Test fun dummyTest() { val message = "Hello, World!" print(message) assertEquals(message, outStream.toString(), "Output should match the message") } @ParameterizedTest @ValueSource(strings = [ "a", "hello", "a very special christmas", "1 2 3 piano" ]) fun `write atoms`(name: String) { val write = Write(Atom(name)) val result = write.satisfy(emptyMap()).toList() assertEquals(1, result.size, "Should return one result") assertTrue(result[0].isSuccess, "Result should be successful") assertEquals(name, outStream.toString(), "Output should match the atom") } @Test fun `write structure`() { val write = Write(CompoundTerm(Atom("person"), listOf(Atom("john"), Atom("doe")))) val result = write.satisfy(emptyMap()).toList() assertEquals(1, result.size, "Should return one result") assertTrue(result[0].isSuccess, "Result should be successful") assertEquals("person(john, doe)", outStream.toString().trim(), "Output should match the structure") } @Test fun `write arithmetic`() { val a = Integer(1) val b = Variable("B") val c = Float(2.0f) val d = Variable("D") val mul = Multiply(c, d) val sub = Subtract(b, mul) val expr = EvaluatesTo(a, sub) val expected1 = "1 =:= B - (2.0 * D)" val expected2 = "=:=(1, -(B, *(2.0, D)))" val write = Write(expr) val result = write.satisfy(emptyMap()).toList() assertEquals(1, result.size, "Should return one result") assertTrue(result[0].isSuccess, "Result should be successful") val output = outStream.toString() assertTrue(output == expected1 || output == expected2, "Output should match the arithmetic expression") } @Test fun `write nl`() { val nl = Nl val result = nl.satisfy(emptyMap()).toList() assertEquals(1, result.size, "Should return one result") assertTrue(result[0].isSuccess, "Result should be successful") assertTrue(outStream.toString().contains("\n"), "Output should contain a newline") } @Test fun `read term`() { val inputStream = ByteArrayInputStream("hello.".toByteArray()) System.setIn(inputStream) val read = Read(Variable("X")) val result = read.satisfy(emptyMap()).toList() assertEquals(1, result.size, "Should return one result") assertTrue(result[0].isSuccess, "Result should be successful") val answer = result[0].getOrNull()!! assertTrue(answer.containsKey(Variable("X")), "Result should be successful") assertInstanceOf(Atom::class.java, answer[Variable("X")], "Output should be an atom") assertEquals(Atom("hello"), answer[Variable("X")], "Output should match the read term") } @Test fun `read between(1, 2, 3)`() { val inputStream = ByteArrayInputStream("between(1, 2, 3).".toByteArray()) System.setIn(inputStream) val read = Read(Variable("X")) val result = read.satisfy(emptyMap()).toList() assertEquals(1, result.size, "Should return one result") assertTrue(result[0].isSuccess, "Result should be successful") val answer = result[0].getOrNull()!! assertTrue(answer.containsKey(Variable("X")), "Result should be successful") assertInstanceOf(CompoundTerm::class.java, answer[Variable("X")], "Output should be a compound term") assertEquals( CompoundTerm(Atom("between"), listOf(Integer(1), Integer(2), Integer(3))), answer[Variable("X")], "Output should match the read term" ) } @Test fun `read foo(a, X, b, Y, c, Z)`() { val inputStream = ByteArrayInputStream("foo(A, x, B, y, C, z).".toByteArray()) System.setIn(inputStream) val read = Read(CompoundTerm(Atom("foo"), listOf( Atom("a"), Variable("X"), Atom("b"), Variable("Y"), Atom("c"), Variable("Z") ))) val result = read.satisfy(emptyMap()).toList() assertEquals(1, result.size, "Should return one result") assertTrue(result[0].isSuccess, "Result should be successful") val answer = result[0].getOrNull()!! assertTrue(answer.containsKey(Variable("X")), "Result should be successful") assertTrue(answer.containsKey(Variable("Y")), "Result should be successful") assertTrue(answer.containsKey(Variable("Z")), "Result should be successful") assertEquals(Atom("x"), answer[Variable("X")], "Output should match the read term") assertEquals(Atom("y"), answer[Variable("Y")], "Output should match the read term") assertEquals(Atom("z"), answer[Variable("Z")], "Output should match the read term") } }