summaryrefslogtreecommitdiff
path: root/test
diff options
context:
space:
mode:
authorvivian, zhang <vivian.zhang@intel.com>2012-06-03 11:21:25 +0800
committervivian, zhang <vivian.zhang@intel.com>2012-06-03 11:21:25 +0800
commit018fcb4a1852ab3368903d57bc0b5e54fa03e6c8 (patch)
tree108a0f4727db6ea287725f85bbca3eee9801983a /test
parentc0384c46d79b70ce46d887fdaa2f4c59fb89fd33 (diff)
downloaddbus-python-2.0alpha.tar.gz
dbus-python-2.0alpha.tar.bz2
dbus-python-2.0alpha.zip
Initial import package dbus-python: D-Bus Python BindingsHEAD2.0_alphamaster2.0alpha1.0_post
Diffstat (limited to 'test')
-rw-r--r--test/Makefile.am47
-rw-r--r--test/Makefile.in719
-rw-r--r--test/TestSuitePythonService.service.in3
-rw-r--r--test/cross-test-client.py393
-rw-r--r--test/cross-test-server.py323
-rw-r--r--test/crosstest.py44
-rw-r--r--test/dbus_py_test.c126
-rwxr-xr-xtest/run-test.sh124
-rwxr-xr-xtest/run-with-tmp-session-bus.sh75
-rwxr-xr-xtest/test-client.py587
-rw-r--r--test/test-p2p.py95
-rwxr-xr-xtest/test-service.py344
-rw-r--r--test/test-signals.py160
-rwxr-xr-xtest/test-standalone.py297
-rw-r--r--test/test-unusable-main-loop.py39
-rw-r--r--test/tmp-session-bus.conf.in21
16 files changed, 3397 insertions, 0 deletions
diff --git a/test/Makefile.am b/test/Makefile.am
new file mode 100644
index 0000000..a40c3d1
--- /dev/null
+++ b/test/Makefile.am
@@ -0,0 +1,47 @@
+abs_top_srcdir = @abs_top_srcdir@
+abs_top_builddir = @abs_top_builddir@
+
+EXTRA_DIST = \
+ cross-test-client.py \
+ cross-test-server.py \
+ crosstest.py \
+ run-test.sh \
+ run-with-tmp-session-bus.sh \
+ test-client.py \
+ test-p2p.py \
+ test-service.py \
+ test-signals.py \
+ test-standalone.py \
+ test-unusable-main-loop.py \
+ TestSuitePythonService.service.in \
+ tmp-session-bus.conf.in
+
+# If you try to make this noinst, libtool helpfully gives us a static
+# library, which doesn't work as a Python extension: so force the install
+# target not to work here instead.
+pyexec_LTLIBRARIES = dbus_py_test.la
+
+install:
+ @echo "Not installing anything from test/"
+
+dbus_py_test_la_CPPFLAGS = -I$(top_srcdir)/include $(DBUS_CFLAGS) \
+ $(PYTHON_INCLUDES)
+dbus_py_test_la_LDFLAGS = -module -avoid-version \
+ $(DBUS_LIBS)
+dbus_py_test_la_SOURCES = dbus_py_test.c \
+ $(top_srcdir)/include/dbus-python.h
+
+TESTS_ENVIRONMENT = DBUS_TOP_SRCDIR="$(abs_top_srcdir)" \
+ DBUS_TOP_BUILDDIR="$(abs_top_builddir)" \
+ DBUS_PYTHON_VERSION='$(PACKAGE_VERSION)' \
+ PYTHONPATH="$(abs_top_builddir)/test/.libs:$(abs_top_srcdir):$(abs_top_srcdir)/test:$(abs_top_builddir)/_dbus_bindings/.libs:$(abs_top_builddir)/_dbus_glib_bindings/.libs" \
+ PYTHON='$(PYTHON)'
+
+TESTS = run-test.sh
+
+cross-test-server:
+ $(TESTS_ENVIRONMENT) $(PYTHON) $(top_srcdir)/test/cross-test-server.py
+cross-test-client:
+ $(TESTS_ENVIRONMENT) $(PYTHON) $(top_srcdir)/test/cross-test-client.py
+
+.PHONY: cross-test-compile cross-test-server cross-test-client
diff --git a/test/Makefile.in b/test/Makefile.in
new file mode 100644
index 0000000..40c85cb
--- /dev/null
+++ b/test/Makefile.in
@@ -0,0 +1,719 @@
+# Makefile.in generated by automake 1.11.1 from Makefile.am.
+# @configure_input@
+
+# Copyright (C) 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002,
+# 2003, 2004, 2005, 2006, 2007, 2008, 2009 Free Software Foundation,
+# Inc.
+# This Makefile.in is free software; the Free Software Foundation
+# gives unlimited permission to copy and/or distribute it,
+# with or without modifications, as long as this notice is preserved.
+
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY, to the extent permitted by law; without
+# even the implied warranty of MERCHANTABILITY or FITNESS FOR A
+# PARTICULAR PURPOSE.
+
+@SET_MAKE@
+
+VPATH = @srcdir@
+pkgdatadir = $(datadir)/@PACKAGE@
+pkgincludedir = $(includedir)/@PACKAGE@
+pkglibdir = $(libdir)/@PACKAGE@
+pkglibexecdir = $(libexecdir)/@PACKAGE@
+am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd
+install_sh_DATA = $(install_sh) -c -m 644
+install_sh_PROGRAM = $(install_sh) -c
+install_sh_SCRIPT = $(install_sh) -c
+INSTALL_HEADER = $(INSTALL_DATA)
+transform = $(program_transform_name)
+NORMAL_INSTALL = :
+PRE_INSTALL = :
+POST_INSTALL = :
+NORMAL_UNINSTALL = :
+PRE_UNINSTALL = :
+POST_UNINSTALL = :
+build_triplet = @build@
+host_triplet = @host@
+subdir = test
+DIST_COMMON = $(srcdir)/Makefile.am $(srcdir)/Makefile.in \
+ $(srcdir)/TestSuitePythonService.service.in \
+ $(srcdir)/tmp-session-bus.conf.in
+ACLOCAL_M4 = $(top_srcdir)/aclocal.m4
+am__aclocal_m4_deps = $(top_srcdir)/m4/am-check-pymod.m4 \
+ $(top_srcdir)/m4/am-check-python-headers.m4 \
+ $(top_srcdir)/m4/dbus-py-add-rst2htmlflag.m4 \
+ $(top_srcdir)/m4/jh-add-cflag.m4 $(top_srcdir)/m4/libtool.m4 \
+ $(top_srcdir)/m4/ltoptions.m4 $(top_srcdir)/m4/ltsugar.m4 \
+ $(top_srcdir)/m4/ltversion.m4 $(top_srcdir)/m4/lt~obsolete.m4 \
+ $(top_srcdir)/m4/tp-compiler-flag.m4 \
+ $(top_srcdir)/m4/tp-compiler-warnings.m4 \
+ $(top_srcdir)/configure.ac
+am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \
+ $(ACLOCAL_M4)
+mkinstalldirs = $(install_sh) -d
+CONFIG_HEADER = $(top_builddir)/config.h
+CONFIG_CLEAN_FILES = tmp-session-bus.conf \
+ TestSuitePythonService.service
+CONFIG_CLEAN_VPATH_FILES =
+am__vpath_adj_setup = srcdirstrip=`echo "$(srcdir)" | sed 's|.|.|g'`;
+am__vpath_adj = case $$p in \
+ $(srcdir)/*) f=`echo "$$p" | sed "s|^$$srcdirstrip/||"`;; \
+ *) f=$$p;; \
+ esac;
+am__strip_dir = f=`echo $$p | sed -e 's|^.*/||'`;
+am__install_max = 40
+am__nobase_strip_setup = \
+ srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*|]/\\\\&/g'`
+am__nobase_strip = \
+ for p in $$list; do echo "$$p"; done | sed -e "s|$$srcdirstrip/||"
+am__nobase_list = $(am__nobase_strip_setup); \
+ for p in $$list; do echo "$$p $$p"; done | \
+ sed "s| $$srcdirstrip/| |;"' / .*\//!s/ .*/ ./; s,\( .*\)/[^/]*$$,\1,' | \
+ $(AWK) 'BEGIN { files["."] = "" } { files[$$2] = files[$$2] " " $$1; \
+ if (++n[$$2] == $(am__install_max)) \
+ { print $$2, files[$$2]; n[$$2] = 0; files[$$2] = "" } } \
+ END { for (dir in files) print dir, files[dir] }'
+am__base_list = \
+ sed '$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;s/\n/ /g' | \
+ sed '$$!N;$$!N;$$!N;$$!N;s/\n/ /g'
+am__installdirs = "$(DESTDIR)$(pyexecdir)"
+LTLIBRARIES = $(pyexec_LTLIBRARIES)
+dbus_py_test_la_LIBADD =
+am_dbus_py_test_la_OBJECTS = dbus_py_test_la-dbus_py_test.lo
+dbus_py_test_la_OBJECTS = $(am_dbus_py_test_la_OBJECTS)
+AM_V_lt = $(am__v_lt_$(V))
+am__v_lt_ = $(am__v_lt_$(AM_DEFAULT_VERBOSITY))
+am__v_lt_0 = --silent
+dbus_py_test_la_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC \
+ $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=link $(CCLD) \
+ $(AM_CFLAGS) $(CFLAGS) $(dbus_py_test_la_LDFLAGS) $(LDFLAGS) \
+ -o $@
+DEFAULT_INCLUDES = -I.@am__isrc@ -I$(top_builddir)
+depcomp = $(SHELL) $(top_srcdir)/depcomp
+am__depfiles_maybe = depfiles
+am__mv = mv -f
+COMPILE = $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) \
+ $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS)
+LTCOMPILE = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \
+ $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) \
+ $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) \
+ $(AM_CFLAGS) $(CFLAGS)
+AM_V_CC = $(am__v_CC_$(V))
+am__v_CC_ = $(am__v_CC_$(AM_DEFAULT_VERBOSITY))
+am__v_CC_0 = @echo " CC " $@;
+AM_V_at = $(am__v_at_$(V))
+am__v_at_ = $(am__v_at_$(AM_DEFAULT_VERBOSITY))
+am__v_at_0 = @
+CCLD = $(CC)
+LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \
+ $(LIBTOOLFLAGS) --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) \
+ $(AM_LDFLAGS) $(LDFLAGS) -o $@
+AM_V_CCLD = $(am__v_CCLD_$(V))
+am__v_CCLD_ = $(am__v_CCLD_$(AM_DEFAULT_VERBOSITY))
+am__v_CCLD_0 = @echo " CCLD " $@;
+AM_V_GEN = $(am__v_GEN_$(V))
+am__v_GEN_ = $(am__v_GEN_$(AM_DEFAULT_VERBOSITY))
+am__v_GEN_0 = @echo " GEN " $@;
+SOURCES = $(dbus_py_test_la_SOURCES)
+DIST_SOURCES = $(dbus_py_test_la_SOURCES)
+ETAGS = etags
+CTAGS = ctags
+am__tty_colors = \
+red=; grn=; lgn=; blu=; std=
+DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST)
+ACLOCAL = @ACLOCAL@
+AMTAR = @AMTAR@
+AM_DEFAULT_VERBOSITY = @AM_DEFAULT_VERBOSITY@
+AR = @AR@
+AUTOCONF = @AUTOCONF@
+AUTOHEADER = @AUTOHEADER@
+AUTOMAKE = @AUTOMAKE@
+AWK = @AWK@
+CC = @CC@
+CCDEPMODE = @CCDEPMODE@
+CFLAGS = @CFLAGS@
+CPP = @CPP@
+CPPFLAGS = @CPPFLAGS@
+CYGPATH_W = @CYGPATH_W@
+DBUS_CFLAGS = @DBUS_CFLAGS@
+DBUS_GLIB_CFLAGS = @DBUS_GLIB_CFLAGS@
+DBUS_GLIB_LIBS = @DBUS_GLIB_LIBS@
+DBUS_LIBS = @DBUS_LIBS@
+DBUS_PYTHON_MAJOR_VERSION = @DBUS_PYTHON_MAJOR_VERSION@
+DBUS_PYTHON_MICRO_VERSION = @DBUS_PYTHON_MICRO_VERSION@
+DBUS_PYTHON_MINOR_VERSION = @DBUS_PYTHON_MINOR_VERSION@
+DEFS = @DEFS@
+DEPDIR = @DEPDIR@
+DSYMUTIL = @DSYMUTIL@
+DUMPBIN = @DUMPBIN@
+ECHO_C = @ECHO_C@
+ECHO_N = @ECHO_N@
+ECHO_T = @ECHO_T@
+EGREP = @EGREP@
+EPYDOC = @EPYDOC@
+EXEEXT = @EXEEXT@
+FGREP = @FGREP@
+GREP = @GREP@
+INSTALL = @INSTALL@
+INSTALL_DATA = @INSTALL_DATA@
+INSTALL_PROGRAM = @INSTALL_PROGRAM@
+INSTALL_SCRIPT = @INSTALL_SCRIPT@
+INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@
+LD = @LD@
+LDFLAGS = @LDFLAGS@
+LIBOBJS = @LIBOBJS@
+LIBS = @LIBS@
+LIBTOOL = @LIBTOOL@
+LIPO = @LIPO@
+LN_S = @LN_S@
+LTLIBOBJS = @LTLIBOBJS@
+MAKEINFO = @MAKEINFO@
+MKDIR_P = @MKDIR_P@
+NM = @NM@
+NMEDIT = @NMEDIT@
+OBJDUMP = @OBJDUMP@
+OBJEXT = @OBJEXT@
+OTOOL = @OTOOL@
+OTOOL64 = @OTOOL64@
+PACKAGE = @PACKAGE@
+PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@
+PACKAGE_NAME = @PACKAGE_NAME@
+PACKAGE_STRING = @PACKAGE_STRING@
+PACKAGE_TARNAME = @PACKAGE_TARNAME@
+PACKAGE_URL = @PACKAGE_URL@
+PACKAGE_VERSION = @PACKAGE_VERSION@
+PATH_SEPARATOR = @PATH_SEPARATOR@
+PKG_CONFIG = @PKG_CONFIG@
+PLATFORM = @PLATFORM@
+PYTHON = @PYTHON@
+PYTHON_EXEC_PREFIX = @PYTHON_EXEC_PREFIX@
+PYTHON_INCLUDES = @PYTHON_INCLUDES@
+PYTHON_PLATFORM = @PYTHON_PLATFORM@
+PYTHON_PREFIX = @PYTHON_PREFIX@
+PYTHON_VERSION = @PYTHON_VERSION@
+RANLIB = @RANLIB@
+RST2HTML = @RST2HTML@
+RST2HTMLFLAGS = @RST2HTMLFLAGS@
+SED = @SED@
+SET_MAKE = @SET_MAKE@
+SHELL = @SHELL@
+STRIP = @STRIP@
+VERSION = @VERSION@
+abs_builddir = @abs_builddir@
+abs_srcdir = @abs_srcdir@
+abs_top_builddir = @abs_top_builddir@
+abs_top_srcdir = @abs_top_srcdir@
+ac_ct_CC = @ac_ct_CC@
+ac_ct_DUMPBIN = @ac_ct_DUMPBIN@
+am__include = @am__include@
+am__leading_dot = @am__leading_dot@
+am__quote = @am__quote@
+am__tar = @am__tar@
+am__untar = @am__untar@
+bindir = @bindir@
+build = @build@
+build_alias = @build_alias@
+build_cpu = @build_cpu@
+build_os = @build_os@
+build_vendor = @build_vendor@
+builddir = @builddir@
+datadir = @datadir@
+datarootdir = @datarootdir@
+docdir = @docdir@
+dvidir = @dvidir@
+exec_prefix = @exec_prefix@
+host = @host@
+host_alias = @host_alias@
+host_cpu = @host_cpu@
+host_os = @host_os@
+host_vendor = @host_vendor@
+htmldir = @htmldir@
+includedir = @includedir@
+infodir = @infodir@
+install_sh = @install_sh@
+libdir = @libdir@
+libexecdir = @libexecdir@
+localedir = @localedir@
+localstatedir = @localstatedir@
+lt_ECHO = @lt_ECHO@
+mandir = @mandir@
+mkdir_p = @mkdir_p@
+oldincludedir = @oldincludedir@
+pdfdir = @pdfdir@
+pkgpyexecdir = @pkgpyexecdir@
+pkgpythondir = @pkgpythondir@
+prefix = @prefix@
+program_transform_name = @program_transform_name@
+psdir = @psdir@
+pyexecdir = @pyexecdir@
+pythondir = @pythondir@
+sbindir = @sbindir@
+sharedstatedir = @sharedstatedir@
+srcdir = @srcdir@
+sysconfdir = @sysconfdir@
+target_alias = @target_alias@
+top_build_prefix = @top_build_prefix@
+top_builddir = @top_builddir@
+top_srcdir = @top_srcdir@
+EXTRA_DIST = \
+ cross-test-client.py \
+ cross-test-server.py \
+ crosstest.py \
+ run-test.sh \
+ run-with-tmp-session-bus.sh \
+ test-client.py \
+ test-p2p.py \
+ test-service.py \
+ test-signals.py \
+ test-standalone.py \
+ test-unusable-main-loop.py \
+ TestSuitePythonService.service.in \
+ tmp-session-bus.conf.in
+
+
+# If you try to make this noinst, libtool helpfully gives us a static
+# library, which doesn't work as a Python extension: so force the install
+# target not to work here instead.
+pyexec_LTLIBRARIES = dbus_py_test.la
+dbus_py_test_la_CPPFLAGS = -I$(top_srcdir)/include $(DBUS_CFLAGS) \
+ $(PYTHON_INCLUDES)
+
+dbus_py_test_la_LDFLAGS = -module -avoid-version \
+ $(DBUS_LIBS)
+
+dbus_py_test_la_SOURCES = dbus_py_test.c \
+ $(top_srcdir)/include/dbus-python.h
+
+TESTS_ENVIRONMENT = DBUS_TOP_SRCDIR="$(abs_top_srcdir)" \
+ DBUS_TOP_BUILDDIR="$(abs_top_builddir)" \
+ DBUS_PYTHON_VERSION='$(PACKAGE_VERSION)' \
+ PYTHONPATH="$(abs_top_builddir)/test/.libs:$(abs_top_srcdir):$(abs_top_srcdir)/test:$(abs_top_builddir)/_dbus_bindings/.libs:$(abs_top_builddir)/_dbus_glib_bindings/.libs" \
+ PYTHON='$(PYTHON)'
+
+TESTS = run-test.sh
+all: all-am
+
+.SUFFIXES:
+.SUFFIXES: .c .lo .o .obj
+$(srcdir)/Makefile.in: $(srcdir)/Makefile.am $(am__configure_deps)
+ @for dep in $?; do \
+ case '$(am__configure_deps)' in \
+ *$$dep*) \
+ ( cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh ) \
+ && { if test -f $@; then exit 0; else break; fi; }; \
+ exit 1;; \
+ esac; \
+ done; \
+ echo ' cd $(top_srcdir) && $(AUTOMAKE) --gnu test/Makefile'; \
+ $(am__cd) $(top_srcdir) && \
+ $(AUTOMAKE) --gnu test/Makefile
+.PRECIOUS: Makefile
+Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status
+ @case '$?' in \
+ *config.status*) \
+ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \
+ *) \
+ echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe)'; \
+ cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe);; \
+ esac;
+
+$(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES)
+ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
+
+$(top_srcdir)/configure: $(am__configure_deps)
+ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
+$(ACLOCAL_M4): $(am__aclocal_m4_deps)
+ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
+$(am__aclocal_m4_deps):
+tmp-session-bus.conf: $(top_builddir)/config.status $(srcdir)/tmp-session-bus.conf.in
+ cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@
+TestSuitePythonService.service: $(top_builddir)/config.status $(srcdir)/TestSuitePythonService.service.in
+ cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@
+install-pyexecLTLIBRARIES: $(pyexec_LTLIBRARIES)
+ @$(NORMAL_INSTALL)
+ test -z "$(pyexecdir)" || $(MKDIR_P) "$(DESTDIR)$(pyexecdir)"
+ @list='$(pyexec_LTLIBRARIES)'; test -n "$(pyexecdir)" || list=; \
+ list2=; for p in $$list; do \
+ if test -f $$p; then \
+ list2="$$list2 $$p"; \
+ else :; fi; \
+ done; \
+ test -z "$$list2" || { \
+ echo " $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL) $(INSTALL_STRIP_FLAG) $$list2 '$(DESTDIR)$(pyexecdir)'"; \
+ $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL) $(INSTALL_STRIP_FLAG) $$list2 "$(DESTDIR)$(pyexecdir)"; \
+ }
+
+uninstall-pyexecLTLIBRARIES:
+ @$(NORMAL_UNINSTALL)
+ @list='$(pyexec_LTLIBRARIES)'; test -n "$(pyexecdir)" || list=; \
+ for p in $$list; do \
+ $(am__strip_dir) \
+ echo " $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=uninstall rm -f '$(DESTDIR)$(pyexecdir)/$$f'"; \
+ $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=uninstall rm -f "$(DESTDIR)$(pyexecdir)/$$f"; \
+ done
+
+clean-pyexecLTLIBRARIES:
+ -test -z "$(pyexec_LTLIBRARIES)" || rm -f $(pyexec_LTLIBRARIES)
+ @list='$(pyexec_LTLIBRARIES)'; for p in $$list; do \
+ dir="`echo $$p | sed -e 's|/[^/]*$$||'`"; \
+ test "$$dir" != "$$p" || dir=.; \
+ echo "rm -f \"$${dir}/so_locations\""; \
+ rm -f "$${dir}/so_locations"; \
+ done
+dbus_py_test.la: $(dbus_py_test_la_OBJECTS) $(dbus_py_test_la_DEPENDENCIES)
+ $(AM_V_CCLD)$(dbus_py_test_la_LINK) -rpath $(pyexecdir) $(dbus_py_test_la_OBJECTS) $(dbus_py_test_la_LIBADD) $(LIBS)
+
+mostlyclean-compile:
+ -rm -f *.$(OBJEXT)
+
+distclean-compile:
+ -rm -f *.tab.c
+
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/dbus_py_test_la-dbus_py_test.Plo@am__quote@
+
+.c.o:
+@am__fastdepCC_TRUE@ $(AM_V_CC)$(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $<
+@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po
+@am__fastdepCC_FALSE@ $(AM_V_CC) @AM_BACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='$<' object='$@' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(COMPILE) -c $<
+
+.c.obj:
+@am__fastdepCC_TRUE@ $(AM_V_CC)$(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ `$(CYGPATH_W) '$<'`
+@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po
+@am__fastdepCC_FALSE@ $(AM_V_CC) @AM_BACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='$<' object='$@' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(COMPILE) -c `$(CYGPATH_W) '$<'`
+
+.c.lo:
+@am__fastdepCC_TRUE@ $(AM_V_CC)$(LTCOMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $<
+@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Plo
+@am__fastdepCC_FALSE@ $(AM_V_CC) @AM_BACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='$<' object='$@' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(LTCOMPILE) -c -o $@ $<
+
+dbus_py_test_la-dbus_py_test.lo: dbus_py_test.c
+@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(dbus_py_test_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT dbus_py_test_la-dbus_py_test.lo -MD -MP -MF $(DEPDIR)/dbus_py_test_la-dbus_py_test.Tpo -c -o dbus_py_test_la-dbus_py_test.lo `test -f 'dbus_py_test.c' || echo '$(srcdir)/'`dbus_py_test.c
+@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/dbus_py_test_la-dbus_py_test.Tpo $(DEPDIR)/dbus_py_test_la-dbus_py_test.Plo
+@am__fastdepCC_FALSE@ $(AM_V_CC) @AM_BACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='dbus_py_test.c' object='dbus_py_test_la-dbus_py_test.lo' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(dbus_py_test_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o dbus_py_test_la-dbus_py_test.lo `test -f 'dbus_py_test.c' || echo '$(srcdir)/'`dbus_py_test.c
+
+mostlyclean-libtool:
+ -rm -f *.lo
+
+clean-libtool:
+ -rm -rf .libs _libs
+
+ID: $(HEADERS) $(SOURCES) $(LISP) $(TAGS_FILES)
+ list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \
+ unique=`for i in $$list; do \
+ if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
+ done | \
+ $(AWK) '{ files[$$0] = 1; nonempty = 1; } \
+ END { if (nonempty) { for (i in files) print i; }; }'`; \
+ mkid -fID $$unique
+tags: TAGS
+
+TAGS: $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \
+ $(TAGS_FILES) $(LISP)
+ set x; \
+ here=`pwd`; \
+ list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \
+ unique=`for i in $$list; do \
+ if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
+ done | \
+ $(AWK) '{ files[$$0] = 1; nonempty = 1; } \
+ END { if (nonempty) { for (i in files) print i; }; }'`; \
+ shift; \
+ if test -z "$(ETAGS_ARGS)$$*$$unique"; then :; else \
+ test -n "$$unique" || unique=$$empty_fix; \
+ if test $$# -gt 0; then \
+ $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \
+ "$$@" $$unique; \
+ else \
+ $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \
+ $$unique; \
+ fi; \
+ fi
+ctags: CTAGS
+CTAGS: $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \
+ $(TAGS_FILES) $(LISP)
+ list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \
+ unique=`for i in $$list; do \
+ if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
+ done | \
+ $(AWK) '{ files[$$0] = 1; nonempty = 1; } \
+ END { if (nonempty) { for (i in files) print i; }; }'`; \
+ test -z "$(CTAGS_ARGS)$$unique" \
+ || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \
+ $$unique
+
+GTAGS:
+ here=`$(am__cd) $(top_builddir) && pwd` \
+ && $(am__cd) $(top_srcdir) \
+ && gtags -i $(GTAGS_ARGS) "$$here"
+
+distclean-tags:
+ -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags
+
+check-TESTS: $(TESTS)
+ @failed=0; all=0; xfail=0; xpass=0; skip=0; \
+ srcdir=$(srcdir); export srcdir; \
+ list=' $(TESTS) '; \
+ $(am__tty_colors); \
+ if test -n "$$list"; then \
+ for tst in $$list; do \
+ if test -f ./$$tst; then dir=./; \
+ elif test -f $$tst; then dir=; \
+ else dir="$(srcdir)/"; fi; \
+ if $(TESTS_ENVIRONMENT) $${dir}$$tst; then \
+ all=`expr $$all + 1`; \
+ case " $(XFAIL_TESTS) " in \
+ *[\ \ ]$$tst[\ \ ]*) \
+ xpass=`expr $$xpass + 1`; \
+ failed=`expr $$failed + 1`; \
+ col=$$red; res=XPASS; \
+ ;; \
+ *) \
+ col=$$grn; res=PASS; \
+ ;; \
+ esac; \
+ elif test $$? -ne 77; then \
+ all=`expr $$all + 1`; \
+ case " $(XFAIL_TESTS) " in \
+ *[\ \ ]$$tst[\ \ ]*) \
+ xfail=`expr $$xfail + 1`; \
+ col=$$lgn; res=XFAIL; \
+ ;; \
+ *) \
+ failed=`expr $$failed + 1`; \
+ col=$$red; res=FAIL; \
+ ;; \
+ esac; \
+ else \
+ skip=`expr $$skip + 1`; \
+ col=$$blu; res=SKIP; \
+ fi; \
+ echo "$${col}$$res$${std}: $$tst"; \
+ done; \
+ if test "$$all" -eq 1; then \
+ tests="test"; \
+ All=""; \
+ else \
+ tests="tests"; \
+ All="All "; \
+ fi; \
+ if test "$$failed" -eq 0; then \
+ if test "$$xfail" -eq 0; then \
+ banner="$$All$$all $$tests passed"; \
+ else \
+ if test "$$xfail" -eq 1; then failures=failure; else failures=failures; fi; \
+ banner="$$All$$all $$tests behaved as expected ($$xfail expected $$failures)"; \
+ fi; \
+ else \
+ if test "$$xpass" -eq 0; then \
+ banner="$$failed of $$all $$tests failed"; \
+ else \
+ if test "$$xpass" -eq 1; then passes=pass; else passes=passes; fi; \
+ banner="$$failed of $$all $$tests did not behave as expected ($$xpass unexpected $$passes)"; \
+ fi; \
+ fi; \
+ dashes="$$banner"; \
+ skipped=""; \
+ if test "$$skip" -ne 0; then \
+ if test "$$skip" -eq 1; then \
+ skipped="($$skip test was not run)"; \
+ else \
+ skipped="($$skip tests were not run)"; \
+ fi; \
+ test `echo "$$skipped" | wc -c` -le `echo "$$banner" | wc -c` || \
+ dashes="$$skipped"; \
+ fi; \
+ report=""; \
+ if test "$$failed" -ne 0 && test -n "$(PACKAGE_BUGREPORT)"; then \
+ report="Please report to $(PACKAGE_BUGREPORT)"; \
+ test `echo "$$report" | wc -c` -le `echo "$$banner" | wc -c` || \
+ dashes="$$report"; \
+ fi; \
+ dashes=`echo "$$dashes" | sed s/./=/g`; \
+ if test "$$failed" -eq 0; then \
+ echo "$$grn$$dashes"; \
+ else \
+ echo "$$red$$dashes"; \
+ fi; \
+ echo "$$banner"; \
+ test -z "$$skipped" || echo "$$skipped"; \
+ test -z "$$report" || echo "$$report"; \
+ echo "$$dashes$$std"; \
+ test "$$failed" -eq 0; \
+ else :; fi
+
+distdir: $(DISTFILES)
+ @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \
+ topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \
+ list='$(DISTFILES)'; \
+ dist_files=`for file in $$list; do echo $$file; done | \
+ sed -e "s|^$$srcdirstrip/||;t" \
+ -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \
+ case $$dist_files in \
+ */*) $(MKDIR_P) `echo "$$dist_files" | \
+ sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \
+ sort -u` ;; \
+ esac; \
+ for file in $$dist_files; do \
+ if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \
+ if test -d $$d/$$file; then \
+ dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \
+ if test -d "$(distdir)/$$file"; then \
+ find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \
+ fi; \
+ if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \
+ cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \
+ find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \
+ fi; \
+ cp -fpR $$d/$$file "$(distdir)$$dir" || exit 1; \
+ else \
+ test -f "$(distdir)/$$file" \
+ || cp -p $$d/$$file "$(distdir)/$$file" \
+ || exit 1; \
+ fi; \
+ done
+check-am: all-am
+ $(MAKE) $(AM_MAKEFLAGS) check-TESTS
+check: check-am
+all-am: Makefile $(LTLIBRARIES)
+installdirs:
+ for dir in "$(DESTDIR)$(pyexecdir)"; do \
+ test -z "$$dir" || $(MKDIR_P) "$$dir"; \
+ done
+install-exec: install-exec-am
+install-data: install-data-am
+uninstall: uninstall-am
+
+install-am: all-am
+ @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am
+
+installcheck: installcheck-am
+install-strip:
+ $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \
+ install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \
+ `test -z '$(STRIP)' || \
+ echo "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'"` install
+mostlyclean-generic:
+
+clean-generic:
+
+distclean-generic:
+ -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES)
+ -test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES)
+
+maintainer-clean-generic:
+ @echo "This command is intended for maintainers to use"
+ @echo "it deletes files that may require special tools to rebuild."
+clean: clean-am
+
+clean-am: clean-generic clean-libtool clean-pyexecLTLIBRARIES \
+ mostlyclean-am
+
+distclean: distclean-am
+ -rm -rf ./$(DEPDIR)
+ -rm -f Makefile
+distclean-am: clean-am distclean-compile distclean-generic \
+ distclean-tags
+
+dvi: dvi-am
+
+dvi-am:
+
+html: html-am
+
+html-am:
+
+info: info-am
+
+info-am:
+
+install-data-am:
+
+install-dvi: install-dvi-am
+
+install-dvi-am:
+
+install-exec-am: install-pyexecLTLIBRARIES
+
+install-html: install-html-am
+
+install-html-am:
+
+install-info: install-info-am
+
+install-info-am:
+
+install-man:
+
+install-pdf: install-pdf-am
+
+install-pdf-am:
+
+install-ps: install-ps-am
+
+install-ps-am:
+
+installcheck-am:
+
+maintainer-clean: maintainer-clean-am
+ -rm -rf ./$(DEPDIR)
+ -rm -f Makefile
+maintainer-clean-am: distclean-am maintainer-clean-generic
+
+mostlyclean: mostlyclean-am
+
+mostlyclean-am: mostlyclean-compile mostlyclean-generic \
+ mostlyclean-libtool
+
+pdf: pdf-am
+
+pdf-am:
+
+ps: ps-am
+
+ps-am:
+
+uninstall-am: uninstall-pyexecLTLIBRARIES
+
+.MAKE: check-am install-am install-strip
+
+.PHONY: CTAGS GTAGS all all-am check check-TESTS check-am clean \
+ clean-generic clean-libtool clean-pyexecLTLIBRARIES ctags \
+ distclean distclean-compile distclean-generic \
+ distclean-libtool distclean-tags distdir dvi dvi-am html \
+ html-am info info-am install install-am install-data \
+ install-data-am install-dvi install-dvi-am install-exec \
+ install-exec-am install-html install-html-am install-info \
+ install-info-am install-man install-pdf install-pdf-am \
+ install-ps install-ps-am install-pyexecLTLIBRARIES \
+ install-strip installcheck installcheck-am installdirs \
+ maintainer-clean maintainer-clean-generic mostlyclean \
+ mostlyclean-compile mostlyclean-generic mostlyclean-libtool \
+ pdf pdf-am ps ps-am tags uninstall uninstall-am \
+ uninstall-pyexecLTLIBRARIES
+
+
+install:
+ @echo "Not installing anything from test/"
+
+cross-test-server:
+ $(TESTS_ENVIRONMENT) $(PYTHON) $(top_srcdir)/test/cross-test-server.py
+cross-test-client:
+ $(TESTS_ENVIRONMENT) $(PYTHON) $(top_srcdir)/test/cross-test-client.py
+
+.PHONY: cross-test-compile cross-test-server cross-test-client
+
+# Tell versions [3.59,3.63) of GNU make to not export all variables.
+# Otherwise a system limit (for SysV at least) may be exceeded.
+.NOEXPORT:
diff --git a/test/TestSuitePythonService.service.in b/test/TestSuitePythonService.service.in
new file mode 100644
index 0000000..5abdf20
--- /dev/null
+++ b/test/TestSuitePythonService.service.in
@@ -0,0 +1,3 @@
+[D-BUS Service]
+Name=org.freedesktop.DBus.TestSuitePythonService
+Exec=/bin/bash -c "@PYTHON@ @abs_top_srcdir@/test/test-service.py"
diff --git a/test/cross-test-client.py b/test/cross-test-client.py
new file mode 100644
index 0000000..ee18f77
--- /dev/null
+++ b/test/cross-test-client.py
@@ -0,0 +1,393 @@
+# Copyright (C) 2006 Collabora Ltd. <http://www.collabora.co.uk/>
+#
+# Permission is hereby granted, free of charge, to any person
+# obtaining a copy of this software and associated documentation
+# files (the "Software"), to deal in the Software without
+# restriction, including without limitation the rights to use, copy,
+# modify, merge, publish, distribute, sublicense, and/or sell copies
+# of the Software, and to permit persons to whom the Software is
+# furnished to do so, subject to the following conditions:
+#
+# The above copyright notice and this permission notice shall be
+# included in all copies or substantial portions of the Software.
+#
+# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+# HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+# WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+# DEALINGS IN THE SOFTWARE.
+
+from time import sleep
+import logging
+
+import gobject
+
+from dbus import SessionBus, Interface, Array, Byte, Double, Boolean, ByteArray, Int16, Int32, Int64, UInt16, UInt32, UInt64, String, UTF8String, Struct, Dictionary
+from dbus.service import BusName
+import dbus.glib
+
+from crosstest import CROSS_TEST_PATH, CROSS_TEST_BUS_NAME,\
+ INTERFACE_SINGLE_TESTS, INTERFACE_TESTS,\
+ INTERFACE_SIGNAL_TESTS, INTERFACE_CALLBACK_TESTS,\
+ SignalTestsImpl
+
+
+logging.basicConfig()
+logging.getLogger().setLevel(1)
+logger = logging.getLogger('cross-test-client')
+
+
+class Client(SignalTestsImpl):
+ fail_id = 0
+ expected = set()
+
+ def quit(self):
+ for x in self.expected:
+ self.fail_id += 1
+ print "%s fail %d" % (x, self.fail_id)
+ s = "report %d: reply to %s didn't arrive" % (self.fail_id, x)
+ print s
+ logger.error(s)
+ logger.info("asking server to Exit")
+ Interface(self.obj, INTERFACE_TESTS).Exit(reply_handler=self.quit_reply_handler, error_handler=self.quit_error_handler)
+ # if the server doesn't reply we'll just exit anyway
+ gobject.timeout_add(1000, lambda: (loop.quit(), False)[1])
+
+ def quit_reply_handler(self):
+ logger.info("server says it will exit")
+ loop.quit()
+
+ def quit_error_handler(self, e):
+ logger.error("error telling server to quit: %s %s",
+ e.__class__, e)
+ loop.quit()
+
+ @dbus.service.method(INTERFACE_CALLBACK_TESTS, 'qd')
+ def Response(self, input1, input2):
+ logger.info("signal/callback: Response received (%r,%r)",
+ input1, input2)
+ self.expected.discard('%s.Trigger' % INTERFACE_SIGNAL_TESTS)
+ if (input1, input2) != (42, 23):
+ self.fail_id += 1
+ print "%s.Trigger fail %d" % (INTERFACE_SIGNAL_TESTS, self.fail_id)
+ s = ("report %d: expected (42,23), got %r"
+ % (self.fail_id, (input1, input2)))
+ logger.error(s)
+ print s
+ else:
+ print "%s.Trigger pass" % INTERFACE_SIGNAL_TESTS
+ self.quit()
+
+ def assert_method_matches(self, interface, check_fn, check_arg, member, *args):
+ if_obj = Interface(self.obj, interface)
+ method = getattr(if_obj, member)
+ try:
+ real_ret = method(*args)
+ except Exception, e:
+ self.fail_id += 1
+ print "%s.%s fail %d" % (interface, member, self.fail_id)
+ s = ("report %d: %s.%s%r: raised %r \"%s\""
+ % (self.fail_id, interface, member, args, e, e))
+ print s
+ logger.error(s)
+ __import__('traceback').print_exc()
+ return
+ try:
+ check_fn(real_ret, check_arg)
+ except Exception, e:
+ self.fail_id += 1
+ print "%s.%s fail %d" % (interface, member, self.fail_id)
+ s = ("report %d: %s.%s%r: %s"
+ % (self.fail_id, interface, member, args, e))
+ print s
+ logger.error(s)
+ return
+ print "%s.%s pass" % (interface, member)
+
+ def assert_method_eq(self, interface, ret, member, *args):
+ def equals(real_ret, exp):
+ if real_ret != exp:
+ raise AssertionError('expected %r of class %s, got %r of class %s' % (exp, exp.__class__, real_ret, real_ret.__class__))
+ if real_ret != exp:
+ raise AssertionError('expected %r, got %r' % (exp, real_ret))
+ if not isinstance(exp, (tuple, type(None))):
+ if real_ret.variant_level != getattr(exp, 'variant_level', 0):
+ raise AssertionError('expected variant_level=%d, got %r with level %d'
+ % (getattr(exp, 'variant_level', 0), real_ret,
+ real_ret.variant_level))
+ if isinstance(exp, list) or isinstance(exp, tuple):
+ for i in xrange(len(exp)):
+ try:
+ equals(real_ret[i], exp[i])
+ except AssertionError, e:
+ if not isinstance(e.args, tuple):
+ e.args = (e.args,)
+ e.args = e.args + ('(at position %d in sequence)' % i,)
+ raise e
+ elif isinstance(exp, dict):
+ for k in exp:
+ try:
+ equals(real_ret[k], exp[k])
+ except AssertionError, e:
+ if not isinstance(e.args, tuple):
+ e.args = (e.args,)
+ e.args = e.args + ('(at key %r in dict)' % k,)
+ raise e
+ self.assert_method_matches(interface, equals, ret, member, *args)
+
+ def assert_InvertMapping_eq(self, interface, expected, member, mapping):
+ def check(real_ret, exp):
+ for key in exp:
+ if key not in real_ret:
+ raise AssertionError('missing key %r' % key)
+ for key in real_ret:
+ if key not in exp:
+ raise AssertionError('unexpected key %r' % key)
+ got = list(real_ret[key])
+ wanted = list(exp[key])
+ got.sort()
+ wanted.sort()
+ if got != wanted:
+ raise AssertionError('expected %r => %r, got %r'
+ % (key, wanted, got))
+ self.assert_method_matches(interface, check, expected, member, mapping)
+
+ def triggered_cb(self, param, sender_path):
+ logger.info("method/signal: Triggered(%r) by %r",
+ param, sender_path)
+ self.expected.discard('%s.Trigger' % INTERFACE_TESTS)
+ if sender_path != '/Where/Ever':
+ self.fail_id += 1
+ print "%s.Trigger fail %d" % (INTERFACE_TESTS, self.fail_id)
+ s = ("report %d: expected signal from /Where/Ever, got %r"
+ % (self.fail_id, sender_path))
+ print s
+ logger.error(s)
+ elif param != 42:
+ self.fail_id += 1
+ print "%s.Trigger fail %d" % (INTERFACE_TESTS, self.fail_id)
+ s = ("report %d: expected signal param 42, got %r"
+ % (self.fail_id, parameter))
+ print s
+ logger.error(s)
+ else:
+ print "%s.Trigger pass" % INTERFACE_TESTS
+
+ def trigger_returned_cb(self):
+ logger.info('method/signal: Trigger() returned')
+ # Callback tests
+ logger.info("signal/callback: Emitting signal to trigger callback")
+ self.expected.add('%s.Trigger' % INTERFACE_SIGNAL_TESTS)
+ self.Trigger(UInt16(42), 23.0)
+ logger.info("signal/callback: Emitting signal returned")
+
+ def run_client(self):
+ bus = SessionBus()
+ obj = bus.get_object(CROSS_TEST_BUS_NAME, CROSS_TEST_PATH)
+ self.obj = obj
+
+ self.run_synchronous_tests(obj)
+
+ # Signal tests
+ logger.info("Binding signal handler for Triggered")
+ # FIXME: doesn't seem to work when going via the Interface method
+ # FIXME: should be possible to ask the proxy object for its
+ # bus name
+ bus.add_signal_receiver(self.triggered_cb, 'Triggered',
+ INTERFACE_SIGNAL_TESTS,
+ CROSS_TEST_BUS_NAME,
+ path_keyword='sender_path')
+ logger.info("method/signal: Triggering signal")
+ self.expected.add('%s.Trigger' % INTERFACE_TESTS)
+ Interface(obj, INTERFACE_TESTS).Trigger(u'/Where/Ever', dbus.UInt64(42), reply_handler=self.trigger_returned_cb, error_handler=self.trigger_error_handler)
+
+ def trigger_error_handler(self, e):
+ logger.error("method/signal: %s %s", e.__class__, e)
+ Interface(self.obj, INTERFACE_TESTS).Exit()
+ self.quit()
+
+ def run_synchronous_tests(self, obj):
+ # We can't test that coercion works correctly unless the server has
+ # sent us introspection data. Java doesn't :-/
+ have_signatures = True
+
+ # "Single tests"
+ if have_signatures:
+ self.assert_method_eq(INTERFACE_SINGLE_TESTS, 6, 'Sum', [1, 2, 3])
+ self.assert_method_eq(INTERFACE_SINGLE_TESTS, 6, 'Sum', ['\x01', '\x02', '\x03'])
+ self.assert_method_eq(INTERFACE_SINGLE_TESTS, 6, 'Sum', [Byte(1), Byte(2), Byte(3)])
+ self.assert_method_eq(INTERFACE_SINGLE_TESTS, 6, 'Sum', ByteArray('\x01\x02\x03'))
+
+ # Main tests
+ self.assert_method_eq(INTERFACE_TESTS, String(u'foo', variant_level=1), 'Identity', String('foo'))
+ self.assert_method_eq(INTERFACE_TESTS, String(u'foo', variant_level=1), 'Identity', UTF8String('foo'))
+ self.assert_method_eq(INTERFACE_TESTS, Byte(42, variant_level=1), 'Identity', Byte(42))
+ self.assert_method_eq(INTERFACE_TESTS, Byte(42, variant_level=23), 'Identity', Byte(42, variant_level=23))
+ self.assert_method_eq(INTERFACE_TESTS, Double(42.5, variant_level=1), 'Identity', 42.5)
+ self.assert_method_eq(INTERFACE_TESTS, Double(-42.5, variant_level=1), 'Identity', -42.5)
+
+ if have_signatures:
+ self.assert_method_eq(INTERFACE_TESTS, String(u'foo', variant_level=1), 'Identity', 'foo')
+ self.assert_method_eq(INTERFACE_TESTS, Byte(42, variant_level=1), 'Identity', Byte(42))
+ self.assert_method_eq(INTERFACE_TESTS, Double(42.5, variant_level=1), 'Identity', Double(42.5))
+ self.assert_method_eq(INTERFACE_TESTS, Double(-42.5, variant_level=1), 'Identity', -42.5)
+
+ for i in (0, 42, 255):
+ self.assert_method_eq(INTERFACE_TESTS, Byte(i), 'IdentityByte', Byte(i))
+ for i in (True, False):
+ self.assert_method_eq(INTERFACE_TESTS, i, 'IdentityBool', i)
+
+ for i in (-0x8000, 0, 42, 0x7fff):
+ self.assert_method_eq(INTERFACE_TESTS, i, 'IdentityInt16', Int16(i))
+ for i in (0, 42, 0xffff):
+ self.assert_method_eq(INTERFACE_TESTS, i, 'IdentityUInt16', UInt16(i))
+ for i in (-0x7fffffff-1, 0, 42, 0x7fffffff):
+ self.assert_method_eq(INTERFACE_TESTS, i, 'IdentityInt32', Int32(i))
+ for i in (0L, 42L, 0xffffffffL):
+ self.assert_method_eq(INTERFACE_TESTS, i, 'IdentityUInt32', UInt32(i))
+ MANY = 0x8000L * 0x10000L * 0x10000L * 0x10000L
+ for i in (-MANY, 0, 42, MANY-1):
+ self.assert_method_eq(INTERFACE_TESTS, i, 'IdentityInt64', Int64(i))
+ for i in (0, 42, 2*MANY - 1):
+ self.assert_method_eq(INTERFACE_TESTS, i, 'IdentityUInt64', UInt64(i))
+
+ self.assert_method_eq(INTERFACE_TESTS, 42.3, 'IdentityDouble', 42.3)
+ for i in ('', 'foo'):
+ self.assert_method_eq(INTERFACE_TESTS, i, 'IdentityString', i)
+ for i in (u'\xa9', '\xc2\xa9'):
+ self.assert_method_eq(INTERFACE_TESTS, u'\xa9', 'IdentityString', i)
+
+ if have_signatures:
+ self.assert_method_eq(INTERFACE_TESTS, Byte(0x42), 'IdentityByte', '\x42')
+ self.assert_method_eq(INTERFACE_TESTS, True, 'IdentityBool', 42)
+ self.assert_method_eq(INTERFACE_TESTS, 42, 'IdentityInt16', 42)
+ self.assert_method_eq(INTERFACE_TESTS, 42, 'IdentityUInt16', 42)
+ self.assert_method_eq(INTERFACE_TESTS, 42, 'IdentityInt32', 42)
+ self.assert_method_eq(INTERFACE_TESTS, 42, 'IdentityUInt32', 42)
+ self.assert_method_eq(INTERFACE_TESTS, 42, 'IdentityInt64', 42)
+ self.assert_method_eq(INTERFACE_TESTS, 42, 'IdentityUInt64', 42)
+ self.assert_method_eq(INTERFACE_TESTS, 42.0, 'IdentityDouble', 42)
+
+ self.assert_method_eq(INTERFACE_TESTS, [Byte('\x01', variant_level=1),
+ Byte('\x02', variant_level=1),
+ Byte('\x03', variant_level=1)],
+ 'IdentityArray',
+ Array([Byte('\x01'),
+ Byte('\x02'),
+ Byte('\x03')],
+ signature='v'))
+
+ self.assert_method_eq(INTERFACE_TESTS, [Int32(1, variant_level=1),
+ Int32(2, variant_level=1),
+ Int32(3, variant_level=1)],
+ 'IdentityArray',
+ Array([Int32(1),
+ Int32(2),
+ Int32(3)],
+ signature='v'))
+ self.assert_method_eq(INTERFACE_TESTS, [String(u'a', variant_level=1),
+ String(u'b', variant_level=1),
+ String(u'c', variant_level=1)],
+ 'IdentityArray',
+ Array([String('a'),
+ String('b'),
+ String('c')],
+ signature='v'))
+
+ if have_signatures:
+ self.assert_method_eq(INTERFACE_TESTS, [Byte('\x01', variant_level=1),
+ Byte('\x02', variant_level=1),
+ Byte('\x03', variant_level=1)],
+ 'IdentityArray',
+ ByteArray('\x01\x02\x03'))
+ self.assert_method_eq(INTERFACE_TESTS, [Int32(1, variant_level=1),
+ Int32(2, variant_level=1),
+ Int32(3, variant_level=1)],
+ 'IdentityArray',
+ [Int32(1),
+ Int32(2),
+ Int32(3)])
+ self.assert_method_eq(INTERFACE_TESTS, [String(u'a', variant_level=1),
+ String(u'b', variant_level=1),
+ String(u'c', variant_level=1)],
+ 'IdentityArray',
+ ['a','b','c'])
+
+ self.assert_method_eq(INTERFACE_TESTS,
+ [Byte(1), Byte(2), Byte(3)],
+ 'IdentityByteArray',
+ ByteArray('\x01\x02\x03'))
+ if have_signatures:
+ self.assert_method_eq(INTERFACE_TESTS, [1,2,3], 'IdentityByteArray', ['\x01', '\x02', '\x03'])
+ self.assert_method_eq(INTERFACE_TESTS, [False,True], 'IdentityBoolArray', [False,True])
+ if have_signatures:
+ self.assert_method_eq(INTERFACE_TESTS, [False,True,True], 'IdentityBoolArray', [0,1,2])
+
+ self.assert_method_eq(INTERFACE_TESTS, [1,2,3], 'IdentityInt16Array', [Int16(1),Int16(2),Int16(3)])
+ self.assert_method_eq(INTERFACE_TESTS, [1,2,3], 'IdentityUInt16Array', [UInt16(1),UInt16(2),UInt16(3)])
+ self.assert_method_eq(INTERFACE_TESTS, [1,2,3], 'IdentityInt32Array', [Int32(1),Int32(2),Int32(3)])
+ self.assert_method_eq(INTERFACE_TESTS, [1,2,3], 'IdentityUInt32Array', [UInt32(1),UInt32(2),UInt32(3)])
+ self.assert_method_eq(INTERFACE_TESTS, [1,2,3], 'IdentityInt64Array', [Int64(1),Int64(2),Int64(3)])
+ self.assert_method_eq(INTERFACE_TESTS, [1,2,3], 'IdentityUInt64Array', [UInt64(1),UInt64(2),UInt64(3)])
+
+ if have_signatures:
+ self.assert_method_eq(INTERFACE_TESTS, [1,2,3], 'IdentityInt16Array', [1,2,3])
+ self.assert_method_eq(INTERFACE_TESTS, [1,2,3], 'IdentityUInt16Array', [1,2,3])
+ self.assert_method_eq(INTERFACE_TESTS, [1,2,3], 'IdentityInt32Array', [1,2,3])
+ self.assert_method_eq(INTERFACE_TESTS, [1,2,3], 'IdentityUInt32Array', [1,2,3])
+ self.assert_method_eq(INTERFACE_TESTS, [1,2,3], 'IdentityInt64Array', [1,2,3])
+ self.assert_method_eq(INTERFACE_TESTS, [1,2,3], 'IdentityUInt64Array', [1,2,3])
+
+ self.assert_method_eq(INTERFACE_TESTS, [1.0,2.5,3.1], 'IdentityDoubleArray', [1.0,2.5,3.1])
+ if have_signatures:
+ self.assert_method_eq(INTERFACE_TESTS, [1.0,2.5,3.1], 'IdentityDoubleArray', [1,2.5,3.1])
+ self.assert_method_eq(INTERFACE_TESTS, ['a','b','c'], 'IdentityStringArray', ['a','b','c'])
+ self.assert_method_eq(INTERFACE_TESTS, 6, 'Sum', [Int32(1),Int32(2),Int32(3)])
+ if have_signatures:
+ self.assert_method_eq(INTERFACE_TESTS, 6, 'Sum', [1,2,3])
+
+ self.assert_InvertMapping_eq(INTERFACE_TESTS, {'fps': ['unreal', 'quake'], 'rts': ['warcraft']}, 'InvertMapping', {'unreal': 'fps', 'quake': 'fps', 'warcraft': 'rts'})
+
+ self.assert_method_eq(INTERFACE_TESTS, ('a', 1, 2), 'DeStruct', ('a', UInt32(1), Int16(2)))
+ self.assert_method_eq(INTERFACE_TESTS, Array([String('x', variant_level=1)]),
+ 'Primitize', [String('x', variant_level=1)])
+ self.assert_method_eq(INTERFACE_TESTS, Array([String('x', variant_level=1)]),
+ 'Primitize', [String('x', variant_level=23)])
+ self.assert_method_eq(INTERFACE_TESTS,
+ Array([String('x', variant_level=1),
+ Byte(1, variant_level=1),
+ Byte(2, variant_level=1)]),
+ 'Primitize',
+ Array([String('x'), Byte(1), Byte(2)],
+ signature='v'))
+ self.assert_method_eq(INTERFACE_TESTS,
+ Array([String('x', variant_level=1),
+ Byte(1, variant_level=1),
+ Byte(2, variant_level=1)]),
+ 'Primitize',
+ Array([String('x'), Array([Byte(1), Byte(2)])],
+ signature='v'))
+ self.assert_method_eq(INTERFACE_TESTS, Boolean(False), 'Invert', True)
+ self.assert_method_eq(INTERFACE_TESTS, Boolean(True), 'Invert', False)
+ if have_signatures:
+ self.assert_method_eq(INTERFACE_TESTS, Boolean(False), 'Invert', 42)
+ self.assert_method_eq(INTERFACE_TESTS, Boolean(True), 'Invert', 0)
+
+
+if __name__ == '__main__':
+ # FIXME: should be possible to export objects without a bus name
+ if 0:
+ client = Client(dbus.SessionBus(), '/Client')
+ else:
+ # the Java cross test's interpretation is that the client should be
+ # at /Test too
+ client = Client(dbus.SessionBus(), '/Test')
+ gobject.idle_add(client.run_client)
+
+ loop = gobject.MainLoop()
+ logger.info("running...")
+ loop.run()
+ logger.info("main loop exited.")
diff --git a/test/cross-test-server.py b/test/cross-test-server.py
new file mode 100644
index 0000000..40d121a
--- /dev/null
+++ b/test/cross-test-server.py
@@ -0,0 +1,323 @@
+# Copyright (C) 2006 Collabora Ltd. <http://www.collabora.co.uk/>
+#
+# Permission is hereby granted, free of charge, to any person
+# obtaining a copy of this software and associated documentation
+# files (the "Software"), to deal in the Software without
+# restriction, including without limitation the rights to use, copy,
+# modify, merge, publish, distribute, sublicense, and/or sell copies
+# of the Software, and to permit persons to whom the Software is
+# furnished to do so, subject to the following conditions:
+#
+# The above copyright notice and this permission notice shall be
+# included in all copies or substantial portions of the Software.
+#
+# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+# HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+# WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+# DEALINGS IN THE SOFTWARE.
+
+import logging
+
+import gobject
+
+import dbus.glib
+from dbus import SessionBus
+from dbus.service import BusName
+
+from crosstest import CROSS_TEST_PATH, CROSS_TEST_BUS_NAME, \
+ INTERFACE_SINGLE_TESTS, INTERFACE_TESTS,\
+ INTERFACE_CALLBACK_TESTS, INTERFACE_SIGNAL_TESTS,\
+ SignalTestsImpl
+
+
+logging.basicConfig()
+logging.getLogger().setLevel(1)
+logger = logging.getLogger('cross-test-server')
+
+
+class VerboseSet(set):
+ def add(self, thing):
+ print '%s ok' % thing
+ set.add(self, thing)
+
+
+objects = {}
+
+
+tested_things = VerboseSet()
+testable_things = [
+ INTERFACE_SINGLE_TESTS + '.Sum',
+ INTERFACE_TESTS + '.Identity',
+ INTERFACE_TESTS + '.IdentityByte',
+ INTERFACE_TESTS + '.IdentityBool',
+ INTERFACE_TESTS + '.IdentityInt16',
+ INTERFACE_TESTS + '.IdentityUInt16',
+ INTERFACE_TESTS + '.IdentityInt32',
+ INTERFACE_TESTS + '.IdentityUInt32',
+ INTERFACE_TESTS + '.IdentityInt64',
+ INTERFACE_TESTS + '.IdentityUInt64',
+ INTERFACE_TESTS + '.IdentityDouble',
+ INTERFACE_TESTS + '.IdentityString',
+ INTERFACE_TESTS + '.IdentityArray',
+ INTERFACE_TESTS + '.IdentityByteArray',
+ INTERFACE_TESTS + '.IdentityBoolArray',
+ INTERFACE_TESTS + '.IdentityInt16Array',
+ INTERFACE_TESTS + '.IdentityUInt16Array',
+ INTERFACE_TESTS + '.IdentityInt32Array',
+ INTERFACE_TESTS + '.IdentityUInt32Array',
+ INTERFACE_TESTS + '.IdentityInt64Array',
+ INTERFACE_TESTS + '.IdentityUInt64Array',
+ INTERFACE_TESTS + '.IdentityDoubleArray',
+ INTERFACE_TESTS + '.IdentityStringArray',
+ INTERFACE_TESTS + '.Sum',
+ INTERFACE_TESTS + '.InvertMapping',
+ INTERFACE_TESTS + '.DeStruct',
+ INTERFACE_TESTS + '.Primitize',
+ INTERFACE_TESTS + '.Trigger',
+ INTERFACE_TESTS + '.Exit',
+ INTERFACE_TESTS + '.Invert',
+ INTERFACE_SIGNAL_TESTS + '.Trigger',
+]
+
+
+class SingleTestsImpl(dbus.service.Object):
+
+ @dbus.service.method(INTERFACE_SINGLE_TESTS, 'ay', 'u')
+ def Sum(self, input):
+ tested_things.add(INTERFACE_SINGLE_TESTS + '.Sum')
+ u = sum(input)
+ logger.info('Sum of %r is %r', input, u)
+ return u
+
+
+class TestsImpl(dbus.service.Object):
+
+ def __init__(self, bus_name, service_path, exit_fn):
+ self._exit_fn = exit_fn
+ dbus.service.Object.__init__(self, bus_name, service_path)
+
+ @dbus.service.method(INTERFACE_TESTS, 'v', 'v')
+ def Identity(self, input):
+ tested_things.add(INTERFACE_TESTS + '.Identity')
+ return input
+
+ @dbus.service.method(INTERFACE_TESTS, 'y', 'y')
+ def IdentityByte(self, input):
+ tested_things.add(INTERFACE_TESTS + '.IdentityByte')
+ return input
+
+ @dbus.service.method(INTERFACE_TESTS, 'b', 'b')
+ def IdentityBool(self, input):
+ tested_things.add(INTERFACE_TESTS + '.IdentityBool')
+ return input
+
+ @dbus.service.method(INTERFACE_TESTS, 'n', 'n')
+ def IdentityInt16(self, input):
+ tested_things.add(INTERFACE_TESTS + '.IdentityInt16')
+ return input
+
+ @dbus.service.method(INTERFACE_TESTS, 'q', 'q')
+ def IdentityUInt16(self, input):
+ tested_things.add(INTERFACE_TESTS + '.IdentityUInt16')
+ return input
+
+ @dbus.service.method(INTERFACE_TESTS, 'i', 'i')
+ def IdentityInt32(self, input):
+ tested_things.add(INTERFACE_TESTS + '.IdentityInt32')
+ return input
+
+ @dbus.service.method(INTERFACE_TESTS, 'u', 'u')
+ def IdentityUInt32(self, input):
+ tested_things.add(INTERFACE_TESTS + '.IdentityUInt32')
+ return input
+
+ @dbus.service.method(INTERFACE_TESTS, 'x', 'x')
+ def IdentityInt64(self, input):
+ tested_things.add(INTERFACE_TESTS + '.IdentityInt64')
+ return input
+
+ @dbus.service.method(INTERFACE_TESTS, 't', 't')
+ def IdentityUInt64(self, input):
+ tested_things.add(INTERFACE_TESTS + '.IdentityUInt64')
+ return input
+
+ @dbus.service.method(INTERFACE_TESTS, 'd', 'd')
+ def IdentityDouble(self, input):
+ tested_things.add(INTERFACE_TESTS + '.IdentityDouble')
+ return input
+
+ @dbus.service.method(INTERFACE_TESTS, 's', 's')
+ def IdentityString(self, input):
+ tested_things.add(INTERFACE_TESTS + '.IdentityString')
+ return input
+
+ @dbus.service.method(INTERFACE_TESTS, 'av', 'av')
+ def IdentityArray(self, input):
+ tested_things.add(INTERFACE_TESTS + '.IdentityArray')
+ return input
+
+ @dbus.service.method(INTERFACE_TESTS, 'ay', 'ay')
+ def IdentityByteArray(self, input):
+ tested_things.add(INTERFACE_TESTS + '.IdentityByteArray')
+ return input
+
+ @dbus.service.method(INTERFACE_TESTS, 'ab', 'ab')
+ def IdentityBoolArray(self, input):
+ tested_things.add(INTERFACE_TESTS + '.IdentityBoolArray')
+ return input
+
+ @dbus.service.method(INTERFACE_TESTS, 'an', 'an')
+ def IdentityInt16Array(self, input):
+ tested_things.add(INTERFACE_TESTS + '.IdentityInt16Array')
+ return input
+
+ @dbus.service.method(INTERFACE_TESTS, 'aq', 'aq')
+ def IdentityUInt16Array(self, input):
+ tested_things.add(INTERFACE_TESTS + '.IdentityUInt16Array')
+ return input
+
+ @dbus.service.method(INTERFACE_TESTS, 'ai', 'ai')
+ def IdentityInt32Array(self, input):
+ tested_things.add(INTERFACE_TESTS + '.IdentityInt32Array')
+ return input
+
+ @dbus.service.method(INTERFACE_TESTS, 'au', 'au')
+ def IdentityUInt32Array(self, input):
+ tested_things.add(INTERFACE_TESTS + '.IdentityUInt32Array')
+ return input
+
+ @dbus.service.method(INTERFACE_TESTS, 'ax', 'ax')
+ def IdentityInt64Array(self, input):
+ tested_things.add(INTERFACE_TESTS + '.IdentityInt64Array')
+ return input
+
+ @dbus.service.method(INTERFACE_TESTS, 'at', 'at')
+ def IdentityUInt64Array(self, input):
+ tested_things.add(INTERFACE_TESTS + '.IdentityUInt64Array')
+ return input
+
+ @dbus.service.method(INTERFACE_TESTS, 'ad', 'ad')
+ def IdentityDoubleArray(self, input):
+ tested_things.add(INTERFACE_TESTS + '.IdentityDoubleArray')
+ return input
+
+ @dbus.service.method(INTERFACE_TESTS, 'as', 'as')
+ def IdentityStringArray(self, input):
+ tested_things.add(INTERFACE_TESTS + '.IdentityStringArray')
+ return input
+
+ @dbus.service.method(INTERFACE_TESTS, 'ai', 'x')
+ def Sum(self, input):
+ tested_things.add(INTERFACE_TESTS + '.Sum')
+ x = sum(input)
+ logger.info('Sum of %r is %r', input, x)
+ return x
+
+
+ @dbus.service.method(INTERFACE_TESTS, 'a{ss}', 'a{sas}', utf8_strings=True)
+ def InvertMapping(self, input):
+ tested_things.add(INTERFACE_TESTS + '.InvertMapping')
+ output = dbus.Dictionary({})
+ for k, v in input.iteritems():
+ output.setdefault(v, []).append(k)
+ return output
+
+ @dbus.service.method(INTERFACE_TESTS, '(sun)', 'sun')
+ def DeStruct(self, input):
+ tested_things.add(INTERFACE_TESTS + '.DeStruct')
+ return input
+
+ @dbus.service.method(INTERFACE_TESTS, 'v', 'av')
+ def Primitize(self, input):
+ tested_things.add(INTERFACE_TESTS + '.Primitize')
+ return list(self.primitivize_helper(input))
+
+ def primitivize_helper(self, input):
+ if (isinstance(input, tuple) or isinstance(input, dbus.Struct)
+ or isinstance(input, list) or isinstance(input, dbus.Array)):
+ for x in input:
+ for y in self.primitivize_helper(x):
+ yield y
+ elif isinstance(input, dbus.ByteArray):
+ for x in input:
+ yield dbus.Byte(ord(x))
+ elif isinstance(input, dict) or isinstance(input, dbus.Dictionary):
+ for x in input:
+ for y in self.primitivize_helper(x):
+ yield y
+ for y in self.primitivize_helper(input[x]):
+ yield y
+ elif input.variant_level > 0:
+ yield input.__class__(input)
+ else:
+ yield input
+
+ @dbus.service.method(INTERFACE_TESTS, 'b', 'b')
+ def Invert(self, input):
+ tested_things.add(INTERFACE_TESTS + '.Invert')
+ return not input
+
+ @dbus.service.method(INTERFACE_TESTS, 'st', '', utf8_strings=True,
+ connection_keyword='conn')
+ def Trigger(self, object, parameter, conn=None):
+ assert isinstance(object, str)
+ logger.info('method/signal: client wants me to emit Triggered(%r) from %r', parameter, object)
+ tested_things.add(INTERFACE_TESTS + '.Trigger')
+ gobject.idle_add(lambda: self.emit_Triggered_from(conn, object,
+ parameter))
+
+ def emit_Triggered_from(self, conn, object, parameter):
+ assert isinstance(object, str)
+ logger.info('method/signal: Emitting Triggered(%r) from %r', parameter, object)
+ obj = objects.get(object, None)
+ if obj is None:
+ obj = SignalTestsImpl(conn, object)
+ objects[object] = obj
+ obj.Triggered(parameter)
+ logger.info('method/signal: Emitted Triggered')
+
+ @dbus.service.method(INTERFACE_TESTS, '', '')
+ def Exit(self):
+ logger.info('client wants me to Exit')
+ tested_things.add(INTERFACE_TESTS + '.Exit')
+ for x in testable_things:
+ if x not in tested_things:
+ print '%s untested' % x
+ logger.info('will quit when idle')
+ gobject.idle_add(self._exit_fn)
+
+
+class Server(SingleTestsImpl, TestsImpl, SignalTestsImpl):
+
+ def triggered_by_client(self, parameter1, parameter2, sender, sender_path):
+ # Called when the client emits TestSignals.Trigger from any object.
+ logger.info('signal/callback: Triggered by client (%s:%s): (%r,%r)', sender, sender_path, parameter1, parameter2)
+ tested_things.add(INTERFACE_SIGNAL_TESTS + '.Trigger')
+ dbus.Interface(dbus.SessionBus().get_object(sender, sender_path),
+ INTERFACE_CALLBACK_TESTS).Response(parameter1, parameter2)
+ logger.info('signal/callback: Sent Response')
+
+
+
+if __name__ == '__main__':
+ bus = SessionBus()
+ bus_name = BusName(CROSS_TEST_BUS_NAME, bus=bus)
+ loop = gobject.MainLoop()
+ obj = Server(bus_name, CROSS_TEST_PATH, loop.quit)
+ objects[CROSS_TEST_PATH] = obj
+ bus.add_signal_receiver(obj.triggered_by_client,
+ signal_name='Trigger',
+ dbus_interface=INTERFACE_SIGNAL_TESTS,
+ named_service=None,
+ path=None,
+ sender_keyword='sender',
+ path_keyword='sender_path',
+ utf8_strings=True)
+
+ logger.info("running...")
+ loop.run()
+ logger.info("main loop exited.")
diff --git a/test/crosstest.py b/test/crosstest.py
new file mode 100644
index 0000000..0020baf
--- /dev/null
+++ b/test/crosstest.py
@@ -0,0 +1,44 @@
+# Shared code for the cross-test.
+
+# Copyright (C) 2006 Collabora Ltd. <http://www.collabora.co.uk/>
+#
+# Permission is hereby granted, free of charge, to any person
+# obtaining a copy of this software and associated documentation
+# files (the "Software"), to deal in the Software without
+# restriction, including without limitation the rights to use, copy,
+# modify, merge, publish, distribute, sublicense, and/or sell copies
+# of the Software, and to permit persons to whom the Software is
+# furnished to do so, subject to the following conditions:
+#
+# The above copyright notice and this permission notice shall be
+# included in all copies or substantial portions of the Software.
+#
+# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+# HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+# WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+# DEALINGS IN THE SOFTWARE.
+
+import dbus.service
+
+INTERFACE_SINGLE_TESTS = 'org.freedesktop.DBus.Binding.SingleTests'
+INTERFACE_TESTS = 'org.freedesktop.DBus.Binding.Tests'
+INTERFACE_SIGNAL_TESTS = 'org.freedesktop.DBus.Binding.TestSignals'
+INTERFACE_CALLBACK_TESTS = 'org.freedesktop.DBus.Binding.TestCallbacks'
+
+CROSS_TEST_PATH = '/Test'
+CROSS_TEST_BUS_NAME = 'org.freedesktop.DBus.Binding.TestServer'
+
+
+# Exported by both the client and the server
+class SignalTestsImpl(dbus.service.Object):
+ @dbus.service.signal(INTERFACE_SIGNAL_TESTS, 't')
+ def Triggered(self, parameter):
+ pass
+
+ @dbus.service.signal(INTERFACE_SIGNAL_TESTS, 'qd')
+ def Trigger(self, parameter1, parameter2):
+ pass
diff --git a/test/dbus_py_test.c b/test/dbus_py_test.c
new file mode 100644
index 0000000..5604e32
--- /dev/null
+++ b/test/dbus_py_test.c
@@ -0,0 +1,126 @@
+/* Test fixtures for dbus-python, based on _dbus_glib_bindings.
+ *
+ * Copyright (C) 2007 Collabora Ltd. <http://www.collabora.co.uk/>
+ *
+ * Permission is hereby granted, free of charge, to any person
+ * obtaining a copy of this software and associated documentation
+ * files (the "Software"), to deal in the Software without
+ * restriction, including without limitation the rights to use, copy,
+ * modify, merge, publish, distribute, sublicense, and/or sell copies
+ * of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+ * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+ * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
+ */
+
+#include <Python.h>
+#include "dbus-python.h"
+
+PyMODINIT_FUNC initdbus_py_test(void);
+
+#if defined(__GNUC__)
+# if __GNUC__ >= 3
+# define UNUSED __attribute__((__unused__))
+# else
+# define UNUSED /*nothing*/
+# endif
+#else
+# define UNUSED /*nothing*/
+#endif
+
+static dbus_bool_t
+dbus_py_test_set_up_conn(DBusConnection *conn UNUSED, void *data UNUSED)
+{
+ PyErr_SetString(PyExc_ValueError, "Dummy error from UnusableMainLoop");
+ return 0;
+}
+
+static dbus_bool_t
+dbus_py_test_set_up_srv(DBusServer *srv UNUSED, void *data UNUSED)
+{
+ PyErr_SetString(PyExc_ValueError, "Dummy error from UnusableMainLoop");
+ return 0;
+}
+
+static void
+dbus_py_test_free(void *data UNUSED)
+{
+}
+
+static PyObject *
+dbus_test_native_mainloop(void)
+{
+ PyObject *loop = DBusPyNativeMainLoop_New4(dbus_py_test_set_up_conn,
+ dbus_py_test_set_up_srv,
+ dbus_py_test_free,
+ NULL);
+ return loop;
+}
+
+static PyObject *
+UnusableMainLoop (PyObject *always_null UNUSED, PyObject *args, PyObject *kwargs)
+{
+ PyObject *mainloop, *function, *result;
+ int set_as_default = 0;
+ static char *argnames[] = {"set_as_default", NULL};
+
+ if (PyTuple_Size(args) != 0) {
+ PyErr_SetString(PyExc_TypeError, "UnusableMainLoop() takes no "
+ "positional arguments");
+ return NULL;
+ }
+ if (!PyArg_ParseTupleAndKeywords(args, kwargs, "|i", argnames,
+ &set_as_default)) {
+ return NULL;
+ }
+
+ mainloop = dbus_test_native_mainloop();
+ if (mainloop && set_as_default) {
+ if (!_dbus_bindings_module) {
+ PyErr_SetString(PyExc_ImportError, "_dbus_bindings not imported");
+ Py_DECREF(mainloop);
+ return NULL;
+ }
+ function = PyObject_GetAttrString(_dbus_bindings_module,
+ "set_default_main_loop");
+ if (!function) {
+ Py_DECREF(mainloop);
+ return NULL;
+ }
+ result = PyObject_CallFunctionObjArgs(function, mainloop, NULL);
+ Py_DECREF(function);
+ if (!result) {
+ Py_DECREF(mainloop);
+ return NULL;
+ }
+ }
+ return mainloop;
+}
+
+static PyMethodDef module_functions[] = {
+ {"UnusableMainLoop", (PyCFunction)UnusableMainLoop,
+ METH_VARARGS|METH_KEYWORDS, "Return a main loop that fails to attach"},
+ {NULL, NULL, 0, NULL}
+};
+
+PyMODINIT_FUNC
+initdbus_py_test(void)
+{
+ PyObject *this_module;
+
+ if (import_dbus_bindings("dbus_py_test") < 0) return;
+ this_module = Py_InitModule3 ("dbus_py_test", module_functions, "");
+ if (!this_module) return;
+}
+
+/* vim:set ft=c cino< sw=4 sts=4 et: */
diff --git a/test/run-test.sh b/test/run-test.sh
new file mode 100755
index 0000000..45e2ed4
--- /dev/null
+++ b/test/run-test.sh
@@ -0,0 +1,124 @@
+#! /bin/bash
+
+# Copyright (C) 2006 Red Hat Inc. <http://www.redhat.com/>
+# Copyright (C) 2006-2007 Collabora Ltd. <http://www.collabora.co.uk/>
+#
+# Permission is hereby granted, free of charge, to any person
+# obtaining a copy of this software and associated documentation
+# files (the "Software"), to deal in the Software without
+# restriction, including without limitation the rights to use, copy,
+# modify, merge, publish, distribute, sublicense, and/or sell copies
+# of the Software, and to permit persons to whom the Software is
+# furnished to do so, subject to the following conditions:
+#
+# The above copyright notice and this permission notice shall be
+# included in all copies or substantial portions of the Software.
+#
+# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+# HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+# WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+# DEALINGS IN THE SOFTWARE.
+
+export DBUS_FATAL_WARNINGS=1
+ulimit -c unlimited
+
+function die()
+{
+ if ! test -z "$DBUS_SESSION_BUS_PID" ; then
+ echo "killing message bus $DBUS_SESSION_BUS_PID" >&2
+ kill -9 "$DBUS_SESSION_BUS_PID"
+ fi
+ echo "$SCRIPTNAME: $*" >&2
+ exit 1
+}
+
+if test -z "$PYTHON"; then
+ echo "Warning: \$PYTHON not set, assuming 'python'" >&2
+ export PYTHON=python
+fi
+
+if test -z "$DBUS_TOP_SRCDIR" ; then
+ die "Must set DBUS_TOP_SRCDIR"
+fi
+
+if test -z "$DBUS_TOP_BUILDDIR" ; then
+ die "Must set DBUS_TOP_BUILDDIR"
+fi
+
+SCRIPTNAME=$0
+
+## so the tests can complain if you fail to use the script to launch them
+export DBUS_TEST_PYTHON_RUN_TEST_SCRIPT=1
+# Rerun ourselves with tmp session bus if we're not already
+if test -z "$DBUS_TEST_PYTHON_IN_RUN_TEST"; then
+ DBUS_TEST_PYTHON_IN_RUN_TEST=1
+ export DBUS_TEST_PYTHON_IN_RUN_TEST
+ exec "$DBUS_TOP_SRCDIR"/test/run-with-tmp-session-bus.sh $SCRIPTNAME
+fi
+
+dbus-monitor > "$DBUS_TOP_BUILDDIR"/test/monitor.log &
+
+echo "running test-standalone.py"
+$PYTHON "$DBUS_TOP_SRCDIR"/test/test-standalone.py || die "test-standalone.py failed"
+
+echo "running test-unusable-main-loop.py"
+$PYTHON "$DBUS_TOP_SRCDIR"/test/test-unusable-main-loop.py || die "... failed"
+
+#echo "running the examples"
+
+#$PYTHON "$DBUS_TOP_SRCDIR"/examples/example-service.py &
+#$PYTHON "$DBUS_TOP_SRCDIR"/examples/example-signal-emitter.py &
+#$PYTHON "$DBUS_TOP_SRCDIR"/examples/list-system-services.py --session ||
+# die "list-system-services.py --session failed!"
+#$PYTHON "$DBUS_TOP_SRCDIR"/examples/example-async-client.py ||
+# die "example-async-client failed!"
+#$PYTHON "$DBUS_TOP_SRCDIR"/examples/example-client.py --exit-service ||
+# die "example-client failed!"
+#$PYTHON "$DBUS_TOP_SRCDIR"/examples/example-signal-recipient.py --exit-service ||
+# die "example-signal-recipient failed!"
+
+echo "running cross-test (for better diagnostics use mjj29's dbus-test)"
+
+${MAKE:-make} -s cross-test-server > "$DBUS_TOP_BUILDDIR"/test/cross-server.log&
+sleep 1
+${MAKE:-make} -s cross-test-client > "$DBUS_TOP_BUILDDIR"/test/cross-client.log
+
+if grep . "$DBUS_TOP_BUILDDIR"/test/cross-client.log >/dev/null; then
+ : # OK
+else
+ die "cross-test client produced no output"
+fi
+if grep . "$DBUS_TOP_BUILDDIR"/test/cross-server.log >/dev/null; then
+ : # OK
+else
+ die "cross-test server produced no output"
+fi
+
+if grep fail "$DBUS_TOP_BUILDDIR"/test/cross-client.log; then
+ die "^^^ Cross-test client reports failures, see test/cross-client.log"
+else
+ echo " - cross-test client reported no failures"
+fi
+if grep untested "$DBUS_TOP_BUILDDIR"/test/cross-server.log; then
+ die "^^^ Cross-test server reports incomplete test coverage"
+else
+ echo " - cross-test server reported no untested functions"
+fi
+
+echo "running test-client.py"
+$PYTHON "$DBUS_TOP_SRCDIR"/test/test-client.py || die "test-client.py failed"
+echo "running test-signals.py"
+$PYTHON "$DBUS_TOP_SRCDIR"/test/test-signals.py || die "test-signals.py failed"
+
+echo "running test-p2p.py"
+$PYTHON "$DBUS_TOP_SRCDIR"/test/test-p2p.py || die "... failed"
+
+rm -f "$DBUS_TOP_BUILDDIR"/test/test-service.log
+rm -f "$DBUS_TOP_BUILDDIR"/test/cross-client.log
+rm -f "$DBUS_TOP_BUILDDIR"/test/cross-server.log
+rm -f "$DBUS_TOP_BUILDDIR"/test/monitor.log
+exit 0
diff --git a/test/run-with-tmp-session-bus.sh b/test/run-with-tmp-session-bus.sh
new file mode 100755
index 0000000..e767f2d
--- /dev/null
+++ b/test/run-with-tmp-session-bus.sh
@@ -0,0 +1,75 @@
+#! /bin/bash
+
+# Copyright (C) 2003-2005 Red Hat Inc. <http://www.redhat.com/>
+# Copyright (C) 2005 Colin Walters
+# Copyright (C) 2007 Collabora Ltd. <http://www.collabora.co.uk/>
+#
+# Permission is hereby granted, free of charge, to any person
+# obtaining a copy of this software and associated documentation
+# files (the "Software"), to deal in the Software without
+# restriction, including without limitation the rights to use, copy,
+# modify, merge, publish, distribute, sublicense, and/or sell copies
+# of the Software, and to permit persons to whom the Software is
+# furnished to do so, subject to the following conditions:
+#
+# The above copyright notice and this permission notice shall be
+# included in all copies or substantial portions of the Software.
+#
+# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+# HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+# WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+# DEALINGS IN THE SOFTWARE.
+
+SCRIPTNAME=$0
+WRAPPED_SCRIPT=$1
+shift
+
+function die()
+{
+ if ! test -z "$DBUS_SESSION_BUS_PID" ; then
+ echo "killing message bus $DBUS_SESSION_BUS_PID" >&2
+ kill -9 "$DBUS_SESSION_BUS_PID"
+ fi
+ echo "$SCRIPTNAME: $*" >&2
+ exit 1
+}
+
+if test -z "$DBUS_TOP_BUILDDIR" ; then
+ die "Must set DBUS_TOP_BUILDDIR"
+fi
+
+## convenient to be able to ctrl+C without leaking the message bus process
+trap 'die "Received SIGINT"' SIGINT
+
+CONFIG_FILE="$DBUS_TOP_BUILDDIR"/test/tmp-session-bus.conf
+
+unset DBUS_SESSION_BUS_ADDRESS
+unset DBUS_SESSION_BUS_PID
+
+echo "Running dbus-launch --sh-syntax --config-file=$CONFIG_FILE" >&2
+eval `dbus-launch --sh-syntax --config-file=$CONFIG_FILE`
+
+if test -z "$DBUS_SESSION_BUS_PID" ; then
+ die "Failed to launch message bus for introspection generation to run"
+fi
+
+echo "Started bus pid $DBUS_SESSION_BUS_PID at $DBUS_SESSION_BUS_ADDRESS" >&2
+
+# Execute wrapped script
+echo "Running: $WRAPPED_SCRIPT $*" >&2
+"$WRAPPED_SCRIPT" "$@" || die "script \"$WRAPPED_SCRIPT\" failed"
+
+kill -TERM "$DBUS_SESSION_BUS_PID" \
+ || die "Message bus vanished! should not have happened" \
+ && echo "Killed daemon $DBUS_SESSION_BUS_PID" >&2
+
+sleep 2
+
+## be sure it really died
+kill -9 $DBUS_SESSION_BUS_PID > /dev/null 2>&1 || true
+
+exit 0
diff --git a/test/test-client.py b/test/test-client.py
new file mode 100755
index 0000000..753d892
--- /dev/null
+++ b/test/test-client.py
@@ -0,0 +1,587 @@
+#!/usr/bin/env python
+
+# Copyright (C) 2004 Red Hat Inc. <http://www.redhat.com/>
+# Copyright (C) 2005-2007 Collabora Ltd. <http://www.collabora.co.uk/>
+#
+# Permission is hereby granted, free of charge, to any person
+# obtaining a copy of this software and associated documentation
+# files (the "Software"), to deal in the Software without
+# restriction, including without limitation the rights to use, copy,
+# modify, merge, publish, distribute, sublicense, and/or sell copies
+# of the Software, and to permit persons to whom the Software is
+# furnished to do so, subject to the following conditions:
+#
+# The above copyright notice and this permission notice shall be
+# included in all copies or substantial portions of the Software.
+#
+# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+# HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+# WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+# DEALINGS IN THE SOFTWARE.
+
+import sys
+import os
+import unittest
+import time
+import logging
+import weakref
+
+builddir = os.path.normpath(os.environ["DBUS_TOP_BUILDDIR"])
+pydir = os.path.normpath(os.environ["DBUS_TOP_SRCDIR"])
+
+import dbus
+import _dbus_bindings
+import gobject
+import dbus.glib
+import dbus.service
+
+
+logging.basicConfig()
+
+
+pkg = dbus.__file__
+if not pkg.startswith(pydir):
+ raise Exception("DBus modules (%s) are not being picked up from the package"%pkg)
+
+if not _dbus_bindings.__file__.startswith(builddir):
+ raise Exception("DBus modules (%s) are not being picked up from the package"%_dbus_bindings.__file__)
+
+test_types_vals = [1, 12323231, 3.14159265, 99999999.99,
+ "dude", "123", "What is all the fuss about?", "gob@gob.com",
+ u'\\u310c\\u310e\\u3114', u'\\u0413\\u0414\\u0415',
+ u'\\u2200software \\u2203crack', u'\\xf4\\xe5\\xe8',
+ [1,2,3], ["how", "are", "you"], [1.23,2.3], [1], ["Hello"],
+ (1,2,3), (1,), (1,"2",3), ("2", "what"), ("you", 1.2),
+ {1:"a", 2:"b"}, {"a":1, "b":2}, #{"a":(1,"B")},
+ {1:1.1, 2:2.2}, [[1,2,3],[2,3,4]], [["a","b"],["c","d"]],
+ True, False,
+ dbus.Int16(-10), dbus.UInt16(10), 'SENTINEL',
+ #([1,2,3],"c", 1.2, ["a","b","c"], {"a": (1,"v"), "b": (2,"d")})
+ ]
+
+NAME = "org.freedesktop.DBus.TestSuitePythonService"
+IFACE = "org.freedesktop.DBus.TestSuiteInterface"
+OBJECT = "/org/freedesktop/DBus/TestSuitePythonObject"
+
+class TestDBusBindings(unittest.TestCase):
+ def setUp(self):
+ self.bus = dbus.SessionBus()
+ self.remote_object = self.bus.get_object(NAME, OBJECT)
+ self.remote_object_follow = self.bus.get_object(NAME, OBJECT,
+ follow_name_owner_changes=True)
+ self.iface = dbus.Interface(self.remote_object, IFACE)
+
+ def testGObject(self):
+ print "Testing ExportedGObject... ",
+ remote_gobject = self.bus.get_object(NAME, OBJECT + '/GObject')
+ iface = dbus.Interface(remote_gobject, IFACE)
+ print "introspection, ",
+ remote_gobject.Introspect(dbus_interface=dbus.INTROSPECTABLE_IFACE)
+ print "method call, ",
+ self.assertEquals(iface.Echo('123'), '123')
+ print "... OK"
+
+ def testWeakRefs(self):
+ # regression test for Sugar crash caused by smcv getting weak refs
+ # wrong - pre-bugfix, this would segfault
+ bus = dbus.SessionBus(private=True)
+ ref = weakref.ref(bus)
+ self.assert_(ref() is bus)
+ del bus
+ self.assert_(ref() is None)
+
+ def testInterfaceKeyword(self):
+ #test dbus_interface parameter
+ print self.remote_object.Echo("dbus_interface on Proxy test Passed", dbus_interface = IFACE)
+ print self.iface.Echo("dbus_interface on Interface test Passed", dbus_interface = IFACE)
+ self.assert_(True)
+
+ def testGetDBusMethod(self):
+ self.assertEquals(self.iface.get_dbus_method('AcceptListOfByte')('\1\2\3'), [1,2,3])
+ self.assertEquals(self.remote_object.get_dbus_method('AcceptListOfByte', dbus_interface=IFACE)('\1\2\3'), [1,2,3])
+
+ def testCallingConventionOptions(self):
+ self.assertEquals(self.iface.AcceptListOfByte('\1\2\3'), [1,2,3])
+ self.assertEquals(self.iface.AcceptListOfByte('\1\2\3', byte_arrays=True), '\1\2\3')
+ self.assertEquals(self.iface.AcceptByteArray('\1\2\3'), [1,2,3])
+ self.assertEquals(self.iface.AcceptByteArray('\1\2\3', byte_arrays=True), '\1\2\3')
+ self.assert_(isinstance(self.iface.AcceptUTF8String('abc'), unicode))
+ self.assert_(isinstance(self.iface.AcceptUTF8String('abc', utf8_strings=True), str))
+ self.assert_(isinstance(self.iface.AcceptUnicodeString('abc'), unicode))
+ self.assert_(isinstance(self.iface.AcceptUnicodeString('abc', utf8_strings=True), str))
+
+ def testIntrospection(self):
+ #test introspection
+ print "\n********* Introspection Test ************"
+ print self.remote_object.Introspect(dbus_interface="org.freedesktop.DBus.Introspectable")
+ print "Introspection test passed"
+ self.assert_(True)
+
+ def testMultiPathIntrospection(self):
+ # test introspection on an object exported in multiple places
+ # https://bugs.freedesktop.org/show_bug.cgi?id=11794
+ remote_object = self.bus.get_object(NAME, OBJECT + '/Multi1')
+ remote_object.Introspect(dbus_interface="org.freedesktop.DBus.Introspectable")
+ remote_object = self.bus.get_object(NAME, OBJECT + '/Multi2')
+ remote_object.Introspect(dbus_interface="org.freedesktop.DBus.Introspectable")
+ remote_object = self.bus.get_object(NAME, OBJECT + '/Multi2/3')
+ remote_object.Introspect(dbus_interface="org.freedesktop.DBus.Introspectable")
+ self.assert_(True)
+
+ def testPythonTypes(self):
+ #test sending python types and getting them back
+ print "\n********* Testing Python Types ***********"
+
+ for send_val in test_types_vals:
+ print "Testing %s"% str(send_val)
+ recv_val = self.iface.Echo(send_val)
+ self.assertEquals(send_val, recv_val)
+ self.assertEquals(recv_val.variant_level, 1)
+
+ def testMethodExtraInfoKeywords(self):
+ print "Testing MethodExtraInfoKeywords..."
+ sender, path, destination, message_cls = self.iface.MethodExtraInfoKeywords()
+ self.assert_(sender.startswith(':'))
+ self.assertEquals(path, '/org/freedesktop/DBus/TestSuitePythonObject')
+ # we're using the "early binding" form of get_object (without
+ # follow_name_owner_changes), so the destination we actually sent it
+ # to will be the unique name
+ self.assert_(destination.startswith(':'))
+ self.assertEquals(message_cls, 'dbus.lowlevel.MethodCallMessage')
+
+ def testUtf8StringsSync(self):
+ send_val = u'foo'
+ recv_val = self.iface.Echo(send_val, utf8_strings=True)
+ self.assert_(isinstance(recv_val, str))
+ self.assert_(isinstance(recv_val, dbus.UTF8String))
+ recv_val = self.iface.Echo(send_val, utf8_strings=False)
+ self.assert_(isinstance(recv_val, unicode))
+ self.assert_(isinstance(recv_val, dbus.String))
+
+ def testBenchmarkIntrospect(self):
+ print "\n********* Benchmark Introspect ************"
+ a = time.time()
+ print a
+ print self.iface.GetComplexArray()
+ b = time.time()
+ print b
+ print "Delta: %f" % (b - a)
+ self.assert_(True)
+
+ def testAsyncCalls(self):
+ #test sending python types and getting them back async
+ print "\n********* Testing Async Calls ***********"
+
+ failures = []
+ main_loop = gobject.MainLoop()
+
+ class async_check:
+ def __init__(self, test_controler, expected_result, do_exit, utf8):
+ self.expected_result = expected_result
+ self.do_exit = do_exit
+ self.utf8 = utf8
+ self.test_controler = test_controler
+
+ def callback(self, val):
+ try:
+ if self.do_exit:
+ main_loop.quit()
+
+ self.test_controler.assertEquals(val, self.expected_result)
+ self.test_controler.assertEquals(val.variant_level, 1)
+ if self.utf8 and not isinstance(val, dbus.UTF8String):
+ failures.append('%r should have been utf8 but was not' % val)
+ return
+ elif not self.utf8 and isinstance(val, dbus.UTF8String):
+ failures.append('%r should not have been utf8' % val)
+ return
+ except Exception, e:
+ failures.append("%s:\n%s" % (e.__class__, e))
+
+ def error_handler(self, error):
+ print error
+ if self.do_exit:
+ main_loop.quit()
+
+ failures.append('%s: %s' % (error.__class__, error))
+
+ last_type = test_types_vals[-1]
+ for send_val in test_types_vals:
+ print "Testing %s" % str(send_val)
+ utf8 = (send_val == 'gob@gob.com')
+ check = async_check(self, send_val, last_type == send_val,
+ utf8)
+ recv_val = self.iface.Echo(send_val,
+ reply_handler=check.callback,
+ error_handler=check.error_handler,
+ utf8_strings=utf8)
+ main_loop.run()
+ if failures:
+ self.assert_(False, failures)
+
+ def testStrictMarshalling(self):
+ print "\n********* Testing strict return & signal marshalling ***********"
+
+ # these values are the same as in the server, and the
+ # methods should only succeed when they are called with
+ # the right value number, because they have out_signature
+ # decorations, and return an unmatching type when called
+ # with a different number
+ values = ["", ("",""), ("","",""), [], {}, ["",""], ["","",""]]
+ methods = [
+ (self.iface.ReturnOneString, 'SignalOneString', set([0]), set([0])),
+ (self.iface.ReturnTwoStrings, 'SignalTwoStrings', set([1, 5]), set([1])),
+ (self.iface.ReturnStruct, 'SignalStruct', set([1, 5]), set([1])),
+ # all of our test values are sequences so will marshall correctly into an array :P
+ (self.iface.ReturnArray, 'SignalArray', set(range(len(values))), set([3, 5, 6])),
+ (self.iface.ReturnDict, 'SignalDict', set([0, 3, 4]), set([4]))
+ ]
+
+ for (method, signal, success_values, return_values) in methods:
+ print "\nTrying correct behaviour of", method._method_name
+ for value in range(len(values)):
+ try:
+ ret = method(value)
+ except Exception, e:
+ print "%s(%r) raised %s: %s" % (method._method_name, values[value], e.__class__, e)
+
+ # should fail if it tried to marshal the wrong type
+ self.assert_(value not in success_values, "%s should succeed when we ask it to return %r\n%s\n%s" % (method._method_name, values[value], e.__class__, e))
+ else:
+ print "%s(%r) returned %r" % (method._method_name, values[value], ret)
+
+ # should only succeed if it's the right return type
+ self.assert_(value in success_values, "%s should fail when we ask it to return %r" % (method._method_name, values[value]))
+
+ # check the value is right too :D
+ returns = map(lambda n: values[n], return_values)
+ self.assert_(ret in returns, "%s should return one of %r but it returned %r instead" % (method._method_name, returns, ret))
+
+ print "\nTrying correct emission of", signal
+ for value in range(len(values)):
+ try:
+ self.iface.EmitSignal(signal, value)
+ except Exception, e:
+ print "EmitSignal(%s, %r) raised %s" % (signal, values[value], e.__class__)
+
+ # should fail if it tried to marshal the wrong type
+ self.assert_(value not in success_values, "EmitSignal(%s) should succeed when we ask it to return %r\n%s\n%s" % (signal, values[value], e.__class__, e))
+ else:
+ print "EmitSignal(%s, %r) appeared to succeed" % (signal, values[value])
+
+ # should only succeed if it's the right return type
+ self.assert_(value in success_values, "EmitSignal(%s) should fail when we ask it to return %r" % (signal, values[value]))
+
+ # FIXME: wait for the signal here
+
+ print
+
+ def testInheritance(self):
+ print "\n********* Testing inheritance from dbus.method.Interface ***********"
+ ret = self.iface.CheckInheritance()
+ print "CheckInheritance returned %s" % ret
+ self.assert_(ret, "overriding CheckInheritance from TestInterface failed")
+
+ def testAsyncMethods(self):
+ print "\n********* Testing asynchronous method implementation *******"
+ for async in (True, False):
+ for fail in (True, False):
+ try:
+ val = ('a', 1, False, [1,2], {1:2})
+ print "calling AsynchronousMethod with %s %s %s" % (async, fail, val)
+ ret = self.iface.AsynchronousMethod(async, fail, val)
+ except Exception, e:
+ self.assert_(fail, '%s: %s' % (e.__class__, e))
+ print "Expected failure: %s: %s" % (e.__class__, e)
+ else:
+ self.assert_(not fail, 'Expected failure but succeeded?!')
+ self.assertEquals(val, ret)
+ self.assertEquals(1, ret.variant_level)
+
+ def testBusInstanceCaching(self):
+ print "\n********* Testing dbus.Bus instance sharing *********"
+
+ # unfortunately we can't test the system bus here
+ # but the codepaths are the same
+ for (cls, type, func) in ((dbus.SessionBus, dbus.Bus.TYPE_SESSION, dbus.Bus.get_session), (dbus.StarterBus, dbus.Bus.TYPE_STARTER, dbus.Bus.get_starter)):
+ print "\nTesting %s:" % cls.__name__
+
+ share_cls = cls()
+ share_type = dbus.Bus(bus_type=type)
+ share_func = func()
+
+ private_cls = cls(private=True)
+ private_type = dbus.Bus(bus_type=type, private=True)
+ private_func = func(private=True)
+
+ print " - checking shared instances are the same..."
+ self.assert_(share_cls == share_type, '%s should equal %s' % (share_cls, share_type))
+ self.assert_(share_type == share_func, '%s should equal %s' % (share_type, share_func))
+
+ print " - checking private instances are distinct from the shared instance..."
+ self.assert_(share_cls != private_cls, '%s should not equal %s' % (share_cls, private_cls))
+ self.assert_(share_type != private_type, '%s should not equal %s' % (share_type, private_type))
+ self.assert_(share_func != private_func, '%s should not equal %s' % (share_func, private_func))
+
+ print " - checking private instances are distinct from each other..."
+ self.assert_(private_cls != private_type, '%s should not equal %s' % (private_cls, private_type))
+ self.assert_(private_type != private_func, '%s should not equal %s' % (private_type, private_func))
+ self.assert_(private_func != private_cls, '%s should not equal %s' % (private_func, private_cls))
+
+ def testSenderName(self):
+ print '\n******** Testing sender name keyword ********'
+ myself = self.iface.WhoAmI()
+ print "I am", myself
+
+ def testBusGetNameOwner(self):
+ ret = self.bus.get_name_owner(NAME)
+ self.assert_(ret.startswith(':'), ret)
+
+ def testBusListNames(self):
+ ret = self.bus.list_names()
+ self.assert_(NAME in ret, ret)
+
+ def testBusListActivatableNames(self):
+ ret = self.bus.list_activatable_names()
+ self.assert_(NAME in ret, ret)
+
+ def testBusNameHasOwner(self):
+ self.assert_(self.bus.name_has_owner(NAME))
+ self.assert_(not self.bus.name_has_owner('badger.mushroom.snake'))
+
+ def testBusNameCreation(self):
+ print '\n******** Testing BusName creation ********'
+ test = [('org.freedesktop.DBus.Python.TestName', True),
+ ('org.freedesktop.DBus.Python.TestName', True),
+ ('org.freedesktop.DBus.Python.InvalidName&^*%$', False)]
+ # Do some more intelligent handling/testing of queueing vs success?
+ # ('org.freedesktop.DBus.TestSuitePythonService', False)]
+ # For some reason this actually succeeds
+ # ('org.freedesktop.DBus', False)]
+
+ # make a method call to ensure the test service is active
+ self.iface.Echo("foo")
+
+ names = {}
+ for (name, succeed) in test:
+ try:
+ print "requesting %s" % name
+ busname = dbus.service.BusName(name, dbus.SessionBus())
+ except Exception, e:
+ print "%s:\n%s" % (e.__class__, e)
+ self.assert_(not succeed, 'did not expect registering bus name %s to fail' % name)
+ else:
+ print busname
+ self.assert_(succeed, 'expected registering bus name %s to fail'% name)
+ if name in names:
+ self.assert_(names[name] == busname, 'got a new instance for same name %s' % name)
+ print "instance of %s re-used, good!" % name
+ else:
+ names[name] = busname
+
+ del busname
+
+ print
+
+ del names
+
+ bus = dbus.Bus()
+ ret = bus.name_has_owner('org.freedesktop.DBus.Python.TestName')
+ self.assert_(not ret, 'deleting reference failed to release BusName org.freedesktop.DBus.Python.TestName')
+
+ def testMultipleReturnWithoutSignature(self):
+ # https://bugs.freedesktop.org/show_bug.cgi?id=10174
+ ret = self.iface.MultipleReturnWithoutSignature()
+ self.assert_(not isinstance(ret, dbus.Struct), repr(ret))
+ self.assertEquals(ret, ('abc', 123))
+
+ def testListExportedChildObjects(self):
+ self.assert_(self.iface.TestListExportedChildObjects())
+
+ def testRemoveFromConnection(self):
+ # https://bugs.freedesktop.org/show_bug.cgi?id=10457
+ self.assert_(not self.iface.HasRemovableObject())
+ self.assert_(self.iface.AddRemovableObject())
+ self.assert_(self.iface.HasRemovableObject())
+
+ removable = self.bus.get_object(NAME, OBJECT + '/RemovableObject')
+ iface = dbus.Interface(removable, IFACE)
+ self.assert_(iface.IsThere())
+ self.assert_(iface.RemoveSelf())
+
+ self.assert_(not self.iface.HasRemovableObject())
+
+ # and again...
+ self.assert_(self.iface.AddRemovableObject())
+ self.assert_(self.iface.HasRemovableObject())
+ self.assert_(iface.IsThere())
+ self.assert_(iface.RemoveSelf())
+ self.assert_(not self.iface.HasRemovableObject())
+
+ def testFallbackObjectTrivial(self):
+ obj = self.bus.get_object(NAME, OBJECT + '/Fallback')
+ iface = dbus.Interface(obj, IFACE)
+ path, rel, unique_name = iface.TestPathAndConnKeywords()
+ self.assertEquals(path, OBJECT + '/Fallback')
+ self.assertEquals(rel, '/')
+ self.assertEquals(unique_name, obj.bus_name)
+
+ def testFallbackObjectNested(self):
+ obj = self.bus.get_object(NAME, OBJECT + '/Fallback/Nested')
+ iface = dbus.Interface(obj, IFACE)
+ path, rel, unique_name = iface.TestPathAndConnKeywords()
+ self.assertEquals(path, OBJECT + '/Fallback/Nested')
+ self.assertEquals(rel, '/')
+ self.assertEquals(unique_name, obj.bus_name)
+
+ obj = self.bus.get_object(NAME, OBJECT + '/Fallback/Nested/Badger/Mushroom')
+ iface = dbus.Interface(obj, IFACE)
+ path, rel, unique_name = iface.TestPathAndConnKeywords()
+ self.assertEquals(path, OBJECT + '/Fallback/Nested/Badger/Mushroom')
+ self.assertEquals(rel, '/Badger/Mushroom')
+ self.assertEquals(unique_name, obj.bus_name)
+
+ def testFallbackObject(self):
+ obj = self.bus.get_object(NAME, OBJECT + '/Fallback/Badger/Mushroom')
+ iface = dbus.Interface(obj, IFACE)
+ path, rel, unique_name = iface.TestPathAndConnKeywords()
+ self.assertEquals(path, OBJECT + '/Fallback/Badger/Mushroom')
+ self.assertEquals(rel, '/Badger/Mushroom')
+ self.assertEquals(unique_name, obj.bus_name)
+
+ def testTimeoutSync(self):
+ self.assert_(self.iface.BlockFor500ms(timeout=1.0) is None)
+ self.assertRaises(dbus.DBusException,
+ lambda: self.iface.BlockFor500ms(timeout=0.25))
+
+ def testAsyncRaise(self):
+ self.assertRaises(dbus.DBusException, self.iface.AsyncRaise)
+ try:
+ self.iface.AsyncRaise()
+ except dbus.DBusException, e:
+ self.assert_(e.get_dbus_name() ==
+ 'org.freedesktop.bugzilla.bug12403',
+ e.get_dbus_name())
+ else:
+ self.assert_(False)
+
+ def testClosePrivateBus(self):
+ # fd.o #12096
+ dbus.Bus(private=True).close()
+
+ def testTimeoutAsyncClient(self):
+ loop = gobject.MainLoop()
+ passes = []
+ fails = []
+ def correctly_returned():
+ passes.append('1000')
+ if len(passes) + len(fails) >= 2:
+ loop.quit()
+ def correctly_failed(exc):
+ passes.append('250')
+ if len(passes) + len(fails) >= 2:
+ loop.quit()
+ def incorrectly_returned():
+ fails.append('250')
+ if len(passes) + len(fails) >= 2:
+ loop.quit()
+ def incorrectly_failed(exc):
+ fails.append('1000')
+ if len(passes) + len(fails) >= 2:
+ loop.quit()
+ self.iface.BlockFor500ms(timeout=1.0,
+ reply_handler=correctly_returned,
+ error_handler=incorrectly_failed)
+ self.iface.BlockFor500ms(timeout=0.25,
+ reply_handler=incorrectly_returned,
+ error_handler=correctly_failed)
+ loop.run()
+ self.assertEquals(passes, ['250', '1000'])
+ self.assertEquals(fails, [])
+
+ def testTimeoutAsyncService(self):
+ self.assert_(self.iface.AsyncWait500ms(timeout=1.0) is None)
+ self.assertRaises(dbus.DBusException,
+ lambda: self.iface.AsyncWait500ms(timeout=0.25))
+
+ def testExceptions(self):
+ #self.assertRaises(dbus.DBusException,
+ # lambda: self.iface.RaiseValueError)
+ #self.assertRaises(dbus.DBusException,
+ # lambda: self.iface.RaiseDBusExceptionNoTraceback)
+ #self.assertRaises(dbus.DBusException,
+ # lambda: self.iface.RaiseDBusExceptionWithTraceback)
+
+ try:
+ self.iface.RaiseValueError()
+ except Exception, e:
+ self.assert_(isinstance(e, dbus.DBusException), e.__class__)
+ self.assert_('.ValueError: Traceback ' in str(e),
+ 'Wanted a traceback but got:\n"""%s"""' % str(e))
+ else:
+ raise AssertionError('Wanted an exception')
+
+ try:
+ self.iface.RaiseDBusExceptionNoTraceback()
+ except Exception, e:
+ self.assert_(isinstance(e, dbus.DBusException), e.__class__)
+ self.assertEquals(str(e),
+ 'com.example.Networking.ServerError: '
+ 'Server not responding')
+ else:
+ raise AssertionError('Wanted an exception')
+
+ try:
+ self.iface.RaiseDBusExceptionWithTraceback()
+ except Exception, e:
+ self.assert_(isinstance(e, dbus.DBusException), e.__class__)
+ self.assert_(str(e).startswith('com.example.Misc.RealityFailure: '
+ 'Traceback '),
+ 'Wanted a traceback but got:\n%s' % str(e))
+ else:
+ raise AssertionError('Wanted an exception')
+
+""" Remove this for now
+class TestDBusPythonToGLibBindings(unittest.TestCase):
+ def setUp(self):
+ self.bus = dbus.SessionBus()
+ self.remote_object = self.bus.get_object("org.freedesktop.DBus.TestSuiteGLibService", "/org/freedesktop/DBus/Tests/MyTestObject")
+ self.iface = dbus.Interface(self.remote_object, "org.freedesktop.DBus.Tests.MyObject")
+
+ def testIntrospection(self):
+ #test introspection
+ print "\n********* Introspection Test ************"
+ print self.remote_object.Introspect(dbus_interface="org.freedesktop.DBus.Introspectable")
+ print "Introspection test passed"
+ self.assert_(True)
+
+ def testCalls(self):
+ print "\n********* Call Test ************"
+ result = self.iface.ManyArgs(1000, 'Hello GLib', 2)
+ print result
+ self.assert_(result == [2002.0, 'HELLO GLIB'])
+
+ arg0 = {"Dude": 1, "john": "palmieri", "python": 2.4}
+ result = self.iface.ManyStringify(arg0)
+ print result
+
+ print "Call test passed"
+ self.assert_(True)
+
+ def testPythonTypes(self):
+ print "\n********* Testing Python Types ***********"
+
+ for send_val in test_types_vals:
+ print "Testing %s"% str(send_val)
+ recv_val = self.iface.EchoVariant(send_val)
+ self.assertEquals(send_val, recv_val.object)
+"""
+if __name__ == '__main__':
+ gobject.threads_init()
+ dbus.glib.init_threads()
+
+ unittest.main()
diff --git a/test/test-p2p.py b/test/test-p2p.py
new file mode 100644
index 0000000..8494f23
--- /dev/null
+++ b/test/test-p2p.py
@@ -0,0 +1,95 @@
+#!/usr/bin/env python
+
+# Copyright (C) 2004 Red Hat Inc. <http://www.redhat.com/>
+# Copyright (C) 2005-2007 Collabora Ltd. <http://www.collabora.co.uk/>
+#
+# Permission is hereby granted, free of charge, to any person
+# obtaining a copy of this software and associated documentation
+# files (the "Software"), to deal in the Software without
+# restriction, including without limitation the rights to use, copy,
+# modify, merge, publish, distribute, sublicense, and/or sell copies
+# of the Software, and to permit persons to whom the Software is
+# furnished to do so, subject to the following conditions:
+#
+# The above copyright notice and this permission notice shall be
+# included in all copies or substantial portions of the Software.
+#
+# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+# HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+# WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+# DEALINGS IN THE SOFTWARE.
+
+
+import sys
+import os
+import unittest
+import time
+import logging
+import weakref
+
+builddir = os.path.normpath(os.environ["DBUS_TOP_BUILDDIR"])
+pydir = os.path.normpath(os.environ["DBUS_TOP_SRCDIR"])
+
+import dbus
+import _dbus_bindings
+import gobject
+import dbus.glib
+import dbus.service
+
+
+logging.basicConfig()
+logging.getLogger().setLevel(1)
+
+
+NAME = "org.freedesktop.DBus.TestSuitePythonService"
+IFACE = "org.freedesktop.DBus.TestSuiteInterface"
+OBJECT = "/org/freedesktop/DBus/TestSuitePythonObject"
+
+class TestDBusBindings(unittest.TestCase):
+ # This test case relies on the test service already having been activated.
+
+ def get_conn_and_unique(self):
+ # since I haven't implemented servers yet, I'll use the bus daemon
+ # as our peer - note that there's no name tracking because we're not
+ # using dbus.bus.BusConnection!
+ conn = dbus.connection.Connection(
+ os.environ['DBUS_SESSION_BUS_ADDRESS'])
+ unique = conn.call_blocking('org.freedesktop.DBus',
+ '/org/freedesktop/DBus',
+ 'org.freedesktop.DBus', 'Hello',
+ '', (), utf8_strings=True)
+ self.assert_(unique.__class__ == dbus.UTF8String, repr(unique))
+ self.assert_(unique.startswith(':'), unique)
+ conn.set_unique_name(unique)
+ return conn, unique
+
+ def testCall(self):
+ conn, unique = self.get_conn_and_unique()
+ ret = conn.call_blocking(NAME, OBJECT, IFACE, 'Echo', 'v', ('V',))
+ self.assertEquals(ret, 'V')
+
+ def testCallThroughProxy(self):
+ conn, unique = self.get_conn_and_unique()
+ proxy = conn.get_object(NAME, OBJECT)
+ iface = dbus.Interface(proxy, IFACE)
+ ret = iface.Echo('V')
+ self.assertEquals(ret, 'V')
+
+ def testSetUniqueName(self):
+ conn, unique = self.get_conn_and_unique()
+ ret = conn.call_blocking(NAME, OBJECT, IFACE,
+ 'MethodExtraInfoKeywords', '', (),
+ utf8_strings=True)
+ self.assertEquals(ret, (unique, OBJECT, NAME,
+ 'dbus.lowlevel.MethodCallMessage'))
+
+
+if __name__ == '__main__':
+ gobject.threads_init()
+ dbus.glib.init_threads()
+
+ unittest.main()
diff --git a/test/test-service.py b/test/test-service.py
new file mode 100755
index 0000000..51865eb
--- /dev/null
+++ b/test/test-service.py
@@ -0,0 +1,344 @@
+#!/usr/bin/env python
+
+# Copyright (C) 2004 Red Hat Inc. <http://www.redhat.com/>
+# Copyright (C) 2005-2007 Collabora Ltd. <http://www.collabora.co.uk/>
+#
+# Permission is hereby granted, free of charge, to any person
+# obtaining a copy of this software and associated documentation
+# files (the "Software"), to deal in the Software without
+# restriction, including without limitation the rights to use, copy,
+# modify, merge, publish, distribute, sublicense, and/or sell copies
+# of the Software, and to permit persons to whom the Software is
+# furnished to do so, subject to the following conditions:
+#
+# The above copyright notice and this permission notice shall be
+# included in all copies or substantial portions of the Software.
+#
+# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+# HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+# WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+# DEALINGS IN THE SOFTWARE.
+
+import sys
+import os
+import logging
+from time import sleep
+
+builddir = os.path.normpath(os.environ["DBUS_TOP_BUILDDIR"])
+pydir = os.path.normpath(os.environ["DBUS_TOP_SRCDIR"])
+
+import dbus
+
+if not dbus.__file__.startswith(pydir):
+ raise Exception("DBus modules are not being picked up from the package")
+
+import dbus.service
+import dbus.glib
+import gobject
+import random
+
+from dbus.gobject_service import ExportedGObject
+
+
+logging.basicConfig(filename=builddir + '/test/test-service.log', filemode='w')
+logging.getLogger().setLevel(1)
+logger = logging.getLogger('test-service')
+
+
+NAME = "org.freedesktop.DBus.TestSuitePythonService"
+IFACE = "org.freedesktop.DBus.TestSuiteInterface"
+OBJECT = "/org/freedesktop/DBus/TestSuitePythonObject"
+
+class RemovableObject(dbus.service.Object):
+ # Part of test for https://bugs.freedesktop.org/show_bug.cgi?id=10457
+ @dbus.service.method(IFACE, in_signature='', out_signature='b')
+ def IsThere(self):
+ return True
+
+ @dbus.service.method(IFACE, in_signature='', out_signature='b')
+ def RemoveSelf(self):
+ self.remove_from_connection()
+ return True
+
+class TestGObject(ExportedGObject):
+ def __init__(self, bus_name, object_path=OBJECT + '/GObject'):
+ super(TestGObject, self).__init__(bus_name, object_path)
+
+ @dbus.service.method(IFACE)
+ def Echo(self, arg):
+ return arg
+
+class TestInterface(dbus.service.Interface):
+ @dbus.service.method(IFACE, in_signature='', out_signature='b')
+ def CheckInheritance(self):
+ return False
+
+class Fallback(dbus.service.FallbackObject):
+ def __init__(self, conn, object_path=OBJECT + '/Fallback'):
+ super(Fallback, self).__init__(conn, object_path)
+ self.add_to_connection(conn, object_path + '/Nested')
+
+ @dbus.service.method(IFACE, in_signature='', out_signature='oos',
+ path_keyword='path', rel_path_keyword='rel',
+ connection_keyword='conn')
+ def TestPathAndConnKeywords(self, path=None, conn=None, rel=None):
+ return path, rel, conn.get_unique_name()
+
+ @dbus.service.signal(IFACE, signature='s', rel_path_keyword='rel_path')
+ def SignalOneString(self, test, rel_path=None):
+ logger.info('SignalOneString(%r) @ %r', test, rel_path)
+
+ # Deprecated usage
+ @dbus.service.signal(IFACE, signature='ss', path_keyword='path')
+ def SignalTwoStrings(self, test, test2, path=None):
+ logger.info('SignalTwoStrings(%r, %r) @ %r', test, test2, path)
+
+ @dbus.service.method(IFACE, in_signature='su', out_signature='',
+ path_keyword='path')
+ def EmitSignal(self, signal, value, path=None):
+ sig = getattr(self, str(signal), None)
+ assert sig is not None
+
+ assert path.startswith(OBJECT + '/Fallback')
+ rel_path = path[len(OBJECT + '/Fallback'):]
+ if rel_path == '':
+ rel_path = '/'
+
+ if signal == 'SignalOneString':
+ logger.info('Emitting %s from rel %r', signal, rel_path)
+ sig('I am a fallback', rel_path=rel_path)
+ else:
+ val = ('I am', 'a fallback')
+ logger.info('Emitting %s from abs %r', signal, path)
+ sig('I am', 'a deprecated fallback', path=path)
+
+class MultiPathObject(dbus.service.Object):
+ SUPPORTS_MULTIPLE_OBJECT_PATHS = True
+
+class TestObject(dbus.service.Object, TestInterface):
+ def __init__(self, bus_name, object_path=OBJECT):
+ dbus.service.Object.__init__(self, bus_name, object_path)
+ self._removable = RemovableObject()
+ self._multi = MultiPathObject(bus_name, object_path + '/Multi1')
+ self._multi.add_to_connection(bus_name.get_bus(),
+ object_path + '/Multi2')
+ self._multi.add_to_connection(bus_name.get_bus(),
+ object_path + '/Multi2/3')
+
+ """ Echo whatever is sent
+ """
+ @dbus.service.method(IFACE)
+ def Echo(self, arg):
+ return arg
+
+ @dbus.service.method(IFACE, in_signature='s', out_signature='s')
+ def AcceptUnicodeString(self, foo):
+ assert isinstance(foo, unicode), (foo, foo.__class__.__mro__)
+ return foo
+
+ @dbus.service.method(IFACE, in_signature='s', out_signature='s', utf8_strings=True)
+ def AcceptUTF8String(self, foo):
+ assert isinstance(foo, str), (foo, foo.__class__.__mro__)
+ return foo
+
+ @dbus.service.method(IFACE, in_signature='', out_signature='soss',
+ sender_keyword='sender', path_keyword='path',
+ destination_keyword='dest', message_keyword='msg')
+ def MethodExtraInfoKeywords(self, sender=None, path=None, dest=None,
+ msg=None):
+ return (sender, path, dest,
+ msg.__class__.__module__ + '.' + msg.__class__.__name__)
+
+ @dbus.service.method(IFACE, in_signature='ay', out_signature='ay')
+ def AcceptListOfByte(self, foo):
+ assert isinstance(foo, list), (foo, foo.__class__.__mro__)
+ return foo
+
+ @dbus.service.method(IFACE, in_signature='ay', out_signature='ay', byte_arrays=True)
+ def AcceptByteArray(self, foo):
+ assert isinstance(foo, str), (foo, foo.__class__.__mro__)
+ return foo
+
+ @dbus.service.method(IFACE)
+ def GetComplexArray(self):
+ ret = []
+ for i in range(0,100):
+ ret.append((random.randint(0,100), random.randint(0,100), str(random.randint(0,100))))
+
+ return dbus.Array(ret, signature="(uus)")
+
+ def returnValue(self, test):
+ if test == 0:
+ return ""
+ elif test == 1:
+ return "",""
+ elif test == 2:
+ return "","",""
+ elif test == 3:
+ return []
+ elif test == 4:
+ return {}
+ elif test == 5:
+ return ["",""]
+ elif test == 6:
+ return ["","",""]
+
+ @dbus.service.method(IFACE, in_signature='u', out_signature='s')
+ def ReturnOneString(self, test):
+ return self.returnValue(test)
+
+ @dbus.service.method(IFACE, in_signature='u', out_signature='ss')
+ def ReturnTwoStrings(self, test):
+ return self.returnValue(test)
+
+ @dbus.service.method(IFACE, in_signature='u', out_signature='(ss)')
+ def ReturnStruct(self, test):
+ logger.info('ReturnStruct(%r) -> %r', test, self.returnValue(test))
+ return self.returnValue(test)
+
+ @dbus.service.method(IFACE, in_signature='u', out_signature='as')
+ def ReturnArray(self, test):
+ return self.returnValue(test)
+
+ @dbus.service.method(IFACE, in_signature='u', out_signature='a{ss}')
+ def ReturnDict(self, test):
+ return self.returnValue(test)
+
+ @dbus.service.signal(IFACE, signature='s')
+ def SignalOneString(self, test):
+ logger.info('SignalOneString(%r)', test)
+
+ @dbus.service.signal(IFACE, signature='ss')
+ def SignalTwoStrings(self, test, test2):
+ logger.info('SignalTwoStrings(%r, %r)', test, test2)
+
+ @dbus.service.signal(IFACE, signature='(ss)')
+ def SignalStruct(self, test):
+ logger.info('SignalStruct(%r)', test)
+
+ @dbus.service.signal(IFACE, signature='as')
+ def SignalArray(self, test):
+ pass
+
+ @dbus.service.signal(IFACE, signature='a{ss}')
+ def SignalDict(self, test):
+ pass
+
+ @dbus.service.method(IFACE, in_signature='su', out_signature='')
+ def EmitSignal(self, signal, value):
+ sig = getattr(self, str(signal), None)
+ assert(sig != None)
+
+ val = self.returnValue(value)
+ # make two string case work by passing arguments in by tuple
+ if (signal == 'SignalTwoStrings' and (value == 1 or value == 5)):
+ val = tuple(val)
+ else:
+ val = tuple([val])
+
+ logger.info('Emitting %s with %r', signal, val)
+ sig(*val)
+
+ def CheckInheritance(self):
+ return True
+
+ @dbus.service.method(IFACE, in_signature='', out_signature='b')
+ def TestListExportedChildObjects(self):
+ objs_root = session_bus.list_exported_child_objects('/')
+ assert objs_root == ['org'], objs_root
+ objs_org = session_bus.list_exported_child_objects('/org')
+ assert objs_org == ['freedesktop'], objs_org
+ return True
+
+ @dbus.service.method(IFACE, in_signature='bbv', out_signature='v', async_callbacks=('return_cb', 'error_cb'))
+ def AsynchronousMethod(self, async, fail, variant, return_cb, error_cb):
+ try:
+ if async:
+ gobject.timeout_add(500, self.AsynchronousMethod, False, fail, variant, return_cb, error_cb)
+ return
+ else:
+ if fail:
+ raise RuntimeError
+ else:
+ return_cb(variant)
+
+ return False # do not run again
+ except Exception, e:
+ error_cb(e)
+
+ @dbus.service.method(IFACE, in_signature='', out_signature='s', sender_keyword='sender')
+ def WhoAmI(self, sender):
+ return sender
+
+ @dbus.service.method(IFACE, in_signature='', out_signature='b')
+ def AddRemovableObject(self):
+ # Part of test for https://bugs.freedesktop.org/show_bug.cgi?id=10457
+ # Keep the removable object reffed, since that's the use case for this
+ self._removable.add_to_connection(self._connection,
+ OBJECT + '/RemovableObject')
+ return True
+
+ @dbus.service.method(IFACE, in_signature='', out_signature='b')
+ def HasRemovableObject(self):
+ # Part of test for https://bugs.freedesktop.org/show_bug.cgi?id=10457
+ objs = session_bus.list_exported_child_objects(OBJECT)
+ return ('RemovableObject' in objs)
+
+ @dbus.service.method(IFACE)
+ def MultipleReturnWithoutSignature(self):
+ # https://bugs.freedesktop.org/show_bug.cgi?id=10174
+ return dbus.String('abc'), dbus.Int32(123)
+
+ @dbus.service.method(IFACE, in_signature='', out_signature='')
+ def BlockFor500ms(self):
+ sleep(0.5)
+
+ @dbus.service.method(IFACE, in_signature='', out_signature='',
+ async_callbacks=('return_cb', 'raise_cb'))
+ def AsyncWait500ms(self, return_cb, raise_cb):
+ def return_from_async_wait():
+ return_cb()
+ return False
+ gobject.timeout_add(500, return_from_async_wait)
+
+ @dbus.service.method(IFACE, in_signature='', out_signature='')
+ def RaiseValueError(self):
+ raise ValueError('Wrong!')
+
+ @dbus.service.method(IFACE, in_signature='', out_signature='')
+ def RaiseDBusExceptionNoTraceback(self):
+ class ServerError(dbus.DBusException):
+ """Exception representing a normal "environmental" error"""
+ include_traceback = False
+ _dbus_error_name = 'com.example.Networking.ServerError'
+
+ raise ServerError('Server not responding')
+
+ @dbus.service.method(IFACE, in_signature='', out_signature='')
+ def RaiseDBusExceptionWithTraceback(self):
+ class RealityFailure(dbus.DBusException):
+ """Exception representing a programming error"""
+ include_traceback = True
+ _dbus_error_name = 'com.example.Misc.RealityFailure'
+
+ raise RealityFailure('Botched invariant')
+
+ @dbus.service.method(IFACE, in_signature='', out_signature='',
+ async_callbacks=('return_cb', 'raise_cb'))
+ def AsyncRaise(self, return_cb, raise_cb):
+ class Fdo12403Error(dbus.DBusException):
+ _dbus_error_name = 'org.freedesktop.bugzilla.bug12403'
+
+ raise_cb(Fdo12403Error())
+
+session_bus = dbus.SessionBus()
+global_name = dbus.service.BusName(NAME, bus=session_bus)
+object = TestObject(global_name)
+g_object = TestGObject(global_name)
+fallback_object = Fallback(session_bus)
+loop = gobject.MainLoop()
+loop.run()
diff --git a/test/test-signals.py b/test/test-signals.py
new file mode 100644
index 0000000..04b1e53
--- /dev/null
+++ b/test/test-signals.py
@@ -0,0 +1,160 @@
+#!/usr/bin/env python
+
+# Copyright (C) 2004 Red Hat Inc. <http://www.redhat.com/>
+# Copyright (C) 2005-2007 Collabora Ltd. <http://www.collabora.co.uk/>
+#
+# Permission is hereby granted, free of charge, to any person
+# obtaining a copy of this software and associated documentation
+# files (the "Software"), to deal in the Software without
+# restriction, including without limitation the rights to use, copy,
+# modify, merge, publish, distribute, sublicense, and/or sell copies
+# of the Software, and to permit persons to whom the Software is
+# furnished to do so, subject to the following conditions:
+#
+# The above copyright notice and this permission notice shall be
+# included in all copies or substantial portions of the Software.
+#
+# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+# HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+# WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+# DEALINGS IN THE SOFTWARE.
+
+import sys
+import os
+import unittest
+import time
+import logging
+
+builddir = os.path.normpath(os.environ["DBUS_TOP_BUILDDIR"])
+pydir = os.path.normpath(os.environ["DBUS_TOP_SRCDIR"])
+
+import dbus
+import _dbus_bindings
+import gobject
+import dbus.glib
+import dbus.service
+
+
+logging.basicConfig()
+logging.getLogger().setLevel(1)
+logger = logging.getLogger('test-signals')
+
+
+pkg = dbus.__file__
+if not pkg.startswith(pydir):
+ raise Exception("DBus modules (%s) are not being picked up from the package"%pkg)
+
+if not _dbus_bindings.__file__.startswith(builddir):
+ raise Exception("DBus modules (%s) are not being picked up from the package"%_dbus_bindings.__file__)
+
+
+NAME = "org.freedesktop.DBus.TestSuitePythonService"
+IFACE = "org.freedesktop.DBus.TestSuiteInterface"
+OBJECT = "/org/freedesktop/DBus/TestSuitePythonObject"
+
+
+class TestSignals(unittest.TestCase):
+ def setUp(self):
+ logger.info('setUp()')
+ self.bus = dbus.SessionBus()
+ self.remote_object = self.bus.get_object(NAME, OBJECT)
+ self.remote_object_fallback_trivial = self.bus.get_object(NAME,
+ OBJECT + '/Fallback')
+ self.remote_object_fallback = self.bus.get_object(NAME,
+ OBJECT + '/Fallback/Badger')
+ self.remote_object_follow = self.bus.get_object(NAME, OBJECT,
+ follow_name_owner_changes=True)
+ self.iface = dbus.Interface(self.remote_object, IFACE)
+ self.iface_follow = dbus.Interface(self.remote_object_follow, IFACE)
+ self.fallback_iface = dbus.Interface(self.remote_object_fallback, IFACE)
+ self.fallback_trivial_iface = dbus.Interface(
+ self.remote_object_fallback_trivial, IFACE)
+ self.in_test = None
+
+ def signal_test_impl(self, iface, name, test_removal=False):
+ self.in_test = name
+ # using append rather than assignment here to avoid scoping issues
+ result = []
+
+ def _timeout_handler():
+ logger.debug('_timeout_handler for %s: current state %s', name, self.in_test)
+ if self.in_test == name:
+ main_loop.quit()
+ def _signal_handler(s, sender, path):
+ logger.debug('_signal_handler for %s: current state %s', name, self.in_test)
+ if self.in_test not in (name, name + '+removed'):
+ return
+ logger.info('Received signal from %s:%s, argument is %r',
+ sender, path, s)
+ result.append('received')
+ main_loop.quit()
+ def _rm_timeout_handler():
+ logger.debug('_timeout_handler for %s: current state %s', name, self.in_test)
+ if self.in_test == name + '+removed':
+ main_loop.quit()
+
+ logger.info('Testing %s', name)
+ match = iface.connect_to_signal('SignalOneString', _signal_handler,
+ sender_keyword='sender',
+ path_keyword='path')
+ logger.info('Waiting for signal...')
+ iface.EmitSignal('SignalOneString', 0)
+ source_id = gobject.timeout_add(1000, _timeout_handler)
+ main_loop.run()
+ if not result:
+ raise AssertionError('Signal did not arrive within 1 second')
+ logger.debug('Removing match')
+ match.remove()
+ gobject.source_remove(source_id)
+ if test_removal:
+ self.in_test = name + '+removed'
+ logger.info('Testing %s', name)
+ result = []
+ iface.EmitSignal('SignalOneString', 0)
+ source_id = gobject.timeout_add(1000, _rm_timeout_handler)
+ main_loop.run()
+ if result:
+ raise AssertionError('Signal should not have arrived, but did')
+ gobject.source_remove(source_id)
+
+ def testFallback(self):
+ self.signal_test_impl(self.fallback_iface, 'Fallback')
+
+ def testFallbackTrivial(self):
+ self.signal_test_impl(self.fallback_trivial_iface, 'FallbackTrivial')
+
+ def testSignal(self):
+ self.signal_test_impl(self.iface, 'Signal')
+
+ def testRemoval(self):
+ self.signal_test_impl(self.iface, 'Removal', True)
+
+ def testSignalAgain(self):
+ self.signal_test_impl(self.iface, 'SignalAgain')
+
+ def testRemovalAgain(self):
+ self.signal_test_impl(self.iface, 'RemovalAgain', True)
+
+ def testSignalF(self):
+ self.signal_test_impl(self.iface_follow, 'Signal')
+
+ def testRemovalF(self):
+ self.signal_test_impl(self.iface_follow, 'Removal', True)
+
+ def testSignalAgainF(self):
+ self.signal_test_impl(self.iface_follow, 'SignalAgain')
+
+ def testRemovalAgainF(self):
+ self.signal_test_impl(self.iface_follow, 'RemovalAgain', True)
+
+if __name__ == '__main__':
+ main_loop = gobject.MainLoop()
+ gobject.threads_init()
+ dbus.glib.init_threads()
+
+ logger.info('Starting unit test')
+ unittest.main()
diff --git a/test/test-standalone.py b/test/test-standalone.py
new file mode 100755
index 0000000..929fc37
--- /dev/null
+++ b/test/test-standalone.py
@@ -0,0 +1,297 @@
+#!/usr/bin/env python
+
+"""Tests that don't need an active D-Bus connection to run, but can be
+run in isolation.
+"""
+
+# Copyright (C) 2006 Collabora Ltd. <http://www.collabora.co.uk/>
+#
+# Permission is hereby granted, free of charge, to any person
+# obtaining a copy of this software and associated documentation
+# files (the "Software"), to deal in the Software without
+# restriction, including without limitation the rights to use, copy,
+# modify, merge, publish, distribute, sublicense, and/or sell copies
+# of the Software, and to permit persons to whom the Software is
+# furnished to do so, subject to the following conditions:
+#
+# The above copyright notice and this permission notice shall be
+# included in all copies or substantial portions of the Software.
+#
+# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+# HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+# WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+# DEALINGS IN THE SOFTWARE.
+
+import sys
+import os
+import unittest
+import time
+from traceback import print_exc
+
+builddir = os.path.normpath(os.environ["DBUS_TOP_BUILDDIR"])
+pydir = os.path.normpath(os.environ["DBUS_TOP_SRCDIR"])
+
+import _dbus_bindings
+import dbus
+import dbus.types as types
+
+# Check that we're using the right versions
+if not dbus.__file__.startswith(pydir):
+ raise Exception("DBus modules (%s) are not being picked up from the package"%dbus.__file__)
+if not _dbus_bindings.__file__.startswith(builddir):
+ raise Exception("DBus modules (%s) are not being picked up from the package"%_dbus_bindings.__file__)
+assert (_dbus_bindings._python_version & 0xffff0000
+ == sys.hexversion & 0xffff0000), \
+ '_dbus_bindings was compiled for Python %x but this is Python %x, '\
+ 'a different major version'\
+ % (_dbus_bindings._python_version, sys.hexversion)
+assert _dbus_bindings.__version__ == os.environ['DBUS_PYTHON_VERSION'], \
+ '_dbus_bindings was compiled as version %s but Automake says '\
+ 'we should be version %s' \
+ % (_dbus_bindings.__version__, os.environ['DBUS_PYTHON_VERSION'])
+
+class TestTypes(unittest.TestCase):
+
+ def test_Dictionary(self):
+ self.assertEquals(types.Dictionary({'foo':'bar'}), {'foo':'bar'})
+ self.assertEquals(types.Dictionary({}, variant_level=2), {})
+ self.assertEquals(types.Dictionary({}, variant_level=2).variant_level, 2)
+
+ def test_Array(self):
+ self.assertEquals(types.Array(['foo','bar']), ['foo','bar'])
+ self.assertEquals(types.Array([], variant_level=2), [])
+ self.assertEquals(types.Array([], variant_level=2).variant_level, 2)
+
+ def test_Double(self):
+ self.assertEquals(types.Double(0.0), 0.0)
+ self.assertEquals(types.Double(0.125, variant_level=2), 0.125)
+ self.assertEquals(types.Double(0.125, variant_level=2).variant_level, 2)
+
+ def test_Struct(self):
+ x = types.Struct(('',))
+ self.assertEquals(x.variant_level, 0)
+ self.assertEquals(x, ('',))
+ x = types.Struct('abc', variant_level=42)
+ self.assertEquals(x.variant_level, 42)
+ self.assertEquals(x, ('a','b','c'))
+
+ def test_Byte(self):
+ self.assertEquals(types.Byte('x', variant_level=2), types.Byte(ord('x')))
+
+ def test_object_path_attr(self):
+ class MyObject(object):
+ __dbus_object_path__ = '/foo'
+ from _dbus_bindings import SignalMessage
+ self.assertEquals(SignalMessage.guess_signature(MyObject()), 'o')
+
+ def test_integers(self):
+ # This is an API guarantee. Note that exactly which of these types
+ # are ints and which of them are longs is *not* guaranteed.
+ for cls in (types.Int16, types.UInt16, types.Int32, types.UInt32,
+ types.Int64, types.UInt64):
+ self.assert_(issubclass(cls, (int, long)))
+ self.assert_(isinstance(cls(0), (int, long)))
+ self.assertEquals(cls(0), 0)
+ self.assertEquals(cls(23, variant_level=1), 23)
+ self.assertEquals(cls(23, variant_level=1).variant_level, 1)
+
+ def test_integer_limits_16(self):
+ self.assertEquals(types.Int16(0x7fff), 0x7fff)
+ self.assertEquals(types.Int16(-0x8000), -0x8000)
+ self.assertEquals(types.UInt16(0xffff), 0xffff)
+ self.assertRaises(Exception, types.Int16, 0x8000)
+ self.assertRaises(Exception, types.Int16, -0x8001)
+ self.assertRaises(Exception, types.UInt16, 0x10000)
+
+ def test_integer_limits_32(self):
+ self.assertEquals(types.Int32(0x7fffffff), 0x7fffffff)
+ self.assertEquals(types.Int32(-0x80000000L), -0x80000000L)
+ self.assertEquals(types.UInt32(0xffffffffL), 0xffffffffL)
+ self.assertRaises(Exception, types.Int32, 0x80000000L)
+ self.assertRaises(Exception, types.Int32, -0x80000001L)
+ self.assertRaises(Exception, types.UInt32, 0x100000000L)
+
+ def test_integer_limits_64(self):
+ self.assertEquals(types.Int64(0x7fffffffffffffffL), 0x7fffffffffffffffL)
+ self.assertEquals(types.Int64(-0x8000000000000000L), -0x8000000000000000L)
+ self.assertEquals(types.UInt64(0xffffffffffffffffL), 0xffffffffffffffffL)
+ self.assertRaises(Exception, types.Int16, 0x8000000000000000L)
+ self.assertRaises(Exception, types.Int16, -0x8000000000000001L)
+ self.assertRaises(Exception, types.UInt16, 0x10000000000000000L)
+
+ def test_Signature(self):
+ self.assertRaises(Exception, types.Signature, 'a')
+ self.assertEquals(types.Signature('ab', variant_level=23), 'ab')
+ self.assert_(isinstance(types.Signature('ab'), str))
+ self.assertEquals(tuple(types.Signature('ab(xt)a{sv}')),
+ ('ab', '(xt)', 'a{sv}'))
+ self.assert_(isinstance(tuple(types.Signature('ab'))[0],
+ types.Signature))
+
+
+class TestMessageMarshalling(unittest.TestCase):
+
+ def test_count(self):
+ from _dbus_bindings import SignalMessage
+ s = SignalMessage('/', 'foo.bar', 'baz')
+ try:
+ s.append('a', signature='ss')
+ except TypeError:
+ pass
+ else:
+ raise AssertionError('Appending too few things in a message '
+ 'should fail')
+ s = SignalMessage('/', 'foo.bar', 'baz')
+ try:
+ s.append('a','b','c', signature='ss')
+ except TypeError:
+ pass
+ else:
+ raise AssertionError('Appending too many things in a message '
+ 'should fail')
+
+ def test_append(self):
+ aeq = self.assertEquals
+ from _dbus_bindings import SignalMessage
+ s = SignalMessage('/', 'foo.bar', 'baz')
+ s.append([types.Byte(1)], signature='ay')
+ aeq(s.get_signature(), 'ay')
+ aeq(s.get_args_list(), [[types.Byte(1)]])
+
+ s = SignalMessage('/', 'foo.bar', 'baz')
+ s.append([], signature='ay')
+ aeq(s.get_args_list(), [[]])
+
+ def test_append_ByteArray(self):
+ aeq = self.assertEquals
+ from _dbus_bindings import SignalMessage
+ s = SignalMessage('/', 'foo.bar', 'baz')
+ s.append(types.ByteArray('ab'), signature='ay')
+ aeq(s.get_args_list(), [[types.Byte('a'), types.Byte('b')]])
+ s = SignalMessage('/', 'foo.bar', 'baz')
+ s.append(types.ByteArray('ab'), signature='av')
+ aeq(s.get_args_list(), [[types.Byte('a'), types.Byte('b')]])
+
+ def test_append_Variant(self):
+ a = self.assert_
+ aeq = self.assertEquals
+ from _dbus_bindings import SignalMessage
+ s = SignalMessage('/', 'foo.bar', 'baz')
+ s.append(types.Int32(1, variant_level=0),
+ types.String('a', variant_level=42),
+ types.Array([types.Byte('a', variant_level=1),
+ types.UInt32(123, variant_level=1)],
+ signature='v'),
+ signature='vvv')
+ aeq(s.get_signature(), 'vvv')
+ args = s.get_args_list()
+ aeq(args[0].__class__, types.Int32)
+ aeq(args[0].variant_level, 1)
+ aeq(args[1].__class__, types.String)
+ aeq(args[1].variant_level, 42)
+ aeq(args[2].__class__, types.Array)
+ aeq(args[2].variant_level, 1)
+ aeq(args[2].signature, 'v')
+
+ def test_guess_signature(self):
+ aeq = self.assertEquals
+ from _dbus_bindings import Message
+ aeq(Message.guess_signature(('a','b')), '(ss)')
+ aeq(Message.guess_signature('a','b'), 'ss')
+ aeq(Message.guess_signature(['a','b']), 'as')
+ aeq(Message.guess_signature(('a',)), '(s)')
+ aeq(Message.guess_signature('abc'), 's')
+ aeq(Message.guess_signature(types.Int32(123)), 'i')
+ aeq(Message.guess_signature(types.ByteArray('abc')), 'ay')
+ aeq(Message.guess_signature(('a',)), '(s)')
+ aeq(Message.guess_signature(['a']), 'as')
+ aeq(Message.guess_signature({'a':'b'}), 'a{ss}')
+
+ def test_guess_signature_dbus_types(self):
+ aeq = self.assertEquals
+ from _dbus_bindings import Message
+ gs = Message.guess_signature
+ aeq(gs(types.Dictionary({'a':'b'})), 'a{ss}')
+ aeq(gs(types.Dictionary({'a':'b'}, signature='sv')), 'a{sv}')
+ aeq(gs(types.Dictionary({}, signature='iu')), 'a{iu}')
+ aeq(gs(types.Array([types.Int32(1)])), 'ai')
+ aeq(gs(types.Array([types.Int32(1)], signature='u')), 'au')
+
+ def test_get_args_options(self):
+ aeq = self.assertEquals
+ s = _dbus_bindings.SignalMessage('/', 'foo.bar', 'baz')
+ s.append('b', 'bytes', -1, 1, 'str', 'var', signature='yayiusv')
+ aeq(s.get_args_list(), [ord('b'),
+ [ord('b'),ord('y'),ord('t'),ord('e'), ord('s')],
+ -1, 1, u'str', u'var'])
+ byte, bytes, int32, uint32, string, variant = s.get_args_list()
+ aeq(byte.__class__, types.Byte)
+ aeq(bytes.__class__, types.Array)
+ aeq(bytes[0].__class__, types.Byte)
+ aeq(int32.__class__, types.Int32)
+ aeq(uint32.__class__, types.UInt32)
+ aeq(string.__class__, types.String)
+ aeq(string.variant_level, 0)
+ aeq(variant.__class__, types.String)
+ aeq(variant.variant_level, 1)
+
+ byte, bytes, int32, uint32, string, variant = s.get_args_list(
+ byte_arrays=True)
+ aeq(byte.__class__, types.Byte)
+ aeq(bytes.__class__, types.ByteArray)
+ aeq(bytes, 'bytes')
+ aeq(bytes[0].__class__, str)
+ aeq(int32.__class__, types.Int32)
+ aeq(uint32.__class__, types.UInt32)
+ aeq(string.__class__, types.String)
+ aeq(variant.__class__, types.String)
+ aeq(variant.variant_level, 1)
+
+ byte, bytes, int32, uint32, string, variant = s.get_args_list(
+ utf8_strings=True)
+ aeq(byte.__class__, types.Byte)
+ aeq(bytes.__class__, types.Array)
+ aeq(bytes[0].__class__, types.Byte)
+ aeq(int32.__class__, types.Int32)
+ aeq(uint32.__class__, types.UInt32)
+ aeq(string.__class__, types.UTF8String)
+ aeq(string, 'str')
+ aeq(variant.__class__, types.UTF8String)
+ aeq(variant.variant_level, 1)
+ aeq(variant, 'var')
+
+ def test_object_path_attr(self):
+ from _dbus_bindings import SignalMessage
+ class MyObject(object):
+ __dbus_object_path__ = '/foo'
+ s = SignalMessage('/', 'foo.bar', 'baz')
+ s.append(MyObject(), signature='o')
+ s.append(MyObject())
+ self.assertEquals(s.get_args_list(), ['/foo', '/foo'])
+
+ def test_struct(self):
+ from _dbus_bindings import SignalMessage
+ s = SignalMessage('/', 'foo.bar', 'baz')
+ try:
+ s.append(('a',), signature='(ss)')
+ except TypeError:
+ pass
+ else:
+ raise AssertionError('Appending too few things in a struct '
+ 'should fail')
+ s = SignalMessage('/', 'foo.bar', 'baz')
+ try:
+ s.append(('a','b','c'), signature='(ss)')
+ except TypeError:
+ pass
+ else:
+ raise AssertionError('Appending too many things in a struct '
+ 'should fail')
+
+
+if __name__ == '__main__':
+ unittest.main()
diff --git a/test/test-unusable-main-loop.py b/test/test-unusable-main-loop.py
new file mode 100644
index 0000000..cee8723
--- /dev/null
+++ b/test/test-unusable-main-loop.py
@@ -0,0 +1,39 @@
+#!/usr/bin/env python
+
+# Copyright (C) 2007 Collabora Ltd. <http://www.collabora.co.uk/>
+#
+# Permission is hereby granted, free of charge, to any person
+# obtaining a copy of this software and associated documentation
+# files (the "Software"), to deal in the Software without
+# restriction, including without limitation the rights to use, copy,
+# modify, merge, publish, distribute, sublicense, and/or sell copies
+# of the Software, and to permit persons to whom the Software is
+# furnished to do so, subject to the following conditions:
+#
+# The above copyright notice and this permission notice shall be
+# included in all copies or substantial portions of the Software.
+#
+# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+# HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+# WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+# DEALINGS IN THE SOFTWARE.
+
+import dbus
+
+from dbus_py_test import UnusableMainLoop
+
+def main():
+ UnusableMainLoop(set_as_default=True)
+ try:
+ bus = dbus.SessionBus()
+ except ValueError, e:
+ print "Correctly got ValueError from UnusableMainLoop"
+ else:
+ raise AssertionError("Expected ValueError from UnusableMainLoop")
+
+if __name__ == '__main__':
+ main()
diff --git a/test/tmp-session-bus.conf.in b/test/tmp-session-bus.conf.in
new file mode 100644
index 0000000..9d172ff
--- /dev/null
+++ b/test/tmp-session-bus.conf.in
@@ -0,0 +1,21 @@
+<!-- @configure_input@ -->
+<!DOCTYPE busconfig PUBLIC "-//freedesktop//DTD D-BUS Bus Configuration 1.0//EN"
+ "http://www.freedesktop.org/standards/dbus/1.0/busconfig.dtd">
+<busconfig>
+ <!-- Our well-known bus type, don't change this -->
+ <type>session</type>
+ <listen>unix:tmpdir=@abs_top_builddir@/test</listen>
+
+ <servicedir>@abs_top_builddir@/test</servicedir>
+
+ <policy context="default">
+ <!-- Allow everything to be sent -->
+ <allow send_destination="*"/>
+ <!-- Allow everything to be received -->
+ <allow eavesdrop="true"/>
+ <!-- Allow anyone to own anything -->
+ <allow own="*"/>
+ </policy>
+
+</busconfig>
+<!-- vim:set ft=xml sts=2 sw=2 et: -->