mirror of
https://gitlab.gnome.org/GNOME/glib.git
synced 2024-11-06 09:26:17 +01:00
tests: Add test coverage for signals that match the message bus's name
This is a special case of unique names, even though it's syntactically a well-known name. Signed-off-by: Simon McVittie <smcv@collabora.com>
This commit is contained in:
parent
b4b7411e67
commit
e6cd64c66c
@ -13,6 +13,7 @@
|
|||||||
#define DBUS_SERVICE_DBUS "org.freedesktop.DBus"
|
#define DBUS_SERVICE_DBUS "org.freedesktop.DBus"
|
||||||
#define DBUS_PATH_DBUS "/org/freedesktop/DBus"
|
#define DBUS_PATH_DBUS "/org/freedesktop/DBus"
|
||||||
#define DBUS_INTERFACE_DBUS DBUS_SERVICE_DBUS
|
#define DBUS_INTERFACE_DBUS DBUS_SERVICE_DBUS
|
||||||
|
#define NAME_OWNER_CHANGED "NameOwnerChanged"
|
||||||
|
|
||||||
/* A signal that each connection emits to indicate that it has finished
|
/* A signal that each connection emits to indicate that it has finished
|
||||||
* emitting other signals */
|
* emitting other signals */
|
||||||
@ -101,6 +102,7 @@ typedef struct
|
|||||||
const char *iface;
|
const char *iface;
|
||||||
const char *member;
|
const char *member;
|
||||||
const char *arg0;
|
const char *arg0;
|
||||||
|
const char *args;
|
||||||
guint received_by_conn;
|
guint received_by_conn;
|
||||||
guint received_by_proxy;
|
guint received_by_proxy;
|
||||||
} TestEmitSignal;
|
} TestEmitSignal;
|
||||||
@ -120,6 +122,8 @@ typedef struct
|
|||||||
{
|
{
|
||||||
const char *name;
|
const char *name;
|
||||||
TestConn owner;
|
TestConn owner;
|
||||||
|
guint received_by_conn;
|
||||||
|
guint received_by_proxy;
|
||||||
} TestOwnName;
|
} TestOwnName;
|
||||||
|
|
||||||
typedef enum
|
typedef enum
|
||||||
@ -461,6 +465,63 @@ static const TestPlan plan_limit_by_well_known_name =
|
|||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
|
static const TestPlan plan_limit_to_message_bus =
|
||||||
|
{
|
||||||
|
.description = "A subscription to the message bus only accepts messages "
|
||||||
|
"from the message bus",
|
||||||
|
.steps = {
|
||||||
|
{
|
||||||
|
/* Subscriber wants to receive signals from the message bus itself */
|
||||||
|
.action = TEST_ACTION_SUBSCRIBE,
|
||||||
|
.u.subscribe = {
|
||||||
|
.string_sender = DBUS_SERVICE_DBUS,
|
||||||
|
.path = DBUS_PATH_DBUS,
|
||||||
|
.iface = DBUS_INTERFACE_DBUS,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
/* Attacker wants to trick subscriber into thinking that the message
|
||||||
|
* bus sent a signal */
|
||||||
|
.action = TEST_ACTION_EMIT_SIGNAL,
|
||||||
|
.u.signal = {
|
||||||
|
.sender = TEST_CONN_ATTACKER,
|
||||||
|
.path = DBUS_PATH_DBUS,
|
||||||
|
.iface = DBUS_INTERFACE_DBUS,
|
||||||
|
.member = NAME_OWNER_CHANGED,
|
||||||
|
.arg0 = "would I lie to you?",
|
||||||
|
.received_by_conn = 0,
|
||||||
|
.received_by_proxy = 0
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
/* Attacker tries harder, by sending a signal unicast directly to
|
||||||
|
* the subscriber, and using more realistic arguments */
|
||||||
|
.action = TEST_ACTION_EMIT_SIGNAL,
|
||||||
|
.u.signal = {
|
||||||
|
.unicast_to = TEST_CONN_SUBSCRIBER,
|
||||||
|
.sender = TEST_CONN_ATTACKER,
|
||||||
|
.path = DBUS_PATH_DBUS,
|
||||||
|
.iface = DBUS_INTERFACE_DBUS,
|
||||||
|
.member = NAME_OWNER_CHANGED,
|
||||||
|
.args = "('com.example.Name', '', ':1.12')",
|
||||||
|
.received_by_conn = 0,
|
||||||
|
.received_by_proxy = 0
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
/* When the message bus sends a signal (in this case triggered by
|
||||||
|
* owning a name), it should still get through */
|
||||||
|
.action = TEST_ACTION_OWN_NAME,
|
||||||
|
.u.own_name = {
|
||||||
|
.name = OWNED_LATER_NAME,
|
||||||
|
.owner = TEST_CONN_SERVICE,
|
||||||
|
.received_by_conn = 1,
|
||||||
|
.received_by_proxy = 1
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
typedef struct
|
typedef struct
|
||||||
{
|
{
|
||||||
const TestPlan *plan;
|
const TestPlan *plan;
|
||||||
@ -591,7 +652,18 @@ fixture_received_signal (Fixture *f,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
g_assert_cmpint (received->sender, !=, TEST_CONN_NONE);
|
if (g_str_equal (sender_name, DBUS_SERVICE_DBUS))
|
||||||
|
{
|
||||||
|
g_test_message ("Signal received from message bus %s",
|
||||||
|
sender_name);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
g_test_message ("Signal received from %s %s",
|
||||||
|
test_conn_descriptions[received->sender],
|
||||||
|
sender_name);
|
||||||
|
g_assert_cmpint (received->sender, !=, TEST_CONN_NONE);
|
||||||
|
}
|
||||||
|
|
||||||
g_test_message ("Signal received from %s %s via %s",
|
g_test_message ("Signal received from %s %s via %s",
|
||||||
test_conn_descriptions[received->sender],
|
test_conn_descriptions[received->sender],
|
||||||
@ -607,13 +679,56 @@ fixture_received_signal (Fixture *f,
|
|||||||
g_test_message ("\tString argument 0: %s", received->arg0);
|
g_test_message ("\tString argument 0: %s", received->arg0);
|
||||||
g_test_message ("\tSent in step: %u", received->step);
|
g_test_message ("\tSent in step: %u", received->step);
|
||||||
}
|
}
|
||||||
else
|
else if (g_variant_is_of_type (parameters, G_VARIANT_TYPE ("(uu)")))
|
||||||
{
|
{
|
||||||
g_assert_cmpstr (g_variant_get_type_string (parameters), ==, "(uu)");
|
|
||||||
g_variant_get (parameters, "(uu)", NULL, &received->step);
|
g_variant_get (parameters, "(uu)", NULL, &received->step);
|
||||||
g_test_message ("\tArgument 0: (not a string)");
|
g_test_message ("\tArgument 0: (not a string)");
|
||||||
g_test_message ("\tSent in step: %u", received->step);
|
g_test_message ("\tSent in step: %u", received->step);
|
||||||
}
|
}
|
||||||
|
else if (g_variant_is_of_type (parameters, G_VARIANT_TYPE ("(sss)")))
|
||||||
|
{
|
||||||
|
const char *name;
|
||||||
|
const char *old_owner;
|
||||||
|
const char *new_owner;
|
||||||
|
|
||||||
|
/* The only signal of this signature that we legitimately receive
|
||||||
|
* during this test is NameOwnerChanged, so just assert that it
|
||||||
|
* is from the message bus and can be matched to a plausible step.
|
||||||
|
* (This is less thorough than the above, and will not work if we
|
||||||
|
* add a test scenario where a name's ownership is repeatedly
|
||||||
|
* changed while watching NameOwnerChanged - so don't do that.) */
|
||||||
|
g_assert_cmpstr (sender_name, ==, DBUS_SERVICE_DBUS);
|
||||||
|
g_assert_cmpstr (path, ==, DBUS_PATH_DBUS);
|
||||||
|
g_assert_cmpstr (iface, ==, DBUS_INTERFACE_DBUS);
|
||||||
|
g_assert_cmpstr (member, ==, NAME_OWNER_CHANGED);
|
||||||
|
|
||||||
|
g_variant_get (parameters, "(&s&s&s)", &name, &old_owner, &new_owner);
|
||||||
|
|
||||||
|
for (i = 0; i < G_N_ELEMENTS (f->plan->steps); i++)
|
||||||
|
{
|
||||||
|
const TestStep *step = &f->plan->steps[i];
|
||||||
|
|
||||||
|
if (step->action == TEST_ACTION_OWN_NAME)
|
||||||
|
{
|
||||||
|
const TestOwnName *own_name = &step->u.own_name;
|
||||||
|
|
||||||
|
if (g_str_equal (name, own_name->name)
|
||||||
|
&& g_str_equal (new_owner, f->unique_names[own_name->owner])
|
||||||
|
&& own_name->received_by_conn > 0)
|
||||||
|
{
|
||||||
|
received->step = i;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (i >= G_N_ELEMENTS (f->plan->steps))
|
||||||
|
g_error ("Could not match message to a test step");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
g_error ("Unexpected message received");
|
||||||
|
}
|
||||||
|
|
||||||
g_ptr_array_add (f->received, g_steal_pointer (&received));
|
g_ptr_array_add (f->received, g_steal_pointer (&received));
|
||||||
}
|
}
|
||||||
@ -782,10 +897,15 @@ fixture_emit_signal (Fixture *f,
|
|||||||
* Otherwise put something that will not match any arg0.
|
* Otherwise put something that will not match any arg0.
|
||||||
* Either way, put the sequence number in argument 1 so we can
|
* Either way, put the sequence number in argument 1 so we can
|
||||||
* correlate sent messages with received messages later. */
|
* correlate sent messages with received messages later. */
|
||||||
if (signal->arg0 != NULL)
|
if (signal->args != NULL)
|
||||||
|
{
|
||||||
|
/* floating */
|
||||||
|
body = g_variant_new_parsed (signal->args);
|
||||||
|
g_assert_nonnull (body);
|
||||||
|
}
|
||||||
|
else if (signal->arg0 != NULL)
|
||||||
{
|
{
|
||||||
g_test_message ("\tString argument 0: %s", signal->arg0);
|
g_test_message ("\tString argument 0: %s", signal->arg0);
|
||||||
/* floating */
|
|
||||||
body = g_variant_new ("(su)", signal->arg0, (guint32) step_number);
|
body = g_variant_new ("(su)", signal->arg0, (guint32) step_number);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
@ -933,8 +1053,6 @@ fixture_run_plan (Fixture *f,
|
|||||||
|
|
||||||
g_assert_cmpuint (received->step, <, G_N_ELEMENTS (f->received_by_conn));
|
g_assert_cmpuint (received->step, <, G_N_ELEMENTS (f->received_by_conn));
|
||||||
g_assert_cmpuint (received->step, <, G_N_ELEMENTS (f->received_by_proxy));
|
g_assert_cmpuint (received->step, <, G_N_ELEMENTS (f->received_by_proxy));
|
||||||
g_assert_cmpint (plan->steps[received->step].action,
|
|
||||||
==, TEST_ACTION_EMIT_SIGNAL);
|
|
||||||
|
|
||||||
if (received->received_by_proxy != NULL)
|
if (received->received_by_proxy != NULL)
|
||||||
f->received_by_proxy[received->step] += 1;
|
f->received_by_proxy[received->step] += 1;
|
||||||
@ -974,6 +1092,34 @@ fixture_run_plan (Fixture *f,
|
|||||||
g_assert_cmpuint (f->received_by_proxy[i], ==, 0);
|
g_assert_cmpuint (f->received_by_proxy[i], ==, 0);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
else if (step->action == TEST_ACTION_OWN_NAME)
|
||||||
|
{
|
||||||
|
const TestOwnName *own_name = &plan->steps[i].u.own_name;
|
||||||
|
|
||||||
|
if (mode != SUBSCRIPTION_MODE_PROXY)
|
||||||
|
{
|
||||||
|
g_test_message ("NameOwnerChanged from step %u was received %u "
|
||||||
|
"times by GDBusConnection, expected %u",
|
||||||
|
i, f->received_by_conn[i], own_name->received_by_conn);
|
||||||
|
g_assert_cmpuint (f->received_by_conn[i], ==, own_name->received_by_conn);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
g_assert_cmpuint (f->received_by_conn[i], ==, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (mode != SUBSCRIPTION_MODE_CONN)
|
||||||
|
{
|
||||||
|
g_test_message ("NameOwnerChanged from step %u was received %u "
|
||||||
|
"times by GDBusProxy, expected %u",
|
||||||
|
i, f->received_by_proxy[i], own_name->received_by_proxy);
|
||||||
|
g_assert_cmpuint (f->received_by_proxy[i], ==, own_name->received_by_proxy);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
g_assert_cmpuint (f->received_by_proxy[i], ==, 0);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1100,6 +1246,7 @@ main (int argc,
|
|||||||
ADD_SUBSCRIBE_TEST (limit_by_unique_name);
|
ADD_SUBSCRIBE_TEST (limit_by_unique_name);
|
||||||
ADD_SUBSCRIBE_TEST (nonexistent_unique_name);
|
ADD_SUBSCRIBE_TEST (nonexistent_unique_name);
|
||||||
ADD_SUBSCRIBE_TEST (limit_by_well_known_name);
|
ADD_SUBSCRIBE_TEST (limit_by_well_known_name);
|
||||||
|
ADD_SUBSCRIBE_TEST (limit_to_message_bus);
|
||||||
|
|
||||||
return g_test_run();
|
return g_test_run();
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user