#include <sys/stat.h>
#include <atf-c.h>
#include <fcntl.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <private/pkg.h>
#include <xmalloc.h>
#include <pkghash.h>
ATF_TC_WITHOUT_HEAD(deferred_rc_init_free);
ATF_TC_WITHOUT_HEAD(deferred_rc_free_null);
ATF_TC_WITHOUT_HEAD(deferred_rc_stop_entries);
ATF_TC_WITHOUT_HEAD(deferred_rc_start_entries);
ATF_TC_WITHOUT_HEAD(deferred_rc_dedup);
ATF_TC_WITHOUT_HEAD(deferred_rc_tmpdir_cleanup);
ATF_TC_WITHOUT_HEAD(deferred_rc_free_reuse);
ATF_TC_WITHOUT_HEAD(deferred_rc_stop_all_null_oldpath);
ATF_TC_WITHOUT_HEAD(deferred_rc_tmpdir_multiple_scripts);
ATF_TC_WITHOUT_HEAD(deferred_rc_seen_sets_independent);
ATF_TC_WITHOUT_HEAD(deferred_rc_mixed_stop_start);
ATF_TC_BODY(deferred_rc_init_free, tc)
{
struct deferred_rc rc;
pkg_deferred_rc_init(&rc);
ATF_REQUIRE_EQ(rc.tmpdir, NULL);
ATF_REQUIRE_EQ(rc.to_stop.len, 0);
ATF_REQUIRE_EQ(rc.to_start.len, 0);
ATF_REQUIRE_EQ(rc.seen_stop, NULL);
ATF_REQUIRE_EQ(rc.seen_start, NULL);
pkg_deferred_rc_free(&rc);
ATF_REQUIRE_EQ(rc.tmpdir, NULL);
ATF_REQUIRE_EQ(rc.to_stop.len, 0);
ATF_REQUIRE_EQ(rc.to_start.len, 0);
}
ATF_TC_BODY(deferred_rc_free_null, tc)
{
pkg_deferred_rc_free(NULL);
}
ATF_TC_BODY(deferred_rc_stop_entries, tc)
{
struct deferred_rc rc;
struct deferred_rc_stop s;
pkg_deferred_rc_init(&rc);
s.name = xstrdup("sshd");
s.oldpath = xstrdup("/tmp/fakepath/sshd");
vec_push(&rc.to_stop, s);
s.name = xstrdup("nginx");
s.oldpath = NULL;
vec_push(&rc.to_stop, s);
ATF_REQUIRE_EQ(rc.to_stop.len, 2);
ATF_REQUIRE_STREQ(rc.to_stop.d[0].name, "sshd");
ATF_REQUIRE(rc.to_stop.d[0].oldpath != NULL);
ATF_REQUIRE_STREQ(rc.to_stop.d[1].name, "nginx");
ATF_REQUIRE_EQ(rc.to_stop.d[1].oldpath, NULL);
ATF_REQUIRE_EQ(rc.to_start.len, 0);
free(rc.to_stop.d[0].oldpath);
rc.to_stop.d[0].oldpath = NULL;
pkg_deferred_rc_free(&rc);
}
ATF_TC_BODY(deferred_rc_start_entries, tc)
{
struct deferred_rc rc;
pkg_deferred_rc_init(&rc);
vec_push(&rc.to_start, xstrdup("postfix"));
vec_push(&rc.to_start, xstrdup("dovecot"));
ATF_REQUIRE_EQ(rc.to_start.len, 2);
ATF_REQUIRE_STREQ(rc.to_start.d[0], "postfix");
ATF_REQUIRE_STREQ(rc.to_start.d[1], "dovecot");
ATF_REQUIRE_EQ(rc.to_stop.len, 0);
pkg_deferred_rc_free(&rc);
}
ATF_TC_BODY(deferred_rc_dedup, tc)
{
struct deferred_rc rc;
struct deferred_rc_stop s;
pkg_deferred_rc_init(&rc);
pkghash_safe_add(rc.seen_stop, "svc", NULL, NULL);
s.name = xstrdup("svc");
s.oldpath = NULL;
vec_push(&rc.to_stop, s);
ATF_REQUIRE(pkghash_get(rc.seen_stop, "svc") != NULL);
ATF_REQUIRE_EQ(rc.to_stop.len, 1);
pkghash_safe_add(rc.seen_start, "svc2", NULL, NULL);
vec_push(&rc.to_start, xstrdup("svc2"));
ATF_REQUIRE(pkghash_get(rc.seen_start, "svc2") != NULL);
ATF_REQUIRE_EQ(rc.to_start.len, 1);
pkghash_safe_add(rc.seen_start, "svc", NULL, NULL);
ATF_REQUIRE(pkghash_get(rc.seen_start, "svc") != NULL);
pkg_deferred_rc_free(&rc);
}
ATF_TC_BODY(deferred_rc_tmpdir_cleanup, tc)
{
struct deferred_rc rc;
struct deferred_rc_stop s;
char tdir[] = "/tmp/pkg-test-rc.XXXXXX";
char script_path[PATH_MAX];
char *saved_tmpdir;
int fd;
ATF_REQUIRE(mkdtemp(tdir) != NULL);
pkg_deferred_rc_init(&rc);
rc.tmpdir = xstrdup(tdir);
snprintf(script_path, sizeof(script_path), "%s/fakesvc", tdir);
fd = open(script_path, O_WRONLY | O_CREAT, 0755);
ATF_REQUIRE(fd != -1);
write(fd, "#!/bin/sh\n", 10);
close(fd);
s.name = xstrdup("fakesvc");
s.oldpath = xstrdup(script_path);
vec_push(&rc.to_stop, s);
saved_tmpdir = xstrdup(rc.tmpdir);
ATF_REQUIRE(access(script_path, F_OK) == 0);
pkg_deferred_rc_free(&rc);
ATF_REQUIRE_EQ_MSG(access(script_path, F_OK), -1,
"saved rc script should have been removed");
ATF_REQUIRE_EQ_MSG(access(saved_tmpdir, F_OK), -1,
"tmpdir should have been removed");
free(saved_tmpdir);
}
ATF_TC_BODY(deferred_rc_free_reuse, tc)
{
struct deferred_rc rc;
struct deferred_rc_stop s;
pkg_deferred_rc_init(&rc);
s.name = xstrdup("sshd");
s.oldpath = NULL;
vec_push(&rc.to_stop, s);
vec_push(&rc.to_start, xstrdup("nginx"));
pkghash_safe_add(rc.seen_stop, "sshd", NULL, NULL);
pkghash_safe_add(rc.seen_start, "nginx", NULL, NULL);
pkg_deferred_rc_free(&rc);
pkg_deferred_rc_init(&rc);
ATF_REQUIRE_EQ(rc.tmpdir, NULL);
ATF_REQUIRE_EQ(rc.to_stop.len, 0);
ATF_REQUIRE_EQ(rc.to_start.len, 0);
ATF_REQUIRE_EQ(rc.seen_stop, NULL);
ATF_REQUIRE_EQ(rc.seen_start, NULL);
s.name = xstrdup("postfix");
s.oldpath = NULL;
vec_push(&rc.to_stop, s);
ATF_REQUIRE_EQ(rc.to_stop.len, 1);
ATF_REQUIRE_STREQ(rc.to_stop.d[0].name, "postfix");
pkg_deferred_rc_free(&rc);
}
ATF_TC_BODY(deferred_rc_stop_all_null_oldpath, tc)
{
struct deferred_rc rc;
struct deferred_rc_stop s;
pkg_deferred_rc_init(&rc);
s.name = xstrdup("sshd");
s.oldpath = NULL;
vec_push(&rc.to_stop, s);
s.name = xstrdup("nginx");
s.oldpath = NULL;
vec_push(&rc.to_stop, s);
s.name = xstrdup("postfix");
s.oldpath = NULL;
vec_push(&rc.to_stop, s);
ATF_REQUIRE_EQ(rc.to_stop.len, 3);
ATF_REQUIRE_EQ(rc.to_stop.d[0].oldpath, NULL);
ATF_REQUIRE_EQ(rc.to_stop.d[1].oldpath, NULL);
ATF_REQUIRE_EQ(rc.to_stop.d[2].oldpath, NULL);
pkg_deferred_rc_free(&rc);
}
ATF_TC_BODY(deferred_rc_tmpdir_multiple_scripts, tc)
{
struct deferred_rc rc;
struct deferred_rc_stop s;
char tdir[] = "/tmp/pkg-test-rc.XXXXXX";
char path1[PATH_MAX], path2[PATH_MAX], path3[PATH_MAX];
int fd;
ATF_REQUIRE(mkdtemp(tdir) != NULL);
pkg_deferred_rc_init(&rc);
rc.tmpdir = xstrdup(tdir);
snprintf(path1, sizeof(path1), "%s/svc_a", tdir);
fd = open(path1, O_WRONLY | O_CREAT, 0755);
ATF_REQUIRE(fd != -1);
write(fd, "#!/bin/sh\n", 10);
close(fd);
snprintf(path2, sizeof(path2), "%s/svc_b", tdir);
fd = open(path2, O_WRONLY | O_CREAT, 0755);
ATF_REQUIRE(fd != -1);
write(fd, "#!/bin/sh\n", 10);
close(fd);
snprintf(path3, sizeof(path3), "%s/svc_c", tdir);
fd = open(path3, O_WRONLY | O_CREAT, 0755);
ATF_REQUIRE(fd != -1);
write(fd, "#!/bin/sh\n", 10);
close(fd);
s.name = xstrdup("svc_a");
s.oldpath = xstrdup(path1);
vec_push(&rc.to_stop, s);
s.name = xstrdup("svc_b");
s.oldpath = xstrdup(path2);
vec_push(&rc.to_stop, s);
s.name = xstrdup("svc_c");
s.oldpath = xstrdup(path3);
vec_push(&rc.to_stop, s);
ATF_REQUIRE_EQ(rc.to_stop.len, 3);
char *saved_tmpdir = xstrdup(rc.tmpdir);
pkg_deferred_rc_free(&rc);
ATF_REQUIRE_EQ_MSG(access(path1, F_OK), -1,
"svc_a script should have been removed");
ATF_REQUIRE_EQ_MSG(access(path2, F_OK), -1,
"svc_b script should have been removed");
ATF_REQUIRE_EQ_MSG(access(path3, F_OK), -1,
"svc_c script should have been removed");
ATF_REQUIRE_EQ_MSG(access(saved_tmpdir, F_OK), -1,
"tmpdir should have been removed");
free(saved_tmpdir);
}
ATF_TC_BODY(deferred_rc_seen_sets_independent, tc)
{
struct deferred_rc rc;
pkg_deferred_rc_init(&rc);
pkghash_safe_add(rc.seen_stop, "only_stop", NULL, NULL);
pkghash_safe_add(rc.seen_start, "only_start", NULL, NULL);
ATF_REQUIRE(pkghash_get(rc.seen_stop, "only_stop") != NULL);
ATF_REQUIRE(pkghash_get(rc.seen_start, "only_stop") == NULL);
ATF_REQUIRE(pkghash_get(rc.seen_start, "only_start") != NULL);
ATF_REQUIRE(pkghash_get(rc.seen_stop, "only_start") == NULL);
ATF_REQUIRE(pkghash_get(rc.seen_stop, "unknown") == NULL);
ATF_REQUIRE(pkghash_get(rc.seen_start, "unknown") == NULL);
pkg_deferred_rc_free(&rc);
}
ATF_TC_BODY(deferred_rc_mixed_stop_start, tc)
{
struct deferred_rc rc;
struct deferred_rc_stop s;
pkg_deferred_rc_init(&rc);
pkghash_safe_add(rc.seen_stop, "sshd", NULL, NULL);
s.name = xstrdup("sshd");
s.oldpath = NULL;
vec_push(&rc.to_stop, s);
pkghash_safe_add(rc.seen_stop, "nginx", NULL, NULL);
s.name = xstrdup("nginx");
s.oldpath = NULL;
vec_push(&rc.to_stop, s);
pkghash_safe_add(rc.seen_start, "sshd", NULL, NULL);
vec_push(&rc.to_start, xstrdup("sshd"));
pkghash_safe_add(rc.seen_start, "postfix", NULL, NULL);
vec_push(&rc.to_start, xstrdup("postfix"));
ATF_REQUIRE_EQ(rc.to_stop.len, 2);
ATF_REQUIRE_EQ(rc.to_start.len, 2);
ATF_REQUIRE(pkghash_get(rc.seen_stop, "sshd") != NULL);
ATF_REQUIRE(pkghash_get(rc.seen_start, "sshd") != NULL);
ATF_REQUIRE(pkghash_get(rc.seen_stop, "nginx") != NULL);
ATF_REQUIRE(pkghash_get(rc.seen_start, "nginx") == NULL);
ATF_REQUIRE(pkghash_get(rc.seen_stop, "postfix") == NULL);
ATF_REQUIRE(pkghash_get(rc.seen_start, "postfix") != NULL);
pkg_deferred_rc_free(&rc);
}
ATF_TP_ADD_TCS(tp)
{
ATF_TP_ADD_TC(tp, deferred_rc_init_free);
ATF_TP_ADD_TC(tp, deferred_rc_free_null);
ATF_TP_ADD_TC(tp, deferred_rc_stop_entries);
ATF_TP_ADD_TC(tp, deferred_rc_start_entries);
ATF_TP_ADD_TC(tp, deferred_rc_dedup);
ATF_TP_ADD_TC(tp, deferred_rc_tmpdir_cleanup);
ATF_TP_ADD_TC(tp, deferred_rc_free_reuse);
ATF_TP_ADD_TC(tp, deferred_rc_stop_all_null_oldpath);
ATF_TP_ADD_TC(tp, deferred_rc_tmpdir_multiple_scripts);
ATF_TP_ADD_TC(tp, deferred_rc_seen_sets_independent);
ATF_TP_ADD_TC(tp, deferred_rc_mixed_stop_start);
return (atf_no_error());
}