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)
}
}
|