1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170
|
#include <test.h>
#include <eval_context.h>
#include <misc_lib.h> /* xsnprintf */
#include <known_dirs.h>
#include <time_classes.h>
char CFWORKDIR[CF_BUFSIZE];
void tests_setup(void)
{
static char env[] = /* Needs to be static for putenv() */
"CFENGINE_TEST_OVERRIDE_WORKDIR=/tmp/CFENGINE_eval_context_test.XXXXXX";
char *workdir = strchr(env, '=');
assert(workdir && workdir[1] == '/');
workdir++;
mkdtemp(workdir);
strlcpy(CFWORKDIR, workdir, CF_BUFSIZE);
putenv(env);
mkdir(GetStateDir(), 0766);
}
void tests_teardown(void)
{
char cmd[CF_BUFSIZE];
xsnprintf(cmd, CF_BUFSIZE, "rm -rf '%s'", CFWORKDIR);
system(cmd);
}
static void test_class_persistence(void)
{
EvalContext *ctx = EvalContextNew();
// simulate old version
{
CF_DB *dbp;
PersistentClassInfo i;
assert_true(OpenDB(&dbp, dbid_state));
i.expires = UINT_MAX;
i.policy = CONTEXT_STATE_POLICY_RESET;
WriteDB(dbp, "old", &i, sizeof(PersistentClassInfo));
CloseDB(dbp);
}
// e.g. by monitoring
EvalContextHeapPersistentSave(ctx, "class1", 3, CONTEXT_STATE_POLICY_PRESERVE, "a,b");
// e.g. by a class promise in a bundle with a namespace
{
Policy *p = PolicyNew();
Bundle *bp = PolicyAppendBundle(p, "ns1", "bundle1", "agent", NULL, NULL);
EvalContextStackPushBundleFrame(ctx, bp, NULL, false);
EvalContextHeapPersistentSave(ctx, "class2", 5, CONTEXT_STATE_POLICY_PRESERVE, "x");
EvalContextStackPopFrame(ctx);
PolicyDestroy(p);
}
EvalContextHeapPersistentLoadAll(ctx);
{
const Class *cls = EvalContextClassGet(ctx, "default", "old");
assert_true(cls != NULL);
assert_string_equal("old", cls->name);
assert_true(cls->tags != NULL);
assert_int_equal(1, StringSetSize(cls->tags));
assert_true(StringSetContains(cls->tags, "source=persistent"));
}
{
const Class *cls = EvalContextClassGet(ctx, "default", "class1");
assert_true(cls != NULL);
assert_string_equal("class1", cls->name);
assert_true(cls->tags != NULL);
assert_int_equal(3, StringSetSize(cls->tags));
assert_true(StringSetContains(cls->tags, "source=persistent"));
assert_true(StringSetContains(cls->tags, "a"));
assert_true(StringSetContains(cls->tags, "b"));
}
{
const Class *cls = EvalContextClassGet(ctx, "ns1", "class2");
assert_true(cls != NULL);
assert_string_equal("ns1", cls->ns);
assert_string_equal("class2", cls->name);
assert_true(cls->tags != NULL);
assert_int_equal(2, StringSetSize(cls->tags));
assert_true(StringSetContains(cls->tags, "source=persistent"));
assert_true(StringSetContains(cls->tags, "x"));
}
EvalContextDestroy(ctx);
}
void test_changes_chroot(void)
{
/* Should add '/' to the end implicitly. */
SetChangesChroot("/changes/go/here");
/* The most trivial case. */
const char *chrooted = ToChangesChroot("/etc/issue");
assert_string_equal(chrooted, "/changes/go/here/etc/issue");
/* A shorter path to test that NUL-byte is added/copied properly. */
chrooted = ToChangesChroot("/etc/ab");
assert_string_equal(chrooted, "/changes/go/here/etc/ab");
/* And a longer path again. */
chrooted = ToChangesChroot("/etc/sysctl.d/00-default.conf");
assert_string_equal(chrooted, "/changes/go/here/etc/sysctl.d/00-default.conf");
#ifndef __MINGW32__
/* Inverse should work as expected */
const char *normal = ToNormalRoot(chrooted);
assert_string_equal(normal, "/etc/sysctl.d/00-default.conf");
#endif
}
void test_eval_with_token_from_list(void)
{
/* The timestamp should generate these classes (among others):
* 'GMT_Afternoon', 'GMT_Day29', 'GMT_Hr13', 'GMT_Hr13_Q3', 'GMT_Lcycle_2',
* 'GMT_May', 'GMT_Min30_35', 'GMT_Min33', 'GMT_Q3', 'GMT_Wednesday',
* 'GMT_Yr2024'
*/
const time_t timestamp = 1716989621;
StringSet *time_classes = GetTimeClasses(timestamp);
StringSetIterator iter = StringSetIteratorInit(time_classes);
const char *time_class = NULL;
while((time_class = StringSetIteratorNext(&iter)) != NULL) {
printf("Time class: %s\n", time_class);
}
assert_true(EvalWithTokenFromList("GMT_Wednesday", time_classes));
assert_false(EvalWithTokenFromList("GMT_Monday", time_classes));
assert_false(EvalWithTokenFromList("GMT_Wednesday.GMT_Monday", time_classes));
assert_true(EvalWithTokenFromList("GMT_Monday|GMT_Wednesday", time_classes));
assert_true(EvalWithTokenFromList("!GMT_Monday", time_classes));
StringSetDestroy(time_classes);
}
int main()
{
PRINT_TEST_BANNER();
tests_setup();
const UnitTest tests[] =
{
unit_test(test_class_persistence),
unit_test(test_changes_chroot),
unit_test(test_eval_with_token_from_list),
};
int ret = run_tests(tests);
tests_teardown();
return ret;
}
|