summaryrefslogtreecommitdiff
path: root/rpc_test.go
blob: 1a06b9e32385109c7ffbd1311211e62ecf90997a (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
package tanja

import (
	"reflect"
	"strings"
	"testing"
)

type sT struct {
	tst         *testing.T
	ses         *Session
	thiscalled  int
	replycalled int
	closecalled int
}

var testmap map[string]Element = map[string]Element{
	"a":     El("val"),
	"stttr": El(nil),
}

var testslice []Element = []Element{El(0), El("")}

func (t *sT) ExportThis(a float32, b uint8, c string, d bool, e map[string]Element, f []Element) {
	if a != 10.5 {
		t.tst.Errorf("a == %v != 10.5", a)
	}
	if b != 42 {
		t.tst.Errorf("b == %v != 42", a)
	}
	if c != "str" {
		t.tst.Errorf("c == %v != str", c)
	}
	if !d {
		t.tst.Errorf("d == %v != true", d)
	}
	if !reflect.DeepEqual(e, testmap) {
		t.tst.Errorf("e == %v != %v", e, testmap)
	}
	if !reflect.DeepEqual(f, testslice) {
		t.tst.Errorf("f == %v != %v", f, testslice)
	}
	t.thiscalled++
}

func (t *sT) ExportReply(m *Message, s string) {
	if s != "10" {
		t.tst.Errorf("ExportReply string argument is '%s', expected '%s'", s, "argument")
	}
	if len(m.Tup) != 5 || m.Tup[4].String() != "extra" {
		t.tst.Errorf("ExportReply invalid tuple length or missing extra element")
	}
	m.Reply(len(s))
	m.Close()
	t.replycalled++
}

func (t *sT) ExportClose(s string) {
	t.closecalled++
	if s == "really!" {
		t.ses.Close()
	}
}

func (t *sT) DontExport() {
	t.tst.Error("DontExport() called.")
}

func TestRPC(tst *testing.T) {
	node := NewNode()
	ses := node.Session()

	obj := &sT{tst: tst, ses: ses}
	n := ses.RegRPC(obj, func(s string) Tuple {
		if strings.HasPrefix(s, "Export") {
			return Tup("prefix", 1, strings.ToLower(s[6:]))
		}
		return nil
	})
	if n != 3 {
		tst.Fatalf("Number of exported methods is %d, expected %d", n, 3)
	}

	go func() {
		// These shouldn't match anything
		ses.Send(false)
		ses.Send(false, "")
		ses.Send(false, "Prefix", 1, "close", 1)
		ses.Send(false, "prefix", 2, "close", 1)
		ses.Send(false, "prefix", 1, "Close", 1)

		// Try replying
		r := ses.Send(true, "prefix", 1, nil, 10, "extra")
		if t := <-r.Chan(); !reflect.DeepEqual(t, Tup(2)) || <-r.Chan() != nil {
			tst.Error("Received invalid reply")
		}
		r.Close()

		// Should match and close immediately.
		r = ses.Send(true, "prefix", 1, "close", 10.2)
		if <-r.Chan() != nil {
			tst.Error("Close did not immediately close the return path")
		}
		r.Close()

		// Testing various types
		ses.Send(false, "prefix", 1, "this", 10.5, "42", "str", "some_true_value", testmap, testslice)

		// Actual close
		ses.Send(false, "prefix", 1, "close", "really!")
		// Shouldn't be received
		ses.Send(false, "prefix", 1, nil, "str")
	}()

	ses.Run()
	if obj.thiscalled != 1 {
		tst.Errorf("This is called %d times, expected %d", obj.thiscalled, 1)
	}
	if obj.closecalled != 3 {
		tst.Errorf("Close is called %d times, expected %d", obj.closecalled, 3)
	}
	if obj.replycalled != 1 {
		tst.Errorf("Close is called %d times, expected %d", obj.replycalled, 1)
	}
}