Skip to content

Commit c706676

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 8ea2165 commit c706676

File tree

2 files changed

+185
-0
lines changed

2 files changed

+185
-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: 177 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,177 @@
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 char scalar_arg_exp0[] = {
57+
0x67, 0x45, 0x23, 0x01,
58+
0x02, 0x00, 0x00, 0x00,
59+
0x00, 0x00, 0x00, 0x00,
60+
};
61+
62+
static const char scalar_arg_exp1[] = {
63+
'h', 'i',
64+
};
65+
66+
static const struct expected_invoke_arg scalar_arg_exp[] = {
67+
{
68+
.len = sizeof(scalar_arg_exp0),
69+
.ptr = scalar_arg_exp0,
70+
},
71+
{
72+
.len = sizeof(scalar_arg_exp1),
73+
.ptr = scalar_arg_exp1,
74+
},
75+
{
76+
.len = 0,
77+
.ptr = NULL,
78+
},
79+
};
80+
81+
static const uint32_t scalar_arg_sc = REMOTE_SCALARS_MAKE(0, 3, 0);
82+
83+
static const struct hrpc_arg_def_interp4 scalar_arg_args[] = {
84+
{ HRPC_ARG_WORD, sizeof(uint32_t) },
85+
{ HRPC_ARG_BLOB_SEQ, sizeof(char) },
86+
{ HRPC_ARG_BLOB_SEQ, sizeof(char) },
87+
};
88+
89+
static const struct hrpc_method_def_interp4 scalar_arg_def = {
90+
.msg_id = 0,
91+
.n_args = HRPC_ARRAY_SIZE(scalar_arg_args),
92+
.args = scalar_arg_args,
93+
.n_inner_types = 0,
94+
.inner_types = NULL,
95+
};
96+
97+
int ioctl(int fd, ioctl_operation op, ...)
98+
{
99+
struct fastrpc_invoke *invoke;
100+
struct fastrpc_invoke_args *args;
101+
size_t i, n_inbufs, n_outbufs;
102+
void *data;
103+
va_list list;
104+
105+
va_start(list, op);
106+
data = va_arg(list, void *);
107+
va_end(list);
108+
109+
if (op != (ioctl_operation) FASTRPC_IOCTL_INVOKE) {
110+
return syscall(SYS_ioctl, fd, op, data);
111+
} else {
112+
invoke = data;
113+
114+
if (fd != -1)
115+
return -1;
116+
117+
if (invoke->handle != 0)
118+
return -1;
119+
120+
if (invoke->sc != expected_sc)
121+
return -1;
122+
123+
n_inbufs = REMOTE_SCALARS_INBUFS(invoke->sc);
124+
n_outbufs = REMOTE_SCALARS_OUTBUFS(invoke->sc);
125+
args = (struct fastrpc_invoke_args *) invoke->args;
126+
127+
for (i = 0; i < n_inbufs; i++) {
128+
if (args[i].fd != -1 || args[i].attr != 0)
129+
return -1;
130+
131+
if (args[i].length != expected[i].len)
132+
return -1;
133+
134+
if (memcmp((void *) args[i].ptr,
135+
expected[i].ptr,
136+
args[i].length))
137+
return -1;
138+
}
139+
140+
for (i = n_inbufs; i < n_inbufs + n_outbufs; i++) {
141+
if (args[i].fd != -1 || args[i].attr != 0)
142+
return -1;
143+
144+
if (args[i].length < expected[i].len)
145+
return -1;
146+
147+
memcpy((void *) args[i].ptr,
148+
expected[i].ptr,
149+
args[i].length);
150+
}
151+
152+
return 0;
153+
}
154+
}
155+
156+
int main(void)
157+
{
158+
int ret, fd = -1;
159+
uint32_t hdl = 0;
160+
161+
expected_sc = no_args_sc;
162+
expected = NULL;
163+
ret = hexagonrpc(&no_args_def, fd, hdl);
164+
if (ret)
165+
return 1;
166+
167+
expected_sc = scalar_arg_sc;
168+
expected = scalar_arg_exp;
169+
ret = hexagonrpc(&scalar_arg_def, fd, hdl,
170+
(uint32_t) 0x01234567,
171+
(uint32_t) 2, (const void *) "hi",
172+
(uint32_t) 0, (const void *) NULL);
173+
if (ret)
174+
return 1;
175+
176+
return 0;
177+
}

0 commit comments

Comments
 (0)