blob: 38905715e2198511b0030e53a9beb41dea4cacae [file]
/*
* Embedded Linux library
* Copyright (C) 2011-2014 Intel Corporation
*
* SPDX-License-Identifier: LGPL-2.1-or-later
*/
#ifdef HAVE_CONFIG_H
#include <config.h>
#endif
#include <assert.h>
#include <ell/ell.h>
#include "ell/dbus-private.h"
static bool do_print = true;
static void do_debug(const char *str, void *user_data)
{
const char *prefix = user_data;
l_info("%s%s", prefix, str);
}
struct message_data {
const char *type;
const char *path;
const char *interface;
const char *member;
const char *destination;
const char *signature;
const unsigned char *binary;
size_t binary_len;
};
static const unsigned char basic_1[] = {
0x6c, 0x01, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x57, 0x04, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x2f, 0x66, 0x6f, 0x6f, 0x2f, 0x62, 0x61, 0x72, 0x00, 0x00, 0x6f, 0x00,
0x00, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x46, 0x6f, 0x6f, 0x62, 0x61, 0x72, 0x00, 0x00, 0x73, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x66, 0x6f, 0x6f, 0x2e, 0x62, 0x61, 0x72, 0x00, 0x00, 0x73, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x66, 0x6f, 0x6f, 0x2e, 0x62, 0x61, 0x72, 0x00, 0x00, 0x73, 0x13, 0x29,
0x42, 0x5a, 0x00, 0x00, 0x01, 0xff, 0xe0, 0xff, 0x20, 0x00, 0x00, 0x00,
0xe8, 0xff, 0xff, 0xff, 0x18, 0x00, 0x00, 0x00, 0x9d, 0xff, 0xff, 0xff,
0x7d, 0x7f, 0x00, 0x00, 0x63, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x14, 0x40, 0x00, 0x28, 0x62, 0x79,
0x6e, 0x71, 0x69, 0x75, 0x78, 0x74, 0x64, 0x29, 0x6e,
};
static const struct message_data message_data_basic_1 = {
.type = "method_call",
.path = "/foo/bar",
.interface = "foo.bar",
.member = "Foobar",
.destination = "foo.bar",
.signature = "bynqiuxtd",
.binary = basic_1,
.binary_len = sizeof(basic_1),
};
static const unsigned char message_binary_complex_1[] = {
0x6c, 0x01, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x57, 0x04, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x2f, 0x63, 0x6f, 0x6d, 0x2f, 0x65, 0x78, 0x61, 0x6d, 0x70, 0x6c, 0x65,
0x2f, 0x6f, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x00, 0x00, 0x6f, 0x00, 0x00,
0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x6d, 0x65, 0x74, 0x68,
0x6f, 0x64, 0x00, 0x00, 0x73, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x63, 0x6f, 0x6d, 0x2e,
0x65, 0x78, 0x61, 0x6d, 0x70, 0x6c, 0x65, 0x2e, 0x69, 0x6e, 0x74, 0x65,
0x72, 0x66, 0x61, 0x63, 0x65, 0x00, 0x00, 0x73, 0x06, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x63, 0x6f, 0x6d, 0x2e, 0x65, 0x78, 0x61, 0x6d,
0x70, 0x6c, 0x65, 0x00, 0x00, 0x73, 0x1e, 0x31, 0x58, 0x6e, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x2f, 0x63, 0x6f, 0x6d, 0x2f, 0x65, 0x78, 0x61,
0x6d, 0x70, 0x6c, 0x65, 0x2f, 0x6f, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x00,
0x00, 0x00, 0x00, 0x00, 0x4e, 0x61, 0x6d, 0x65, 0x00, 0x00, 0x00, 0x00,
0x4c, 0x69, 0x6e, 0x75, 0x73, 0x20, 0x54, 0x6f, 0x72, 0x76, 0x61, 0x6c,
0x64, 0x73, 0x00, 0x00, 0x73, 0x05, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x44, 0x65, 0x76, 0x65, 0x6c, 0x6f, 0x70, 0x65, 0x72, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x62, 0x0a, 0x1a, 0x34, 0x14, 0x00,
0x28, 0x6f, 0x61, 0x7b, 0x73, 0x76, 0x7d, 0x29, 0x82,
};
static const struct message_data message_data_complex_1 = {
.type = "method_call",
.path = "/com/example/object",
.interface = "com.example.interface",
.member = "method",
.destination = "com.example",
.signature = "oa{sv}",
.binary = message_binary_complex_1,
.binary_len = sizeof(message_binary_complex_1),
};
static const unsigned char message_binary_empty_sig[] = {
0x6c, 0x01, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x57, 0x04, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x2f, 0x66, 0x6f, 0x6f, 0x2f, 0x62, 0x61, 0x72, 0x00, 0x00, 0x6f, 0x00,
0x00, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x46, 0x6f, 0x6f, 0x62, 0x61, 0x72, 0x00, 0x00, 0x73, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x66, 0x6f, 0x6f, 0x2e, 0x62, 0x61, 0x72, 0x00, 0x00, 0x73, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x66, 0x6f, 0x6f, 0x2e, 0x62, 0x61, 0x72, 0x00, 0x00, 0x73, 0x13, 0x29,
0x42, 0x5a, 0x00, 0x00, 0x00, 0x00, 0x28, 0x29, 0x6e,
};
static const struct message_data message_data_empty_sig = {
.type = "method_call",
.path = "/foo/bar",
.interface = "foo.bar",
.member = "Foobar",
.destination = "foo.bar",
.signature = "",
.binary = message_binary_empty_sig,
.binary_len = sizeof(message_binary_empty_sig),
};
static struct l_dbus_message *check_message(const struct message_data *msg_data)
{
struct l_dbus_message *msg;
msg = dbus_message_from_blob(msg_data->binary, msg_data->binary_len,
NULL, 0);
assert(msg);
if (msg_data->path) {
const char *path = l_dbus_message_get_path(msg);
assert(path);
assert(!strcmp(msg_data->path, path));
if (do_print)
l_info("path=%s", path);
}
if (msg_data->interface) {
const char *interface = l_dbus_message_get_interface(msg);
assert(interface);
assert(!strcmp(msg_data->interface, interface));
if (do_print)
l_info("interface=%s", interface);
}
if (msg_data->member) {
const char *member = l_dbus_message_get_member(msg);
assert(member);
assert(!strcmp(msg_data->member, member));
if (do_print)
l_info("member=%s", member);
}
if (msg_data->destination) {
const char *destination = l_dbus_message_get_destination(msg);
assert(destination);
assert(!strcmp(msg_data->destination, destination));
if (do_print)
l_info("destination=%s", destination);
}
if (msg_data->signature) {
const char *signature = l_dbus_message_get_signature(msg);
assert(signature);
assert(!strcmp(msg_data->signature, signature));
if (do_print)
l_info("signature=%s", signature);
}
return msg;
}
static struct l_dbus_message *build_message(const struct message_data *msg_data)
{
struct l_dbus_message *msg;
msg = _dbus_message_new_method_call(2, msg_data->destination,
msg_data->path, msg_data->interface, msg_data->member);
assert(msg);
return msg;
}
static void compare_message(struct l_dbus_message *msg,
const struct message_data *msg_data)
{
bool result;
if (do_print) {
void *blob;
void *header, *body;
size_t header_size, body_size;
header = _dbus_message_get_header(msg, &header_size);
body = _dbus_message_get_body(msg, &body_size);
blob = l_malloc(header_size + body_size);
memcpy(blob, header, header_size);
memcpy(blob + header_size, body, body_size);
l_util_hexdump(true, blob, header_size + body_size,
do_debug, "[MSG] ");
l_free(blob);
l_util_hexdump(true, msg_data->binary, msg_data->binary_len,
do_debug, "[MSG] ");
}
result = dbus_message_compare(msg, msg_data->binary,
msg_data->binary_len);
assert(result);
l_dbus_message_unref(msg);
}
static void parse_basic_1(const void *data)
{
struct l_dbus_message *msg = check_message(data);
bool result;
bool b;
uint8_t y;
uint16_t q;
int16_t n;
uint32_t u;
int32_t i;
uint64_t t;
int64_t x;
double d;
result = l_dbus_message_get_arguments(msg, "bynqiuxtd", &b, &y, &n, &q,
&i, &u, &x, &t, &d);
assert(result);
assert(b == true);
assert(y == 255);
assert(n == -32);
assert(q == 32);
assert(i == -24);
assert(u == 24);
assert(x == 140179142606749);
assert(t == 99);
assert(d == 5.0);
l_dbus_message_unref(msg);
}
static void build_basic_1(const void *data)
{
struct l_dbus_message *msg = build_message(data);
bool result;
result = l_dbus_message_set_arguments(msg, "bynqiuxtd", true, 255,
-32, 32, -24, 24,
(uint64_t) 140179142606749,
(int64_t) 99, 5.0);
assert(result);
_dbus_message_set_serial(msg, 1111);
compare_message(msg, data);
}
static void check_complex_1(const void *data)
{
struct l_dbus_message *msg = check_message(data);
struct l_dbus_message_iter dict, iter;
const char *path, *str;
bool result, val;
result = l_dbus_message_get_arguments(msg, "oa{sv}", &path, &dict);
assert(result);
assert(!strcmp(path, "/com/example/object"));
result = l_dbus_message_iter_next_entry(&dict, &str, &iter);
assert(result);
assert(!strcmp(str, "Name"));
result = l_dbus_message_iter_get_variant(&iter, "s", &str);
assert(result);
assert(!strcmp(str, "Linus Torvalds"));
result = l_dbus_message_iter_next_entry(&dict, &str, &iter);
assert(result);
assert(!strcmp(str, "Developer"));
result = l_dbus_message_iter_get_variant(&iter, "b", &val);
assert(result);
assert(val);
result = l_dbus_message_iter_next_entry(&dict, &str, &iter);
assert(!result);
l_dbus_message_unref(msg);
}
static void build_complex_1(const void *data)
{
struct l_dbus_message *msg = build_message(data);
bool result;
result = l_dbus_message_set_arguments(msg, "oa{sv}",
"/com/example/object", 2,
"Name", "s", "Linus Torvalds",
"Developer", "b", true);
assert(result);
_dbus_message_set_serial(msg, 1111);
compare_message(msg, data);
}
static void check_empty_sig(const void *data)
{
struct l_dbus_message *msg = check_message(data);
assert(l_dbus_message_get_arguments(msg, ""));
l_dbus_message_unref(msg);
}
static void build_empty_sig(const void *data)
{
struct l_dbus_message *msg = build_message(data);
bool result;
result = l_dbus_message_set_arguments(msg, "");
assert(result);
_dbus_message_set_serial(msg, 1111);
compare_message(msg, data);
}
static void builder_rewind(const void *data)
{
struct l_dbus_message *msg = build_message(data);
struct l_dbus_message_builder *builder;
bool b = true;
builder = l_dbus_message_builder_new(msg);
assert(builder);
assert(l_dbus_message_builder_append_basic(builder, 'o',
"/com/example/object"));
assert(l_dbus_message_builder_enter_array(builder, "{sv}"));
assert(_dbus_message_builder_mark(builder));
assert(l_dbus_message_builder_enter_dict(builder, "sv"));
assert(l_dbus_message_builder_append_basic(builder, 's', "Name"));
assert(l_dbus_message_builder_enter_variant(builder, "s"));
assert(l_dbus_message_builder_append_basic(builder, 's',
"Invalid"));
assert(l_dbus_message_builder_leave_variant(builder));
assert(l_dbus_message_builder_leave_dict(builder));
assert(_dbus_message_builder_rewind(builder));
assert(l_dbus_message_builder_enter_dict(builder, "sv"));
assert(l_dbus_message_builder_append_basic(builder, 's', "Name"));
assert(l_dbus_message_builder_enter_variant(builder, "s"));
assert(l_dbus_message_builder_append_basic(builder, 's',
"Linus Torvalds"));
assert(l_dbus_message_builder_leave_variant(builder));
assert(l_dbus_message_builder_leave_dict(builder));
assert(l_dbus_message_builder_enter_dict(builder, "sv"));
assert(l_dbus_message_builder_append_basic(builder, 's', "Developer"));
assert(l_dbus_message_builder_enter_variant(builder, "b"));
assert(l_dbus_message_builder_append_basic(builder, 'b', &b));
assert(l_dbus_message_builder_leave_variant(builder));
assert(l_dbus_message_builder_leave_dict(builder));
assert(l_dbus_message_builder_leave_array(builder));
assert(l_dbus_message_builder_finalize(builder));
l_dbus_message_builder_destroy(builder);
compare_message(msg, data);
}
int main(int argc, char *argv[])
{
l_test_init(&argc, &argv);
l_test_add("Basic 1 (parse)", parse_basic_1, &message_data_basic_1);
l_test_add("Basic 1 (build)", build_basic_1, &message_data_basic_1);
l_test_add("Complex 1 (parse)", check_complex_1,
&message_data_complex_1);
l_test_add("Complex 1 (build)", build_complex_1,
&message_data_complex_1);
l_test_add("Empty signature (parse)", check_empty_sig,
&message_data_empty_sig);
l_test_add("Empty signature (build)", build_empty_sig,
&message_data_empty_sig);
l_test_add("Message Builder Rewind Complex 1", builder_rewind,
&message_data_complex_1);
return l_test_run();
}