summaryrefslogtreecommitdiff
path: root/lib9p/tests
diff options
context:
space:
mode:
authorLuke T. Shumaker <lukeshu@lukeshu.com>2025-02-04 09:05:14 -0700
committerLuke T. Shumaker <lukeshu@lukeshu.com>2025-02-04 21:01:49 -0700
commit57d4c9f154cacd5d0dcc2f45033d784b3e0b6734 (patch)
treef96f5c57bbb042b3962bed49853621f6d344de04 /lib9p/tests
parent635539cd0da713729ec2852b3691dc9f73734e59 (diff)
lib9p: Test that we can do clean shutdown
Diffstat (limited to 'lib9p/tests')
-rwxr-xr-xlib9p/tests/runtest9
-rw-r--r--lib9p/tests/test_server/main.c105
2 files changed, 95 insertions, 19 deletions
diff --git a/lib9p/tests/runtest b/lib9p/tests/runtest
index 29d2089..d963c53 100755
--- a/lib9p/tests/runtest
+++ b/lib9p/tests/runtest
@@ -26,7 +26,8 @@ while [[ -d /proc/$server_pid && "$(readlink /proc/$server_pid/fd/4 2>/dev/null)
out=$("${client[@]}" ls -l '')
expect_lines \
'd-r-xr-xr-x M 0 root root 0 Oct 7 15:51 Documentation' \
- '--r--r--r-- M 0 root root 14 Oct 7 15:51 README.md'
+ '--r--r--r-- M 0 root root 14 Oct 7 15:51 README.md' \
+ '---w--w--w- M 0 root root 0 Oct 7 15:51 shutdown'
out=$("${client[@]}" ls -l 'Documentation/')
expect_lines \
@@ -43,3 +44,9 @@ expect_lines \
out=$("${client[@]}" stat 'Documentation/x')
expect_lines \
"'x' 'root' 'root' 'root' q (0000000000000009 1 ) m 0444 at 1728337905 mt 1728337904 l 4 t 0 d 0"
+
+out=$("${client[@]}" write 'shutdown' <<<1)
+expect_lines ''
+
+wait "$server_pid"
+trap - EXIT
diff --git a/lib9p/tests/test_server/main.c b/lib9p/tests/test_server/main.c
index 8e5011a..71c6cc2 100644
--- a/lib9p/tests/test_server/main.c
+++ b/lib9p/tests/test_server/main.c
@@ -24,7 +24,80 @@
#error config.h must define CONFIG_SRV9P_NUM_CONNS
#endif
-/* implementation *************************************************************/
+/* globals ********************************************************************/
+
+static implements_lib9p_srv_file *get_root(struct lib9p_srv_ctx *, struct lib9p_s);
+
+const char *hexdig = "0123456789abcdef";
+
+struct {
+ struct hostnet_tcp_listener listeners[CONFIG_SRV9P_NUM_CONNS];
+ struct lib9p_srv srv;
+} globals = {
+ .srv = (struct lib9p_srv){
+ .rootdir = get_root,
+ },
+};
+
+/* api ************************************************************************/
+
+struct api_file {
+ implements_lib9p_srv_file;
+
+ uint64_t pathnum;
+};
+
+static implements_lib9p_srv_file *api_clone(implements_lib9p_srv_file *self, struct lib9p_srv_ctx *) { return self; }
+static void api_free(implements_lib9p_srv_file *, struct lib9p_srv_ctx *) {}
+
+static uint32_t api_io(implements_lib9p_srv_file *, struct lib9p_srv_ctx *, lib9p_o_t) { return 0; }
+static void api_wstat(implements_lib9p_srv_file *, struct lib9p_srv_ctx *ctx, struct lib9p_stat) { lib9p_error(&ctx->basectx, LINUX_EROFS, "cannot wstat API file"); }
+static void api_remove(implements_lib9p_srv_file *, struct lib9p_srv_ctx *ctx) { lib9p_error(&ctx->basectx, LINUX_EROFS, "cannot remove API file"); }
+
+static struct lib9p_stat api_stat(implements_lib9p_srv_file *_self, struct lib9p_srv_ctx *) {
+ struct api_file *self = VCALL_SELF(struct api_file, implements_lib9p_srv_file, _self);
+ return (struct lib9p_stat){
+ .kern_type = 0,
+ .kern_dev = 0,
+ .file_qid = {
+ .type = LIB9P_QT_FILE,
+ .vers = 1,
+ .path = self->pathnum,
+ },
+ .file_mode = 0222,
+ .file_atime = 1728337905,
+ .file_mtime = 1728337904,
+ .file_size = 0,
+ .file_name = lib9p_str("shutdown"),
+ .file_owner_uid = lib9p_str("root"),
+ .file_owner_gid = lib9p_str("root"),
+ .file_last_modified_uid = lib9p_str("root"),
+ .file_extension = lib9p_str(NULL),
+ .file_owner_n_uid = 0,
+ .file_owner_n_gid = 0,
+ .file_last_modified_n_uid = 0,
+ };
+}
+static uint32_t api_pwrite(implements_lib9p_srv_file *, struct lib9p_srv_ctx *, void *, uint32_t byte_count, uint64_t) {
+ if (byte_count == 0)
+ return 0;
+ for (int i = 0; i < CONFIG_SRV9P_NUM_CONNS; i++)
+ VCALL(&globals.listeners[i], close);
+ return byte_count;
+}
+
+static struct lib9p_srv_file_vtable api_file_vtable = {
+ .clone = api_clone,
+ .free = api_free,
+
+ .io = api_io,
+ .stat = api_stat,
+ .wstat = api_wstat,
+ .remove = api_remove,
+
+ .pread = NULL,
+ .pwrite = api_pwrite,
+};
/* file tree ******************************************************************/
@@ -74,6 +147,10 @@ static struct util9p_static_dir root = {
},
}),
STATIC_FILE("README.md", README_md),
+ &((struct api_file){
+ .vtable = &api_file_vtable,
+ .pathnum = __COUNTER__,
+ }),
NULL,
},
};
@@ -84,26 +161,17 @@ static implements_lib9p_srv_file *get_root(struct lib9p_srv_ctx *LM_UNUSED(ctx),
/* main ***********************************************************************/
-static COROUTINE read_cr(void *_srv) {
- struct lib9p_srv *srv = _srv;
- assert(srv);
-
+static COROUTINE read_cr(void *_i) {
+ int i = *((int *)_i);
cr_begin();
- struct hostnet_tcp_listener listener;
- hostnet_tcp_listener_init(&listener, 9000);
+ hostnet_tcp_listener_init(&globals.listeners[i], 9000);
- lib9p_srv_read_cr(srv, &listener);
+ lib9p_srv_read_cr(&globals.srv, &globals.listeners[i]);
cr_end();
}
-const char *hexdig = "0123456789abcdef";
-
-struct lib9p_srv srv = {
- .rootdir = get_root,
-};
-
static COROUTINE init_cr(void *) {
cr_begin();
@@ -111,13 +179,13 @@ static COROUTINE init_cr(void *) {
for (int i = 0; i < CONFIG_SRV9P_NUM_CONNS; i++) {
char name[] = {'r', 'e', 'a', 'd', '-', hexdig[i], '\0'};
- if (!coroutine_add(name, read_cr, &srv))
- error(1, 0, "coroutine_add(read_cr, &srv)");
+ if (!coroutine_add(name, read_cr, &i))
+ error(1, 0, "coroutine_add(read_cr, &i)");
}
for (int i = 0; i < 2*CONFIG_SRV9P_NUM_CONNS; i++) {
char name[] = {'w', 'r', 'i', 't', 'e', '-', hexdig[i], '\0'};
- if (!coroutine_add(name, lib9p_srv_write_cr, &srv))
- error(1, 0, "coroutine_add(lib9p_srv_write_cr, &srv)");
+ if (!coroutine_add(name, lib9p_srv_write_cr, &globals.srv))
+ error(1, 0, "coroutine_add(lib9p_srv_write_cr, &globals.srv)");
}
cr_exit();
@@ -126,4 +194,5 @@ static COROUTINE init_cr(void *) {
int main() {
coroutine_add("init", init_cr, NULL);
coroutine_main();
+ return 0;
}