test-bus-match.c revision cc65fe5e14770d0116e0f475c5dc2ef57113bc98
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Foster/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Foster
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Foster/***
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Foster This file is part of systemd.
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Foster
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Foster Copyright 2013 Lennart Poettering
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Foster
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Foster systemd is free software; you can redistribute it and/or modify it
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Foster under the terms of the GNU Lesser General Public License as published by
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Foster the Free Software Foundation; either version 2.1 of the License, or
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Foster (at your option) any later version.
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Foster
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Foster systemd is distributed in the hope that it will be useful, but
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Foster WITHOUT ANY WARRANTY; without even the implied warranty of
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Foster MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Foster Lesser General Public License for more details.
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Foster
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Foster You should have received a copy of the GNU Lesser General Public License
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Foster along with systemd; If not, see <http://www.gnu.org/licenses/>.
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Foster***/
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Foster
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Foster#include "log.h"
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Foster#include "macro.h"
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Foster
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Foster#include "bus-match.h"
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Foster#include "bus-message.h"
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Foster#include "bus-util.h"
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Foster#include "bus-slot.h"
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Foster
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Fosterstatic bool mask[32];
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Foster
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Fosterstatic int filter(sd_bus_message *m, void *userdata, sd_bus_error *ret_error) {
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Foster log_info("Ran %u", PTR_TO_UINT(userdata));
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Foster assert_se(PTR_TO_UINT(userdata) < ELEMENTSOF(mask));
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Foster mask[PTR_TO_UINT(userdata)] = true;
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Foster return 0;
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Foster}
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Foster
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Fosterstatic bool mask_contains(unsigned a[], unsigned n) {
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Foster unsigned i, j;
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Foster
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Foster for (i = 0; i < ELEMENTSOF(mask); i++) {
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Foster bool found = false;
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Foster
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Foster for (j = 0; j < n; j++)
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Foster if (a[j] == i) {
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Foster found = true;
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Foster break;
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Foster }
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Foster
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Foster if (found != mask[i])
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Foster return false;
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Foster }
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Foster
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Foster return true;
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Foster}
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Foster
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Fosterstatic int match_add(sd_bus_slot *slots, struct bus_match_node *root, const char *match, int value) {
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Foster struct bus_match_component *components = NULL;
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Foster unsigned n_components = 0;
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Foster sd_bus_slot *s;
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Foster int r;
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Foster
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Foster s = slots + value;
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Foster zero(*s);
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Foster
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Foster r = bus_match_parse(match, &components, &n_components);
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Foster if (r < 0)
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Foster return r;
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Foster
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Foster s->userdata = INT_TO_PTR(value);
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Foster s->match_callback.callback = filter;
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Foster
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Foster r = bus_match_add(root, components, n_components, &s->match_callback);
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Foster bus_match_parse_free(components, n_components);
return r;
}
static void test_match_scope(const char *match, enum bus_match_scope scope) {
struct bus_match_component *components = NULL;
unsigned n_components = 0;
assert_se(bus_match_parse(match, &components, &n_components) >= 0);
assert_se(bus_match_get_scope(components, n_components) == scope);
bus_match_parse_free(components, n_components);
}
int main(int argc, char *argv[]) {
struct bus_match_node root = {
.type = BUS_MATCH_ROOT,
};
_cleanup_bus_message_unref_ sd_bus_message *m = NULL;
_cleanup_bus_close_unref_ sd_bus *bus = NULL;
enum bus_match_node_type i;
sd_bus_slot slots[19];
int r;
r = sd_bus_open_system(&bus);
if (r < 0)
return EXIT_TEST_SKIP;
assert_se(match_add(slots, &root, "arg2='wal\\'do',sender='foo',type='signal',interface='bar.x',", 1) >= 0);
assert_se(match_add(slots, &root, "arg2='wal\\'do2',sender='foo',type='signal',interface='bar.x',", 2) >= 0);
assert_se(match_add(slots, &root, "arg3='test',sender='foo',type='signal',interface='bar.x',", 3) >= 0);
assert_se(match_add(slots, &root, "arg3='test',sender='foo',type='method_call',interface='bar.x',", 4) >= 0);
assert_se(match_add(slots, &root, "", 5) >= 0);
assert_se(match_add(slots, &root, "interface='quux.x'", 6) >= 0);
assert_se(match_add(slots, &root, "interface='bar.x'", 7) >= 0);
assert_se(match_add(slots, &root, "member='waldo',path='/foo/bar'", 8) >= 0);
assert_se(match_add(slots, &root, "path='/foo/bar'", 9) >= 0);
assert_se(match_add(slots, &root, "path_namespace='/foo'", 10) >= 0);
assert_se(match_add(slots, &root, "path_namespace='/foo/quux'", 11) >= 0);
assert_se(match_add(slots, &root, "arg1='two'", 12) >= 0);
assert_se(match_add(slots, &root, "member='waldo',arg2path='/prefix/'", 13) >= 0);
assert_se(match_add(slots, &root, "member=waldo,path='/foo/bar',arg3namespace='prefix'", 14) >= 0);
assert_se(match_add(slots, &root, "arg4='pi'", 15) >= 0);
assert_se(match_add(slots, &root, "arg4='pa'", 16) >= 0);
assert_se(match_add(slots, &root, "arg4='po'", 17) >= 0);
assert_se(match_add(slots, &root, "arg4='pu'", 18) >= 0);
bus_match_dump(&root, 0);
assert_se(sd_bus_message_new_signal(bus, &m, "/foo/bar", "bar.x", "waldo") >= 0);
assert_se(sd_bus_message_append(m, "ssssas", "one", "two", "/prefix/three", "prefix.four", 3, "pi", "pa", "po") >= 0);
assert_se(bus_message_seal(m, 1, 0) >= 0);
zero(mask);
assert_se(bus_match_run(NULL, &root, m) == 0);
assert_se(mask_contains((unsigned[]) { 9, 8, 7, 5, 10, 12, 13, 14, 15, 16, 17 }, 11));
assert_se(bus_match_remove(&root, &slots[8].match_callback) >= 0);
assert_se(bus_match_remove(&root, &slots[13].match_callback) >= 0);
bus_match_dump(&root, 0);
zero(mask);
assert_se(bus_match_run(NULL, &root, m) == 0);
assert_se(mask_contains((unsigned[]) { 9, 5, 10, 12, 14, 7, 15, 16, 17 }, 9));
for (i = 0; i < _BUS_MATCH_NODE_TYPE_MAX; i++) {
char buf[32];
const char *x;
assert_se(x = bus_match_node_type_to_string(i, buf, sizeof(buf)));
if (i >= BUS_MATCH_MESSAGE_TYPE)
assert_se(bus_match_node_type_from_string(x, strlen(x)) == i);
}
bus_match_free(&root);
test_match_scope("interface='foobar'", BUS_MATCH_GENERIC);
test_match_scope("", BUS_MATCH_GENERIC);
test_match_scope("interface='org.freedesktop.DBus.Local'", BUS_MATCH_LOCAL);
test_match_scope("sender='org.freedesktop.DBus.Local'", BUS_MATCH_LOCAL);
test_match_scope("member='gurke',path='/org/freedesktop/DBus/Local'", BUS_MATCH_LOCAL);
test_match_scope("arg2='piep',sender='org.freedesktop.DBus',member='waldo'", BUS_MATCH_DRIVER);
return 0;
}