static int setup_test(Manager **m) { char **tests_path = STRV_MAKE("exists", "existsglobFOOBAR", "changed", "modified", "unit", "directorynotempty", "makedirectory"); char **test_path; Manager *tmp = NULL; int r; assert_se(m); r = enter_cgroup_subroot(); if (r == -ENOMEDIUM) { log_notice_errno(r, "Skipping test: cgroupfs not available"); return -EXIT_TEST_SKIP; } r = manager_new(UNIT_FILE_USER, MANAGER_TEST_RUN_BASIC, &tmp); if (MANAGER_SKIP_TEST(r)) { log_notice_errno(r, "Skipping test: manager_new: %m"); return -EXIT_TEST_SKIP; } assert_se(r >= 0); assert_se(manager_startup(tmp, NULL, NULL) >= 0); STRV_FOREACH(test_path, tests_path) { _cleanup_free_ char *p = NULL; p = strjoin("/tmp/test-path_", *test_path); assert_se(p); (void) rm_rf(p, REMOVE_ROOT|REMOVE_PHYSICAL); }
static int setup_test(Manager **m) { char **tests_path = STRV_MAKE("exists", "existsglobFOOBAR", "changed", "modified", "unit", "directorynotempty", "makedirectory"); char **test_path; Manager *tmp = NULL; int r; assert_se(m); r = manager_new(MANAGER_USER, true, &tmp); if (IN_SET(r, -EPERM, -EACCES, -EADDRINUSE, -EHOSTDOWN, -ENOENT, -ENOEXEC)) { printf("Skipping test: manager_new: %s", strerror(-r)); return -EXIT_TEST_SKIP; } assert_se(r >= 0); assert_se(manager_startup(tmp, NULL, NULL) >= 0); STRV_FOREACH(test_path, tests_path) { _cleanup_free_ char *p = NULL; p = strjoin("/tmp/test-path_", *test_path, NULL); assert_se(p); (void) rm_rf(p, REMOVE_ROOT|REMOVE_PHYSICAL); }
int main(int argc, char *argv[]) { Manager *m = NULL; int r; log_set_target(LOG_TARGET_AUTO); log_set_facility(LOG_AUTH); log_parse_environment(); log_open(); umask(0022); if (argc != 1) { log_error("This program takes no arguments."); r = -EINVAL; goto finish; } /* Always create the directories people can create inotify * watches in. Note that some applications might check for the * existence of /run/systemd/machines/ to determine whether * machined is available, so please always make sure this * check stays in. */ mkdir_label("/run/systemd/machines", 0755); m = manager_new(); if (!m) { r = log_oom(); goto finish; } r = manager_startup(m); if (r < 0) { log_error("Failed to fully start up daemon: %s", strerror(-r)); goto finish; } log_debug("systemd-machined running as pid "PID_FMT, getpid()); sd_notify(false, "READY=1\n" "STATUS=Processing requests..."); r = manager_run(m); log_debug("systemd-machined stopped as pid "PID_FMT, getpid()); finish: sd_notify(false, "STOPPING=1\n" "STATUS=Shutting down..."); if (m) manager_free(m); return r < 0 ? EXIT_FAILURE : EXIT_SUCCESS; }
int main(int argc, char *argv[]) { _cleanup_(manager_unrefp) Manager *m = NULL; int r; log_set_target(LOG_TARGET_AUTO); log_set_facility(LOG_AUTH); log_parse_environment(); log_open(); umask(0022); if (argc != 1) { log_error("This program takes no arguments."); r = -EINVAL; goto finish; } /* Always create the directories people can create inotify watches in. Note that some applications might check * for the existence of /run/systemd/machines/ to determine whether machined is available, so please always * make sure this check stays in. */ (void) mkdir_label("/run/systemd/machines", 0755); assert_se(sigprocmask_many(SIG_BLOCK, NULL, SIGCHLD, SIGTERM, SIGINT, -1) >= 0); r = manager_new(&m); if (r < 0) { log_error_errno(r, "Failed to allocate manager object: %m"); goto finish; } r = manager_startup(m); if (r < 0) { log_error_errno(r, "Failed to fully start up daemon: %m"); goto finish; } log_debug("systemd-machined running as pid "PID_FMT, getpid_cached()); (void) sd_notify(false, "READY=1\n" "STATUS=Processing requests..."); r = manager_run(m); log_debug("systemd-machined stopped as pid "PID_FMT, getpid_cached()); (void) sd_notify(false, "STOPPING=1\n" "STATUS=Shutting down..."); finish: return r < 0 ? EXIT_FAILURE : EXIT_SUCCESS; }
int main(int argc, char *argv[]) { test_function_t tests[] = { test_exec_workingdirectory, test_exec_personality, test_exec_ignoresigpipe, test_exec_privatetmp, test_exec_privatedevices, test_exec_systemcallfilter, test_exec_systemcallerrornumber, test_exec_user, test_exec_group, test_exec_environment, test_exec_umask, test_exec_runtimedirectory, NULL, }; test_function_t *test = NULL; Manager *m = NULL; int r; log_parse_environment(); log_open(); /* It is needed otherwise cgroup creation fails */ if (getuid() != 0) { printf("Skipping test: not root\n"); return EXIT_TEST_SKIP; } assert_se(setenv("XDG_RUNTIME_DIR", "/tmp/", 1) == 0); assert_se(set_unit_path(TEST_DIR ":") >= 0); r = manager_new(SYSTEMD_USER, true, &m); if (IN_SET(r, -EPERM, -EACCES, -EADDRINUSE, -EHOSTDOWN, -ENOENT)) { printf("Skipping test: manager_new: %s", strerror(-r)); return EXIT_TEST_SKIP; } assert_se(r >= 0); assert_se(manager_startup(m, NULL, NULL) >= 0); for (test = tests; test && *test; test++) (*test)(m); manager_free(m); return 0; }
static int test_cgroup_mask(void) { Manager *m; Unit *son, *daughter, *parent, *root; FILE *serial = NULL; FDSet *fdset = NULL; int r; const char *dir = TEST_DIR; /* Prepare the manager. */ assert_se(set_unit_path(dir) >= 0); r = manager_new(SYSTEMD_USER, &m); if (r == -EPERM || r == -EACCES) { puts("manager_new: Permission denied. Skipping test."); return EXIT_TEST_SKIP; } assert(r >= 0); assert_se(manager_startup(m, serial, fdset) >= 0); /* Load units and verify hierarchy. */ assert_se(manager_load_unit(m, "parent.slice", NULL, NULL, &parent) >= 0); assert_se(manager_load_unit(m, "son.service", NULL, NULL, &son) >= 0); assert_se(manager_load_unit(m, "daughter.service", NULL, NULL, &daughter) >= 0); assert(parent->load_state == UNIT_LOADED); assert(son->load_state == UNIT_LOADED); assert(daughter->load_state == UNIT_LOADED); assert(UNIT_DEREF(son->slice) == parent); assert(UNIT_DEREF(daughter->slice) == parent); root = UNIT_DEREF(parent->slice); /* Verify per-unit cgroups settings. */ assert(cgroup_context_get_mask(unit_get_cgroup_context(son)) == (CGROUP_CPU | CGROUP_CPUACCT)); assert(cgroup_context_get_mask(unit_get_cgroup_context(daughter)) == 0); assert(cgroup_context_get_mask(unit_get_cgroup_context(parent)) == CGROUP_BLKIO); assert(cgroup_context_get_mask(unit_get_cgroup_context(root)) == 0); /* Verify aggregation of controller masks. */ assert(son->cgroup_members_mask == (CGROUP_CPU | CGROUP_CPUACCT)); assert(daughter->cgroup_members_mask == 0); assert(parent->cgroup_members_mask == (CGROUP_CPU | CGROUP_CPUACCT | CGROUP_BLKIO)); assert(root->cgroup_members_mask == (CGROUP_CPU | CGROUP_CPUACCT | CGROUP_BLKIO)); manager_free(m); return 0; }
static int setup_test(Manager **m) { char **tests_path = STRV_MAKE("exists", "existsglobFOOBAR", "changed", "modified", "unit", "directorynotempty", "makedirectory"); char **test_path; Manager *tmp; int r; assert_se(m); r = manager_new(SYSTEMD_USER, true, &tmp); if (IN_SET(r, -EPERM, -EACCES, -EADDRINUSE, -EHOSTDOWN, -ENOENT)) { printf("Skipping test: manager_new: %s", strerror(-r)); return -EXIT_TEST_SKIP; } assert_se(r >= 0); assert_se(manager_startup(tmp, NULL, NULL) >= 0); STRV_FOREACH(test_path, tests_path) { rm_rf_dangerous(strappenda("/tmp/test-path_", *test_path), false, true, false); }
static int run_tests(UnitFileScope scope, test_function_t *tests) { test_function_t *test = NULL; Manager *m = NULL; int r; assert_se(tests); r = manager_new(scope, true, &m); if (MANAGER_SKIP_TEST(r)) { printf("Skipping test: manager_new: %s\n", strerror(-r)); return EXIT_TEST_SKIP; } assert_se(r >= 0); assert_se(manager_startup(m, NULL, NULL) >= 0); for (test = tests; test && *test; test++) (*test)(m); manager_free(m); return 0; }
static void test_config_parse_exec(void) { /* int config_parse_exec( const char *unit, const char *filename, unsigned line, const char *section, unsigned section_line, const char *lvalue, int ltype, const char *rvalue, void *data, void *userdata) */ int r; ExecCommand *c = NULL, *c1; const char *ccc; Manager *m = NULL; Unit *u = NULL; r = manager_new(UNIT_FILE_USER, MANAGER_TEST_RUN_MINIMAL, &m); if (MANAGER_SKIP_TEST(r)) { log_notice_errno(r, "Skipping test: manager_new: %m"); return; } assert_se(r >= 0); assert_se(manager_startup(m, NULL, NULL) >= 0); assert_se(u = unit_new(m, sizeof(Service))); log_info("/* basic test */"); r = config_parse_exec(NULL, "fake", 1, "section", 1, "LValue", 0, "/RValue r1", &c, u); assert_se(r >= 0); check_execcommand(c, "/RValue", "/RValue", "r1", NULL, false); r = config_parse_exec(NULL, "fake", 2, "section", 1, "LValue", 0, "/RValue///slashes r1///", &c, u); log_info("/* test slashes */"); assert_se(r >= 0); c1 = c->command_next; check_execcommand(c1, "/RValue/slashes", "/RValue///slashes", "r1///", NULL, false); log_info("/* trailing slash */"); r = config_parse_exec(NULL, "fake", 4, "section", 1, "LValue", 0, "/RValue/ argv0 r1", &c, u); assert_se(r == -ENOEXEC); assert_se(c1->command_next == NULL); log_info("/* honour_argv0 */"); r = config_parse_exec(NULL, "fake", 3, "section", 1, "LValue", 0, "@/RValue///slashes2 ///argv0 r1", &c, u); assert_se(r >= 0); c1 = c1->command_next; check_execcommand(c1, "/RValue/slashes2", "///argv0", "r1", NULL, false); log_info("/* honour_argv0, no args */"); r = config_parse_exec(NULL, "fake", 3, "section", 1, "LValue", 0, "@/RValue", &c, u); assert_se(r == -ENOEXEC); assert_se(c1->command_next == NULL); log_info("/* no command, whitespace only, reset */"); r = config_parse_exec(NULL, "fake", 3, "section", 1, "LValue", 0, " ", &c, u); assert_se(r == 0); assert_se(c == NULL); log_info("/* ignore && honour_argv0 */"); r = config_parse_exec(NULL, "fake", 4, "section", 1, "LValue", 0, "-@/RValue///slashes3 argv0a r1", &c, u); assert_se(r >= 0); c1 = c; check_execcommand(c1, "/RValue/slashes3", "argv0a", "r1", NULL, true); log_info("/* ignore && honour_argv0 */"); r = config_parse_exec(NULL, "fake", 4, "section", 1, "LValue", 0, "@-/RValue///slashes4 argv0b r1", &c, u); assert_se(r >= 0); c1 = c1->command_next; check_execcommand(c1, "/RValue/slashes4", "argv0b", "r1", NULL, true); log_info("/* ignore && ignore */"); r = config_parse_exec(NULL, "fake", 4, "section", 1, "LValue", 0, "--/RValue argv0 r1", &c, u); assert_se(r == 0); assert_se(c1->command_next == NULL); log_info("/* ignore && ignore (2) */"); r = config_parse_exec(NULL, "fake", 4, "section", 1, "LValue", 0, "-@-/RValue argv0 r1", &c, u); assert_se(r == 0); assert_se(c1->command_next == NULL); log_info("/* semicolon */"); r = config_parse_exec(NULL, "fake", 5, "section", 1, "LValue", 0, "-@/RValue argv0 r1 ; " "/goo/goo boo", &c, u); assert_se(r >= 0); c1 = c1->command_next; check_execcommand(c1, "/RValue", "argv0", "r1", NULL, true); c1 = c1->command_next; check_execcommand(c1, "/goo/goo", NULL, "boo", NULL, false); log_info("/* two semicolons in a row */"); r = config_parse_exec(NULL, "fake", 5, "section", 1, "LValue", 0, "-@/RValue argv0 r1 ; ; " "/goo/goo boo", &c, u); assert_se(r == -ENOEXEC); c1 = c1->command_next; check_execcommand(c1, "/RValue", "argv0", "r1", NULL, true); /* second command fails because the executable name is ";" */ assert_se(c1->command_next == NULL); log_info("/* trailing semicolon */"); r = config_parse_exec(NULL, "fake", 5, "section", 1, "LValue", 0, "-@/RValue argv0 r1 ; ", &c, u); assert_se(r >= 0); c1 = c1->command_next; check_execcommand(c1, "/RValue", "argv0", "r1", NULL, true); assert_se(c1->command_next == NULL); log_info("/* trailing semicolon, no whitespace */"); r = config_parse_exec(NULL, "fake", 5, "section", 1, "LValue", 0, "-@/RValue argv0 r1 ;", &c, u); assert_se(r >= 0); c1 = c1->command_next; check_execcommand(c1, "/RValue", "argv0", "r1", NULL, true); assert_se(c1->command_next == NULL); log_info("/* trailing semicolon in single quotes */"); r = config_parse_exec(NULL, "fake", 5, "section", 1, "LValue", 0, "-@/RValue argv0 r1 ';'", &c, u); assert_se(r >= 0); c1 = c1->command_next; check_execcommand(c1, "/RValue", "argv0", "r1", ";", true); log_info("/* escaped semicolon */"); r = config_parse_exec(NULL, "fake", 5, "section", 1, "LValue", 0, "/bin/find \\;", &c, u); assert_se(r >= 0); c1 = c1->command_next; check_execcommand(c1, "/bin/find", NULL, ";", NULL, false); log_info("/* escaped semicolon with following arg */"); r = config_parse_exec(NULL, "fake", 5, "section", 1, "LValue", 0, "/sbin/find \\; /x", &c, u); assert_se(r >= 0); c1 = c1->command_next; check_execcommand(c1, "/sbin/find", NULL, ";", "/x", false); log_info("/* escaped semicolon as part of an expression */"); r = config_parse_exec(NULL, "fake", 5, "section", 1, "LValue", 0, "/sbin/find \\;x", &c, u); assert_se(r >= 0); c1 = c1->command_next; check_execcommand(c1, "/sbin/find", NULL, "\\;x", NULL, false); log_info("/* encoded semicolon */"); r = config_parse_exec(NULL, "fake", 5, "section", 1, "LValue", 0, "/bin/find \\073", &c, u); assert_se(r >= 0); c1 = c1->command_next; check_execcommand(c1, "/bin/find", NULL, ";", NULL, false); log_info("/* quoted semicolon */"); r = config_parse_exec(NULL, "fake", 5, "section", 1, "LValue", 0, "/bin/find \";\"", &c, u); assert_se(r >= 0); c1 = c1->command_next; check_execcommand(c1, "/bin/find", NULL, ";", NULL, false); log_info("/* quoted semicolon with following arg */"); r = config_parse_exec(NULL, "fake", 5, "section", 1, "LValue", 0, "/sbin/find \";\" /x", &c, u); assert_se(r >= 0); c1 = c1->command_next; check_execcommand(c1, "/sbin/find", NULL, ";", "/x", false); log_info("/* spaces in the filename */"); r = config_parse_exec(NULL, "fake", 5, "section", 1, "LValue", 0, "\"/PATH WITH SPACES/daemon\" -1 -2", &c, u); assert_se(r >= 0); c1 = c1->command_next; check_execcommand(c1, "/PATH WITH SPACES/daemon", NULL, "-1", "-2", false); log_info("/* spaces in the filename, no args */"); r = config_parse_exec(NULL, "fake", 5, "section", 1, "LValue", 0, "\"/PATH WITH SPACES/daemon -1 -2\"", &c, u); assert_se(r >= 0); c1 = c1->command_next; check_execcommand(c1, "/PATH WITH SPACES/daemon -1 -2", NULL, NULL, NULL, false); log_info("/* spaces in the filename, everything quoted */"); r = config_parse_exec(NULL, "fake", 5, "section", 1, "LValue", 0, "\"/PATH WITH SPACES/daemon\" \"-1\" '-2'", &c, u); assert_se(r >= 0); c1 = c1->command_next; check_execcommand(c1, "/PATH WITH SPACES/daemon", NULL, "-1", "-2", false); log_info("/* escaped spaces in the filename */"); r = config_parse_exec(NULL, "fake", 5, "section", 1, "LValue", 0, "\"/PATH\\sWITH\\sSPACES/daemon\" '-1 -2'", &c, u); assert_se(r >= 0); c1 = c1->command_next; check_execcommand(c1, "/PATH WITH SPACES/daemon", NULL, "-1 -2", NULL, false); log_info("/* escaped spaces in the filename (2) */"); r = config_parse_exec(NULL, "fake", 5, "section", 1, "LValue", 0, "\"/PATH\\x20WITH\\x20SPACES/daemon\" \"-1 -2\"", &c, u); assert_se(r >= 0); c1 = c1->command_next; check_execcommand(c1, "/PATH WITH SPACES/daemon", NULL, "-1 -2", NULL, false); for (ccc = "abfnrtv\\\'\"x"; *ccc; ccc++) { /* \\x is an incomplete hexadecimal sequence, invalid because of the slash */ char path[] = "/path\\X"; path[sizeof(path) - 2] = *ccc; log_info("/* invalid character: \\%c */", *ccc); r = config_parse_exec(NULL, "fake", 4, "section", 1, "LValue", 0, path, &c, u); assert_se(r == -ENOEXEC); assert_se(c1->command_next == NULL); } log_info("/* valid character: \\s */"); r = config_parse_exec(NULL, "fake", 4, "section", 1, "LValue", 0, "/path\\s", &c, u); assert_se(r >= 0); c1 = c1->command_next; check_execcommand(c1, "/path ", NULL, NULL, NULL, false); log_info("/* quoted backslashes */"); r = config_parse_exec(NULL, "fake", 5, "section", 1, "LValue", 0, "/bin/grep '\\w+\\K'", &c, u); assert_se(r >= 0); c1 = c1->command_next; check_execcommand(c1, "/bin/grep", NULL, "\\w+\\K", NULL, false); log_info("/* trailing backslash: \\ */"); /* backslash is invalid */ r = config_parse_exec(NULL, "fake", 4, "section", 1, "LValue", 0, "/path\\", &c, u); assert_se(r == -ENOEXEC); assert_se(c1->command_next == NULL); log_info("/* missing ending ' */"); r = config_parse_exec(NULL, "fake", 4, "section", 1, "LValue", 0, "/path 'foo", &c, u); assert_se(r == -ENOEXEC); assert_se(c1->command_next == NULL); log_info("/* missing ending ' with trailing backslash */"); r = config_parse_exec(NULL, "fake", 4, "section", 1, "LValue", 0, "/path 'foo\\", &c, u); assert_se(r == -ENOEXEC); assert_se(c1->command_next == NULL); log_info("/* invalid space between modifiers */"); r = config_parse_exec(NULL, "fake", 4, "section", 1, "LValue", 0, "- /path", &c, u); assert_se(r == 0); assert_se(c1->command_next == NULL); log_info("/* only modifiers, no path */"); r = config_parse_exec(NULL, "fake", 4, "section", 1, "LValue", 0, "-", &c, u); assert_se(r == 0); assert_se(c1->command_next == NULL); log_info("/* empty argument, reset */"); r = config_parse_exec(NULL, "fake", 4, "section", 1, "LValue", 0, "", &c, u); assert_se(r == 0); assert_se(c == NULL); exec_command_free_list(c); unit_free(u); manager_free(m); }
int main(int argc, char *argv[]) { _cleanup_(sd_bus_error_free) sd_bus_error err = SD_BUS_ERROR_NULL; Manager *m = NULL; Unit *a = NULL, *b = NULL, *c = NULL, *d = NULL, *e = NULL, *g = NULL, *h = NULL; FILE *serial = NULL; FDSet *fdset = NULL; Job *j; int r; /* prepare the test */ assert_se(set_unit_path(TEST_DIR) >= 0); r = manager_new(MANAGER_USER, true, &m); if (IN_SET(r, -EPERM, -EACCES, -EADDRINUSE, -EHOSTDOWN, -ENOENT, -ENOEXEC)) { printf("Skipping test: manager_new: %s", strerror(-r)); return EXIT_TEST_SKIP; } assert_se(r >= 0); assert_se(manager_startup(m, serial, fdset) >= 0); printf("Load1:\n"); assert_se(manager_load_unit(m, "a.service", NULL, NULL, &a) >= 0); assert_se(manager_load_unit(m, "b.service", NULL, NULL, &b) >= 0); assert_se(manager_load_unit(m, "c.service", NULL, NULL, &c) >= 0); manager_dump_units(m, stdout, "\t"); printf("Test1: (Trivial)\n"); r = manager_add_job(m, JOB_START, c, JOB_REPLACE, &err, &j); if (sd_bus_error_is_set(&err)) log_error("error: %s: %s", err.name, err.message); assert_se(r == 0); manager_dump_jobs(m, stdout, "\t"); printf("Load2:\n"); manager_clear_jobs(m); assert_se(manager_load_unit(m, "d.service", NULL, NULL, &d) >= 0); assert_se(manager_load_unit(m, "e.service", NULL, NULL, &e) >= 0); manager_dump_units(m, stdout, "\t"); printf("Test2: (Cyclic Order, Unfixable)\n"); assert_se(manager_add_job(m, JOB_START, d, JOB_REPLACE, NULL, &j) == -EDEADLK); manager_dump_jobs(m, stdout, "\t"); printf("Test3: (Cyclic Order, Fixable, Garbage Collector)\n"); assert_se(manager_add_job(m, JOB_START, e, JOB_REPLACE, NULL, &j) == 0); manager_dump_jobs(m, stdout, "\t"); printf("Test4: (Identical transaction)\n"); assert_se(manager_add_job(m, JOB_START, e, JOB_FAIL, NULL, &j) == 0); manager_dump_jobs(m, stdout, "\t"); printf("Load3:\n"); assert_se(manager_load_unit(m, "g.service", NULL, NULL, &g) >= 0); manager_dump_units(m, stdout, "\t"); printf("Test5: (Colliding transaction, fail)\n"); assert_se(manager_add_job(m, JOB_START, g, JOB_FAIL, NULL, &j) == -EDEADLK); printf("Test6: (Colliding transaction, replace)\n"); assert_se(manager_add_job(m, JOB_START, g, JOB_REPLACE, NULL, &j) == 0); manager_dump_jobs(m, stdout, "\t"); printf("Test7: (Unmergeable job type, fail)\n"); assert_se(manager_add_job(m, JOB_STOP, g, JOB_FAIL, NULL, &j) == -EDEADLK); printf("Test8: (Mergeable job type, fail)\n"); assert_se(manager_add_job(m, JOB_RESTART, g, JOB_FAIL, NULL, &j) == 0); manager_dump_jobs(m, stdout, "\t"); printf("Test9: (Unmergeable job type, replace)\n"); assert_se(manager_add_job(m, JOB_STOP, g, JOB_REPLACE, NULL, &j) == 0); manager_dump_jobs(m, stdout, "\t"); printf("Load4:\n"); assert_se(manager_load_unit(m, "h.service", NULL, NULL, &h) >= 0); manager_dump_units(m, stdout, "\t"); printf("Test10: (Unmergeable job type of auxiliary job, fail)\n"); assert_se(manager_add_job(m, JOB_START, h, JOB_FAIL, NULL, &j) == 0); manager_dump_jobs(m, stdout, "\t"); manager_free(m); return 0; }
static int test_cgroup_mask(void) { Manager *m = NULL; Unit *son, *daughter, *parent, *root, *grandchild, *parent_deep; FILE *serial = NULL; FDSet *fdset = NULL; int r; /* Prepare the manager. */ assert_se(set_unit_path(TEST_DIR) >= 0); r = manager_new(MANAGER_USER, true, &m); if (r == -EPERM || r == -EACCES) { puts("manager_new: Permission denied. Skipping test."); return EXIT_TEST_SKIP; } assert_se(r >= 0); /* Turn off all kinds of default accouning, so that we can * verify the masks resulting of our configuration and nothing * else. */ m->default_cpu_accounting = m->default_memory_accounting = m->default_blockio_accounting = m->default_tasks_accounting = false; m->default_tasks_max = (uint64_t) -1; assert_se(r >= 0); assert_se(manager_startup(m, serial, fdset) >= 0); /* Load units and verify hierarchy. */ assert_se(manager_load_unit(m, "parent.slice", NULL, NULL, &parent) >= 0); assert_se(manager_load_unit(m, "son.service", NULL, NULL, &son) >= 0); assert_se(manager_load_unit(m, "daughter.service", NULL, NULL, &daughter) >= 0); assert_se(manager_load_unit(m, "grandchild.service", NULL, NULL, &grandchild) >= 0); assert_se(manager_load_unit(m, "parent-deep.slice", NULL, NULL, &parent_deep) >= 0); assert_se(parent->load_state == UNIT_LOADED); assert_se(son->load_state == UNIT_LOADED); assert_se(daughter->load_state == UNIT_LOADED); assert_se(grandchild->load_state == UNIT_LOADED); assert_se(parent_deep->load_state == UNIT_LOADED); assert_se(UNIT_DEREF(son->slice) == parent); assert_se(UNIT_DEREF(daughter->slice) == parent); assert_se(UNIT_DEREF(parent_deep->slice) == parent); assert_se(UNIT_DEREF(grandchild->slice) == parent_deep); root = UNIT_DEREF(parent->slice); /* Verify per-unit cgroups settings. */ assert_se(unit_get_own_mask(son) == (CGROUP_MASK_CPU | CGROUP_MASK_CPUACCT)); assert_se(unit_get_own_mask(daughter) == 0); assert_se(unit_get_own_mask(grandchild) == 0); assert_se(unit_get_own_mask(parent_deep) == CGROUP_MASK_MEMORY); assert_se(unit_get_own_mask(parent) == CGROUP_MASK_BLKIO); assert_se(unit_get_own_mask(root) == 0); /* Verify aggregation of member masks */ assert_se(unit_get_members_mask(son) == 0); assert_se(unit_get_members_mask(daughter) == 0); assert_se(unit_get_members_mask(grandchild) == 0); assert_se(unit_get_members_mask(parent_deep) == 0); assert_se(unit_get_members_mask(parent) == (CGROUP_MASK_CPU | CGROUP_MASK_CPUACCT | CGROUP_MASK_MEMORY)); assert_se(unit_get_members_mask(root) == (CGROUP_MASK_CPU | CGROUP_MASK_CPUACCT | CGROUP_MASK_BLKIO | CGROUP_MASK_MEMORY)); /* Verify aggregation of sibling masks. */ assert_se(unit_get_siblings_mask(son) == (CGROUP_MASK_CPU | CGROUP_MASK_CPUACCT | CGROUP_MASK_MEMORY)); assert_se(unit_get_siblings_mask(daughter) == (CGROUP_MASK_CPU | CGROUP_MASK_CPUACCT | CGROUP_MASK_MEMORY)); assert_se(unit_get_siblings_mask(grandchild) == 0); assert_se(unit_get_siblings_mask(parent_deep) == (CGROUP_MASK_CPU | CGROUP_MASK_CPUACCT | CGROUP_MASK_MEMORY)); assert_se(unit_get_siblings_mask(parent) == (CGROUP_MASK_CPU | CGROUP_MASK_CPUACCT | CGROUP_MASK_BLKIO | CGROUP_MASK_MEMORY)); assert_se(unit_get_siblings_mask(root) == (CGROUP_MASK_CPU | CGROUP_MASK_CPUACCT | CGROUP_MASK_BLKIO | CGROUP_MASK_MEMORY)); /* Verify aggregation of target masks. */ assert_se(unit_get_target_mask(son) == ((CGROUP_MASK_CPU | CGROUP_MASK_CPUACCT | CGROUP_MASK_MEMORY) & m->cgroup_supported)); assert_se(unit_get_target_mask(daughter) == ((CGROUP_MASK_CPU | CGROUP_MASK_CPUACCT | CGROUP_MASK_MEMORY) & m->cgroup_supported)); assert_se(unit_get_target_mask(grandchild) == 0); assert_se(unit_get_target_mask(parent_deep) == ((CGROUP_MASK_CPU | CGROUP_MASK_CPUACCT | CGROUP_MASK_MEMORY) & m->cgroup_supported)); assert_se(unit_get_target_mask(parent) == ((CGROUP_MASK_CPU | CGROUP_MASK_CPUACCT | CGROUP_MASK_BLKIO | CGROUP_MASK_MEMORY) & m->cgroup_supported)); assert_se(unit_get_target_mask(root) == ((CGROUP_MASK_CPU | CGROUP_MASK_CPUACCT | CGROUP_MASK_BLKIO | CGROUP_MASK_MEMORY) & m->cgroup_supported)); manager_free(m); return 0; }
static void test_config_parse_log_extra_fields(void) { /* int config_parse_log_extra_fields( const char *unit, const char *filename, unsigned line, const char *section, unsigned section_line, const char *lvalue, int ltype, const char *rvalue, void *data, void *userdata) */ int r; _cleanup_(manager_freep) Manager *m = NULL; _cleanup_(unit_freep) Unit *u = NULL; ExecContext c = {}; r = manager_new(UNIT_FILE_USER, MANAGER_TEST_RUN_MINIMAL, &m); if (MANAGER_SKIP_TEST(r)) { log_notice_errno(r, "Skipping test: manager_new: %m"); return; } assert_se(r >= 0); assert_se(manager_startup(m, NULL, NULL) >= 0); assert_se(u = unit_new(m, sizeof(Service))); log_info("/* %s – basic test */", __func__); r = config_parse_log_extra_fields(NULL, "fake", 1, "section", 1, "LValue", 0, "FOO=BAR \"QOOF=quux ' ' \"", &c, u); assert_se(r >= 0); assert_se(c.n_log_extra_fields == 2); assert_se(strneq(c.log_extra_fields[0].iov_base, "FOO=BAR", c.log_extra_fields[0].iov_len)); assert_se(strneq(c.log_extra_fields[1].iov_base, "QOOF=quux ' ' ", c.log_extra_fields[1].iov_len)); log_info("/* %s – add some */", __func__); r = config_parse_log_extra_fields(NULL, "fake", 1, "section", 1, "LValue", 0, "FOO2=BAR2 QOOF2=quux ' '", &c, u); assert_se(r >= 0); assert_se(c.n_log_extra_fields == 4); assert_se(strneq(c.log_extra_fields[0].iov_base, "FOO=BAR", c.log_extra_fields[0].iov_len)); assert_se(strneq(c.log_extra_fields[1].iov_base, "QOOF=quux ' ' ", c.log_extra_fields[1].iov_len)); assert_se(strneq(c.log_extra_fields[2].iov_base, "FOO2=BAR2", c.log_extra_fields[2].iov_len)); assert_se(strneq(c.log_extra_fields[3].iov_base, "QOOF2=quux", c.log_extra_fields[3].iov_len)); exec_context_dump(&c, stdout, " --> "); log_info("/* %s – reset */", __func__); r = config_parse_log_extra_fields(NULL, "fake", 1, "section", 1, "LValue", 0, "", &c, u); assert_se(r >= 0); assert_se(c.n_log_extra_fields == 0); exec_context_free_log_extra_fields(&c); log_info("/* %s – bye */", __func__); }
int main(int argc, char *argv[]) { Manager *m = NULL; Unit *idle_ok, *idle_bad, *rr_ok, *rr_bad, *rr_sched; Service *ser; FILE *serial = NULL; FDSet *fdset = NULL; int r; /* prepare the test */ assert_se(set_unit_path(TEST_DIR) >= 0); r = manager_new(MANAGER_USER, true, &m); if (IN_SET(r, -EPERM, -EACCES, -EADDRINUSE, -EHOSTDOWN, -ENOENT, -ENOEXEC)) { printf("Skipping test: manager_new: %s", strerror(-r)); return EXIT_TEST_SKIP; } assert_se(r >= 0); assert_se(manager_startup(m, serial, fdset) >= 0); /* load idle ok */ assert_se(manager_load_unit(m, "sched_idle_ok.service", NULL, NULL, &idle_ok) >= 0); assert_se(idle_ok->load_state == UNIT_LOADED); ser = SERVICE(idle_ok); assert_se(ser->exec_context.cpu_sched_policy == SCHED_OTHER); assert_se(ser->exec_context.cpu_sched_priority == 0); /* * load idle bad. This should print a warning but we have no way to look at it. */ assert_se(manager_load_unit(m, "sched_idle_bad.service", NULL, NULL, &idle_bad) >= 0); assert_se(idle_bad->load_state == UNIT_LOADED); ser = SERVICE(idle_ok); assert_se(ser->exec_context.cpu_sched_policy == SCHED_OTHER); assert_se(ser->exec_context.cpu_sched_priority == 0); /* * load rr ok. * Test that the default priority is moving from 0 to 1. */ assert_se(manager_load_unit(m, "sched_rr_ok.service", NULL, NULL, &rr_ok) >= 0); assert_se(rr_ok->load_state == UNIT_LOADED); ser = SERVICE(rr_ok); assert_se(ser->exec_context.cpu_sched_policy == SCHED_RR); assert_se(ser->exec_context.cpu_sched_priority == 1); /* * load rr bad. * Test that the value of 0 and 100 is ignored. */ assert_se(manager_load_unit(m, "sched_rr_bad.service", NULL, NULL, &rr_bad) >= 0); assert_se(rr_bad->load_state == UNIT_LOADED); ser = SERVICE(rr_bad); assert_se(ser->exec_context.cpu_sched_policy == SCHED_RR); assert_se(ser->exec_context.cpu_sched_priority == 1); /* * load rr change. * Test that anything between 1 and 99 can be set. */ assert_se(manager_load_unit(m, "sched_rr_change.service", NULL, NULL, &rr_sched) >= 0); assert_se(rr_sched->load_state == UNIT_LOADED); ser = SERVICE(rr_sched); assert_se(ser->exec_context.cpu_sched_policy == SCHED_RR); assert_se(ser->exec_context.cpu_sched_priority == 99); manager_free(m); return EXIT_SUCCESS; }
int main(int argc, char *argv[]) { test_function_t tests[] = { test_exec_workingdirectory, test_exec_personality, test_exec_ignoresigpipe, test_exec_privatetmp, test_exec_privatedevices, test_exec_privatenetwork, test_exec_systemcallfilter, test_exec_systemcallerrornumber, test_exec_user, test_exec_group, test_exec_environment, test_exec_environmentfile, test_exec_passenvironment, test_exec_umask, test_exec_runtimedirectory, test_exec_capabilityboundingset, test_exec_oomscoreadjust, test_exec_ioschedulingclass, NULL, }; test_function_t *test = NULL; Manager *m = NULL; int r; log_parse_environment(); log_open(); /* It is needed otherwise cgroup creation fails */ if (getuid() != 0) { printf("Skipping test: not root\n"); return EXIT_TEST_SKIP; } assert_se(setenv("XDG_RUNTIME_DIR", "/tmp/", 1) == 0); assert_se(set_unit_path(TEST_DIR "/test-execute/") >= 0); /* Unset VAR1, VAR2 and VAR3 which are used in the PassEnvironment test * cases, otherwise (and if they are present in the environment), * `manager_default_environment` will copy them into the default * environment which is passed to each created job, which will make the * tests that expect those not to be present to fail. */ assert_se(unsetenv("VAR1") == 0); assert_se(unsetenv("VAR2") == 0); assert_se(unsetenv("VAR3") == 0); r = manager_new(MANAGER_USER, true, &m); if (MANAGER_SKIP_TEST(r)) { printf("Skipping test: manager_new: %s\n", strerror(-r)); return EXIT_TEST_SKIP; } assert_se(r >= 0); assert_se(manager_startup(m, NULL, NULL) >= 0); for (test = tests; test && *test; test++) (*test)(m); manager_free(m); return 0; }