Skip to content

Commit 43256e8

Browse files
authored
Merge pull request #1 from bcmi-labs/tests
Added integration test based on various board combinations.
2 parents bb9bd6f + d00603c commit 43256e8

File tree

11 files changed

+705
-0
lines changed

11 files changed

+705
-0
lines changed

extras/integration_test/README.md

Lines changed: 133 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,133 @@
1+
## Integration test for the RPC library
2+
3+
This is a test that runs on the Arduino Zero board. It could be easily extended to other boards with multiple serial ports.
4+
5+
### Running the test
6+
7+
Prerequisites:
8+
9+
* An Arduino Zero board, connected with both the USB ports.
10+
* `arduino-cli`
11+
* The platform `arduino:samd` installed through the `arduino-cli`.
12+
* The dependencies of the RPClite library installed through the `arduino-cli`.
13+
* A working `go` programming language compiler.
14+
15+
To run the test, from a terminal change directory to this folder, and run:
16+
17+
`go test -v`
18+
19+
it should compile and upload the test sketch, and perform the RPC call tests.
20+
21+
The output should look similar to the following:
22+
23+
```
24+
RpcLite/test/RpcClientTest$ go test -v
25+
=== RUN TestBasicComm
26+
Lo sketch usa 27028 byte (10%) dello spazio disponibile per i programmi. Il massimo è 262144 byte.
27+
Le variabili globali usano 4040 byte (12%) di memoria dinamica, lasciando altri 28728 byte liberi per le variabili locali. Il massimo è 32768 byte.
28+
Atmel SMART device 0x10010005 found
29+
Device : ATSAMD21G18A
30+
Chip ID : 10010005
31+
Version : v2.0 [Arduino:XYZ] Apr 11 2019 13:09:49
32+
Address : 8192
33+
Pages : 3968
34+
Page Size : 64 bytes
35+
Total Size : 248KB
36+
Planes : 1
37+
Lock Regions : 16
38+
Locked : none
39+
Security : false
40+
Boot Flash : true
41+
BOD : true
42+
BOR : true
43+
Arduino : FAST_CHIP_ERASE
44+
Arduino : FAST_MULTI_PAGE_WRITE
45+
Arduino : CAN_CHECKSUM_MEMORY_BUFFER
46+
Erase flash
47+
done in 0.873 seconds
48+
49+
Write 27028 bytes to flash (423 pages)
50+
[==============================] 100% (423/423 pages)
51+
done in 0.155 seconds
52+
53+
Verify 27028 bytes of flash with checksum.
54+
Verify successful
55+
done in 0.026 seconds
56+
CPU reset.
57+
=== RUN TestBasicComm/RPCClientCallFloatArgs
58+
/dev/ttyACM0 READ << 94
59+
/dev/ttyACM0 READ << 0001
60+
/dev/ttyACM0 READ << a4
61+
/dev/ttyACM0 READ << 6d75
62+
/dev/ttyACM0 READ << 6c
63+
/dev/ttyACM0 READ << 74
64+
/dev/ttyACM0 READ << 92cb
65+
/dev/ttyACM0 READ << 40
66+
/dev/ttyACM0 READ << 0000
67+
/dev/ttyACM0 READ << 00
68+
/dev/ttyACM0 READ << 0000
69+
/dev/ttyACM0 READ << 00
70+
/dev/ttyACM0 READ << 00cb
71+
/dev/ttyACM0 READ << 40
72+
/dev/ttyACM0 READ << 08
73+
/dev/ttyACM0 READ << 0000
74+
/dev/ttyACM0 READ << 00
75+
/dev/ttyACM0 READ << 0000
76+
/dev/ttyACM0 READ << 00
77+
/dev/ttyACM0 WRITE >> 94
78+
/dev/ttyACM0 WRITE >> 01
79+
/dev/ttyACM0 WRITE >> 01
80+
/dev/ttyACM0 WRITE >> c0
81+
/dev/ttyACM0 WRITE >> cb4018000000000000
82+
=== RUN TestBasicComm/RPCClientCallFloatArgsError
83+
/dev/ttyACM0 READ << 9400
84+
/dev/ttyACM0 READ << 02a46d
85+
/dev/ttyACM0 READ << 75
86+
/dev/ttyACM0 READ << 6c74
87+
/dev/ttyACM0 READ << 91
88+
/dev/ttyACM0 READ << cb40
89+
/dev/ttyACM0 READ << 00
90+
/dev/ttyACM0 READ << 00
91+
/dev/ttyACM0 READ << 0000
92+
/dev/ttyACM0 READ << 00
93+
/dev/ttyACM0 READ << 0000
94+
/dev/ttyACM0 WRITE >> 94
95+
/dev/ttyACM0 WRITE >> 01
96+
/dev/ttyACM0 WRITE >> 02
97+
/dev/ttyACM0 WRITE >> 92
98+
/dev/ttyACM0 WRITE >> 01
99+
/dev/ttyACM0 WRITE >> b1
100+
/dev/ttyACM0 WRITE >> 6d697373696e6720706172616d65746572
101+
/dev/ttyACM0 WRITE >> c0
102+
=== RUN TestBasicComm/RPCClientCallBoolArgs
103+
/dev/ttyACM0 READ << 9400
104+
/dev/ttyACM0 READ << 03
105+
/dev/ttyACM0 READ << a26f
106+
/dev/ttyACM0 READ << 72
107+
/dev/ttyACM0 READ << 92c3
108+
/dev/ttyACM0 READ << c2
109+
/dev/ttyACM0 WRITE >> 94
110+
/dev/ttyACM0 WRITE >> 01
111+
/dev/ttyACM0 WRITE >> 03
112+
/dev/ttyACM0 WRITE >> c0
113+
/dev/ttyACM0 WRITE >> c3
114+
/dev/ttyACM0 READ << 9400
115+
/dev/ttyACM0 READ << 04
116+
/dev/ttyACM0 READ << a26f
117+
/dev/ttyACM0 READ << 72
118+
/dev/ttyACM0 READ << 91
119+
/dev/ttyACM0 READ << c2
120+
/dev/ttyACM0 WRITE >> 94
121+
/dev/ttyACM0 WRITE >> 01
122+
/dev/ttyACM0 WRITE >> 04
123+
/dev/ttyACM0 WRITE >> c0
124+
/dev/ttyACM0 WRITE >> c2
125+
/dev/ttyACM0 CLOSE
126+
--- PASS: TestBasicComm (10.21s)
127+
--- PASS: TestBasicComm/RPCClientCallFloatArgs (0.03s)
128+
--- PASS: TestBasicComm/RPCClientCallFloatArgsError (0.03s)
129+
--- PASS: TestBasicComm/RPCClientCallBoolArgs (0.01s)
130+
PASS
131+
ok RpcClientZeroTest 10.216s
132+
RpcLite/test/RpcClientTest$
133+
```
Lines changed: 112 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,112 @@
1+
package testsuite
2+
3+
import (
4+
"testing"
5+
"time"
6+
7+
"github.com/stretchr/testify/require"
8+
"github.com/vmihailenco/msgpack/v5"
9+
"go.bug.st/serial"
10+
)
11+
12+
func TestRPCClient(t *testing.T) {
13+
// Get the upload port to upload the sketch
14+
rpcPort, debugPort := UploadSketchAndGetRPCAndDebugPorts(t)
15+
16+
// Connect to the RPC serial port
17+
_rpcSer, err := serial.Open(rpcPort, &serial.Mode{BaudRate: 115200})
18+
rpcSer := &DebugStream{Upstream: _rpcSer, Portname: rpcPort}
19+
require.NoError(t, err)
20+
t.Cleanup(func() { rpcSer.Close() })
21+
in := msgpack.NewDecoder(rpcSer)
22+
out := msgpack.NewEncoder(rpcSer)
23+
out.UseCompactInts(true)
24+
25+
// Connect to the Debug serial port
26+
debugSer, err := serial.Open(debugPort, &serial.Mode{BaudRate: 115200})
27+
require.NoError(t, err)
28+
t.Cleanup(func() { debugSer.Close() })
29+
expectDebug := func(s string) { Expect(t, debugSer, s) }
30+
31+
// Timeout fallback: close the connection after 10 seconds, if the test do not go through
32+
go func() {
33+
time.Sleep(10 * time.Second)
34+
rpcSer.Close()
35+
debugSer.Close()
36+
}()
37+
38+
msgID := 0
39+
40+
// 1: Receive an RPC call to the "mult" method with 2 arguments
41+
// and send back the result
42+
t.Run("RPCClientCallFloatArgs", func(t *testing.T) {
43+
arr, err := in.DecodeSlice()
44+
require.NoError(t, err)
45+
require.Equal(t, []any{int8(0), int8(msgID), "mult", []any{2.0, 3.0}}, arr)
46+
err = out.Encode([]any{1, msgID, nil, 6.0})
47+
require.NoError(t, err)
48+
expectDebug("mult(2.0, 3.0)\r\n")
49+
expectDebug("-> 6.00\r\n")
50+
msgID++
51+
})
52+
53+
// 2: Receive an RPC call to the "mult" method with 1 argument (wrong number of arguments)
54+
// and send back an error with [int, string] format
55+
t.Run("RPCClientCallFloatArgsError", func(t *testing.T) {
56+
arr, err := in.DecodeSlice()
57+
require.NoError(t, err)
58+
require.Equal(t, []any{int8(0), int8(msgID), "mult", []any{2.0}}, arr)
59+
err = out.Encode([]any{1, msgID, []any{1, "missing parameter"}, nil})
60+
require.NoError(t, err)
61+
expectDebug("mult(2.0)\r\n")
62+
expectDebug("-> error\r\n")
63+
msgID++
64+
})
65+
66+
// 3, 4: Receive an RPC call to the "or" method with 1 or 2 arguments
67+
// and send back the result
68+
t.Run("RPCClientCallBoolArgs", func(t *testing.T) {
69+
arr, err := in.DecodeSlice()
70+
require.NoError(t, err)
71+
require.Equal(t, []any{int8(0), int8(msgID), "or", []any{true, false}}, arr)
72+
err = out.Encode([]any{1, msgID, nil, true})
73+
require.NoError(t, err)
74+
expectDebug("or(true, false)\r\n")
75+
expectDebug("-> true\r\n")
76+
msgID++
77+
78+
arr, err = in.DecodeSlice()
79+
require.NoError(t, err)
80+
require.Equal(t, []any{int8(0), int8(msgID), "or", []any{false}}, arr)
81+
err = out.Encode([]any{1, msgID, nil, false})
82+
require.NoError(t, err)
83+
expectDebug("or(false)\r\n")
84+
expectDebug("-> false\r\n")
85+
msgID++
86+
})
87+
88+
// 5: Receive an RPC call to the "mult" method with 1 argument (wrong number of arguments)
89+
// and send back an error with [int, string] format with a long string
90+
t.Run("RPCClientCallFloatArgsErrorWithLongString", func(t *testing.T) {
91+
arr, err := in.DecodeSlice()
92+
require.NoError(t, err)
93+
require.Equal(t, []any{int8(0), int8(msgID), "mult", []any{2.0}}, arr)
94+
err = out.Encode([]any{1, msgID, []any{2, "method get_led_state not available"}, nil})
95+
require.NoError(t, err)
96+
expectDebug("mult(2.0)\r\n")
97+
expectDebug("-> error\r\n")
98+
msgID++
99+
})
100+
101+
// RPC: Receive an RPC call to the "mult" method with 1 argument (wrong number of arguments)
102+
// and send back a custom error without [int, string] format
103+
// t.Run("RPCClientCallFloatArgsErrorCustom", func(t *testing.T) {
104+
// arr, err := in.DecodeSlice()
105+
// require.NoError(t, err)
106+
// require.Equal(t, []any{int8(0), int8(3), "mult", []any{2.0}}, arr)
107+
// err = out.Encode([]any{1, 3, "missing parameter", nil})
108+
// require.NoError(t, err)
109+
// expectDebug("mult(2.0)\r\n")
110+
// expectDebug("-> error\r\n")
111+
// })
112+
}
Lines changed: 93 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,93 @@
1+
package testsuite
2+
3+
import (
4+
"testing"
5+
"time"
6+
7+
"github.com/stretchr/testify/require"
8+
"github.com/vmihailenco/msgpack/v5"
9+
"go.bug.st/serial"
10+
)
11+
12+
func TestRPCServer(t *testing.T) {
13+
// Get the upload port to upload the sketch
14+
rpcPort, debugPort := UploadSketchAndGetRPCAndDebugPorts(t)
15+
16+
// Connect to the RPC serial port
17+
_rpcSer, err := serial.Open(rpcPort, &serial.Mode{BaudRate: 115200})
18+
rpcSer := &DebugStream{Upstream: _rpcSer, Portname: rpcPort}
19+
require.NoError(t, err)
20+
t.Cleanup(func() { rpcSer.Close() })
21+
in := msgpack.NewDecoder(rpcSer)
22+
out := msgpack.NewEncoder(rpcSer)
23+
out.UseCompactInts(true)
24+
25+
// Connect to the Debug serial port
26+
debugSer, err := serial.Open(debugPort, &serial.Mode{BaudRate: 115200})
27+
require.NoError(t, err)
28+
t.Cleanup(func() { debugSer.Close() })
29+
expectDebug := func(s string) { Expect(t, debugSer, s) }
30+
31+
// Timeout fallback: close the connection after 10 seconds, if the test do not go through
32+
go func() {
33+
time.Sleep(10 * time.Second)
34+
rpcSer.Close()
35+
debugSer.Close()
36+
}()
37+
38+
// 1: Send an RPC call to the "add" method with 2 arguments
39+
// and get back the result
40+
t.Run("RPCServerCallIntArgs", func(t *testing.T) {
41+
err = out.Encode([]any{0, 1, "add", []any{2, 3}})
42+
require.NoError(t, err)
43+
expectDebug("add(2, 3)\r\n")
44+
arr, err := in.DecodeSlice()
45+
require.NoError(t, err)
46+
require.Equal(t, []any{int8(1), int8(1), nil, int8(5)}, arr)
47+
})
48+
49+
// 2, 3: Send the same RPC call with 1 and 3 arguments, and get back the error
50+
t.Run("RPCServerCallWrongIntArgsCount", func(t *testing.T) {
51+
err = out.Encode([]any{0, 2, "add", []any{2}})
52+
require.NoError(t, err)
53+
arr, err := in.DecodeSlice()
54+
require.NoError(t, err)
55+
require.Equal(t, []any{
56+
int8(1),
57+
int8(2),
58+
[]any{uint8(253), "Missing call parameters (WARNING: Default param resolution is not implemented)"},
59+
nil,
60+
}, arr)
61+
62+
err = out.Encode([]any{0, 3, "add", []any{2, 3, 4}})
63+
require.NoError(t, err)
64+
arr, err = in.DecodeSlice()
65+
require.NoError(t, err)
66+
require.Equal(t, []any{
67+
int8(1),
68+
int8(3),
69+
[]any{uint8(253), "Too many parameters"},
70+
nil,
71+
}, arr)
72+
})
73+
74+
// 4: Send an RPC call to the "greet" method
75+
t.Run("RPCServerCallNoArgsReturnString", func(t *testing.T) {
76+
err = out.Encode([]any{0, 4, "greet", []any{}})
77+
require.NoError(t, err)
78+
expectDebug("greet()\r\n")
79+
arr, err := in.DecodeSlice()
80+
require.NoError(t, err)
81+
require.Equal(t, []any{int8(1), int8(4), nil, "Hello World!"}, arr)
82+
})
83+
84+
// 5: Send an RPC call to the "loopback" method with 1 string argument
85+
t.Run("RPCServerCallStringArgsReturnString", func(t *testing.T) {
86+
err = out.Encode([]any{0, 5, "loopback", []any{"Hello World!"}})
87+
require.NoError(t, err)
88+
expectDebug("loopback(\"Hello World!\")\r\n")
89+
arr, err := in.DecodeSlice()
90+
require.NoError(t, err)
91+
require.Equal(t, []any{int8(1), int8(5), nil, "Hello World!"}, arr)
92+
})
93+
}

0 commit comments

Comments
 (0)