diff options
-rw-r--r-- | .bzrignore | 1 | ||||
-rw-r--r-- | configure.ac | 11 | ||||
-rw-r--r-- | debian/changelog | 7 | ||||
-rw-r--r-- | libdbusmenu-glib/server.c | 2 | ||||
-rw-r--r-- | tools/Makefile.am | 5 | ||||
-rwxr-xr-x | tools/dbusmenu-bench | 157 | ||||
-rw-r--r-- | tools/testapp/CMakeLists.txt | 29 | ||||
-rw-r--r-- | tools/testapp/Makefile.am | 17 | ||||
-rw-r--r-- | tools/testapp/main.c | 153 |
9 files changed, 373 insertions, 9 deletions
@@ -58,3 +58,4 @@ libdbusmenu-gtk/libdbusmenu_gtk_la-genericmenuitem.lo tests/test-glib-objects tests/test-glib-objects-test tests/test-glib-objects.xml +tools/testapp/dbusmenu-testapp diff --git a/configure.ac b/configure.ac index b14e797..7a578ec 100644 --- a/configure.ac +++ b/configure.ac @@ -1,11 +1,11 @@ -AC_INIT(libdbusmenu, 0.2.1, ted@canonical.com) -AC_COPYRIGHT([Copyright 2009 Canonical]) +AC_INIT(libdbusmenu, 0.2.2, ted@canonical.com) +AC_COPYRIGHT([Copyright 2009,2010 Canonical]) AC_PREREQ(2.53) AM_CONFIG_HEADER(config.h) -AM_INIT_AUTOMAKE(libdbusmenu, 0.2.1) +AM_INIT_AUTOMAKE(libdbusmenu, 0.2.2) AM_MAINTAINER_MODE @@ -65,8 +65,8 @@ AC_SUBST(DBUSMENUTESTS_LIBS) # Lib versioning ########################### -LIBDBUSMENU_CURRENT=0 -LIBDBUSMENU_REVISION=11 +LIBDBUSMENU_CURRENT=1 +LIBDBUSMENU_REVISION=0 LIBDBUSMENU_AGE=0 AC_SUBST(LIBDBUSMENU_CURRENT) @@ -105,6 +105,7 @@ libdbusmenu-glib/dbusmenu-glib.pc libdbusmenu-gtk/Makefile libdbusmenu-gtk/dbusmenu-gtk.pc tools/Makefile +tools/testapp/Makefile tests/Makefile ]) diff --git a/debian/changelog b/debian/changelog index 70fc772..221d219 100644 --- a/debian/changelog +++ b/debian/changelog @@ -1,11 +1,12 @@ -libdbusmenu (0.2.1-0ubuntu2~ppa1) lucid; urgency=low +libdbusmenu (0.2.2-0ubuntu1~ppa1) UNRELEASED; urgency=low - * Upstream Merge + * Upstream Release 0.2.2 * Interoperability fixes * Adding timestamps to events * Better handling of XML + * Adding tools for timing dbusmenu - -- Ted Gould <ted@ubuntu.com> Thu, 04 Feb 2010 11:21:01 -0800 + -- Ted Gould <ted@ubuntu.com> Thu, 04 Feb 2010 12:14:58 -0800 libdbusmenu (0.2.1-0ubuntu1) lucid; urgency=low diff --git a/libdbusmenu-glib/server.c b/libdbusmenu-glib/server.c index 9d84750..7d8e5c3 100644 --- a/libdbusmenu-glib/server.c +++ b/libdbusmenu-glib/server.c @@ -44,7 +44,7 @@ static gboolean _dbusmenu_server_get_children (DbusmenuServer * server, gint id, #include "dbusmenu-server.h" -#define DBUSMENU_VERSION_NUMBER 1 +#define DBUSMENU_VERSION_NUMBER 2 /* Privates, I'll show you mine... */ typedef struct _DbusmenuServerPrivate DbusmenuServerPrivate; diff --git a/tools/Makefile.am b/tools/Makefile.am index 415050f..eedfa29 100644 --- a/tools/Makefile.am +++ b/tools/Makefile.am @@ -1,6 +1,10 @@ +SUBDIRS = testapp + libexec_PROGRAMS = dbusmenu-dumper +libexec_SCRIPTS = dbusmenu-bench + dbusmenu_dumper_SOURCES = \ dbusmenu-dumper.c @@ -12,3 +16,4 @@ dbusmenu_dumper_LDADD = \ ../libdbusmenu-glib/libdbusmenu-glib.la \ $(DBUSMENUGLIB_LIBS) +EXTRA_DIST = dbusmenu-bench diff --git a/tools/dbusmenu-bench b/tools/dbusmenu-bench new file mode 100755 index 0000000..4b58da8 --- /dev/null +++ b/tools/dbusmenu-bench @@ -0,0 +1,157 @@ +#!/usr/bin/env python +# encoding: utf-8 +""" +A library to communicate a menu object set accross DBus and +track updates and maintain consistency. + +Copyright 2010 Canonical Ltd. + +Authors: + Aurélien Gâteau <aurelien.gateau@canonical.com> + +This program is free software: you can redistribute it and/or modify it +under the terms of either or both of the following licenses: + +1) the GNU Lesser General Public License version 3, as published by the +Free Software Foundation; and/or +2) the GNU Lesser General Public License version 2.1, as published by +the Free Software Foundation. + +This program is distributed in the hope that it will be useful, but +WITHOUT ANY WARRANTY; without even the implied warranties of +MERCHANTABILITY, SATISFACTORY QUALITY or FITNESS FOR A PARTICULAR +PURPOSE. See the applicable version of the GNU Lesser General Public +License for more details. + +You should have received a copy of both the GNU Lesser General Public +License version 3 and version 2.1 along with this program. If not, see +<http://www.gnu.org/licenses/> +""" +import itertools +import time +import sys +from optparse import OptionParser +from xml.etree import ElementTree as ET + +import dbus + +DBUS_INTERFACE = "org.ayatana.dbusmenu" +DBUS_SERVICE = "org.dbusmenu.test" +DBUS_PATH = "/MenuBar" + +PROBE_GET_LAYOUT = "GetLayout" +PROBE_GET_PROPERTIES = "GetProperties" +PROBE_GET_CHILDREN = "GetChildren" +PROBES = PROBE_GET_LAYOUT, PROBE_GET_PROPERTIES, PROBE_GET_CHILDREN + +class Chrono(object): + def __init__(self): + self._time = 0 + self.restart() + + def restart(self): + new_time = time.time() + delta = new_time - self._time + self._time = new_time + return delta + + def elapsed(self): + return time.time() - self._time + + +def dump_properties(properties, prepend=""): + for key, value in properties.items(): + print "%s- %s: %s" % (prepend, key, value) + + +def run_test_sequence(menu, dump=False): + """ + Runs the test sequence and returns a dict of method_name: seconds + """ + property_names = ["type", "label", "enabled", "icon-name"] + times = dict() + chrono = Chrono() + revision, layout = menu.GetLayout(dbus.Int32(0)) + times["GetLayout"] = chrono.elapsed() + if dump: + print "revision:", revision + print "layout:" + print layout + + # Get ids + tree = ET.fromstring(layout) + root_id = int(tree.attrib["id"]) + child_element = tree.find("menu") + assert child_element is not None + child_id = int(child_element.attrib["id"]) + + chrono.restart() + children = menu.GetChildren(dbus.Int32(root_id), property_names) + times["GetChildren"] = chrono.elapsed() + if dump: + print "children:" + for child in children: + id, properties = child + print "- %d:" % id + dump_properties(properties, prepend=" ") + + chrono.restart() + properties = menu.GetProperties(dbus.Int32(child_id), property_names) + times["GetProperties"] = chrono.elapsed() + if dump: + print "properties:" + dump_properties(properties) + + return times + +def create_timing_dict(): + return dict(zip(PROBES, itertools.repeat(0))) + +def print_probe(prefix, name, value, timestamp): + value = int(value * 1000000) + print "%(prefix)s.%(name)s:%(value)d@%(timestamp)d" % locals() + +def main(): + parser = OptionParser(usage = "%prog [options]") + + parser.add_option("-c", "--count", dest="count", type=int, default=1, + help="repeat calls COUNT times", metavar="COUNT") + parser.add_option("-d", "--dump", dest="dump", action="store_true", default=False, + help="dump call output to stdout") + + (options, args) = parser.parse_args() + + bus = dbus.SessionBus() + proxy = bus.get_object(DBUS_SERVICE, DBUS_PATH) + menu = dbus.Interface(proxy, dbus_interface=DBUS_INTERFACE) + + if options.dump: + run_test_sequence(menu, dump=True) + return + + cumulated_timings = create_timing_dict() + min_timings = create_timing_dict() + max_timings = create_timing_dict() + for x in range(options.count): + timings = run_test_sequence(menu) + for name, timing in timings.items(): + cumulated_timings[name] += timing + if min_timings[name] == 0 or min_timings[name] > timing: + min_timings[name] = timing + if max_timings[name] < timing: + max_timings[name] = timing + + timestamp = int(time.time()) + for name, timing in cumulated_timings.items(): + print_probe("average", name, timing / options.count, timestamp) + for name, timing in min_timings.items(): + print_probe("min", name, timing, timestamp) + for name, timing in max_timings.items(): + print_probe("max", name, timing, timestamp) + + return 0 + + +if __name__=="__main__": + sys.exit(main()) +# vi: ts=4 sw=4 et tw=0 diff --git a/tools/testapp/CMakeLists.txt b/tools/testapp/CMakeLists.txt new file mode 100644 index 0000000..b848e50 --- /dev/null +++ b/tools/testapp/CMakeLists.txt @@ -0,0 +1,29 @@ +find_package(PkgConfig REQUIRED) + +pkg_check_modules(DBUSMENUGLIB REQUIRED dbusmenu-glib) +pkg_check_modules(GLIB REQUIRED glib-2.0) +pkg_check_modules(JSONGLIB REQUIRED json-glib-1.0) + +set(glibapp_SRCS + main.c + ) + +include_directories( + ${DBUSMENUGLIB_INCLUDE_DIRS} + ${GLIB_INCLUDE_DIRS} + ${JSONGLIB_INCLUDE_DIRS} + ) + +link_directories( + ${DBUSMENUGLIB_LIBRARY_DIRS} + ${GLIB_LIBRARY_DIRS} + ${JSONGLIB_LIBRARY_DIRS} + ) + +add_executable(dbusmenubench-glibapp ${glibapp_SRCS}) + +target_link_libraries(dbusmenubench-glibapp + ${DBUSMENUGLIB_LIBRARIES} + ${GLIB_LIBARIES} + ${JSONGLIB_LIBRARIES} + ) diff --git a/tools/testapp/Makefile.am b/tools/testapp/Makefile.am new file mode 100644 index 0000000..a8b42dd --- /dev/null +++ b/tools/testapp/Makefile.am @@ -0,0 +1,17 @@ + +libexec_PROGRAMS = dbusmenu-testapp + +dbusmenu_testapp_SOURCES = \ + main.c + +dbusmenu_testapp_CFLAGS = \ + -I $(srcdir)/../.. \ + $(DBUSMENUTESTS_CFLAGS) \ + $(DBUSMENUGLIB_CFLAGS) \ + -Wall -Werror + +dbusmenu_testapp_LDADD = \ + $(builddir)/../../libdbusmenu-glib/libdbusmenu-glib.la \ + $(builddir)/../../libdbusmenu-gtk/libdbusmenu-gtk.la \ + $(DBUSMENUGTK_LIBS) \ + $(DBUSMENUTESTS_LIBS) diff --git a/tools/testapp/main.c b/tools/testapp/main.c new file mode 100644 index 0000000..f489407 --- /dev/null +++ b/tools/testapp/main.c @@ -0,0 +1,153 @@ +/* +A library to communicate a menu object set accross DBus and +track updates and maintain consistency. + +Copyright 2010 Canonical Ltd. + +Authors: + Aurélien Gâteau <aurelien.gateau@canonical.com> + +This program is free software: you can redistribute it and/or modify it +under the terms of either or both of the following licenses: + +1) the GNU Lesser General Public License version 3, as published by the +Free Software Foundation; and/or +2) the GNU Lesser General Public License version 2.1, as published by +the Free Software Foundation. + +This program is distributed in the hope that it will be useful, but +WITHOUT ANY WARRANTY; without even the implied warranties of +MERCHANTABILITY, SATISFACTORY QUALITY or FITNESS FOR A PARTICULAR +PURPOSE. See the applicable version of the GNU Lesser General Public +License for more details. + +You should have received a copy of both the GNU Lesser General Public +License version 3 and version 2.1 along with this program. If not, see +<http://www.gnu.org/licenses/> +*/ +#include <glib.h> + +#include <dbus/dbus-glib.h> +#include <dbus/dbus-glib-bindings.h> + +#include <json-glib/json-glib.h> + +#include <libdbusmenu-glib/server.h> +#include <libdbusmenu-glib/menuitem.h> + +#define USAGE "dbusmenubench-glibapp <path/to/menu.json>" + +static void +set_props (DbusmenuMenuitem * mi, JsonObject * node) +{ + if (node == NULL) return; + + GList * members = NULL; + for (members = json_object_get_members(node); members != NULL; members = g_list_next(members)) { + const gchar * member = members->data; + + if (!g_strcmp0(member, "id")) { continue; } + if (!g_strcmp0(member, "submenu")) { continue; } + + JsonNode * lnode = json_object_get_member(node, member); + if (JSON_NODE_TYPE(lnode) != JSON_NODE_VALUE) { continue; } + + dbusmenu_menuitem_property_set(mi, member, json_node_get_string(lnode)); + } + + return; +} + +static DbusmenuMenuitem * +layout2menuitem (JsonNode * inlayout) +{ + if (inlayout == NULL) return NULL; + if (JSON_NODE_TYPE(inlayout) != JSON_NODE_OBJECT) return NULL; + + JsonObject * layout = json_node_get_object(inlayout); + + DbusmenuMenuitem * local = NULL; + if (json_object_has_member(layout, "id")) { + JsonNode * node = json_object_get_member(layout, "id"); + g_return_val_if_fail(JSON_NODE_TYPE(node) == JSON_NODE_VALUE, NULL); + local = dbusmenu_menuitem_new_with_id(json_node_get_int(node)); + } else { + local = dbusmenu_menuitem_new(); + } + + set_props(local, layout); + + if (json_object_has_member(layout, "submenu")) { + JsonNode * node = json_object_get_member(layout, "submenu"); + g_return_val_if_fail(JSON_NODE_TYPE(node) == JSON_NODE_ARRAY, local); + JsonArray * array = json_node_get_array(node); + guint count; + for (count = 0; count < json_array_get_length(array); count++) { + DbusmenuMenuitem * child = layout2menuitem(json_array_get_element(array, count)); + if (child != NULL) { + dbusmenu_menuitem_child_append(local, child); + } + } + } + + /* g_debug("Layout to menu return: 0x%X", (unsigned int)local); */ + return local; +} + +void init_menu(DbusmenuMenuitem *root, const char *filename) +{ + JsonParser * parser = json_parser_new(); + GError * error = NULL; + if (!json_parser_load_from_file(parser, filename, &error)) { + g_debug("Failed parsing file %s because: %s", filename, error->message); + return; + } + JsonNode * root_node = json_parser_get_root(parser); + if (JSON_NODE_TYPE(root_node) != JSON_NODE_ARRAY) { + g_debug("Root node is not an array, fail. It's an: %s", json_node_type_name(root_node)); + return; + } + + JsonArray * root_array = json_node_get_array(root_node); + int pos; + int count = json_array_get_length(root_array); + for (pos=0; pos < count; ++pos) { + DbusmenuMenuitem *child = layout2menuitem(json_array_get_element(root_array, pos)); + dbusmenu_menuitem_child_append(root, child); + } +} + +int main (int argc, char ** argv) +{ + g_type_init(); + + if (argc != 2) { + g_warning(USAGE); + return 1; + } + const char *filename = argv[1]; + + GError * error = NULL; + DBusGConnection * connection = dbus_g_bus_get(DBUS_BUS_SESSION, NULL); + DBusGProxy * bus_proxy = dbus_g_proxy_new_for_name(connection, DBUS_SERVICE_DBUS, DBUS_PATH_DBUS, DBUS_INTERFACE_DBUS); + guint nameret = 0; + + if (!org_freedesktop_DBus_request_name(bus_proxy, "org.dbusmenu.test", 0, &nameret, &error)) { + g_error("Unable to call to request name"); + return 1; + } + + if (nameret != DBUS_REQUEST_NAME_REPLY_PRIMARY_OWNER) { + g_error("Unable to get name"); + return 1; + } + + DbusmenuServer *server = dbusmenu_server_new("/MenuBar"); + DbusmenuMenuitem *root = dbusmenu_menuitem_new_with_id(0); + init_menu(root, filename); + dbusmenu_server_set_root(server, root); + + g_main_loop_run(g_main_loop_new(NULL, FALSE)); + + return 0; +} |