package prolog.builtins import org.junit.jupiter.api.Assertions.* import org.junit.jupiter.api.BeforeEach 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.arithmetic.Integer import prolog.ast.terms.Atom import prolog.ast.terms.CompoundTerm import prolog.ast.terms.Variable import java.io.ByteArrayInputStream import java.io.ByteArrayOutputStream import java.io.PrintStream 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") } }