]> git.ipfire.org Git - thirdparty/systemd.git/commitdiff
test-homectl-prompts: add manual test to exercise prompt functionality
authorZbigniew Jędrzejewski-Szmek <zbyszek@amutable.com>
Tue, 5 May 2026 11:21:30 +0000 (13:21 +0200)
committerZbigniew Jędrzejewski-Szmek <zbyszek@amutable.com>
Tue, 5 May 2026 20:06:41 +0000 (22:06 +0200)
The prompt for groups is nice. The prompt for a shell could use some
love. Looking at this is much easier if we can invoke the code outside
in isolation.

I wrote this when looking at https://github.com/systemd/systemd/pull/41947,
where I wanted to see how the homectl prompt works with the changes.

src/home/meson.build
src/home/test-homectl-prompts.c [new file with mode: 0644]

index 8c644842c1470b05928a32529ece551577144340..600f00b4ac9978253baf55da65c63056c30a1d01 100644 (file)
@@ -47,11 +47,14 @@ systemd_homed_sources += [homed_gperf_c]
 homectl_sources = files(
         'homectl-fido2.c',
         'homectl-pkcs11.c',
-        'homectl-prompts.c',
         'homectl-recovery-key.c',
         'homectl.c',
 )
 
+homectl_extract = files(
+        'homectl-prompts.c',
+)
+
 pam_systemd_home_sources = files(
         'home-util.c',
         'pam_systemd_home.c',
@@ -86,6 +89,7 @@ executables += [
                 'name' : 'homectl',
                 'public' : true,
                 'sources' : homectl_sources,
+                'extract' : homectl_extract,
                 'objects' : ['systemd-homed'],
                 'dependencies' : [
                         libdl,
@@ -94,6 +98,11 @@ executables += [
                         threads,
                 ],
         },
+        test_template + {
+                'sources' : files('test-homectl-prompts.c'),
+                'objects' : ['homectl'],
+                'type' : 'manual',
+        },
         test_template + {
                 'sources' : files('test-homed-regression-31896.c'),
                 'type' : 'manual',
diff --git a/src/home/test-homectl-prompts.c b/src/home/test-homectl-prompts.c
new file mode 100644 (file)
index 0000000..aaa81cc
--- /dev/null
@@ -0,0 +1,106 @@
+/* SPDX-License-Identifier: LGPL-2.1-or-later */
+
+#include "alloc-util.h"
+#include "format-table.h"
+#include "help-util.h"
+#include "homectl-prompts.h"
+#include "main-func.h"
+#include "options.h"
+#include "string-util.h"
+#include "strv.h"
+#include "tests.h"
+#include "verbs.h"
+
+static int help(void) {
+        _cleanup_(table_unrefp) Table *options = NULL, *verbs = NULL;
+        int r;
+
+        r = option_parser_get_help_table(&options);
+        if (r < 0)
+                return r;
+
+        r = verbs_get_help_table(&verbs);
+        if (r < 0)
+                return r;
+
+        (void) table_sync_column_widths(0, options, verbs);
+
+        help_cmdline("[OPTIONS...] VERB [USERNAME]");
+        help_abstract("Exercise homectl prompt functions in isolation.");
+
+        help_section("Verbs");
+        r = table_print_or_warn(verbs);
+        if (r < 0)
+                return r;
+
+        help_section("Options");
+        return table_print_or_warn(options);
+}
+
+VERB(verb_groups, "groups", "[USER]", VERB_ANY, 2, 0, "Select groups");
+static int verb_groups(int argc, char *argv[], uintptr_t _data, void *userdata) {
+        assert(argv);
+
+        const char *username = argv[1] ?: "test";
+        int r;
+
+        _cleanup_strv_free_ char **t = NULL;
+
+        r = prompt_groups(username, &t);
+        if (r < 0)
+                return r;
+
+        _cleanup_free_ char *s = ASSERT_PTR(strv_join(t, ", "));
+        log_info("groups: %s → %s", username, s);
+        return 0;
+}
+
+VERB(verb_shell, "shell", "[USER]", VERB_ANY, 2, 0, "Select shell");
+static int verb_shell(int argc, char *argv[], uintptr_t _data, void *userdata) {
+        assert(argv);
+
+        const char *username = argv[1] ?: "test";
+        int r;
+
+        _cleanup_free_ char *s = NULL;
+
+        r = prompt_shell(username, &s);
+        if (r < 0)
+                return r;
+
+        log_info("shell: %s → %s", username, strnull(s));
+        return 0;
+}
+
+static int parse_argv(int argc, char **argv, char ***remaining_args) {
+        assert(argc >= 0);
+        assert(argv);
+        assert(remaining_args);
+
+        OptionParser opts = { argc, argv };
+
+        FOREACH_OPTION_OR_RETURN(c, &opts)
+                switch (c) {
+
+                OPTION_COMMON_HELP:
+                        return help();
+                }
+
+        *remaining_args = option_parser_get_args(&opts);
+        return 1;
+}
+
+static int run(int argc, char **argv) {
+        int r;
+
+        test_setup_logging(LOG_DEBUG);
+
+        char **args = NULL;
+        r = parse_argv(argc, argv, &args);
+        if (r <= 0)
+                return r;
+
+        return dispatch_verb_with_args(args, /* userdata= */ NULL);
+}
+
+DEFINE_MAIN_FUNCTION(run);