/* * * Embedded Linux library * * Copyright (C) 2011-2014 Intel Corporation. All rights reserved. * * This library 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. * * This library 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 this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA * */ #ifdef HAVE_CONFIG_H #include #endif #include #include #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(); }