./0000755000004100000410000000000012763551700011251 5ustar www-datawww-data./autogen.sh0000755000004100000410000000024512763551700013253 0ustar www-datawww-data#!/bin/sh PKG_NAME="dbus-test-runner" which gnome-autogen.sh || { echo "You need gnome-common from GNOME SVN" exit 1 } USE_GNOME2_MACROS=1 \ . gnome-autogen.sh ./Makefile.am.coverage0000644000004100000410000000250512763551700015101 0ustar www-datawww-data # Coverage targets .PHONY: clean-gcno clean-gcda \ coverage-html generate-coverage-html clean-coverage-html \ coverage-gcovr generate-coverage-gcovr clean-coverage-gcovr clean-local: clean-gcno clean-coverage-html clean-coverage-gcovr if HAVE_GCOV clean-gcno: @echo Removing old coverage instrumentation -find -name '*.gcno' -print | xargs -r rm clean-gcda: @echo Removing old coverage results -find -name '*.gcda' -print | xargs -r rm coverage-html: clean-gcda -$(MAKE) $(AM_MAKEFLAGS) -k check $(MAKE) $(AM_MAKEFLAGS) generate-coverage-html generate-coverage-html: @echo Collecting coverage data $(LCOV) --directory $(top_builddir) --capture --output-file coverage.info --no-checksum --compat-libtool LANG=C $(GENHTML) --prefix $(top_builddir) --output-directory coveragereport --title "Code Coverage" --legend --show-details coverage.info clean-coverage-html: clean-gcda -$(LCOV) --directory $(top_builddir) -z -rm -rf coverage.info coveragereport if HAVE_GCOVR coverage-gcovr: clean-gcda -$(MAKE) $(AM_MAKEFLAGS) -k check $(MAKE) $(AM_MAKEFLAGS) generate-coverage-gcovr generate-coverage-gcovr: @echo Generating coverage GCOVR report $(GCOVR) -x -r $(top_builddir) -o $(top_builddir)/coverage.xml clean-coverage-gcovr: clean-gcda -rm -rf $(top_builddir)/coverage.xml endif # HAVE_GCOVR endif # HAVE_GCOV ./tests/0000755000004100000410000000000012763551700012413 5ustar www-datawww-data./tests/test-libdbustest.c0000644000004100000410000000420012763551700016054 0ustar www-datawww-data #include #include void test_env_var (void) { DbusTestService * service = dbus_test_service_new(NULL); g_assert(service != NULL); dbus_test_service_set_conf_file(service, SESSION_CONF); g_unsetenv("DBUS_SESSION_BUS_ADDRESS"); dbus_test_service_start_tasks(service); g_assert(g_getenv("DBUS_SESSION_BUS_ADDRESS") != NULL); g_object_unref(service); return; } void test_task_start (void) { DbusTestService * service = dbus_test_service_new(NULL); g_assert(service != NULL); dbus_test_service_set_conf_file(service, SESSION_CONF); DbusTestTask * task = dbus_test_task_new(); g_assert(task != NULL); dbus_test_service_add_task(service, task); dbus_test_service_start_tasks(service); g_assert(dbus_test_task_get_state(task) == DBUS_TEST_TASK_STATE_FINISHED); g_object_unref(task); g_object_unref(service); return; } void test_task_wait (void) { DbusTestService * service = dbus_test_service_new(NULL); g_assert(service != NULL); dbus_test_service_set_conf_file(service, SESSION_CONF); DbusTestTask * task = dbus_test_task_new(); g_assert(task != NULL); dbus_test_task_set_wait_for(task, "org.test.name"); dbus_test_service_add_task(service, task); DbusTestProcess * proc = dbus_test_process_new(GETNAME_PATH); g_assert(proc != NULL); g_assert(DBUS_TEST_IS_TASK(proc)); dbus_test_process_append_param(proc, "org.test.name"); dbus_test_service_add_task_with_priority(service, DBUS_TEST_TASK(proc), DBUS_TEST_SERVICE_PRIORITY_LAST); dbus_test_service_start_tasks(service); g_assert(dbus_test_task_get_state(task) == DBUS_TEST_TASK_STATE_FINISHED); g_object_unref(task); g_object_unref(service); return; } /* Build our test suite */ void test_libdbustest_suite (void) { g_test_add_func ("/libdbustest/env_var", test_env_var); g_test_add_func ("/libdbustest/task_start", test_task_start); g_test_add_func ("/libdbustest/task_wait", test_task_wait); return; } int main (int argc, char ** argv) { #ifndef GLIB_VERSION_2_36 g_type_init (); #endif g_test_init (&argc, &argv, NULL); test_libdbustest_suite(); g_log_set_always_fatal(G_LOG_LEVEL_CRITICAL); return g_test_run(); } ./tests/Makefile.am0000644000004100000410000004001112763551700014443 0ustar www-datawww-data DBUS_RUNNER=$(top_builddir)/src/dbus-test-runner --dbus-config $(srcdir)/../data/session.conf DBUS_RUNNER_SYSTEM=$(top_builddir)/src/dbus-test-runner --dbus-config $(srcdir)/../data/system.conf TESTS = DISTCLEANFILES = $(TESTS) XFAIL_TESTS = check_PROGRAMS = \ test-own-name \ test-check-name TESTS += test-simple test-simple: Makefile.am @echo "#!/bin/sh" > $@ @echo $(DBUS_RUNNER) --task true >> $@ @chmod +x $@ TESTS += test-manytask test-manytask: Makefile.am @echo "#!/bin/sh" > $@ @echo $(DBUS_RUNNER) --task true --task true --task true --task true --task true --task true --task true --task true --task true --task true --task true --task true --task true --task true --task true --task true --task true --task true --task true --task true --task true --task true --task true --task true --task true --task true --task true >> $@ @chmod +x $@ TESTS += test-ignore test-ignore: Makefile.am @echo "#!/bin/sh" > $@ @echo $(DBUS_RUNNER) --task false --ignore-return >> $@ @chmod +x $@ TESTS += test-ignore-second test-ignore-second: Makefile.am @echo "#!/bin/sh" > $@ @echo $(DBUS_RUNNER) --task true --task false --ignore-return >> $@ @chmod +x $@ TESTS += test-invert test-invert: Makefile.am @echo "#!/bin/sh" > $@ @echo $(DBUS_RUNNER) --task false --invert-return >> $@ @chmod +x $@ TESTS += test-invert-second test-invert-second: Makefile.am @echo "#!/bin/sh" > $@ @echo $(DBUS_RUNNER) --task true --task false --invert-return >> $@ @chmod +x $@ TESTS += test-param test-param: Makefile.am @echo "#!/bin/sh" > $@ @echo $(DBUS_RUNNER) --task \"$(srcdir)/delayrm.sh\" --parameter \"$(builddir)/bob\" --task touch --parameter \"$(builddir)/bob\" --ignore-return >> $@ @chmod +x $@ TESTS += test-timeout test-timeout: Makefile.am @echo "#!/bin/sh" > $@ @echo $(DBUS_RUNNER) --max-wait 1 --task sleep --parameter 3 >> $@ @chmod +x $@ XFAIL_TESTS += test-timeout TESTS += test-timeout-disable test-timeout-disable: Makefile.am @echo "#!/bin/sh" > $@ @echo $(DBUS_RUNNER) --max-wait 0 --task true >> $@ @chmod +x $@ TESTS += test-param-only-name test-param-only-name: Makefile.am @echo "#!/bin/sh" > $@ @echo $(DBUS_RUNNER) --task-name Name >> $@ @chmod +x $@ XFAIL_TESTS += test-param-only-name TESTS += test-param-dup-name test-param-dup-name: Makefile.am @echo "#!/bin/sh" > $@ @echo $(DBUS_RUNNER) --task true --task-name Name --task-name Name2 >> $@ @chmod +x $@ XFAIL_TESTS += test-param-dup-name TESTS += test-param-only-ignore test-param-only-ignore: Makefile.am @echo "#!/bin/sh" > $@ @echo $(DBUS_RUNNER) --ignore-return >> $@ @chmod +x $@ XFAIL_TESTS += test-param-only-ignore TESTS += test-param-only-invert test-param-only-invert: Makefile.am @echo "#!/bin/sh" > $@ @echo $(DBUS_RUNNER) --invert-return >> $@ @chmod +x $@ XFAIL_TESTS += test-param-only-invert TESTS += test-param-multi-return-invert test-param-multi-return-invert: Makefile.am @echo "#!/bin/sh" > $@ @echo $(DBUS_RUNNER) --task true --ignore-return --invert-return >> $@ @chmod +x $@ XFAIL_TESTS += test-param-multi-return-invert TESTS += test-param-multi-return-ignore test-param-multi-return-ignore: Makefile.am @echo "#!/bin/sh" > $@ @echo $(DBUS_RUNNER) --task true --invert-return --ignore-return >> $@ @chmod +x $@ XFAIL_TESTS += test-param-multi-return-ignore TESTS += test-param-only-param test-param-only-param: Makefile.am @echo "#!/bin/sh" > $@ @echo $(DBUS_RUNNER) --parameter bob >> $@ @chmod +x $@ XFAIL_TESTS += test-param-only-param TESTS += test-param-only-wait test-param-only-wait: Makefile.am @echo "#!/bin/sh" > $@ @echo $(DBUS_RUNNER) --wait-for org.test.test >> $@ @chmod +x $@ XFAIL_TESTS += test-param-only-wait TESTS += test-param-wait-system test-param-wait-system: Makefile.am test-own-name @echo "#!/bin/sh" > $@ @echo $(DBUS_RUNNER) --bus-type=system --task ls --task-bus=system --wait-for org.test.test --task $(builddir)/test-own-name --parameter --system --parameter org.test.test --ignore-return --task-bus=system >> $@ @chmod +x $@ TESTS += test-param-multi-wait test-param-multi-wait: Makefile.am @echo "#!/bin/sh" > $@ @echo $(DBUS_RUNNER) --task true --wait-for org.test.test --wait-for org.test.test2 >> $@ @chmod +x $@ XFAIL_TESTS += test-param-multi-wait TESTS += test-param-bad test-param-bad: Makefile.am @echo "#!/bin/sh" > $@ @echo $(DBUS_RUNNER) --this-is-most-surly-not-a-real-parameter >> $@ @chmod +x $@ XFAIL_TESTS += test-param-bad TESTS += test-param-bad-task test-param-bad-task: Makefile.am @echo "#!/bin/sh" > $@ @echo $(DBUS_RUNNER) --task this-is-most-surly-not-a-real-program >> $@ @chmod +x $@ XFAIL_TESTS += test-param-bad-task TESTS += test-no-tasks test-no-tasks: Makefile.am @echo "#!/bin/sh" > $@ @echo $(DBUS_RUNNER) >> $@ @chmod +x $@ XFAIL_TESTS += test-no-tasks TESTS += test-output test-output: Makefile.am @echo "#!/bin/sh -e" > $@ @echo "$(DBUS_RUNNER) --task cat --parameter \"$(top_srcdir)/src/dbus-test-runner.c\" --task-name \"cat1\" --task cat --parameter \"$(top_srcdir)/src/dbus-test-runner.c\" --task-name \"cat2\" > testcat.output.txt" >> $@ @echo "echo Finding cat1 data" >> $@ @echo "grep ^cat1: testcat.output.txt | tail -n +2 | head -n -1 > testcat.output.cat1.txt" >> $@ @echo "echo Finding cat2 data" >> $@ @echo "grep ^cat2: testcat.output.txt | tail -n +2 | head -n -1 > testcat.output.cat2.txt" >> $@ @echo "echo Filtering cat1 data" >> $@ @echo "sed -e s/cat1:\\ //g testcat.output.cat1.txt > testcat.output.cat1.filtered.txt" >> $@ @echo "echo Filtering cat2 data" >> $@ @echo "sed -e s/cat2:\\ //g testcat.output.cat2.txt > testcat.output.cat2.filtered.txt" >> $@ @echo "echo Verifying cat 1" >> $@ @echo "diff testcat.output.cat1.filtered.txt \"$(top_srcdir)/src/dbus-test-runner.c\" > /dev/null" >> $@ @echo "echo Verifying cat 2" >> $@ @echo "diff testcat.output.cat2.filtered.txt \"$(top_srcdir)/src/dbus-test-runner.c\" > /dev/null" >> $@ @chmod +x $@ DISTCLEANFILES += testcat.output.txt testcat.output.cat1.txt testcat.output.cat2.txt testcat.output.cat1.filtered.txt testcat.output.cat2.filtered.txt if TEST_BUSTLE TESTS += test-bustle test-bustle: Makefile.am test-bustle.reference test-bustle.0.4.reference @echo "#!/bin/sh -e" > $@ @echo "chmod +x $(top_srcdir)/libdbustest/dbus-test-bustle-handler" >> $@ @echo $(DBUS_RUNNER) --bustle-monitor $(top_srcdir)/libdbustest/dbus-test-bustle-handler --bustle-data \"$(builddir)/test-bustle.bustle\" --task $(srcdir)/test-bustle-list.sh >> $@ @echo "if [ -x /usr/bin/bustle-count ] ; then" >> $@ @echo "grep ^sig \"$(builddir)/test-bustle.bustle\" | grep ":1.1" | grep "com.launchpad.dbustestrunner" | cut -f 5-9 > test-bustle.filtered" >> $@ @echo "diff \"$(srcdir)/test-bustle.reference\" \"$(builddir)/test-bustle.filtered\"" >> $@ @echo "else" >> $@ @echo "bustle --count \"$(builddir)/test-bustle.bustle\" > \"$(builddir)/test-bustle.filtered\"" >> $@ @echo "diff \"$(srcdir)/test-bustle.0.4.reference\" \"$(builddir)/test-bustle.filtered\"" >> $@ @echo "fi" >> $@ @chmod +x $@ DISTCLEANFILES += test-bustle.bustle test-bustle.filtered TESTS += test-bustle-bad-file test-bustle-bad-file: Makefile.am @echo "#!/bin/sh -e" > $@ @echo "chmod +x $(top_srcdir)/libdbustest/dbus-test-bustle-handler" >> $@ @echo $(DBUS_RUNNER) --bustle-monitor $(top_srcdir)/libdbustest/dbus-test-bustle-handler --bustle-data \"$(builddir)\" --task true >> $@ @chmod +x $@ XFAIL_TESTS += test-bustle-bad-file TESTS += test-bustle-bad-monitor test-bustle-bad-monitor: Makefile.am @echo "#!/bin/sh -e" > $@ @echo $(DBUS_RUNNER) --bustle-monitor probably-doesnt-exist --bustle-data \"$(builddir)/test-bustle-bad-monitor.bustle\" --task true >> $@ @chmod +x $@ XFAIL_TESTS += test-bustle-bad-monitor DISTCLEANFILES += test-bustle-bad-monitor.bustle TESTS += test-bustle-bad-monitor-error test-bustle-bad-monitor-error: Makefile.am @echo "#!/bin/sh -e" > $@ @echo $(DBUS_RUNNER) --bustle-monitor sleep --bustle-data \"$(builddir)/test-bustle-bad-monitor-error.bustle\" --task true >> $@ @chmod +x $@ XFAIL_TESTS += test-bustle-bad-monitor-error DISTCLEANFILES += test-bustle-bad-monitor-error.bustle TESTS += test-bustle-data test-bustle-data: Makefile.am @echo "#!/bin/sh -e" > $@ @echo "chmod +x $(top_srcdir)/libdbustest/dbus-test-bustle-handler" >> $@ @echo "$(DBUS_RUNNER) --bustle-monitor $(top_srcdir)/libdbustest/dbus-test-bustle-handler --bustle-data \"$(builddir)/test-bustle-data.bustle\" \\" >> $@ @echo "--task $(srcdir)/test-bustle-list.sh \\" >> $@ @echo "--task $(srcdir)/test-bustle-list.sh \\" >> $@ @echo "--task $(srcdir)/test-bustle-list.sh \\" >> $@ @echo "--task $(srcdir)/test-bustle-list.sh \\" >> $@ @echo "--task $(srcdir)/test-bustle-list.sh \\" >> $@ @echo "--task $(srcdir)/test-bustle-list.sh \\" >> $@ @echo "--task $(srcdir)/test-bustle-list.sh \\" >> $@ @echo "--task $(srcdir)/test-bustle-list.sh \\" >> $@ @echo "--task $(srcdir)/test-bustle-list.sh \\" >> $@ @echo "--task $(srcdir)/test-bustle-list.sh \\" >> $@ @echo "--task $(srcdir)/test-bustle-list.sh \\" >> $@ @echo "--task $(srcdir)/test-bustle-list.sh" >> $@ @echo "if [ -x /usr/bin/bustle-count ] ; then" >> $@ @echo "chmod +x $(srcdir)/test-bustle-data-check.sh" >> $@ @echo "$(srcdir)/test-bustle-data-check.sh \"$(builddir)/test-bustle-data.bustle\" 12" >> $@ @echo "else" >> $@ @echo "chmod +x $(srcdir)/test-bustle-data-check.0.4.sh" >> $@ @echo "$(srcdir)/test-bustle-data-check.0.4.sh \"$(builddir)/test-bustle-data.bustle\" 12" >> $@ @echo "fi" >> $@ @chmod +x $@ DISTCLEANFILES += test-bustle-data.bustle endif test_own_name_SOURCES = \ test-own-name.c test_own_name_CFLAGS = \ $(DBUS_TEST_RUNNER_CFLAGS) \ -Wall -Werror test_own_name_LDADD = \ $(DBUS_TEST_RUNNER_LIBS) test_check_name_SOURCES = \ test-check-name.c test_check_name_CFLAGS = \ $(DBUS_TEST_RUNNER_CFLAGS) \ -Wall -Werror test_check_name_LDADD = \ $(DBUS_TEST_RUNNER_LIBS) TESTS += test-wait-for test-wait-for: Makefile.am test-own-name test-check-name @echo "#!/bin/sh" > $@ @echo $(DBUS_RUNNER) --task $(builddir)/test-check-name --parameter org.test.name --wait-for org.test.name --task $(builddir)/test-own-name --parameter org.test.name --ignore-return >> $@ @chmod +x $@ TESTS += test-daemon-bad test-daemon-bad: Makefile.am @echo "#!/bin/sh" > $@ @echo $(DBUS_RUNNER) --dbus-daemon false --task true >> $@ @chmod +x $@ XFAIL_TESTS += test-daemon-bad TESTS += test-daemon-missing test-daemon-missing: Makefile.am @echo "#!/bin/sh" > $@ @echo $(DBUS_RUNNER) --dbus-daemon probably-doesnt-exist --task true >> $@ @chmod +x $@ XFAIL_TESTS += test-daemon-missing TESTS += test-daemon-junk test-daemon-junk: Makefile.am test-daemon-junk-spitter @echo "#!/bin/sh" > $@ @echo $(DBUS_RUNNER) --dbus-daemon $(builddir)/test-daemon-junk-spitter --task true >> $@ @chmod +x $@ test-daemon-junk-spitter: Makefile.am @echo "#!/bin/sh" > $@ @echo cat $(top_builddir)/src/dbus-test-runner >> $@ @chmod +x $@ XFAIL_TESTS += test-daemon-junk DISTCLEANFILES += test-daemon-junk-spitter TESTS += test-wait-output test-wait-output: Makefile.am test-wait-outputer @echo "#!/bin/sh" > $@ @echo $(DBUS_RUNNER) --task "$(srcdir)/test-wait-outputer" --task-name output --ignore-return --wait-until-complete \| tee $(builddir)/test-wait-output.output >> $@ @echo "grep ^output: $(builddir)/test-wait-output.output | tail -n +2 > $(builddir)/test-wait-output.output-only" >> $@ @echo "sed -e s/output:\\ //g $(builddir)/test-wait-output.output-only > $(builddir)/test-wait-output.filtered" >> $@ @echo diff $(srcdir)/test-wait-output.reference $(builddir)/test-wait-output.filtered >> $@ @chmod +x $@ DISTCLEANFILES += \ test-wait-output.output \ test-wait-output.output-only \ test-wait-output.filtered TESTS += test-busses-base test-busses-base: Makefile.am @echo "#!/bin/sh -e" > $@ @echo echo TEST: session >> $@ @echo $(DBUS_RUNNER) --bus-type session --task /bin/true >> $@ @echo echo TEST: system >> $@ @echo $(DBUS_RUNNER_SYSTEM) --bus-type system --task /bin/true >> $@ @echo echo TEST: both >> $@ @echo $(DBUS_RUNNER) --bus-type both --task /bin/true >> $@ @echo echo TEST: session, session >> $@ @echo $(DBUS_RUNNER) --bus-type session --task /bin/true --task-bus=session >> $@ @echo echo TEST: session, both >> $@ @echo $(DBUS_RUNNER) --bus-type session --task /bin/true --task-bus=both >> $@ @echo echo TEST: system, system >> $@ @echo $(DBUS_RUNNER_SYSTEM) --bus-type system --task /bin/true --task-bus=system >> $@ @echo echo TEST: system, both >> $@ @echo $(DBUS_RUNNER_SYSTEM) --bus-type system --task /bin/true --task-bus=both >> $@ @echo echo TEST: both, session >> $@ @echo $(DBUS_RUNNER) --bus-type both --task /bin/true --task-bus=session >> $@ @echo echo TEST: both, system >> $@ @echo $(DBUS_RUNNER) --bus-type both --task /bin/true --task-bus=system >> $@ @echo echo TEST: both, both >> $@ @echo $(DBUS_RUNNER) --bus-type both --task /bin/true --task-bus=both >> $@ @echo echo TEST: verify session, session >> $@ @echo $(DBUS_RUNNER) --bus-type session --task gdbus --parameter call --parameter --session --parameter --dest --parameter org.freedesktop.DBus --parameter --object-path --parameter / --parameter --method --parameter org.freedesktop.DBus.GetId >> $@ @echo echo TEST: verify session, both >> $@ @echo $(DBUS_RUNNER) --bus-type both --task gdbus --parameter call --parameter --session --parameter --dest --parameter org.freedesktop.DBus --parameter --object-path --parameter / --parameter --method --parameter org.freedesktop.DBus.GetId >> $@ @echo echo TEST: verify system, system >> $@ @echo $(DBUS_RUNNER_SYSTEM) --bus-type system --task gdbus --parameter call --parameter --system --parameter --dest --parameter org.freedesktop.DBus --parameter --object-path --parameter / --parameter --method --parameter org.freedesktop.DBus.GetId >> $@ @echo echo TEST: verify system, both >> $@ @echo $(DBUS_RUNNER) --bus-type both --task gdbus --parameter call --parameter --system --parameter --dest --parameter org.freedesktop.DBus --parameter --object-path --parameter / --parameter --method --parameter org.freedesktop.DBus.GetId >> $@ @chmod +x $@ ########################### # libdbustest ########################### check_PROGRAMS += \ test-libdbustest \ test-libdbustest-getname TESTS += test-libdbustest-test test_libdbustest_SOURCES = \ test-libdbustest.c test_libdbustest_CFLAGS = \ $(DBUS_TEST_RUNNER_CFLAGS) \ -I$(top_srcdir) \ -DSESSION_CONF="\"$(top_srcdir)/data/session.conf\"" \ -DGETNAME_PATH="\"$(abs_builddir)/test-libdbustest-getname\"" \ -Wall -Werror test_libdbustest_LDADD = \ $(DBUS_TEST_RUNNER_LIBS) \ $(top_builddir)/libdbustest/libdbustest.la test_libdbustest_getname_SOURCES = \ test-libdbustest-getname.c test_libdbustest_getname_CFLAGS = \ $(DBUS_TEST_RUNNER_CFLAGS) \ -Wall -Werror test_libdbustest_getname_LDADD = \ $(DBUS_TEST_RUNNER_LIBS) LIBDBUSTEST_XML_REPORT = $(builddir)/libdbustest-results.xml test-libdbustest-test: test-libdbustest test-libdbustest-getname @echo "#!/bin/bash" > $@ @echo $(XVFB_RUN) >> $@ @echo gtester -k --verbose -o=$(LIBDBUSTEST_XML_REPORT) $(builddir)/test-libdbustest >> $@ @chmod +x $@ DISTCLEANFILES += $(LIBDBUSTEST_XML_REPORT) ########################### # libdbustest-mock ########################### check_PROGRAMS += \ test-libdbustest-mock TESTS += test-libdbustest-mock-test test_libdbustest_mock_SOURCES = \ test-libdbustest-mock.c test_libdbustest_mock_CFLAGS = \ $(DBUS_TEST_RUNNER_CFLAGS) \ -I$(top_srcdir) \ -DSESSION_CONF="\"$(top_srcdir)/data/session.conf\"" \ -DGETNAME_PATH="\"$(abs_builddir)/test-libdbustest-getname\"" \ -Wall -Werror test_libdbustest_mock_LDADD = \ $(DBUS_TEST_RUNNER_LIBS) \ $(top_builddir)/libdbustest/libdbustest.la LIBDBUSTEST_MOCK_XML_REPORT = $(builddir)/libdbustest-mock-results.xml test-libdbustest-mock-test: test-libdbustest-mock @echo "#!/bin/bash" > $@ @echo $(XVFB_RUN) >> $@ @echo gtester -k --verbose -o=$(LIBDBUSTEST_MOCK_XML_REPORT) $(builddir)/test-libdbustest-mock >> $@ @chmod +x $@ DISTCLEANFILES += $(LIBDBUSTEST_MOCK_XML_REPORT) ########################### # END ########################### EXTRA_DIST = \ test-wait-outputer \ test-wait-output.reference \ delayrm.sh \ test-bustle.reference \ test-bustle.0.4.reference \ test-bustle-data-check.sh \ test-bustle-data-check.0.4.sh \ test-bustle-list.sh ./tests/test-wait-output.reference0000644000004100000410000000004612763551700017552 0ustar www-datawww-dataOne Two Three Four Five Shutting down ./tests/test-libdbustest-getname.c0000644000004100000410000000222712763551700017501 0ustar www-datawww-data #include #include GMainLoop * mainloop = NULL; gboolean error = FALSE; void name_acquired (GDBusConnection * connection, const gchar * name, gpointer user_data) { g_main_loop_quit(mainloop); return; } void name_lost (GDBusConnection * connection, const gchar * name, gpointer user_data) { g_warning("Name lost!"); error = TRUE; g_main_loop_quit(mainloop); return; } int main (int argc, gchar * argv[]) { if (argc != 2) { g_critical("Need a name"); return -1; } #ifndef GLIB_VERSION_2_36 g_type_init(); #endif guint name = g_bus_own_name(G_BUS_TYPE_SESSION, argv[1], /* name */ G_BUS_NAME_OWNER_FLAGS_NONE, /* flags */ NULL, /* bus acquired */ name_acquired, /* name acquired */ name_lost, /* name lost */ NULL, /* user data */ NULL /* ud free */ ); mainloop = g_main_loop_new(NULL, FALSE); g_main_loop_run(mainloop); g_bus_unown_name(name); if (error) { return -1; } else { return 0; } } ./tests/test-own-name.c0000644000004100000410000000277012763551700015263 0ustar www-datawww-data#include #include void name_aquired (GDBusConnection * connection, const gchar * name, gpointer user_data) { g_debug("Got name: %s", name); return; } gboolean end_of_line (gpointer user_data) { g_main_loop_quit((GMainLoop *)user_data); return FALSE; } int main (int argc, char * argv[]) { gboolean system_bus = FALSE; GOptionContext *options; GError *error = NULL; const GOptionEntry option_entries[] = { { "system", 'y', G_OPTION_FLAG_NONE, G_OPTION_ARG_NONE, &system_bus, "Own the name on the system bus", NULL }, { NULL } }; #ifndef GLIB_VERSION_2_36 g_type_init(); #endif options = g_option_context_new(NULL); g_option_context_add_main_entries(options, option_entries, NULL); if (!g_option_context_parse(options, &argc, &argv, &error)) { g_printerr("%s", error->message); g_error_free(error); return 1; } if (argc != 2) { g_error("ARG, need a single argument"); return 1; } g_debug("Trying for name: %s", argv[1]); g_bus_own_name(system_bus ? G_BUS_TYPE_SYSTEM : G_BUS_TYPE_SESSION, argv[1], G_BUS_NAME_OWNER_FLAGS_NONE, NULL, /* bus aquired */ name_aquired, NULL, /* lost */ NULL, /* data */ NULL); /* destroy */ GMainLoop * mainloop = g_main_loop_new(NULL, FALSE); g_timeout_add_seconds(2, end_of_line, mainloop); g_main_loop_run(mainloop); g_main_loop_unref(mainloop); g_option_context_free(options); g_debug("Quitting"); return 0; } ./tests/test-bustle-list.sh0000755000004100000410000000017612763551700016202 0ustar www-datawww-data#!/bin/sh sleep 1 gdbus emit --session --object-path /test/dbustestrunner/signal --signal com.launchpad.dbustestrunner.signal ./tests/test-bustle.reference0000644000004100000410000000010512763551700016542 0ustar www-datawww-data:1.1 /test/dbustestrunner/signal com.launchpad.dbustestrunner signal ./tests/test-bustle.0.4.reference0000644000004100000410000000006112763551700017043 0ustar www-datawww-data 1 signal com.launchpad.dbustestrunner.signal ./tests/test-bustle-data-check.sh0000755000004100000410000000011012763551700017177 0ustar www-datawww-data#!/bin/bash -e [ `grep ^sig $1 | grep dbustestrunner | wc -l` -eq $2 ] ./tests/test-check-name.c0000644000004100000410000000202012763551700015521 0ustar www-datawww-data#include #include int main (int argc, char * argv[]) { #ifndef GLIB_VERSION_2_36 g_type_init(); #endif if (argc != 2) { g_error("ARG, need a single argument"); return 1; } g_debug("Looking for name: %s", argv[1]); GDBusConnection * bus = g_bus_get_sync(G_BUS_TYPE_SESSION, NULL, NULL); g_return_val_if_fail(bus != NULL, 1); GDBusProxy * proxy = g_dbus_proxy_new_sync(bus, G_DBUS_PROXY_FLAGS_DO_NOT_LOAD_PROPERTIES | G_DBUS_PROXY_FLAGS_DO_NOT_CONNECT_SIGNALS | G_DBUS_PROXY_FLAGS_DO_NOT_AUTO_START, NULL, argv[1], "/", "org.freedesktop.DBus.Introspectable", NULL, NULL); /* cancel, error */ g_return_val_if_fail(proxy != NULL, 1); g_return_val_if_fail(g_dbus_proxy_get_name_owner(proxy) != NULL, 1); g_debug("Quitting"); return 0; } ./tests/test-wait-outputer0000755000004100000410000000016012763551700016144 0ustar www-datawww-data#!/bin/bash sleep 1 echo "One" sleep 1 echo "Two" sleep 1 echo "Three" sleep 1 echo "Four" sleep 1 echo "Five" ./tests/delayrm.sh0000755000004100000410000000003212763551700014402 0ustar www-datawww-data#!/bin/sh sleep 0.2 rm $1 ./tests/manual0000644000004100000410000000076012763551700013616 0ustar www-datawww-dataTest-case dbus-test-runner/build-hud
Grab the build dependencies for HUD: sudo apt-get build-dep hud
Install the Bazaar build tools: sudo apt-get install bzr-builddeb
Get a copy of HUD trunk: bzr co --lightweight lp:hud
Build HUD: cd hud ; bzr bd
HUD should build and run it's test suite successfully
The package may not build successfully, but we just want the test suite to pass
./tests/test-bustle-data-check.0.4.sh0000755000004100000410000000010112763551700017477 0ustar www-datawww-data#!/bin/bash -e [ `bustle --count $1 | cut -d " " -f 4` -eq $2 ] ./tests/test-libdbustest-mock.c0000644000004100000410000004442012763551700017013 0ustar www-datawww-data #include #include #include /* Timeout on our loop */ static gboolean timeout_quit_func (gpointer user_data) { GMainLoop * loop = (GMainLoop *)user_data; g_main_loop_quit(loop); return FALSE; } static void process_mainloop (const guint delay) { GMainLoop * temploop = g_main_loop_new (NULL, FALSE); g_timeout_add (delay, timeout_quit_func, temploop); g_main_loop_run (temploop); g_main_loop_unref (temploop); } #define SESSION_MAX_WAIT 100 /* * Waiting until the session bus shuts down */ GDBusConnection * wait_for_close_ptr = NULL; static void wait_for_connection_close (GDBusConnection *connection) { wait_for_close_ptr = connection; g_object_add_weak_pointer(G_OBJECT(connection), (gpointer) &wait_for_close_ptr); g_object_unref (connection); int wait_count; for (wait_count = 0; wait_for_close_ptr != NULL && wait_count < SESSION_MAX_WAIT; wait_count++) { process_mainloop(200); } g_assert(wait_count != SESSION_MAX_WAIT); } static void signal_emitted (GDBusConnection * connection, const gchar * sender, const gchar * path, const gchar * interface, const gchar * signal, GVariant * params, gpointer user_data) { guint * count = (guint *)user_data; (*count)++; } void test_basic (void) { DbusTestService * service = dbus_test_service_new(NULL); g_assert(service != NULL); dbus_test_service_set_conf_file(service, SESSION_CONF); DbusTestDbusMock * mock = dbus_test_dbus_mock_new("foo.test"); g_assert(mock != NULL); dbus_test_service_add_task(service, DBUS_TEST_TASK(mock)); dbus_test_service_start_tasks(service); gchar * dbusname = NULL; g_object_get(mock, "dbus-name", &dbusname, NULL); g_assert(g_strcmp0(dbusname, "foo.test") == 0); g_free(dbusname); gchar * exec = NULL; g_object_get(mock, "executable", &exec, NULL); g_assert(g_strcmp0(exec, "python3") == 0); g_free(exec); g_assert(dbus_test_task_get_state(DBUS_TEST_TASK(mock)) == DBUS_TEST_TASK_STATE_RUNNING); /* check setup */ GDBusConnection * bus = g_bus_get_sync(G_BUS_TYPE_SESSION, NULL, NULL); g_dbus_connection_set_exit_on_close(bus, FALSE); /* Ensure we can get an object */ DbusTestDbusMockObject * obj = dbus_test_dbus_mock_get_object(mock, "/test", "foo.test.interface", NULL); g_assert(obj != NULL); DbusTestDbusMockObject * newobj = dbus_test_dbus_mock_get_object(mock, "/test", "foo.test.interface", NULL); g_assert(obj == newobj); g_object_unref(mock); g_object_unref(service); wait_for_connection_close(bus); return; } void test_properties (void) { DbusTestService * service = dbus_test_service_new(NULL); g_assert(service != NULL); dbus_test_service_set_conf_file(service, SESSION_CONF); DbusTestDbusMock * mock = dbus_test_dbus_mock_new("foo.test"); g_assert(mock != NULL); DbusTestDbusMockObject * obj = dbus_test_dbus_mock_get_object(mock, "/test", "foo.test.interface", NULL); /* String property */ g_assert(dbus_test_dbus_mock_object_add_property(mock, obj, "prop1", G_VARIANT_TYPE_STRING, g_variant_new_string("test"), NULL)); /* Invalid type */ g_assert(!dbus_test_dbus_mock_object_add_property(mock, obj, "prop2", G_VARIANT_TYPE_STRING, g_variant_new_uint32(5), NULL)); /* Complex type */ g_assert(dbus_test_dbus_mock_object_add_property(mock, obj, "prop3", G_VARIANT_TYPE("(sssss)"), g_variant_new("(sssss)", "a", "b", "c", "d", "e"), NULL)); dbus_test_service_add_task(service, DBUS_TEST_TASK(mock)); dbus_test_service_start_tasks(service); g_assert(dbus_test_task_get_state(DBUS_TEST_TASK(mock)) == DBUS_TEST_TASK_STATE_RUNNING); /* check setup */ GDBusConnection * bus = g_bus_get_sync(G_BUS_TYPE_SESSION, NULL, NULL); g_dbus_connection_set_exit_on_close(bus, FALSE); GVariant * propret = NULL; GVariant * testvar = NULL; GError * error = NULL; /* Check prop1 */ propret = g_dbus_connection_call_sync(bus, "foo.test", "/test", "org.freedesktop.DBus.Properties", "Get", g_variant_new("(ss)", "foo.test.interface", "prop1"), G_VARIANT_TYPE("(v)"), G_DBUS_CALL_FLAGS_NONE, -1, NULL, &error); if (error != NULL) { g_error("Unable to get property: %s", error->message); g_error_free(error); } g_assert(propret != NULL); testvar = g_variant_new_variant(g_variant_new_string("test")); testvar = g_variant_new_tuple(&testvar, 1); g_variant_ref_sink(testvar); g_assert(g_variant_equal(propret, testvar)); g_variant_unref(testvar); g_variant_unref(propret); /* Check lack of prop2 */ propret = g_dbus_connection_call_sync(bus, "foo.test", "/test", "org.freedesktop.DBus.Properties", "Get", g_variant_new("(ss)", "foo.test.interface", "prop2"), G_VARIANT_TYPE("(v)"), G_DBUS_CALL_FLAGS_NONE, -1, NULL, &error); g_assert(error != NULL); g_error_free(error); error = NULL; g_assert(propret == NULL); /* Check prop3 */ propret = g_dbus_connection_call_sync(bus, "foo.test", "/test", "org.freedesktop.DBus.Properties", "Get", g_variant_new("(ss)", "foo.test.interface", "prop3"), G_VARIANT_TYPE("(v)"), G_DBUS_CALL_FLAGS_NONE, -1, NULL, &error); if (error != NULL) { g_error("Unable to get property: %s", error->message); g_error_free(error); } g_assert(propret != NULL); testvar = g_variant_new_variant(g_variant_new("(sssss)", "a", "b", "c", "d", "e")); testvar = g_variant_new_tuple(&testvar, 1); g_variant_ref_sink(testvar); g_assert(g_variant_equal(propret, testvar)); g_variant_unref(testvar); g_variant_unref(propret); /* Update the properties */ g_assert(dbus_test_dbus_mock_object_update_property(mock, obj, "prop1", g_variant_new_string("test-update"), NULL)); /* Check prop1 again */ propret = g_dbus_connection_call_sync(bus, "foo.test", "/test", "org.freedesktop.DBus.Properties", "Get", g_variant_new("(ss)", "foo.test.interface", "prop1"), G_VARIANT_TYPE("(v)"), G_DBUS_CALL_FLAGS_NONE, -1, NULL, &error); if (error != NULL) { g_error("Unable to get property: %s", error->message); g_error_free(error); } g_assert(propret != NULL); testvar = g_variant_new_variant(g_variant_new_string("test-update")); testvar = g_variant_new_tuple(&testvar, 1); g_variant_ref_sink(testvar); g_assert(g_variant_equal(propret, testvar)); g_variant_unref(testvar); g_variant_unref(propret); /* Update the property wrong */ g_assert(!dbus_test_dbus_mock_object_update_property(mock, obj, "prop1", g_variant_new_uint32(5), NULL)); /* Check prop1 again */ propret = g_dbus_connection_call_sync(bus, "foo.test", "/test", "org.freedesktop.DBus.Properties", "Get", g_variant_new("(ss)", "foo.test.interface", "prop1"), G_VARIANT_TYPE("(v)"), G_DBUS_CALL_FLAGS_NONE, -1, NULL, &error); if (error != NULL) { g_error("Unable to get property: %s", error->message); g_error_free(error); } g_assert(propret != NULL); testvar = g_variant_new_variant(g_variant_new_string("test-update")); testvar = g_variant_new_tuple(&testvar, 1); g_variant_ref_sink(testvar); g_assert(g_variant_equal(propret, testvar)); g_variant_unref(testvar); g_variant_unref(propret); /* Clean up */ g_object_unref(mock); g_object_unref(service); wait_for_connection_close(bus); return; } void test_methods (void) { DbusTestService * service = dbus_test_service_new(NULL); g_assert(service != NULL); dbus_test_service_set_conf_file(service, SESSION_CONF); DbusTestDbusMock * mock = dbus_test_dbus_mock_new("foo.test"); g_assert(mock != NULL); DbusTestDbusMockObject * obj = dbus_test_dbus_mock_get_object(mock, "/test", "foo.test.interface", NULL); dbus_test_dbus_mock_object_add_method(mock, obj, "method1", G_VARIANT_TYPE("(ss)"), G_VARIANT_TYPE("s"), "ret = 'test'", NULL); dbus_test_service_add_task(service, DBUS_TEST_TASK(mock)); dbus_test_service_start_tasks(service); g_assert(dbus_test_task_get_state(DBUS_TEST_TASK(mock)) == DBUS_TEST_TASK_STATE_RUNNING); /* Check 'em */ GDBusConnection * bus = g_bus_get_sync(G_BUS_TYPE_SESSION, NULL, NULL); g_dbus_connection_set_exit_on_close(bus, FALSE); GVariant * propret = NULL; GVariant * testvar = NULL; GError * error = NULL; /* Check prop1 */ propret = g_dbus_connection_call_sync(bus, "foo.test", "/test", "foo.test.interface", "method1", g_variant_new("(ss)", "testin", "moretest"), G_VARIANT_TYPE("(s)"), G_DBUS_CALL_FLAGS_NONE, -1, NULL, &error); if (error != NULL) { g_error("Unable to call method1: %s", error->message); g_error_free(error); } g_assert(propret != NULL); testvar = g_variant_new_string("test"); testvar = g_variant_new_tuple(&testvar, 1); g_variant_ref_sink(testvar); g_assert(g_variant_equal(propret, testvar)); g_variant_unref(testvar); g_variant_unref(propret); /* Ask DBusMock if it got called */ g_assert(dbus_test_dbus_mock_object_check_method_call(mock, obj, "method1", NULL, NULL)); g_assert(dbus_test_dbus_mock_object_check_method_call(mock, obj, "method1", g_variant_new("(ss)", "testin", "moretest"), NULL)); g_assert(dbus_test_dbus_mock_object_clear_method_calls(mock, obj, NULL)); g_assert(!dbus_test_dbus_mock_object_check_method_call(mock, obj, "method1", NULL, NULL)); /* Clean up */ g_object_unref(mock); g_object_unref(service); wait_for_connection_close(bus); return; } static void signal_abc_emitted (GDBusConnection * connection, const gchar * sender, const gchar * path, const gchar * interface, const gchar * signal, GVariant * params, gpointer user_data) { if (g_variant_equal(params, g_variant_new_parsed("('a', 'b', 'c')"))) { guint * count = (guint *)user_data; (*count)++; } } void test_signals (void) { DbusTestService * service = dbus_test_service_new(NULL); g_assert(service != NULL); dbus_test_service_set_conf_file(service, SESSION_CONF); DbusTestDbusMock * mock = dbus_test_dbus_mock_new("foo.test"); g_assert(mock != NULL); DbusTestDbusMockObject * obj = dbus_test_dbus_mock_get_object(mock, "/test", "foo.test.interface", NULL); dbus_test_service_add_task(service, DBUS_TEST_TASK(mock)); dbus_test_service_start_tasks(service); g_assert(dbus_test_task_get_state(DBUS_TEST_TASK(mock)) == DBUS_TEST_TASK_STATE_RUNNING); GDBusConnection * bus = g_bus_get_sync(G_BUS_TYPE_SESSION, NULL, NULL); g_dbus_connection_set_exit_on_close(bus, FALSE); guint signal_count = 0; g_dbus_connection_signal_subscribe(bus, NULL, /* sender */ "foo.test.interface", "testsig", "/test", NULL, /* arg0 */ G_DBUS_SIGNAL_FLAGS_NONE, signal_emitted, &signal_count, NULL); /* user data cleanup */ g_assert(dbus_test_dbus_mock_object_emit_signal(mock, obj, "testsig", NULL, NULL, NULL)); g_usleep(100000); while (g_main_pending()) g_main_iteration(TRUE); g_assert(signal_count == 1); /* Signal with params */ guint signal_abc_count = 0; g_dbus_connection_signal_subscribe(bus, NULL, /* sender */ "foo.test.interface", "testsig_abc", "/test", NULL, /* arg0 */ G_DBUS_SIGNAL_FLAGS_NONE, signal_abc_emitted, &signal_abc_count, NULL); /* user data cleanup */ g_assert(dbus_test_dbus_mock_object_emit_signal(mock, obj, "testsig_abc", G_VARIANT_TYPE("(sss)"), g_variant_new_parsed("('a', 'b', 'c')"), NULL)); g_usleep(100000); while (g_main_pending()) g_main_iteration(TRUE); g_assert(signal_abc_count == 1); /* Clean up */ g_object_unref(mock); g_object_unref(service); wait_for_connection_close(bus); return; } void test_running (void) { DbusTestService * service = dbus_test_service_new(NULL); g_assert(service != NULL); dbus_test_service_set_conf_file(service, SESSION_CONF); DbusTestDbusMock * mock = dbus_test_dbus_mock_new("foo.test"); g_assert(mock != NULL); /* Startup the mock */ dbus_test_service_add_task(service, DBUS_TEST_TASK(mock)); dbus_test_service_start_tasks(service); GDBusConnection * bus = g_bus_get_sync(G_BUS_TYPE_SESSION, NULL, NULL); g_dbus_connection_set_exit_on_close(bus, FALSE); /* Add the object */ DbusTestDbusMockObject * obj = dbus_test_dbus_mock_get_object(mock, "/test", "foo.test.interface", NULL); g_assert(obj != NULL); g_assert(dbus_test_dbus_mock_object_add_method(mock, obj, "method1", G_VARIANT_TYPE("s"), G_VARIANT_TYPE("s"), "ret = 'test'", NULL)); GVariant * propret = NULL; GVariant * testvar = NULL; GError * error = NULL; /* Check method */ propret = g_dbus_connection_call_sync(bus, "foo.test", "/test", "foo.test.interface", "method1", g_variant_new("(s)", "testin"), G_VARIANT_TYPE("(s)"), G_DBUS_CALL_FLAGS_NONE, -1, NULL, &error); if (error != NULL) { g_error("Unable to call method1: %s", error->message); g_error_free(error); } g_assert(propret != NULL); testvar = g_variant_new_string("test"); testvar = g_variant_new_tuple(&testvar, 1); g_variant_ref_sink(testvar); g_assert(g_variant_equal(propret, testvar)); g_variant_unref(testvar); g_variant_unref(propret); /* Add a property */ g_assert(dbus_test_dbus_mock_object_add_property(mock, obj, "prop1", G_VARIANT_TYPE_STRING, g_variant_new_string("test"), NULL)); /* Check prop1 */ propret = g_dbus_connection_call_sync(bus, "foo.test", "/test", "org.freedesktop.DBus.Properties", "Get", g_variant_new("(ss)", "foo.test.interface", "prop1"), G_VARIANT_TYPE("(v)"), G_DBUS_CALL_FLAGS_NONE, -1, NULL, &error); if (error != NULL) { g_error("Unable to get property: %s", error->message); g_error_free(error); } g_assert(propret != NULL); testvar = g_variant_new_variant(g_variant_new_string("test")); testvar = g_variant_new_tuple(&testvar, 1); g_variant_ref_sink(testvar); g_assert(g_variant_equal(propret, testvar)); g_variant_unref(testvar); g_variant_unref(propret); /* Clean up */ g_object_unref(mock); g_object_unref(service); wait_for_connection_close(bus); return; } void test_running_system (void) { DbusTestService * service = dbus_test_service_new(NULL); g_assert(service != NULL); dbus_test_service_set_bus(service, DBUS_TEST_SERVICE_BUS_SYSTEM); dbus_test_service_set_conf_file(service, SESSION_CONF); DbusTestDbusMock * mock = dbus_test_dbus_mock_new("foo.test"); g_assert(mock != NULL); dbus_test_task_set_bus(DBUS_TEST_TASK(mock), DBUS_TEST_SERVICE_BUS_SYSTEM); /* Startup the mock */ dbus_test_service_add_task(service, DBUS_TEST_TASK(mock)); dbus_test_service_start_tasks(service); GDBusConnection * bus = g_bus_get_sync(G_BUS_TYPE_SYSTEM, NULL, NULL); g_dbus_connection_set_exit_on_close(bus, FALSE); /* Add the object */ DbusTestDbusMockObject * obj = dbus_test_dbus_mock_get_object(mock, "/test", "foo.test.interface", NULL); g_assert(obj != NULL); g_assert(dbus_test_dbus_mock_object_add_method(mock, obj, "method1", G_VARIANT_TYPE("s"), G_VARIANT_TYPE("s"), "ret = 'test'", NULL)); GVariant * propret = NULL; GVariant * testvar = NULL; GError * error = NULL; /* Check method */ propret = g_dbus_connection_call_sync(bus, "foo.test", "/test", "foo.test.interface", "method1", g_variant_new("(s)", "testin"), G_VARIANT_TYPE("(s)"), G_DBUS_CALL_FLAGS_NONE, -1, NULL, &error); if (error != NULL) { g_error("Unable to call method1: %s", error->message); g_error_free(error); } g_assert(propret != NULL); testvar = g_variant_new_string("test"); testvar = g_variant_new_tuple(&testvar, 1); g_variant_ref_sink(testvar); g_assert(g_variant_equal(propret, testvar)); g_variant_unref(testvar); g_variant_unref(propret); /* Clean up */ g_object_unref(mock); g_object_unref(service); wait_for_connection_close(bus); } void test_interfaces (void) { DbusTestService * service = dbus_test_service_new(NULL); g_assert(service != NULL); dbus_test_service_set_conf_file(service, SESSION_CONF); DbusTestDbusMock * mock = dbus_test_dbus_mock_new("foo.test"); g_assert(mock != NULL); /* Add the first object */ DbusTestDbusMockObject * obj1 = dbus_test_dbus_mock_get_object(mock, "/test", "foo.test.interface", NULL); g_assert(obj1 != NULL); g_assert(dbus_test_dbus_mock_object_add_method(mock, obj1, "testmethod", G_VARIANT_TYPE("s"), G_VARIANT_TYPE("s"), "ret = 'test'", NULL)); /* Add the second object */ DbusTestDbusMockObject * obj2 = dbus_test_dbus_mock_get_object(mock, "/test", "foo.test.otherinterface", NULL); g_assert(obj2 != NULL); g_assert(dbus_test_dbus_mock_object_add_method(mock, obj2, "testothermethod", G_VARIANT_TYPE("s"), G_VARIANT_TYPE("s"), "ret = 'test'", NULL)); /* Startup the mock */ dbus_test_service_add_task(service, DBUS_TEST_TASK(mock)); dbus_test_service_start_tasks(service); GDBusConnection * bus = g_bus_get_sync(G_BUS_TYPE_SESSION, NULL, NULL); g_dbus_connection_set_exit_on_close(bus, FALSE); /* Vars */ GVariant * propret = NULL; GError * error = NULL; guint len = 0; /* Check method */ propret = g_dbus_connection_call_sync(bus, "foo.test", "/test", "foo.test.interface", "testmethod", g_variant_new("(s)", "testin"), G_VARIANT_TYPE("(s)"), G_DBUS_CALL_FLAGS_NONE, -1, NULL, &error); if (error != NULL) { g_error("Unable to call testmethod: %s", error->message); g_error_free(error); } g_assert(propret != NULL); g_variant_unref(propret); g_assert(dbus_test_dbus_mock_object_get_method_calls(mock, obj1, "testmethod", &len, NULL) != NULL); g_assert(len == 1); /* Check method */ len = 0; propret = g_dbus_connection_call_sync(bus, "foo.test", "/test", "foo.test.otherinterface", "testothermethod", g_variant_new("(s)", "testin"), G_VARIANT_TYPE("(s)"), G_DBUS_CALL_FLAGS_NONE, -1, NULL, &error); if (error != NULL) { g_error("Unable to call testothermethod: %s", error->message); g_error_free(error); } g_assert(propret != NULL); g_variant_unref(propret); g_assert(dbus_test_dbus_mock_object_get_method_calls(mock, obj2, "testothermethod", &len, NULL) != NULL); g_assert(len == 1); /* Clean up */ g_object_unref(mock); g_object_unref(service); wait_for_connection_close(bus); return; } /* Build our test suite */ void test_libdbustest_mock_suite (void) { g_test_add_func ("/libdbustest/mock/basic", test_basic); g_test_add_func ("/libdbustest/mock/properties", test_properties); g_test_add_func ("/libdbustest/mock/methods", test_methods); g_test_add_func ("/libdbustest/mock/signals", test_signals); g_test_add_func ("/libdbustest/mock/running", test_running); g_test_add_func ("/libdbustest/mock/running-system", test_running_system); g_test_add_func ("/libdbustest/mock/interfaces", test_interfaces); return; } int main (int argc, char ** argv) { #ifndef GLIB_VERSION_2_36 g_type_init (); #endif g_test_init (&argc, &argv, NULL); test_libdbustest_mock_suite(); g_log_set_always_fatal(G_LOG_LEVEL_ERROR); return g_test_run(); } ./src/0000755000004100000410000000000012763551710012041 5ustar www-datawww-data./src/Makefile.am0000644000004100000410000000064212763551700014076 0ustar www-datawww-data bin_PROGRAMS = dbus-test-runner dbus_test_runner_SOURCES = dbus-test-runner.c dbus_test_runner_CFLAGS = $(DBUS_TEST_RUNNER_CFLAGS) \ $(COVERAGE_CFLAGS) \ -I$(top_srcdir) \ -DDEFAULT_SESSION_CONF="\"$(datadir)/dbus-test-runner/session.conf\"" \ -Wall -Werror -Wextra dbus_test_runner_LDADD = $(DBUS_TEST_RUNNER_LIBS) \ $(top_builddir)/libdbustest/libdbustest.la dbus_test_runner_LDFLAGS = $(COVERAGE_LDFLAGS) ./src/dbus-test-runner.c0000644000004100000410000002665312763551710015442 0ustar www-datawww-data/* Copyright 2010 Canonical Ltd. Authors: Ted Gould This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License version 3, as published by the Free Software Foundation. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranties of MERCHANTABILITY, SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program. If not, see . */ #include #include #include static DbusTestServiceBus bus_type = DBUS_TEST_SERVICE_BUS_SESSION; static gint max_wait = 60; static gboolean keep_env = FALSE; static DbusTestProcess * last_task = NULL; static DbusTestService * service = NULL; static gboolean timeout = FALSE; #define NAME_SET "dbus-test-runner-name-set" static gboolean option_bus_type (G_GNUC_UNUSED const gchar * arg, const gchar * value, G_GNUC_UNUSED gpointer data, GError ** error) { if (bus_type != DBUS_TEST_SERVICE_BUS_SESSION) { g_set_error_literal(error, G_OPTION_ERROR, G_OPTION_ERROR_BAD_VALUE, "Bus type set more than once"); return TRUE; } if (g_strcmp0(value, "session") == 0) { bus_type = DBUS_TEST_SERVICE_BUS_SESSION; } else if (g_strcmp0(value, "system") == 0) { bus_type = DBUS_TEST_SERVICE_BUS_SYSTEM; } else if (g_strcmp0(value, "both") == 0) { bus_type = DBUS_TEST_SERVICE_BUS_BOTH; } else { g_set_error(error, G_OPTION_ERROR, G_OPTION_ERROR_BAD_VALUE, "Bus type '%s' unknown", value); } return TRUE; } static gboolean option_task (G_GNUC_UNUSED const gchar * arg, const gchar * value, G_GNUC_UNUSED gpointer data, G_GNUC_UNUSED GError ** error) { if (last_task != NULL) { g_object_unref(last_task); last_task = NULL; } last_task = dbus_test_process_new(value); dbus_test_service_add_task(service, DBUS_TEST_TASK(last_task)); return TRUE; } static gboolean option_taskname (G_GNUC_UNUSED const gchar * arg, const gchar * value, G_GNUC_UNUSED gpointer data, GError ** error) { if (last_task == NULL) { g_set_error(error, G_OPTION_ERROR, G_OPTION_ERROR_BAD_VALUE, "No task to put the name %s on.", value); return FALSE; } if (g_object_get_data(G_OBJECT(last_task), NAME_SET)) { g_set_error(error, G_OPTION_ERROR, G_OPTION_ERROR_BAD_VALUE, "Task already has the name %s. Asked to put %s on it.", dbus_test_task_get_name(DBUS_TEST_TASK(last_task)), value); return FALSE; } g_object_set_data(G_OBJECT(last_task), NAME_SET, GINT_TO_POINTER(TRUE)); dbus_test_task_set_name(DBUS_TEST_TASK(last_task), value); return TRUE; } static gboolean option_taskbus (G_GNUC_UNUSED const gchar * arg, const gchar * value, G_GNUC_UNUSED gpointer data, GError ** error) { if (last_task == NULL) { g_set_error(error, G_OPTION_ERROR, G_OPTION_ERROR_BAD_VALUE, "No task to put the name %s on.", value); return FALSE; } if (g_strcmp0(value, "session") == 0) { dbus_test_task_set_bus(DBUS_TEST_TASK(last_task), DBUS_TEST_SERVICE_BUS_SESSION); } else if (g_strcmp0(value, "system") == 0) { dbus_test_task_set_bus(DBUS_TEST_TASK(last_task), DBUS_TEST_SERVICE_BUS_SYSTEM); } else if (g_strcmp0(value, "both") == 0) { dbus_test_task_set_bus(DBUS_TEST_TASK(last_task), DBUS_TEST_SERVICE_BUS_BOTH); } else { g_set_error(error, G_OPTION_ERROR, G_OPTION_ERROR_BAD_VALUE, "Bus type '%s' unknown", value); } return TRUE; } static gboolean option_complete (G_GNUC_UNUSED const gchar * arg, G_GNUC_UNUSED const gchar * value, G_GNUC_UNUSED gpointer data, GError ** error) { if (last_task == NULL) { g_set_error(error, G_OPTION_ERROR, G_OPTION_ERROR_BAD_VALUE, "No task to put adjust return on."); return FALSE; } if (dbus_test_task_get_wait_finished(DBUS_TEST_TASK(last_task))) { g_set_error(error, G_OPTION_ERROR, G_OPTION_ERROR_BAD_VALUE, "Task has already be setup to wait until finished."); return FALSE; } dbus_test_task_set_wait_finished(DBUS_TEST_TASK(last_task), TRUE); return TRUE; } static gboolean option_noreturn (G_GNUC_UNUSED const gchar * arg, G_GNUC_UNUSED const gchar * value, G_GNUC_UNUSED gpointer data, GError ** error) { if (last_task == NULL) { g_set_error(error, G_OPTION_ERROR, G_OPTION_ERROR_BAD_VALUE, "No task to put adjust return on."); return FALSE; } if (dbus_test_task_get_return(DBUS_TEST_TASK(last_task)) != DBUS_TEST_TASK_RETURN_NORMAL) { g_set_error(error, G_OPTION_ERROR, G_OPTION_ERROR_BAD_VALUE, "Task return type has already been modified."); return FALSE; } dbus_test_task_set_return(DBUS_TEST_TASK(last_task), DBUS_TEST_TASK_RETURN_IGNORE); return TRUE; } static gboolean option_invert (G_GNUC_UNUSED const gchar * arg, G_GNUC_UNUSED const gchar * value, G_GNUC_UNUSED gpointer data, GError ** error) { if (last_task == NULL) { g_set_error(error, G_OPTION_ERROR, G_OPTION_ERROR_BAD_VALUE, "No task to put adjust return on."); return FALSE; } if (dbus_test_task_get_return(DBUS_TEST_TASK(last_task)) != DBUS_TEST_TASK_RETURN_NORMAL) { g_set_error(error, G_OPTION_ERROR, G_OPTION_ERROR_BAD_VALUE, "Task return type has already been modified."); return FALSE; } dbus_test_task_set_return(DBUS_TEST_TASK(last_task), DBUS_TEST_TASK_RETURN_INVERT); return TRUE; } static gboolean option_param (G_GNUC_UNUSED const gchar * arg, const gchar * value, G_GNUC_UNUSED gpointer data, GError ** error) { if (last_task == NULL) { g_set_error(error, G_OPTION_ERROR, G_OPTION_ERROR_BAD_VALUE, "No task to put adjust return on."); return FALSE; } dbus_test_process_append_param(last_task, value); return TRUE; } static gboolean option_wait (G_GNUC_UNUSED const gchar * arg, const gchar * value, G_GNUC_UNUSED gpointer data, GError ** error) { if (last_task == NULL) { g_set_error(error, G_OPTION_ERROR, G_OPTION_ERROR_BAD_VALUE, "No task to add a wait on %s for.", value); return FALSE; } if (dbus_test_task_get_wait_for(DBUS_TEST_TASK(last_task)) != NULL) { g_set_error(error, G_OPTION_ERROR, G_OPTION_ERROR_BAD_VALUE, "Task is already waiting for %s. Asked to wait for %s", dbus_test_task_get_wait_for(DBUS_TEST_TASK(last_task)), value); return FALSE; } dbus_test_task_set_wait_for(DBUS_TEST_TASK(last_task), value); return TRUE; } static gboolean max_wait_hit (G_GNUC_UNUSED gpointer user_data) { g_warning("Timing out at maximum wait of %d seconds.", max_wait); dbus_test_service_stop(service); timeout = TRUE; return FALSE; } static gchar * dbus_configfile = NULL; static gchar * dbus_daemon = NULL; static gchar * bustle_cmd = NULL; static gchar * bustle_datafile = NULL; static GOptionEntry general_options[] = { {"dbus-daemon", 0, 0, G_OPTION_ARG_FILENAME, &dbus_daemon, "Path to the DBus deamon to use. Defaults to 'dbus-daemon'.", "executable"}, {"dbus-config", 'd', 0, G_OPTION_ARG_FILENAME, &dbus_configfile, "Configuration file for newly created DBus server. Defaults to '" DEFAULT_SESSION_CONF "'.", "config_file"}, {"bustle-monitor", 0, 0, G_OPTION_ARG_FILENAME, &bustle_cmd, "Path to the Bustle DBus Monitor to use. Defaults to 'bustle-dbus-monitor'.", "executable"}, {"bustle-data", 'b', 0, G_OPTION_ARG_FILENAME, &bustle_datafile, "A file to write out data from the bustle logger to.", "data_file"}, {"max-wait", 'm', 0, G_OPTION_ARG_INT, &max_wait, "The maximum amount of time the test runner will wait for the test to complete. Default is 30 seconds.", "seconds"}, {"keep-env", 0, 0, G_OPTION_ARG_NONE, &keep_env, "Whether to propagate the execution environment to the dbus-server and all the services activated by it. By default the environment is cleared.", NULL }, {"bus-type", 0, 0, G_OPTION_ARG_CALLBACK, option_bus_type, "Configures which buses are represented by the tool to the tasks. Default: session", "{session|system|both}" }, { NULL, 0, 0, 0, NULL, NULL, NULL } }; static GOptionEntry task_options[] = { {"task", 't', G_OPTION_FLAG_FILENAME, G_OPTION_ARG_CALLBACK, option_task, "Defines a new task to run under our private DBus session.", "executable"}, {"task-name", 'n', 0, G_OPTION_ARG_CALLBACK, option_taskname, "A string to label output from the previously defined task. Defaults to taskN.", "name"}, {"task-bus", 0, 0, G_OPTION_ARG_CALLBACK, option_taskbus, "Configures which bus the task expects to connect to. Default: both", "{session|system|both}"}, {"ignore-return", 'r', G_OPTION_FLAG_NO_ARG, G_OPTION_ARG_CALLBACK, option_noreturn, "Do not use the return value of the task to calculate whether the test passes or fails.", NULL}, {"invert-return", 'i', G_OPTION_FLAG_NO_ARG, G_OPTION_ARG_CALLBACK, option_invert, "Invert the return value of the task before calculating whether the test passes or fails.", NULL}, {"parameter", 'p', 0, G_OPTION_ARG_CALLBACK, option_param, "Add a parameter to the call of this utility. May be called as many times as you'd like.", NULL}, {"wait-for", 'f', 0, G_OPTION_ARG_CALLBACK, option_wait, "A dbus-name that should appear on the bus before this task is started", "dbus-name"}, {"wait-until-complete", 'c', G_OPTION_FLAG_NO_ARG,G_OPTION_ARG_CALLBACK, option_complete, "Signal that we should wait until this task exits even if we don't need the return value", NULL}, { NULL, 0, 0, 0, NULL, NULL, NULL } }; int main (int argc, char * argv[]) { GError * error = NULL; GOptionContext * context; #ifndef GLIB_VERSION_2_36 g_type_init(); #endif service = dbus_test_service_new(NULL); context = g_option_context_new("- run multiple tasks under an independent DBus session bus"); g_option_context_add_main_entries(context, general_options, "dbus-runner"); GOptionGroup * taskgroup = g_option_group_new("task-control", "Task control options", "Options that are used to control how the task is handled by the test runner.", NULL, NULL); g_option_group_add_entries(taskgroup, task_options); g_option_context_add_group(context, taskgroup); if (!g_option_context_parse(context, &argc, &argv, &error)) { g_print("option parsing failed: %s\n", error->message); g_error_free(error); return 1; } dbus_test_service_set_bus(service, bus_type); if (dbus_daemon != NULL) { dbus_test_service_set_daemon(service, dbus_daemon); } if (dbus_configfile != NULL) { dbus_test_service_set_conf_file(service, dbus_configfile); } if (bustle_datafile != NULL) { DbusTestBustle * bustler = dbus_test_bustle_new(bustle_datafile); /* We want to ensure that bustle captures all the data so start it first */ dbus_test_service_add_task_with_priority(service, DBUS_TEST_TASK(bustler), DBUS_TEST_SERVICE_PRIORITY_FIRST); if (bustle_cmd != NULL) { dbus_test_bustle_set_executable(bustler, bustle_cmd); } g_object_unref(bustler); } if (max_wait > 0) { g_timeout_add_seconds(max_wait, max_wait_hit, NULL); } dbus_test_service_set_keep_environment(service, keep_env); /* These should all be in the service now */ if (last_task != NULL) { g_object_unref(last_task); last_task = NULL; } else { g_critical("No tasks assigned"); g_object_unref(service); return -1; } gint service_status = dbus_test_service_run(service); g_object_unref(service); if (timeout) { return -1; } else { return service_status; } } ./README0000644000004100000410000000000012763551700012117 0ustar www-datawww-data./po/0000755000004100000410000000000012763551700011667 5ustar www-datawww-data./po/Makefile.in.in0000644000004100000410000001604612763551700014350 0ustar www-datawww-data# Makefile for program source directory in GNU NLS utilities package. # Copyright (C) 1995, 1996, 1997 by Ulrich Drepper # Copyright (C) 2004-2008 Rodney Dawes # # This file may be copied and used freely without restrictions. It may # be used in projects which are not available under a GNU Public License, # but which still want to provide support for the GNU gettext functionality. # # - Modified by Owen Taylor to use GETTEXT_PACKAGE # instead of PACKAGE and to look for po2tbl in ./ not in intl/ # # - Modified by jacob berkman to install # Makefile.in.in and po2tbl.sed.in for use with glib-gettextize # # - Modified by Rodney Dawes for use with intltool # # We have the following line for use by intltoolize: # INTLTOOL_MAKEFILE GETTEXT_PACKAGE = @GETTEXT_PACKAGE@ PACKAGE = @PACKAGE@ VERSION = @VERSION@ SHELL = @SHELL@ srcdir = @srcdir@ top_srcdir = @top_srcdir@ top_builddir = @top_builddir@ VPATH = @srcdir@ prefix = @prefix@ exec_prefix = @exec_prefix@ datadir = @datadir@ datarootdir = @datarootdir@ libdir = @libdir@ DATADIRNAME = @DATADIRNAME@ itlocaledir = $(prefix)/$(DATADIRNAME)/locale subdir = po install_sh = @install_sh@ # Automake >= 1.8 provides @mkdir_p@. # Until it can be supposed, use the safe fallback: mkdir_p = $(install_sh) -d INSTALL = @INSTALL@ INSTALL_DATA = @INSTALL_DATA@ GMSGFMT = @GMSGFMT@ MSGFMT = @MSGFMT@ XGETTEXT = @XGETTEXT@ INTLTOOL_UPDATE = @INTLTOOL_UPDATE@ INTLTOOL_EXTRACT = @INTLTOOL_EXTRACT@ MSGMERGE = INTLTOOL_EXTRACT="$(INTLTOOL_EXTRACT)" XGETTEXT="$(XGETTEXT)" srcdir=$(srcdir) $(INTLTOOL_UPDATE) --gettext-package $(GETTEXT_PACKAGE) --dist GENPOT = INTLTOOL_EXTRACT="$(INTLTOOL_EXTRACT)" XGETTEXT="$(XGETTEXT)" srcdir=$(srcdir) $(INTLTOOL_UPDATE) --gettext-package $(GETTEXT_PACKAGE) --pot ALL_LINGUAS = @ALL_LINGUAS@ PO_LINGUAS=$(shell if test -r $(srcdir)/LINGUAS; then grep -v "^\#" $(srcdir)/LINGUAS; else echo "$(ALL_LINGUAS)"; fi) USER_LINGUAS=$(shell if test -n "$(LINGUAS)"; then LLINGUAS="$(LINGUAS)"; ALINGUAS="$(ALL_LINGUAS)"; for lang in $$LLINGUAS; do if test -n "`grep \^$$lang$$ $(srcdir)/LINGUAS 2>/dev/null`" -o -n "`echo $$ALINGUAS|tr ' ' '\n'|grep \^$$lang$$`"; then printf "$$lang "; fi; done; fi) USE_LINGUAS=$(shell if test -n "$(USER_LINGUAS)" -o -n "$(LINGUAS)"; then LLINGUAS="$(USER_LINGUAS)"; else if test -n "$(PO_LINGUAS)"; then LLINGUAS="$(PO_LINGUAS)"; else LLINGUAS="$(ALL_LINGUAS)"; fi; fi; for lang in $$LLINGUAS; do printf "$$lang "; done) POFILES=$(shell LINGUAS="$(PO_LINGUAS)"; for lang in $$LINGUAS; do printf "$$lang.po "; done) DISTFILES = Makefile.in.in POTFILES.in $(POFILES) EXTRA_DISTFILES = ChangeLog POTFILES.skip Makevars LINGUAS POTFILES = \ # This comment gets stripped out CATALOGS=$(shell LINGUAS="$(USE_LINGUAS)"; for lang in $$LINGUAS; do printf "$$lang.gmo "; done) .SUFFIXES: .SUFFIXES: .po .pox .gmo .mo .msg .cat AM_DEFAULT_VERBOSITY = @AM_DEFAULT_VERBOSITY@ INTLTOOL_V_MSGFMT = $(INTLTOOL__v_MSGFMT_$(V)) INTLTOOL__v_MSGFMT_= $(INTLTOOL__v_MSGFMT_$(AM_DEFAULT_VERBOSITY)) INTLTOOL__v_MSGFMT_0 = @echo " MSGFMT" $@; .po.pox: $(MAKE) $(GETTEXT_PACKAGE).pot $(MSGMERGE) $< $(GETTEXT_PACKAGE).pot -o $*.pox .po.mo: $(INTLTOOL_V_MSGFMT)$(MSGFMT) -o $@ $< .po.gmo: $(INTLTOOL_V_MSGFMT)file=`echo $* | sed 's,.*/,,'`.gmo \ && rm -f $$file && $(GMSGFMT) -o $$file $< .po.cat: sed -f ../intl/po2msg.sed < $< > $*.msg \ && rm -f $@ && gencat $@ $*.msg all: all-@USE_NLS@ all-yes: $(CATALOGS) all-no: $(GETTEXT_PACKAGE).pot: $(POTFILES) $(GENPOT) install: install-data install-data: install-data-@USE_NLS@ install-data-no: all install-data-yes: all linguas="$(USE_LINGUAS)"; \ for lang in $$linguas; do \ dir=$(DESTDIR)$(itlocaledir)/$$lang/LC_MESSAGES; \ $(mkdir_p) $$dir; \ if test -r $$lang.gmo; then \ $(INSTALL_DATA) $$lang.gmo $$dir/$(GETTEXT_PACKAGE).mo; \ echo "installing $$lang.gmo as $$dir/$(GETTEXT_PACKAGE).mo"; \ else \ $(INSTALL_DATA) $(srcdir)/$$lang.gmo $$dir/$(GETTEXT_PACKAGE).mo; \ echo "installing $(srcdir)/$$lang.gmo as" \ "$$dir/$(GETTEXT_PACKAGE).mo"; \ fi; \ if test -r $$lang.gmo.m; then \ $(INSTALL_DATA) $$lang.gmo.m $$dir/$(GETTEXT_PACKAGE).mo.m; \ echo "installing $$lang.gmo.m as $$dir/$(GETTEXT_PACKAGE).mo.m"; \ else \ if test -r $(srcdir)/$$lang.gmo.m ; then \ $(INSTALL_DATA) $(srcdir)/$$lang.gmo.m \ $$dir/$(GETTEXT_PACKAGE).mo.m; \ echo "installing $(srcdir)/$$lang.gmo.m as" \ "$$dir/$(GETTEXT_PACKAGE).mo.m"; \ else \ true; \ fi; \ fi; \ done # Empty stubs to satisfy archaic automake needs dvi info ctags tags CTAGS TAGS ID: # Define this as empty until I found a useful application. install-exec installcheck: uninstall: linguas="$(USE_LINGUAS)"; \ for lang in $$linguas; do \ rm -f $(DESTDIR)$(itlocaledir)/$$lang/LC_MESSAGES/$(GETTEXT_PACKAGE).mo; \ rm -f $(DESTDIR)$(itlocaledir)/$$lang/LC_MESSAGES/$(GETTEXT_PACKAGE).mo.m; \ done check: all $(GETTEXT_PACKAGE).pot rm -f missing notexist srcdir=$(srcdir) $(INTLTOOL_UPDATE) -m if [ -r missing -o -r notexist ]; then \ exit 1; \ fi mostlyclean: rm -f *.pox $(GETTEXT_PACKAGE).pot *.old.po cat-id-tbl.tmp rm -f .intltool-merge-cache clean: mostlyclean distclean: clean rm -f Makefile Makefile.in POTFILES stamp-it rm -f *.mo *.msg *.cat *.cat.m *.gmo maintainer-clean: distclean @echo "This command is intended for maintainers to use;" @echo "it deletes files that may require special tools to rebuild." rm -f Makefile.in.in distdir = ../$(PACKAGE)-$(VERSION)/$(subdir) dist distdir: $(DISTFILES) dists="$(DISTFILES)"; \ extra_dists="$(EXTRA_DISTFILES)"; \ for file in $$extra_dists; do \ test -f $(srcdir)/$$file && dists="$$dists $(srcdir)/$$file"; \ done; \ for file in $$dists; do \ test -f $$file || file="$(srcdir)/$$file"; \ ln $$file $(distdir) 2> /dev/null \ || cp -p $$file $(distdir); \ done update-po: Makefile $(MAKE) $(GETTEXT_PACKAGE).pot tmpdir=`pwd`; \ linguas="$(USE_LINGUAS)"; \ for lang in $$linguas; do \ echo "$$lang:"; \ result="`$(MSGMERGE) -o $$tmpdir/$$lang.new.po $$lang`"; \ if $$result; then \ if cmp $(srcdir)/$$lang.po $$tmpdir/$$lang.new.po >/dev/null 2>&1; then \ rm -f $$tmpdir/$$lang.new.po; \ else \ if mv -f $$tmpdir/$$lang.new.po $$lang.po; then \ :; \ else \ echo "msgmerge for $$lang.po failed: cannot move $$tmpdir/$$lang.new.po to $$lang.po" 1>&2; \ rm -f $$tmpdir/$$lang.new.po; \ exit 1; \ fi; \ fi; \ else \ echo "msgmerge for $$lang.gmo failed!"; \ rm -f $$tmpdir/$$lang.new.po; \ fi; \ done Makefile POTFILES: stamp-it @if test ! -f $@; then \ rm -f stamp-it; \ $(MAKE) stamp-it; \ fi stamp-it: Makefile.in.in $(top_builddir)/config.status POTFILES.in cd $(top_builddir) \ && CONFIG_FILES=$(subdir)/Makefile.in CONFIG_HEADERS= CONFIG_LINKS= \ $(SHELL) ./config.status # Tell versions [3.59,3.63) of GNU make not to export all variables. # Otherwise a system limit (for SysV at least) may be exceeded. .NOEXPORT: ./po/POTFILES.in0000644000004100000410000000002712763551700013443 0ustar www-datawww-datasrc/dbus-test-runner.c ./Makefile.am0000644000004100000410000000020012763551700013275 0ustar www-datawww-dataSUBDIRS = \ data \ libdbustest \ src \ tests \ po src: libdbustest tests: src include $(top_srcdir)/Makefile.am.coverage ./AUTHORS0000644000004100000410000000000012763551700012307 0ustar www-datawww-data./m4/0000755000004100000410000000000012763551700011571 5ustar www-datawww-data./m4/gcov.m40000644000004100000410000000470512763551700012777 0ustar www-datawww-data# Checks for existence of coverage tools: # * gcov # * lcov # * genhtml # * gcovr # # Sets ac_cv_check_gcov to yes if tooling is present # and reports the executables to the variables LCOV, GCOVR and GENHTML. AC_DEFUN([AC_TDD_GCOV], [ AC_ARG_ENABLE(gcov, AS_HELP_STRING([--enable-gcov], [enable coverage testing with gcov]), [use_gcov=$enableval], [use_gcov=no]) if test "x$use_gcov" = "xyes"; then # we need gcc: if test "$GCC" != "yes"; then AC_MSG_ERROR([GCC is required for --enable-gcov]) fi # Check if ccache is being used AC_CHECK_PROG(SHTOOL, shtool, shtool) case `$SHTOOL path $CC` in *ccache*[)] gcc_ccache=yes;; *[)] gcc_ccache=no;; esac if test "$gcc_ccache" = "yes" && (test -z "$CCACHE_DISABLE" || test "$CCACHE_DISABLE" != "1"); then AC_MSG_ERROR([ccache must be disabled when --enable-gcov option is used. You can disable ccache by setting environment variable CCACHE_DISABLE=1.]) fi lcov_version_list="1.6 1.7 1.8 1.9" AC_CHECK_PROG(LCOV, lcov, lcov) AC_CHECK_PROG(GENHTML, genhtml, genhtml) if test "$LCOV"; then AC_CACHE_CHECK([for lcov version], glib_cv_lcov_version, [ glib_cv_lcov_version=invalid lcov_version=`$LCOV -v 2>/dev/null | $SED -e 's/^.* //'` for lcov_check_version in $lcov_version_list; do if test "$lcov_version" = "$lcov_check_version"; then glib_cv_lcov_version="$lcov_check_version (ok)" fi done ]) else lcov_msg="To enable code coverage reporting you must have one of the following lcov versions installed: $lcov_version_list" AC_MSG_ERROR([$lcov_msg]) fi case $glib_cv_lcov_version in ""|invalid[)] lcov_msg="You must have one of the following versions of lcov: $lcov_version_list (found: $lcov_version)." AC_MSG_ERROR([$lcov_msg]) LCOV="exit 0;" ;; esac if test -z "$GENHTML"; then AC_MSG_ERROR([Could not find genhtml from the lcov package]) fi ac_cv_check_gcov=yes ac_cv_check_lcov=yes # Remove all optimization flags from CFLAGS changequote({,}) CFLAGS=`echo "$CFLAGS" | $SED -e 's/-O[0-9]*//g'` changequote([,]) # Add the special gcc flags COVERAGE_CFLAGS="-O0 -fprofile-arcs -ftest-coverage" COVERAGE_CXXFLAGS="-O0 -fprofile-arcs -ftest-coverage" COVERAGE_LDFLAGS="-lgcov" # Check availability of gcovr AC_CHECK_PROG(GCOVR, gcovr, gcovr) if test -z "$GCOVR"; then ac_cv_check_gcovr=no else ac_cv_check_gcovr=yes fi fi ]) # AC_TDD_GCOV ./libdbustest/0000755000004100000410000000000012763551710013576 5ustar www-datawww-data./libdbustest/dbustest.pc.in0000644000004100000410000000036212763551700016364 0ustar www-datawww-datalibdir=@libdir@ includedir=@includedir@ Cflags: -I${includedir}/libdbustest-@apiversion@ Requires: glib-2.0 Libs: -L${libdir} -ldbustest Name: libdbustest Description: A library to assist testing with a fresh DBus daemon Version: @VERSION@ ./libdbustest/dbus-mock.c0000644000004100000410000010666512763551700015643 0ustar www-datawww-data/* Copyright 2013 Canonical Ltd. Authors: Ted Gould This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License version 3, as published by the Free Software Foundation. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranties of MERCHANTABILITY, SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program. If not, see . */ #ifdef HAVE_CONFIG_H #include "config.h" #endif #include "dbus-test.h" #include "dbus-mock-iface.h" #include "string.h" /* strlen */ typedef struct _MockObjectProperty MockObjectProperty; typedef struct _MockObjectMethod MockObjectMethod; struct _DbusTestDbusMockPrivate { gchar * name; _DbusMockIfaceOrgFreedesktopDBusMock * proxy; /* Entries of DbusTestDbusMockObject */ GList * objects; GHashTable * object_proxies; GDBusConnection * bus; GCancellable * cancel; }; /* Represents every object on the bus that we're mocking */ struct _DbusTestDbusMockObject { gchar * object_path; gchar * interface; GArray * properties; GArray * methods; }; /* A property on an object */ struct _MockObjectProperty { gchar * name; GVariantType * type; GVariant * value; }; /* A method on an object */ struct _MockObjectMethod { gchar * name; GVariantType * in; GVariantType * out; gchar * code; GArray * calls; }; enum { PROP_0, PROP_DBUS_NAME, NUM_PROPS }; enum { ERROR_METHOD_NOT_FOUND, NUM_ERRORS }; static guint mock_cnt = 0; #define DBUS_TEST_DBUS_MOCK_GET_PRIVATE(o) \ (G_TYPE_INSTANCE_GET_PRIVATE ((o), DBUS_TEST_TYPE_DBUS_MOCK, DbusTestDbusMockPrivate)) static void dbus_test_dbus_mock_class_init (DbusTestDbusMockClass *klass); static void dbus_test_dbus_mock_init (DbusTestDbusMock *self); static void constructed (GObject * object); static void dbus_test_dbus_mock_dispose (GObject *object); static void dbus_test_dbus_mock_finalize (GObject *object); static void run (DbusTestTask * task); static void get_property (GObject * object, guint property_id, GValue * value, GParamSpec * pspec); static void set_property (GObject * object, guint property_id, const GValue * value, GParamSpec * pspec); static void object_free (gpointer data); static void method_free (gpointer data); static void property_free (gpointer data); G_DEFINE_TYPE (DbusTestDbusMock, dbus_test_dbus_mock, DBUS_TEST_TYPE_PROCESS); G_DEFINE_QUARK("dbus-test-dbus-mock", _dbus_mock); /* Initialize Class */ static void dbus_test_dbus_mock_class_init (DbusTestDbusMockClass *klass) { GObjectClass *object_class = G_OBJECT_CLASS (klass); g_type_class_add_private (klass, sizeof (DbusTestDbusMockPrivate)); object_class->dispose = dbus_test_dbus_mock_dispose; object_class->finalize = dbus_test_dbus_mock_finalize; object_class->get_property = get_property; object_class->set_property = set_property; object_class->constructed = constructed; g_object_class_install_property (object_class, PROP_DBUS_NAME, g_param_spec_string("dbus-name", "DBus Name", "The well known name for dbusmock on the session bus", "com.canonical.DBusTestRunner.DBusMock", /* default */ G_PARAM_STATIC_STRINGS | G_PARAM_CONSTRUCT_ONLY | G_PARAM_READWRITE)); DbusTestTaskClass * tclass = DBUS_TEST_TASK_CLASS(klass); tclass->run = run; return; } /* Initialize Instance */ static void dbus_test_dbus_mock_init (DbusTestDbusMock *self) { self->priv = DBUS_TEST_DBUS_MOCK_GET_PRIVATE(self); self->priv->objects = NULL; self->priv->object_proxies = g_hash_table_new_full(g_str_hash, g_str_equal, g_free, g_object_unref); self->priv->cancel = g_cancellable_new(); return; } /* Finish init with our properties set */ static void constructed (GObject * object) { if (mock_cnt == 0) { dbus_test_task_set_name(DBUS_TEST_TASK(object), "DBusMock"); } else { gchar * name = g_strdup_printf("DBusMock-%d", mock_cnt); dbus_test_task_set_name(DBUS_TEST_TASK(object), name); g_free(name); } mock_cnt++; return; } /* Free references */ static void dbus_test_dbus_mock_dispose (GObject *object) { DbusTestDbusMock * self = DBUS_TEST_DBUS_MOCK(object); if (self->priv->cancel != NULL) g_cancellable_cancel(self->priv->cancel); g_clear_object(&self->priv->cancel); g_hash_table_remove_all(self->priv->object_proxies); g_list_free_full(self->priv->objects, object_free); self->priv->objects = NULL; g_clear_object(&self->priv->proxy); g_clear_object(&self->priv->bus); G_OBJECT_CLASS (dbus_test_dbus_mock_parent_class)->dispose (object); return; } /* Free memory */ static void dbus_test_dbus_mock_finalize (GObject *object) { DbusTestDbusMock * self = DBUS_TEST_DBUS_MOCK(object); g_free(self->priv->name); g_hash_table_destroy(self->priv->object_proxies); G_OBJECT_CLASS (dbus_test_dbus_mock_parent_class)->finalize (object); return; } /* Get a property */ static void get_property (GObject * object, guint property_id, GValue * value, GParamSpec * pspec) { DbusTestDbusMock * self = DBUS_TEST_DBUS_MOCK(object); switch (property_id) { case PROP_DBUS_NAME: g_value_set_string(value, self->priv->name); break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID(object, property_id, pspec); } return; } /* Set a property */ static void set_property (GObject * object, guint property_id, const GValue * value, GParamSpec * pspec) { DbusTestDbusMock * self = DBUS_TEST_DBUS_MOCK(object); switch (property_id) { case PROP_DBUS_NAME: g_free(self->priv->name); self->priv->name = g_value_dup_string(value); break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID(object, property_id, pspec); } return; } /* Check to see if we're running */ static inline gboolean is_running (DbusTestDbusMock * mock) { return dbus_test_task_get_state(DBUS_TEST_TASK(mock)) == DBUS_TEST_TASK_STATE_RUNNING; } /* Turns a property object into the variant to represent it */ static GVariant * property_to_variant (MockObjectProperty * prop) { GVariantBuilder builder; g_variant_builder_init(&builder, G_VARIANT_TYPE_DICT_ENTRY); g_variant_builder_add_value(&builder, g_variant_new_string(prop->name)); g_variant_builder_add_value(&builder, g_variant_new_variant(prop->value)); return g_variant_builder_end(&builder); } /* DBus Mock is expecting a list of the types of the parameters as a string, but without the tuple wrapper. So in the traditional variant type for parameters we could think of a function taking "(ss)" to get two strings. DBus Mock wants to recieve the string "ss". If there are no params, it should recieve the NULL string. */ static GVariant * method_params_to_variant (const GVariantType * params) { if (params == NULL) { return g_variant_new_string(""); } const gchar * peek = g_variant_type_peek_string(params); if (peek == NULL) return g_variant_new_string(""); guint len = strlen(peek); if (len == 0) return g_variant_new_string(""); /* The only way if it's non-zero for it to be a single GVariantType is to have a tuple or array. In the tuple case, unwrap. */ if (peek[0] == '(' && peek[len - 1] == ')') { /* remove exterior tuple */ gchar * modified = g_strndup(peek + 1, len - 2); return g_variant_new_take_string(modified); } else { return g_variant_new_string(peek); } } /* Turns a method into the variant to represent it */ static GVariant * method_to_variant (MockObjectMethod * method) { GVariantBuilder builder; g_variant_builder_init(&builder, G_VARIANT_TYPE_TUPLE); g_variant_builder_add_value(&builder, g_variant_new_string(method->name)); g_variant_builder_add_value(&builder, method_params_to_variant(method->in)); g_variant_builder_add_value(&builder, method_params_to_variant(method->out)); g_variant_builder_add_value(&builder, g_variant_new_string(method->code)); return g_variant_builder_end(&builder); } /* Add an object to the DBus Mock */ static gboolean install_object (DbusTestDbusMock * mock, DbusTestDbusMockObject * object, GError ** error) { GVariant * properties = NULL; GVariant * methods = NULL; g_return_val_if_fail(mock->priv->proxy != NULL, FALSE); if (object->properties->len > 0) { GVariantBuilder property_builder; guint i; g_variant_builder_init(&property_builder, G_VARIANT_TYPE_ARRAY); for (i = 0; i < object->properties->len; i++) { MockObjectProperty * prop = &g_array_index(object->properties, MockObjectProperty, i); g_variant_builder_add_value(&property_builder, property_to_variant(prop)); } properties = g_variant_builder_end(&property_builder); } else { properties = g_variant_new_array(G_VARIANT_TYPE("{sv}"), NULL, 0); } if (object->methods->len > 0) { GVariantBuilder method_builder; guint i; g_variant_builder_init(&method_builder, G_VARIANT_TYPE_ARRAY); for (i = 0; i < object->methods->len; i++) { MockObjectMethod * method = &g_array_index(object->methods, MockObjectMethod, i); g_variant_builder_add_value(&method_builder, method_to_variant(method)); } methods = g_variant_builder_end(&method_builder); } else { methods = g_variant_new_array(G_VARIANT_TYPE("(ssss)"), NULL, 0); } _DbusMockIfaceOrgFreedesktopDBusMock * proxy = g_hash_table_lookup(mock->priv->object_proxies, object->object_path); if (proxy == NULL) { g_debug("Add object (%s) on '%s'", object->interface, object->object_path); gboolean add_object = _dbus_mock_iface_org_freedesktop_dbus_mock_call_add_object_sync( mock->priv->proxy, object->object_path, object->interface, properties, methods, mock->priv->cancel, error); if (add_object) { proxy = _dbus_mock_iface_org_freedesktop_dbus_mock_proxy_new_sync(mock->priv->bus, G_DBUS_PROXY_FLAGS_DO_NOT_LOAD_PROPERTIES | G_DBUS_PROXY_FLAGS_DO_NOT_AUTO_START, mock->priv->name, object->object_path, /* path */ mock->priv->cancel, error ); g_hash_table_insert(mock->priv->object_proxies, g_strdup(object->object_path), proxy); } } else { gboolean methods_sent = FALSE; gboolean props_sent = FALSE; if (object->properties->len > 0) { g_debug("Add props"); props_sent = _dbus_mock_iface_org_freedesktop_dbus_mock_call_add_properties_sync( proxy, object->interface, properties, NULL, /* cancel */ error); } else { props_sent = TRUE; g_variant_ref_sink(properties); g_variant_unref(properties); } if (object->methods->len > 0) { g_debug("Add methods"); methods_sent = _dbus_mock_iface_org_freedesktop_dbus_mock_call_add_methods_sync( proxy, object->interface, methods, NULL, /* cancel */ error); } else { methods_sent = TRUE; g_variant_ref_sink(methods); g_variant_unref(methods); } if (!methods_sent || !props_sent) { g_warning("Unable to send methods and properties"); proxy = NULL; } } return proxy != NULL; } /* Catch the mock taking too long to start */ static gboolean mock_start_check (gpointer ploop) { GMainLoop * loop = (GMainLoop *)ploop; g_main_loop_quit(loop); return G_SOURCE_REMOVE; } /* Called when the name owner changes, should be to get one */ static void got_name_owner (GObject * obj, G_GNUC_UNUSED GParamSpec * pspec, gpointer ploop) { gchar * owner = g_dbus_proxy_get_name_owner(G_DBUS_PROXY(obj)); if (owner != NULL) { g_free(owner); GMainLoop * loop = (GMainLoop *)ploop; g_main_loop_quit(loop); } return; } /* Configure the executable and parameters for the mock */ static void configure_process (DbusTestDbusMock * self) { const gchar * paramval = NULL; /* Execute: python3 -m dbusmock $name / com.canonical.DbusTest.DbusMock */ g_object_set(G_OBJECT(self), "executable", "python3", NULL); GArray * params = g_array_new(TRUE, TRUE, sizeof(gchar *)); /* NOTE: No free func, none of the memory is managed by the array */ paramval = "-m"; g_array_append_val(params, paramval); paramval = "dbusmock"; g_array_append_val(params, paramval); /* If we're set for system, go there, otherwise default to session */ if (dbus_test_task_get_bus(DBUS_TEST_TASK(self)) == DBUS_TEST_SERVICE_BUS_SYSTEM) { paramval = "--system"; g_array_append_val(params, paramval); } g_array_append_val(params, self->priv->name); paramval = "/"; g_array_append_val(params, paramval); paramval = "com.canonical.DbusTest.DbusMock"; g_array_append_val(params, paramval); g_object_set(G_OBJECT(self), "parameters", params, NULL); g_array_unref(params); } /* Run the mock */ static void run (DbusTestTask * task) { GError * error = NULL; DbusTestDbusMock * self = DBUS_TEST_DBUS_MOCK(task); /* Grab the new bus */ if (dbus_test_task_get_bus(DBUS_TEST_TASK(self)) == DBUS_TEST_SERVICE_BUS_SYSTEM) { self->priv->bus = g_bus_get_sync(G_BUS_TYPE_SYSTEM, NULL, &error); } else { self->priv->bus = g_bus_get_sync(G_BUS_TYPE_SESSION, NULL, &error); } if (error != NULL) { g_warning("Unable to get bus to start DBus Mock: %s", error->message); g_error_free(error); return; } /* Use the process code to get the process running */ configure_process(self); DBUS_TEST_TASK_CLASS (dbus_test_dbus_mock_parent_class)->run (task); /**** Initialize the DBus Mock instance ****/ /* Zero, Setup the proxy */ self->priv->proxy = _dbus_mock_iface_org_freedesktop_dbus_mock_proxy_new_sync(self->priv->bus, G_DBUS_PROXY_FLAGS_DO_NOT_LOAD_PROPERTIES | G_DBUS_PROXY_FLAGS_DO_NOT_AUTO_START, self->priv->name, "/", /* path */ self->priv->cancel, &error ); if (error != NULL) { g_critical("Unable to build proxy to DBusMock: %s", error->message); g_error_free(error); return; } /* First, Ensure we have a proxy */ gchar * owner = g_dbus_proxy_get_name_owner(G_DBUS_PROXY(self->priv->proxy)); if (owner == NULL) { g_debug("Waiting on name from DBusMock"); GMainLoop * mainloop = g_main_loop_new(NULL, FALSE); guint timeout_sig = g_timeout_add_seconds(3, mock_start_check, mainloop); gulong owner_sig = g_signal_connect(G_OBJECT(self->priv->proxy), "notify::g-name-owner", G_CALLBACK(got_name_owner), mainloop); g_main_loop_run(mainloop); g_main_loop_unref(mainloop); g_signal_handler_disconnect(self->priv->proxy, owner_sig); g_source_remove(timeout_sig); owner = g_dbus_proxy_get_name_owner(G_DBUS_PROXY(self->priv->proxy)); if (owner == NULL) { g_critical("Unable to get DBusMock started within 3 seconds"); return; } } g_free(owner); /* Second, Install Objects */ GList * lobj = self->priv->objects; for (lobj = self->priv->objects; lobj != NULL; lobj = g_list_next(lobj)) { GError * error = NULL; DbusTestDbusMockObject * obj = (DbusTestDbusMockObject *)lobj->data; install_object(self, obj, &error); if (error != NULL) { g_warning("Unable to install object '%s': %s", obj->object_path, error->message); g_error_free(error); } } return; } /** * dbus_test_dbus_mock_new: * @bus_name: The name dbus mock should get on the bus * * Creates a new dbus mock process with a given name on the bus. This actually * doesn't cause the process to start until the whole DBusTest framework is told * to run. But it represents one that will start when told to. * * Return value: A new dbus mock instance */ DbusTestDbusMock * dbus_test_dbus_mock_new (const gchar * bus_name) { g_return_val_if_fail(bus_name != NULL, NULL); DbusTestDbusMock * mock = g_object_new(DBUS_TEST_TYPE_DBUS_MOCK, "dbus-name", bus_name, NULL); return mock; } /** * dbus_test_dbus_mock_get_object: * @mock: A #DbusTestDbusMock instance * @path: DBus path of the object * @interface: Interface on that object * @error: A possible error * * Gets a pointer to a handle for an object on the dbus mock instance. If it * didn't exist previous to calling this function, it is created. If it did, * this is the pointer for it. When the dbus mock is started this object will * be created with the parameters and methods that are added to it. * * Return Value: (transfer none): Handle to refer to an object on the DBus Mock */ DbusTestDbusMockObject * dbus_test_dbus_mock_get_object (DbusTestDbusMock * mock, const gchar * path, const gchar * interface, GError ** error) { g_return_val_if_fail(DBUS_TEST_IS_DBUS_MOCK(mock), NULL); g_return_val_if_fail(path != NULL, NULL); g_return_val_if_fail(interface != NULL, NULL); /* Check to see if we have that one */ GList * lobj = mock->priv->objects; for (lobj = mock->priv->objects; lobj != NULL; lobj = g_list_next(lobj)) { DbusTestDbusMockObject * obj = (DbusTestDbusMockObject *)lobj->data; if (g_strcmp0(path, obj->object_path) == 0 && g_strcmp0(interface, obj->interface) == 0) { return obj; } } /* K, that's cool. We'll build it then. */ DbusTestDbusMockObject * newobj = g_new0(DbusTestDbusMockObject, 1); newobj->object_path = g_strdup(path); newobj->interface = g_strdup(interface); newobj->properties = g_array_new(FALSE, TRUE, sizeof(MockObjectProperty)); g_array_set_clear_func(newobj->properties, property_free); newobj->methods = g_array_new(FALSE, TRUE, sizeof(MockObjectMethod)); g_array_set_clear_func(newobj->methods, method_free); mock->priv->objects = g_list_prepend(mock->priv->objects, newobj); g_debug("Creating object: %s (%s)", newobj->object_path, newobj->interface); if (!is_running(mock)) { return newobj; } install_object(mock, newobj, error); return newobj; } /* Objects are initialized in dbus_test_dbus_mock_get_object() and they are free'd in this function */ static void object_free (gpointer data) { DbusTestDbusMockObject * obj = (DbusTestDbusMockObject *)data; g_debug("Freeing object: %s (%s)", obj->object_path, obj->interface); g_free(obj->interface); g_free(obj->object_path); g_array_free(obj->properties, TRUE); g_array_free(obj->methods, TRUE); g_free(data); return; } /* Little helper to get a method */ static inline MockObjectMethod * get_obj_method (DbusTestDbusMockObject * obj, const gchar * name) { guint i; for (i = 0; i < obj->methods->len; i++) { MockObjectMethod * method = &g_array_index(obj->methods, MockObjectMethod, i); if (g_strcmp0(method->name, name) == 0) { return method; } } return NULL; } /* Free the resources for the call */ static void call_free (gpointer pcall) { DbusTestDbusMockCall * call = (DbusTestDbusMockCall *)pcall; g_free((gchar *)call->name); g_variant_unref(call->params); } /** * dbus_test_dbus_mock_object_add_method: * @mock: A #DbusTestDbusMock instance * @obj: A handle to an object on the mock interface * @method: Name of the method * @inparams: (allow-none): Parameters going into the method as a tuple * @outparams: (allow-none): Parameters gonig out of the method as a tuple * @python_code: Python code to execute when the method is called * @error: Possible error to return * * Sets up a method on the object specified. When the method is activated this is * both tracked by DBusMock and the code in @python_code is executed. This then * can return a value that is the same type as @outparams. * * Return value: Whether it was registered successfully */ gboolean dbus_test_dbus_mock_object_add_method (DbusTestDbusMock * mock, DbusTestDbusMockObject * obj, const gchar * method, const GVariantType * inparams, const GVariantType * outparams, const gchar * python_code, G_GNUC_UNUSED GError ** error) { g_return_val_if_fail(DBUS_TEST_IS_DBUS_MOCK(mock), FALSE); g_return_val_if_fail(obj != NULL, FALSE); g_return_val_if_fail(method != NULL, FALSE); g_return_val_if_fail(python_code != NULL, FALSE); /* Check to make sure it doesn't already exist */ MockObjectMethod * meth = get_obj_method(obj, method); g_return_val_if_fail(meth == NULL, FALSE); /* Build a new one */ MockObjectMethod newmethod; newmethod.name = g_strdup(method); newmethod.in = inparams ? g_variant_type_copy(inparams) : NULL; newmethod.out = outparams ? g_variant_type_copy(outparams) : NULL; newmethod.code = g_strdup(python_code); newmethod.calls = g_array_new(TRUE, TRUE, sizeof(DbusTestDbusMockCall)); g_array_set_clear_func(newmethod.calls, call_free); g_array_append_val(obj->methods, newmethod); /* If we're not running we can just leave it here */ if (!is_running(mock)) { return TRUE; } GVariant * in = method_params_to_variant(inparams); GVariant * out = method_params_to_variant(outparams); g_variant_ref_sink(in); g_variant_ref_sink(out); _DbusMockIfaceOrgFreedesktopDBusMock * proxy = g_hash_table_lookup(mock->priv->object_proxies, obj->object_path); g_return_val_if_fail(proxy != NULL, FALSE); /* Should never happen */ gboolean ret = _dbus_mock_iface_org_freedesktop_dbus_mock_call_add_method_sync( proxy, obj->interface, method, g_variant_get_string(in, NULL), g_variant_get_string(out, NULL), python_code, mock->priv->cancel, error ); g_variant_unref(in); g_variant_unref(out); return ret; } /* Free the data allocated in dbus_test_dbus_mock_object_add_method() */ static void method_free (gpointer data) { MockObjectMethod * method = (MockObjectMethod *)data; g_free(method->name); g_variant_type_free(method->in); g_variant_type_free(method->out); g_free(method->code); g_array_free(method->calls, TRUE); /* NOTE: No free of 'data' */ return; } /** * dbus_test_dbus_mock_object_check_method_call: * @mock: A #DbusTestDbusMock instance * @obj: A handle to an object on the mock interface * @method: Name of the method * @params: (allow none): Parameters to check * @error: A possible error * * Quick function to check to see if a method was called. If the @params value is set * then the parameters of the call will also be checked. If the method was called more * than once this function will return FALSE. * * Return value: Whether the function was called */ gboolean dbus_test_dbus_mock_object_check_method_call (DbusTestDbusMock * mock, DbusTestDbusMockObject * obj, const gchar * method, GVariant * params, GError ** error) { guint length = 0; guint i; const DbusTestDbusMockCall * calls; calls = dbus_test_dbus_mock_object_get_method_calls(mock, obj, method, &length, error); if (length == 0) { return FALSE; } /* Don't check params */ if (params == NULL) { return TRUE; } for (i = 0; i < length; i++) { if (g_variant_equal(params, calls[i].params)) { return TRUE; } } return FALSE; } /** * dbus_test_dbus_mock_object_clear_method_calls: * @mock: A #DbusTestDbusMock instance * @obj: A handle to an object on the mock interface * @error: A possible error * * Clears the queued set of method calls for the method. * * Return value: Whether we were able to clear it */ gboolean dbus_test_dbus_mock_object_clear_method_calls (DbusTestDbusMock * mock, DbusTestDbusMockObject * obj, GError ** error) { g_return_val_if_fail(DBUS_TEST_IS_DBUS_MOCK(mock), FALSE); g_return_val_if_fail(obj != NULL, FALSE); if (!is_running(mock)) { return FALSE; } _DbusMockIfaceOrgFreedesktopDBusMock * proxy = g_hash_table_lookup(mock->priv->object_proxies, obj->object_path); g_return_val_if_fail(proxy != NULL, FALSE); /* Should never happen */ return _dbus_mock_iface_org_freedesktop_dbus_mock_call_clear_calls_sync( proxy, mock->priv->cancel, error ); } /* We get back an av from DBusMock but everyone else uses a tuple. Let's use that */ static GVariant * variant_array_to_tuple (GVariant * array_in) { if (g_variant_n_children(array_in) == 0) { return g_variant_new_tuple(NULL, 0); } GVariantIter iter; g_variant_iter_init(&iter, array_in); GVariantBuilder builder; g_variant_builder_init(&builder, G_VARIANT_TYPE_TUPLE); GVariant * item = NULL; while (g_variant_iter_loop(&iter, "v", &item)) { g_variant_builder_add_value(&builder, item); } return g_variant_builder_end(&builder); } /** * dbus_test_dbus_mock_object_get_method_calls: * @mock: A #DbusTestDbusMock instance * @obj: A handle to an object on the mock interface * @method: Name of the method * @length: (out) (allow-none): Name of the method * @error: A possible error * * Gets a list of all method calls for a function including the parmeters. * * Return value: (transfer none): An array of calls with the last item * having a timestamp of 0. Also length in the optional @len param. */ const DbusTestDbusMockCall * dbus_test_dbus_mock_object_get_method_calls (DbusTestDbusMock * mock, DbusTestDbusMockObject * obj, const gchar * method, guint * length, GError ** error) { /* Default state */ if (length != NULL) { *length = 0; } /* Check our params */ g_return_val_if_fail(DBUS_TEST_IS_DBUS_MOCK(mock), NULL); g_return_val_if_fail(obj != NULL, NULL); g_return_val_if_fail(method != NULL, NULL); if (!is_running(mock)) { return NULL; } _DbusMockIfaceOrgFreedesktopDBusMock * proxy = g_hash_table_lookup(mock->priv->object_proxies, obj->object_path); g_return_val_if_fail(proxy != NULL, FALSE); /* Should never happen */ /* Find our method */ MockObjectMethod * meth = get_obj_method(obj, method); if (meth == NULL) { g_set_error(error, _dbus_mock_quark(), ERROR_METHOD_NOT_FOUND, "Method '%s' not found on object '%s'", method, obj->object_path); return NULL; } /* Clear the current list of calls */ g_array_set_size(meth->calls, 0); GVariant * call_list = NULL; _dbus_mock_iface_org_freedesktop_dbus_mock_call_get_calls_sync( proxy, &call_list, mock->priv->cancel, error); if (call_list == NULL) { return NULL; } GVariantIter call_list_itr; g_variant_iter_init(&call_list_itr, call_list); guint64 timestamp = 0; const gchar * name = NULL; GVariant * params = NULL; while (g_variant_iter_loop(&call_list_itr, "(t&s@av)", ×tamp, &name, ¶ms)) { if (g_strcmp0(method, name) != 0) { continue; } DbusTestDbusMockCall callsig = { .timestamp = timestamp, .name = g_strdup(name), .params = g_variant_ref_sink(variant_array_to_tuple(params)) }; g_array_append_val(meth->calls, callsig); } g_variant_unref(call_list); if (length != NULL) { *length = meth->calls->len; } return (const DbusTestDbusMockCall *)meth->calls->data; } /* Quick helper to get an object property */ static inline MockObjectProperty * get_obj_property (DbusTestDbusMockObject * obj, const gchar * name) { guint i; for (i = 0; i < obj->properties->len; i++) { MockObjectProperty * prop = &g_array_index(obj->properties, MockObjectProperty, i); if (g_strcmp0(prop->name, name) == 0) { return prop; } } return NULL; } /** * dbus_test_dbus_mock_object_add_property: * @mock: A #DbusTestDbusMock instance * @obj: A handle to an object on the mock interface * @name: Name of the property * @type: Type of the property * @value: Initial value of the property * @error: A possible error * * Adds a property to the object and sets its initial value. * * Return value: Whether it was added */ gboolean dbus_test_dbus_mock_object_add_property (DbusTestDbusMock * mock, DbusTestDbusMockObject * obj, const gchar * name, const GVariantType * type, GVariant * value, G_GNUC_UNUSED GError ** error) { g_return_val_if_fail(DBUS_TEST_IS_DBUS_MOCK(mock), FALSE); g_return_val_if_fail(obj != NULL, FALSE); g_return_val_if_fail(name != NULL, FALSE); g_return_val_if_fail(type != NULL, FALSE); g_return_val_if_fail(value != NULL, FALSE); g_return_val_if_fail(g_variant_is_of_type(value, type), FALSE); /* Check to see if we have the property */ MockObjectProperty * prop = get_obj_property(obj, name); g_return_val_if_fail(prop == NULL, FALSE); /* Build a new one */ MockObjectProperty newprop; newprop.name = g_strdup(name); newprop.type = g_variant_type_copy(type); newprop.value = g_variant_ref_sink(value); g_array_append_val(obj->properties, newprop); /* If we're not running we can just leave it here */ if (!is_running(mock)) { return TRUE; } _DbusMockIfaceOrgFreedesktopDBusMock * proxy = g_hash_table_lookup(mock->priv->object_proxies, obj->object_path); g_return_val_if_fail(proxy != NULL, FALSE); /* Should never happen */ GVariantBuilder builder; g_variant_builder_init(&builder, G_VARIANT_TYPE_ARRAY); g_variant_builder_open(&builder, G_VARIANT_TYPE_DICT_ENTRY); g_variant_builder_add_value(&builder, g_variant_new_string(name)); g_variant_builder_open(&builder, G_VARIANT_TYPE_VARIANT); g_variant_builder_add_value(&builder, value); g_variant_builder_close(&builder); /* variant */ g_variant_builder_close(&builder); /* dict_entry */ return _dbus_mock_iface_org_freedesktop_dbus_mock_call_add_properties_sync( proxy, obj->interface, g_variant_builder_end(&builder), mock->priv->cancel, error ); } /* Free the data allocated in dbus_test_dbus_mock_object_add_property() */ static void property_free (gpointer data) { MockObjectProperty * property = (MockObjectProperty *)data; g_free(property->name); g_variant_type_free(property->type); g_variant_unref(property->value); /* NOTE: No free of 'data' */ return; } /** * dbus_test_dbus_mock_object_update_property: * @mock: A #DbusTestDbusMock instance * @obj: A handle to an object on the mock interface * @name: Name of the property * @value: Initial value of the property * @error: A possible error * * Changes the value of a property and will send a signal that it changed * depending on the value of @signal. * * Return value: Whether it was changed */ gboolean dbus_test_dbus_mock_object_update_property (DbusTestDbusMock * mock, DbusTestDbusMockObject * obj, const gchar * name, GVariant * value, GError ** error) { g_return_val_if_fail(DBUS_TEST_IS_DBUS_MOCK(mock), FALSE); g_return_val_if_fail(obj != NULL, FALSE); g_return_val_if_fail(name != NULL, FALSE); g_return_val_if_fail(value != NULL, FALSE); MockObjectProperty * prop = get_obj_property(obj, name); g_return_val_if_fail(prop != NULL, FALSE); /* Grab a ref, we'll have to start managing this */ g_variant_ref_sink(value); if (!g_variant_is_of_type(value, prop->type)) { g_critical("Property '%s' is not of same value in dbus_test_dbus_mock_object_update_property()", name); g_variant_unref(value); return FALSE; } /* Send the update to Dbusmock */ if (is_running(mock)) { GError * local_error = NULL; g_dbus_connection_call_sync(mock->priv->bus, mock->priv->name, obj->object_path, "org.freedesktop.DBus.Properties", "Set", g_variant_new("(ssv)", obj->interface, name, value), NULL, /* return */ G_DBUS_CALL_FLAGS_NO_AUTO_START, -1, /* timeout */ mock->priv->cancel, &local_error); if (local_error != NULL) { g_warning("Unable to update property: %s", local_error->message); g_propagate_error(error, local_error); g_variant_unref(value); return FALSE; } _DbusMockIfaceOrgFreedesktopDBusMock * proxy = g_hash_table_lookup(mock->priv->object_proxies, obj->object_path); if (proxy != NULL) { GVariantBuilder changed_builder; g_variant_builder_init(&changed_builder, G_VARIANT_TYPE_ARRAY); /* s */ g_variant_builder_open(&changed_builder, G_VARIANT_TYPE_VARIANT); g_variant_builder_add_value(&changed_builder, g_variant_new_string(obj->interface)); g_variant_builder_close(&changed_builder); /* a{sv} */ g_variant_builder_open(&changed_builder, G_VARIANT_TYPE_VARIANT); g_variant_builder_open(&changed_builder, G_VARIANT_TYPE_DICTIONARY); g_variant_builder_open(&changed_builder, G_VARIANT_TYPE_DICT_ENTRY); g_variant_builder_add_value(&changed_builder, g_variant_new_string(name)); g_variant_builder_open(&changed_builder, G_VARIANT_TYPE_VARIANT); g_variant_builder_add_value(&changed_builder, value); g_variant_builder_close(&changed_builder); /* v */ g_variant_builder_close(&changed_builder); /* dict entry */ g_variant_builder_close(&changed_builder); /* dict */ g_variant_builder_close(&changed_builder); /* v */ /* as */ g_variant_builder_open(&changed_builder, G_VARIANT_TYPE_VARIANT); g_variant_builder_add_value(&changed_builder, g_variant_new_array(G_VARIANT_TYPE_STRING, NULL, 0)); g_variant_builder_close(&changed_builder); _dbus_mock_iface_org_freedesktop_dbus_mock_call_emit_signal_sync(proxy, "org.freedesktop.DBus.Properties", "PropertiesChanged", "sa{sv}as", g_variant_builder_end(&changed_builder), mock->priv->cancel, &local_error); if (local_error != NULL) { g_warning("Unable to emit properties changed: %s", local_error->message); g_clear_error(&local_error); } } } /* It's updated, let's cache */ g_variant_unref(prop->value); prop->value = value; return TRUE; } /* DBus Mock has an odd way of doing things. Converting. */ static GVariant * tuple_to_array (GVariant * tuple) { GVariantIter iter; GVariantBuilder builder; if (tuple == NULL) { return g_variant_new_array(G_VARIANT_TYPE_VARIANT, NULL, 0); } g_variant_ref_sink(tuple); if (g_variant_n_children(tuple) == 0) { /* Make sure to swallow the variant if it is there */ g_variant_unref(tuple); return g_variant_new_array(G_VARIANT_TYPE_VARIANT, NULL, 0); } g_variant_iter_init(&iter, tuple); g_variant_builder_init(&builder, G_VARIANT_TYPE_ARRAY); guint i; for (i = 0; i < g_variant_n_children(tuple); i++) { g_variant_builder_open(&builder, G_VARIANT_TYPE_VARIANT); GVariant * entry = g_variant_get_child_value(tuple, i); g_variant_builder_add_value(&builder, entry); g_variant_unref(entry); g_variant_builder_close(&builder); } g_variant_unref(tuple); /* Don't use iter after this */ return g_variant_builder_end(&builder); } /** * dbus_test_dbus_mock_object_emit_signal: * @mock: A #DbusTestDbusMock instance * @obj: A handle to an object on the mock interface * @name: Name of the signal * @params: The parameters of the signal as a tuple * @values: Values to emit with the signal * @error: A possible error * * Causes the object on the dbus mock to emit a signal with the @params * provided. * * Return value: Whether we were able to request the signal * to be emitted. */ gboolean dbus_test_dbus_mock_object_emit_signal (DbusTestDbusMock * mock, DbusTestDbusMockObject * obj, const gchar * name, const GVariantType * params, GVariant * values, GError ** error) { g_return_val_if_fail(DBUS_TEST_IS_DBUS_MOCK(mock), FALSE); g_return_val_if_fail(obj != NULL, FALSE); g_return_val_if_fail(name != NULL, FALSE); if (params == NULL) { g_return_val_if_fail(values == NULL, FALSE); } else { g_return_val_if_fail(values != NULL, FALSE); } if (!is_running(mock)) { return FALSE; } _DbusMockIfaceOrgFreedesktopDBusMock * proxy = g_hash_table_lookup(mock->priv->object_proxies, obj->object_path); g_return_val_if_fail(proxy != NULL, FALSE); /* Should never happen */ /* floating ref swallowed by call_emit_signal() */ GVariant * sig_params = tuple_to_array(values); GVariant * sig_types = method_params_to_variant(params); g_variant_ref_sink(sig_types); gboolean retval = _dbus_mock_iface_org_freedesktop_dbus_mock_call_emit_signal_sync( proxy, obj->interface, name, g_variant_get_string(sig_types, NULL), sig_params, mock->priv->cancel, error ); g_variant_unref(sig_types); return retval; } ./libdbustest/dbus-mock.h0000644000004100000410000001520112763551700015631 0ustar www-datawww-data/* Copyright 2013 Canonical Ltd. Authors: Ted Gould This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License version 3, as published by the Free Software Foundation. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranties of MERCHANTABILITY, SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program. If not, see . */ #ifndef __DBUS_TEST_DBUS_MOCK_H__ #define __DBUS_TEST_DBUS_MOCK_H__ #ifndef __DBUS_TEST_TOP_LEVEL__ #error "Please include #include only" #endif #include #include "process.h" G_BEGIN_DECLS #define DBUS_TEST_TYPE_DBUS_MOCK (dbus_test_dbus_mock_get_type ()) #define DBUS_TEST_DBUS_MOCK(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), DBUS_TEST_TYPE_DBUS_MOCK, DbusTestDbusMock)) #define DBUS_TEST_DBUS_MOCK_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), DBUS_TEST_TYPE_DBUS_MOCK, DbusTestDbusMockClass)) #define DBUS_TEST_IS_DBUS_MOCK(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), DBUS_TEST_TYPE_DBUS_MOCK)) #define DBUS_TEST_IS_DBUS_MOCK_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), DBUS_TEST_TYPE_DBUS_MOCK)) #define DBUS_TEST_DBUS_MOCK_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), DBUS_TEST_TYPE_DBUS_MOCK, DbusTestDbusMockClass)) typedef struct _DbusTestDbusMock DbusTestDbusMock; typedef struct _DbusTestDbusMockClass DbusTestDbusMockClass; typedef struct _DbusTestDbusMockPrivate DbusTestDbusMockPrivate; typedef struct _DbusTestDbusMockObject DbusTestDbusMockObject; typedef struct _DbusTestDbusMockCall DbusTestDbusMockCall; struct _DbusTestDbusMockClass { DbusTestProcessClass parent_class; }; struct _DbusTestDbusMock { DbusTestProcess parent; DbusTestDbusMockPrivate * priv; }; struct _DbusTestDbusMockCall { guint64 timestamp; const gchar * name; GVariant * params; }; GType dbus_test_dbus_mock_get_type (void); DbusTestDbusMock * dbus_test_dbus_mock_new (const gchar * bus_name); /* Object stuff */ DbusTestDbusMockObject * dbus_test_dbus_mock_get_object (DbusTestDbusMock * mock, const gchar * path, const gchar * interface, GError ** error); gboolean dbus_test_dbus_mock_object_add_method (DbusTestDbusMock * mock, DbusTestDbusMockObject * obj, const gchar * method, const GVariantType * inparams, const GVariantType * outparams, const gchar * python_code, GError ** error); gboolean dbus_test_dbus_mock_object_check_method_call (DbusTestDbusMock * mock, DbusTestDbusMockObject * obj, const gchar * method, GVariant * params, GError ** error); gboolean dbus_test_dbus_mock_object_clear_method_calls (DbusTestDbusMock * mock, DbusTestDbusMockObject * obj, GError ** error); const DbusTestDbusMockCall * dbus_test_dbus_mock_object_get_method_calls (DbusTestDbusMock * mock, DbusTestDbusMockObject * obj, const gchar * method, guint * len, GError ** error); gboolean dbus_test_dbus_mock_object_add_property (DbusTestDbusMock * mock, DbusTestDbusMockObject * obj, const gchar * name, const GVariantType * type, GVariant * value, GError ** error); gboolean dbus_test_dbus_mock_object_update_property (DbusTestDbusMock * mock, DbusTestDbusMockObject * obj, const gchar * name, GVariant * value, GError ** error); gboolean dbus_test_dbus_mock_object_emit_signal (DbusTestDbusMock * mock, DbusTestDbusMockObject * obj, const gchar * name, const GVariantType * params, GVariant * values, GError ** error); G_END_DECLS #endif ./libdbustest/Makefile.am0000644000004100000410000000451612763551700015637 0ustar www-datawww-data lib_LTLIBRARIES = libdbustest.la ABI_VERSION = 1 API_VERSION = 1 AM_CFLAGS = -Wall libdbustestincludedir=$(includedir)/libdbustest-$(API_VERSION)/libdbustest libdbustestinclude_HEADERS = \ bustle.h \ dbus-mock.h \ dbus-test.h \ process.h \ service.h \ task.h libdbustest_la_SOURCES = \ bustle.c \ bustle.h \ dbus-mock.h \ dbus-mock.c \ dbus-test.h \ process.c \ process.h \ service.c \ service.h \ task.c \ task.h \ watchdog.c \ watchdog.h libdbustest_la_CFLAGS = \ $(DBUS_TEST_RUNNER_CFLAGS) \ $(COVERAGE_CFLAGS) \ -I$(top_srcdir) \ -I$(builddir) \ -DDEFAULT_SESSION_CONF="\"$(datadir)/dbus-test-runner/session.conf\"" \ -DDEFAULT_SYSTEM_CONF="\"$(datadir)/dbus-test-runner/system.conf\"" \ -DBUSTLE_DUAL_MONITOR="\"$(pkgdatadir)/dbus-test-bustle-handler\"" \ -DWATCHDOG="\"$(pkglibexecdir)/dbus-test-watchdog\"" \ -DG_LOG_DOMAIN=\"libdbustest\" \ -Wall -Werror -Wextra libdbustest_la_LIBADD = \ libdbustest-generated.la \ $(DBUS_TEST_RUNNER_LIBS) libdbustest_la_LDFLAGS = \ $(DBUS_TEST_RUNNER_LDFLAGS) \ $(COVERAGE_LDFLAGS) \ -version-info $(ABI_VERSION):0:0 \ -no-undefined \ -export-symbols-regex "^[^_].*" noinst_LTLIBRARIES = libdbustest-generated.la libdbustest_generated_la_CFLAGS = \ $(DBUS_TEST_RUNNER_CFLAGS) \ -I$(builddir) \ -DG_LOG_DOMAIN=\"libdbustest\" \ -Wall -Werror libdbustest_generated_la_SOURCES = \ dbus-mock-iface.h \ dbus-mock-iface.c dbus-mock-iface.c: dbus-mock-iface.xml $(AM_V_GEN) gdbus-codegen \ --interface-prefix org.freedesktop.DBus.Mock. \ --generate-c-code dbus-mock-iface \ --c-namespace _DbusMockIface \ $^ dbus-mock-iface.h: dbus-mock-iface.c dbus-mock.c: dbus-mock-iface.h pkgdata_SCRIPTS = \ dbus-test-bustle-handler EXTRA_DIST = \ dbus-mock-iface.xml \ dbus-test-bustle-handler \ dbustest.pc.in pkgconfig_DATA = dbustest-$(API_VERSION).pc pkgconfigdir = $(libdir)/pkgconfig %-$(API_VERSION).pc: %.pc.in $(AM_V_GEN) sed \ -e "s:\@apiversion\@:$(API_VERSION):" \ -e "s:\@libdir\@:$(libdir):" \ -e "s:\@includedir\@:$(includedir):" \ -e "s:\@VERSION\@:$(VERSION):" \ $< > $@ pkglibexec_PROGRAMS = \ dbus-test-watchdog dbus_test_watchdog_SOURCES = \ leash.c dbus_test_watchdog_LDADD = \ $(DBUS_TEST_RUNNER_LIBS) dbus_test_watchdog_CFLAGS = \ $(DBUS_TEST_RUNNER_CFLAGS) DISTCLEANFILES = \ dbus-mock-iface.c dbus-mock-iface.h \ dbustest-$(API_VERSION).pc ./libdbustest/glib-compat.h0000644000004100000410000000401112763551700016140 0ustar www-datawww-data/* Copyright 2012 Canonical Ltd. Authors: David Barth This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License version 3, as published by the Free Software Foundation. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranties of MERCHANTABILITY, SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program. If not, see . */ #ifndef GLIB_COMPAT_H #define GLIB_COMPAT_H #if !GLIB_CHECK_VERSION(2, 34, 0) #define g_clear_pointer(pp, destroy) \ G_STMT_START { \ G_STATIC_ASSERT (sizeof *(pp) == sizeof (gpointer)); \ /* Only one access, please */ \ gpointer *_pp = (gpointer *) (pp); \ gpointer _p; \ /* This assignment is needed to avoid a gcc warning */ \ GDestroyNotify _destroy = (GDestroyNotify) (destroy); \ \ (void) (0 ? (gpointer) *(pp) : 0); \ do \ _p = g_atomic_pointer_get (_pp); \ while G_UNLIKELY (!g_atomic_pointer_compare_and_exchange (_pp, _p, NULL)); \ \ if (_p) \ _destroy (_p); \ } G_STMT_END #endif #endif /* GLIB_COMPAT_H */ ./libdbustest/process.c0000644000004100000410000003035412763551700015424 0ustar www-datawww-data/* Copyright 2012 Canonical Ltd. Authors: Ted Gould This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License version 3, as published by the Free Software Foundation. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranties of MERCHANTABILITY, SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program. If not, see . */ #ifdef HAVE_CONFIG_H #include "config.h" #endif #include "dbus-test.h" #include "glib-compat.h" struct _DbusTestProcessPrivate { gchar * executable; GArray * parameters; GPid pid; guint io_watch; guint watcher; GIOChannel * io_chan; gboolean complete; gint status; }; enum { PROP_0, PROP_EXECUTABLE, PROP_PARAMETERS, NUM_PROPS }; #define DBUS_TEST_PROCESS_GET_PRIVATE(o) \ (G_TYPE_INSTANCE_GET_PRIVATE ((o), DBUS_TEST_TYPE_PROCESS, DbusTestProcessPrivate)) static void dbus_test_process_class_init (DbusTestProcessClass *klass); static void dbus_test_process_init (DbusTestProcess *self); static void dbus_test_process_dispose (GObject *object); static void dbus_test_process_finalize (GObject *object); static void process_run (DbusTestTask * task); static DbusTestTaskState get_state (DbusTestTask * task); static gboolean get_passed (DbusTestTask * task); static void get_property (GObject * object, guint property_id, GValue * value, GParamSpec * pspec); static void set_property (GObject * object, guint property_id, const GValue * value, GParamSpec * pspec); G_DEFINE_TYPE (DbusTestProcess, dbus_test_process, DBUS_TEST_TYPE_TASK); static void dbus_test_process_class_init (DbusTestProcessClass *klass) { GObjectClass *object_class = G_OBJECT_CLASS (klass); g_type_class_add_private (klass, sizeof (DbusTestProcessPrivate)); object_class->dispose = dbus_test_process_dispose; object_class->finalize = dbus_test_process_finalize; object_class->get_property = get_property; object_class->set_property = set_property; g_object_class_install_property (object_class, PROP_EXECUTABLE, g_param_spec_string("executable", "Executable Name", "The executable being run by the process object", "", /* default */ G_PARAM_STATIC_STRINGS | G_PARAM_READWRITE)); g_object_class_install_property (object_class, PROP_PARAMETERS, g_param_spec_boxed("parameters", "Parameters", "Parameters to pass to the executable", G_TYPE_ARRAY, G_PARAM_STATIC_STRINGS | G_PARAM_READWRITE)); DbusTestTaskClass * task_class = DBUS_TEST_TASK_CLASS(klass); task_class->run = process_run; task_class->get_state = get_state; task_class->get_passed = get_passed; return; } /* Small helper to free the result of the pointer */ static void array_free_helper (gpointer data) { gchar ** typed_data = (gchar **)data; g_free(*typed_data); return; } static void dbus_test_process_init (DbusTestProcess *self) { self->priv = DBUS_TEST_PROCESS_GET_PRIVATE(self); self->priv->executable = NULL; self->priv->parameters = g_array_new(TRUE /* zero terminated */, TRUE /* clear */, sizeof(gchar *)); g_array_set_clear_func(self->priv->parameters, array_free_helper); self->priv->io_chan = NULL; return; } static void dbus_test_process_dispose (GObject *object) { g_return_if_fail(DBUS_TEST_IS_PROCESS(object)); DbusTestProcess * process = DBUS_TEST_PROCESS(object); if (process->priv->io_watch != 0) { g_source_remove(process->priv->io_watch); process->priv->io_watch = 0; } if (process->priv->watcher != 0) { g_source_remove(process->priv->watcher); process->priv->watcher = 0; } if (process->priv->pid != 0) { gchar * killstr = g_strdup_printf("kill -9 %d", process->priv->pid); g_spawn_command_line_async(killstr, NULL); g_free(killstr); g_spawn_close_pid(process->priv->pid); process->priv->pid = 0; } if (process->priv->io_chan != NULL) { GIOStatus status = G_IO_STATUS_NORMAL; while ((G_IO_IN & g_io_channel_get_buffer_condition(process->priv->io_chan)) && status == G_IO_STATUS_NORMAL) { gchar * line = NULL; gsize termloc; status = g_io_channel_read_line (process->priv->io_chan, &line, NULL, &termloc, NULL); if (status != G_IO_STATUS_NORMAL) { continue; } line[termloc] = '\0'; dbus_test_task_print(DBUS_TEST_TASK(process), line); g_free(line); } g_clear_pointer(&process->priv->io_chan, g_io_channel_unref); } G_OBJECT_CLASS (dbus_test_process_parent_class)->dispose (object); return; } static void dbus_test_process_finalize (GObject *object) { g_return_if_fail(DBUS_TEST_IS_PROCESS(object)); DbusTestProcess * process = DBUS_TEST_PROCESS(object); g_free(process->priv->executable); process->priv->executable = NULL; g_array_free(process->priv->parameters, TRUE /* free segment */); process->priv->parameters = NULL; G_OBJECT_CLASS (dbus_test_process_parent_class)->finalize (object); return; } /* Get a property */ static void get_property (GObject * object, guint property_id, G_GNUC_UNUSED GValue * value, GParamSpec * pspec) { DbusTestProcess * self = DBUS_TEST_PROCESS(object); switch (property_id) { case PROP_EXECUTABLE: g_value_set_string(value, self->priv->executable); break; case PROP_PARAMETERS: g_value_set_boxed(value, self->priv->parameters); break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID(object, property_id, pspec); } return; } /* Set a property */ static void set_property (GObject * object, guint property_id, G_GNUC_UNUSED const GValue * value, GParamSpec * pspec) { if (get_state(DBUS_TEST_TASK(object)) == DBUS_TEST_TASK_STATE_RUNNING) { g_warning("Can't set properties on a running process"); return; } DbusTestProcess * self = DBUS_TEST_PROCESS(object); switch (property_id) { case PROP_EXECUTABLE: g_free(self->priv->executable); self->priv->executable = g_value_dup_string(value); break; case PROP_PARAMETERS: g_array_free(self->priv->parameters, TRUE); self->priv->parameters = g_value_dup_boxed(value); break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID(object, property_id, pspec); } return; } static void proc_watcher (GPid pid, gint status, gpointer data) { gchar *message; g_return_if_fail(DBUS_TEST_IS_PROCESS(data)); DbusTestProcess * process = DBUS_TEST_PROCESS(data); if (pid != 0) { g_spawn_close_pid(pid); process->priv->pid = 0; } process->priv->complete = TRUE; process->priv->status = status; process->priv->watcher = 0; if (status) { message = g_strdup_printf("Exited with status %d", status); dbus_test_task_print(DBUS_TEST_TASK(process), message); g_free(message); } g_signal_emit_by_name(G_OBJECT(process), DBUS_TEST_TASK_SIGNAL_STATE_CHANGED, DBUS_TEST_TASK_STATE_FINISHED, NULL); return; } static gboolean proc_writes (GIOChannel * channel, G_GNUC_UNUSED GIOCondition condition, gpointer data) { g_return_val_if_fail(DBUS_TEST_IS_PROCESS(data), FALSE); DbusTestProcess * process = DBUS_TEST_PROCESS(data); gchar * line; gsize termloc; gboolean done = FALSE; do { GIOStatus status = g_io_channel_read_line (channel, &line, NULL, &termloc, NULL); if (status == G_IO_STATUS_EOF) { done = TRUE; continue; } if (status != G_IO_STATUS_NORMAL) { continue; } line[termloc] = '\0'; dbus_test_task_print(DBUS_TEST_TASK(process), line); g_free(line); } while (G_IO_IN & g_io_channel_get_buffer_condition(channel)); if (done) { process->priv->io_watch = 0; // wait for proc_watcher to switch state to FINISHED return FALSE; } return TRUE; } static void process_run (DbusTestTask * task) { g_return_if_fail(DBUS_TEST_IS_PROCESS(task)); DbusTestProcess * process = DBUS_TEST_PROCESS(task); gchar * current_dir = g_get_current_dir(); gchar ** argv; argv = g_new0(gchar *, process->priv->parameters->len + 2); argv[0] = process->priv->executable; guint i; for (i = 0; i < process->priv->parameters->len; i++) { argv[i + 1] = g_array_index(process->priv->parameters, gchar *, i); } GError * error = NULL; gint proc_stdout; g_spawn_async_with_pipes(current_dir, argv, /* argv */ NULL, /* envp */ G_SPAWN_SEARCH_PATH | G_SPAWN_DO_NOT_REAP_CHILD, /* flags */ NULL, /* child setup func */ NULL, /* child setup data */ &(process->priv->pid), /* PID */ NULL, /* stdin */ &proc_stdout, /* stdout */ NULL, /* stderr */ &error); /* error */ g_free(current_dir); g_free(argv); if (error != NULL) { g_warning("Unable to start process '%s': %s", process->priv->executable, error->message); process->priv->complete = TRUE; process->priv->status = -1; g_signal_emit_by_name(G_OBJECT(process), DBUS_TEST_TASK_SIGNAL_STATE_CHANGED, DBUS_TEST_TASK_STATE_FINISHED, NULL); return; } if (TRUE) { gchar * message = g_strdup_printf("Started with PID: %d", process->priv->pid); dbus_test_task_print(task, message); g_free(message); } process->priv->io_chan = g_io_channel_unix_new(proc_stdout); g_io_channel_set_buffer_size(process->priv->io_chan, 10 * 1024 * 1024); /* 10 MB should be enough for anyone */ process->priv->io_watch = g_io_add_watch(process->priv->io_chan, G_IO_IN | G_IO_HUP | G_IO_ERR, /* conditions */ proc_writes, /* func */ process); /* func data */ process->priv->watcher = g_child_watch_add(process->priv->pid, proc_watcher, process); g_signal_emit_by_name(G_OBJECT(process), DBUS_TEST_TASK_SIGNAL_STATE_CHANGED, DBUS_TEST_TASK_STATE_RUNNING, NULL); return; } DbusTestProcess * dbus_test_process_new (const gchar * executable) { g_return_val_if_fail(executable != NULL, NULL); DbusTestProcess * proc = g_object_new(DBUS_TEST_TYPE_PROCESS, "executable", executable, NULL); return proc; } /** * dbus_test_process_get_pid: * @process: The #DbusTestProcess to check * * Gets the process ID of the task if it is running * * Return value: The current PID or 0 if not running */ GPid dbus_test_process_get_pid (DbusTestProcess * process) { g_return_val_if_fail(DBUS_TEST_IS_PROCESS(process), 0); if (get_state(DBUS_TEST_TASK(process)) == DBUS_TEST_TASK_STATE_RUNNING) { return process->priv->pid; } return 0; } void dbus_test_process_append_param (DbusTestProcess * process, const gchar * parameter) { g_return_if_fail(DBUS_TEST_IS_PROCESS(process)); g_return_if_fail(parameter != NULL); gchar * newstr = g_strdup(parameter); g_array_append_val(process->priv->parameters, newstr); return; } static DbusTestTaskState get_state (DbusTestTask * task) { g_return_val_if_fail(DBUS_TEST_IS_PROCESS(task), DBUS_TEST_TASK_STATE_FINISHED); DbusTestProcess * process = DBUS_TEST_PROCESS(task); if (process->priv->complete) { return DBUS_TEST_TASK_STATE_FINISHED; } if (process->priv->pid != 0) { return DBUS_TEST_TASK_STATE_RUNNING; } return DBUS_TEST_TASK_STATE_INIT; } static gboolean get_passed (DbusTestTask * task) { g_return_val_if_fail(DBUS_TEST_IS_PROCESS(task), FALSE); DbusTestProcess * process = DBUS_TEST_PROCESS(task); if (!process->priv->complete) { return FALSE; } if (process->priv->status == 0) { return TRUE; } return FALSE; } ./libdbustest/process.h0000644000004100000410000000403412763551700015425 0ustar www-datawww-data/* Copyright 2012 Canonical Ltd. Authors: Ted Gould This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License version 3, as published by the Free Software Foundation. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranties of MERCHANTABILITY, SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program. If not, see . */ #ifndef __DBUS_TEST_PROCESS_H__ #define __DBUS_TEST_PROCESS_H__ #include #include #include "dbus-test.h" G_BEGIN_DECLS #define DBUS_TEST_TYPE_PROCESS (dbus_test_process_get_type ()) #define DBUS_TEST_PROCESS(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), DBUS_TEST_TYPE_PROCESS, DbusTestProcess)) #define DBUS_TEST_PROCESS_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), DBUS_TEST_TYPE_PROCESS, DbusTestProcessClass)) #define DBUS_TEST_IS_PROCESS(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), DBUS_TEST_TYPE_PROCESS)) #define DBUS_TEST_IS_PROCESS_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), DBUS_TEST_TYPE_PROCESS)) #define DBUS_TEST_PROCESS_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), DBUS_TEST_TYPE_PROCESS, DbusTestProcessClass)) typedef struct _DbusTestProcess DbusTestProcess; typedef struct _DbusTestProcessClass DbusTestProcessClass; typedef struct _DbusTestProcessPrivate DbusTestProcessPrivate; struct _DbusTestProcessClass { DbusTestTaskClass parent_class; }; struct _DbusTestProcess { DbusTestTask parent; DbusTestProcessPrivate * priv; }; GType dbus_test_process_get_type (void); DbusTestProcess * dbus_test_process_new (const gchar * executable); void dbus_test_process_append_param (DbusTestProcess * process, const gchar * parameter); GPid dbus_test_process_get_pid (DbusTestProcess * process); G_END_DECLS #endif ./libdbustest/watchdog.c0000644000004100000410000000513412763551710015545 0ustar www-datawww-data#ifdef HAVE_CONFIG_H #include "config.h" #endif #include "watchdog.h" struct _DbusTestWatchdogPrivate { GPid watchdog; }; #define DBUS_TEST_WATCHDOG_GET_PRIVATE(o) \ (G_TYPE_INSTANCE_GET_PRIVATE ((o), DBUS_TEST_TYPE_WATCHDOG, DbusTestWatchdogPrivate)) static void dbus_test_watchdog_class_init (DbusTestWatchdogClass *klass); static void dbus_test_watchdog_init (DbusTestWatchdog *self); static void dbus_test_watchdog_finalize (GObject *object); G_DEFINE_TYPE (DbusTestWatchdog, dbus_test_watchdog, G_TYPE_OBJECT); /* Initialize class */ static void dbus_test_watchdog_class_init (DbusTestWatchdogClass *klass) { GObjectClass *object_class = G_OBJECT_CLASS (klass); g_type_class_add_private (klass, sizeof (DbusTestWatchdogPrivate)); object_class->finalize = dbus_test_watchdog_finalize; return; } /* Initialize instance data */ static void dbus_test_watchdog_init (G_GNUC_UNUSED DbusTestWatchdog *self) { self->priv = DBUS_TEST_WATCHDOG_GET_PRIVATE(self); self->priv->watchdog = 0; return; } /* clean up memory */ static void dbus_test_watchdog_finalize (GObject *object) { DbusTestWatchdog * watchdog = DBUS_TEST_WATCHDOG(object); if (watchdog->priv->watchdog != 0) { kill(watchdog->priv->watchdog, SIGTERM); } G_OBJECT_CLASS (dbus_test_watchdog_parent_class)->finalize (object); return; } /** * dbus_test_watchdog_add_pid: * @watchdog: Instance of #DbusTestWatchdog * @pid: PID to kill * * Adds a PID for the watchdog to watch. */ void dbus_test_watchdog_add_pid (DbusTestWatchdog * watchdog, GPid pid) { g_return_if_fail(DBUS_TEST_IS_WATCHDOG(watchdog)); g_return_if_fail(pid != 0); g_return_if_fail(watchdog->priv->watchdog == 0); /* Setting up argument vector */ gchar * strpid = g_strdup_printf("%d", pid); gchar * argv[3]; argv[0] = WATCHDOG; argv[1] = strpid; argv[2] = NULL; GError * error = NULL; /* Spawn the watchdog, we now have 60 secs */ g_spawn_async (NULL, /* cwd */ argv, NULL, /* env */ 0, /* flags */ NULL, NULL, /* Setup function */ &watchdog->priv->watchdog, &error); g_free(strpid); if (error != NULL) { g_warning("Unable to start watchdog"); watchdog->priv->watchdog = 0; g_error_free(error); return; } return; } /** * dbus_test_watchdog_add_pid: * @watchdog: Instance of #DbusTestWatchdog * * Tell the watchdog not to kill. For now. */ void dbus_test_watchdog_ping (DbusTestWatchdog * watchdog) { g_return_if_fail(DBUS_TEST_IS_WATCHDOG(watchdog)); if (watchdog->priv->watchdog != 0) { kill(watchdog->priv->watchdog, SIGHUP); } return; } ./libdbustest/leash.c0000644000004100000410000000335612763551710015045 0ustar www-datawww-data/* Copyright 2013 Canonical Ltd. Authors: Ted Gould This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License version 3, as published by the Free Software Foundation. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranties of MERCHANTABILITY, SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program. If not, see . */ #include #include GMainLoop * mainloop = NULL; guint timer = 0; pid_t victim = 0; static gboolean sigterm_graceful_exit (gpointer user_data); static gboolean destroy_everyone (gpointer user_data) { if (victim != 0) { kill(victim, SIGTERM); } sigterm_graceful_exit(0); return FALSE; } static void restart_handler (void) { if (timer != 0) { g_source_remove(timer); } timer = g_timeout_add_seconds(60, destroy_everyone, NULL); return; } static gboolean sighup_dont_die (gpointer user_data) { restart_handler(); return TRUE; } static gboolean sigterm_graceful_exit (gpointer user_data) { g_main_loop_quit(mainloop); return FALSE; } int main (int argc, char * argv[]) { if (argc != 2) { g_critical("Need a PID to kill"); return -1; } #ifndef GLIB_VERSION_2_36 g_type_init(); #endif g_unix_signal_add (SIGTERM, sigterm_graceful_exit, NULL); g_unix_signal_add (SIGHUP, sighup_dont_die, NULL); victim = atoi(argv[1]); restart_handler(); mainloop = g_main_loop_new(NULL, FALSE); g_main_loop_run(mainloop); g_main_loop_unref(mainloop); return 0; } ./libdbustest/bustle.h0000644000004100000410000000364712763551700015256 0ustar www-datawww-data/* Copyright 2012 Canonical Ltd. Authors: Ted Gould This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License version 3, as published by the Free Software Foundation. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranties of MERCHANTABILITY, SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program. If not, see . */ #ifndef __DBUS_TEST_BUSTLE_H__ #define __DBUS_TEST_BUSTLE_H__ #include #include G_BEGIN_DECLS #define DBUS_TEST_TYPE_BUSTLE (dbus_test_bustle_get_type ()) #define DBUS_TEST_BUSTLE(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), DBUS_TEST_TYPE_BUSTLE, DbusTestBustle)) #define DBUS_TEST_BUSTLE_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), DBUS_TEST_TYPE_BUSTLE, DbusTestBustleClass)) #define DBUS_TEST_IS_BUSTLE(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), DBUS_TEST_TYPE_BUSTLE)) #define DBUS_TEST_IS_BUSTLE_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), DBUS_TEST_TYPE_BUSTLE)) #define DBUS_TEST_BUSTLE_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), DBUS_TEST_TYPE_BUSTLE, DbusTestBustleClass)) typedef struct _DbusTestBustle DbusTestBustle; typedef struct _DbusTestBustleClass DbusTestBustleClass; typedef struct _DbusTestBustlePrivate DbusTestBustlePrivate; struct _DbusTestBustleClass { DbusTestTaskClass parent_class; }; struct _DbusTestBustle { DbusTestTask parent; DbusTestBustlePrivate * priv; }; GType dbus_test_bustle_get_type (void); DbusTestBustle * dbus_test_bustle_new (const gchar * filename); void dbus_test_bustle_set_executable (DbusTestBustle * bustle, const gchar * executable); G_END_DECLS #endif ./libdbustest/dbus-test-bustle-handler0000755000004100000410000000036712763551700020352 0ustar www-datawww-data#!/bin/bash -e if [ -x /usr/bin/bustle-pcap ]; then exec /usr/bin/bustle-pcap $1 fi if [ -x /usr/bin/bustle-dbus-monitor ]; then exec /usr/bin/bustle-dbus-monitor --session > $1 fi echo "Unable to find a suitable Bustle capture tool" exit 1 ./libdbustest/service.h0000644000004100000410000000603012763551700015405 0ustar www-datawww-data/* Copyright 2012 Canonical Ltd. Authors: Ted Gould This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License version 3, as published by the Free Software Foundation. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranties of MERCHANTABILITY, SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program. If not, see . */ #ifndef __DBUS_TEST_SERVICE_H__ #define __DBUS_TEST_SERVICE_H__ #ifndef __DBUS_TEST_TOP_LEVEL__ #error "Please include #include only" #endif #include #include "task.h" G_BEGIN_DECLS #define DBUS_TEST_TYPE_SERVICE (dbus_test_service_get_type ()) #define DBUS_TEST_SERVICE(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), DBUS_TEST_TYPE_SERVICE, DbusTestService)) #define DBUS_TEST_SERVICE_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), DBUS_TEST_TYPE_SERVICE, DbusTestServiceClass)) #define DBUS_TEST_IS_SERVICE(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), DBUS_TEST_TYPE_SERVICE)) #define DBUS_TEST_IS_SERVICE_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), DBUS_TEST_TYPE_SERVICE)) #define DBUS_TEST_SERVICE_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), DBUS_TEST_TYPE_SERVICE, DbusTestServiceClass)) typedef struct _DbusTestService DbusTestService; typedef struct _DbusTestServiceClass DbusTestServiceClass; typedef struct _DbusTestServicePrivate DbusTestServicePrivate; struct _DbusTestServiceClass { GObjectClass parent_class; }; struct _DbusTestService { GObject parent; DbusTestServicePrivate * priv; }; typedef enum { DBUS_TEST_SERVICE_PRIORITY_FIRST, DBUS_TEST_SERVICE_PRIORITY_NORMAL, DBUS_TEST_SERVICE_PRIORITY_LAST } DbusTestServicePriority; typedef enum { DBUS_TEST_SERVICE_BUS_SESSION, DBUS_TEST_SERVICE_BUS_SYSTEM, DBUS_TEST_SERVICE_BUS_BOTH } DbusTestServiceBus; GType dbus_test_service_get_type (void); DbusTestService * dbus_test_service_new (const gchar * address); void dbus_test_service_start_tasks (DbusTestService * service); int dbus_test_service_run (DbusTestService * service); void dbus_test_service_stop (DbusTestService * service); void dbus_test_service_add_task (DbusTestService * service, DbusTestTask * task); void dbus_test_service_add_task_with_priority (DbusTestService * service, DbusTestTask * task, DbusTestServicePriority prio); gboolean dbus_test_service_remove_task (DbusTestService * service, DbusTestTask * task); void dbus_test_service_set_daemon (DbusTestService * service, const gchar * daemon); void dbus_test_service_set_conf_file (DbusTestService * service, const gchar * conffile); void dbus_test_service_set_keep_environment (DbusTestService * service, gboolean keep_env); void dbus_test_service_set_bus (DbusTestService * service, DbusTestServiceBus bus); G_END_DECLS #endif ./libdbustest/dbus-mock-iface.xml0000644000004100000410000000640512763551700017255 0ustar www-datawww-data ./libdbustest/dbus-test.h0000644000004100000410000000202512763551700015657 0ustar www-datawww-data/* Copyright 2012 Canonical Ltd. Authors: Ted Gould This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License version 3, as published by the Free Software Foundation. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranties of MERCHANTABILITY, SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program. If not, see . */ #ifndef __DBUS_TEST_H__ #define __DBUS_TEST_H__ #ifdef __DBUS_TEST_TOP_LEVEL__ #error "Please include #include only" #endif #define __DBUS_TEST_TOP_LEVEL__ 1 #include #include #include #include #include #endif /* __DBUS_TEST_H__ */ ./libdbustest/task.c0000644000004100000410000002547512763551700014720 0ustar www-datawww-data/* Copyright 2012 Canonical Ltd. Authors: Ted Gould This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License version 3, as published by the Free Software Foundation. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranties of MERCHANTABILITY, SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program. If not, see . */ #ifdef HAVE_CONFIG_H #include "config.h" #endif #include "dbus-test.h" #include struct _DbusTestTaskPrivate { DbusTestTaskReturn return_type; gchar * wait_for; DbusTestServiceBus wait_for_bus; guint wait_task; gchar * name; gchar * name_padded; glong padding_cnt; gboolean been_run; gboolean wait_until_complete; DbusTestServiceBus preferred_bus; }; /* Signals */ enum { STATE_CHANGED, LAST_SIGNAL /* Don't touch! */ }; #define DBUS_TEST_TASK_GET_PRIVATE(o) \ (G_TYPE_INSTANCE_GET_PRIVATE ((o), DBUS_TEST_TYPE_TASK, DbusTestTaskPrivate)) static void dbus_test_task_class_init (DbusTestTaskClass *klass); static void dbus_test_task_init (DbusTestTask *self); static void dbus_test_task_dispose (GObject *object); static void dbus_test_task_finalize (GObject *object); G_DEFINE_TYPE (DbusTestTask, dbus_test_task, G_TYPE_OBJECT); static guint signals[LAST_SIGNAL] = {0}; static void dbus_test_task_class_init (DbusTestTaskClass *klass) { GObjectClass *object_class = G_OBJECT_CLASS (klass); g_type_class_add_private (klass, sizeof (DbusTestTaskPrivate)); object_class->dispose = dbus_test_task_dispose; object_class->finalize = dbus_test_task_finalize; klass->run = NULL; klass->get_state = NULL; klass->get_passed = NULL; signals[STATE_CHANGED] = g_signal_new(DBUS_TEST_TASK_SIGNAL_STATE_CHANGED, G_TYPE_FROM_CLASS (klass), G_SIGNAL_RUN_LAST, G_STRUCT_OFFSET (DbusTestTaskClass, state_changed), NULL, NULL, g_cclosure_marshal_VOID__INT, G_TYPE_NONE, 1, G_TYPE_INT, G_TYPE_NONE); return; } static void dbus_test_task_init (DbusTestTask *self) { static gint task_count = 0; self->priv = DBUS_TEST_TASK_GET_PRIVATE(self); self->priv->return_type = DBUS_TEST_TASK_RETURN_NORMAL; self->priv->wait_for = NULL; self->priv->wait_for_bus = DBUS_TEST_SERVICE_BUS_BOTH; self->priv->wait_task = 0; self->priv->name = g_strdup_printf("task-%d", task_count++); self->priv->name_padded = NULL; self->priv->padding_cnt = 0; self->priv->been_run = FALSE; self->priv->wait_until_complete = FALSE; self->priv->preferred_bus = DBUS_TEST_SERVICE_BUS_BOTH; return; } static void dbus_test_task_dispose (GObject *object) { g_return_if_fail(DBUS_TEST_IS_TASK(object)); DbusTestTask * self = DBUS_TEST_TASK(object); if (self->priv->wait_task != 0) { g_bus_unwatch_name(self->priv->wait_task); self->priv->wait_task = 0; } G_OBJECT_CLASS (dbus_test_task_parent_class)->dispose (object); return; } static void dbus_test_task_finalize (GObject *object) { g_return_if_fail(DBUS_TEST_IS_TASK(object)); DbusTestTask * self = DBUS_TEST_TASK(object); g_print("%s: Shutting down\n", self->priv->name); g_free(self->priv->name); g_free(self->priv->name_padded); g_free(self->priv->wait_for); G_OBJECT_CLASS (dbus_test_task_parent_class)->finalize (object); return; } DbusTestTask * dbus_test_task_new (void) { DbusTestTask * task = g_object_new(DBUS_TEST_TYPE_TASK, NULL); return task; } void dbus_test_task_set_name (DbusTestTask * task, const gchar * name) { g_return_if_fail(DBUS_TEST_IS_TASK(task)); g_free(task->priv->name); g_free(task->priv->name_padded); task->priv->name = g_strdup(name); if (task->priv->padding_cnt != 0 && task->priv->name != NULL) { gchar * fillstr = g_strnfill(task->priv->padding_cnt - g_utf8_strlen(task->priv->name, -1), ' '); task->priv->name_padded = g_strconcat(task->priv->name, fillstr, NULL); g_free(fillstr); } else { task->priv->name_padded = NULL; } return; } void dbus_test_task_set_name_spacing (DbusTestTask * task, glong chars) { g_return_if_fail(DBUS_TEST_IS_TASK(task)); g_free(task->priv->name_padded); task->priv->padding_cnt = chars; g_return_if_fail(task->priv->padding_cnt >= g_utf8_strlen(task->priv->name, -1)); if (chars != 0 && task->priv->name != NULL) { gchar * fillstr = g_strnfill(task->priv->padding_cnt - g_utf8_strlen(task->priv->name, -1), ' '); task->priv->name_padded = g_strconcat(task->priv->name, fillstr, NULL); g_free(fillstr); } else { task->priv->name_padded = NULL; } return; } void dbus_test_task_set_wait_for (DbusTestTask * task, const gchar * dbus_name) { return dbus_test_task_set_wait_for_bus(task, dbus_name, DBUS_TEST_SERVICE_BUS_BOTH); } void dbus_test_task_set_wait_for_bus (DbusTestTask * task, const gchar * dbus_name, DbusTestServiceBus bus) { g_return_if_fail(DBUS_TEST_IS_TASK(task)); if (task->priv->wait_for != NULL) { g_free(task->priv->wait_for); task->priv->wait_for = NULL; task->priv->wait_for_bus = DBUS_TEST_SERVICE_BUS_BOTH; } if (dbus_name == NULL) { return; } task->priv->wait_for = g_strdup(dbus_name); task->priv->wait_for_bus = bus; return; } void dbus_test_task_set_return (DbusTestTask * task, DbusTestTaskReturn ret) { g_return_if_fail(DBUS_TEST_IS_TASK(task)); if (ret != task->priv->return_type && dbus_test_task_get_state(task) == DBUS_TEST_TASK_STATE_FINISHED) { g_warning("Changing return type after the task has finished"); } task->priv->return_type = ret; return; } void dbus_test_task_print (DbusTestTask * task, const gchar * message) { g_return_if_fail(DBUS_TEST_IS_TASK(task)); g_return_if_fail(message != NULL); gchar * name = task->priv->name; if (task->priv->name_padded != NULL) { name = task->priv->name_padded; } g_print("%s: %s\n", name, message); return; } DbusTestTaskState dbus_test_task_get_state (DbusTestTask * task) { g_return_val_if_fail(DBUS_TEST_IS_TASK(task), DBUS_TEST_TASK_STATE_FINISHED); if (task->priv->wait_task != 0) { return DBUS_TEST_TASK_STATE_WAITING; } DbusTestTaskClass * klass = DBUS_TEST_TASK_GET_CLASS(task); if (klass->get_state != NULL) { return klass->get_state(task); } if (task->priv->been_run) { return DBUS_TEST_TASK_STATE_FINISHED; } else { return DBUS_TEST_TASK_STATE_INIT; } } DbusTestTaskReturn dbus_test_task_get_return (DbusTestTask * task) { g_return_val_if_fail(DBUS_TEST_IS_TASK(task), DBUS_TEST_TASK_RETURN_IGNORE); return task->priv->return_type; } static void wait_for_found (G_GNUC_UNUSED GDBusConnection * connection, G_GNUC_UNUSED const gchar * name, G_GNUC_UNUSED const gchar * name_owner, gpointer user_data) { g_return_if_fail(DBUS_TEST_IS_TASK(user_data)); DbusTestTask * task = DBUS_TEST_TASK(user_data); g_bus_unwatch_name(task->priv->wait_task); task->priv->wait_task = 0; DbusTestTaskClass * klass = DBUS_TEST_TASK_GET_CLASS(task); task->priv->been_run = TRUE; if (klass->run != NULL) { klass->run(task); } else { g_signal_emit(G_OBJECT(task), signals[STATE_CHANGED], 0, DBUS_TEST_TASK_STATE_FINISHED, NULL); } return; } void dbus_test_task_run (DbusTestTask * task) { g_return_if_fail(DBUS_TEST_IS_TASK(task)); /* We're going to process the waiting at this level if we've been asked to do so */ if (task->priv->wait_for != NULL) { GBusType bustype = G_BUS_TYPE_SESSION; if (task->priv->wait_for_bus == DBUS_TEST_SERVICE_BUS_BOTH && task->priv->preferred_bus == DBUS_TEST_SERVICE_BUS_SYSTEM) { bustype = G_BUS_TYPE_SYSTEM; } task->priv->wait_task = g_bus_watch_name(bustype, task->priv->wait_for, G_BUS_NAME_WATCHER_FLAGS_NONE, wait_for_found, NULL, task, NULL); g_signal_emit(G_OBJECT(task), signals[STATE_CHANGED], 0, DBUS_TEST_TASK_STATE_WAITING, NULL); return; } DbusTestTaskClass * klass = DBUS_TEST_TASK_GET_CLASS(task); task->priv->been_run = TRUE; if (klass->run != NULL) { klass->run(task); } else { g_signal_emit(G_OBJECT(task), signals[STATE_CHANGED], 0, DBUS_TEST_TASK_STATE_FINISHED, NULL); } return; } gboolean dbus_test_task_passed (DbusTestTask * task) { g_return_val_if_fail(DBUS_TEST_IS_TASK(task), FALSE); g_return_val_if_fail(task->priv->been_run, FALSE); /* If we don't care, we always pass */ if (task->priv->return_type == DBUS_TEST_TASK_RETURN_IGNORE) { return TRUE; } DbusTestTaskClass * klass = DBUS_TEST_TASK_GET_CLASS(task); if (klass->get_passed == NULL) { return FALSE; } gboolean subret = klass->get_passed(task); if (task->priv->return_type == DBUS_TEST_TASK_RETURN_INVERT) { return !subret; } return subret; } const gchar * dbus_test_task_get_name (DbusTestTask * task) { g_return_val_if_fail(DBUS_TEST_IS_TASK(task), NULL); return task->priv->name; } const gchar * dbus_test_task_get_wait_for (DbusTestTask * task) { g_return_val_if_fail(DBUS_TEST_IS_TASK(task), NULL); return task->priv->wait_for; } /** * dbus_test_task_set_wait_finished: * @task: Task to adjust the value on * @wait_till_complete: Set this task to wait until complete * even if we don't care about the return value. * * If this task has the value of its return set to ignore this * means we won't exit early. */ void dbus_test_task_set_wait_finished (DbusTestTask * task, gboolean wait_till_complete) { g_return_if_fail(DBUS_TEST_IS_TASK(task)); task->priv->wait_until_complete = wait_till_complete; return; } /** * dbus_test_task_set_wait_finished: * @task: Task to get the value from * * Check to see if we should wait on this taks irregardless * of whether we care about the return value. */ gboolean dbus_test_task_get_wait_finished (DbusTestTask * task) { g_return_val_if_fail(DBUS_TEST_IS_TASK(task), FALSE); return task->priv->wait_until_complete; } /** * dbus_test_task_set_bus: * @task: Task to get the bus from * @bus: Preferred bus for this task * * Set which bus this task prefers to be on. */ void dbus_test_task_set_bus (DbusTestTask * task, DbusTestServiceBus bus) { g_return_if_fail(DBUS_TEST_IS_TASK(task)); task->priv->preferred_bus = bus; } /** * dbus_test_task_get_bus: * @task: Task to get the bus from * * Check to see which bus this task prefers to be on. */ DbusTestServiceBus dbus_test_task_get_bus (DbusTestTask * task) { g_return_val_if_fail(DBUS_TEST_IS_TASK(task), DBUS_TEST_SERVICE_BUS_BOTH); return task->priv->preferred_bus; } ./libdbustest/bustle.c0000644000004100000410000002061412763551700015242 0ustar www-datawww-data/* Copyright 2012 Canonical Ltd. Authors: Ted Gould This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License version 3, as published by the Free Software Foundation. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranties of MERCHANTABILITY, SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program. If not, see . */ #ifdef HAVE_CONFIG_H #include "config.h" #endif #include #include "glib-compat.h" #include "dbus-test.h" struct _DbusTestBustlePrivate { gchar * filename; gchar * executable; guint watch; GIOChannel * stderr; GIOChannel * file; GPid pid; gboolean crashed; }; #define DBUS_TEST_BUSTLE_GET_PRIVATE(o) \ (G_TYPE_INSTANCE_GET_PRIVATE ((o), DBUS_TEST_TYPE_BUSTLE, DbusTestBustlePrivate)) static void dbus_test_bustle_class_init (DbusTestBustleClass *klass); static void dbus_test_bustle_init (DbusTestBustle *self); static void dbus_test_bustle_dispose (GObject *object); static void dbus_test_bustle_finalize (GObject *object); static void process_run (DbusTestTask * task); static DbusTestTaskState get_state (DbusTestTask * task); static gboolean get_passed (DbusTestTask * task); static gboolean bustle_write_error (GIOChannel * channel, GIOCondition condition, gpointer data); G_DEFINE_TYPE (DbusTestBustle, dbus_test_bustle, DBUS_TEST_TYPE_TASK); static void dbus_test_bustle_class_init (DbusTestBustleClass *klass) { GObjectClass *object_class = G_OBJECT_CLASS (klass); g_type_class_add_private (klass, sizeof (DbusTestBustlePrivate)); object_class->dispose = dbus_test_bustle_dispose; object_class->finalize = dbus_test_bustle_finalize; DbusTestTaskClass * task_class = DBUS_TEST_TASK_CLASS(klass); task_class->run = process_run; task_class->get_state = get_state; task_class->get_passed = get_passed; return; } static void dbus_test_bustle_init (DbusTestBustle *self) { gchar * current_dir = g_get_current_dir(); self->priv = DBUS_TEST_BUSTLE_GET_PRIVATE(self); self->priv->filename = g_strconcat(current_dir, G_DIR_SEPARATOR_S, "bustle.log", NULL); self->priv->executable = g_strdup(BUSTLE_DUAL_MONITOR); self->priv->watch = 0; self->priv->stderr = NULL; self->priv->file = NULL; self->priv->pid = 0; self->priv->crashed = FALSE; g_free (current_dir); return; } static void dbus_test_bustle_dispose (GObject *object) { g_return_if_fail(DBUS_TEST_IS_BUSTLE(object)); DbusTestBustle * bustler = DBUS_TEST_BUSTLE(object); if (bustler->priv->watch != 0) { g_source_remove(bustler->priv->watch); bustler->priv->watch = 0; } if (bustler->priv->pid != 0) { gchar * command = g_strdup_printf("kill -INT %d", bustler->priv->pid); g_spawn_command_line_sync(command, NULL, NULL, NULL, NULL); g_free(command); g_spawn_close_pid(bustler->priv->pid); } if (bustler->priv->stderr != NULL) { while (G_IO_IN & g_io_channel_get_buffer_condition(bustler->priv->stderr)) { bustle_write_error(bustler->priv->stderr, 0 /* unused */, bustler); } g_clear_pointer(&bustler->priv->stderr, g_io_channel_unref); } if (bustler->priv->file != NULL) { g_io_channel_shutdown(bustler->priv->file, TRUE, NULL); g_clear_pointer(&bustler->priv->file, g_io_channel_unref); } G_OBJECT_CLASS (dbus_test_bustle_parent_class)->dispose (object); return; } static void dbus_test_bustle_finalize (GObject *object) { g_return_if_fail(DBUS_TEST_IS_BUSTLE(object)); DbusTestBustle * bustler = DBUS_TEST_BUSTLE(object); g_free(bustler->priv->filename); g_free(bustler->priv->executable); G_OBJECT_CLASS (dbus_test_bustle_parent_class)->finalize (object); return; } DbusTestBustle * dbus_test_bustle_new (const gchar * filename) { g_return_val_if_fail(filename != NULL, NULL); DbusTestBustle * bustler = g_object_new(DBUS_TEST_TYPE_BUSTLE, NULL); g_free(bustler->priv->filename); bustler->priv->filename = g_strdup(filename); dbus_test_task_set_name(DBUS_TEST_TASK(bustler), "Bustle"); return bustler; } void dbus_test_bustle_set_executable (DbusTestBustle * bustle, const gchar * executable) { g_return_if_fail(DBUS_TEST_IS_BUSTLE(bustle)); g_return_if_fail(executable != NULL); g_free(bustle->priv->executable); bustle->priv->executable = g_strdup(executable); return; } static void bustle_watcher (GPid pid, G_GNUC_UNUSED gint status, gpointer data) { g_critical("Bustle Monitor exited abruptly!"); DbusTestBustle * bustler = DBUS_TEST_BUSTLE(data); if (bustler->priv->pid != 0) { g_spawn_close_pid(pid); bustler->priv->pid = 0; } bustler->priv->crashed = TRUE; g_signal_emit_by_name(G_OBJECT(bustler), DBUS_TEST_TASK_SIGNAL_STATE_CHANGED, DBUS_TEST_TASK_STATE_FINISHED, NULL); return; } static gboolean bustle_write_error (GIOChannel * channel, G_GNUC_UNUSED GIOCondition condition, gpointer data) { gchar * line; gsize termloc; do { GIOStatus status = g_io_channel_read_line (channel, &line, NULL, &termloc, NULL); if (status == G_IO_STATUS_EOF) { return FALSE; } if (status != G_IO_STATUS_NORMAL) { continue; } line[termloc] = '\0'; dbus_test_task_print(DBUS_TEST_TASK(data), line); g_free(line); } while (G_IO_IN & g_io_channel_get_buffer_condition(channel)); return TRUE; } static void process_run (DbusTestTask * task) { g_return_if_fail(DBUS_TEST_IS_BUSTLE(task)); DbusTestBustle * bustler = DBUS_TEST_BUSTLE(task); if (bustler->priv->pid != 0) { return; } GError * error = NULL; bustler->priv->file = g_io_channel_new_file(bustler->priv->filename, "w", &error); if (error != NULL) { g_critical("Unable to open bustle file '%s': %s", bustler->priv->filename, error->message); g_error_free(error); bustler->priv->crashed = TRUE; g_signal_emit_by_name(G_OBJECT(bustler), DBUS_TEST_TASK_SIGNAL_STATE_CHANGED, DBUS_TEST_TASK_STATE_FINISHED, NULL); return; } gint bustle_stderr_num; gchar * current_dir = g_get_current_dir(); gchar ** bustle_monitor = g_new0(gchar *, 3); bustle_monitor[0] = (gchar *)bustler->priv->executable; bustle_monitor[1] = (gchar *)bustler->priv->filename; g_spawn_async_with_pipes(current_dir, bustle_monitor, /* argv */ NULL, /* envp */ /* G_SPAWN_SEARCH_PATH | G_SPAWN_STDERR_TO_DEV_NULL, */ /* flags */ G_SPAWN_SEARCH_PATH | G_SPAWN_DO_NOT_REAP_CHILD, /* flags */ NULL, /* child setup func */ NULL, /* child setup data */ &bustler->priv->pid, /* PID */ NULL, /* stdin */ NULL, /* stdout */ &bustle_stderr_num, /* stderr */ &error); /* error */ g_free(current_dir); g_free(bustle_monitor); if (error != NULL) { g_critical("Unable to start bustling data: %s", error->message); g_error_free(error); bustler->priv->pid = 0; /* ensure this */ bustler->priv->crashed = TRUE; g_signal_emit_by_name(G_OBJECT(bustler), DBUS_TEST_TASK_SIGNAL_STATE_CHANGED, DBUS_TEST_TASK_STATE_FINISHED, NULL); return; } if (TRUE) { gchar * start = g_strdup_printf("Starting bustle monitor. PID: %d", bustler->priv->pid); dbus_test_task_print(DBUS_TEST_TASK(bustler), start); g_free(start); } bustler->priv->watch = g_child_watch_add(bustler->priv->pid, bustle_watcher, bustler); bustler->priv->stderr = g_io_channel_unix_new(bustle_stderr_num); g_io_add_watch(bustler->priv->stderr, G_IO_IN | G_IO_HUP | G_IO_ERR, /* conditions */ bustle_write_error, /* func */ bustler); /* func data */ return; } static DbusTestTaskState get_state (DbusTestTask * task) { /* We're always finished, but we want an error */ g_return_val_if_fail(DBUS_TEST_IS_BUSTLE(task), DBUS_TEST_TASK_STATE_FINISHED); return DBUS_TEST_TASK_STATE_FINISHED; } static gboolean get_passed (DbusTestTask * task) { g_return_val_if_fail(DBUS_TEST_IS_BUSTLE(task), FALSE); DbusTestBustle * bustler = DBUS_TEST_BUSTLE(task); if (bustler->priv->crashed) { return FALSE; } else { return TRUE; } } ./libdbustest/task.h0000644000004100000410000000722612763551700014717 0ustar www-datawww-data/* Copyright 2012 Canonical Ltd. Authors: Ted Gould This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License version 3, as published by the Free Software Foundation. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranties of MERCHANTABILITY, SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program. If not, see . */ #ifndef __DBUS_TEST_TASK_H__ #define __DBUS_TEST_TASK_H__ #ifndef __DBUS_TEST_TOP_LEVEL__ #error "Please include #include only" #endif #include #include G_BEGIN_DECLS #define DBUS_TEST_TASK_SIGNAL_STATE_CHANGED "state-changed" #define DBUS_TEST_TYPE_TASK (dbus_test_task_get_type ()) #define DBUS_TEST_TASK(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), DBUS_TEST_TYPE_TASK, DbusTestTask)) #define DBUS_TEST_TASK_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), DBUS_TEST_TYPE_TASK, DbusTestTaskClass)) #define DBUS_TEST_IS_TASK(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), DBUS_TEST_TYPE_TASK)) #define DBUS_TEST_IS_TASK_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), DBUS_TEST_TYPE_TASK)) #define DBUS_TEST_TASK_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), DBUS_TEST_TYPE_TASK, DbusTestTaskClass)) typedef struct _DbusTestTask DbusTestTask; typedef struct _DbusTestTaskClass DbusTestTaskClass; typedef struct _DbusTestTaskPrivate DbusTestTaskPrivate; typedef enum { DBUS_TEST_TASK_STATE_INIT, DBUS_TEST_TASK_STATE_WAITING, DBUS_TEST_TASK_STATE_RUNNING, DBUS_TEST_TASK_STATE_FINISHED } DbusTestTaskState; typedef enum { DBUS_TEST_TASK_RETURN_NORMAL, DBUS_TEST_TASK_RETURN_IGNORE, DBUS_TEST_TASK_RETURN_INVERT } DbusTestTaskReturn; struct _DbusTestTaskClass { GObjectClass parent_class; /* Subclassable functions */ void (*run) (DbusTestTask * task); DbusTestTaskState (*get_state) (DbusTestTask * task); gboolean (*get_passed) (DbusTestTask * task); /* Signals */ void (*state_changed) (DbusTestTask * task, DbusTestTaskState new_state, gpointer user_data); }; struct _DbusTestTask { GObject parent; DbusTestTaskPrivate * priv; }; #include "service.h" GType dbus_test_task_get_type (void); DbusTestTask * dbus_test_task_new (void); void dbus_test_task_set_name (DbusTestTask * task, const gchar * name); void dbus_test_task_set_name_spacing (DbusTestTask * task, glong chars); void dbus_test_task_set_wait_for (DbusTestTask * task, const gchar * dbus_name); void dbus_test_task_set_wait_for_bus (DbusTestTask * task, const gchar * dbus_name, DbusTestServiceBus bus); void dbus_test_task_set_return (DbusTestTask * task, DbusTestTaskReturn ret); void dbus_test_task_set_wait_finished (DbusTestTask * task, gboolean wait_till_complete); void dbus_test_task_set_bus (DbusTestTask * task, DbusTestServiceBus bus); void dbus_test_task_print (DbusTestTask * task, const gchar * message); DbusTestTaskState dbus_test_task_get_state (DbusTestTask * task); DbusTestTaskReturn dbus_test_task_get_return (DbusTestTask * task); const gchar * dbus_test_task_get_name (DbusTestTask * task); const gchar * dbus_test_task_get_wait_for (DbusTestTask * task); gboolean dbus_test_task_get_wait_finished (DbusTestTask * task); DbusTestServiceBus dbus_test_task_get_bus (DbusTestTask * task); void dbus_test_task_run (DbusTestTask * task); gboolean dbus_test_task_passed (DbusTestTask * task); G_END_DECLS #endif ./libdbustest/watchdog.h0000644000004100000410000000257512763551700015557 0ustar www-datawww-data#ifndef __DBUS_TEST_WATCHDOG_H__ #define __DBUS_TEST_WATCHDOG_H__ #include #include G_BEGIN_DECLS #define DBUS_TEST_TYPE_WATCHDOG (dbus_test_watchdog_get_type ()) #define DBUS_TEST_WATCHDOG(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), DBUS_TEST_TYPE_WATCHDOG, DbusTestWatchdog)) #define DBUS_TEST_WATCHDOG_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), DBUS_TEST_TYPE_WATCHDOG, DbusTestWatchdogClass)) #define DBUS_TEST_IS_WATCHDOG(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), DBUS_TEST_TYPE_WATCHDOG)) #define DBUS_TEST_IS_WATCHDOG_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), DBUS_TEST_TYPE_WATCHDOG)) #define DBUS_TEST_WATCHDOG_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), DBUS_TEST_TYPE_WATCHDOG, DbusTestWatchdogClass)) typedef struct _DbusTestWatchdog DbusTestWatchdog; typedef struct _DbusTestWatchdogClass DbusTestWatchdogClass; typedef struct _DbusTestWatchdogPrivate DbusTestWatchdogPrivate; struct _DbusTestWatchdogClass { GObjectClass parent_class; }; struct _DbusTestWatchdog { GObject parent; DbusTestWatchdogPrivate * priv; }; GType dbus_test_watchdog_get_type (void); void dbus_test_watchdog_add_pid (DbusTestWatchdog * watchdog, GPid pid); void dbus_test_watchdog_ping (DbusTestWatchdog * watchdog); G_END_DECLS #endif ./libdbustest/service.c0000644000004100000410000005166012763551700015411 0ustar www-datawww-data/* Copyright 2012 Canonical Ltd. Authors: Ted Gould This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License version 3, as published by the Free Software Foundation. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranties of MERCHANTABILITY, SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program. If not, see . */ #ifdef HAVE_CONFIG_H #include "config.h" #endif #include #include #include #include #include "glib-compat.h" #include "dbus-test.h" #include "watchdog.h" typedef enum _ServiceState ServiceState; enum _ServiceState { STATE_INIT, STATE_DAEMON_STARTING, STATE_DAEMON_STARTED, STATE_DAEMON_FAILED, STATE_STARTING, STATE_STARTED, STATE_RUNNING, STATE_FINISHED }; struct _DbusTestServicePrivate { GQueue tasks_first; GQueue tasks_normal; GQueue tasks_last; GMainLoop * mainloop; ServiceState state; gboolean daemon_crashed; GPid dbus; guint dbus_watch; GIOChannel * dbus_io; guint dbus_io_watch; gchar * dbus_daemon; gchar * dbus_configfile; gboolean first_time; gboolean keep_env; DbusTestWatchdog * watchdog; guint watchdog_source; DbusTestServiceBus bus_type; }; #define SERVICE_CHANGE_HANDLER "dbus-test-service-change-handler" #define DBUS_TEST_SERVICE_GET_PRIVATE(o) \ (G_TYPE_INSTANCE_GET_PRIVATE ((o), DBUS_TEST_TYPE_SERVICE, DbusTestServicePrivate)) static void dbus_test_service_class_init (DbusTestServiceClass *klass); static void dbus_test_service_init (DbusTestService *self); static void dbus_test_service_dispose (GObject *object); static void dbus_test_service_finalize (GObject *object); static gboolean watchdog_ping (gpointer user_data); G_DEFINE_TYPE (DbusTestService, dbus_test_service, G_TYPE_OBJECT); static void dbus_test_service_class_init (DbusTestServiceClass *klass) { GObjectClass *object_class = G_OBJECT_CLASS (klass); g_type_class_add_private (klass, sizeof (DbusTestServicePrivate)); object_class->dispose = dbus_test_service_dispose; object_class->finalize = dbus_test_service_finalize; return; } static void dbus_test_service_init (DbusTestService *self) { self->priv = DBUS_TEST_SERVICE_GET_PRIVATE(self); g_queue_init(&self->priv->tasks_first); g_queue_init(&self->priv->tasks_normal); g_queue_init(&self->priv->tasks_last); self->priv->mainloop = g_main_loop_new(NULL, FALSE); self->priv->state = STATE_INIT; self->priv->daemon_crashed = FALSE; self->priv->dbus = 0; self->priv->dbus_watch = 0; self->priv->dbus_io = NULL; self->priv->dbus_io_watch = 0; self->priv->dbus_daemon = g_strdup("dbus-daemon"); self->priv->dbus_configfile = g_strdup(DEFAULT_SESSION_CONF); self->priv->first_time = TRUE; self->priv->keep_env = FALSE; self->priv->watchdog = g_object_new(DBUS_TEST_TYPE_WATCHDOG, NULL); self->priv->watchdog_source = g_timeout_add_seconds_full(G_PRIORITY_DEFAULT, 5, watchdog_ping, g_object_ref(self->priv->watchdog), g_object_unref); self->priv->bus_type = DBUS_TEST_SERVICE_BUS_SESSION; return; } static void task_unref (gpointer data, G_GNUC_UNUSED gpointer user_data) { DbusTestTask * task = DBUS_TEST_TASK(data); gulong handler = GPOINTER_TO_UINT(g_object_get_data(G_OBJECT(task), SERVICE_CHANGE_HANDLER)); if (handler != 0) { g_signal_handler_disconnect(G_OBJECT(task), handler); } g_object_unref(task); return; } static void dbus_test_service_dispose (GObject *object) { g_return_if_fail(DBUS_TEST_IS_SERVICE(object)); DbusTestService * self = DBUS_TEST_SERVICE(object); if (!g_queue_is_empty(&self->priv->tasks_last)) { g_queue_foreach(&self->priv->tasks_last, task_unref, NULL); g_queue_clear(&self->priv->tasks_last); } if (!g_queue_is_empty(&self->priv->tasks_normal)) { g_queue_foreach(&self->priv->tasks_normal, task_unref, NULL); g_queue_clear(&self->priv->tasks_normal); } if (!g_queue_is_empty(&self->priv->tasks_first)) { g_queue_foreach(&self->priv->tasks_first, task_unref, NULL); g_queue_clear(&self->priv->tasks_first); } if (self->priv->dbus_watch != 0) { g_source_remove(self->priv->dbus_watch); self->priv->dbus_watch = 0; } if (self->priv->dbus_io_watch != 0) { g_source_remove(self->priv->dbus_io_watch); self->priv->dbus_io_watch = 0; } if (self->priv->dbus_io != NULL) { g_io_channel_shutdown(self->priv->dbus_io, TRUE, NULL); g_io_channel_unref(self->priv->dbus_io); self->priv->dbus_io = NULL; } g_print("DBus daemon: Shutdown\n"); if (self->priv->dbus != 0) { gchar * cmd = g_strdup_printf("kill -9 %d", self->priv->dbus); g_spawn_command_line_async(cmd, NULL); g_free(cmd); g_spawn_close_pid(self->priv->dbus); self->priv->dbus = 0; } if (self->priv->mainloop != NULL) { g_main_loop_unref(self->priv->mainloop); self->priv->mainloop = NULL; } g_clear_object(&self->priv->watchdog); if (self->priv->watchdog_source != 0) { g_source_remove(self->priv->watchdog_source); self->priv->watchdog_source = 0; } G_OBJECT_CLASS (dbus_test_service_parent_class)->dispose (object); return; } static void dbus_test_service_finalize (GObject *object) { g_return_if_fail(DBUS_TEST_IS_SERVICE(object)); DbusTestService * self = DBUS_TEST_SERVICE(object); g_free(self->priv->dbus_daemon); self->priv->dbus_daemon = NULL; g_free(self->priv->dbus_configfile); self->priv->dbus_configfile = NULL; G_OBJECT_CLASS (dbus_test_service_parent_class)->finalize (object); return; } DbusTestService * dbus_test_service_new (G_GNUC_UNUSED const gchar * address) { DbusTestService * service = g_object_new(DBUS_TEST_TYPE_SERVICE, NULL); /* TODO: Use the address */ return service; } /* Ping the watchdog so that it knows we're still alive */ static gboolean watchdog_ping (gpointer user_data) { DbusTestWatchdog * watchdog = DBUS_TEST_WATCHDOG(user_data); dbus_test_watchdog_ping(watchdog); return TRUE; } static gboolean all_tasks_finished_helper (G_GNUC_UNUSED DbusTestService * service, DbusTestTask * task, G_GNUC_UNUSED gpointer user_data) { DbusTestTaskState state = dbus_test_task_get_state(task); DbusTestTaskReturn ret = dbus_test_task_get_return(task); if (state != DBUS_TEST_TASK_STATE_FINISHED && (ret != DBUS_TEST_TASK_RETURN_IGNORE || dbus_test_task_get_wait_finished(task))) { return FALSE; } return TRUE; } static gboolean all_tasks_started_helper (G_GNUC_UNUSED DbusTestService * service, DbusTestTask * task, G_GNUC_UNUSED gpointer user_data) { DbusTestTaskState state = dbus_test_task_get_state(task); if (state == DBUS_TEST_TASK_STATE_INIT || state == DBUS_TEST_TASK_STATE_WAITING) { return FALSE; } return TRUE; } static gboolean all_tasks_bus_match (DbusTestService * service, DbusTestTask * task, G_GNUC_UNUSED gpointer user_data) { return service->priv->bus_type == DBUS_TEST_SERVICE_BUS_BOTH || dbus_test_task_get_bus(task) == DBUS_TEST_SERVICE_BUS_BOTH || dbus_test_task_get_bus(task) == service->priv->bus_type; } typedef struct { DbusTestService * service; gboolean passing; gpointer user_data; gboolean (*func) (DbusTestService * service, DbusTestTask * task, gpointer data); } all_tasks_helper_data_t; static void all_tasks_helper (gpointer taskp, gpointer datap) { all_tasks_helper_data_t * data = (all_tasks_helper_data_t *)datap; if (!data->passing) { /* Quick exit */ return; } data->passing = data->func(data->service, DBUS_TEST_TASK(taskp), data->user_data); } static gboolean all_tasks (DbusTestService * service, gboolean (*helper) (DbusTestService * service, DbusTestTask * task, gpointer user_data), gpointer user_data) { all_tasks_helper_data_t data = { .passing = TRUE, .service = service, .func = helper, .user_data = user_data }; g_queue_foreach(&service->priv->tasks_first, all_tasks_helper, &data); if (!data.passing) { return FALSE; } g_queue_foreach(&service->priv->tasks_normal, all_tasks_helper, &data); if (!data.passing) { return FALSE; } g_queue_foreach(&service->priv->tasks_last, all_tasks_helper, &data); if (!data.passing) { return FALSE; } return TRUE; } static void task_set_name_length (gpointer data, gpointer user_data) { DbusTestTask * task = DBUS_TEST_TASK(data); glong * length = (glong *)user_data; dbus_test_task_set_name_spacing(task, *length); return; } static void task_get_name_length (gpointer data, gpointer user_data) { DbusTestTask * task = DBUS_TEST_TASK(data); glong * length = (glong *)user_data; const gchar * name = dbus_test_task_get_name(task); g_return_if_fail(name != NULL); glong nlength = g_utf8_strlen(name, -1); *length = MAX(*length, nlength); return; } static void normalize_name_lengths (DbusTestService * service) { glong length = 0; g_queue_foreach(&service->priv->tasks_first, task_get_name_length, &length); g_queue_foreach(&service->priv->tasks_normal, task_get_name_length, &length); g_queue_foreach(&service->priv->tasks_last, task_get_name_length, &length); g_queue_foreach(&service->priv->tasks_first, task_set_name_length, &length); g_queue_foreach(&service->priv->tasks_normal, task_set_name_length, &length); g_queue_foreach(&service->priv->tasks_last, task_set_name_length, &length); return; } static void task_starter (gpointer data, G_GNUC_UNUSED gpointer user_data) { DbusTestTask * task = DBUS_TEST_TASK(data); dbus_test_task_run(task); return; } static gboolean dbus_writes (GIOChannel * channel, GIOCondition condition, gpointer data) { DbusTestService * service = DBUS_TEST_SERVICE(data); if (condition & G_IO_ERR) { g_critical("DBus writing failure!"); return FALSE; } gchar * line; gsize termloc; GIOStatus status = g_io_channel_read_line (channel, &line, NULL, &termloc, NULL); g_return_val_if_fail(status == G_IO_STATUS_NORMAL, FALSE); line[termloc] = '\0'; g_print("DBus daemon: %s\n", line); if (service->priv->first_time) { service->priv->first_time = FALSE; g_setenv("DBUS_STARTER_ADDRESS", line, TRUE); switch (service->priv->bus_type) { case DBUS_TEST_SERVICE_BUS_SESSION: g_setenv("DBUS_SESSION_BUS_ADDRESS", line, TRUE); g_setenv("DBUS_STARTER_BUS_TYPE", "session", TRUE); break; case DBUS_TEST_SERVICE_BUS_SYSTEM: g_setenv("DBUS_SYSTEM_BUS_ADDRESS", line, TRUE); g_setenv("DBUS_STARTER_BUS_TYPE", "system", TRUE); break; case DBUS_TEST_SERVICE_BUS_BOTH: g_setenv("DBUS_SESSION_BUS_ADDRESS", line, TRUE); g_setenv("DBUS_SYSTEM_BUS_ADDRESS", line, TRUE); g_setenv("DBUS_STARTER_BUS_TYPE", "session", TRUE); break; } if (service->priv->state == STATE_DAEMON_STARTING) { g_main_loop_quit(service->priv->mainloop); } } g_free(line); return TRUE; } static void dbus_watcher (GPid pid, G_GNUC_UNUSED gint status, gpointer data) { DbusTestService * service = DBUS_TEST_SERVICE(data); g_critical("DBus Daemon exited abruptly!"); service->priv->daemon_crashed = TRUE; g_main_loop_quit(DBUS_TEST_SERVICE(data)->priv->mainloop); if (pid != 0) { g_spawn_close_pid(pid); } return; } static void dbus_child_setup () { setpgrp(); } static void start_daemon (DbusTestService * service) { if (service->priv->dbus != 0) { return; } service->priv->state = STATE_DAEMON_STARTING; gint dbus_stdout = 0; GError * error = NULL; gchar * blank[1] = {NULL}; gchar * current_dir = g_get_current_dir(); gchar * dbus_startup[] = {service->priv->dbus_daemon, "--config-file", service->priv->dbus_configfile, "--print-address", NULL}; g_spawn_async_with_pipes(current_dir, dbus_startup, /* argv */ service->priv->keep_env ? NULL : blank, /* envp */ G_SPAWN_SEARCH_PATH | G_SPAWN_DO_NOT_REAP_CHILD, /* flags */ (GSpawnChildSetupFunc) dbus_child_setup, /* child setup func */ NULL, /* child setup data */ &service->priv->dbus, /* PID */ NULL, /* stdin */ &dbus_stdout, /* stdout */ NULL, /* stderr */ &error); /* error */ g_free (current_dir); if (error != NULL) { g_critical("Unable to start dbus daemon: %s", error->message); g_error_free(error); service->priv->daemon_crashed = TRUE; return; } dbus_test_watchdog_add_pid(service->priv->watchdog, service->priv->dbus); service->priv->dbus_watch = g_child_watch_add(service->priv->dbus, dbus_watcher, service); service->priv->dbus_io = g_io_channel_unix_new(dbus_stdout); service->priv->dbus_io_watch = g_io_add_watch(service->priv->dbus_io, G_IO_IN | G_IO_HUP | G_IO_ERR, /* conditions */ dbus_writes, /* func */ service); /* func data */ g_main_loop_run(service->priv->mainloop); /* we should have a usable connection now, let's check */ const gchar * bus_address = NULL; if (service->priv->bus_type == DBUS_TEST_SERVICE_BUS_SYSTEM) { bus_address = g_getenv("DBUS_SYSTEM_BUS_ADDRESS"); } else { bus_address = g_getenv("DBUS_SESSION_BUS_ADDRESS"); } g_return_if_fail(bus_address != NULL); gchar **tokens = g_strsplit (bus_address, ",", 0); guint i; gboolean is_valid = FALSE; for (i = 0; i < g_strv_length (tokens); i++) { if (strlen (tokens[i]) && g_dbus_is_supported_address (tokens[i], NULL)) { is_valid = TRUE; break; } } g_strfreev(tokens); if (!is_valid) { service->priv->state = STATE_DAEMON_FAILED; g_critical ("DBus daemon failed: Bus address is not supported"); g_error_free (error); return; } service->priv->state = STATE_DAEMON_STARTED; return; } void dbus_test_service_start_tasks (DbusTestService * service) { g_return_if_fail(DBUS_TEST_SERVICE(service)); g_return_if_fail(all_tasks(service, all_tasks_bus_match, NULL)); start_daemon(service); g_return_if_fail(g_getenv("DBUS_SESSION_BUS_ADDRESS") != NULL || g_getenv("DBUS_SYSTEM_BUS_ADDRESS") != NULL); g_return_if_fail(service->priv->state != STATE_DAEMON_FAILED); if (all_tasks(service, all_tasks_started_helper, NULL)) { /* If we have all started we can mark it as such as long as we understand where we could hit this case */ if (service->priv->state == STATE_INIT || service->priv->state == STATE_DAEMON_STARTED) { service->priv->state = STATE_STARTED; } return; } normalize_name_lengths(service); g_queue_foreach(&service->priv->tasks_first, task_starter, NULL); if (!g_queue_is_empty(&service->priv->tasks_first)) { g_usleep(100000); } g_queue_foreach(&service->priv->tasks_normal, task_starter, NULL); if (!g_queue_is_empty(&service->priv->tasks_last)) { g_usleep(100000); } g_queue_foreach(&service->priv->tasks_last, task_starter, NULL); if (!all_tasks(service, all_tasks_started_helper, NULL)) { service->priv->state = STATE_STARTING; g_main_loop_run(service->priv->mainloop); /* This should never happen, but let's be sure */ g_return_if_fail(all_tasks(service, all_tasks_started_helper, NULL)); } service->priv->state = STATE_STARTED; return; } static gboolean all_tasks_passed_helper (G_GNUC_UNUSED DbusTestService * service, DbusTestTask * task, G_GNUC_UNUSED gpointer user_data) { return dbus_test_task_passed(task); } static int get_status (DbusTestService * service) { if (service->priv->daemon_crashed || service->priv->state == STATE_DAEMON_FAILED) { return -1; } if (all_tasks(service, all_tasks_passed_helper, NULL)) { return 0; } else { return -1; } } int dbus_test_service_run (DbusTestService * service) { g_return_val_if_fail(DBUS_TEST_SERVICE(service), -1); dbus_test_service_start_tasks(service); g_return_val_if_fail(service->priv->state == STATE_STARTED, get_status(service)); if (all_tasks(service, all_tasks_finished_helper, NULL)) { return get_status(service); } service->priv->state = STATE_RUNNING; g_main_loop_run(service->priv->mainloop); /* This should never happen, but let's be sure */ g_return_val_if_fail(all_tasks(service, all_tasks_finished_helper, NULL), -1); service->priv->state = STATE_FINISHED; return get_status(service); } static void task_state_changed (G_GNUC_UNUSED DbusTestTask * task, G_GNUC_UNUSED DbusTestTaskState state, gpointer user_data) { g_return_if_fail(DBUS_TEST_IS_SERVICE(user_data)); DbusTestService * service = DBUS_TEST_SERVICE(user_data); if (service->priv->state == STATE_STARTING && all_tasks(service, all_tasks_started_helper, NULL)) { g_main_loop_quit(service->priv->mainloop); return; } if (service->priv->state == STATE_RUNNING && all_tasks(service, all_tasks_finished_helper, NULL)) { g_main_loop_quit(service->priv->mainloop); return; } return; } void dbus_test_service_add_task (DbusTestService * service, DbusTestTask * task) { return dbus_test_service_add_task_with_priority(service, task, DBUS_TEST_SERVICE_PRIORITY_NORMAL); } void dbus_test_service_add_task_with_priority (DbusTestService * service, DbusTestTask * task, DbusTestServicePriority prio) { g_return_if_fail(DBUS_TEST_IS_SERVICE(service)); g_return_if_fail(DBUS_TEST_IS_TASK(task)); /* Check to ensure that the task and the service match in thier goals for busness. Fail early. */ g_return_if_fail(all_tasks_bus_match(service, task, NULL)); GQueue * queue = NULL; switch (prio) { case DBUS_TEST_SERVICE_PRIORITY_FIRST: queue = &service->priv->tasks_first; break; case DBUS_TEST_SERVICE_PRIORITY_NORMAL: queue = &service->priv->tasks_normal; break; case DBUS_TEST_SERVICE_PRIORITY_LAST: queue = &service->priv->tasks_last; break; default: g_assert_not_reached(); break; } g_queue_push_tail(queue, g_object_ref(task)); gulong connect = g_signal_connect(G_OBJECT(task), DBUS_TEST_TASK_SIGNAL_STATE_CHANGED, G_CALLBACK(task_state_changed), service); g_object_set_data(G_OBJECT(task), SERVICE_CHANGE_HANDLER, GUINT_TO_POINTER(connect)); return; } /** * @service: A #DbusTestService * @task: Task to remove * * Removes a task from those managed by the service, it won't * be checked for status or managed anymore by the service. * * Return Value: Whether the task was found and removed, FALSE if not found */ gboolean dbus_test_service_remove_task (DbusTestService * service, DbusTestTask * task) { g_return_val_if_fail(DBUS_TEST_IS_SERVICE(service), FALSE); g_return_val_if_fail(DBUS_TEST_IS_TASK(task), FALSE); guint count = 0; count += g_queue_remove_all(&service->priv->tasks_first, task); count += g_queue_remove_all(&service->priv->tasks_normal, task); count += g_queue_remove_all(&service->priv->tasks_last, task); /* Checking the count here so that we can generate a warning. Guessing that this actually never happens, but it's easy to check */ if (count > 1) { g_warning("Task '%s' was added to the service %d times!", dbus_test_task_get_name(task), count); } /* We're going to disconnect here even if count is zero because, well, it shouldn't hurt in that case and might be good for us. */ g_signal_handlers_disconnect_by_data(task, service); /* If we've added it multiple times, we made multiple references, fix it. */ guint i; for (i = 0; i < count; i++) { g_object_unref(task); } return count > 0; } void dbus_test_service_set_daemon (DbusTestService * service, const gchar * daemon) { g_return_if_fail(DBUS_TEST_IS_SERVICE(service)); g_free(service->priv->dbus_daemon); service->priv->dbus_daemon = g_strdup(daemon); return; } void dbus_test_service_set_conf_file (DbusTestService * service, const gchar * conffile) { g_return_if_fail(DBUS_TEST_IS_SERVICE(service)); g_free(service->priv->dbus_configfile); service->priv->dbus_configfile = g_strdup(conffile); return; } void dbus_test_service_set_keep_environment (DbusTestService * service, gboolean keep_env) { g_return_if_fail(DBUS_TEST_IS_SERVICE(service)); service->priv->keep_env = keep_env; } void dbus_test_service_stop (DbusTestService * service) { g_return_if_fail(DBUS_TEST_IS_SERVICE(service)); g_main_loop_quit(service->priv->mainloop); return; } void dbus_test_service_set_bus (DbusTestService * service, DbusTestServiceBus bus) { g_return_if_fail(DBUS_TEST_IS_SERVICE(service)); g_return_if_fail(service->priv->dbus == 0); /* we can't change after we're running */ if (bus == DBUS_TEST_SERVICE_BUS_BOTH) { g_warning("Setting bus to BOTH, which is typically only used as a default value."); } service->priv->bus_type = bus; g_warn_if_fail(all_tasks(service, all_tasks_bus_match, NULL)); if (bus == DBUS_TEST_SERVICE_BUS_SYSTEM) { g_free(service->priv->dbus_configfile); service->priv->dbus_configfile = g_strdup(DEFAULT_SYSTEM_CONF); } else { /* BOTH and SESSION get the session config — for backwards compatibility there */ g_free(service->priv->dbus_configfile); service->priv->dbus_configfile = g_strdup(DEFAULT_SESSION_CONF); } } ./data/0000755000004100000410000000000012763551700012162 5ustar www-datawww-data./data/system.conf0000644000004100000410000000315412763551700014360 0ustar www-datawww-data system unix:tmpdir=/tmp 60000 1000000000 1000000000 1000000000 120000 240000 100000 10000 100000 10000 50000 50000 50000 300000 ./data/Makefile.am0000644000004100000410000000020212763551700014210 0ustar www-datawww-data sessionconfdir = $(datadir)/dbus-test-runner/ sessionconf_DATA = session.conf system.conf EXTRA_DIST = session.conf system.conf ./data/session.conf0000644000004100000410000000315512763551700014520 0ustar www-datawww-data session unix:tmpdir=/tmp 60000 1000000000 1000000000 1000000000 120000 240000 100000 10000 100000 10000 50000 50000 50000 300000 ./MERGE-REVIEW0000644000004100000410000000102012763551700013023 0ustar www-datawww-data This documents the expections that the project has on what both submitters and reviewers should ensure that they've done for a merge into the project. == Submitter Responsibilities == * Ensure the project compiles and the test suite executes without error * Ensure that non-obvious code has comments explaining it == Reviewer Responsibilities == * Did the Jenkins build compile? Pass? Run unit tests successfully? * Are there appropriate tests to cover any new functionality? * Run all the appropriate manual tests ./configure.ac0000644000004100000410000000412212763551700013536 0ustar www-datawww-data AC_INIT(dbus-test-runner, 15.04.0, ted@canonical.com) AC_COPYRIGHT([Copyright 2009-2013 Canonical]) AC_PREREQ(2.53) AM_CONFIG_HEADER(config.h) AM_INIT_AUTOMAKE(dbus-test-runner, 15.04.0) AM_MAINTAINER_MODE IT_PROG_INTLTOOL([0.35.0]) AC_ISC_POSIX AC_PROG_CC AM_PROG_CC_C_O AC_STDC_HEADERS AC_PROG_LIBTOOL AC_SUBST(VERSION) AC_CONFIG_MACRO_DIR([m4]) m4_ifdef([AM_SILENT_RULES],[AM_SILENT_RULES([yes])]) ########################### # Dependencies ########################### GLIB_REQUIRED_VERSION=2.34 DBUS_REQUIRED_VERSION=0.76 GIO_REQUIRED_VERSION=2.30 PKG_CHECK_MODULES(DBUS_TEST_RUNNER, glib-2.0 >= $GLIB_REQUIRED_VERSION gio-2.0 >= $GIO_REQUIRED_VERSION gio-unix-2.0 >= $GIO_REQUIRED_VERSION dbus-glib-1 >= $DBUS_REQUIRED_VERSION) AC_SUBST(DBUS_TEST_RUNNER_CFLAGS) AC_SUBST(DBUS_TEST_RUNNER_LIBS) ########################### # Internationalization ########################### GETTEXT_PACKAGE=dbus-test-runner AC_SUBST(GETTEXT_PACKAGE) AC_DEFINE_UNQUOTED(GETTEXT_PACKAGE, "$GETTEXT_PACKAGE", [Name of the default gettext domain]) AM_GLIB_GNU_GETTEXT ########################### # gcov coverage reporting ########################### m4_include([m4/gcov.m4]) AC_TDD_GCOV AM_CONDITIONAL([HAVE_GCOV], [test "x$ac_cv_check_gcov" = xyes]) AM_CONDITIONAL([HAVE_LCOV], [test "x$ac_cv_check_lcov" = xyes]) AM_CONDITIONAL([HAVE_GCOVR], [test "x$ac_cv_check_gcovr" = xyes]) AC_SUBST(COVERAGE_CFLAGS) AC_SUBST(COVERAGE_CXXFLAGS) AC_SUBST(COVERAGE_LDFLAGS) ########################### # Enable bustle tests ########################### AC_CHECK_PROG([have_bustle], [bustle], [yes],,,) AM_CONDITIONAL([TEST_BUSTLE], [test "x$ac_cv_prog_have_bustle" = xyes]) ########################### # Files ########################### AC_OUTPUT([ Makefile po/Makefile.in libdbustest/Makefile src/Makefile data/Makefile tests/Makefile ]) ########################### # Results ########################### AC_MSG_NOTICE([ dbus-test-runner Configuration: Prefix: $prefix Coverage reporting: $use_gcov ]) ./NEWS0000644000004100000410000000000012763551700011736 0ustar www-datawww-data./build.sh0000755000004100000410000000016612763551700012712 0ustar www-datawww-data#!/bin/sh gcc -o dbus-test-runner `pkg-config --cflags --libs glib-2.0 gobject-2.0` dbus-test-runner.c -Wall -Werror ./ChangeLog0000644000004100000410000000000012763551700013011 0ustar www-datawww-data