Skip to content

Commit 58ead35

Browse files
committed
tests: add unit test for hexagonrpc function
The hexagonrpc function is getting very complex and deserves its own unit test. Add a unit test for the hexagonrpc function. Signed-off-by: Richard Acayan <[email protected]>
1 parent 84ce12d commit 58ead35

File tree

2 files changed

+303
-0
lines changed

2 files changed

+303
-0
lines changed

tests/meson.build

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,5 +24,13 @@ test_hexagonfs = executable('test_hexagonfs',
2424
include_directories : include,
2525
)
2626

27+
test_hexagonrpc = executable('test_hexagonrpc',
28+
'test_hexagonrpc.c',
29+
'../libhexagonrpc/hexagonrpc.c',
30+
c_args : cflags,
31+
include_directories : include,
32+
)
33+
2734
test('iobuffer', test_iobuffer)
2835
test('hexagonfs', test_hexagonfs, args : [sample_file])
36+
test('hexagonrpc', test_hexagonrpc)

tests/test_hexagonrpc.c

Lines changed: 295 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,295 @@
1+
/*
2+
* FastRPC reverse tunnel - tests for virtual filesystem
3+
*
4+
* Copyright (C) 2025 HexagonRPC Contributors
5+
*
6+
* This file is part of HexagonRPC.
7+
*
8+
* HexagonRPC is free software: you can redistribute it and/or modify
9+
* it under the terms of the GNU General Public License as published by
10+
* the Free Software Foundation, either version 3 of the License, or
11+
* (at your option) any later version.
12+
*
13+
* This program is distributed in the hope that it will be useful,
14+
* but WITHOUT ANY WARRANTY; without even the implied warranty of
15+
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16+
* GNU General Public License for more details.
17+
*
18+
* You should have received a copy of the GNU General Public License
19+
* along with this program. If not, see <https://www.gnu.org/licenses/>.
20+
*/
21+
22+
#include <libhexagonrpc/hexagonrpc.h>
23+
#include <misc/fastrpc.h>
24+
#include <stdarg.h>
25+
#include <stdint.h>
26+
#include <stdio.h>
27+
#include <string.h>
28+
#include <sys/ioctl.h>
29+
#include <sys/syscall.h>
30+
#include <unistd.h>
31+
32+
#ifdef __GLIBC__
33+
typedef unsigned long int ioctl_operation;
34+
#else
35+
typedef int ioctl_operation;
36+
#endif
37+
38+
struct expected_invoke_arg {
39+
size_t len;
40+
const void *ptr;
41+
};
42+
43+
static const struct expected_invoke_arg *expected = NULL;
44+
static uint32_t expected_sc = 0;
45+
46+
static const uint32_t no_args_sc = REMOTE_SCALARS_MAKE(0, 0, 0);
47+
48+
static const struct hrpc_method_def_interp4 no_args_def = {
49+
.msg_id = 0,
50+
.n_args = 0,
51+
.args = NULL,
52+
.n_inner_types = 0,
53+
.inner_types = NULL,
54+
};
55+
56+
static const unsigned char scalar_arg_exp0[] = {
57+
0x67, 0x45, 0x23, 0x01,
58+
0x02, 0x00, 0x00, 0x00,
59+
0x00, 0x00, 0x00, 0x00,
60+
0x10, 0x32, 0x54, 0x76, 0x98, 0xba, 0xdc, 0xfe,
61+
};
62+
63+
static const unsigned char scalar_arg_exp1[] = {
64+
'h', 'i',
65+
};
66+
67+
static const struct expected_invoke_arg scalar_arg_exp[] = {
68+
{
69+
.len = sizeof(scalar_arg_exp0),
70+
.ptr = scalar_arg_exp0,
71+
},
72+
{
73+
.len = sizeof(scalar_arg_exp1),
74+
.ptr = scalar_arg_exp1,
75+
},
76+
{
77+
.len = 0,
78+
.ptr = NULL,
79+
},
80+
};
81+
82+
static const uint32_t scalar_arg_sc = REMOTE_SCALARS_MAKE(0, 3, 0);
83+
84+
static const struct hrpc_arg_def_interp4 scalar_arg_args[] = {
85+
{ HRPC_ARG_WORD, sizeof(uint32_t) },
86+
{ HRPC_ARG_BLOB_SEQ, sizeof(char) },
87+
{ HRPC_ARG_BLOB_SEQ, sizeof(char) },
88+
{ HRPC_ARG_WORD, sizeof(uint64_t) },
89+
};
90+
91+
static const struct hrpc_method_def_interp4 scalar_arg_def = {
92+
.msg_id = 0,
93+
.n_args = HRPC_ARRAY_SIZE(scalar_arg_args),
94+
.args = scalar_arg_args,
95+
.n_inner_types = 0,
96+
.inner_types = NULL,
97+
};
98+
99+
static const uint32_t out_arg_sc = REMOTE_SCALARS_MAKE(1, 1, 3);
100+
101+
static const unsigned char out_arg_exp0[] = {
102+
0x02, 0x00, 0x00, 0x00,
103+
0x05, 0x00, 0x00, 0x00,
104+
};
105+
106+
static const unsigned char out_arg_exp1[] = {
107+
0x00, 0x00, 0x00, 0x00,
108+
};
109+
110+
static const unsigned char out_arg_exp2[] = {
111+
'h', 'i',
112+
};
113+
114+
static const unsigned char out_arg_exp3[] = {
115+
'h', 'e', 'l', 'l', 'o',
116+
};
117+
118+
static const struct expected_invoke_arg out_arg_exp[] = {
119+
{
120+
.len = sizeof(out_arg_exp0),
121+
.ptr = out_arg_exp0,
122+
},
123+
{
124+
.len = sizeof(out_arg_exp1),
125+
.ptr = out_arg_exp1,
126+
},
127+
{
128+
.len = sizeof(out_arg_exp2),
129+
.ptr = out_arg_exp2,
130+
},
131+
{
132+
.len = sizeof(out_arg_exp3),
133+
.ptr = out_arg_exp3,
134+
},
135+
};
136+
137+
static const struct hrpc_arg_def_interp4 out_arg_args[] = {
138+
{ HRPC_ARG_OUT_BLOB, sizeof(uint32_t) },
139+
{ HRPC_ARG_OUT_BLOB_SEQ, sizeof(char) },
140+
{ HRPC_ARG_OUT_BLOB_SEQ, sizeof(char) },
141+
};
142+
143+
static const struct hrpc_method_def_interp4 out_arg_def = {
144+
.msg_id = 1,
145+
.n_args = HRPC_ARRAY_SIZE(out_arg_args),
146+
.args = out_arg_args,
147+
.n_inner_types = 0,
148+
.inner_types = NULL,
149+
};
150+
151+
static const uint32_t thirty_third_method_sc = REMOTE_SCALARS_MAKE(31, 3, 0);
152+
153+
static const unsigned char thirty_third_method_exp0[] = {
154+
0x20, 0x00, 0x00, 0x00,
155+
0x67, 0x45, 0x23, 0x01,
156+
0x02, 0x00, 0x00, 0x00,
157+
0x00, 0x00, 0x00, 0x00,
158+
};
159+
160+
static const unsigned char thirty_third_method_exp1[] = {
161+
'h', 'i',
162+
};
163+
164+
static const struct expected_invoke_arg thirty_third_method_exp[] = {
165+
{
166+
.len = sizeof(thirty_third_method_exp0),
167+
.ptr = thirty_third_method_exp0,
168+
},
169+
{
170+
.len = sizeof(thirty_third_method_exp1),
171+
.ptr = thirty_third_method_exp1,
172+
},
173+
{
174+
.len = 0,
175+
.ptr = NULL,
176+
},
177+
};
178+
179+
static const struct hrpc_arg_def_interp4 thirty_third_method_args[] = {
180+
{ HRPC_ARG_WORD, sizeof(uint32_t) },
181+
{ HRPC_ARG_BLOB_SEQ, sizeof(char) },
182+
{ HRPC_ARG_BLOB_SEQ, sizeof(char) },
183+
};
184+
185+
static const struct hrpc_method_def_interp4 thirty_third_method_def = {
186+
.msg_id = 32,
187+
.n_args = HRPC_ARRAY_SIZE(thirty_third_method_args),
188+
.args = thirty_third_method_args,
189+
.n_inner_types = 0,
190+
.inner_types = NULL,
191+
};
192+
193+
int ioctl(int fd, ioctl_operation op, ...)
194+
{
195+
struct fastrpc_invoke *invoke;
196+
struct fastrpc_invoke_args *args;
197+
size_t i, n_inbufs, n_outbufs;
198+
void *data;
199+
va_list list;
200+
201+
va_start(list, op);
202+
data = va_arg(list, void *);
203+
va_end(list);
204+
205+
if (op != (ioctl_operation) FASTRPC_IOCTL_INVOKE) {
206+
return syscall(SYS_ioctl, fd, op, data);
207+
} else {
208+
invoke = data;
209+
210+
if (fd != -1)
211+
return -1;
212+
213+
if (invoke->handle != 0)
214+
return -1;
215+
216+
if (invoke->sc != expected_sc)
217+
return -1;
218+
219+
n_inbufs = REMOTE_SCALARS_INBUFS(invoke->sc);
220+
n_outbufs = REMOTE_SCALARS_OUTBUFS(invoke->sc);
221+
args = (struct fastrpc_invoke_args *) invoke->args;
222+
223+
for (i = 0; i < n_inbufs; i++) {
224+
if (args[i].fd != -1 || args[i].attr != 0)
225+
return -1;
226+
227+
if (args[i].length != expected[i].len)
228+
return -1;
229+
230+
if (memcmp((void *) args[i].ptr,
231+
expected[i].ptr,
232+
args[i].length))
233+
return -1;
234+
}
235+
236+
for (i = n_inbufs; i < n_inbufs + n_outbufs; i++) {
237+
if (args[i].fd != -1 || args[i].attr != 0)
238+
return -1;
239+
240+
if (args[i].length < expected[i].len)
241+
return -1;
242+
243+
memcpy((void *) args[i].ptr,
244+
expected[i].ptr,
245+
args[i].length);
246+
}
247+
248+
return 0;
249+
}
250+
}
251+
252+
int main(void)
253+
{
254+
int ret, fd = -1;
255+
uint32_t hdl = 0;
256+
uint32_t word_out;
257+
char hi[2];
258+
char hello[5];
259+
260+
expected_sc = no_args_sc;
261+
expected = NULL;
262+
ret = hexagonrpc(&no_args_def, fd, hdl);
263+
if (ret)
264+
return 1;
265+
266+
expected_sc = scalar_arg_sc;
267+
expected = scalar_arg_exp;
268+
ret = hexagonrpc(&scalar_arg_def, fd, hdl,
269+
(uint32_t) 0x01234567,
270+
(uint32_t) 2, (const void *) "hi",
271+
(uint32_t) 0, (const void *) NULL,
272+
(uint64_t) 0xfedcba9876543210 );
273+
if (ret)
274+
return 1;
275+
276+
expected_sc = out_arg_sc;
277+
expected = out_arg_exp;
278+
ret = hexagonrpc(&out_arg_def, fd, hdl,
279+
(void *) &word_out,
280+
(uint32_t) 2, (void *) hi,
281+
(uint32_t) 5, (void *) hello);
282+
if (ret)
283+
return 1;
284+
285+
expected_sc = thirty_third_method_sc;
286+
expected = thirty_third_method_exp;
287+
ret = hexagonrpc(&thirty_third_method_def, fd, hdl,
288+
(uint32_t) 0x01234567,
289+
(uint32_t) 2, (const void *) "hi",
290+
(uint32_t) 0, (const void *) NULL);
291+
if (ret)
292+
return 1;
293+
294+
return 0;
295+
}

0 commit comments

Comments
 (0)