diff options
author | Simon McVittie <smcv@debian.org> | 2015-02-09 13:32:57 +0000 |
---|---|---|
committer | Simon McVittie <smcv@debian.org> | 2015-02-09 13:32:57 +0000 |
commit | 8fd2c8098849695fce037fa3731a916ac5354e91 (patch) | |
tree | 71ee233983f8d60f96a34ef602b8e85a51301462 /test | |
parent | df40668f10c30c52a3f8bd50868ba31108a2eee2 (diff) | |
download | dbus-8fd2c8098849695fce037fa3731a916ac5354e91.tar.gz |
Imported Upstream version 1.9.10upstream/1.9.10
Diffstat (limited to 'test')
-rw-r--r-- | test/Makefile.am | 33 | ||||
-rw-r--r-- | test/Makefile.in | 144 | ||||
-rw-r--r-- | test/corrupt.c | 4 | ||||
-rw-r--r-- | test/data/valid-config-files/forbidding.conf.in | 18 | ||||
-rw-r--r-- | test/dbus-daemon-eavesdrop.c | 3 | ||||
-rw-r--r-- | test/dbus-daemon.c | 3 | ||||
-rw-r--r-- | test/fdpass.c | 852 | ||||
-rw-r--r-- | test/internals/refs.c | 5 | ||||
-rw-r--r-- | test/internals/syslog.c | 5 | ||||
-rw-r--r-- | test/loopback.c | 5 | ||||
-rw-r--r-- | test/marshal.c | 4 | ||||
-rw-r--r-- | test/monitor.c | 1496 | ||||
-rw-r--r-- | test/relay.c | 5 | ||||
-rw-r--r-- | test/sd-activation.c | 34 | ||||
-rw-r--r-- | test/syntax.c | 4 | ||||
-rw-r--r-- | test/test-utils-glib.c | 26 | ||||
-rw-r--r-- | test/test-utils-glib.h | 2 | ||||
-rw-r--r-- | test/uid-permissions.c | 3 |
18 files changed, 2607 insertions, 39 deletions
diff --git a/test/Makefile.am b/test/Makefile.am index 8b84c7d2..c2a55c9e 100644 --- a/test/Makefile.am +++ b/test/Makefile.am @@ -156,6 +156,8 @@ installable_tests += \ test-corrupt \ test-dbus-daemon \ test-dbus-daemon-eavesdrop \ + test-fdpass \ + test-monitor \ test-loopback \ test-marshal \ test-refs \ @@ -240,14 +242,25 @@ test_sd_activation_LDADD = \ $(NULL) test_marshal_SOURCES = marshal.c +test_marshal_CPPFLAGS = $(testutils_shared_if_possible_cppflags) test_marshal_LDADD = \ - $(top_builddir)/dbus/libdbus-1.la \ + $(testutils_shared_if_possible_libs) \ + $(GLIB_LIBS) \ + $(NULL) + +test_monitor_SOURCES = \ + monitor.c \ + $(NULL) +test_monitor_CPPFLAGS = $(testutils_shared_if_possible_cppflags) +test_monitor_LDADD = \ + $(testutils_shared_if_possible_libs) \ $(GLIB_LIBS) \ $(NULL) test_syntax_SOURCES = syntax.c +test_syntax_CPPFLAGS = $(testutils_shared_if_possible_cppflags) test_syntax_LDADD = \ - $(top_builddir)/dbus/libdbus-1.la \ + $(testutils_shared_if_possible_libs) \ $(GLIB_LIBS) \ $(NULL) @@ -260,6 +273,17 @@ test_uid_permissions_LDADD = \ $(GLIB_LIBS) \ $(NULL) +test_fdpass_SOURCES = \ + fdpass.c \ + $(NULL) +test_fdpass_CPPFLAGS = \ + $(static_cppflags) \ + $(NULL) +test_fdpass_LDADD = \ + libdbus-testutils-internal.la \ + $(GLIB_LIBS) \ + $(NULL) + if DBUS_ENABLE_MODULAR_TESTS TESTS += $(installable_tests) installcheck_tests += $(installable_tests) @@ -295,6 +319,7 @@ in_data = \ data/valid-config-files/debug-allow-all-sha1.conf.in \ data/valid-config-files/debug-allow-all.conf.in \ data/valid-config-files/finite-timeout.conf.in \ + data/valid-config-files/forbidding.conf.in \ data/valid-config-files/incoming-limit.conf.in \ data/valid-config-files/multi-user.conf.in \ data/valid-config-files/systemd-activation.conf.in \ @@ -492,14 +517,14 @@ $(imported_data): data/valid-config-files/%.conf: $(top_builddir)/bus/%.conf $(AM_V_at)$(MKDIR_P) data/valid-config-files $(AM_V_GEN)cp $< $@ -$(installable_test_meta): %.test: % Makefile +$(installable_test_meta): %.test: %$(EXEEXT) Makefile $(AM_V_GEN) ( \ echo '[Test]'; \ echo 'Type=session'; \ echo 'Exec=env DBUS_TEST_HOME=$$(pwd)/home.tmp $(testexecdir)/$*'; \ ) > $@.tmp && mv $@.tmp $@ -$(installable_test_meta_with_config): %_with_config.test: % Makefile +$(installable_test_meta_with_config): %_with_config.test: %$(EXEEXT) Makefile $(AM_V_GEN) ( \ echo '[Test]'; \ echo 'Type=session'; \ diff --git a/test/Makefile.in b/test/Makefile.in index 9231159b..01a0879e 100644 --- a/test/Makefile.in +++ b/test/Makefile.in @@ -103,6 +103,8 @@ testexec_PROGRAMS = $(am__EXEEXT_7) @DBUS_WITH_GLIB_TRUE@ test-corrupt \ @DBUS_WITH_GLIB_TRUE@ test-dbus-daemon \ @DBUS_WITH_GLIB_TRUE@ test-dbus-daemon-eavesdrop \ +@DBUS_WITH_GLIB_TRUE@ test-fdpass \ +@DBUS_WITH_GLIB_TRUE@ test-monitor \ @DBUS_WITH_GLIB_TRUE@ test-loopback \ @DBUS_WITH_GLIB_TRUE@ test-marshal \ @DBUS_WITH_GLIB_TRUE@ test-refs \ @@ -176,6 +178,8 @@ libdbus_testutils_la_OBJECTS = $(am_libdbus_testutils_la_OBJECTS) @DBUS_WITH_GLIB_TRUE@am__EXEEXT_2 = test-corrupt$(EXEEXT) \ @DBUS_WITH_GLIB_TRUE@ test-dbus-daemon$(EXEEXT) \ @DBUS_WITH_GLIB_TRUE@ test-dbus-daemon-eavesdrop$(EXEEXT) \ +@DBUS_WITH_GLIB_TRUE@ test-fdpass$(EXEEXT) \ +@DBUS_WITH_GLIB_TRUE@ test-monitor$(EXEEXT) \ @DBUS_WITH_GLIB_TRUE@ test-loopback$(EXEEXT) \ @DBUS_WITH_GLIB_TRUE@ test-marshal$(EXEEXT) test-refs$(EXEEXT) \ @DBUS_WITH_GLIB_TRUE@ test-relay$(EXEEXT) \ @@ -223,13 +227,21 @@ test_dbus_daemon_eavesdrop_DEPENDENCIES = \ test_exit_SOURCES = test-exit.c test_exit_OBJECTS = test-exit.$(OBJEXT) test_exit_LDADD = $(LDADD) +am_test_fdpass_OBJECTS = test_fdpass-fdpass.$(OBJEXT) +test_fdpass_OBJECTS = $(am_test_fdpass_OBJECTS) +test_fdpass_DEPENDENCIES = libdbus-testutils-internal.la \ + $(am__DEPENDENCIES_1) am_test_loopback_OBJECTS = test_loopback-loopback.$(OBJEXT) test_loopback_OBJECTS = $(am_test_loopback_OBJECTS) test_loopback_DEPENDENCIES = $(testutils_shared_if_possible_libs) \ $(am__DEPENDENCIES_1) -am_test_marshal_OBJECTS = marshal.$(OBJEXT) +am_test_marshal_OBJECTS = test_marshal-marshal.$(OBJEXT) test_marshal_OBJECTS = $(am_test_marshal_OBJECTS) -test_marshal_DEPENDENCIES = $(top_builddir)/dbus/libdbus-1.la \ +test_marshal_DEPENDENCIES = $(testutils_shared_if_possible_libs) \ + $(am__DEPENDENCIES_1) +am_test_monitor_OBJECTS = test_monitor-monitor.$(OBJEXT) +test_monitor_OBJECTS = $(am_test_monitor_OBJECTS) +test_monitor_DEPENDENCIES = $(testutils_shared_if_possible_libs) \ $(am__DEPENDENCIES_1) test_names_SOURCES = test-names.c test_names_OBJECTS = test_names-test-names.$(OBJEXT) @@ -270,9 +282,9 @@ test_sleep_forever_LDADD = $(LDADD) am_test_spawn_OBJECTS = test_spawn-spawn-test.$(OBJEXT) test_spawn_OBJECTS = $(am_test_spawn_OBJECTS) test_spawn_DEPENDENCIES = $(top_builddir)/dbus/libdbus-internal.la -am_test_syntax_OBJECTS = syntax.$(OBJEXT) +am_test_syntax_OBJECTS = test_syntax-syntax.$(OBJEXT) test_syntax_OBJECTS = $(am_test_syntax_OBJECTS) -test_syntax_DEPENDENCIES = $(top_builddir)/dbus/libdbus-1.la \ +test_syntax_DEPENDENCIES = $(testutils_shared_if_possible_libs) \ $(am__DEPENDENCIES_1) am_test_syslog_OBJECTS = internals/test_syslog-syslog.$(OBJEXT) test_syslog_OBJECTS = $(am_test_syslog_OBJECTS) @@ -322,7 +334,8 @@ SOURCES = $(libdbus_testutils_internal_la_SOURCES) \ $(manual_dir_iter_SOURCES) $(manual_tcp_SOURCES) \ $(test_corrupt_SOURCES) $(test_dbus_daemon_SOURCES) \ $(test_dbus_daemon_eavesdrop_SOURCES) test-exit.c \ - $(test_loopback_SOURCES) $(test_marshal_SOURCES) test-names.c \ + $(test_fdpass_SOURCES) $(test_loopback_SOURCES) \ + $(test_marshal_SOURCES) $(test_monitor_SOURCES) test-names.c \ $(test_printf_SOURCES) $(test_refs_SOURCES) \ $(test_relay_SOURCES) $(test_sd_activation_SOURCES) \ test-segfault.c test-service.c $(test_shell_SOURCES) \ @@ -335,7 +348,8 @@ DIST_SOURCES = $(am__libdbus_testutils_internal_la_SOURCES_DIST) \ $(manual_tcp_SOURCES) $(test_corrupt_SOURCES) \ $(test_dbus_daemon_SOURCES) \ $(test_dbus_daemon_eavesdrop_SOURCES) test-exit.c \ - $(test_loopback_SOURCES) $(test_marshal_SOURCES) test-names.c \ + $(test_fdpass_SOURCES) $(test_loopback_SOURCES) \ + $(test_marshal_SOURCES) $(test_monitor_SOURCES) test-names.c \ $(test_printf_SOURCES) $(test_refs_SOURCES) \ $(test_relay_SOURCES) $(test_sd_activation_SOURCES) \ test-segfault.c test-service.c $(test_shell_SOURCES) \ @@ -982,14 +996,26 @@ test_sd_activation_LDADD = \ $(NULL) test_marshal_SOURCES = marshal.c +test_marshal_CPPFLAGS = $(testutils_shared_if_possible_cppflags) test_marshal_LDADD = \ - $(top_builddir)/dbus/libdbus-1.la \ + $(testutils_shared_if_possible_libs) \ + $(GLIB_LIBS) \ + $(NULL) + +test_monitor_SOURCES = \ + monitor.c \ + $(NULL) + +test_monitor_CPPFLAGS = $(testutils_shared_if_possible_cppflags) +test_monitor_LDADD = \ + $(testutils_shared_if_possible_libs) \ $(GLIB_LIBS) \ $(NULL) test_syntax_SOURCES = syntax.c +test_syntax_CPPFLAGS = $(testutils_shared_if_possible_cppflags) test_syntax_LDADD = \ - $(top_builddir)/dbus/libdbus-1.la \ + $(testutils_shared_if_possible_libs) \ $(GLIB_LIBS) \ $(NULL) @@ -1003,12 +1029,26 @@ test_uid_permissions_LDADD = \ $(GLIB_LIBS) \ $(NULL) +test_fdpass_SOURCES = \ + fdpass.c \ + $(NULL) + +test_fdpass_CPPFLAGS = \ + $(static_cppflags) \ + $(NULL) + +test_fdpass_LDADD = \ + libdbus-testutils-internal.la \ + $(GLIB_LIBS) \ + $(NULL) + in_data = \ data/valid-config-files-system/debug-allow-all-fail.conf.in \ data/valid-config-files-system/debug-allow-all-pass.conf.in \ data/valid-config-files/debug-allow-all-sha1.conf.in \ data/valid-config-files/debug-allow-all.conf.in \ data/valid-config-files/finite-timeout.conf.in \ + data/valid-config-files/forbidding.conf.in \ data/valid-config-files/incoming-limit.conf.in \ data/valid-config-files/multi-user.conf.in \ data/valid-config-files/systemd-activation.conf.in \ @@ -1254,6 +1294,10 @@ test-exit$(EXEEXT): $(test_exit_OBJECTS) $(test_exit_DEPENDENCIES) $(EXTRA_test_ @rm -f test-exit$(EXEEXT) $(AM_V_CCLD)$(LINK) $(test_exit_OBJECTS) $(test_exit_LDADD) $(LIBS) +test-fdpass$(EXEEXT): $(test_fdpass_OBJECTS) $(test_fdpass_DEPENDENCIES) $(EXTRA_test_fdpass_DEPENDENCIES) + @rm -f test-fdpass$(EXEEXT) + $(AM_V_CCLD)$(LINK) $(test_fdpass_OBJECTS) $(test_fdpass_LDADD) $(LIBS) + test-loopback$(EXEEXT): $(test_loopback_OBJECTS) $(test_loopback_DEPENDENCIES) $(EXTRA_test_loopback_DEPENDENCIES) @rm -f test-loopback$(EXEEXT) $(AM_V_CCLD)$(LINK) $(test_loopback_OBJECTS) $(test_loopback_LDADD) $(LIBS) @@ -1262,6 +1306,10 @@ test-marshal$(EXEEXT): $(test_marshal_OBJECTS) $(test_marshal_DEPENDENCIES) $(EX @rm -f test-marshal$(EXEEXT) $(AM_V_CCLD)$(LINK) $(test_marshal_OBJECTS) $(test_marshal_LDADD) $(LIBS) +test-monitor$(EXEEXT): $(test_monitor_OBJECTS) $(test_monitor_DEPENDENCIES) $(EXTRA_test_monitor_DEPENDENCIES) + @rm -f test-monitor$(EXEEXT) + $(AM_V_CCLD)$(LINK) $(test_monitor_OBJECTS) $(test_monitor_LDADD) $(LIBS) + test-names$(EXEEXT): $(test_names_OBJECTS) $(test_names_DEPENDENCIES) $(EXTRA_test_names_DEPENDENCIES) @rm -f test-names$(EXEEXT) $(AM_V_CCLD)$(LINK) $(test_names_OBJECTS) $(test_names_LDADD) $(LIBS) @@ -1342,8 +1390,6 @@ distclean-compile: @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/manual_authz-manual-authz.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/manual_dir_iter-manual-dir-iter.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/manual_tcp-manual-tcp.Po@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/marshal.Po@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/syntax.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/test-exit.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/test-segfault.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/test-sleep-forever.Po@am__quote@ @@ -1352,7 +1398,10 @@ distclean-compile: @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/test_corrupt-corrupt.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/test_dbus_daemon-dbus-daemon.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/test_dbus_daemon_eavesdrop-dbus-daemon-eavesdrop.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/test_fdpass-fdpass.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/test_loopback-loopback.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/test_marshal-marshal.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/test_monitor-monitor.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/test_names-test-names.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/test_relay-relay.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/test_sd_activation-sd-activation.Po@am__quote@ @@ -1360,6 +1409,7 @@ distclean-compile: @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/test_shell-shell-test.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/test_shell_service-test-shell-service.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/test_spawn-spawn-test.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/test_syntax-syntax.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/test_uid_permissions-uid-permissions.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@internals/$(DEPDIR)/test_printf-printf.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@internals/$(DEPDIR)/test_refs-refs.Po@am__quote@ @@ -1487,6 +1537,20 @@ test_dbus_daemon_eavesdrop-dbus-daemon-eavesdrop.obj: dbus-daemon-eavesdrop.c @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(test_dbus_daemon_eavesdrop_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o test_dbus_daemon_eavesdrop-dbus-daemon-eavesdrop.obj `if test -f 'dbus-daemon-eavesdrop.c'; then $(CYGPATH_W) 'dbus-daemon-eavesdrop.c'; else $(CYGPATH_W) '$(srcdir)/dbus-daemon-eavesdrop.c'; fi` +test_fdpass-fdpass.o: fdpass.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(test_fdpass_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT test_fdpass-fdpass.o -MD -MP -MF $(DEPDIR)/test_fdpass-fdpass.Tpo -c -o test_fdpass-fdpass.o `test -f 'fdpass.c' || echo '$(srcdir)/'`fdpass.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/test_fdpass-fdpass.Tpo $(DEPDIR)/test_fdpass-fdpass.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='fdpass.c' object='test_fdpass-fdpass.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(test_fdpass_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o test_fdpass-fdpass.o `test -f 'fdpass.c' || echo '$(srcdir)/'`fdpass.c + +test_fdpass-fdpass.obj: fdpass.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(test_fdpass_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT test_fdpass-fdpass.obj -MD -MP -MF $(DEPDIR)/test_fdpass-fdpass.Tpo -c -o test_fdpass-fdpass.obj `if test -f 'fdpass.c'; then $(CYGPATH_W) 'fdpass.c'; else $(CYGPATH_W) '$(srcdir)/fdpass.c'; fi` +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/test_fdpass-fdpass.Tpo $(DEPDIR)/test_fdpass-fdpass.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='fdpass.c' object='test_fdpass-fdpass.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(test_fdpass_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o test_fdpass-fdpass.obj `if test -f 'fdpass.c'; then $(CYGPATH_W) 'fdpass.c'; else $(CYGPATH_W) '$(srcdir)/fdpass.c'; fi` + test_loopback-loopback.o: loopback.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(test_loopback_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT test_loopback-loopback.o -MD -MP -MF $(DEPDIR)/test_loopback-loopback.Tpo -c -o test_loopback-loopback.o `test -f 'loopback.c' || echo '$(srcdir)/'`loopback.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/test_loopback-loopback.Tpo $(DEPDIR)/test_loopback-loopback.Po @@ -1501,6 +1565,34 @@ test_loopback-loopback.obj: loopback.c @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(test_loopback_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o test_loopback-loopback.obj `if test -f 'loopback.c'; then $(CYGPATH_W) 'loopback.c'; else $(CYGPATH_W) '$(srcdir)/loopback.c'; fi` +test_marshal-marshal.o: marshal.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(test_marshal_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT test_marshal-marshal.o -MD -MP -MF $(DEPDIR)/test_marshal-marshal.Tpo -c -o test_marshal-marshal.o `test -f 'marshal.c' || echo '$(srcdir)/'`marshal.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/test_marshal-marshal.Tpo $(DEPDIR)/test_marshal-marshal.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='marshal.c' object='test_marshal-marshal.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(test_marshal_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o test_marshal-marshal.o `test -f 'marshal.c' || echo '$(srcdir)/'`marshal.c + +test_marshal-marshal.obj: marshal.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(test_marshal_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT test_marshal-marshal.obj -MD -MP -MF $(DEPDIR)/test_marshal-marshal.Tpo -c -o test_marshal-marshal.obj `if test -f 'marshal.c'; then $(CYGPATH_W) 'marshal.c'; else $(CYGPATH_W) '$(srcdir)/marshal.c'; fi` +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/test_marshal-marshal.Tpo $(DEPDIR)/test_marshal-marshal.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='marshal.c' object='test_marshal-marshal.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(test_marshal_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o test_marshal-marshal.obj `if test -f 'marshal.c'; then $(CYGPATH_W) 'marshal.c'; else $(CYGPATH_W) '$(srcdir)/marshal.c'; fi` + +test_monitor-monitor.o: monitor.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(test_monitor_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT test_monitor-monitor.o -MD -MP -MF $(DEPDIR)/test_monitor-monitor.Tpo -c -o test_monitor-monitor.o `test -f 'monitor.c' || echo '$(srcdir)/'`monitor.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/test_monitor-monitor.Tpo $(DEPDIR)/test_monitor-monitor.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='monitor.c' object='test_monitor-monitor.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(test_monitor_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o test_monitor-monitor.o `test -f 'monitor.c' || echo '$(srcdir)/'`monitor.c + +test_monitor-monitor.obj: monitor.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(test_monitor_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT test_monitor-monitor.obj -MD -MP -MF $(DEPDIR)/test_monitor-monitor.Tpo -c -o test_monitor-monitor.obj `if test -f 'monitor.c'; then $(CYGPATH_W) 'monitor.c'; else $(CYGPATH_W) '$(srcdir)/monitor.c'; fi` +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/test_monitor-monitor.Tpo $(DEPDIR)/test_monitor-monitor.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='monitor.c' object='test_monitor-monitor.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(test_monitor_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o test_monitor-monitor.obj `if test -f 'monitor.c'; then $(CYGPATH_W) 'monitor.c'; else $(CYGPATH_W) '$(srcdir)/monitor.c'; fi` + test_names-test-names.o: test-names.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(test_names_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT test_names-test-names.o -MD -MP -MF $(DEPDIR)/test_names-test-names.Tpo -c -o test_names-test-names.o `test -f 'test-names.c' || echo '$(srcdir)/'`test-names.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/test_names-test-names.Tpo $(DEPDIR)/test_names-test-names.Po @@ -1627,6 +1719,20 @@ test_spawn-spawn-test.obj: spawn-test.c @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(test_spawn_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o test_spawn-spawn-test.obj `if test -f 'spawn-test.c'; then $(CYGPATH_W) 'spawn-test.c'; else $(CYGPATH_W) '$(srcdir)/spawn-test.c'; fi` +test_syntax-syntax.o: syntax.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(test_syntax_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT test_syntax-syntax.o -MD -MP -MF $(DEPDIR)/test_syntax-syntax.Tpo -c -o test_syntax-syntax.o `test -f 'syntax.c' || echo '$(srcdir)/'`syntax.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/test_syntax-syntax.Tpo $(DEPDIR)/test_syntax-syntax.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='syntax.c' object='test_syntax-syntax.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(test_syntax_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o test_syntax-syntax.o `test -f 'syntax.c' || echo '$(srcdir)/'`syntax.c + +test_syntax-syntax.obj: syntax.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(test_syntax_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT test_syntax-syntax.obj -MD -MP -MF $(DEPDIR)/test_syntax-syntax.Tpo -c -o test_syntax-syntax.obj `if test -f 'syntax.c'; then $(CYGPATH_W) 'syntax.c'; else $(CYGPATH_W) '$(srcdir)/syntax.c'; fi` +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/test_syntax-syntax.Tpo $(DEPDIR)/test_syntax-syntax.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='syntax.c' object='test_syntax-syntax.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(test_syntax_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o test_syntax-syntax.obj `if test -f 'syntax.c'; then $(CYGPATH_W) 'syntax.c'; else $(CYGPATH_W) '$(srcdir)/syntax.c'; fi` + internals/test_syslog-syslog.o: internals/syslog.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(test_syslog_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT internals/test_syslog-syslog.o -MD -MP -MF internals/$(DEPDIR)/test_syslog-syslog.Tpo -c -o internals/test_syslog-syslog.o `test -f 'internals/syslog.c' || echo '$(srcdir)/'`internals/syslog.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) internals/$(DEPDIR)/test_syslog-syslog.Tpo internals/$(DEPDIR)/test_syslog-syslog.Po @@ -1957,6 +2063,20 @@ test-dbus-daemon-eavesdrop.log: test-dbus-daemon-eavesdrop$(EXEEXT) --log-file $$b.log --trs-file $$b.trs \ $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \ "$$tst" $(AM_TESTS_FD_REDIRECT) +test-fdpass.log: test-fdpass$(EXEEXT) + @p='test-fdpass$(EXEEXT)'; \ + b='test-fdpass'; \ + $(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \ + --log-file $$b.log --trs-file $$b.trs \ + $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \ + "$$tst" $(AM_TESTS_FD_REDIRECT) +test-monitor.log: test-monitor$(EXEEXT) + @p='test-monitor$(EXEEXT)'; \ + b='test-monitor'; \ + $(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \ + --log-file $$b.log --trs-file $$b.trs \ + $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \ + "$$tst" $(AM_TESTS_FD_REDIRECT) test-loopback.log: test-loopback$(EXEEXT) @p='test-loopback$(EXEEXT)'; \ b='test-loopback'; \ @@ -2337,14 +2457,14 @@ $(imported_data): data/valid-config-files/%.conf: $(top_builddir)/bus/%.conf $(AM_V_at)$(MKDIR_P) data/valid-config-files $(AM_V_GEN)cp $< $@ -$(installable_test_meta): %.test: % Makefile +$(installable_test_meta): %.test: %$(EXEEXT) Makefile $(AM_V_GEN) ( \ echo '[Test]'; \ echo 'Type=session'; \ echo 'Exec=env DBUS_TEST_HOME=$$(pwd)/home.tmp $(testexecdir)/$*'; \ ) > $@.tmp && mv $@.tmp $@ -$(installable_test_meta_with_config): %_with_config.test: % Makefile +$(installable_test_meta_with_config): %_with_config.test: %$(EXEEXT) Makefile $(AM_V_GEN) ( \ echo '[Test]'; \ echo 'Type=session'; \ diff --git a/test/corrupt.c b/test/corrupt.c index b0084fd3..500cbeb7 100644 --- a/test/corrupt.c +++ b/test/corrupt.c @@ -31,7 +31,7 @@ #include <dbus/dbus.h> -#include "test-utils.h" +#include "test-utils-glib.h" typedef struct { DBusError e; @@ -379,7 +379,7 @@ int main (int argc, char **argv) { - g_test_init (&argc, &argv, NULL); + test_init (&argc, &argv); g_test_add ("/corrupt/tcp", Fixture, "tcp:host=127.0.0.1", setup, test_corrupt, teardown); diff --git a/test/data/valid-config-files/forbidding.conf.in b/test/data/valid-config-files/forbidding.conf.in new file mode 100644 index 00000000..6a674f88 --- /dev/null +++ b/test/data/valid-config-files/forbidding.conf.in @@ -0,0 +1,18 @@ +<!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>@TEST_LISTEN@</listen> + + <policy context="default"> + <!-- Allow everything --> + <allow send_destination="*"/> + <allow receive_sender="*"/> + <allow own="*"/> + + <!-- Exception: some messages are forbidden --> + <deny send_interface="com.example.CannotSend"/> + <deny receive_interface="com.example.CannotReceive"/> + </policy> +</busconfig> diff --git a/test/dbus-daemon-eavesdrop.c b/test/dbus-daemon-eavesdrop.c index 686ccb35..41985787 100644 --- a/test/dbus-daemon-eavesdrop.c +++ b/test/dbus-daemon-eavesdrop.c @@ -413,8 +413,7 @@ int main (int argc, char **argv) { - g_test_init (&argc, &argv, NULL); - g_test_bug_base ("https://bugs.freedesktop.org/show_bug.cgi?id="); + test_init (&argc, &argv); g_test_add ("/eavedrop/match_keyword/broadcast", Fixture, NULL, setup, test_eavesdrop_broadcast, teardown); diff --git a/test/dbus-daemon.c b/test/dbus-daemon.c index 02590904..6b0e9b8a 100644 --- a/test/dbus-daemon.c +++ b/test/dbus-daemon.c @@ -608,8 +608,7 @@ int main (int argc, char **argv) { - g_test_init (&argc, &argv, NULL); - g_test_bug_base ("https://bugs.freedesktop.org/show_bug.cgi?id="); + test_init (&argc, &argv); g_test_add ("/echo/session", Fixture, NULL, setup, test_echo, teardown); g_test_add ("/echo/limited", Fixture, &limited_config, diff --git a/test/fdpass.c b/test/fdpass.c new file mode 100644 index 00000000..fa958da8 --- /dev/null +++ b/test/fdpass.c @@ -0,0 +1,852 @@ +/* + * Copyright © 2010-2012 Nokia Corporation + * Copyright © 2014 Collabora Ltd. + * + * 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 <config.h> + +#include <dbus/dbus.h> +#include <dbus/dbus-internals.h> +#include <dbus/dbus-sysdeps.h> + +#include <glib.h> + +#include <string.h> + +#ifdef G_OS_UNIX +# include <dbus/dbus-sysdeps-unix.h> + +# include <errno.h> +# include <fcntl.h> +# ifdef HAVE_SYS_RESOURCE_H +# include <sys/resource.h> +# endif +# include <sys/stat.h> +# include <sys/time.h> +# include <sys/types.h> +# include <unistd.h> +#endif + +#include "test-utils-glib.h" + +/* Arbitrary; included here to avoid relying on the default */ +#define MAX_MESSAGE_UNIX_FDS 20 +/* This test won't work on Linux unless this is true. */ +_DBUS_STATIC_ASSERT (MAX_MESSAGE_UNIX_FDS <= 253); + +/* Arbitrary; included here to avoid relying on the default. */ +#define MAX_INCOMING_UNIX_FDS (MAX_MESSAGE_UNIX_FDS * 4) + +/* Arbitrary, except that MAX_MESSAGE_UNIX_FDS * SOME_MESSAGES must be + * less than the process's file descriptor limit. */ +#define SOME_MESSAGES 50 + +/* Linux won't allow more than 253 fds per sendmsg(). */ +#define TOO_MANY_FDS 255 +_DBUS_STATIC_ASSERT (MAX_MESSAGE_UNIX_FDS < TOO_MANY_FDS); + +/* As in test/relay.c, this is a miniature dbus-daemon: we relay messages + * from the client on the left to the client on the right. + * + * left socket left dispatch right socket right + * client ===========> server --------------> server ===========> client + * conn conn conn conn + */ + +typedef struct { + TestMainContext *ctx; + DBusError e; + + DBusServer *server; + + DBusConnection *left_client_conn; + DBusConnection *left_server_conn; + + DBusConnection *right_server_conn; + DBusConnection *right_client_conn; + /* queue of DBusMessage received by right_client_conn */ + GQueue messages; + + int fd_before; +} Fixture; + +#if !GLIB_CHECK_VERSION (2, 38, 0) +#define g_test_skip(s) my_test_skip (s) +static inline void my_test_skip (const gchar *s) +{ + g_message ("SKIP: %s", s); +} +#endif + +#ifdef HAVE_UNIX_FD_PASSING + +static void oom (const gchar *doing) G_GNUC_NORETURN; + +static void +oom (const gchar *doing) +{ + g_error ("out of memory (%s)", doing); +} + +static void +assert_no_error (const DBusError *e) +{ + if (G_UNLIKELY (dbus_error_is_set (e))) + g_error ("expected success but got error: %s: %s", e->name, e->message); +} + +static DBusHandlerResult +left_server_message_cb (DBusConnection *server_conn, + DBusMessage *message, + void *data) +{ + Fixture *f = data; + + g_assert (server_conn == f->left_server_conn); + g_assert (f->right_server_conn != NULL); + + dbus_connection_send (f->right_server_conn, message, NULL); + + return DBUS_HANDLER_RESULT_HANDLED; +} + +static DBusHandlerResult +right_client_message_cb (DBusConnection *client_conn, + DBusMessage *message, + void *data) +{ + Fixture *f = data; + + g_assert (client_conn == f->right_client_conn); + g_queue_push_tail (&f->messages, dbus_message_ref (message)); + + return DBUS_HANDLER_RESULT_HANDLED; +} + +static void +new_conn_cb (DBusServer *server, + DBusConnection *server_conn, + void *data) +{ + Fixture *f = data; + + dbus_connection_set_max_message_unix_fds (server_conn, + MAX_MESSAGE_UNIX_FDS); + dbus_connection_set_max_received_unix_fds (server_conn, + MAX_INCOMING_UNIX_FDS); + + if (f->left_server_conn == NULL) + { + f->left_server_conn = dbus_connection_ref (server_conn); + + if (!dbus_connection_add_filter (server_conn, + left_server_message_cb, f, NULL)) + oom ("adding filter"); + } + else + { + g_assert (f->right_server_conn == NULL); + f->right_server_conn = dbus_connection_ref (server_conn); + } + + test_connection_setup (f->ctx, server_conn); +} + +static void +test_connect (Fixture *f, + gconstpointer data G_GNUC_UNUSED) +{ + char *address; + + g_assert (f->left_server_conn == NULL); + g_assert (f->right_server_conn == NULL); + + address = dbus_server_get_address (f->server); + g_assert (address != NULL); + + f->left_client_conn = dbus_connection_open_private (address, &f->e); + assert_no_error (&f->e); + g_assert (f->left_client_conn != NULL); + test_connection_setup (f->ctx, f->left_client_conn); + + /* The left client connection is allowed to behave abusively. */ + dbus_connection_set_max_message_unix_fds (f->left_client_conn, 1000); + dbus_connection_set_max_received_unix_fds (f->left_client_conn, 1000000); + + while (f->left_server_conn == NULL) + { + g_print ("."); + test_main_context_iterate (f->ctx, TRUE); + } + + f->right_client_conn = dbus_connection_open_private (address, &f->e); + assert_no_error (&f->e); + g_assert (f->right_client_conn != NULL); + test_connection_setup (f->ctx, f->right_client_conn); + + dbus_free (address); + + while (f->right_server_conn == NULL) + { + g_print ("."); + test_main_context_iterate (f->ctx, TRUE); + } + + if (!dbus_connection_add_filter (f->right_client_conn, + right_client_message_cb, f, NULL)) + oom ("adding filter"); + + /* The right client connection is allowed to queue all the messages. */ + dbus_connection_set_max_message_unix_fds (f->right_client_conn, 1000); + dbus_connection_set_max_received_unix_fds (f->right_client_conn, 1000000); + + while (!dbus_connection_get_is_authenticated (f->left_client_conn) || + !dbus_connection_get_is_authenticated (f->right_client_conn) || + !dbus_connection_get_is_authenticated (f->left_server_conn) || + !dbus_connection_get_is_authenticated (f->right_server_conn)) + { + g_printerr ("*"); + test_main_context_iterate (f->ctx, TRUE); + } + + if (!dbus_connection_can_send_type (f->left_client_conn, + DBUS_TYPE_UNIX_FD)) + g_error ("left client connection cannot send Unix fds"); + + if (!dbus_connection_can_send_type (f->left_server_conn, + DBUS_TYPE_UNIX_FD)) + g_error ("left server connection cannot send Unix fds"); + + if (!dbus_connection_can_send_type (f->right_client_conn, + DBUS_TYPE_UNIX_FD)) + g_error ("right client connection cannot send Unix fds"); + + if (!dbus_connection_can_send_type (f->right_server_conn, + DBUS_TYPE_UNIX_FD)) + g_error ("right server connection cannot send Unix fds"); +} +#endif + +static void +setup (Fixture *f, + gconstpointer data G_GNUC_UNUSED) +{ +#ifdef HAVE_UNIX_FD_PASSING + /* We assume that anything with fd-passing supports the unix: transport */ + + f->ctx = test_main_context_get (); + dbus_error_init (&f->e); + g_queue_init (&f->messages); + + f->server = dbus_server_listen ("unix:tmpdir=/tmp", &f->e); + assert_no_error (&f->e); + g_assert (f->server != NULL); + + dbus_server_set_new_connection_function (f->server, + new_conn_cb, f, NULL); + test_server_setup (f->ctx, f->server); + + f->fd_before = open ("/dev/null", O_RDONLY); + + /* this should succeed on any reasonable Unix */ + if (f->fd_before < 0) + g_error ("cannot open /dev/null for reading: %s", g_strerror (errno)); + + _dbus_fd_set_close_on_exec (f->fd_before); +#endif +} + +static void +test_relay (Fixture *f, + gconstpointer data) +{ +#ifdef HAVE_UNIX_FD_PASSING + /* We assume that any platform with working fd-passing is POSIX, + * and therefore has open() and fstat() */ + dbus_uint32_t serial; + DBusMessage *outgoing, *incoming; + int fd_after; + struct stat stat_before; + struct stat stat_after; + + test_connect (f, data); + + outgoing = dbus_message_new_signal ("/com/example/Hello", + "com.example.Hello", "Greeting"); + g_assert (outgoing != NULL); + + if (!dbus_message_append_args (outgoing, + DBUS_TYPE_UNIX_FD, &f->fd_before, + DBUS_TYPE_INVALID)) + oom ("appending fd"); + + if (!dbus_connection_send (f->left_client_conn, outgoing, &serial)) + oom ("sending message"); + + dbus_message_unref (outgoing); + + while (g_queue_get_length (&f->messages) < 1) + { + g_print ("."); + test_main_context_iterate (f->ctx, TRUE); + } + + g_assert_cmpuint (g_queue_get_length (&f->messages), ==, 1); + + incoming = g_queue_pop_head (&f->messages); + + g_assert (dbus_message_contains_unix_fds (incoming)); + g_assert_cmpstr (dbus_message_get_destination (incoming), ==, NULL); + g_assert_cmpstr (dbus_message_get_error_name (incoming), ==, NULL); + g_assert_cmpstr (dbus_message_get_interface (incoming), ==, + "com.example.Hello"); + g_assert_cmpstr (dbus_message_get_member (incoming), ==, "Greeting"); + g_assert_cmpstr (dbus_message_get_sender (incoming), ==, NULL); + g_assert_cmpstr (dbus_message_get_signature (incoming), ==, + DBUS_TYPE_UNIX_FD_AS_STRING); + g_assert_cmpstr (dbus_message_get_path (incoming), ==, "/com/example/Hello"); + g_assert_cmpuint (dbus_message_get_serial (incoming), ==, serial); + + if (!dbus_message_get_args (incoming, + &f->e, + DBUS_TYPE_UNIX_FD, &fd_after, + DBUS_TYPE_INVALID)) + g_error ("%s: %s", f->e.name, f->e.message); + + assert_no_error (&f->e); + + if (fstat (f->fd_before, &stat_before) < 0) + g_error ("%s", g_strerror (errno)); + + if (fstat (fd_after, &stat_after) < 0) + g_error ("%s", g_strerror (errno)); + + /* this seems like enough to say "it's the same file" */ + g_assert_cmpint (stat_before.st_dev, ==, stat_after.st_dev); + g_assert_cmpint (stat_before.st_ino, ==, stat_after.st_ino); + g_assert_cmpint (stat_before.st_rdev, ==, stat_after.st_rdev); + + dbus_message_unref (incoming); + + if (close (fd_after) < 0) + g_error ("%s", g_strerror (errno)); + + g_assert (dbus_connection_get_is_connected (f->right_client_conn)); + g_assert (dbus_connection_get_is_connected (f->right_server_conn)); + g_assert (dbus_connection_get_is_connected (f->left_client_conn)); + g_assert (dbus_connection_get_is_connected (f->left_server_conn)); +#else + g_test_skip ("fd-passing not supported on this platform"); +#endif +} + +static void +test_limit (Fixture *f, + gconstpointer data) +{ +#ifdef HAVE_UNIX_FD_PASSING + dbus_uint32_t serial; + DBusMessage *outgoing, *incoming; + int i; + + test_connect (f, data); + + outgoing = dbus_message_new_signal ("/com/example/Hello", + "com.example.Hello", "Greeting"); + g_assert (outgoing != NULL); + + for (i = 0; i < MAX_MESSAGE_UNIX_FDS; i++) + { + if (!dbus_message_append_args (outgoing, + DBUS_TYPE_UNIX_FD, &f->fd_before, + DBUS_TYPE_INVALID)) + oom ("appending fd"); + } + + if (!dbus_connection_send (f->left_client_conn, outgoing, &serial)) + oom ("sending message"); + + dbus_message_unref (outgoing); + + while (g_queue_get_length (&f->messages) < 1) + { + g_print ("."); + test_main_context_iterate (f->ctx, TRUE); + } + + g_assert_cmpuint (g_queue_get_length (&f->messages), ==, 1); + + incoming = g_queue_pop_head (&f->messages); + + g_assert (dbus_message_contains_unix_fds (incoming)); + g_assert_cmpstr (dbus_message_get_destination (incoming), ==, NULL); + g_assert_cmpstr (dbus_message_get_error_name (incoming), ==, NULL); + g_assert_cmpstr (dbus_message_get_interface (incoming), ==, + "com.example.Hello"); + g_assert_cmpstr (dbus_message_get_member (incoming), ==, "Greeting"); + g_assert_cmpstr (dbus_message_get_sender (incoming), ==, NULL); + g_assert_cmpstr (dbus_message_get_path (incoming), ==, "/com/example/Hello"); + g_assert_cmpuint (dbus_message_get_serial (incoming), ==, serial); + + dbus_message_unref (incoming); + + g_assert (dbus_connection_get_is_connected (f->right_client_conn)); + g_assert (dbus_connection_get_is_connected (f->right_server_conn)); + g_assert (dbus_connection_get_is_connected (f->left_client_conn)); + g_assert (dbus_connection_get_is_connected (f->left_server_conn)); +#else + g_test_skip ("fd-passing not supported on this platform"); +#endif +} + +static void +test_too_many (Fixture *f, + gconstpointer data) +{ +#ifdef HAVE_UNIX_FD_PASSING + DBusMessage *outgoing; + int i; + + test_connect (f, data); + + outgoing = dbus_message_new_signal ("/com/example/Hello", + "com.example.Hello", "Greeting"); + g_assert (outgoing != NULL); + + for (i = 0; i < MAX_MESSAGE_UNIX_FDS + GPOINTER_TO_UINT (data); i++) + { + if (!dbus_message_append_args (outgoing, + DBUS_TYPE_UNIX_FD, &f->fd_before, + DBUS_TYPE_INVALID)) + oom ("appending fd"); + } + + if (!dbus_connection_send (f->left_client_conn, outgoing, NULL)) + oom ("sending message"); + + dbus_message_unref (outgoing); + + /* The sender is unceremoniously disconnected. */ + while (dbus_connection_get_is_connected (f->left_client_conn) || + dbus_connection_get_is_connected (f->left_server_conn)) + { + g_print ("."); + test_main_context_iterate (f->ctx, TRUE); + } + + /* The message didn't get through without its fds. */ + g_assert_cmpuint (g_queue_get_length (&f->messages), ==, 0); + + /* The intended victim is unaffected by the left connection's + * misbehaviour. */ + g_assert (dbus_connection_get_is_connected (f->right_client_conn)); + g_assert (dbus_connection_get_is_connected (f->right_server_conn)); +#else + g_test_skip ("fd-passing not supported on this platform"); +#endif +} + +static void +test_too_many_split (Fixture *f, + gconstpointer data) +{ +#ifdef HAVE_UNIX_FD_PASSING + DBusMessage *outgoing; + int i; + int left_client_socket; + char *payload; + int payload_len; + DBusString buffer; + int fds[TOO_MANY_FDS]; + int done; + + /* This test deliberately pushes up against OS limits, so skip it + * if we don't have enough fds. 4 times the maximum per message + * ought to be enough: that will cover the message, the dup'd fds + * we actually send, the copy that we potentially receive, and some + * spare capacity for everything else. */ +#ifdef HAVE_GETRLIMIT + struct rlimit lim; + + if (getrlimit (RLIMIT_NOFILE, &lim) == 0) + { + if (lim.rlim_cur != RLIM_INFINITY && + lim.rlim_cur < 4 * TOO_MANY_FDS) + { + g_test_skip ("not enough RLIMIT_NOFILE"); + return; + } + } +#endif + + test_connect (f, data); + + outgoing = dbus_message_new_signal ("/com/example/Hello", + "com.example.Hello", "Greeting"); + g_assert (outgoing != NULL); + + /* TOO_MANY_FDS fds are far too many: in particular, Linux doesn't allow + * sending this many in a single sendmsg(). libdbus never splits + * a message between two sendmsg() calls if it can help it, and + * in particular it always sends all the fds with the first sendmsg(), + * but malicious senders might not be so considerate. */ + for (i = 0; i < TOO_MANY_FDS; i++) + { + if (!dbus_message_append_args (outgoing, + DBUS_TYPE_UNIX_FD, &f->fd_before, + DBUS_TYPE_INVALID)) + oom ("appending fd"); + } + + /* This probably shouldn't work for messages with fds, but it does, + * which is convenient for this sort of trickery. */ + if (!dbus_message_marshal (outgoing, &payload, &payload_len)) + oom ("marshalling message"); + + _dbus_string_init_const_len (&buffer, payload, payload_len); + + for (i = 0; i < TOO_MANY_FDS; i++) + { + fds[i] = dup (f->fd_before); + + if (fds[i] < 0) + g_error ("could not dup fd: %s", g_strerror (errno)); + } + + /* This is blatant cheating, and the API documentation specifically + * tells you not use this function in this way. Never do this + * in application code. */ + if (!dbus_connection_get_socket (f->left_client_conn, &left_client_socket)) + g_error ("'unix:' DBusConnection should have had a socket"); + + /* Just to be sure that we're at a message boundary. */ + dbus_connection_flush (f->left_client_conn); + + /* We have too many fds for one sendmsg(), so send the first half + * (rounding down if odd) with the first byte... */ + done = _dbus_write_socket_with_unix_fds (left_client_socket, &buffer, 0, 1, + &fds[0], TOO_MANY_FDS / 2); + + if (done < 0) + g_error ("could not send first byte and first batch of fds: %s", + g_strerror (errno)); + + /* ... and the second half (rounding up if odd) with the rest of + * the message */ + done = _dbus_write_socket_with_unix_fds (left_client_socket, &buffer, 1, + payload_len - 1, &fds[TOO_MANY_FDS / 2], + TOO_MANY_FDS - (TOO_MANY_FDS / 2)); + + if (done < 0) + { + g_error ("could not send rest of message and rest of fds: %s", + g_strerror (errno)); + } + else if (done < payload_len - 1) + { + /* For simplicity, assume the socket buffer is big enough for the + * whole message, which should be < 2 KiB. If this fails on some + * OS, redo this test code to use a proper loop like the real + * libdbus does. */ + g_error ("short write in sendmsg(), fix this test: %d/%d", + done, payload_len - 1); + } + + dbus_free (payload); + + for (i = 0; i < TOO_MANY_FDS; i++) + close (fds[i]); + + dbus_message_unref (outgoing); + + /* The sender is unceremoniously disconnected. */ + while (dbus_connection_get_is_connected (f->left_client_conn) || + dbus_connection_get_is_connected (f->left_server_conn)) + { + g_print ("."); + test_main_context_iterate (f->ctx, TRUE); + } + + /* The message didn't get through without its fds. */ + g_assert_cmpuint (g_queue_get_length (&f->messages), ==, 0); + + /* The intended victim is unaffected by the left connection's + * misbehaviour. */ + g_assert (dbus_connection_get_is_connected (f->right_client_conn)); + g_assert (dbus_connection_get_is_connected (f->right_server_conn)); +#else + g_test_skip ("fd-passing not supported on this platform"); +#endif +} + +static void +test_flood (Fixture *f, + gconstpointer data) +{ +#ifdef HAVE_UNIX_FD_PASSING + int i, j; + DBusMessage *outgoing[SOME_MESSAGES]; + dbus_uint32_t serial; + + test_connect (f, data); + + for (j = 0; j < SOME_MESSAGES; j++) + { + outgoing[j] = dbus_message_new_signal ("/com/example/Hello", + "com.example.Hello", "Greeting"); + g_assert (outgoing[j] != NULL); + + for (i = 0; i < GPOINTER_TO_UINT (data); i++) + { + if (!dbus_message_append_args (outgoing[j], + DBUS_TYPE_UNIX_FD, &f->fd_before, + DBUS_TYPE_INVALID)) + oom ("appending fd"); + } + } + + /* This is in its own loop so we do it as fast as possible */ + for (j = 0; j < SOME_MESSAGES; j++) + { + if (!dbus_connection_send (f->left_client_conn, outgoing[j], &serial)) + oom ("sending message"); + } + + for (j = 0; j < SOME_MESSAGES; j++) + { + dbus_message_unref (outgoing[j]); + } + + while (g_queue_get_length (&f->messages) < SOME_MESSAGES) + { + g_print ("."); + test_main_context_iterate (f->ctx, TRUE); + } + + g_assert_cmpuint (g_queue_get_length (&f->messages), ==, SOME_MESSAGES); + + for (j = 0; j < SOME_MESSAGES; j++) + { + DBusMessage *incoming; + + incoming = g_queue_pop_head (&f->messages); + + g_assert (dbus_message_contains_unix_fds (incoming)); + g_assert_cmpstr (dbus_message_get_destination (incoming), ==, NULL); + g_assert_cmpstr (dbus_message_get_error_name (incoming), ==, NULL); + g_assert_cmpstr (dbus_message_get_interface (incoming), ==, + "com.example.Hello"); + g_assert_cmpstr (dbus_message_get_member (incoming), ==, "Greeting"); + g_assert_cmpstr (dbus_message_get_sender (incoming), ==, NULL); + g_assert_cmpstr (dbus_message_get_path (incoming), ==, "/com/example/Hello"); + + dbus_message_unref (incoming); + } + + g_assert (dbus_connection_get_is_connected (f->right_client_conn)); + g_assert (dbus_connection_get_is_connected (f->right_server_conn)); + g_assert (dbus_connection_get_is_connected (f->left_client_conn)); + g_assert (dbus_connection_get_is_connected (f->left_server_conn)); +#else + g_test_skip ("fd-passing not supported on this platform"); +#endif +} + +static void +test_odd_limit (Fixture *f, + gconstpointer data) +{ +#ifdef HAVE_UNIX_FD_PASSING + DBusMessage *outgoing; + int i; + + test_connect (f, data); + dbus_connection_set_max_message_unix_fds (f->left_server_conn, 7); + dbus_connection_set_max_message_unix_fds (f->right_server_conn, 7); + + outgoing = dbus_message_new_signal ("/com/example/Hello", + "com.example.Hello", "Greeting"); + g_assert (outgoing != NULL); + + for (i = 0; i < 7 + GPOINTER_TO_INT (data); i++) + { + if (!dbus_message_append_args (outgoing, + DBUS_TYPE_UNIX_FD, &f->fd_before, + DBUS_TYPE_INVALID)) + oom ("appending fd"); + } + + if (!dbus_connection_send (f->left_client_conn, outgoing, NULL)) + oom ("sending message"); + + dbus_message_unref (outgoing); + + if (GPOINTER_TO_INT (data) > 0) + { + /* The sender is unceremoniously disconnected. */ + while (dbus_connection_get_is_connected (f->left_client_conn) || + dbus_connection_get_is_connected (f->left_server_conn)) + { + g_print ("."); + test_main_context_iterate (f->ctx, TRUE); + } + + /* The message didn't get through without its fds. */ + g_assert_cmpuint (g_queue_get_length (&f->messages), ==, 0); + + /* The intended victim is unaffected by the left connection's + * misbehaviour. */ + g_assert (dbus_connection_get_is_connected (f->right_client_conn)); + g_assert (dbus_connection_get_is_connected (f->right_server_conn)); + } + else + { + DBusMessage *incoming; + + /* We're at or under the limit. The message gets through intact. */ + while (g_queue_get_length (&f->messages) < 1) + { + g_print ("."); + test_main_context_iterate (f->ctx, TRUE); + } + + g_assert_cmpuint (g_queue_get_length (&f->messages), ==, 1); + + incoming = g_queue_pop_head (&f->messages); + + g_assert (dbus_message_contains_unix_fds (incoming)); + g_assert_cmpstr (dbus_message_get_destination (incoming), ==, NULL); + g_assert_cmpstr (dbus_message_get_error_name (incoming), ==, NULL); + g_assert_cmpstr (dbus_message_get_interface (incoming), ==, + "com.example.Hello"); + g_assert_cmpstr (dbus_message_get_member (incoming), ==, "Greeting"); + g_assert_cmpstr (dbus_message_get_sender (incoming), ==, NULL); + g_assert_cmpstr (dbus_message_get_path (incoming), ==, + "/com/example/Hello"); + + dbus_message_unref (incoming); + + g_assert (dbus_connection_get_is_connected (f->right_client_conn)); + g_assert (dbus_connection_get_is_connected (f->right_server_conn)); + g_assert (dbus_connection_get_is_connected (f->left_client_conn)); + g_assert (dbus_connection_get_is_connected (f->left_server_conn)); + } +#else + g_test_skip ("fd-passing not supported on this platform"); +#endif +} + +static void +teardown (Fixture *f, + gconstpointer data G_GNUC_UNUSED) +{ +#ifdef HAVE_UNIX_FD_PASSING + if (f->left_client_conn != NULL) + { + dbus_connection_close (f->left_client_conn); + dbus_connection_unref (f->left_client_conn); + f->left_client_conn = NULL; + } + + if (f->right_client_conn != NULL) + { + dbus_connection_close (f->right_client_conn); + dbus_connection_unref (f->right_client_conn); + f->right_client_conn = NULL; + } + + if (f->left_server_conn != NULL) + { + dbus_connection_close (f->left_server_conn); + dbus_connection_unref (f->left_server_conn); + f->left_server_conn = NULL; + } + + if (f->right_server_conn != NULL) + { + dbus_connection_close (f->right_server_conn); + dbus_connection_unref (f->right_server_conn); + f->right_server_conn = NULL; + } + + if (f->server != NULL) + { + dbus_server_disconnect (f->server); + dbus_server_unref (f->server); + f->server = NULL; + } + + test_main_context_unref (f->ctx); + + if (f->fd_before >= 0 && close (f->fd_before) < 0) + g_error ("%s", g_strerror (errno)); +#endif +} + +int +main (int argc, + char **argv) +{ + test_init (&argc, &argv); + + g_test_add ("/relay", Fixture, NULL, setup, + test_relay, teardown); + g_test_add ("/limit", Fixture, NULL, setup, + test_limit, teardown); + + g_test_add ("/too-many/plus1", Fixture, GUINT_TO_POINTER (1), setup, + test_too_many, teardown); + g_test_add ("/too-many/plus2", Fixture, GUINT_TO_POINTER (2), setup, + test_too_many, teardown); + g_test_add ("/too-many/plus17", Fixture, GUINT_TO_POINTER (17), setup, + test_too_many, teardown); + + g_test_add ("/too-many/split", Fixture, NULL, setup, + test_too_many_split, teardown); + + g_test_add ("/flood/1", Fixture, GUINT_TO_POINTER (1), + setup, test_flood, teardown); +#if MAX_MESSAGE_UNIX_FDS >= 2 + g_test_add ("/flood/half-limit", Fixture, + GUINT_TO_POINTER (MAX_MESSAGE_UNIX_FDS / 2), + setup, test_flood, teardown); +#endif +#if MAX_MESSAGE_UNIX_FDS >= 4 + g_test_add ("/flood/over-half-limit", Fixture, + GUINT_TO_POINTER (3 * MAX_MESSAGE_UNIX_FDS / 4), + setup, test_flood, teardown); +#endif + g_test_add ("/flood/limit", Fixture, + GUINT_TO_POINTER (MAX_MESSAGE_UNIX_FDS), setup, test_flood, teardown); + + g_test_add ("/odd-limit/minus1", Fixture, GINT_TO_POINTER (-1), setup, + test_odd_limit, teardown); + g_test_add ("/odd-limit/at", Fixture, GINT_TO_POINTER (0), setup, + test_odd_limit, teardown); + g_test_add ("/odd-limit/plus1", Fixture, GINT_TO_POINTER (+1), setup, + test_odd_limit, teardown); + g_test_add ("/odd-limit/plus2", Fixture, GINT_TO_POINTER (+2), setup, + test_odd_limit, teardown); + + return g_test_run (); +} diff --git a/test/internals/refs.c b/test/internals/refs.c index 85cb3bc0..7eae44e1 100644 --- a/test/internals/refs.c +++ b/test/internals/refs.c @@ -35,7 +35,7 @@ #include <dbus/dbus-message-internal.h> #include <dbus/dbus-pending-call-internal.h> #include <dbus/dbus-server-protected.h> -#include "test-utils.h" +#include "test-utils-glib.h" static void assert_no_error (const DBusError *e) @@ -585,8 +585,7 @@ int main (int argc, char **argv) { - g_test_init (&argc, &argv, NULL); - g_test_bug_base ("https://bugs.freedesktop.org/show_bug.cgi?id="); + test_init (&argc, &argv); g_test_add ("/refs/connection", Fixture, NULL, setup_connection, test_connection, teardown); diff --git a/test/internals/syslog.c b/test/internals/syslog.c index 80a0cebb..805c5784 100644 --- a/test/internals/syslog.c +++ b/test/internals/syslog.c @@ -33,6 +33,8 @@ #include <dbus/dbus.h> #include <dbus/dbus-sysdeps.h> +#include "test-utils-glib.h" + typedef struct { int dummy; } Fixture; @@ -93,8 +95,7 @@ int main (int argc, char **argv) { - g_test_init (&argc, &argv, NULL); - g_test_bug_base ("https://bugs.freedesktop.org/show_bug.cgi?id="); + test_init (&argc, &argv); g_test_add ("/syslog", Fixture, NULL, setup, test_syslog, teardown); diff --git a/test/loopback.c b/test/loopback.c index 7526d8d2..eeb0d65d 100644 --- a/test/loopback.c +++ b/test/loopback.c @@ -32,7 +32,7 @@ #include <string.h> -#include "test-utils.h" +#include "test-utils-glib.h" typedef struct { TestMainContext *ctx; @@ -255,8 +255,7 @@ int main (int argc, char **argv) { - g_test_init (&argc, &argv, NULL); - g_test_bug_base ("https://bugs.freedesktop.org/show_bug.cgi?id="); + test_init (&argc, &argv); g_test_add ("/connect/tcp", Fixture, "tcp:host=127.0.0.1", setup, test_connect, teardown); diff --git a/test/marshal.c b/test/marshal.c index d74e7671..3353ec00 100644 --- a/test/marshal.c +++ b/test/marshal.c @@ -31,6 +31,8 @@ #include <dbus/dbus.h> +#include "test-utils-glib.h" + typedef struct { DBusError e; } Fixture; @@ -248,7 +250,7 @@ main (int argc, char *aligned_le_blob; char *aligned_be_blob; - g_test_init (&argc, &argv, NULL); + test_init (&argc, &argv); /* We have to pass in a buffer that's at least "default aligned", * i.e. on GNU systems to 8 or 16. The linker may have only given diff --git a/test/monitor.c b/test/monitor.c new file mode 100644 index 00000000..32b7b5dd --- /dev/null +++ b/test/monitor.c @@ -0,0 +1,1496 @@ +/* Integration tests for monitor-mode D-Bus connections + * + * Copyright © 2010-2011 Nokia Corporation + * Copyright © 2015 Collabora Ltd. + * + * 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 <config.h> + +#include <string.h> + +#include "test-utils-glib.h" + +typedef struct { + const char *config_file; + const char * const *match_rules; + gboolean care_about_our_names; +} Config; + +typedef struct { + const Config *config; + TestMainContext *ctx; + DBusError e; + GError *ge; + + gchar *address; + GPid daemon_pid; + + DBusConnection *monitor; + DBusConnection *sender; + DBusConnection *recipient; + + GQueue monitored; + + const char *monitor_name; + const char *sender_name; + const char *recipient_name; + + DBusConnection *systemd; + const char *systemd_name; + DBusMessage *systemd_message; + DBusConnection *activated; + const char *activated_name; + DBusMessage *activated_message; +} Fixture; + +static const char * const no_match_rules[] = { + NULL +}; + +static const char * const wildcard_match_rules[] = { + "", + NULL, + FALSE +}; + +static const char * const eavesdrop_match_rules[] = { + "eavesdrop=true", + NULL, + FALSE +}; + +static const char * const no_eavesdrop_match_rules[] = { + "eavesdrop=false", + NULL, + FALSE +}; + +static const char * const selective_match_rules[] = { + "interface='com.example.Interesting'", + "interface='com.example.Fun'", + NULL, + FALSE +}; + +static Config forbidding_config = { + "valid-config-files/forbidding.conf", + NULL, + FALSE +}; + +static Config wildcard_config = { + NULL, + wildcard_match_rules, + FALSE +}; + +static Config selective_config = { + NULL, + selective_match_rules, + FALSE +}; + +static Config no_rules_config = { + NULL, + no_match_rules, + FALSE +}; + +static Config eavesdrop_config = { + NULL, + eavesdrop_match_rules, + FALSE +}; + +static Config no_eavesdrop_config = { + NULL, + no_eavesdrop_match_rules, + FALSE +}; + +static Config fake_systemd_config = { + "valid-config-files/systemd-activation.conf", + NULL, + FALSE +}; + +static Config side_effects_config = { + NULL, + NULL, + TRUE +}; + +static inline const char * +not_null2 (const char *x, + const char *fallback) +{ + if (x == NULL) + return fallback; + + return x; +} + +static inline const char * +not_null (const char *x) +{ + return not_null2 (x, "(null)"); +} + +#define log_message(m) _log_message (m, __FILE__, __LINE__) + +G_GNUC_UNUSED +static void +_log_message (DBusMessage *m, + const char *file, + int line) +{ + g_message ("%s:%d: message type %d (%s)", file, line, + dbus_message_get_type (m), + dbus_message_type_to_string (dbus_message_get_type (m))); + g_message ("\tfrom: %s", + not_null2 (dbus_message_get_sender (m), "(dbus-daemon)")); + g_message ("\tto: %s", + not_null2 (dbus_message_get_destination (m), "(broadcast)")); + g_message ("\tpath: %s", + not_null (dbus_message_get_path (m))); + g_message ("\tinterface: %s", + not_null (dbus_message_get_interface (m))); + g_message ("\tmember: %s", + not_null (dbus_message_get_member (m))); + g_message ("\tsignature: %s", + not_null (dbus_message_get_signature (m))); + g_message ("\terror name: %s", + not_null (dbus_message_get_error_name (m))); + + if (strcmp ("s", dbus_message_get_signature (m)) == 0) + { + DBusError e = DBUS_ERROR_INIT; + const char *s; + + dbus_message_get_args (m, &e, + DBUS_TYPE_STRING, &s, + DBUS_TYPE_INVALID); + test_assert_no_error (&e); + g_message ("\tstring payload: %s", s); + } +} + +/* these are macros so they get the right line number */ + +#define assert_hello(m) \ +do { \ + g_assert_cmpstr (dbus_message_type_to_string (dbus_message_get_type (m)), \ + ==, dbus_message_type_to_string (DBUS_MESSAGE_TYPE_METHOD_CALL)); \ + g_assert_cmpstr (dbus_message_get_destination (m), ==, DBUS_SERVICE_DBUS); \ + g_assert_cmpstr (dbus_message_get_path (m), ==, DBUS_PATH_DBUS); \ + g_assert_cmpstr (dbus_message_get_interface (m), ==, DBUS_INTERFACE_DBUS); \ + g_assert_cmpstr (dbus_message_get_member (m), ==, "Hello"); \ + g_assert_cmpstr (dbus_message_get_signature (m), ==, ""); \ + g_assert_cmpint (dbus_message_get_serial (m), !=, 0); \ + g_assert_cmpint (dbus_message_get_reply_serial (m), ==, 0); \ +} while (0) + +#define assert_hello_reply(m) \ +do { \ + DBusError _e = DBUS_ERROR_INIT; \ + const char *_s; \ + \ + g_assert_cmpstr (dbus_message_type_to_string (dbus_message_get_type (m)), \ + ==, dbus_message_type_to_string (DBUS_MESSAGE_TYPE_METHOD_RETURN)); \ + g_assert_cmpstr (dbus_message_get_sender (m), ==, DBUS_SERVICE_DBUS); \ + g_assert_cmpstr (dbus_message_get_path (m), ==, NULL); \ + g_assert_cmpstr (dbus_message_get_interface (m), ==, NULL); \ + g_assert_cmpstr (dbus_message_get_member (m), ==, NULL); \ + g_assert_cmpstr (dbus_message_get_signature (m), ==, "s"); \ + g_assert_cmpint (dbus_message_get_serial (m), !=, 0); \ + g_assert_cmpint (dbus_message_get_reply_serial (m), !=, 0); \ + \ + dbus_message_get_args (m, &_e, \ + DBUS_TYPE_STRING, &_s, \ + DBUS_TYPE_INVALID); \ + test_assert_no_error (&_e); \ + g_assert_cmpstr (dbus_message_get_destination (m), ==, _s); \ +} while (0) + +#define assert_name_acquired(m) \ +do { \ + DBusError _e = DBUS_ERROR_INIT; \ + const char *_s; \ + \ + g_assert_cmpstr (dbus_message_type_to_string (dbus_message_get_type (m)), \ + ==, dbus_message_type_to_string (DBUS_MESSAGE_TYPE_SIGNAL)); \ + g_assert_cmpstr (dbus_message_get_sender (m), ==, DBUS_SERVICE_DBUS); \ + g_assert_cmpstr (dbus_message_get_path (m), ==, DBUS_PATH_DBUS); \ + g_assert_cmpstr (dbus_message_get_interface (m), ==, DBUS_INTERFACE_DBUS); \ + g_assert_cmpstr (dbus_message_get_member (m), ==, "NameAcquired"); \ + g_assert_cmpstr (dbus_message_get_signature (m), ==, "s"); \ + g_assert_cmpint (dbus_message_get_serial (m), !=, 0); \ + g_assert_cmpint (dbus_message_get_reply_serial (m), ==, 0); \ + \ + dbus_message_get_args (m, &_e, \ + DBUS_TYPE_STRING, &_s, \ + DBUS_TYPE_INVALID); \ + test_assert_no_error (&_e); \ + g_assert_cmpstr (dbus_message_get_destination (m), ==, _s); \ +} while (0) + +#define assert_method_call(m, sender, \ + destination, path, iface, method, signature) \ +do { \ + g_assert_cmpstr (dbus_message_type_to_string (dbus_message_get_type (m)), \ + ==, dbus_message_type_to_string (DBUS_MESSAGE_TYPE_METHOD_CALL)); \ + g_assert_cmpstr (dbus_message_get_sender (m), ==, sender); \ + g_assert_cmpstr (dbus_message_get_destination (m), ==, destination); \ + g_assert_cmpstr (dbus_message_get_path (m), ==, path); \ + g_assert_cmpstr (dbus_message_get_interface (m), ==, iface); \ + g_assert_cmpstr (dbus_message_get_member (m), ==, method); \ + g_assert_cmpstr (dbus_message_get_signature (m), ==, signature); \ + g_assert_cmpint (dbus_message_get_serial (m), !=, 0); \ + g_assert_cmpint (dbus_message_get_reply_serial (m), ==, 0); \ +} while (0) + +#define assert_signal(m, \ + sender, path, iface, member, signature, \ + destination) \ +do { \ + g_assert_cmpstr (dbus_message_type_to_string (dbus_message_get_type (m)), \ + ==, dbus_message_type_to_string (DBUS_MESSAGE_TYPE_SIGNAL)); \ + g_assert_cmpstr (dbus_message_get_sender (m), ==, sender); \ + g_assert_cmpstr (dbus_message_get_destination (m), ==, destination); \ + g_assert_cmpstr (dbus_message_get_path (m), ==, path); \ + g_assert_cmpstr (dbus_message_get_interface (m), ==, iface); \ + g_assert_cmpstr (dbus_message_get_member (m), ==, member); \ + g_assert_cmpstr (dbus_message_get_signature (m), ==, signature); \ + g_assert_cmpint (dbus_message_get_serial (m), !=, 0); \ + g_assert_cmpint (dbus_message_get_reply_serial (m), ==, 0); \ +} while (0) + +#define assert_method_reply(m, sender, destination, signature) \ +do { \ + g_assert_cmpstr (dbus_message_type_to_string (dbus_message_get_type (m)), \ + ==, dbus_message_type_to_string (DBUS_MESSAGE_TYPE_METHOD_RETURN)); \ + g_assert_cmpstr (dbus_message_get_sender (m), ==, sender); \ + g_assert_cmpstr (dbus_message_get_destination (m), ==, destination); \ + g_assert_cmpstr (dbus_message_get_path (m), ==, NULL); \ + g_assert_cmpstr (dbus_message_get_interface (m), ==, NULL); \ + g_assert_cmpstr (dbus_message_get_member (m), ==, NULL); \ + g_assert_cmpstr (dbus_message_get_signature (m), ==, signature); \ + g_assert_cmpint (dbus_message_get_serial (m), !=, 0); \ + g_assert_cmpint (dbus_message_get_reply_serial (m), !=, 0); \ +} while (0) + +#define assert_error_reply(m, sender, destination, error_name) \ +do { \ + g_assert_cmpstr (dbus_message_type_to_string (dbus_message_get_type (m)), \ + ==, dbus_message_type_to_string (DBUS_MESSAGE_TYPE_ERROR)); \ + g_assert_cmpstr (dbus_message_get_sender (m), ==, sender); \ + g_assert_cmpstr (dbus_message_get_destination (m), ==, destination); \ + g_assert_cmpstr (dbus_message_get_error_name (m), ==, error_name); \ + g_assert_cmpstr (dbus_message_get_path (m), ==, NULL); \ + g_assert_cmpstr (dbus_message_get_interface (m), ==, NULL); \ + g_assert_cmpstr (dbus_message_get_member (m), ==, NULL); \ + g_assert_cmpstr (dbus_message_get_signature (m), ==, "s"); \ + g_assert_cmpint (dbus_message_get_serial (m), !=, 0); \ + g_assert_cmpint (dbus_message_get_reply_serial (m), !=, 0); \ +} while (0) + +/* This is called after processing pending replies to our own method + * calls, but before anything else. + */ +static DBusHandlerResult +monitor_filter (DBusConnection *connection, + DBusMessage *message, + void *user_data) +{ + Fixture *f = user_data; + + g_assert_cmpstr (dbus_message_get_interface (message), !=, + "com.example.Tedious"); + + /* we are not interested in the monitor getting NameAcquired or NameLost + * for most tests */ + if (f->config == NULL || !f->config->care_about_our_names) + { + if (dbus_message_is_signal (message, DBUS_INTERFACE_DBUS, + "NameAcquired") || + dbus_message_is_signal (message, DBUS_INTERFACE_DBUS, + "NameLost")) + { + DBusError e = DBUS_ERROR_INIT; + const char *s; + + dbus_message_get_args (message, &e, + DBUS_TYPE_STRING, &s, + DBUS_TYPE_INVALID); + test_assert_no_error (&e); + + if (strcmp (s, f->monitor_name) == 0) + { + /* ignore */ + return DBUS_HANDLER_RESULT_HANDLED; + } + } + } + + g_queue_push_tail (&f->monitored, dbus_message_ref (message)); + + return DBUS_HANDLER_RESULT_HANDLED; +} + +static DBusHandlerResult +recipient_filter (DBusConnection *connection, + DBusMessage *message, + void *user_data) +{ + g_assert_cmpstr (dbus_message_get_interface (message), !=, + "com.example.CannotSend"); + g_assert_cmpstr (dbus_message_get_interface (message), !=, + "com.example.CannotReceive"); + + return DBUS_HANDLER_RESULT_NOT_YET_HANDLED; +} + +static DBusHandlerResult +systemd_filter (DBusConnection *connection, + DBusMessage *message, + void *user_data) +{ + Fixture *f = user_data; + + if (dbus_message_is_signal (message, DBUS_INTERFACE_DBUS, + "NameAcquired") || + dbus_message_is_signal (message, DBUS_INTERFACE_DBUS, + "NameLost")) + { + return DBUS_HANDLER_RESULT_NOT_YET_HANDLED; + } + + g_assert (f->systemd_message == NULL); + f->systemd_message = dbus_message_ref (message); + + return DBUS_HANDLER_RESULT_NOT_YET_HANDLED; +} + +static DBusHandlerResult +activated_filter (DBusConnection *connection, + DBusMessage *message, + void *user_data) +{ + Fixture *f = user_data; + + if (dbus_message_is_signal (message, DBUS_INTERFACE_DBUS, + "NameAcquired") || + dbus_message_is_signal (message, DBUS_INTERFACE_DBUS, + "NameLost")) + { + return DBUS_HANDLER_RESULT_NOT_YET_HANDLED; + } + + g_assert (f->activated_message == NULL); + f->activated_message = dbus_message_ref (message); + + return DBUS_HANDLER_RESULT_NOT_YET_HANDLED; +} + +static void +setup (Fixture *f, + gconstpointer context) +{ + f->config = context; + + f->ctx = test_main_context_get (); + + f->ge = NULL; + dbus_error_init (&f->e); + + f->address = test_get_dbus_daemon (f->config ? f->config->config_file : NULL, + TEST_USER_ME, &f->daemon_pid); + + if (f->address == NULL) + return; + + f->monitor = test_connect_to_bus (f->ctx, f->address); + f->monitor_name = dbus_bus_get_unique_name (f->monitor); + f->sender = test_connect_to_bus (f->ctx, f->address); + f->sender_name = dbus_bus_get_unique_name (f->sender); + f->recipient = test_connect_to_bus (f->ctx, f->address); + f->recipient_name = dbus_bus_get_unique_name (f->recipient); + + if (!dbus_connection_add_filter (f->monitor, monitor_filter, f, NULL)) + g_error ("OOM"); + + if (!dbus_connection_add_filter (f->recipient, recipient_filter, f, NULL)) + g_error ("OOM"); +} + +static void +become_monitor (Fixture *f) +{ + DBusMessage *m; + DBusPendingCall *pc; + dbus_bool_t ok; + DBusMessageIter appender, array_appender; + const char * const *match_rules; + int i; + dbus_uint32_t zero = 0; + + if (f->config != NULL && f->config->match_rules != NULL) + match_rules = f->config->match_rules; + else + match_rules = wildcard_match_rules; + + m = dbus_message_new_method_call (DBUS_SERVICE_DBUS, + DBUS_PATH_DBUS, DBUS_INTERFACE_MONITORING, "BecomeMonitor"); + + if (m == NULL) + g_error ("OOM"); + + dbus_message_iter_init_append (m, &appender); + + if (!dbus_message_iter_open_container (&appender, DBUS_TYPE_ARRAY, "s", + &array_appender)) + g_error ("OOM"); + + for (i = 0; match_rules[i] != NULL; i++) + { + if (!dbus_message_iter_append_basic (&array_appender, DBUS_TYPE_STRING, + &match_rules[i])) + g_error ("OOM"); + } + + if (!dbus_message_iter_close_container (&appender, &array_appender) || + !dbus_message_iter_append_basic (&appender, DBUS_TYPE_UINT32, &zero)) + g_error ("OOM"); + + if (!dbus_connection_send_with_reply (f->monitor, m, &pc, + DBUS_TIMEOUT_USE_DEFAULT) || + pc == NULL) + g_error ("OOM"); + + dbus_message_unref (m); + m = NULL; + + if (dbus_pending_call_get_completed (pc)) + test_pending_call_store_reply (pc, &m); + else if (!dbus_pending_call_set_notify (pc, test_pending_call_store_reply, + &m, NULL)) + g_error ("OOM"); + + while (m == NULL) + test_main_context_iterate (f->ctx, TRUE); + + ok = dbus_message_get_args (m, &f->e, + DBUS_TYPE_INVALID); + test_assert_no_error (&f->e); + g_assert (ok); + + dbus_pending_call_unref (pc); + dbus_message_unref (m); + m = NULL; +} + +/* + * Test the side-effects of becoming a monitor. + */ +static void +test_become_monitor (Fixture *f, + gconstpointer context) +{ + DBusMessage *m; + int ret; + dbus_bool_t got_unique = FALSE, got_a = FALSE, got_b = FALSE, got_c = FALSE; + dbus_bool_t lost_unique = FALSE, lost_a = FALSE, lost_b = FALSE, lost_c = FALSE; + + if (f->address == NULL) + return; + + ret = dbus_bus_request_name (f->monitor, "com.example.A", + DBUS_NAME_FLAG_DO_NOT_QUEUE, &f->e); + test_assert_no_error (&f->e); + g_assert_cmpint (ret, ==, DBUS_REQUEST_NAME_REPLY_PRIMARY_OWNER); + + ret = dbus_bus_request_name (f->monitor, "com.example.B", + DBUS_NAME_FLAG_DO_NOT_QUEUE, &f->e); + test_assert_no_error (&f->e); + g_assert_cmpint (ret, ==, DBUS_REQUEST_NAME_REPLY_PRIMARY_OWNER); + + ret = dbus_bus_request_name (f->monitor, "com.example.C", + DBUS_NAME_FLAG_DO_NOT_QUEUE, &f->e); + test_assert_no_error (&f->e); + g_assert_cmpint (ret, ==, DBUS_REQUEST_NAME_REPLY_PRIMARY_OWNER); + + while (!got_unique || !got_a || !got_b || !got_c) + { + test_main_context_iterate (f->ctx, TRUE); + + while ((m = g_queue_pop_head (&f->monitored)) != NULL) + { + if (dbus_message_is_signal (m, DBUS_INTERFACE_DBUS, + "NameAcquired")) + { + const char *name; + dbus_bool_t ok = dbus_message_get_args (m, &f->e, + DBUS_TYPE_STRING, &name, + DBUS_TYPE_INVALID); + + g_assert_cmpstr (dbus_message_get_path (m), ==, + DBUS_PATH_DBUS); + + test_assert_no_error (&f->e); + g_assert (ok); + + if (g_str_equal (name, f->monitor_name)) + { + g_assert (!got_unique); + got_unique = TRUE; + } + else if (g_str_equal (name, "com.example.A")) + { + g_assert (!got_a); + got_a = TRUE; + } + else if (g_str_equal (name, "com.example.B")) + { + g_assert (!got_b); + got_b = TRUE; + } + else + { + g_assert_cmpstr (name, ==, "com.example.C"); + g_assert (!got_c); + got_c = TRUE; + } + } + else + { + g_error ("unexpected message %s.%s", + dbus_message_get_interface (m), + dbus_message_get_member (m)); + } + + dbus_message_unref (m); + } + } + + become_monitor (f); + + while (!lost_unique || !lost_a || !lost_b || !lost_c) + { + test_main_context_iterate (f->ctx, TRUE); + + while ((m = g_queue_pop_head (&f->monitored)) != NULL) + { + if (dbus_message_is_signal (m, DBUS_INTERFACE_DBUS, + "NameLost")) + { + const char *name; + dbus_bool_t ok = dbus_message_get_args (m, &f->e, + DBUS_TYPE_STRING, &name, + DBUS_TYPE_INVALID); + + test_assert_no_error (&f->e); + g_assert (ok); + + if (g_str_equal (name, f->monitor_name)) + { + g_assert (!lost_unique); + lost_unique = TRUE; + } + else if (g_str_equal (name, "com.example.A")) + { + g_assert (!lost_a); + lost_a = TRUE; + } + else if (g_str_equal (name, "com.example.B")) + { + g_assert (!lost_b); + lost_b = TRUE; + } + else + { + g_assert_cmpstr (name, ==, "com.example.C"); + g_assert (!lost_c); + lost_c = TRUE; + } + } + else + { + g_error ("unexpected message %s.%s", + dbus_message_get_interface (m), + dbus_message_get_member (m)); + } + + dbus_message_unref (m); + } + } + + /* Calling methods is forbidden; we get disconnected. */ + dbus_bus_add_match (f->monitor, "", &f->e); + g_assert_cmpstr (f->e.name, ==, DBUS_ERROR_NO_REPLY); + g_assert (!dbus_connection_get_is_connected (f->monitor)); + + while (TRUE) + { + test_main_context_iterate (f->ctx, TRUE); + + /* When we iterate all the connection's messages, we see ourselves + * losing all our names, then we're disconnected. */ + while ((m = g_queue_pop_head (&f->monitored)) != NULL) + { + if (dbus_message_is_signal (m, DBUS_INTERFACE_LOCAL, "Disconnected")) + { + dbus_message_unref (m); + goto disconnected; + } + else + { + g_error ("unexpected message %s.%s", + dbus_message_get_interface (m), + dbus_message_get_member (m)); + } + + dbus_message_unref (m); + } + } + +disconnected: + + g_assert (lost_a); + g_assert (lost_b); + g_assert (lost_c); +} + +static void +test_broadcast (Fixture *f, + gconstpointer context) +{ + DBusMessage *m; + + if (f->address == NULL) + return; + + dbus_bus_add_match (f->recipient, "type='signal'", &f->e); + test_assert_no_error (&f->e); + + become_monitor (f); + + m = dbus_message_new_signal ("/foo", "com.example.bar", "BroadcastSignal1"); + dbus_connection_send (f->sender, m, NULL); + dbus_message_unref (m); + + m = dbus_message_new_signal ("/foo", "com.example.bar", "BroadcastSignal2"); + dbus_connection_send (f->sender, m, NULL); + dbus_message_unref (m); + + m = dbus_message_new_signal ("/foo", "com.example.bar", "BroadcastSignal3"); + dbus_connection_send (f->sender, m, NULL); + dbus_message_unref (m); + + while (g_queue_get_length (&f->monitored) < 3) + test_main_context_iterate (f->ctx, TRUE); + + m = g_queue_pop_head (&f->monitored); + assert_signal (m, f->sender_name, "/foo", "com.example.bar", + "BroadcastSignal1", "", NULL); + dbus_message_unref (m); + + m = g_queue_pop_head (&f->monitored); + assert_signal (m, f->sender_name, "/foo", "com.example.bar", + "BroadcastSignal2", "", NULL); + dbus_message_unref (m); + + m = g_queue_pop_head (&f->monitored); + assert_signal (m, f->sender_name, "/foo", "com.example.bar", + "BroadcastSignal3", "", NULL); + dbus_message_unref (m); + + m = g_queue_pop_head (&f->monitored); + g_assert (m == NULL); +} + +static void +test_forbidden_broadcast (Fixture *f, + gconstpointer context) +{ + DBusMessage *m; + + if (f->address == NULL) + return; + + dbus_bus_add_match (f->recipient, "type='signal'", &f->e); + test_assert_no_error (&f->e); + + become_monitor (f); + + m = dbus_message_new_signal ("/foo", "com.example.CannotSend", + "BroadcastSignal1"); + dbus_connection_send (f->sender, m, NULL); + dbus_message_unref (m); + + m = dbus_message_new_signal ("/foo", "com.example.CannotReceive", + "BroadcastSignal2"); + dbus_connection_send (f->sender, m, NULL); + dbus_message_unref (m); + + m = dbus_message_new_signal ("/foo", "com.example.CannotSend", + "BroadcastSignal3"); + dbus_connection_send (f->sender, m, NULL); + dbus_message_unref (m); + + while (g_queue_get_length (&f->monitored) < 6) + test_main_context_iterate (f->ctx, TRUE); + + m = g_queue_pop_head (&f->monitored); + assert_signal (m, f->sender_name, "/foo", "com.example.CannotSend", + "BroadcastSignal1", "", NULL); + dbus_message_unref (m); + + m = g_queue_pop_head (&f->monitored); + assert_error_reply (m, DBUS_SERVICE_DBUS, f->sender_name, + DBUS_ERROR_ACCESS_DENIED); + dbus_message_unref (m); + + m = g_queue_pop_head (&f->monitored); + assert_signal (m, f->sender_name, "/foo", "com.example.CannotReceive", + "BroadcastSignal2", "", NULL); + dbus_message_unref (m); + + m = g_queue_pop_head (&f->monitored); + assert_error_reply (m, DBUS_SERVICE_DBUS, f->sender_name, + DBUS_ERROR_ACCESS_DENIED); + dbus_message_unref (m); + + m = g_queue_pop_head (&f->monitored); + assert_signal (m, f->sender_name, "/foo", "com.example.CannotSend", + "BroadcastSignal3", "", NULL); + dbus_message_unref (m); + + m = g_queue_pop_head (&f->monitored); + assert_error_reply (m, DBUS_SERVICE_DBUS, f->sender_name, + DBUS_ERROR_ACCESS_DENIED); + dbus_message_unref (m); + + m = g_queue_pop_head (&f->monitored); + g_assert (m == NULL); +} + +static void +test_unicast_signal (Fixture *f, + gconstpointer context) +{ + DBusMessage *m; + + if (f->address == NULL) + return; + + become_monitor (f); + + m = dbus_message_new_signal ("/foo", "com.example.bar", "UnicastSignal1"); + if (!dbus_message_set_destination (m, f->recipient_name)) + g_error ("OOM"); + dbus_connection_send (f->sender, m, NULL); + dbus_message_unref (m); + + m = dbus_message_new_signal ("/foo", "com.example.bar", "UnicastSignal2"); + if (!dbus_message_set_destination (m, f->recipient_name)) + g_error ("OOM"); + dbus_connection_send (f->sender, m, NULL); + dbus_message_unref (m); + + m = dbus_message_new_signal ("/foo", "com.example.bar", "UnicastSignal3"); + if (!dbus_message_set_destination (m, f->recipient_name)) + g_error ("OOM"); + dbus_connection_send (f->sender, m, NULL); + dbus_message_unref (m); + + while (g_queue_get_length (&f->monitored) < 3) + test_main_context_iterate (f->ctx, TRUE); + + m = g_queue_pop_head (&f->monitored); + assert_signal (m, f->sender_name, "/foo", + "com.example.bar", "UnicastSignal1", "", f->recipient_name); + dbus_message_unref (m); + + m = g_queue_pop_head (&f->monitored); + assert_signal (m, f->sender_name, "/foo", + "com.example.bar", "UnicastSignal2", "", f->recipient_name); + dbus_message_unref (m); + + m = g_queue_pop_head (&f->monitored); + assert_signal (m, f->sender_name, "/foo", + "com.example.bar", "UnicastSignal3", "", f->recipient_name); + dbus_message_unref (m); + + m = g_queue_pop_head (&f->monitored); + g_assert (m == NULL); +} + +static void +test_forbidden (Fixture *f, + gconstpointer context) +{ + DBusMessage *m; + + if (f->address == NULL) + return; + + become_monitor (f); + + m = dbus_message_new_signal ("/foo", "com.example.CannotSend", + "UnicastSignal1"); + if (!dbus_message_set_destination (m, f->recipient_name)) + g_error ("OOM"); + dbus_connection_send (f->sender, m, NULL); + dbus_message_unref (m); + + m = dbus_message_new_signal ("/foo", "com.example.CannotReceive", + "UnicastSignal2"); + if (!dbus_message_set_destination (m, f->recipient_name)) + g_error ("OOM"); + dbus_connection_send (f->sender, m, NULL); + dbus_message_unref (m); + + m = dbus_message_new_signal ("/foo", "com.example.CannotSend", + "UnicastSignal3"); + if (!dbus_message_set_destination (m, f->recipient_name)) + g_error ("OOM"); + dbus_connection_send (f->sender, m, NULL); + dbus_message_unref (m); + + while (g_queue_get_length (&f->monitored) < 6) + test_main_context_iterate (f->ctx, TRUE); + + m = g_queue_pop_head (&f->monitored); + assert_signal (m, f->sender_name, "/foo", + "com.example.CannotSend", "UnicastSignal1", "", f->recipient_name); + dbus_message_unref (m); + + m = g_queue_pop_head (&f->monitored); + assert_error_reply (m, DBUS_SERVICE_DBUS, f->sender_name, + DBUS_ERROR_ACCESS_DENIED); + dbus_message_unref (m); + + m = g_queue_pop_head (&f->monitored); + assert_signal (m, f->sender_name, "/foo", + "com.example.CannotReceive", "UnicastSignal2", "", f->recipient_name); + dbus_message_unref (m); + + m = g_queue_pop_head (&f->monitored); + assert_error_reply (m, DBUS_SERVICE_DBUS, f->sender_name, + DBUS_ERROR_ACCESS_DENIED); + dbus_message_unref (m); + + m = g_queue_pop_head (&f->monitored); + assert_signal (m, f->sender_name, "/foo", + "com.example.CannotSend", "UnicastSignal3", "", f->recipient_name); + dbus_message_unref (m); + + m = g_queue_pop_head (&f->monitored); + assert_error_reply (m, DBUS_SERVICE_DBUS, f->sender_name, + DBUS_ERROR_ACCESS_DENIED); + dbus_message_unref (m); + + m = g_queue_pop_head (&f->monitored); + g_assert (m == NULL); +} + +static void +test_method_call (Fixture *f, + gconstpointer context) +{ + DBusMessage *m; + + if (f->address == NULL) + return; + + become_monitor (f); + + m = dbus_message_new_method_call (f->recipient_name, "/foo", "com.example.bar", + "Call1"); + dbus_connection_send (f->sender, m, NULL); + dbus_message_unref (m); + + while (g_queue_get_length (&f->monitored) < 2) + test_main_context_iterate (f->ctx, TRUE); + + m = g_queue_pop_head (&f->monitored); + assert_method_call (m, f->sender_name, f->recipient_name, "/foo", + "com.example.bar", "Call1", ""); + dbus_message_unref (m); + + m = g_queue_pop_head (&f->monitored); + assert_error_reply (m, f->recipient_name, f->sender_name, + DBUS_ERROR_UNKNOWN_METHOD); + dbus_message_unref (m); + + m = g_queue_pop_head (&f->monitored); + g_assert (m == NULL); +} + +static void +test_forbidden_method_call (Fixture *f, + gconstpointer context) +{ + DBusMessage *m; + + if (f->address == NULL) + return; + + become_monitor (f); + + m = dbus_message_new_method_call (f->recipient_name, "/foo", + "com.example.CannotSend", "Call1"); + dbus_connection_send (f->sender, m, NULL); + dbus_message_unref (m); + + while (g_queue_get_length (&f->monitored) < 2) + test_main_context_iterate (f->ctx, TRUE); + + m = g_queue_pop_head (&f->monitored); + assert_method_call (m, f->sender_name, f->recipient_name, "/foo", + "com.example.CannotSend", "Call1", ""); + dbus_message_unref (m); + + m = g_queue_pop_head (&f->monitored); + assert_error_reply (m, DBUS_SERVICE_DBUS, f->sender_name, + DBUS_ERROR_ACCESS_DENIED); + dbus_message_unref (m); + + m = g_queue_pop_head (&f->monitored); + g_assert (m == NULL); + + m = dbus_message_new_method_call (f->recipient_name, "/foo", + "com.example.CannotReceive", "Call2"); + dbus_connection_send (f->sender, m, NULL); + dbus_message_unref (m); + + while (g_queue_get_length (&f->monitored) < 2) + test_main_context_iterate (f->ctx, TRUE); + + m = g_queue_pop_head (&f->monitored); + assert_method_call (m, f->sender_name, f->recipient_name, "/foo", + "com.example.CannotReceive", "Call2", ""); + dbus_message_unref (m); + + m = g_queue_pop_head (&f->monitored); + assert_error_reply (m, DBUS_SERVICE_DBUS, f->sender_name, + DBUS_ERROR_ACCESS_DENIED); + dbus_message_unref (m); + + m = g_queue_pop_head (&f->monitored); + g_assert (m == NULL); +} + +static void +test_dbus_daemon (Fixture *f, + gconstpointer context) +{ + DBusMessage *m; + int res; + + if (f->address == NULL) + return; + + become_monitor (f); + + res = dbus_bus_request_name (f->sender, "com.example.Sender", + DBUS_NAME_FLAG_DO_NOT_QUEUE, &f->e); + test_assert_no_error (&f->e); + g_assert_cmpint (res, ==, DBUS_REQUEST_NAME_REPLY_PRIMARY_OWNER); + + res = dbus_bus_release_name (f->sender, "com.example.Sender", &f->e); + test_assert_no_error (&f->e); + g_assert_cmpint (res, ==, DBUS_RELEASE_NAME_REPLY_RELEASED); + + while (g_queue_get_length (&f->monitored) < 8) + test_main_context_iterate (f->ctx, TRUE); + + m = g_queue_pop_head (&f->monitored); + assert_method_call (m, f->sender_name, DBUS_SERVICE_DBUS, DBUS_PATH_DBUS, + DBUS_INTERFACE_DBUS, "RequestName", "su"); + dbus_message_unref (m); + + m = g_queue_pop_head (&f->monitored); + assert_signal (m, DBUS_SERVICE_DBUS, DBUS_PATH_DBUS, DBUS_INTERFACE_DBUS, + "NameOwnerChanged", "sss", NULL); + dbus_message_unref (m); + + /* FIXME: should we get this? */ + m = g_queue_pop_head (&f->monitored); + assert_signal (m, DBUS_SERVICE_DBUS, DBUS_PATH_DBUS, DBUS_INTERFACE_DBUS, + "NameAcquired", "s", f->sender_name); + dbus_message_unref (m); + + m = g_queue_pop_head (&f->monitored); + assert_method_reply (m, DBUS_SERVICE_DBUS, f->sender_name, "u"); + dbus_message_unref (m); + + m = g_queue_pop_head (&f->monitored); + assert_method_call (m, f->sender_name, DBUS_SERVICE_DBUS, DBUS_PATH_DBUS, + DBUS_INTERFACE_DBUS, "ReleaseName", "s"); + dbus_message_unref (m); + + /* FIXME: should we get this? */ + m = g_queue_pop_head (&f->monitored); + assert_signal (m, DBUS_SERVICE_DBUS, DBUS_PATH_DBUS, DBUS_INTERFACE_DBUS, + "NameLost", "s", f->sender_name); + dbus_message_unref (m); + + m = g_queue_pop_head (&f->monitored); + assert_signal (m, DBUS_SERVICE_DBUS, DBUS_PATH_DBUS, DBUS_INTERFACE_DBUS, + "NameOwnerChanged", "sss", NULL); + dbus_message_unref (m); + + m = g_queue_pop_head (&f->monitored); + assert_method_reply (m, DBUS_SERVICE_DBUS, f->sender_name, "u"); + dbus_message_unref (m); + + m = g_queue_pop_head (&f->monitored); + g_assert (m == NULL); +} + +static void +test_selective (Fixture *f, + gconstpointer context) +{ + DBusMessage *m; + + if (f->address == NULL) + return; + + /* Match rules added before becoming a monitor should be cleared: + * if they weren't, this test would get Interesting twice, then Tedious, + * and only see Fun after that. */ + dbus_bus_add_match (f->monitor, + "eavesdrop='true',interface='com.example.Interesting'", &f->e); + test_assert_no_error (&f->e); + dbus_bus_add_match (f->monitor, + "eavesdrop='true',interface='com.example.Tedious'", &f->e); + test_assert_no_error (&f->e); + + become_monitor (f); + + m = dbus_message_new_signal ("/foo", "com.example.Interesting", + "UnicastSignal1"); + if (!dbus_message_set_destination (m, f->recipient_name)) + g_error ("OOM"); + dbus_connection_send (f->sender, m, NULL); + dbus_message_unref (m); + + m = dbus_message_new_signal ("/foo", "com.example.Tedious", + "UnicastSignal2"); + if (!dbus_message_set_destination (m, f->recipient_name)) + g_error ("OOM"); + dbus_connection_send (f->sender, m, NULL); + dbus_message_unref (m); + + m = dbus_message_new_signal ("/foo", "com.example.Fun", + "UnicastSignal3"); + if (!dbus_message_set_destination (m, f->recipient_name)) + g_error ("OOM"); + dbus_connection_send (f->sender, m, NULL); + dbus_message_unref (m); + + while (g_queue_get_length (&f->monitored) < 2) + test_main_context_iterate (f->ctx, TRUE); + + /* We get the interesting signal and the fun signal, but not the tedious + * signal. */ + + m = g_queue_pop_head (&f->monitored); + assert_signal (m, f->sender_name, "/foo", + "com.example.Interesting", "UnicastSignal1", "", f->recipient_name); + dbus_message_unref (m); + + m = g_queue_pop_head (&f->monitored); + assert_signal (m, f->sender_name, "/foo", + "com.example.Fun", "UnicastSignal3", "", f->recipient_name); + dbus_message_unref (m); + + m = g_queue_pop_head (&f->monitored); + g_assert (m == NULL); +} + +static void +expect_new_connection (Fixture *f) +{ + DBusMessage *m; + + while (g_queue_get_length (&f->monitored) < 4) + test_main_context_iterate (f->ctx, TRUE); + + m = g_queue_pop_head (&f->monitored); + assert_hello (m); + dbus_message_unref (m); + + m = g_queue_pop_head (&f->monitored); + assert_hello_reply (m); + dbus_message_unref (m); + + m = g_queue_pop_head (&f->monitored); + assert_signal (m, DBUS_SERVICE_DBUS, DBUS_PATH_DBUS, DBUS_INTERFACE_DBUS, + "NameOwnerChanged", "sss", NULL); + dbus_message_unref (m); + + m = g_queue_pop_head (&f->monitored); + assert_name_acquired (m); + dbus_message_unref (m); +} + +static void +take_well_known_name (Fixture *f, + DBusConnection *connection, + const char *name) +{ + int ret; + + ret = dbus_bus_request_name (connection, name, + DBUS_NAME_FLAG_DO_NOT_QUEUE, &f->e); + test_assert_no_error (&f->e); + g_assert_cmpint (ret, ==, DBUS_REQUEST_NAME_REPLY_PRIMARY_OWNER); +} + +static void +expect_take_well_known_name (Fixture *f, + DBusConnection *connection, + const char *name) +{ + DBusMessage *m; + const char *connection_name = dbus_bus_get_unique_name (connection); + + while (g_queue_get_length (&f->monitored) < 4) + test_main_context_iterate (f->ctx, TRUE); + + m = g_queue_pop_head (&f->monitored); + assert_method_call (m, connection_name, DBUS_SERVICE_DBUS, DBUS_PATH_DBUS, + DBUS_INTERFACE_DBUS, "RequestName", "su"); + dbus_message_unref (m); + + m = g_queue_pop_head (&f->monitored); + assert_signal (m, DBUS_SERVICE_DBUS, DBUS_PATH_DBUS, DBUS_INTERFACE_DBUS, + "NameOwnerChanged", "sss", NULL); + dbus_message_unref (m); + + m = g_queue_pop_head (&f->monitored); + assert_signal (m, DBUS_SERVICE_DBUS, DBUS_PATH_DBUS, DBUS_INTERFACE_DBUS, + "NameAcquired", "s", connection_name); + dbus_message_unref (m); + + m = g_queue_pop_head (&f->monitored); + assert_method_reply (m, DBUS_SERVICE_DBUS, connection_name, "u"); + dbus_message_unref (m); +} + +static void +test_activation (Fixture *f, + gconstpointer context) +{ + DBusMessage *m; + + if (f->address == NULL) + return; + + become_monitor (f); + + /* The sender sends a message to an activatable service. */ + m = dbus_message_new_signal ("/foo", "com.example.bar", "UnicastSignal1"); + if (!dbus_message_set_destination (m, "com.example.SystemdActivatable1")) + g_error ("OOM"); + dbus_connection_send (f->sender, m, NULL); + dbus_message_unref (m); + + /* We observe the activation request, and the message that caused it, + * before systemd has even joined the bus. */ + while (g_queue_get_length (&f->monitored) < 2) + test_main_context_iterate (f->ctx, TRUE); + + m = g_queue_pop_head (&f->monitored); + assert_signal (m, DBUS_SERVICE_DBUS, DBUS_PATH_DBUS, + "org.freedesktop.systemd1.Activator", "ActivationRequest", "s", + "org.freedesktop.systemd1"); + dbus_message_unref (m); + m = g_queue_pop_head (&f->monitored); + assert_signal (m, f->sender_name, "/foo", + "com.example.bar", "UnicastSignal1", "", + "com.example.SystemdActivatable1"); + dbus_message_unref (m); + + /* The fake systemd connects to the bus. */ + f->systemd = test_connect_to_bus (f->ctx, f->address); + if (!dbus_connection_add_filter (f->systemd, systemd_filter, f, NULL)) + g_error ("OOM"); + f->systemd_name = dbus_bus_get_unique_name (f->systemd); + + expect_new_connection (f); + take_well_known_name (f, f->systemd, "org.freedesktop.systemd1"); + expect_take_well_known_name (f, f->systemd, "org.freedesktop.systemd1"); + + /* It gets its activation request. */ + while (f->systemd_message == NULL) + test_main_context_iterate (f->ctx, TRUE); + + m = f->systemd_message; + f->systemd_message = NULL; + assert_signal (m, DBUS_SERVICE_DBUS, DBUS_PATH_DBUS, + "org.freedesktop.systemd1.Activator", "ActivationRequest", "s", + "org.freedesktop.systemd1"); + dbus_message_unref (m); + + /* systemd starts the activatable service. */ + f->activated = test_connect_to_bus (f->ctx, f->address); + if (!dbus_connection_add_filter (f->activated, activated_filter, + f, NULL)) + g_error ("OOM"); + f->activated_name = dbus_bus_get_unique_name (f->activated); + + expect_new_connection (f); + take_well_known_name (f, f->activated, "com.example.SystemdActivatable1"); + expect_take_well_known_name (f, f->activated, + "com.example.SystemdActivatable1"); + + /* The message is delivered to the activatable service. */ + while (f->activated_message == NULL) + test_main_context_iterate (f->ctx, TRUE); + + m = f->activated_message; + f->activated_message = NULL; + assert_signal (m, f->sender_name, "/foo", + "com.example.bar", "UnicastSignal1", "", + "com.example.SystemdActivatable1"); + dbus_message_unref (m); + + /* The sender sends a message to a different activatable service. */ + m = dbus_message_new_signal ("/foo", "com.example.bar", "UnicastSignal2"); + if (!dbus_message_set_destination (m, "com.example.SystemdActivatable2")) + g_error ("OOM"); + dbus_connection_send (f->sender, m, NULL); + dbus_message_unref (m); + + /* This time systemd is already ready for it. */ + while (g_queue_get_length (&f->monitored) < 2 || + f->systemd_message == NULL) + test_main_context_iterate (f->ctx, TRUE); + + m = f->systemd_message; + f->systemd_message = NULL; + assert_signal (m, DBUS_SERVICE_DBUS, DBUS_PATH_DBUS, + "org.freedesktop.systemd1.Activator", "ActivationRequest", "s", + "org.freedesktop.systemd1"); + dbus_message_unref (m); + + /* The monitor sees the activation request and the signal that + * prompted it.*/ + m = g_queue_pop_head (&f->monitored); + assert_signal (m, DBUS_SERVICE_DBUS, DBUS_PATH_DBUS, + "org.freedesktop.systemd1.Activator", "ActivationRequest", "s", + "org.freedesktop.systemd1"); + dbus_message_unref (m); + m = g_queue_pop_head (&f->monitored); + assert_signal (m, f->sender_name, "/foo", + "com.example.bar", "UnicastSignal2", "", + "com.example.SystemdActivatable2"); + dbus_message_unref (m); + + /* The activatable service takes its name. Here I'm faking it by using + * an existing connection. */ + take_well_known_name (f, f->activated, "com.example.SystemdActivatable2"); + + /* The message is delivered to the activatable service. + * Implementation detail: the monitor sees this happen before it even + * sees that the name request happened, which is pretty odd. */ + while (f->activated_message == NULL) + test_main_context_iterate (f->ctx, TRUE); + + m = f->activated_message; + f->activated_message = NULL; + assert_signal (m, f->sender_name, "/foo", + "com.example.bar", "UnicastSignal2", "", + "com.example.SystemdActivatable2"); + dbus_message_unref (m); + + expect_take_well_known_name (f, f->activated, + "com.example.SystemdActivatable2"); + + /* A third activation. */ + m = dbus_message_new_signal ("/foo", "com.example.bar", "UnicastSignal3"); + if (!dbus_message_set_destination (m, "com.example.SystemdActivatable3")) + g_error ("OOM"); + dbus_connection_send (f->sender, m, NULL); + dbus_message_unref (m); + + /* Once again, we see the activation request and the reason. */ + while (g_queue_get_length (&f->monitored) < 2) + test_main_context_iterate (f->ctx, TRUE); + + m = g_queue_pop_head (&f->monitored); + assert_signal (m, DBUS_SERVICE_DBUS, DBUS_PATH_DBUS, + "org.freedesktop.systemd1.Activator", "ActivationRequest", "s", + "org.freedesktop.systemd1"); + dbus_message_unref (m); + m = g_queue_pop_head (&f->monitored); + assert_signal (m, f->sender_name, "/foo", + "com.example.bar", "UnicastSignal3", "", + "com.example.SystemdActivatable3"); + dbus_message_unref (m); + + /* systemd gets the request too. */ + while (f->systemd_message == NULL) + test_main_context_iterate (f->ctx, TRUE); + + m = f->systemd_message; + f->systemd_message = NULL; + assert_signal (m, DBUS_SERVICE_DBUS, DBUS_PATH_DBUS, + "org.freedesktop.systemd1.Activator", "ActivationRequest", "s", + "org.freedesktop.systemd1"); + dbus_message_unref (m); + + /* This time activation fails */ + m = dbus_message_new_signal ("/org/freedesktop/systemd1", + "org.freedesktop.systemd1.Activator", "ActivationFailure"); + + do + { + const char *unit = "dbus-com.example.SystemdActivatable3.service"; + const char *error_name = "com.example.Nope"; + const char *error_message = "Computer says no"; + + if (!dbus_message_append_args (m, + DBUS_TYPE_STRING, &unit, + DBUS_TYPE_STRING, &error_name, + DBUS_TYPE_STRING, &error_message, + DBUS_TYPE_INVALID)) + g_error ("OOM"); + } + while (0); + + if (!dbus_message_set_destination (m, "org.freedesktop.DBus")) + g_error ("OOM"); + dbus_connection_send (f->systemd, m, NULL); + dbus_message_unref (m); + + /* The monitor sees activation fail */ + + /* Once again, we see the activation request and the reason. */ + while (g_queue_get_length (&f->monitored) < 1) + test_main_context_iterate (f->ctx, TRUE); + + m = g_queue_pop_head (&f->monitored); + assert_error_reply (m, DBUS_SERVICE_DBUS, f->sender_name, + "com.example.Nope"); + dbus_message_unref (m); +} + +static void +teardown (Fixture *f, + gconstpointer context G_GNUC_UNUSED) +{ + dbus_error_free (&f->e); + g_clear_error (&f->ge); + + if (f->monitor != NULL) + { + dbus_connection_remove_filter (f->monitor, monitor_filter, f); + dbus_connection_close (f->monitor); + dbus_connection_unref (f->monitor); + f->monitor = NULL; + } + + if (f->sender != NULL) + { + dbus_connection_close (f->sender); + dbus_connection_unref (f->sender); + f->sender = NULL; + } + + if (f->recipient != NULL) + { + dbus_connection_remove_filter (f->recipient, recipient_filter, f); + dbus_connection_close (f->recipient); + dbus_connection_unref (f->recipient); + f->recipient = NULL; + } + + if (f->systemd != NULL) + { + dbus_connection_remove_filter (f->systemd, systemd_filter, f); + dbus_connection_close (f->systemd); + dbus_connection_unref (f->systemd); + f->systemd = NULL; + } + + if (f->activated != NULL) + { + dbus_connection_remove_filter (f->activated, activated_filter, f); + dbus_connection_close (f->activated); + dbus_connection_unref (f->activated); + f->activated = NULL; + } + + test_kill_pid (f->daemon_pid); + g_spawn_close_pid (f->daemon_pid); + + test_main_context_unref (f->ctx); + + g_queue_foreach (&f->monitored, (GFunc) dbus_message_unref, NULL); + g_queue_clear (&f->monitored); + + g_free (f->address); +} + +int +main (int argc, + char **argv) +{ + test_init (&argc, &argv); + + g_test_add ("/monitor/become", Fixture, &side_effects_config, + setup, test_become_monitor, teardown); + g_test_add ("/monitor/broadcast", Fixture, NULL, + setup, test_broadcast, teardown); + g_test_add ("/monitor/forbidden-broadcast", Fixture, &forbidding_config, + setup, test_forbidden_broadcast, teardown); + g_test_add ("/monitor/unicast-signal", Fixture, NULL, + setup, test_unicast_signal, teardown); + g_test_add ("/monitor/forbidden", Fixture, &forbidding_config, + setup, test_forbidden, teardown); + g_test_add ("/monitor/method-call", Fixture, NULL, + setup, test_method_call, teardown); + g_test_add ("/monitor/forbidden-method", Fixture, &forbidding_config, + setup, test_forbidden_method_call, teardown); + g_test_add ("/monitor/dbus-daemon", Fixture, NULL, + setup, test_dbus_daemon, teardown); + g_test_add ("/monitor/selective", Fixture, &selective_config, + setup, test_selective, teardown); + g_test_add ("/monitor/wildcard", Fixture, &wildcard_config, + setup, test_unicast_signal, teardown); + g_test_add ("/monitor/no-rule", Fixture, &no_rules_config, + setup, test_unicast_signal, teardown); + g_test_add ("/monitor/eavesdrop", Fixture, &eavesdrop_config, + setup, test_unicast_signal, teardown); + g_test_add ("/monitor/no-eavesdrop", Fixture, &no_eavesdrop_config, + setup, test_unicast_signal, teardown); + g_test_add ("/monitor/activation", Fixture, &fake_systemd_config, + setup, test_activation, teardown); + + return g_test_run (); +} diff --git a/test/relay.c b/test/relay.c index ecfe4c82..a6ccb412 100644 --- a/test/relay.c +++ b/test/relay.c @@ -30,7 +30,7 @@ #include <dbus/dbus.h> -#include "test-utils.h" +#include "test-utils-glib.h" /* This is basically a miniature dbus-daemon. We relay messages from the client * on the left to the client on the right. @@ -313,8 +313,7 @@ int main (int argc, char **argv) { - g_test_init (&argc, &argv, NULL); - g_test_bug_base ("https://bugs.freedesktop.org/show_bug.cgi?id="); + test_init (&argc, &argv); g_test_add ("/connect", Fixture, NULL, setup, test_connect, teardown); diff --git a/test/sd-activation.c b/test/sd-activation.c index 14e4ae80..2a7366df 100644 --- a/test/sd-activation.c +++ b/test/sd-activation.c @@ -211,6 +211,37 @@ test_activation (Fixture *f, "org.freedesktop.systemd1"); dbus_message_unref (m); + /* A malicious process tries to disrupt the activation. + * In a more realistic scenario this would be another parallel + * connection. */ + m = dbus_message_new_signal ("/org/freedesktop/systemd1", + "org.freedesktop.systemd1.Activator", "ActivationFailure"); + if (!dbus_message_set_destination (m, "org.freedesktop.DBus")) + g_error ("OOM"); + + do + { + const char *unit = "dbus-com.example.SystemdActivatable2.service"; + const char *error_name = "com.example.Malice"; + const char *error_message = "I'm on yr bus, making yr activations fail"; + + if (!dbus_message_append_args (m, + DBUS_TYPE_STRING, &unit, + DBUS_TYPE_STRING, &error_name, + DBUS_TYPE_STRING, &error_message, + DBUS_TYPE_INVALID)) + g_error ("OOM"); + } + while (0); + + dbus_connection_send (f->caller, m, NULL); + dbus_message_unref (m); + + /* This is just to make sure that the malicious message has arrived and + * been processed by the dbus-daemon, i.e. @caller won the race + * with @activated. */ + take_well_known_name (f, f->caller, "com.example.Sync"); + /* The activatable service takes its name. Here I'm faking it by using * an existing connection; in real life it would be yet another * connection. */ @@ -309,8 +340,7 @@ int main (int argc, char **argv) { - g_test_init (&argc, &argv, NULL); - g_test_bug_base ("https://bugs.freedesktop.org/show_bug.cgi?id="); + test_init (&argc, &argv); g_test_add ("/sd-activation", Fixture, NULL, setup, test_activation, teardown); diff --git a/test/syntax.c b/test/syntax.c index e26b3643..bf960c9e 100644 --- a/test/syntax.c +++ b/test/syntax.c @@ -30,6 +30,8 @@ #include <dbus/dbus.h> +#include "test-utils-glib.h" + typedef struct { DBusError e; } Fixture; @@ -269,7 +271,7 @@ int main (int argc, char **argv) { - g_test_init (&argc, &argv, NULL); + test_init (&argc, &argv); g_test_add ("/syntax/path", Fixture, &paths, setup, test_syntax, teardown); g_test_add ("/syntax/interface", Fixture, &interfaces, diff --git a/test/test-utils-glib.c b/test/test-utils-glib.c index 286e7a54..6cffcb21 100644 --- a/test/test-utils-glib.c +++ b/test/test-utils-glib.c @@ -385,3 +385,29 @@ test_kill_pid (GPid pid) kill (pid, SIGTERM); #endif } + +static gboolean +time_out (gpointer data) +{ + g_error ("timed out"); + return FALSE; +} + +void +test_init (int *argcp, char ***argvp) +{ + g_test_init (argcp, argvp, NULL); + g_test_bug_base ("https://bugs.freedesktop.org/show_bug.cgi?id="); + + /* Prevent tests from hanging forever. This is intended to be long enough + * that any reasonable regression test on any reasonable hardware would + * have finished. */ +#define TIMEOUT 60 + + g_timeout_add_seconds (TIMEOUT, time_out, NULL); +#ifdef G_OS_UNIX + /* The GLib main loop might not be running (we don't use it in every + * test). Die with SIGALRM shortly after if necessary. */ + alarm (TIMEOUT + 10); +#endif +} diff --git a/test/test-utils-glib.h b/test/test-utils-glib.h index 80a7c8d4..fd14fd1f 100644 --- a/test/test-utils-glib.h +++ b/test/test-utils-glib.h @@ -79,4 +79,6 @@ DBusConnection *test_connect_to_bus_as_user (TestMainContext *ctx, void test_kill_pid (GPid pid); +void test_init (int *argcp, char ***argvp); + #endif diff --git a/test/uid-permissions.c b/test/uid-permissions.c index 407b530e..2c62185a 100644 --- a/test/uid-permissions.c +++ b/test/uid-permissions.c @@ -186,8 +186,7 @@ int main (int argc, char **argv) { - g_test_init (&argc, &argv, NULL); - g_test_bug_base ("https://bugs.freedesktop.org/show_bug.cgi?id="); + test_init (&argc, &argv); g_test_add ("/uid-permissions/uae/root", Fixture, &root_ok_config, setup, test_uae, teardown); |