// Copyright 2009 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.

package rpc

import (
	"http";
	"log";
	"net";
	"once";
	"os";
	"strings";
	"testing";
)

var serverAddr string
var httpServerAddr string

const second = 1e9


type Args struct {
	A, B int;
}

type Reply struct {
	C int;
}

type Arith int

func (t *Arith) Add(args *Args, reply *Reply) os.Error {
	reply.C = args.A + args.B;
	return nil;
}

func (t *Arith) Mul(args *Args, reply *Reply) os.Error {
	reply.C = args.A * args.B;
	return nil;
}

func (t *Arith) Div(args *Args, reply *Reply) os.Error {
	if args.B == 0 {
		return os.ErrorString("divide by zero")
	}
	reply.C = args.A / args.B;
	return nil;
}

func (t *Arith) Error(args *Args, reply *Reply) os.Error {
	panicln("ERROR")
}

func startServer() {
	Register(new(Arith));

	l, e := net.Listen("tcp", ":0");	// any available address
	if e != nil {
		log.Exitf("net.Listen tcp :0: %v", e)
	}
	serverAddr = l.Addr().String();
	log.Stderr("Test RPC server listening on ", serverAddr);
	go Accept(l);

	HandleHTTP();
	l, e = net.Listen("tcp", ":0");	// any available address
	if e != nil {
		log.Stderrf("net.Listen tcp :0: %v", e);
		os.Exit(1);
	}
	httpServerAddr = l.Addr().String();
	log.Stderr("Test HTTP RPC server listening on ", httpServerAddr);
	go http.Serve(l, nil);
}

func TestRPC(t *testing.T) {
	once.Do(startServer);

	client, err := Dial("tcp", serverAddr);
	if err != nil {
		t.Fatal("dialing", err)
	}

	// Synchronous calls
	args := &Args{7, 8};
	reply := new(Reply);
	err = client.Call("Arith.Add", args, reply);
	if reply.C != args.A+args.B {
		t.Errorf("Add: expected %d got %d", reply.C, args.A+args.B)
	}

	args = &Args{7, 8};
	reply = new(Reply);
	err = client.Call("Arith.Mul", args, reply);
	if reply.C != args.A*args.B {
		t.Errorf("Mul: expected %d got %d", reply.C, args.A*args.B)
	}

	// Out of order.
	args = &Args{7, 8};
	mulReply := new(Reply);
	mulCall := client.Go("Arith.Mul", args, mulReply, nil);
	addReply := new(Reply);
	addCall := client.Go("Arith.Add", args, addReply, nil);

	<-addCall.Done;
	if addReply.C != args.A+args.B {
		t.Errorf("Add: expected %d got %d", addReply.C, args.A+args.B)
	}

	<-mulCall.Done;
	if mulReply.C != args.A*args.B {
		t.Errorf("Mul: expected %d got %d", mulReply.C, args.A*args.B)
	}

	// Error test
	args = &Args{7, 0};
	reply = new(Reply);
	err = client.Call("Arith.Div", args, reply);
	// expect an error: zero divide
	if err == nil {
		t.Error("Div: expected error")
	} else if err.String() != "divide by zero" {
		t.Error("Div: expected divide by zero error; got", err)
	}
}

func TestHTTPRPC(t *testing.T) {
	once.Do(startServer);

	client, err := DialHTTP("tcp", httpServerAddr);
	if err != nil {
		t.Fatal("dialing", err)
	}

	// Synchronous calls
	args := &Args{7, 8};
	reply := new(Reply);
	err = client.Call("Arith.Add", args, reply);
	if reply.C != args.A+args.B {
		t.Errorf("Add: expected %d got %d", reply.C, args.A+args.B)
	}
}

func TestCheckUnknownService(t *testing.T) {
	once.Do(startServer);

	conn, err := net.Dial("tcp", "", serverAddr);
	if err != nil {
		t.Fatal("dialing:", err)
	}

	client := NewClient(conn);

	args := &Args{7, 8};
	reply := new(Reply);
	err = client.Call("Unknown.Add", args, reply);
	if err == nil {
		t.Error("expected error calling unknown service")
	} else if strings.Index(err.String(), "service") < 0 {
		t.Error("expected error about service; got", err)
	}
}

func TestCheckUnknownMethod(t *testing.T) {
	once.Do(startServer);

	conn, err := net.Dial("tcp", "", serverAddr);
	if err != nil {
		t.Fatal("dialing:", err)
	}

	client := NewClient(conn);

	args := &Args{7, 8};
	reply := new(Reply);
	err = client.Call("Arith.Unknown", args, reply);
	if err == nil {
		t.Error("expected error calling unknown service")
	} else if strings.Index(err.String(), "method") < 0 {
		t.Error("expected error about method; got", err)
	}
}

func TestCheckBadType(t *testing.T) {
	once.Do(startServer);

	conn, err := net.Dial("tcp", "", serverAddr);
	if err != nil {
		t.Fatal("dialing:", err)
	}

	client := NewClient(conn);

	reply := new(Reply);
	err = client.Call("Arith.Add", reply, reply);	// args, reply would be the correct thing to use
	if err == nil {
		t.Error("expected error calling Arith.Add with wrong arg type")
	} else if strings.Index(err.String(), "type") < 0 {
		t.Error("expected error about type; got", err)
	}
}
