#!/usr/bin/env python
# pa4_test_py2.py (Python 2 version)
# Glenn G. Chappell
# 15 Apr 2009
#
# For CS 331 Spring 2009
# Test program for da4.py
# Used in Assignment 4

import pa4
 
class Tester:
    """ Simple unit testing class.
    Set t = Tester()
    Then call t.test(TRUE_IF_SUCCESSFUL, "TEST_NAME")
    for each test.
    """

    def __init__(self):
        self.reset()

    def reset(self):
        self.countTests = 0
        self.countPasses = 0

    def allPassed(self):
        return self.countTests == self.countPasses
        
    def test(self, success, testName=None):
        self.countTests += 1;
        if success:
            self.countPasses += 1;
        print "    ",
        if testName is not None:
            print "Test:", testName, "- ",
        if success:
            print("passed")
        else:
            print("********** FAILED **********")


def test_class_vec3(t):
    def diff(x):
        (a,b) = x
        return a-b

    def mult(x):
        (a,b) = x
        return a*b

    print("Test Suite: class vec3")

    vals1 = [3.2, 2, -21.7]
    vals2 = [4.5, -8, 2]
    vals1p2 = list(map(sum, zip(vals1, vals2)))
    vals1m2 = list(map(diff, zip(vals1, vals2)))
    vals3x2 = [3*a for a in vals2]
    dotp = sum(map(mult, zip(vals1, vals2)))

    # Ctor, str
    v1 = pa4.vec3(*vals1)
    t.test(str(v1)==str(vals1), "vec3 - ctor, str")

    # binary op+
    v2 = pa4.vec3(*vals2)
    t.test(str(v1+v2)==str(vals1p2), "vec3 - binary op+, value")
    t.test(str(v1)==str(vals1), "vec3 - binary op+, 1st operand unchanged")
    t.test(str(v2)==str(vals2), "vec3 - binary op+, 2nd operand unchanged")

    # op+=
    v1 += v2
    t.test(str(v1)==str(vals1p2), "vec3 - op+=")
    t.test(str(v2)==str(vals2), "vec3 - op+=, 2nd operand unchanged")

    # binary op-
    v1 = pa4.vec3(*vals1)
    t.test(str(v1-v2)==str(vals1m2), "vec3 - binary op-, value")
    t.test(str(v1)==str(vals1), "vec3 - binary op-, 1st operand unchanged")
    t.test(str(v2)==str(vals2), "vec3 - binary op-, 2nd operand unchanged")

    # op-=
    v1 -= v2
    t.test(str(v1)==str(vals1m2), "vec3 - op-=")
    t.test(str(v2)==str(vals2), "vec3 - op-=, 2nd operand unchanged")

    # scalar mult
    t.test(str(3*v2)==str(vals3x2), "vec3 - scalar mult, value")
    t.test(str(v2)==str(vals2), "vec3 - scalar mult, 2nd operand unchanged")

    # dot
    v1 = pa4.vec3(*vals1)
    t.test(pa4.dot(v1,v2)==dotp, "vec3 - function dot, value")
    t.test(str(v1)==str(vals1), "vec3 - function dot, 1st argument unchanged")
    t.test(str(v2)==str(vals2), "vec3 - function dot, 2nd argument unchanged")
    

def test_prime3(t):
    def prime3_range(a,b):
        it = pa4.prime3().__iter__()
        for i in range(b):
            value = it.next()
            if i >= a:
                yield value

    print("Test Suite: function prime3")

    # First 100 values
    p3vals100 = list(prime3_range(0,100))
    vals100 = [3, 13, 23, 43, 53, 73, 83, 103, 113, 163, 173, 193,
        223, 233, 263, 283, 293, 313, 353, 373, 383, 433, 443,
        463, 503, 523, 563, 593, 613, 643, 653, 673, 683, 733,
        743, 773, 823, 853, 863, 883, 953, 983, 1013, 1033, 1063,
        1093, 1103, 1123, 1153, 1163, 1193, 1213, 1223, 1283,
        1303, 1373, 1423, 1433, 1453, 1483, 1493, 1523, 1543,
        1553, 1583, 1613, 1663, 1693, 1723, 1733, 1753, 1783,
        1823, 1873, 1913, 1933, 1973, 1993, 2003, 2053, 2063,
        2083, 2113, 2143, 2153, 2203, 2213, 2243, 2273, 2293,
        2333, 2383, 2393, 2423, 2473, 2503, 2543, 2593, 2633,
        2663]
    t.test(p3vals100==vals100, "prime3 - first values")

    # 300th value
    p3val300 = list(prime3_range(299,300))
    val300 = [9533]
    t.test(p3val300==val300, "prime3 - high value")


def test_foo_maybe(t):
    class bar1:
        def foo(self):
            return 3

    class bar2:
        def foo(self):
            return 5

    class bar3:
        pass

    print("Test Suite: function foo_maybe")
    t.test(pa4.foo_maybe(bar1())==3, "foo_maybe - has foo test #1")
    t.test(pa4.foo_maybe(bar2())==5, "foo_maybe - has foo test #2")
    t.test(pa4.foo_maybe(bar3()) is None, "foo_maybe - does not have foo")


def test_get_331_char(t):
    def getit(n):
        try:
            c = pa4.get_331_char(n)
            return c
        except:
            return None

    print("Test Suite: function get_331_char")
    print
    print("    ############################################")
    print("    ##                                        ##")
    print("    ##  NOTE:  THE FOLLOWING TESTS WILL FAIL  ##")
    print("    ##  IF A NET CONNECTION IS NOT AVAILABLE  ##")
    print("    ##                                        ##")
    print("    ############################################")
    print
    t.test(getit(0)=="<", "get_331_char - read char 0")
    t.test(getit(10)=="H", "get_331_char - read char 10")
    t.test(getit(20)=="C", "get_331_char - read char 20")


def test_pa4(t):
    print("TEST SUITES FOR CS 331 ASSIGNMENT 4")
    test_class_vec3(t)
    test_prime3(t)
    test_foo_maybe(t)
    test_get_331_char(t)


if __name__ == "__main__":
    t = Tester()
    test_pa4(t)
    print
    if t.allPassed():
        print("All tests successful")
    else:
        print("Tests ********** UNSUCCESSFUL **********")
    print

