{
"rules":[
- {"event":"vconf_key_changed", "key_name":"file/activationd/acceptance", "newval":"START", "action":"StartUnit", "target":"activationd-acceptance-test.service"},
- {"event":"vconf_key_changed", "key_name":"file/activationd/acceptance", "newval":"STOP", "action":"StopUnit", "target":"activationd-acceptance-test.service"},
- {"event":"vconf_key_changed", "key_name":"file/activationd/acceptance", "newval":"RELOAD", "action":"RestartUnit", "target":"activationd-acceptance-test.service"}
+ {"event":"vconf_key_changed", "key_name":"file/activationd/acceptance_string_p", "newval":"START", "action":"StartUnit", "target":"activationd-acceptance-test-s-p.service"},
+ {"event":"vconf_key_changed", "key_name":"file/activationd/acceptance_string_p", "newval":"STOP", "action":"StopUnit", "target":"activationd-acceptance-test-s-p.service"},
+ {"event":"vconf_key_changed", "key_name":"file/activationd/acceptance_string_p", "newval":"RELOAD", "action":"RestartUnit", "target":"activationd-acceptance-test-s-p.service"},
+ {"event":"vconf_key_changed", "key_name":"file/activationd/acceptance_string_n", "newval":"START", "action":"StartUnit", "target":"activationd-acceptance-test-s-n.service"},
+ {"event":"vconf_key_changed", "key_name":"file/activationd/acceptance_string_n", "newval":"STOP", "action":"StopUnit", "target":"activationd-acceptance-test-s-n.service"},
+ {"event":"vconf_key_changed", "key_name":"file/activationd/acceptance_string_n", "newval":"RELO", "action":"RestartUnit", "target":"activationd-acceptance-test-s-n.service"},
+ {"event":"vconf_key_changed", "key_name":"file/activationd/acceptance_int_p", "newval":1, "action":"StartUnit", "target":"activationd-acceptance-test-i-p.service"},
+ {"event":"vconf_key_changed", "key_name":"file/activationd/acceptance_int_p", "oldval":2, "newval":3, "action":"StopUnit", "target":"activationd-acceptance-test-i-p.service"},
+ {"event":"vconf_key_changed", "key_name":"file/activationd/acceptance_int_p", "oldval":1, "newval":2, "action":"RestartUnit", "target":"activationd-acceptance-test-i-p.service"},
+ {"event":"vconf_key_changed", "key_name":"file/activationd/acceptance_int_n", "newval":2, "action":"StartUnit", "target":"activationd-acceptance-test-i-n.service"},
+ {"event":"vconf_key_changed", "key_name":"file/activationd/acceptance_int_n", "oldval":1, "newval":0, "action":"StopUnit", "target":"activationd-acceptance-test-i-n.service"},
+ {"event":"vconf_key_changed", "key_name":"file/activationd/acceptance_int_n", "oldval":1, "newval":1, "action":"RestartUnit", "target":"activationd-acceptance-test-i-n.service"},
+ {"event":"vconf_key_changed", "key_name":"file/activationd/acceptance_double_p", "newval":1.1, "action":"StartUnit", "target":"activationd-acceptance-test-d-p.service"},
+ {"event":"vconf_key_changed", "key_name":"file/activationd/acceptance_double_p", "oldval":1.2, "newval":1.3, "action":"StopUnit", "target":"activationd-acceptance-test-d-p.service"},
+ {"event":"vconf_key_changed", "key_name":"file/activationd/acceptance_double_p", "oldval":1.1, "newval":1.2, "action":"RestartUnit", "target":"activationd-acceptance-test-d-p.service"},
+ {"event":"vconf_key_changed", "key_name":"file/activationd/acceptance_double_n", "newval":1.1, "action":"StartUnit", "target":"activationd-acceptance-test-d-n.service"},
+ {"event":"vconf_key_changed", "key_name":"file/activationd/acceptance_double_n", "oldval":1.2, "newval":1.1, "action":"StopUnit", "target":"activationd-acceptance-test-d-n.service"},
+ {"event":"vconf_key_changed", "key_name":"file/activationd/acceptance_double_n", "oldval":1.1, "newval":1.2, "action":"RestartUnit", "target":"activationd-acceptance-test-d-n.service"},
+ {"event":"vconf_key_changed", "key_name":"file/activationd/acceptance_bool_p", "oldval":false, "newval":true, "action":"StartUnit", "target":"activationd-acceptance-test-b-p.service"},
+ {"event":"vconf_key_changed", "key_name":"file/activationd/acceptance_bool_p", "oldval":true, "newval":false, "action":"StopUnit", "target":"activationd-acceptance-test-b-p.service"},
+ {"event":"vconf_key_changed", "key_name":"file/activationd/acceptance_bool_p", "oldval":true, "newval":true, "action":"RestartUnit", "target":"activationd-acceptance-test-b-p.service"},
+ {"event":"vconf_key_changed", "key_name":"file/activationd/acceptance_bool_n", "oldval":true, "newval":true, "action":"StartUnit", "target":"activationd-acceptance-test-b-n.service"},
+ {"event":"vconf_key_changed", "key_name":"file/activationd/acceptance_bool_n", "oldval":true, "newval":false, "action":"StopUnit", "target":"activationd-acceptance-test-b-n.service"},
+ {"event":"vconf_key_changed", "key_name":"file/activationd/acceptance_bool_n", "oldval":true, "newval":true, "action":"RestartUnit", "target":"activationd-acceptance-test-b-n.service"}
]
}
#include "common.h"
#include "systemd_dbus.h"
+#include "systemd_dbus.h"
+#include "vconf_key_changed_event.h"
#define DBUS_PROPERTIES_INTERFACE "org.freedesktop.DBus.Properties"
-#define SERVICE_NAME "activationd-acceptance-test.service"
-#define VCONF_ACTIVATION_KEY "file/activationd/acceptance"
+#define SERVICE_NAME_S_P "activationd-acceptance-test-s-p.service"
+#define SERVICE_NAME_S_N "activationd-acceptance-test-s-n.service"
+#define SERVICE_NAME_I_P "activationd-acceptance-test-i-p.service"
+#define SERVICE_NAME_I_N "activationd-acceptance-test-i-n.service"
+#define SERVICE_NAME_D_P "activationd-acceptance-test-d-p.service"
+#define SERVICE_NAME_D_N "activationd-acceptance-test-d-n.service"
+#define SERVICE_NAME_B_P "activationd-acceptance-test-b-p.service"
+#define SERVICE_NAME_B_N "activationd-acceptance-test-b-n.service"
+#define VCONF_KEY_S_P "file/activationd/acceptance_string_p"
+#define VCONF_KEY_S_N "file/activationd/acceptance_string_n"
+#define VCONF_KEY_I_P "file/activationd/acceptance_int_p"
+#define VCONF_KEY_I_N "file/activationd/acceptance_int_n"
+#define VCONF_KEY_D_P "file/activationd/acceptance_double_p"
+#define VCONF_KEY_D_N "file/activationd/acceptance_double_n"
+#define VCONF_KEY_B_P "file/activationd/acceptance_bool_p"
+#define VCONF_KEY_B_N "file/activationd/acceptance_bool_n"
enum unit_state {
UNKNOWN,
INACTIVE
};
+enum {
+ TEST_FAIL,
+ TEST_SUCCESS,
+ TEST_UNKNOWN
+};
+
struct action {
- const char *action;
+ struct vkc_value action;
enum unit_state expected_states[2];
int state_count;
int current_state;
};
struct test_sequence {
+ const char *desc;
struct action actions[3];
+ const char *key;
int current_action;
- int ok;
+ int expected_result;
+ int result;
+ char *unit;
+ char *path;
};
struct test_data {
sd_bus *bus;
sd_event *loop;
- struct test_sequence test;
+ sd_event_source *step_timer;
+ struct test_sequence *tests;
+ int tests_count;
+ int current_test;
enum unit_state state;
enum unit_state prev_state;
- char *path;
};
+int test_step(struct test_data *data);
+
+static struct test_sequence acceptance_tests[] = {
+ {
+ .desc = "string (positive test)",
+ .actions = {
+ {{.type = VKC_STRING, .value.s = "START"}, {ACTIVE, UNKNOWN}, 1, 0},
+ {{.type = VKC_STRING, .value.s = "RELOAD"}, {INACTIVE, ACTIVE}, 2, 0},
+ {{.type = VKC_STRING, .value.s = "STOP"}, {INACTIVE, UNKNOWN}, 1, 0}
+ },
+ .key = VCONF_KEY_S_P,
+ .unit = SERVICE_NAME_S_P,
+ .path = NULL,
+ .expected_result = TEST_SUCCESS,
+ .result = TEST_UNKNOWN,
+ .current_action = 0
+ },
+ {
+ .desc = "string (negative test)",
+ .actions = {
+ {{.type = VKC_STRING, .value.s = "START"}, {ACTIVE, UNKNOWN}, 1, 0},
+ {{.type = VKC_STRING, .value.s = "RELOAD"}, {INACTIVE, ACTIVE}, 2, 0},
+ {{.type = VKC_STRING, .value.s = "STOP"}, {INACTIVE, UNKNOWN}, 1, 0}
+ },
+ .key = VCONF_KEY_S_N,
+ .unit = SERVICE_NAME_S_N,
+ .path = NULL,
+ .expected_result = TEST_FAIL,
+ .result = TEST_UNKNOWN,
+ .current_action = 0
+ },
+ {
+ .desc = "int (positive test)",
+ .actions = {
+ {{.type = VKC_INT, .value.i = 1}, {ACTIVE, UNKNOWN}, 1, 0},
+ {{.type = VKC_INT, .value.i = 2}, {INACTIVE, ACTIVE}, 2, 0},
+ {{.type = VKC_INT, .value.i = 3}, {INACTIVE, UNKNOWN}, 1, 0}
+ },
+ .key = VCONF_KEY_I_P,
+ .unit = SERVICE_NAME_I_P,
+ .path = NULL,
+ .expected_result = TEST_SUCCESS,
+ .result = TEST_UNKNOWN,
+ .current_action = 0
+ },
+ {
+ .desc = "int (negative test)",
+ .actions = {
+ {{.type = VKC_INT, .value.i = 1}, {ACTIVE, UNKNOWN}, 1, 0},
+ {{.type = VKC_INT, .value.i = 2}, {INACTIVE, ACTIVE}, 2, 0},
+ {{.type = VKC_INT, .value.i = 3}, {INACTIVE, UNKNOWN}, 1, 0}
+ },
+ .key = VCONF_KEY_I_N,
+ .unit = SERVICE_NAME_I_N,
+ .path = NULL,
+ .expected_result = TEST_FAIL,
+ .result = TEST_UNKNOWN,
+ .current_action = 0
+ },
+ {
+ .desc = "double (positive test)",
+ .actions = {
+ {{.type = VKC_DOUBLE, .value.d = 1.1}, {ACTIVE, UNKNOWN}, 1, 0},
+ {{.type = VKC_DOUBLE, .value.d = 1.2}, {INACTIVE, ACTIVE}, 2, 0},
+ {{.type = VKC_DOUBLE, .value.d = 1.3}, {INACTIVE, UNKNOWN}, 1, 0}
+ },
+ .key = VCONF_KEY_D_P,
+ .unit = SERVICE_NAME_D_P,
+ .path = NULL,
+ .expected_result = TEST_SUCCESS,
+ .result = TEST_UNKNOWN,
+ .current_action = 0
+ },
+ {
+ .desc = "double (negative test)",
+ .actions = {
+ {{.type = VKC_DOUBLE, .value.d = 1.1}, {ACTIVE, UNKNOWN}, 1, 0},
+ {{.type = VKC_DOUBLE, .value.d = 1.2}, {INACTIVE, ACTIVE}, 2, 0},
+ {{.type = VKC_DOUBLE, .value.d = 1.3}, {INACTIVE, UNKNOWN}, 1, 0}
+ },
+ .key = VCONF_KEY_D_N,
+ .unit = SERVICE_NAME_D_N,
+ .path = NULL,
+ .expected_result = TEST_FAIL,
+ .result = TEST_UNKNOWN,
+ .current_action = 0
+ },
+ {
+ .desc = "bool (positive test)",
+ .actions = {
+ {{.type = VKC_BOOL, .value.b = true}, {ACTIVE, UNKNOWN}, 1, 0},
+ {{.type = VKC_BOOL, .value.b = true}, {INACTIVE, ACTIVE}, 2, 0},
+ {{.type = VKC_BOOL, .value.b = false}, {INACTIVE, UNKNOWN}, 1, 0}
+ },
+ .key = VCONF_KEY_B_P,
+ .unit = SERVICE_NAME_B_P,
+ .path = NULL,
+ .expected_result = TEST_SUCCESS,
+ .result = TEST_UNKNOWN,
+ .current_action = 0
+ },
+ {
+ .desc = "bool (negative test)",
+ .actions = {
+ {{.type = VKC_BOOL, .value.b = true}, {ACTIVE, UNKNOWN}, 1, 0},
+ {{.type = VKC_BOOL, .value.b = true}, {INACTIVE, ACTIVE}, 2, 0},
+ {{.type = VKC_BOOL, .value.b = false}, {INACTIVE, UNKNOWN}, 1, 0}
+ },
+ .key = VCONF_KEY_B_N,
+ .unit = SERVICE_NAME_B_N,
+ .path = NULL,
+ .expected_result = TEST_FAIL,
+ .result = TEST_UNKNOWN,
+ .current_action = 0
+ }
+};
+
+static const char *test_result(int r)
+{
+ if (r == TEST_SUCCESS)
+ return "success";
+ else if (r == TEST_FAIL)
+ return "fail";
+ else
+ return "unknown";
+}
+
static const char *from_unit_state(enum unit_state state)
{
switch (state) {
return UNKNOWN;
}
-static int set_vconf_key(const char *val)
+static int set_vconf_key(const char *key, const struct vkc_value val)
{
+ assert (key);
+
keylist_t *kl = NULL;
kl = vconf_keylist_new();
if (!kl) {
fprintf(stderr, "error creating vconf keylists\n");
return -1;
}
-
- vconf_keylist_add_str(kl, VCONF_ACTIVATION_KEY, val);
+ switch (val.type) {
+ case VKC_STRING:
+ vconf_keylist_add_str(kl, key, val.value.s);
+ break;
+ case VKC_INT:
+ vconf_keylist_add_int(kl, key, val.value.i);
+ break;
+ case VKC_DOUBLE:
+ vconf_keylist_add_dbl(kl, key, val.value.d);
+ break;
+ case VKC_BOOL:
+ vconf_keylist_add_bool(kl, key, val.value.b);
+ break;
+ default:
+ vconf_keylist_free(kl);
+ return -1;
+ }
if (vconf_set(kl) < 0) {
fprintf(stderr, "error saving vconf key\n");
vconf_keylist_free(kl);
return 0;
}
-static int test_step(struct test_data *data)
+static void next_test(struct test_data *data)
{
- struct test_sequence *test = &data->test;
- if (test->current_action == ARRAY_SIZE(test->actions)) {
+ data->state = UNKNOWN;
+ data->prev_state = UNKNOWN;
+ data->current_test++;
+
+ test_step(data);
+}
+
+static int on_test_step_timeout(sd_event_source *s, uint64_t usec, void *userdata)
+{
+ struct test_data *data = (struct test_data *)userdata;
+ struct test_sequence *test = &data->tests[data->current_test];
+
+ test->result = TEST_FAIL;
+ next_test(data);
+ return 0;
+}
+
+static void stop_test_step_timeout(struct test_data *data)
+{
+ int enabled;
+ sd_event_source_get_enabled(data->step_timer, &enabled);
+
+ if (enabled != SD_EVENT_OFF)
+ sd_event_source_set_enabled(data->step_timer, SD_EVENT_OFF);
+}
+
+static int start_test_step_timeout(struct test_data *data)
+{
+ int r;
+ uint64_t now;
+ char err[512];
+
+ sd_event_now(data->loop, CLOCK_REALTIME, &now);
+ r = sd_event_add_time(data->loop, &data->step_timer, CLOCK_REALTIME, now+2000000, 0, on_test_step_timeout, data);
+ if (r < 0) {
+ if (strerror_r(-r, err, sizeof err))
+ fprintf(stderr, "Failed to attach timer to event loop: %s\n", err);
+ return r;
+ }
+
+ return 0;
+}
+
+int test_step(struct test_data *data)
+{
+ struct test_sequence *test;
+
+ stop_test_step_timeout(data);
+
+ /* last test */
+ if (data->current_test == data->tests_count) {
sd_event_exit(data->loop, EXIT_SUCCESS);
- test->ok = 1;
return 0;
}
+ test = &data->tests[data->current_test];
- if (set_vconf_key(test->actions[test->current_action].action))
+ if (test->current_action == ARRAY_SIZE(test->actions)) {
+ test->result = TEST_SUCCESS;
+ next_test(data);
+ return 0;
+ }
+
+ if (set_vconf_key(test->key, test->actions[test->current_action].action))
return -1;
+ start_test_step_timeout(data);
return 0;
}
static int check_test_result(struct test_data *data)
{
- struct action *a = &data->test.actions[data->test.current_action];
+ struct test_sequence *test = &data->tests[data->current_test];
+ struct action *a = &test->actions[test->current_action];
enum unit_state exp_state = a->expected_states[a->current_state];
- if (data->test.ok == 1)
- return 0;
if (data->state != exp_state) {
- data->test.ok = 1;
- fprintf(stderr, "test failed (%s instead of %s at step %d of %s)\n",
+ fprintf(stderr, "test failed (%s instead of %s at step %d of test %d)\n",
from_unit_state(data->state),
from_unit_state(exp_state),
a->current_state,
- a->action);
-
- sd_event_exit(data->loop, EXIT_FAILURE);
+ data->current_test);
+ test->result = TEST_FAIL;
+ next_test(data);
return -1;
}
a->current_state++;
if (a->current_state == a->state_count) {
- data->test.current_action++;
+ test->current_action++;
if (test_step(data) < 0)
return -1;
}
return 0;
}
-
static int check_unit_state(struct test_data *data, const char *state)
{
enum unit_state new_state;
return 0;
}
-
static int on_properties_changed(sd_bus_message *m, void *userdata, sd_bus_error *ret_error) {
int r;
struct test_data *data = (struct test_data*)userdata;
static void cleanup(struct test_data *data)
{
- free(data->path);
+ for (int i = 0; i < data->tests_count; i++)
+ free(data->tests[i].path);
if (!data->bus)
return;
sd_bus_flush(data->bus);
const char *path = NULL;
char err[512];
- ret = sd_bus_call_method(data->bus,
- SYSTEMD_SERVICE,
- SYSTEMD_OBJ,
- SYSTEMD_MANAGER_INTERFACE,
- "LoadUnit",
- &error,
- &reply,
- "s",
- SERVICE_NAME);
+ for (int i = 0; i < data->tests_count; i++) {
+ ret = sd_bus_call_method(data->bus,
+ SYSTEMD_SERVICE,
+ SYSTEMD_OBJ,
+ SYSTEMD_MANAGER_INTERFACE,
+ "LoadUnit",
+ &error,
+ &reply,
+ "s",
+ data->tests[i].unit);
+
+ if (ret < 0) {
+ fprintf(stderr, "Failed to issue LoadUnit() call: %s\n", error.message);
+ return -1;
+ }
- if (ret < 0) {
- fprintf(stderr, "Failed to issue LoadUnit() call: %s\n", error.message);
- return -1;
- }
+ ret = sd_bus_message_read(reply, "o", &path);
+ if (ret < 0) {
+ if (strerror_r(-ret, err, sizeof err))
+ fprintf(stderr, "Failed to read reply: %s\n", err);
+ return -1;
+ }
- ret = sd_bus_message_read(reply, "o", &path);
- if (ret < 0) {
- if (strerror_r(-ret, err, sizeof err))
- fprintf(stderr, "Failed to read reply: %s\n", err);
- return -1;
+ if (!path) {
+ fprintf(stderr, "ould not get object path\n");
+ return -1;
+ }
+ data->tests[i].path = strdup(path);
}
+ return 0;
+}
- if (!path) {
- fprintf(stderr, "ould not get object path\n");
- return -1;
+static int print_results(struct test_data *data)
+{
+ int ret = 0;
+ for (int i = 0; i < data->tests_count; i++) {
+ printf("testing %s - expected %s, got %s\n",
+ data->tests[i].desc,
+ test_result(data->tests[i].expected_result),
+ test_result(data->tests[i].result));
+ if (data->tests[i].expected_result != data->tests[i].result)
+ ret = 1;
}
- data->path = strdup(path);
- return 0;
+ return ret;
}
+
int main(int argc, char *argv[])
{
struct test_data data = {
.bus = NULL,
.loop = NULL,
+ .step_timer = NULL,
.state = UNKNOWN,
.prev_state = UNKNOWN,
- .path = NULL,
- .test = {
- .actions = {
- {"START", {ACTIVE, UNKNOWN}, 1, 0},
- {"RELOAD", {INACTIVE, ACTIVE}, 2, 0},
- {"STOP", {INACTIVE, UNKNOWN}, 1, 0}
- },
- .current_action = 0,
- .ok = 0
- }
+ .tests = acceptance_tests,
+ .tests_count = ARRAY_SIZE(acceptance_tests),
+ .current_test = 0
};
int r;
if (r < 0)
goto fail;
- r = snprintf(buf, sizeof buf, "type='signal',interface='org.freedesktop.DBus.Properties',member='PropertiesChanged', path='%s'", data.path);
- if (r < 0) {
- if (strerror_r(-r, err, sizeof err))
- fprintf(stderr, "Failed to create match rule: %s\n", err);
- goto fail;
- }
+ for (int i = 0; i < data.tests_count; i++) {
+ r = snprintf(buf, sizeof buf, "type='signal',interface='org.freedesktop.DBus.Properties',member='PropertiesChanged', path='%s'", data.tests[i].path);
+ if (r < 0) {
+ if (strerror_r(-r, err, sizeof err))
+ fprintf(stderr, "Failed to create match rule: %s\n", err);
+ goto fail;
+ }
- r = sd_bus_add_match(data.bus, NULL, buf, on_properties_changed, &data);
- if (r < 0) {
- if (strerror_r(-r, err, sizeof err))
- fprintf(stderr, "Failed to add PropertiesChanged match: %s\n", err);
- goto fail;
+ r = sd_bus_add_match(data.bus, NULL, buf, on_properties_changed, &data);
+ if (r < 0) {
+ if (strerror_r(-r, err, sizeof err))
+ fprintf(stderr, "Failed to add PropertiesChanged match: %s\n", err);
+ goto fail;
+ }
}
r = sd_event_new(&data.loop);
goto fail;
}
+ /* time out all tests after 30sec */
sd_event_now(data.loop, CLOCK_REALTIME, &now);
- r = sd_event_add_time(data.loop, NULL, CLOCK_REALTIME, now+10000000, 0, timeout_handler, &data);
+ r = sd_event_add_time(data.loop, NULL, CLOCK_REALTIME, now+30000000, 0, timeout_handler, &data);
if (r < 0) {
if (strerror_r(-r, err, sizeof err))
fprintf(stderr, "Failed to attach timer to event loop: %s\n", err);
goto fail;
}
+ r = print_results(&data);
cleanup(&data);
return r;