#!/usr/bin/env python

import unittest
from unittest import TestCase
import time
import sys
import os
sys.path += os.path.abspath(os.path.join(os.path.split(__file__)[0], "../pylib")),
import simplerpc
from benchmark_service import *
from test_service import *
from threading import Thread

class TestMarshal(TestCase):
    def test_marshal(self):
        m = simplerpc.Marshal()
        assert len(m) == 0
        m.write_v32(45)
        assert len(m) == 1
        assert m.read_v32() == 45
        assert len(m) == 0
        m.write_v64(45)
        assert len(m) == 1
        assert m.read_v64() == 45
        assert len(m) == 0
        m.write_i8(45)
        assert len(m) == 1
        assert m.read_i8() == 45
        assert len(m) == 0
        m.write_i16(45)
        assert len(m) == 2
        assert m.read_i16() == 45
        assert len(m) == 0
        m.write_i32(45)
        assert len(m) == 4
        assert m.read_i32() == 45
        assert len(m) == 0
        m.write_i32(-45)
        assert len(m) == 4
        assert m.read_i32() == -45
        assert len(m) == 0
        m.write_i64(1987)
        assert len(m) == 8
        assert m.read_i64() == 1987
        assert len(m) == 0
        m.write_i64(-1987)
        assert len(m) == 8
        assert m.read_i64() == -1987
        assert len(m) == 0
        m.write_double(-1.987)
        assert len(m) == 8
        assert m.read_double() == -1.987
        assert len(m) == 0
        m.write_str("hello world!")
        print len(m)
        print m.read_str()
        print len(m)
        p = point3(x=3.0, y=4.0, z=5.0)
        m.write_obj(p, "point3")
        print len(m)
        print m.read_obj("point3")
        print len(m)
        comp_s = set(["abc", "def"])
        comp_d = {}
        comp_d[("1", "2")] = []
        comp_d[("a", "b")] = [[("e", "f"), ("g", "hi")], []]
        comp = complex_struct(d=comp_d, s=comp_s, e=empty_struct())
        m.write_obj(comp, "complex_struct")
        print m.read_obj("complex_struct")

class TestUtils(TestCase):
    def test_marshal_wrap(self):
        from simplerpc.server import MarshalWrap

        def a_add_b(a, b):
            return a + b

        f = MarshalWrap(a_add_b, ["rpc::i32", "rpc::i32"], ["rpc::i32"])

        req_m = simplerpc.Marshal()
        req_m.write_i32(3)
        req_m.write_i32(4)

        rep_m_id = f(req_m.id)
        rep_m = simplerpc.Marshal(id=rep_m_id)

        assert len(rep_m) == 4
        assert rep_m.read_i32() == 7
        assert len(rep_m) == 0

        def a_swap_b(a, b):
            return b, a

        f = MarshalWrap(a_swap_b, ["rpc::i32", "rpc::i32"], ["rpc::i32", "rpc::i32"])

        req_m = simplerpc.Marshal()
        req_m.write_i32(3)
        req_m.write_i32(4)

        rep_m_id = f(req_m.id)
        rep_m = simplerpc.Marshal(id=rep_m_id)

        assert len(rep_m) == 8
        assert rep_m.read_i32() == 4
        assert rep_m.read_i32() == 3
        assert len(rep_m) == 0

        def hello_world():
            print "** hello world! **"

        f = MarshalWrap(hello_world, [], [])

        req_m = simplerpc.Marshal()
        assert f(req_m.id) == 0 # NULL rpc return

        def hello_greetings(greetings):
            print "** hello %s **" % greetings

        f = MarshalWrap(hello_greetings, ["std::string"], [])

        req_m = simplerpc.Marshal()
        req_m.write_str("simple-rpc")
        assert f(req_m.id) == 0 # NULL rpc return

class TestAsync(TestCase):
    def test_async_rpc(self):
        s = simplerpc.Server()
        class LazyMath(MathService):
            def gcd(self, a, b):
                print "server zzz..."
                time.sleep(1)
                print "server wake up"
                while True:
                    r = a % b
                    if r == 0: