Drop main() prototype. Syncs with NetBSD-8
[minix.git] / minix / tests / rmibtest / rmibtest.c
blobeec1c3a4b5fdccc2a518b6d6731cd479ebd88cd3
1 /* Remote MIB (RMIB) test service - by D.C. van Moolenbroek */
2 /*
3 * This test is a good start, but not an exhaustive coverage test for all
4 * possible failure cases. The reason for that is mainly that there are
5 * various scenarios that we cannot generate without implementing our own local
6 * bogus RMIB code. Adding that is something for later - TODO.
7 */
8 #include <minix/drivers.h>
9 #include <minix/sysctl.h>
10 #include <minix/rmib.h>
12 static int running;
14 /* The following is a copy of the minix.test subtree in the MIB service. */
15 static char test_string[16], test_struct[12];
17 static struct rmib_node minix_test_secret_table[] = {
18 /* 0*/ [SECRET_VALUE] = RMIB_INT(RMIB_RO, 12345, "value",
19 "The combination to my luggage"),
22 static struct rmib_node minix_test_table[] = {
23 /* 0*/ [TEST_INT] = RMIB_INT(RMIB_RO | CTLFLAG_HEX, 0x01020304,
24 "int", "Value test field"),
25 /* 1*/ [TEST_BOOL] = RMIB_BOOL(RMIB_RW, 0, "bool",
26 "Boolean test field"),
27 /* 2*/ [TEST_QUAD] = RMIB_QUAD(RMIB_RW, 0, "quad",
28 "Quad test field"),
29 /* 3*/ [TEST_STRING] = RMIB_STRING(RMIB_RW, test_string, "string",
30 "String test field"),
31 /* 4*/ [TEST_STRUCT] = RMIB_STRUCT(RMIB_RW, sizeof(test_struct),
32 test_struct, "struct",
33 "Structure test field"),
34 /* 5*/ [TEST_PRIVATE] = RMIB_INT(RMIB_RW | CTLFLAG_PRIVATE, -5375,
35 "private", "Private test field"),
36 /* 6*/ [TEST_ANYWRITE] = RMIB_INT(RMIB_RW | CTLFLAG_ANYWRITE, 0,
37 "anywrite", "AnyWrite test field"),
38 /* 7*/ [TEST_DYNAMIC] = RMIB_INT(RMIB_RO, 0, "deleteme",
39 "This node will be destroyed"),
40 /* 8*/ [TEST_SECRET] = RMIB_NODE(RMIB_RO | CTLFLAG_PRIVATE,
41 minix_test_secret_table, "secret",
42 "Private subtree"),
43 /* 9*/ [TEST_PERM] = RMIB_INT(RMIB_RO, 1, "permanent", NULL),
44 /*10*/ [TEST_DESTROY1] = RMIB_INT(RMIB_RO, 123, "destroy1", NULL),
45 /*11*/ [TEST_DESTROY2] = RMIB_INT(RMIB_RO, 456, "destroy2",
46 "This node will be destroyed"),
49 static struct rmib_node minix_test = RMIB_NODE(RMIB_RW | CTLFLAG_HIDDEN,
50 minix_test_table, "test", "Test87 testing ground");
51 /* Here ends the copy of the minix.test subtree in the MIB service. */
53 static struct rmib_node test_table[] = {
56 static struct rmib_node test_rnode = RMIB_NODE(RMIB_RO, test_table, "test",
57 "Test node");
59 static int value = 5375123;
61 static ssize_t test_func(struct rmib_call *, struct rmib_node *,
62 struct rmib_oldp *, struct rmib_newp *);
64 /* No defined constants because userland will access these by name anyway. */
65 static struct rmib_node minix_rtest_table[] = {
66 [1] = RMIB_INTPTR(RMIB_RW, &value, "int",
67 "Test description"),
68 [2] = RMIB_FUNC(CTLTYPE_INT | RMIB_RW, sizeof(int),
69 test_func, "func", "Test function"),
72 static struct rmib_node minix_rtest = RMIB_NODE(RMIB_RO, minix_rtest_table,
73 "rtest", "Remote test subtree");
76 * Test function that deflects reads and writes to its sibling node. Not a
77 * super useful thing to do, but a decent test of functionality regardless.
79 static ssize_t
80 test_func(struct rmib_call * call, struct rmib_node * node,
81 struct rmib_oldp * oldp, struct rmib_newp * newp)
84 return rmib_readwrite(call, &minix_rtest_table[1], oldp, newp);
88 * Attempt to perform registrations that should be rejected locally, and thus
89 * result in failure immediately. Unfortunately, we cannot verify that the MIB
90 * service also verifies these aspects remotely, at least without talking to it
91 * directly.
93 static void
94 test_local_failures(void)
96 int r, mib[CTL_SHORTNAME + 1];
98 memset(mib, 0, sizeof(mib));
100 /* Test an empty path. */
101 if ((r = rmib_register(mib, 0, &test_rnode)) != EINVAL)
102 panic("registering remote MIB subtree yielded: %d", r);
104 /* Test a path that is too long. */
105 if ((r = rmib_register(mib, CTL_SHORTNAME + 1, &test_rnode)) != EINVAL)
106 panic("registering remote MIB subtree yielded: %d", r);
108 /* Test a mount point that is not a node-type (parent) node. */
109 mib[0] = CTL_MINIX;
110 mib[1] = MINIX_TEST;
111 mib[2] = TEST_INT;
112 if ((r = rmib_register(mib, 3, &minix_test_table[TEST_INT])) != EINVAL)
113 panic("registering remote MIB subtree yielded: %d", r);
117 * Perform a number of registrations that will not be accepted by the MIB
118 * service. We will never know, but the userland test script can verify the
119 * difference by comparing the number of remotes before and after.
121 static void
122 test_remote_failures(void)
124 int r, mib[CTL_SHORTNAME];
126 /* Test an existing one-node path. */
127 mib[0] = CTL_KERN;
128 if ((r = rmib_register(mib, 1, &test_rnode)) != OK)
129 panic("unable to register remote MIB subtree: %d", r);
130 rmib_reset();
132 /* Test a path in which a non-final component does not exist. */
133 mib[1] = CREATE_BASE - 1; /* probably as safe as it gets.. */
134 mib[2] = 0;
135 if ((r = rmib_register(mib, 3, &test_rnode)) != OK)
136 panic("unable to register remote MIB subtree: %d", r);
137 rmib_reset();
139 /* Test a path in which a non-final component is not a parent node. */
140 mib[1] = KERN_OSTYPE;
141 if ((r = rmib_register(mib, 3, &test_rnode)) != OK)
142 panic("unable to register remote MIB subtree: %d", r);
143 rmib_reset();
145 /* Test a path in which a non-final component is a meta-identifier. */
146 mib[1] = CTL_QUERY;
147 if ((r = rmib_register(mib, 3, &test_rnode)) != OK)
148 panic("unable to register remote MIB subtree: %d", r);
149 rmib_reset();
151 /* Test a path in which the final component is a meta-identifier. */
152 if ((r = rmib_register(mib, 2, &test_rnode)) != OK)
153 panic("unable to register remote MIB subtree: %d", r);
154 rmib_reset();
156 /* Test a path in which the final component identifies a non-parent. */
157 mib[1] = KERN_OSTYPE;
158 if ((r = rmib_register(mib, 2, &test_rnode)) != OK)
159 panic("unable to register remote MIB subtree: %d", r);
160 rmib_reset();
162 /* Test a path with unacceptable flags for the final component. */
163 mib[0] = CTL_MINIX;
164 mib[1] = MINIX_TEST;
165 mib[2] = TEST_SECRET;
166 if ((r = rmib_register(mib, 3, &test_rnode)) != OK)
167 panic("unable to register remote MIB subtree: %d", r);
168 rmib_reset();
170 /* Test a path of which the name, but not the ID, already exists. */
171 mib[1] = CREATE_BASE - 1;
172 if ((r = rmib_register(mib, 2, &test_rnode)) != OK)
173 panic("unable to register remote MIB subtree: %d", r);
175 * Do NOT call rmib_reset() anymore now: we want to let the MIB service
176 * get the name from us.
180 static int
181 init(int type __unused, sef_init_info_t * info __unused)
183 const int new_mib[] = { CTL_MINIX, CREATE_BASE - 2 };
184 const int shadow_mib[] = { CTL_MINIX, MINIX_TEST };
185 int r;
187 test_local_failures();
189 test_remote_failures();
192 * We must now register our new test tree before shadowing minix.test,
193 * because if any of the previous requests actually did succeed, the
194 * next registration will be rejected (ID 0 already in use) and no
195 * difference would be detected because of "successful" shadowing.
197 r = rmib_register(new_mib, __arraycount(new_mib), &minix_rtest);
198 if (r != OK)
199 panic("unable to register remote MIB subtree: %d", r);
201 r = rmib_register(shadow_mib, __arraycount(shadow_mib), &minix_test);
202 if (r != OK)
203 panic("unable to register remote MIB subtree: %d", r);
205 running = TRUE;
207 return OK;
210 static void
211 cleanup(void)
213 int r;
215 if ((r = rmib_deregister(&minix_rtest)) != OK)
216 panic("unable to deregister: %d", r);
217 if ((r = rmib_deregister(&minix_test)) != OK)
218 panic("unable to deregister: %d", r);
221 * TODO: the fact that the MIB service can currently not detect the
222 * death of other services is creating somewhat of a problem here: if
223 * we deregister shortly before exiting, the asynchronous deregister
224 * requests may not be delivered before we actually exit (and take our
225 * asynsend table with us), and leave around the remote subtrees until
226 * a user process tries accessing them. We work around this here by
227 * delaying the exit by half a second - shorter than RS's timeout, but
228 * long enough to allow deregistration.
230 sys_setalarm(sys_hz() / 2, 0);
232 running = FALSE;
235 static void
236 got_signal(int sig)
239 if (sig == SIGTERM && running)
240 cleanup();
244 main(void)
246 message m;
247 int r, ipc_status;
249 sef_setcb_init_fresh(init);
250 sef_setcb_signal_handler(got_signal);
252 sef_startup();
254 for (;;) {
255 r = sef_receive_status(ANY, &m, &ipc_status);
257 if (r != OK)
258 panic("sef_receive_status failed: %d", r);
260 if (m.m_source == CLOCK && is_ipc_notify(ipc_status))
261 break; /* the intended exit path; see above */
262 if (m.m_source == MIB_PROC_NR)
263 rmib_process(&m, ipc_status);
266 return EXIT_SUCCESS;