From f599c1b1f4b7bc40d71b36409826dcab47e4b7af Mon Sep 17 00:00:00 2001 From: Charles Kerr Date: Tue, 14 Oct 2014 14:09:32 -0500 Subject: move the mock battery from GSettings to DBus --- src/CMakeLists.txt | 5 + src/main.c | 75 ++--------- src/testing.c | 364 +++++++++++++++++++++++++++++++++++++++++++++++++++++ src/testing.h | 66 ++++++++++ tests/manual | 34 +++-- 5 files changed, 469 insertions(+), 75 deletions(-) create mode 100644 src/testing.c create mode 100644 src/testing.h diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 00b0ee2..6f4bfaf 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -11,6 +11,7 @@ set(SERVICE_MANUAL_SOURCES device-provider.c device.c notifier.c + testing.c service.c) # generated sources @@ -20,6 +21,10 @@ add_gdbus_codegen_with_namespace(SERVICE_GENERATED_SOURCES dbus-battery com.canonical.indicator.power Dbus ${CMAKE_SOURCE_DIR}/data/com.canonical.indicator.power.Battery.xml) +add_gdbus_codegen_with_namespace(SERVICE_GENERATED_SOURCES dbus-testing + com.canonical.indicator.power + Dbus + ${CMAKE_SOURCE_DIR}/data/com.canonical.indicator.power.Testing.xml) # add the bin dir to our include path so the code can find the generated header files include_directories(${CMAKE_CURRENT_BINARY_DIR}) diff --git a/src/main.c b/src/main.c index 112c31e..eaa4070 100644 --- a/src/main.c +++ b/src/main.c @@ -18,67 +18,13 @@ */ #include -#include /* exit() */ +#include #include -#include #include "device.h" -#include "device-provider-mock.h" -#include "device-provider-upower.h" #include "service.h" - -/*** -**** MOCK -***/ - -static IndicatorPowerDevice* -get_mock_battery(GSettings * settings) -{ - const double percent = g_settings_get_int(settings, "mock-battery-level"); - - const UpDeviceState state = g_settings_get_boolean(settings, "mock-battery-charging") - ? UP_DEVICE_STATE_CHARGING - : UP_DEVICE_STATE_DISCHARGING; - - const int seconds_left = g_settings_get_int(settings, "mock-battery-minutes-left") * 60; - - return indicator_power_device_new ("/some/path", - UP_DEVICE_KIND_BATTERY, - percent, - state, - seconds_left); -} - -static IndicatorPowerDeviceProvider* -get_device_provider(GSettings * settings) -{ - IndicatorPowerDeviceProvider * provider = NULL; - - if (g_settings_get_boolean(settings, "mock-battery-enabled")) - { - IndicatorPowerDevice * battery = get_mock_battery(settings); - provider = indicator_power_device_provider_mock_new (); - indicator_power_device_provider_add_device (INDICATOR_POWER_DEVICE_PROVIDER_MOCK(provider), battery); - g_object_unref (battery); - } - else - { - provider = indicator_power_device_provider_upower_new (); - } - - return provider; -} - -static void -on_mock_settings_changed(GSettings* settings, - gchar * key G_GNUC_UNUSED, - gpointer service) -{ - IndicatorPowerDeviceProvider* provider = get_device_provider(settings); - indicator_power_service_set_device_provider (INDICATOR_POWER_SERVICE(service), provider); - g_object_unref(provider); -} +#include "testing.h" /*** **** @@ -94,25 +40,18 @@ on_name_lost (gpointer instance G_GNUC_UNUSED, gpointer loop) int main (int argc G_GNUC_UNUSED, char ** argv G_GNUC_UNUSED) { - GSettings * settings; - GMainLoop * loop; IndicatorPowerService * service; + IndicatorPowerTesting * testing; + GMainLoop * loop; /* boilerplate i18n */ setlocale (LC_ALL, ""); bindtextdomain (GETTEXT_PACKAGE, GNOMELOCALEDIR); textdomain (GETTEXT_PACKAGE); - /* mock settings */ - service = indicator_power_service_new (NULL); - settings = g_settings_new ("com.canonical.indicator.power"); - g_signal_connect(settings, "changed::mock-battery-enabled", G_CALLBACK(on_mock_settings_changed), service); - g_signal_connect(settings, "changed::mock-battery-level", G_CALLBACK(on_mock_settings_changed), service); - g_signal_connect(settings, "changed::mock-battery-charging", G_CALLBACK(on_mock_settings_changed), service); - g_signal_connect(settings, "changed::mock-battery-minutes-left", G_CALLBACK(on_mock_settings_changed), service); - on_mock_settings_changed(settings, NULL, service); - /* run */ + service = indicator_power_service_new (NULL); + testing = indicator_power_testing_new (service); loop = g_main_loop_new (NULL, FALSE); g_signal_connect (service, INDICATOR_POWER_SERVICE_SIGNAL_NAME_LOST, G_CALLBACK(on_name_lost), loop); @@ -121,6 +60,6 @@ main (int argc G_GNUC_UNUSED, char ** argv G_GNUC_UNUSED) /* cleanup */ g_main_loop_unref (loop); g_clear_object (&service); - g_clear_object (&settings); + g_clear_object (&testing); return 0; } diff --git a/src/testing.c b/src/testing.c new file mode 100644 index 0000000..dadf942 --- /dev/null +++ b/src/testing.c @@ -0,0 +1,364 @@ +/* + * Copyright 2014 Canonical Ltd. + * + * 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 . + * + * Authors: + * Charles Kerr + */ + +#include "dbus-shared.h" +#include "device-provider-mock.h" +#include "device-provider-upower.h" +#include "dbus-testing.h" +#include "service.h" +#include "testing.h" + +#include + +/** +*** GObject Properties +**/ + +enum +{ + PROP_0, + PROP_BUS, + PROP_SERVICE, + LAST_PROP +}; + +static GParamSpec * properties[LAST_PROP]; + +/** +*** +**/ + +typedef struct +{ + GDBusConnection * bus; + DbusTesting * skeleton; + IndicatorPowerService * service; + IndicatorPowerDevice * battery_mock; + gpointer provider_mock; + gpointer provider_upower; +} +IndicatorPowerTestingPrivate; + +typedef IndicatorPowerTestingPrivate priv_t; + +G_DEFINE_TYPE_WITH_PRIVATE(IndicatorPowerTesting, + indicator_power_testing, + G_TYPE_OBJECT) + +#define get_priv(o) ((priv_t*)indicator_power_testing_get_instance_private(o)) + +/*** +**** +***/ + +static void +update_device_provider (IndicatorPowerTesting * self) +{ + priv_t * const p = get_priv(self); + IndicatorPowerDeviceProvider * device_provider; + + device_provider = dbus_testing_get_mock_battery_enabled(p->skeleton) + ? p->provider_mock + : p->provider_upower; + indicator_power_service_set_device_provider(p->service, device_provider); +} + +static void +on_mock_battery_enabled_changed(DbusTesting * skeleton G_GNUC_UNUSED, + GParamSpec * pspec G_GNUC_UNUSED, + IndicatorPowerTesting * self) +{ + update_device_provider (self); +} + +static void +on_mock_battery_level_changed(DbusTesting * skeleton, + GParamSpec * pspec G_GNUC_UNUSED, + IndicatorPowerTesting * self) +{ + g_object_set(get_priv(self)->battery_mock, + INDICATOR_POWER_DEVICE_PERCENTAGE, (gdouble)dbus_testing_get_mock_battery_level(skeleton), + NULL); +} + +static void +on_mock_battery_state_changed(DbusTesting * skeleton, + GParamSpec * pspec G_GNUC_UNUSED, + IndicatorPowerTesting * self) +{ + const gchar* state_str = dbus_testing_get_mock_battery_state(skeleton); + UpDeviceState state; + + if (!g_strcmp0(state_str, "charging")) + { + state = UP_DEVICE_STATE_CHARGING; + } + else if (!g_strcmp0(state_str, "discharging")) + { + state = UP_DEVICE_STATE_DISCHARGING; + } + else + { + g_warning("%s unsupported state: '%s'", G_STRLOC, state_str); + state = UP_DEVICE_STATE_UNKNOWN; + } + + g_object_set(get_priv(self)->battery_mock, + INDICATOR_POWER_DEVICE_STATE, (gint)state, + NULL); +} + +static void +on_mock_battery_minutes_left_changed(DbusTesting * skeleton, + GParamSpec * pspec G_GNUC_UNUSED, + IndicatorPowerTesting * self) +{ + g_object_set(get_priv(self)->battery_mock, + INDICATOR_POWER_DEVICE_TIME, (guint64)dbus_testing_get_mock_battery_minutes_left(skeleton), + NULL); +} + +static void +on_bus_changed(IndicatorPowerService * service, + GParamSpec * spec G_GNUC_UNUSED, + IndicatorPowerTesting * self) +{ + GObject * bus = NULL; + g_object_get(service, "bus", &bus, NULL); + indicator_power_testing_set_bus(self, G_DBUS_CONNECTION(bus)); + g_clear_object(&bus); +} + +/*** +**** GObject virtual functions +***/ + +static void +my_get_property(GObject * o, + guint property_id, + GValue * value, + GParamSpec * pspec) +{ + IndicatorPowerTesting * const self = INDICATOR_POWER_TESTING (o); + priv_t * const p = get_priv(self); + + switch (property_id) + { + case PROP_BUS: + g_value_set_object(value, p->bus); + break; + + case PROP_SERVICE: + g_value_set_object(value, p->service); + break; + + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID(o, property_id, pspec); + } +} + +static void +my_set_property(GObject * o, + guint property_id, + const GValue * value, + GParamSpec * pspec) +{ + IndicatorPowerTesting * const self = INDICATOR_POWER_TESTING (o); + priv_t * const p = get_priv(self); + + switch (property_id) + { + case PROP_BUS: + indicator_power_testing_set_bus(self, G_DBUS_CONNECTION(g_value_get_object(value))); + break; + + case PROP_SERVICE: + g_assert(p->service == NULL); /* G_PARAM_CONSTRUCT_ONLY */ + p->service = g_value_dup_object(value); + break; + + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID(o, property_id, pspec); + } +} + +static void +my_dispose(GObject * o) +{ + IndicatorPowerTesting * const self = INDICATOR_POWER_TESTING(o); + priv_t * const p = get_priv (self); + + indicator_power_testing_set_bus(self, NULL); + g_clear_object(&p->skeleton); + g_clear_object(&p->provider_upower); + g_clear_object(&p->provider_mock); + g_clear_object(&p->battery_mock); + g_clear_object(&p->service); + + G_OBJECT_CLASS (indicator_power_testing_parent_class)->dispose(o); +} + +static void +my_finalize (GObject * o G_GNUC_UNUSED) +{ +} + +static void +my_constructed (GObject * o) +{ + IndicatorPowerTesting * const self = INDICATOR_POWER_TESTING(o); + priv_t * const p = get_priv (self); + + g_assert(p->service != NULL); /* G_PARAM_CONSTRUCT_ONLY */ + g_signal_connect(p->service, "notify::bus", G_CALLBACK(on_bus_changed), o); + on_bus_changed(p->service, NULL, self); + update_device_provider(self); +} + + +/*** +**** Instantiation +***/ + +static void +indicator_power_testing_init (IndicatorPowerTesting * self) +{ + priv_t * const p = get_priv (self); + + /* DBus Skeleton */ + + p->skeleton = dbus_testing_skeleton_new(); + dbus_testing_set_mock_battery_level(p->skeleton, 50u); + dbus_testing_set_mock_battery_state(p->skeleton, "discharging"); + dbus_testing_set_mock_battery_enabled(p->skeleton, FALSE); + dbus_testing_set_mock_battery_minutes_left(p->skeleton, 30); + + g_signal_connect(p->skeleton, "notify::mock-battery-enabled", + G_CALLBACK(on_mock_battery_enabled_changed), self); + g_signal_connect(p->skeleton, "notify::mock-battery-level", + G_CALLBACK(on_mock_battery_level_changed), self); + g_signal_connect(p->skeleton, "notify::mock-battery-state", + G_CALLBACK(on_mock_battery_state_changed), self); + g_signal_connect(p->skeleton, "notify::mock-battery-minutes-left", + G_CALLBACK(on_mock_battery_minutes_left_changed), self); + + /* Mock Battery */ + + p->battery_mock = indicator_power_device_new("/some/path", + UP_DEVICE_KIND_BATTERY, + 50.0, + UP_DEVICE_STATE_DISCHARGING, + 60*30); + + + /* Mock Provider */ + + p->provider_mock = indicator_power_device_provider_mock_new(); + + indicator_power_device_provider_add_device(INDICATOR_POWER_DEVICE_PROVIDER_MOCK(p->provider_mock), + p->battery_mock); + + /* UPower Provider */ + + p->provider_upower = indicator_power_device_provider_upower_new(); +} + +static void +indicator_power_testing_class_init (IndicatorPowerTestingClass * klass) +{ + GObjectClass * object_class = G_OBJECT_CLASS (klass); + + object_class->dispose = my_dispose; + object_class->finalize = my_finalize; + object_class->constructed = my_constructed; + object_class->get_property = my_get_property; + object_class->set_property = my_set_property; + + properties[PROP_BUS] = g_param_spec_object ( + "bus", + "Bus", + "The GDBusConnection on which to export menus", + G_TYPE_OBJECT, + G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS); + + properties[PROP_SERVICE] = g_param_spec_object ( + "service", + "Servie", + "The IndicatorPower Service", + G_TYPE_OBJECT, + G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS | G_PARAM_CONSTRUCT_ONLY); + + g_object_class_install_properties (object_class, LAST_PROP, properties); +} + +/*** +**** Public API +***/ + +IndicatorPowerTesting * +indicator_power_testing_new (IndicatorPowerService * service) +{ + GObject * o = g_object_new (INDICATOR_TYPE_POWER_TESTING, "service", service, NULL); + + return INDICATOR_POWER_TESTING (o); +} + +void +indicator_power_testing_set_bus(IndicatorPowerTesting * self, + GDBusConnection * bus) +{ + priv_t * p; + GDBusInterfaceSkeleton * skel; + + g_return_if_fail(INDICATOR_IS_POWER_TESTING(self)); + g_return_if_fail((bus == NULL) || G_IS_DBUS_CONNECTION(bus)); + + p = get_priv (self); + + if (p->bus == bus) + return; + + skel = G_DBUS_INTERFACE_SKELETON(p->skeleton); + + if (p->bus != NULL) + { + if (skel != NULL) + g_dbus_interface_skeleton_unexport (skel); + + g_clear_object (&p->bus); + } + + if (bus != NULL) + { + GError * error; + + p->bus = g_object_ref (bus); + + error = NULL; + if (!g_dbus_interface_skeleton_export(skel, + bus, + BUS_PATH"/Testing", + &error)) + { + g_warning ("Unable to export Testing properties: %s", error->message); + g_error_free (error); + } + } +} + diff --git a/src/testing.h b/src/testing.h new file mode 100644 index 0000000..1370170 --- /dev/null +++ b/src/testing.h @@ -0,0 +1,66 @@ +/* + * Copyright 2014 Canonical Ltd. + * + * 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 . + * + * Authors: + * Charles Kerr + */ + +#ifndef __INDICATOR_POWER_TESTING_H__ +#define __INDICATOR_POWER_TESTING_H__ + +#include + +#include "service.h" + +G_BEGIN_DECLS + +/* standard GObject macros */ +#define INDICATOR_POWER_TESTING(o) (G_TYPE_CHECK_INSTANCE_CAST ((o), INDICATOR_TYPE_POWER_TESTING, IndicatorPowerTesting)) +#define INDICATOR_TYPE_POWER_TESTING (indicator_power_testing_get_type()) +#define INDICATOR_IS_POWER_TESTING(o) (G_TYPE_CHECK_INSTANCE_TYPE ((o), INDICATOR_TYPE_POWER_TESTING)) +#define INDICATOR_POWER_TESTING_GET_CLASS(o) (G_TYPE_INSTANCE_GET_CLASS ((o), INDICATOR_TYPE_POWER_TESTING, IndicatorPowerTestingClass)) + +typedef struct _IndicatorPowerTesting IndicatorPowerTesting; +typedef struct _IndicatorPowerTestingClass IndicatorPowerTestingClass; + +/** + * The Indicator Power Testing. + */ +struct _IndicatorPowerTesting +{ + /*< private >*/ + GObject parent; +}; + +struct _IndicatorPowerTestingClass +{ + GObjectClass parent_class; +}; + +/*** +**** +***/ + +GType indicator_power_testing_get_type (void); + +IndicatorPowerTesting * indicator_power_testing_new (IndicatorPowerService * service); + +void indicator_power_testing_set_bus (IndicatorPowerTesting * self, + GDBusConnection * connection); + + +G_END_DECLS + +#endif /* __INDICATOR_POWER_TESTING_H__ */ diff --git a/tests/manual b/tests/manual index a7351bc..1e6febd 100644 --- a/tests/manual +++ b/tests/manual @@ -1,17 +1,37 @@ Notes on Battery Testing -Mock battery settings are available for testing purposes. +Mock battery propreties are available for testing purposes. -The indicator's schema name is "com.canonical.indicator.power" and there are four keys: "mock-battery-enabled" (a boolean), "mock-battery-level" (charger percent, an integer from 0-100), "mock-battery-charging" (a boolean of whether the mock battery is charging or discharging), and "mock-battery-minutes-left" (minutes remaining to charge/discharge). +The testing properties are DBus properties published on busname "com.canonical.indicator.power", object path "/com/canonical/indicator/power/Testing", and interface "com.canonical.indicator.power.Testing". The four properties are "MockBatteryEnabled" (boolean, default false), "MockBatteryLevel" (uint32 [0-100], default 50), "MockBatteryState" (string, default 'discharging'), "MockBatteryMinutesLeft" (minutes remaining to charge/discharge, uint32, default 30). Example use: -$ gsettings reset-recursively com.canonical.indicator.power # reset settings to the default state -$ gsettings list-recursively com.canonical.indicator.power | grep mock # show the current mock settings -$ gsettings set com.canonical.indicator.power mock-battery-enabled true # use the mock battery -$ gsettings set com.canonical.indicator.power mock-battery-level 10 # set the mock battery's charge to 10% -$ gsettings set com.canonical.indicator.power mock-battery-enabled false # go back to production settings +Show the testing properties: + +$ gdbus call --session --dest "com.canonical.indicator.power" \ + --object-path /com/canonical/indicator/power/Testing \ + --method org.freedesktop.DBus.Properties.GetAll \ + com.canonical.indicator.power.Testing +({'MockBatteryEnabled': , 'MockBatteryLevel': , 'MockBatteryState': <'discharging'>, 'MockBatteryMinutesLeft': },) + +Enable the mock battery: + +$ gdbus call --session --dest "com.canonical.indicator.power" \ + --object-path /com/canonical/indicator/power/Testing \ + --method org.freedesktop.DBus.Properties.Set \ + com.canonical.indicator.power.Testing \ + MockBatteryEnabled \ + "" + +Set the mock battery's charge to 10% + +$ gdbus call --session --dest "com.canonical.indicator.power" \ + --object-path /com/canonical/indicator/power/Testing \ + --method org.freedesktop.DBus.Properties.Set \ + com.canonical.indicator.power.Testing \ + MockBatteryLevel \ + "" Test-case indicator-power/unity7-items-check -- cgit v1.2.3