/* Functional Programming in Scala (Red Book)
   Chapter 3, Functional Data Structures
   Partial test script for List2.scala
   H. Conrad Cunningham

1234567890123456789012345678901234567890123456789012345678901234567890

2019-02-17: Created some tests for List2.scala
2019-04-06: Added tests for head, tail, headList, tailList

 */

// import scala.{List => _, _} // hide standard?
import List._

object TestList2 {

  def pass(t: Boolean): String = t match {
    case true  => "SUCCESS"
    case false => "FAILURE"
  }

  def main(args: Array[String]) {

    val nil = Nil
g    val l11 = Cons(1,Nil)
    val l21 = Cons(1,Cons(1,Nil))
    val l2x = List(2,1)
    val l2y = List(1,2)
    val l3x = List(3,2,1)
    val l3y = List(1,3,2)
    val l3z = List(1,2,3)
    val l4a = List(3,2,3,1)
    val l4b = List(3,3,3,1)
    val l4c = List(2,3,3,2)

    println("\nTesting head and tail")
    println(s"l11.head:      ${pass(l11.head == 1)}")
    println(s"l11.tail:      ${pass(l11.tail == Nil)}")
    println(s"headList(l11): ${pass(headList(l11) == 1)}")
    println(s"tailList(l11): ${pass(tailList(l11) == Nil)}")
    try { 
      print("headList(nil): "); println(s"${headList(nil)}") }
    catch { case ex: RuntimeException => println(s"Caught: ${ex}") }
    try { 
      print("tailList(nil): "); println(s"${tailList(nil)}") }
    catch { case ex: RuntimeException => println(s"Caught: ${ex}") }

    println("\nTesting sum")
    println(s"sum(nil):      ${pass(sum(nil) == 0)}")
    println(s"sum(l11):      ${pass(sum(l11) == 1)}")
    println(s"sum(l21):      ${pass(sum(l21) == 2)}")
    println(s"sum(l2x):      ${pass(sum(l2x) == 3)}")
    println(s"sum(l2y):      ${pass(sum(l2y) == 3)}")
    println(s"sum(l3x):      ${pass(sum(l3x) == 6)}")
    println(s"sum(l3y):      ${pass(sum(l3y) == 6)}")
    println(s"sum(l3z):      ${pass(sum(l3z) == 6)}")
    println(s"sum(l4a):      ${pass(sum(l4a) == 9)}")
    println(s"sum(l4b):      ${pass(sum(l4b) == 10)}")
    println(s"sum(l4c):      ${pass(sum(l4c) == 10)}")

    val dnl: List[Double] = Nil
    val d11: List[Double] = List(1)
    val d21: List[Double] = List(1,1)
    val d2x: List[Double] = List(2,1)
    val d2y: List[Double] = List(1,2)
    val d3x: List[Double] = List(3,2,1)
    val d3y: List[Double] = List(1,3,2)
    val d3z: List[Double] = List(1,2,3)
    val d4a: List[Double] = List(3,2,3,1)
    val d4b: List[Double] = List(3,3,3,1)
    val d4c: List[Double] = List(2,3,3,2)

    println("\nTesting product")
    println(s"product(dnl):  ${pass(product(dnl) == 1)}")
    println(s"product(d11):  ${pass(product(d11) == 1)}")
    println(s"product(d21):  ${pass(product(d21) == 1)}")
    println(s"product(d2x):  ${pass(product(d2x) == 2)}")
    println(s"product(d2y):  ${pass(product(d2y) == 2)}")
    println(s"product(d3x):  ${pass(product(d3x) == 6)}")
    println(s"product(d3y):  ${pass(product(d3y) == 6)}")
    println(s"product(d3z):  ${pass(product(d3z) == 6)}")
    println(s"product(d4a):  ${pass(product(d4a) == 18)}")
    println(s"product(d4b):  ${pass(product(d4b) == 27)}")
    println(s"product(d4b):  ${pass(product(d4b) == 27)}")
    println(s"product(d4c):  ${pass(product(d4c) == 36)}")

    println("\nTesting remdups")
    println(s"remdups(nil):  ${pass(remdups(nil) == nil)}")
    println(s"remdups(l11):  ${pass(remdups(l11) == l11)}")
    println(s"remdups(l21):  ${pass(remdups(l21) == l11)}")
    println(s"remdups(l2x):  ${pass(remdups(l2x) == l2x)}")
    println(s"remdups(l2y):  ${pass(remdups(l2y) == l2y)}")
    println(s"remdups(l3x):  ${pass(remdups(l3x) == l3x)}")
    println(s"remdups(l3y):  ${pass(remdups(l3y) == l3y)}")
    println(s"remdups(l3z):  ${pass(remdups(l3z) == l3z)}")
    println(s"remdups(l4a):  ${pass(remdups(l4a) == l4a)}")
    println(s"remdups(l4b):  ${pass(remdups(l4b)==List(3,1))}")
    println(s"remdups(l4b):  ${pass(remdups(l4b)==List(3,1))}")
    println(
      s"remdups(l4c):  ${pass(remdups(l4c)==List(2,3,2))}")

    // test other functions similarly
  }

}
