#! /usr/bin/env python

import types, string
import unittest
from pyprolog import swipl

lines = """ line 1
 line2"""

class test_PTerm(unittest.TestCase):
    
    def setUp(self):
        self.t0 = swipl.new_term()
        
        self.t1 = swipl.new_term()
        self.a1 = swipl.new_atom('a1')
        self.t1.put_atom(self.a1)
        
        self.t2 = swipl.new_term()
        self.t2.put_integer(43)
        
        self.t3 = swipl.new_term()
        self.t3.put_variable()
        
        self.t4 = swipl.new_term()
        self.t4.put_string(lines)
        
        self.t5 = swipl.new_term()
        self.f = swipl.new_functor(swipl.new_atom('f'), 3)
        self.t5.put_functor(self.f)
        
        self.t6 = swipl.new_term()
        self.t7 = swipl.new_term()
        self.t7.put_atom(swipl.new_atom('term=t7'))
        self.t6.put_term(self.t7)
        
        self.t8 = swipl.new_term()
        self.t8.put_float(-3.14)
        
        self.t9 = swipl.chars_to_term('[]')
        self.t10 = swipl.chars_to_term('[X]')
        self.t11 = swipl.chars_to_term('[x,y,z]')
        
        self.t12 = swipl.new_term()
        self.t12.put_nil()
        
        m = swipl.new_term()
        m.put_nil()
        for i in range(10):
            j = swipl.new_term()
            j.put_integer(i)
            m.cons_list(j, m)
        self.t13 = m
        
        return
    
    def test_term_type(self): 
        msg = 'term_type() is wrong.'
        assert self.t0.term_type() == swipl.PL_VARIABLE, msg
        assert self.t1.term_type() == swipl.PL_ATOM, msg
        assert self.t2.term_type() == swipl.PL_INTEGER, msg
        assert self.t3.term_type() == swipl.PL_VARIABLE, msg
        assert self.t4.term_type() == swipl.PL_STRING, msg
        assert self.t5.term_type() == swipl.PL_TERM, msg
        assert self.t6.term_type() == swipl.PL_ATOM, msg
        assert self.t7.term_type() == swipl.PL_ATOM, msg
        assert self.t8.term_type() == swipl.PL_FLOAT, msg
        assert self.t9.term_type() == swipl.PL_ATOM, msg
        assert self.t10.term_type() == swipl.PL_TERM, msg
        assert self.t11.term_type() == swipl.PL_TERM, msg
        
    def test_is_atom(self): 
        msg = 'is_atom() is wrong.'
        assert not self.t0.is_atom(), msg
        assert self.t1.is_atom(), msg
        assert not self.t2.is_atom(), msg
        assert not self.t3.is_atom(), msg
        assert not self.t4.is_atom(), msg
        assert not self.t5.is_atom(), msg
        assert self.t6.is_atom(), msg
        assert self.t7.is_atom(), msg
        assert not self.t8.is_atom(), msg
        assert self.t9.is_atom(), msg
        assert not self.t10.is_atom(), msg
        assert not self.t11.is_atom(), msg
    
    def test_is_integer(self): 
        msg = 'is_integer() is wrong.'
        assert not self.t0.is_integer(), msg
        assert not self.t1.is_integer(), msg
        assert self.t2.is_integer(), msg
        assert not self.t3.is_integer(), msg
        assert not self.t4.is_integer(), msg
        assert not self.t5.is_integer(), msg
        assert not self.t6.is_integer(), msg
        assert not self.t7.is_integer(), msg
        assert not self.t8.is_integer(), msg
        assert not self.t9.is_integer(), msg
        assert not self.t10.is_integer(), msg
        assert not self.t11.is_integer(), msg
    
    def test_is_float(self): 
        msg = 'is_float() is wrong.'
        assert not self.t0.is_float(), msg
        assert not self.t1.is_float(), msg
        assert not self.t2.is_float(), msg
        assert not self.t3.is_float(), msg
        assert not self.t4.is_float(), msg
        assert not self.t5.is_float(), msg
        assert not self.t6.is_float(), msg
        assert not self.t7.is_float(), msg
        assert self.t8.is_float(), msg
        assert not self.t9.is_float(), msg
        assert not self.t10.is_float(), msg
        assert not self.t11.is_float(), msg
    
    def test_is_variable(self): 
        msg = 'is_variable() is wrong.'
        assert self.t0.is_variable(), msg # error ?
        assert not self.t1.is_variable(), msg
        assert not self.t2.is_variable(), msg
        assert self.t3.is_variable(), msg
        assert not self.t4.is_variable(), msg
        assert not self.t5.is_variable(), msg
        assert not self.t6.is_variable(), msg
        assert not self.t7.is_variable(), msg
        assert not self.t8.is_variable(), msg
        assert not self.t9.is_variable(), msg
        assert not self.t10.is_variable(), msg
        assert not self.t11.is_variable(), msg
    
    def test_is_string(self): 
        msg = 'is_string() is wrong.'
        assert not self.t0.is_string(), msg
        assert not self.t1.is_string(), msg
        assert not self.t2.is_string(), msg
        assert not self.t3.is_string(), msg
        assert self.t4.is_string(), msg
        assert not self.t5.is_string(), msg
        assert not self.t6.is_string(), msg
        assert not self.t7.is_string(), msg
        assert not self.t8.is_string(), msg
        assert not self.t9.is_string(), msg
        assert not self.t10.is_string(), msg
        assert not self.t11.is_string(), msg
    
    def test_is_functor(self): 
        msg = 'is_functor() is wrong.'
        assert not self.t0.is_functor(self.f), msg
        assert not self.t1.is_functor(self.f), msg
        assert not self.t2.is_functor(self.f), msg
        assert not self.t3.is_functor(self.f), msg
        assert not self.t4.is_functor(self.f), msg
        assert self.t5.is_functor(self.f), msg
        assert not self.t6.is_functor(self.f), msg
        assert not self.t7.is_functor(self.f), msg
        assert not self.t8.is_functor(self.f), msg
        f = swipl.new_functor(swipl.new_atom('.'), 2)
        assert not self.t9.is_functor(f), msg
        assert self.t10.is_functor(f), msg
        assert self.t11.is_functor(f), msg
    
    def test_is_number(self): 
        msg = 'is_number() is wrong.'
        assert not self.t0.is_number(), msg
        assert not self.t1.is_number(), msg
        assert self.t2.is_number(), msg
        assert not self.t3.is_number(), msg
        assert not self.t4.is_number(), msg
        assert not self.t5.is_number(), msg
        assert not self.t6.is_number(), msg
        assert not self.t7.is_number(), msg
        assert self.t8.is_number(), msg
        assert not self.t9.is_number(), msg
        assert not self.t10.is_number(), msg
        assert not self.t11.is_number(), msg
    
    def test_is_atomic(self): 
        msg = 'is_atomic() is wrong.'
        assert not self.t0.is_atomic(), msg
        assert self.t1.is_atomic(), msg
        assert self.t2.is_atomic(), msg
        assert not self.t3.is_atomic(), msg
        assert self.t4.is_atomic(), msg
        assert not self.t5.is_atomic(), msg
        assert self.t6.is_atomic(), msg
        assert self.t7.is_atomic(), msg
        assert self.t8.is_atomic(), msg
        assert self.t9.is_atomic(), msg
        assert not self.t10.is_atomic(), msg
        assert not self.t11.is_atomic(), msg
    
    def test_is_compound(self): 
        msg = 'is_compound() is wrong.'
        assert not self.t0.is_compound(), msg
        assert not self.t1.is_compound(), msg
        assert not self.t2.is_compound(), msg
        assert not self.t3.is_compound(), msg
        assert not self.t4.is_compound(), msg
        assert self.t5.is_compound(), msg
        assert not self.t6.is_compound(), msg
        assert not self.t7.is_compound(), msg
        assert not self.t8.is_compound(), msg
        assert not self.t9.is_compound(), msg
        assert self.t10.is_compound(), msg
        assert self.t11.is_compound(), msg
    
    def test_is_list(self): # TBD
        msg = 'is_list() is wrong.'
        assert not self.t0.is_list(), msg
        assert not self.t1.is_list(), msg
        assert not self.t2.is_list(), msg
        assert not self.t3.is_list(), msg
        assert not self.t4.is_list(), msg
        assert not self.t5.is_list(), msg
        assert not self.t6.is_list(), msg
        assert not self.t7.is_list(), msg
        assert not self.t8.is_list(), msg
        assert self.t9.is_list(), msg
        assert self.t10.is_list(), msg
        assert self.t11.is_list(), msg
        assert self.t12.is_list(), msg
        assert repr(self.t13) == '[9, 8, 7, 6, 5, 4, 3, 2, 1, 0]'
        

    def test_get_atom(self):
        msg = 'get_atom() is wrong.'
        a = self.t1.get_atom()
        na = swipl.new_atom('a1')
        assert a.handle == na.handle == self.a1.handle
        assert self.t6.get_atom().handle == self.t7.get_atom().handle
    
    def test_get_chars(self):
        msg = 'get_chars() is wrong.'
        assert self.t0.get_chars()[0] == '_', msg
        assert self.t1.get_chars() == 'a1', msg
        assert self.t2.get_chars() == '43', msg
        assert self.t3.get_chars()[0] == '_', msg
        assert self.t4.get_chars() == lines, msg
        #assert self.t5.get_chars(swipl.CVT_WRITE | swipl.BUF_RING) == 'f', msg
        assert self.t6.get_chars() == 'term=t7', msg
        assert self.t7.get_chars() == 'term=t7', msg
        assert self.t8.get_chars() == '-3.14', msg
        # TBD: more compounds.
    
    def test_get_integer(self):
        msg = 'get_integer() is wrong.'
        assert self.t2.get_integer() == 43
    
    def test_get_long(self):
        msg = 'get_long() is wrong.'
        assert self.t2.get_long() == 43
    
    def test_get_float(self):
        msg = 'get_float() is wrong.'
        assert self.t8.get_float() == -3.14
    
    def test_get_functor(self):
        msg = 'get_functor() is wrong.'
        assert self.t5.get_functor().handle == self.f.handle, msg
    
    def test_get_name_arity(self):
        msg = 'get_name_arity() is wrong.'
        (name, arity) = self.t5.get_name_arity()
        assert name.handle == swipl.new_atom('f').handle, msg
        assert arity == 3, msg
    
    def test_get_nil(self):
        msg = 'get_nil() is wrong.'
        assert self.t9.get_nil() # [].get_nil()
        assert not self.t10.get_nil() # [X].get_nil()
        assert not self.t11.get_nil() # [x, y, z].get_nil()
    
    def test_get_head(self):
        msg = 'get_head() is wrong.'
        try:
            r = self.t9.get_head()
        except swipl.error, reason:
            pass
        else:
            raise AssertionError
        h = self.t10.get_head()
        assert h.is_variable()

        h = self.t11.get_head()
        assert repr(h) == 'x'
    
    def test_get_tail(self):
        msg = 'get_tail() is wrong.'
        try:
            r = self.t9.get_tail()
        except swipl.error, reason:
            pass
        else:
            raise AssertionError
        t = self.t10.get_tail()
        assert t.get_nil()
        t = self.t11.get_tail()
        assert repr(t) == '[y, z]'
    
    def test_get_list(self):
        msg = 'get_list() is wrong.'
        try:
            r = self.t9.get_list()
        except swipl.error, reason:
            pass
        else:
            raise AssertionError
        h,t = self.t10.get_list()
        assert h.is_variable()
        assert t.get_nil()
        h,t = self.t11.get_list()
        assert repr(h) == 'x'
        assert repr(t) == '[y, z]'
        
        
def make_pterm_suite():
    suite = unittest.TestSuite()
    suite.addTest(test_PTerm('test_term_type'))
    suite.addTest(test_PTerm('test_is_atom'))
    suite.addTest(test_PTerm('test_is_integer'))
    suite.addTest(test_PTerm('test_is_float'))
    suite.addTest(test_PTerm('test_is_variable'))
    suite.addTest(test_PTerm('test_is_string'))
    suite.addTest(test_PTerm('test_is_functor'))
    suite.addTest(test_PTerm('test_is_number'))
    suite.addTest(test_PTerm('test_is_atomic'))
    suite.addTest(test_PTerm('test_is_compound'))
    suite.addTest(test_PTerm('test_is_list'))
    suite.addTest(test_PTerm('test_get_atom'))
    suite.addTest(test_PTerm('test_get_chars'))
    suite.addTest(test_PTerm('test_get_integer'))
    suite.addTest(test_PTerm('test_get_long'))
    suite.addTest(test_PTerm('test_get_float'))
    suite.addTest(test_PTerm('test_get_functor'))
    suite.addTest(test_PTerm('test_get_name_arity'))
    suite.addTest(test_PTerm('test_get_nil'))
    suite.addTest(test_PTerm('test_get_head'))
    suite.addTest(test_PTerm('test_get_tail'))
    suite.addTest(test_PTerm('test_get_list'))
    return suite


class test_char_terms(unittest.TestCase):
    
    def setUp(self):
        self.t0 = swipl.chars_to_term('an_atom')
        self.t1 = swipl.chars_to_term('X')
        self.t2 = swipl.chars_to_term('_x')
        self.t3 = swipl.chars_to_term('f(1)')
        self.t4 = swipl.chars_to_term('f1(2,x,Y,"a string")')
        self.t5 = swipl.chars_to_term('f2(f3(a,X), X, b)')
        self.t6 = swipl.chars_to_term('X=f(1, a)')
        self.t7 = swipl.chars_to_term('X=f(1, Y)')
        self.t8 = swipl.chars_to_term('X=[a,b,c], member(b, X).')
        self.t9 = swipl.chars_to_term('X=[a,b,c], member(B, X).')
        self.a1 = swipl.new_term()
        self.a1.put_integer(1)
    
    def test_get_arg(self):
        term = swipl.new_term()
        term.put_integer(1)
        assert self.t3.get_arg(1) == term
        
        term.put_integer(2)
        assert self.t4.get_arg(1) == term
        
        term.put_atom(swipl.new_atom('x'))
        assert self.t4.get_arg(2) == term
        
        assert self.t4.get_arg(3).is_variable()
        
        assert repr(self.t4.get_arg(4)) == "[97, 32, 115, 116, 114, 105, 110, 103]"
    
    def test_chars_to_term(self):
        assert repr(self.t0) == 'an_atom'
        assert repr(self.t1)[0] == '_'
        assert repr(self.t2)[0] == '_'
        assert repr(self.t3) == 'f(1)'
        assert repr(self.t4)[:10] == 'f1(2, x, _'
        assert repr(self.t5)[:10] == 'f2(f3(a, _'
        
        s = repr(self.t6)
        assert s[:2] == '_G'
        assert string.split(s, '=')[1] == 'f(1, a)'
        
        s = repr(self.t7)
        assert s[:2] == '_G'
        assert string.split(s, '=')[1][:7] == 'f(1, _G'
        
        s = repr(self.t8)
        assert s[:2] == '_G'
        assert string.split(s, '=')[1][:23] == '[a, b, c], member(b, _G'
    
    def test_unify_1(self):
        assert self.t1.is_variable()
        assert self.t0.unify(self.t1)
        assert repr(self.t1) == 'an_atom'
    
    def test_unify_2(self):
        assert self.t2.is_variable()
        assert self.t0.unify(self.t2)
        assert repr(self.t2) == 'an_atom'
    
    def test_unify_3(self):
        assert self.t1.is_variable()
        assert self.t2.is_variable()
        assert repr(self.t1) != repr(self.t2)
        
        assert self.t1.unify(self.t2) # X=_x
        
        assert self.t1.is_variable()
        assert self.t2.is_variable()
        assert repr(self.t1) == repr(self.t2)
        
        assert self.t2.unify(self.t0) # _x = an_atom
        
        assert repr(self.t0) == 'an_atom'
        assert repr(self.t1) == 'an_atom'
        assert repr(self.t2) == 'an_atom'
    
    def test_call(self):
        assert self.t9.call()
        assert repr(self.t9) == '[a, b, c]=[a, b, c], member(a, [a, b, c])'
        
        
def make_char_terms_suite():
    suite = unittest.TestSuite()
    suite.addTest(test_char_terms('test_chars_to_term'))
    suite.addTest(test_char_terms('test_unify_1'))
    suite.addTest(test_char_terms('test_unify_2'))
    suite.addTest(test_char_terms('test_unify_3'))
    suite.addTest(test_char_terms('test_call'))
    suite.addTest(test_char_terms('test_get_arg'))
    return suite


def make_suite():
    suite = unittest.TestSuite()
    suite.addTest(make_pterm_suite())
    suite.addTest(make_char_terms_suite())
    return suite

def main():
    runner = unittest.TextTestRunner()
    suite = make_suite()
    runner.run(suite)

if __name__ == '__main__':
    main()
    
"""
get_module
type
PTerm_compare
PTerm_repr
"""
   
# Local Variables:          
# mode:python               
# indent-tabs-mode: nil     
# py-indent-offset: 4  
# py-smart-indentation: nil 
# End:                      
