/*
* This file is part of Cockpit.
*
* Copyright (C) 2014 Red Hat, Inc.
*
* Cockpit is free software; you can redistribute it and/or modify it
* under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation; either version 2.1 of the License, or
* (at your option) any later version.
*
* Cockpit is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with Cockpit; If not, see .
*/
#include "config.h"
#include "cockpitdbusrules.h"
#include "common/cockpittest.h"
#include
typedef struct {
CockpitDBusRules *rules;
} TestCase;
typedef struct {
const gchar *path;
gboolean is_namespace;
const gchar *interface;
const gchar *member;
const gchar *arg0;
} TestRule;
static const TestRule default_rules[] = {
{ "/otree", TRUE, NULL, NULL, NULL },
{ "/scruffy/the/janitor", FALSE, NULL, "Marmalade", NULL },
{ "/planetexpress", TRUE, "org.PlanetExpress.Interface", NULL, NULL },
{ "/arg", FALSE, NULL, NULL, "Durn" },
{ NULL, }
};
static const TestRule empty_rules[] = {
{ NULL, }
};
static const TestRule path_rules[] = {
{ "/otree", TRUE, NULL, NULL, NULL },
{ "/scruffy/the/janitor", FALSE, NULL, NULL, NULL },
{ "/planetexpress", TRUE, NULL, NULL, NULL },
{ "/arg", FALSE, NULL, NULL, NULL },
{ NULL, }
};
static void
setup (TestCase *test,
gconstpointer data)
{
const TestRule *rules = data;
gint i;
if (!rules)
rules = default_rules;
test->rules = cockpit_dbus_rules_new ();
for (i = 0; rules[i].path != NULL; i++)
{
cockpit_dbus_rules_add (test->rules, rules[i].path, rules[i].is_namespace,
rules[i].interface, rules[i].member, rules[i].arg0);
}
}
static void
teardown (TestCase *test,
gconstpointer data)
{
cockpit_assert_expected ();
cockpit_dbus_rules_free (test->rules);
}
static void
test_basics (TestCase *test,
gconstpointer fixture)
{
/* Should all match, only based on path */
g_assert (cockpit_dbus_rules_match (test->rules, "/otree/blah", NULL, NULL, NULL) == TRUE);
g_assert (cockpit_dbus_rules_match (test->rules, "/otree/blah", "org.Interface", NULL, NULL) == TRUE);
g_assert (cockpit_dbus_rules_match (test->rules, "/otree/blah", "org.Interface", "Signal", NULL) == TRUE);
g_assert (cockpit_dbus_rules_match (test->rules, "/otree/blah", "org.Interface", NULL, "arg") == TRUE);
g_assert (cockpit_dbus_rules_match (test->rules, "/otree/blah", NULL, "Signal", "arg") == TRUE);
g_assert (cockpit_dbus_rules_match (test->rules, "/otree/blah", "org.Interface", "Signal", "arg") == TRUE);
g_assert (cockpit_dbus_rules_match (test->rules, "/otree/bark", "org.Interface", "Signal", "arg") == TRUE);
g_assert (cockpit_dbus_rules_match (test->rules, "/otree", "org.Interface", "Signal", "arg") == TRUE);
/* Mismatched path */
g_assert (cockpit_dbus_rules_match (test->rules, "/not", NULL, NULL, NULL) == FALSE);
g_assert (cockpit_dbus_rules_match (test->rules, "/not", "org.Interface", NULL, NULL) == FALSE);
g_assert (cockpit_dbus_rules_match (test->rules, "/not", "org.Interface", "Signal", NULL) == FALSE);
g_assert (cockpit_dbus_rules_match (test->rules, "/not", "org.Interface", NULL, "arg") == FALSE);
g_assert (cockpit_dbus_rules_match (test->rules, "/not", NULL, "Signal", "arg") == FALSE);
g_assert (cockpit_dbus_rules_match (test->rules, "/not", "org.Interface", "Signal", "arg") == FALSE);
/* Interfaces affect matching */
g_assert (cockpit_dbus_rules_match (test->rules, "/planetexpress", NULL, NULL, NULL) == TRUE);
g_assert (cockpit_dbus_rules_match (test->rules, "/planetexpress", "org.PlanetExpress.Interface", NULL, NULL) == TRUE);
g_assert (cockpit_dbus_rules_match (test->rules, "/planetexpress", "other.Interface", NULL, NULL) == FALSE);
g_assert (cockpit_dbus_rules_match (test->rules, "/planetexpress/sub", "org.PlanetExpress.Interface", NULL, NULL) == TRUE);
g_assert (cockpit_dbus_rules_match (test->rules, "/planetexpress/sub", "other.Interface", NULL, NULL) == FALSE);
/* Members affect matching */
g_assert (cockpit_dbus_rules_match (test->rules, "/scruffy/the/janitor", NULL, NULL, NULL) == TRUE);
g_assert (cockpit_dbus_rules_match (test->rules, "/scruffy/the/janitor", NULL, "Marmalade", NULL) == TRUE);
g_assert (cockpit_dbus_rules_match (test->rules, "/scruffy/the/janitor", NULL, "Other", NULL) == FALSE);
g_assert (cockpit_dbus_rules_match (test->rules, "/scruffy/the/janitor/sub", NULL, "Marmalade", NULL) == FALSE);
g_assert (cockpit_dbus_rules_match (test->rules, "/scruffy/the/janitor/sub", NULL, "Other", NULL) == FALSE);
/* Args affect matching */
g_assert (cockpit_dbus_rules_match (test->rules, "/arg", NULL, NULL, NULL) == FALSE);
g_assert (cockpit_dbus_rules_match (test->rules, "/arg", NULL, NULL, "Durn") == TRUE);
g_assert (cockpit_dbus_rules_match (test->rules, "/arg", NULL, NULL, "other") == FALSE);
g_assert (cockpit_dbus_rules_match (test->rules, "/arg/sub", NULL, NULL, "Durn") == FALSE);
g_assert (cockpit_dbus_rules_match (test->rules, "/arg/sub", NULL, NULL, "other") == FALSE);
g_assert (cockpit_dbus_rules_match (test->rules, "/arg/sub", NULL, NULL, NULL) == FALSE);
}
static void
test_nothing (TestCase *test,
gconstpointer fixture)
{
/* No rules should never match anything */
g_assert (cockpit_dbus_rules_match (test->rules, "/", NULL, NULL, NULL) == FALSE);
g_assert (cockpit_dbus_rules_remove (test->rules, NULL, FALSE, NULL, NULL, NULL) == FALSE);
}
static void
test_path_only (TestCase *test,
gconstpointer fixture)
{
/* Should all match, only based on path */
g_assert (cockpit_dbus_rules_match (test->rules, "/otree/blah", NULL, NULL, NULL) == TRUE);
g_assert (cockpit_dbus_rules_match (test->rules, "/otree/blah", "org.Interface", NULL, NULL) == TRUE);
g_assert (cockpit_dbus_rules_match (test->rules, "/otree/blah", "org.Interface", "Signal", NULL) == TRUE);
g_assert (cockpit_dbus_rules_match (test->rules, "/otree/blah", "org.Interface", NULL, "arg") == TRUE);
g_assert (cockpit_dbus_rules_match (test->rules, "/otree/blah", NULL, "Signal", "arg") == TRUE);
g_assert (cockpit_dbus_rules_match (test->rules, "/otree/blah", "org.Interface", "Signal", "arg") == TRUE);
g_assert (cockpit_dbus_rules_match (test->rules, "/otree/bark", "org.Interface", "Signal", "arg") == TRUE);
g_assert (cockpit_dbus_rules_match (test->rules, "/otree", "org.Interface", "Signal", "arg") == TRUE);
/* Mismatched path */
g_assert (cockpit_dbus_rules_match (test->rules, "/not", NULL, NULL, NULL) == FALSE);
g_assert (cockpit_dbus_rules_match (test->rules, "/not", "org.Interface", NULL, NULL) == FALSE);
g_assert (cockpit_dbus_rules_match (test->rules, "/not", "org.Interface", "Signal", NULL) == FALSE);
g_assert (cockpit_dbus_rules_match (test->rules, "/not", "org.Interface", NULL, "arg") == FALSE);
g_assert (cockpit_dbus_rules_match (test->rules, "/not", NULL, "Signal", "arg") == FALSE);
g_assert (cockpit_dbus_rules_match (test->rules, "/not", "org.Interface", "Signal", "arg") == FALSE);
}
static void
test_all_paths (TestCase *test,
gconstpointer fixture)
{
cockpit_dbus_rules_add (test->rules, "/", TRUE, NULL, NULL, NULL);
/* Should all match, only based on path */
g_assert (cockpit_dbus_rules_match (test->rules, "/otree/blah", NULL, NULL, NULL) == TRUE);
g_assert (cockpit_dbus_rules_match (test->rules, "/boring", NULL, NULL, NULL) == TRUE);
g_assert (cockpit_dbus_rules_match (test->rules, "/tettot", NULL, NULL, NULL) == TRUE);
g_assert (cockpit_dbus_rules_match (test->rules, "/aoenut", NULL, NULL, NULL) == TRUE);
}
static void
test_null_path (TestCase *test,
gconstpointer fixture)
{
/* Adds a global empty rule which should match everything */
cockpit_dbus_rules_add (test->rules, NULL, FALSE, NULL, NULL, NULL);
/* Should all match, only based on path */
g_assert (cockpit_dbus_rules_match (test->rules, "/otree/blah", NULL, NULL, NULL) == TRUE);
g_assert (cockpit_dbus_rules_match (test->rules, "/boring", NULL, NULL, NULL) == TRUE);
g_assert (cockpit_dbus_rules_match (test->rules, "/tettot", NULL, NULL, NULL) == TRUE);
g_assert (cockpit_dbus_rules_match (test->rules, "/aoenut", NULL, NULL, NULL) == TRUE);
cockpit_dbus_rules_remove (test->rules, NULL, FALSE, NULL, NULL, NULL);
g_assert (cockpit_dbus_rules_match (test->rules, "/otree/blah", NULL, NULL, NULL) == FALSE);
g_assert (cockpit_dbus_rules_match (test->rules, "/boring", NULL, NULL, NULL) == FALSE);
g_assert (cockpit_dbus_rules_match (test->rules, "/tettot", NULL, NULL, NULL) == FALSE);
g_assert (cockpit_dbus_rules_match (test->rules, "/aoenut", NULL, NULL, NULL) == FALSE);
}
static void
test_root_only (TestCase *test,
gconstpointer fixture)
{
/* This should only match the root path */
cockpit_dbus_rules_add (test->rules, "/", FALSE, NULL, NULL, NULL);
/* Should all match, only based on path */
g_assert (cockpit_dbus_rules_match (test->rules, "/", NULL, NULL, NULL) == TRUE);
g_assert (cockpit_dbus_rules_match (test->rules, "/boring", NULL, NULL, NULL) == FALSE);
g_assert (cockpit_dbus_rules_match (test->rules, "/tettot", NULL, NULL, NULL) == FALSE);
g_assert (cockpit_dbus_rules_match (test->rules, "/aoenut", NULL, NULL, NULL) == FALSE);
}
static void
test_add_ref_remove (TestCase *test,
gconstpointer fixture)
{
const TestRule *rules = default_rules;
gint i;
/* Add all the rules once */
for (i = 0; rules[i].path != NULL; i++)
{
g_assert (cockpit_dbus_rules_add (test->rules, rules[i].path, rules[i].is_namespace,
rules[i].interface, rules[i].member, rules[i].arg0) == TRUE);
}
/* Add them again, should always return FALSE here */
for (i = 0; rules[i].path != NULL; i++)
{
g_assert (cockpit_dbus_rules_add (test->rules, rules[i].path, rules[i].is_namespace,
rules[i].interface, rules[i].member, rules[i].arg0) == FALSE);
}
/* Add another rule */
g_assert (cockpit_dbus_rules_remove (test->rules, "/booo", FALSE, NULL, NULL, NULL) == FALSE);
g_assert (cockpit_dbus_rules_add (test->rules, "/booo", FALSE, NULL, NULL, NULL) == TRUE);
/* Now remove them, the first time shouldn't actually remove */
for (i = 0; rules[i].path != NULL; i++)
{
g_assert (cockpit_dbus_rules_remove (test->rules, rules[i].path, rules[i].is_namespace,
rules[i].interface, rules[i].member, rules[i].arg0) == FALSE);
}
/* The second time actually removes */
for (i = 0; rules[i].path != NULL; i++)
{
g_assert (cockpit_dbus_rules_remove (test->rules, rules[i].path, rules[i].is_namespace,
rules[i].interface, rules[i].member, rules[i].arg0) == TRUE);
}
g_assert (cockpit_dbus_rules_remove (test->rules, "/booo", FALSE, NULL, NULL, NULL) == TRUE);
g_assert (cockpit_dbus_rules_remove (test->rules, "/booo", FALSE, NULL, NULL, NULL) == FALSE);
}
int
main (int argc,
char *argv[])
{
cockpit_test_init (&argc, &argv);
g_test_add ("/rules/basics", TestCase, NULL,
setup, test_basics, teardown);
g_test_add ("/rules/nothing", TestCase, empty_rules,
setup, test_nothing, teardown);
g_test_add ("/rules/path-only", TestCase, path_rules,
setup, test_path_only, teardown);
g_test_add ("/rules/all-paths", TestCase, empty_rules,
setup, test_all_paths, teardown);
g_test_add ("/rules/root-only", TestCase, empty_rules,
setup, test_root_only, teardown);
g_test_add ("/rules/null-path", TestCase, empty_rules,
setup, test_null_path, teardown);
g_test_add ("/rules/add-ref-remove", TestCase, empty_rules,
setup, test_add_ref_remove, teardown);
return g_test_run ();
}