void test_spec_handler(struct spec_handler* handler, struct spec_handler_test* tests) { GNode* node; GNode* handler_node; GNode test_node; struct cc_oci_config config; struct spec_handler_test* test; int fd; ck_assert(! handler->handle_section(NULL, NULL)); ck_assert(! handler->handle_section(&test_node, NULL)); ck_assert(! handler->handle_section(NULL, &config)); /** * Create fake files for Kernel and image so * path validation won't fail */ fd = g_creat("CONTAINER-KERNEL",0755); if (fd < 0) { g_critical ("failed to create file CONTAINER-KERNEL"); } else { close(fd); } fd = g_creat("CLEAR-CONTAINERS.img",0755); if (fd < 0) { g_critical ("failed to create file CLEAR-CONTAINERS.img"); } else { close(fd); } fd = g_creat("QEMU-LITE",0755); if (fd < 0) { g_critical ("failed to create file QEMU-LITE"); } else { close(fd); } for (test=tests; test->file; test++) { memset(&config, 0, sizeof(config)); cc_oci_json_parse(&node, test->file); handler_node = node_find_child(node, handler->name); ck_assert_msg(handler->handle_section( handler_node, &config) == test->test_result, test->file); cc_oci_config_free(&config); g_free_node(node); } if (g_remove("CONTAINER-KERNEL") < 0) { g_critical ("failed to remove file CONTAINER-KERNEL"); } if (g_remove ("CLEAR-CONTAINERS.img") < 0) { g_critical ("failed to remove file CLEAR-CONTAINERS.img"); } if (g_remove ("QEMU-LITE") < 0) { g_critical ("failed to remove file QEMU-LITE"); } }
} END_TEST START_TEST(test_cc_pod_is_vm) { struct cc_oci_config *config = NULL; ck_assert(cc_pod_is_vm(config)); config = cc_oci_config_create (); ck_assert(config); ck_assert(cc_pod_is_vm(config)); config->pod = g_malloc0 (sizeof (struct cc_pod)); ck_assert(config->pod); config->pod->sandbox = false; ck_assert(!cc_pod_is_vm(config)); config->pod->sandbox = true; ck_assert(cc_pod_is_vm(config)); /* clean up */ cc_oci_config_free (config); } END_TEST
} END_TEST START_TEST(test_cc_oci_state_file_create) { struct cc_oci_config config = { { 0 } }; const gchar *timestamp = "foo"; struct oci_cfg_annotation* a = NULL; struct cc_oci_mount *m = NULL; g_autofree gchar *tmpdir = g_dir_make_tmp (NULL, NULL); gboolean ret; ck_assert(! cc_oci_state_file_create (NULL, NULL)); /* Needs: * * - comms_path * - procsock_path * - optarg_bundle_path * - optarg_container_id * - runtime_path * */ ck_assert(! cc_oci_state_file_create (&config, NULL)); ck_assert(! cc_oci_state_file_create (&config, timestamp)); config.optarg_container_id = ""; ck_assert(! cc_oci_state_file_create (&config, NULL)); ck_assert(! cc_oci_state_file_create (&config, timestamp)); config.optarg_container_id = "foo"; ck_assert(! cc_oci_state_file_create (&config, NULL)); ck_assert(! cc_oci_state_file_create (&config, timestamp)); config.bundle_path = g_strdup ("/tmp/bundle"); ck_assert(! cc_oci_state_file_create (&config, NULL)); ck_assert(! cc_oci_state_file_create (&config, timestamp)); config.root_dir = g_strdup (tmpdir); ck_assert (config.root_dir); ck_assert (cc_oci_runtime_dir_setup (&config)); ck_assert(! cc_oci_state_file_create (&config, NULL)); ck_assert(! cc_oci_state_file_create (&config, timestamp)); g_snprintf(config.state.comms_path, PATH_MAX, "/tmp"); g_snprintf(config.state.procsock_path, PATH_MAX, "/tmp"); ck_assert(! cc_oci_state_file_create (&config, NULL)); a = g_new0(struct oci_cfg_annotation, 1); a->key = g_strdup("key1"); a->value = g_strdup("val1"); config.oci.annotations = g_slist_append(config.oci.annotations, a); /* config->vm not set */ ck_assert(! cc_oci_state_file_create (&config, timestamp)); config.vm = g_malloc0 (sizeof(struct cc_oci_vm_cfg)); ck_assert (config.vm); g_strlcpy (config.vm->hypervisor_path, "hypervisor-path", sizeof (config.vm->hypervisor_path)); g_strlcpy (config.vm->image_path, "image-path", sizeof (config.vm->image_path)); g_strlcpy (config.vm->kernel_path, "kernel-path", sizeof (config.vm->kernel_path)); g_strlcpy (config.vm->workload_path, "workload-path", sizeof (config.vm->workload_path)); config.vm->kernel_params = g_strdup ("kernel params"); /* All required elements now set */ m = g_new0(struct cc_oci_mount, 1); g_snprintf(m->dest, sizeof(m->dest), "/tmp/tmp/tmp"); m->directory_created = g_strdup("/tmp/tmp/"); m->ignore_mount = true; config.oci.mounts = g_slist_append(config.oci.mounts, m); ck_assert (cc_oci_state_file_create (&config, timestamp)); ret = g_file_test (config.state.state_file_path, G_FILE_TEST_EXISTS); ck_assert (ret); ck_assert (! g_remove (config.state.state_file_path)); ck_assert (! g_remove (config.state.runtime_path)); ck_assert (! g_remove (tmpdir)); g_snprintf(config.state.runtime_path, PATH_MAX, "/abc/xyz/123"); ck_assert(!cc_oci_state_file_create (&config, timestamp)); /* clean up */ cc_oci_config_free (&config); } END_TEST
} END_TEST START_TEST(test_cc_oci_vm_args_get) { gboolean ret; gchar *path; gchar **args = NULL; gchar *tmpdir; struct cc_oci_config config = { { 0 } }; gchar *args_file; gchar image_contents[] = "hello world"; gchar *image_size = g_strdup_printf ("%lu", (unsigned long int)sizeof(image_contents)-1); gchar *invalid_dir = "/this/directory/must/not/exist"; g_autofree gchar *cc_stdin = NULL; g_autofree gchar *cc_stdout = NULL; GPtrArray *extra_args = NULL; tmpdir = g_dir_make_tmp (NULL, NULL); ck_assert (tmpdir); ret = g_file_test (invalid_dir, (G_FILE_TEST_EXISTS | G_FILE_TEST_IS_DIR)); /* invalid_dir must not exist :) */ ck_assert (! ret); /* ensure the default locations are invalid */ sysconfdir = invalid_dir; defaultsdir = invalid_dir; args_file = g_build_path ("/", tmpdir, "hypervisor.args", NULL); ck_assert (args_file); ck_assert (! cc_oci_vm_args_get (NULL, NULL, NULL)); ck_assert (! cc_oci_vm_args_get (NULL, &args, NULL)); ck_assert (! cc_oci_vm_args_get (&config, NULL, NULL)); /* no bundle_path */ ck_assert (! cc_oci_vm_args_get (&config, &args, NULL)); config.bundle_path = g_strdup (tmpdir); cc_stdin = g_build_path ("/", config.bundle_path, "cc-std.in", NULL); cc_stdout = g_build_path ("/", config.bundle_path, "cc-std.out", NULL); /* no config.vm */ ck_assert (! cc_oci_vm_args_get (&config, &args, NULL)); config.vm = g_new0 (struct cc_oci_vm_cfg, 1); ck_assert (config.vm); config.vm->kernel_params = g_strdup ("param1=foo param2=bar"); g_strlcpy (config.state.comms_path, "comms-path", sizeof (config.state.comms_path)); path = g_build_path ("/", tmpdir, "image", NULL); ck_assert (path); g_strlcpy (config.vm->image_path, path, sizeof (config.vm->image_path)); g_free (path); /* create image_path */ ret = g_file_set_contents (config.vm->image_path, image_contents, -1, NULL); ck_assert (ret); /* no kernel path */ ck_assert (! cc_oci_expand_cmdline (&config, args)); path = g_build_path ("/", tmpdir, "vmlinux", NULL); ck_assert (path); g_strlcpy (config.vm->kernel_path, path, sizeof (config.vm->kernel_path)); g_free (path); /* create kernel_path */ ret = g_file_set_contents (config.vm->kernel_path, "", -1, NULL); ck_assert (ret); /* no root.path */ ck_assert (! cc_oci_expand_cmdline (&config, args)); path = g_build_path ("/", tmpdir, "workload", NULL); ck_assert (path); g_strlcpy (config.oci.root.path, path, sizeof (config.oci.root.path)); g_free (path); /* create root path */ ck_assert (! g_mkdir (config.oci.root.path, 0750)); /* bundle path is now set, but no args file exists there. */ ck_assert (! cc_oci_vm_args_get (&config, &args, NULL)); /* create an empty bundle_path file */ ret = g_file_set_contents (args_file, "", -1, NULL); ck_assert (ret); /* an empty string cannot be split into lines */ ck_assert (! cc_oci_vm_args_get (&config, &args, NULL)); /* recreate the args file */ ret = g_file_set_contents (args_file, "hello # comment\n", -1, NULL); ck_assert (ret); ck_assert (cc_oci_vm_args_get (&config, &args, NULL)); ck_assert (! g_strcmp0 (args[0], "hello")); ck_assert (! args[1]); g_strfreev (args); /* recreate the args file */ ret = g_file_set_contents (args_file, "hello# comment\n", -1, NULL); ck_assert (ret); ck_assert (cc_oci_vm_args_get (&config, &args, NULL)); ck_assert (! g_strcmp0 (args[0], "hello# comment")); ck_assert (! args[1]); g_strfreev (args); /* recreate the args file */ ret = g_file_set_contents (args_file, "hello\\# comment\n", -1, NULL); ck_assert (ret); ck_assert (cc_oci_vm_args_get (&config, &args, NULL)); ck_assert (! g_strcmp0 (args[0], "hello\\# comment")); ck_assert (! args[1]); g_strfreev (args); /* recreate the args file */ ret = g_file_set_contents (args_file, "hello\t # comment\n", -1, NULL); ck_assert (ret); ck_assert (cc_oci_vm_args_get (&config, &args, NULL)); ck_assert (! g_strcmp0 (args[0], "hello")); ck_assert (! args[1]); g_strfreev (args); /* recreate the args file */ ret = g_file_set_contents (args_file, "hello#comment\n", -1, NULL); ck_assert (ret); ck_assert (cc_oci_vm_args_get (&config, &args, NULL)); ck_assert (! g_strcmp0 (args[0], "hello#comment")); ck_assert (! args[1]); g_strfreev (args); /* recreate the args file */ ret = g_file_set_contents (args_file, "# comment\n", -1, NULL); ck_assert (ret); ck_assert (cc_oci_vm_args_get (&config, &args, NULL)); ck_assert(! args[0]); g_strfreev (args); /* recreate the args file */ ret = g_file_set_contents (args_file, "# comment", -1, NULL); ck_assert (ret); ck_assert (cc_oci_vm_args_get (&config, &args, NULL)); ck_assert(! args[0]); g_strfreev (args); /* recreate the args file */ ret = g_file_set_contents (args_file, "foo", -1, NULL); ck_assert (ret); ck_assert (cc_oci_vm_args_get (&config, &args, NULL)); ck_assert (! g_strcmp0 (args[0], "foo")); ck_assert (! args[1]); g_strfreev (args); /* recreate the args file */ ret = g_file_set_contents (args_file, "hello\nworld\nfoo\nbar", -1, NULL); ck_assert (ret); extra_args = g_ptr_array_new (); ck_assert (cc_oci_vm_args_get (&config, &args, extra_args)); ck_assert (! g_strcmp0 (args[0], "hello")); ck_assert (! g_strcmp0 (args[1], "world")); ck_assert (! g_strcmp0 (args[2], "foo")); ck_assert (! g_strcmp0 (args[3], "bar")); ck_assert (! args[4]); g_strfreev (args); g_ptr_array_free(extra_args, TRUE); /* recreate the args file */ ret = g_file_set_contents (args_file, "hello\nworld\nfoo\nbar", -1, NULL); ck_assert (ret); extra_args = g_ptr_array_new (); g_ptr_array_add(extra_args, "-device testdevice"); g_ptr_array_add(extra_args, "-device testdevice2"); ck_assert (cc_oci_vm_args_get (&config, &args, extra_args)); ck_assert (! g_strcmp0 (args[0], "hello")); ck_assert (! g_strcmp0 (args[1], "world")); ck_assert (! g_strcmp0 (args[2], "foo")); ck_assert (! g_strcmp0 (args[3], "bar")); ck_assert (! g_strcmp0 (args[4], "-device testdevice")); ck_assert (! g_strcmp0 (args[5], "-device testdevice2")); ck_assert (! args[6]); g_strfreev (args); g_ptr_array_free(extra_args, TRUE); /* recreate the args file with expandable lines */ ret = g_file_set_contents (args_file, "@WORKLOAD_DIR@\n" "@KERNEL@\n" "@KERNEL_PARAMS@\n" "@IMAGE@\n" "@SIZE@\n" "@COMMS_SOCKET@\n" "@CONSOLE_DEVICE@\n" "@NAME@\n" "@UUID@\n", -1, NULL); ck_assert (ret); ck_assert (cc_oci_vm_args_get (&config, &args, NULL)); ck_assert (check_full_expansion (&config, (const gchar **)args, image_size)); g_strfreev (args); /* clean up */ ck_assert (! g_remove (args_file)); ck_assert (! g_remove (config.vm->image_path)); ck_assert (! g_remove (config.vm->kernel_path)); ck_assert (! g_remove (config.oci.root.path)); if (! config.oci.process.terminal) { ck_assert (! g_remove (cc_stdin)); ck_assert (! g_remove (cc_stdout)); } ck_assert (! g_remove (tmpdir)); g_free (args_file); g_free (tmpdir); g_free (image_size); cc_oci_config_free (&config); } END_TEST
} END_TEST START_TEST(test_cc_oci_expand_cmdline) { gboolean ret; gchar **args; gchar *tmpdir; gchar *path; gchar image_contents[] = "hello world"; gchar *image_size = g_strdup_printf ("%lu", (unsigned long int)sizeof(image_contents)-1); gchar *shell; g_autofree gchar *cc_stdin = NULL; g_autofree gchar *cc_stdout = NULL; struct cc_oci_config config = { { 0 } }; tmpdir = g_dir_make_tmp (NULL, NULL); ck_assert (tmpdir); ck_assert (! cc_oci_expand_cmdline (NULL, NULL)); ck_assert (! cc_oci_expand_cmdline (NULL, NULL)); args = g_new0 (gchar *, 3); ck_assert (args); args[0] = g_strdup (""); args[1] = g_strdup (""); args[2] = NULL; /* no config */ ck_assert (! cc_oci_expand_cmdline (NULL, args)); /* no config.vm */ ck_assert (! cc_oci_expand_cmdline (&config, args)); config.vm = g_new0 (struct cc_oci_vm_cfg, 1); ck_assert (config.vm); path = g_build_path ("/", tmpdir, "image", NULL); ck_assert (path); g_strlcpy (config.vm->image_path, path, sizeof (config.vm->image_path)); g_free (path); /* image_path is ENOENT */ ck_assert (! cc_oci_expand_cmdline (&config, args)); /* create image_path */ ret = g_file_set_contents (config.vm->image_path, image_contents, -1, NULL); ck_assert (ret); /* no kernel path */ ck_assert (! cc_oci_expand_cmdline (&config, args)); path = g_build_path ("/", tmpdir, "vmlinux", NULL); ck_assert (path); g_strlcpy (config.vm->kernel_path, path, sizeof (config.vm->kernel_path)); g_free (path); /* kernel_path is ENOENT */ ck_assert (! cc_oci_expand_cmdline (&config, args)); /* create kernel_path */ ret = g_file_set_contents (config.vm->kernel_path, "", -1, NULL); ck_assert (ret); /* no root.path */ ck_assert (! cc_oci_expand_cmdline (&config, args)); path = g_build_path ("/", tmpdir, "workload", NULL); ck_assert (path); g_strlcpy (config.oci.root.path, path, sizeof (config.oci.root.path)); g_free (path); ck_assert (! g_mkdir (config.oci.root.path, 0750)); g_strlcpy (config.state.comms_path, "comms-path", sizeof (config.state.comms_path)); ck_assert (! config.console); ck_assert (! config.bundle_path); ck_assert (! cc_oci_expand_cmdline (&config, args)); config.bundle_path = g_strdup (tmpdir); ck_assert (cc_oci_expand_cmdline (&config, args)); cc_stdin = g_build_path ("/", config.bundle_path, "cc-std.in", NULL); cc_stdout = g_build_path ("/", config.bundle_path, "cc-std.out", NULL); /* console should have been set */ ck_assert (config.console); g_free (config.console); /* ensure no expansion took place */ ck_assert (! g_strcmp0 (args[0], "")); ck_assert (! g_strcmp0 (args[1], "")); ck_assert (args[2] == NULL); g_strfreev (args); args = g_new0 (gchar *, 3); ck_assert (args); args[0] = g_strdup ("@foo@bar@baz"); args[1] = g_strdup ("@@@@@@@@@@@"); args[2] = NULL; config.console = g_strdup ("console device"); config.vm->kernel_params = g_strdup ("param1=foo param2=bar"); ck_assert (cc_oci_expand_cmdline (&config, args)); ck_assert (! g_strcmp0 (config.console, "console device")); /* ensure no expansion took place */ ck_assert (! g_strcmp0 (args[0], "@foo@bar@baz")); ck_assert (! g_strcmp0 (args[1], "@@@@@@@@@@@")); ck_assert (! args[2]); g_strfreev (args); args = g_new0 (gchar *, 10); ck_assert (args); args[0] = g_strdup ("@WORKLOAD_DIR@"); args[1] = g_strdup ("@KERNEL@"); args[2] = g_strdup ("@KERNEL_PARAMS@"); args[3] = g_strdup ("@IMAGE@"); args[4] = g_strdup ("@SIZE@"); args[5] = g_strdup ("@COMMS_SOCKET@"); args[6] = g_strdup ("@CONSOLE_DEVICE@"); args[7] = g_strdup ("@NAME@"); args[8] = g_strdup ("@UUID@"); args[9] = NULL; ck_assert (cc_oci_expand_cmdline (&config, args)); ck_assert (check_full_expansion (&config, (const gchar **)args, image_size)); g_strfreev (args); /* check expansion of first param if relative */ shell = g_find_program_in_path ("sh"); ck_assert (shell); args = g_new0 (gchar *, 2); ck_assert (args); args[0] = g_strdup ("sh"); args[1] = NULL; ck_assert (cc_oci_expand_cmdline (&config, args)); ck_assert (! g_strcmp0 (args[0], shell)); ck_assert (! args[1]); g_free (args[0]); /* test with an already specified absolute path */ args[0] = g_strdup (shell); ck_assert (cc_oci_expand_cmdline (&config, args)); ck_assert (! g_strcmp0 (args[0], shell)); g_free (shell); g_strfreev (args); /* clean up */ ck_assert (! g_remove (config.vm->image_path)); ck_assert (! g_remove (config.vm->kernel_path)); ck_assert (! g_remove (config.oci.root.path)); if (! config.oci.process.terminal) { ck_assert (! g_remove (cc_stdin)); ck_assert (! g_remove (cc_stdout)); } ck_assert (! g_remove (tmpdir)); g_free (tmpdir); g_free (image_size); cc_oci_config_free (&config); } END_TEST