Plan 9 from Bell Labs’s /usr/web/sources/contrib/ericvh/go-plan9/src/pkg/rpc/server_test.go

Copyright © 2021 Plan 9 Foundation.
Distributed under the MIT License.
Download the Plan 9 distribution.


// 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 err != nil {
		t.Errorf("Add: expected no error but got string %q", err.String())
	}
	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 err != nil {
		t.Errorf("Mul: expected no error but got string %q", err.String())
	}
	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 = <-addCall.Done;
	if addCall.Error != nil {
		t.Errorf("Add: expected no error but got string %q", addCall.Error.String())
	}
	if addReply.C != args.A+args.B {
		t.Errorf("Add: expected %d got %d", addReply.C, args.A+args.B)
	}

	mulCall = <-mulCall.Done;
	if mulCall.Error != nil {
		t.Errorf("Mul: expected no error but got string %q", mulCall.Error.String())
	}
	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 err != nil {
		t.Errorf("Add: expected no error but got string %q", err.String())
	}
	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)
	}
}

type Bad int
type local struct{}

func (t *Bad) ArgNotPointer(args Args, reply *Reply) os.Error {
	return nil
}

func (t *Bad) ArgNotPointerToStruct(args *int, reply *Reply) os.Error {
	return nil
}

func (t *Bad) ReplyNotPointer(args *Args, reply Reply) os.Error {
	return nil
}

func (t *Bad) ReplyNotPointerToStruct(args *Args, reply *int) os.Error {
	return nil
}

func (t *Bad) ArgNotPublic(args *local, reply *Reply) os.Error {
	return nil
}

func (t *Bad) ReplyNotPublic(args *Args, reply *local) os.Error {
	return nil
}

// Check that registration handles lots of bad methods and a type with no suitable methods.
func TestRegistrationError(t *testing.T) {
	err := Register(new(Bad));
	if err == nil {
		t.Errorf("expected error registering bad type")
	}
}

Bell Labs OSI certified Powered by Plan 9

(Return to Plan 9 Home Page)

Copyright © 2021 Plan 9 Foundation. All Rights Reserved.
Comments to webmaster@9p.io.