aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--.bzrignore1
-rw-r--r--configure.ac11
-rw-r--r--debian/changelog7
-rw-r--r--libdbusmenu-glib/server.c2
-rw-r--r--tools/Makefile.am5
-rwxr-xr-xtools/dbusmenu-bench157
-rw-r--r--tools/testapp/CMakeLists.txt29
-rw-r--r--tools/testapp/Makefile.am17
-rw-r--r--tools/testapp/main.c153
9 files changed, 373 insertions, 9 deletions
diff --git a/.bzrignore b/.bzrignore
index d506979..367f47d 100644
--- a/.bzrignore
+++ b/.bzrignore
@@ -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;
+}