2022-05-26 20:32:19 +00:00
|
|
|
package lrpc_test
|
|
|
|
|
|
|
|
import (
|
|
|
|
"context"
|
|
|
|
"encoding/gob"
|
|
|
|
"net"
|
|
|
|
"testing"
|
2022-05-28 21:52:00 +00:00
|
|
|
"time"
|
2022-05-26 20:32:19 +00:00
|
|
|
|
|
|
|
"go.arsenm.dev/lrpc/client"
|
|
|
|
"go.arsenm.dev/lrpc/codec"
|
|
|
|
"go.arsenm.dev/lrpc/server"
|
|
|
|
)
|
|
|
|
|
|
|
|
type Arith struct{}
|
|
|
|
|
|
|
|
func (Arith) Add(ctx *server.Context, in [2]int) int {
|
|
|
|
return in[0] + in[1]
|
|
|
|
}
|
|
|
|
|
|
|
|
func (Arith) Mul(ctx *server.Context, in [2]int) int {
|
|
|
|
return in[0] * in[1]
|
|
|
|
}
|
|
|
|
|
|
|
|
func (Arith) Div(ctx *server.Context, in [2]int) int {
|
|
|
|
return in[0] / in[1]
|
|
|
|
}
|
|
|
|
|
|
|
|
func (Arith) Sub(ctx *server.Context, in [2]int) int {
|
|
|
|
return in[0] - in[1]
|
|
|
|
}
|
|
|
|
|
|
|
|
func TestCalls(t *testing.T) {
|
|
|
|
ctx, cancel := context.WithCancel(context.Background())
|
|
|
|
defer cancel()
|
|
|
|
|
|
|
|
// Create new network pipe
|
|
|
|
sConn, cConn := net.Pipe()
|
|
|
|
|
|
|
|
s := server.New()
|
|
|
|
defer s.Close()
|
|
|
|
// Register Arith for RPC
|
|
|
|
s.Register(Arith{})
|
|
|
|
// Serve the pipe connection using default codec
|
|
|
|
go s.ServeConn(ctx, sConn, codec.Default)
|
|
|
|
|
|
|
|
// Create new client using default codec
|
|
|
|
c := client.New(cConn, codec.Default)
|
|
|
|
defer c.Close()
|
|
|
|
|
|
|
|
// Call Arith.Add()
|
|
|
|
var add int
|
|
|
|
err := c.Call(ctx, "Arith", "Add", [2]int{5, 5}, &add)
|
|
|
|
if err != nil {
|
|
|
|
t.Error(err)
|
|
|
|
}
|
|
|
|
|
|
|
|
// Call Arith.Sub()
|
|
|
|
var sub int
|
|
|
|
err = c.Call(ctx, "Arith", "Sub", [2]int{5, 5}, &sub)
|
|
|
|
if err != nil {
|
|
|
|
t.Error(err)
|
|
|
|
}
|
|
|
|
|
|
|
|
// Call Arith.Mul()
|
|
|
|
var mul int
|
|
|
|
err = c.Call(ctx, "Arith", "Mul", [2]int{5, 5}, &mul)
|
|
|
|
if err != nil {
|
|
|
|
t.Error(err)
|
|
|
|
}
|
|
|
|
|
|
|
|
// Call Arith.Div()
|
|
|
|
var div int
|
|
|
|
err = c.Call(ctx, "Arith", "Div", [2]int{5, 5}, &div)
|
|
|
|
if err != nil {
|
|
|
|
t.Error(err)
|
|
|
|
}
|
|
|
|
|
|
|
|
if add != 10 {
|
|
|
|
t.Errorf("add: expected 10, got %d", add)
|
|
|
|
}
|
|
|
|
|
|
|
|
if sub != 0 {
|
|
|
|
t.Errorf("sub: expected 0, got %d", sub)
|
|
|
|
}
|
|
|
|
|
|
|
|
if mul != 25 {
|
|
|
|
t.Errorf("mul: expected 25, got %d", mul)
|
|
|
|
}
|
|
|
|
|
|
|
|
if div != 1 {
|
|
|
|
t.Errorf("div: expected 1, got %d", div)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
func TestCodecs(t *testing.T) {
|
|
|
|
// Register the 2-integer array for gob
|
|
|
|
gob.Register([2]int{})
|
|
|
|
|
|
|
|
ctx, cancel := context.WithCancel(context.Background())
|
|
|
|
defer cancel()
|
|
|
|
|
|
|
|
// Create function to test each codec
|
|
|
|
testCodec := func(cf codec.CodecFunc, name string) {
|
|
|
|
// Create network pipe
|
|
|
|
sConn, cConn := net.Pipe()
|
|
|
|
|
|
|
|
s := server.New()
|
|
|
|
defer s.Close()
|
|
|
|
// Register Arith for RPC
|
|
|
|
s.Register(Arith{})
|
|
|
|
// Serve the pipe connection using provided codec
|
|
|
|
go s.ServeConn(ctx, sConn, cf)
|
|
|
|
|
|
|
|
// Create new client using provided codec
|
|
|
|
c := client.New(cConn, cf)
|
|
|
|
defer c.Close()
|
|
|
|
|
|
|
|
// Call Arith.Add()
|
|
|
|
var add int
|
|
|
|
err := c.Call(ctx, "Arith", "Add", [2]int{2, 2}, &add)
|
|
|
|
if err != nil {
|
|
|
|
t.Errorf("codec/%s: %v", name, err)
|
|
|
|
}
|
2022-08-07 05:48:42 +00:00
|
|
|
|
2022-05-26 20:32:19 +00:00
|
|
|
if add != 4 {
|
|
|
|
t.Errorf("codec/%s: add: expected 4, got %d", name, add)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// Test all codecs
|
|
|
|
testCodec(codec.Msgpack, "msgpack")
|
|
|
|
testCodec(codec.JSON, "json")
|
|
|
|
testCodec(codec.Gob, "gob")
|
|
|
|
}
|
2022-05-28 21:52:00 +00:00
|
|
|
|
|
|
|
type Channel struct{}
|
|
|
|
|
|
|
|
func (Channel) Time(ctx *server.Context, interval time.Duration) error {
|
|
|
|
ch, err := ctx.MakeChannel()
|
|
|
|
if err != nil {
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
|
|
|
|
tick := time.NewTicker(interval)
|
|
|
|
go func() {
|
|
|
|
for {
|
|
|
|
select {
|
|
|
|
case t := <-tick.C:
|
|
|
|
ch <- t
|
|
|
|
case <-ctx.Done():
|
2022-05-28 21:58:39 +00:00
|
|
|
tick.Stop()
|
2022-05-28 21:52:00 +00:00
|
|
|
close(ch)
|
|
|
|
return
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}()
|
|
|
|
|
|
|
|
return nil
|
|
|
|
}
|
|
|
|
|
|
|
|
func TestChannel(t *testing.T) {
|
|
|
|
ctx, cancel := context.WithCancel(context.Background())
|
|
|
|
defer cancel()
|
|
|
|
|
|
|
|
// Create new network pipe
|
|
|
|
sConn, cConn := net.Pipe()
|
|
|
|
|
|
|
|
s := server.New()
|
|
|
|
defer s.Close()
|
|
|
|
// Register Arith for RPC
|
|
|
|
s.Register(Channel{})
|
|
|
|
// Serve the pipe connection using default codec
|
|
|
|
go s.ServeConn(ctx, sConn, codec.Default)
|
|
|
|
|
|
|
|
// Create new client using default codec
|
|
|
|
c := client.New(cConn, codec.Default)
|
|
|
|
defer c.Close()
|
|
|
|
|
|
|
|
timeCtx, timeCancel := context.WithCancel(ctx)
|
|
|
|
defer timeCancel()
|
|
|
|
|
|
|
|
timeCh := make(chan *time.Time, 2)
|
|
|
|
err := c.Call(timeCtx, "Channel", "Time", time.Millisecond, timeCh)
|
|
|
|
if err != nil {
|
|
|
|
t.Error(err)
|
|
|
|
}
|
|
|
|
|
|
|
|
var loops int
|
|
|
|
var lastTime *time.Time
|
|
|
|
for curTime := range timeCh {
|
|
|
|
if loops > 3 {
|
|
|
|
timeCancel()
|
|
|
|
break
|
|
|
|
}
|
|
|
|
|
|
|
|
if lastTime == nil {
|
|
|
|
lastTime = curTime
|
|
|
|
continue
|
|
|
|
}
|
|
|
|
|
|
|
|
diff := curTime.Sub(*lastTime)
|
|
|
|
diff = diff.Round(time.Millisecond)
|
|
|
|
|
|
|
|
if diff != time.Millisecond {
|
|
|
|
t.Fatalf("expected 1s diff, got %s", diff)
|
|
|
|
}
|
|
|
|
|
|
|
|
lastTime = curTime
|
|
|
|
loops++
|
|
|
|
}
|
|
|
|
}
|