aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorCharles Kerr <charles.kerr@canonical.com>2012-05-24 09:49:30 -0500
committerCharles Kerr <charles.kerr@canonical.com>2012-05-24 09:49:30 -0500
commit622c18549745d3824713fd9d7a4a0d89b31257a5 (patch)
treec6e1a4deaca2943a43a9ff6143d778e4a8349a1b
parent71a3e5394346f529ae74e7174dd4156c0229d190 (diff)
downloadayatana-indicator-power-622c18549745d3824713fd9d7a4a0d89b31257a5.tar.gz
ayatana-indicator-power-622c18549745d3824713fd9d7a4a0d89b31257a5.tar.bz2
ayatana-indicator-power-622c18549745d3824713fd9d7a4a0d89b31257a5.zip
add private container struct IndicatorPowerDevice
-rw-r--r--Makefile.am7
-rw-r--r--configure.ac26
-rw-r--r--m4/gtest.m463
-rw-r--r--src/Makefile.am8
-rw-r--r--src/device.c330
-rw-r--r--src/device.h100
-rw-r--r--tests/Makefile.am38
-rw-r--r--tests/Makefile.am.strings38
-rw-r--r--tests/test-device.cc99
9 files changed, 706 insertions, 3 deletions
diff --git a/Makefile.am b/Makefile.am
index 54ec6a2..00e108d 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -1,5 +1,12 @@
SUBDIRS = po data src
+if BUILD_TESTS
+SUBDIRS += tests
+# build src first
+tests: src
+endif
+
+
############################################################
dist_noinst_SCRIPTS = \
diff --git a/configure.ac b/configure.ac
index 433c7be..876edf7 100644
--- a/configure.ac
+++ b/configure.ac
@@ -11,7 +11,7 @@ AC_CONFIG_SRCDIR([configure.ac])
AC_CONFIG_MACRO_DIR([m4])
AC_CONFIG_AUX_DIR([build-aux])
-AM_INIT_AUTOMAKE([1.11 -Wall foreign subdir-objects dist-xz])
+AM_INIT_AUTOMAKE([1.11 -Wall foreign dist-xz])
AM_MAINTAINER_MODE([enable])
AM_SILENT_RULES([yes])
@@ -19,6 +19,7 @@ AM_SILENT_RULES([yes])
# Check for programs
AC_PROG_CC
AM_PROG_CC_C_O
+AC_PROG_CXX
# Initialize libtool
LT_PREREQ([2.2.6])
@@ -48,6 +49,26 @@ PKG_CHECK_MODULES([GSD],[gnome-settings-daemon >= $GSD_REQUIRED_VERSION])
GLIB_GSETTINGS
###########################
+# Google Test framework
+###########################
+
+AC_ARG_ENABLE([tests],
+ [AS_HELP_STRING([--disable-tests], [Disable test scripts and tools (default=auto)])],
+ [enable_tests=${enableval}],
+ [enable_tests=auto])
+if test "x$enable_tests" != "xno"; then
+ m4_include([m4/gtest.m4])
+ CHECK_GTEST
+ CHECK_XORG_GTEST
+ if test "x$enable_tests" = "xauto"; then
+ enable_tests=${have_gtest}
+ elif test "x$enable_tests" = "xyes" && test "x$have_gtest" != "xyes"; then
+ AC_MSG_ERROR([tests were requested but gtest is not installed.])
+ fi
+fi
+AM_CONDITIONAL([BUILD_TESTS],[test "x$enable_tests" = "xyes"])
+
+###########################
# gcov coverage reporting
###########################
@@ -120,6 +141,7 @@ Makefile
po/Makefile.in
data/Makefile
src/Makefile
+tests/Makefile
])
AC_OUTPUT
@@ -133,5 +155,7 @@ Power Indicator Configuration:
Prefix: $prefix
Local Install: $with_localinstall
+ Unit Tests: $enable_tests
gcov: $use_gcov
+
])
diff --git a/m4/gtest.m4 b/m4/gtest.m4
new file mode 100644
index 0000000..2de334c
--- /dev/null
+++ b/m4/gtest.m4
@@ -0,0 +1,63 @@
+# Copyright (C) 2012 Canonical, Ltd.
+#
+# Permission is hereby granted, free of charge, to any person obtaining a copy
+# of this software and associated documentation files (the "Software"), to deal
+# in the Software without restriction, including without limitation the rights
+# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+# copies of the Software, and to permit persons to whom the Software is
+# furnished to do so, subject to the following conditions:
+#
+# The above copyright notice and this permission notice (including the next
+# paragraph) shall be included in all copies or substantial portions of the
+# Software.
+#
+# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+# SOFTWARE.
+
+# Checks whether the gtest source is available on the system. Allows for
+# adjusting the include and source path. Sets have_gtest=yes if the source is
+# present. Sets GTEST_CPPFLAGS and GTEST_SOURCE to the preprocessor flags and
+# source location respectively.
+AC_DEFUN([CHECK_GTEST],
+[
+ AC_ARG_WITH([gtest-include-path],
+ [AS_HELP_STRING([--with-gtest-include-path],
+ [location of the Google test headers])],
+ [GTEST_CPPFLAGS="-I$withval"])
+
+ AC_ARG_WITH([gtest-source-path],
+ [AS_HELP_STRING([--with-gtest-source-path],
+ [location of the Google test sources, defaults to /usr/src/gtest])],
+ [GTEST_SOURCE="$withval"],
+ [GTEST_SOURCE="/usr/src/gtest"])
+
+ GTEST_CPPFLAGS="$GTEST_CPPFLAGS -I$GTEST_SOURCE"
+
+ AC_LANG_PUSH([C++])
+
+ tmp_CPPFLAGS="$CPPFLAGS"
+ CPPFLAGS="$CPPFLAGS $GTEST_CPPFLAGS"
+
+ AC_CHECK_HEADER([gtest/gtest.h])
+
+ CPPFLAGS="$tmp_CPPFLAGS"
+
+ AC_LANG_POP
+
+ AC_CHECK_FILES([$GTEST_SOURCE/src/gtest-all.cc]
+ [$GTEST_SOURCE/src/gtest_main.cc],
+ [have_gtest_source=yes],
+ [have_gtest_source=no])
+
+ AS_IF([test "x$ac_cv_header_gtest_gtest_h" = xyes -a \
+ "x$have_gtest_source" = xyes],
+ [have_gtest=yes]
+ [AC_SUBST(GTEST_CPPFLAGS)]
+ [AC_SUBST(GTEST_SOURCE)],
+ [have_gtest=no])
+]) # CHECK_GTEST
diff --git a/src/Makefile.am b/src/Makefile.am
index e0211a0..d14c270 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -8,12 +8,16 @@ powerlibdir = $(INDICATORDIR)
powerlib_LTLIBRARIES = libpower.la
libpower_la_SOURCES = \
+ device.c \
indicator-power.c
+noinst_HEADERS = \
+ device.h
+
libpower_la_CFLAGS = \
$(UPOWER_CFLAGS) \
$(INDICATOR_CFLAGS) \
- $(COVERAGE_CFLAGS) \
+ $(COVERAGE_CFLAGS) \
-Wall -Werror \
-DG_LOG_DOMAIN=\"Indicator-Power\"
@@ -22,7 +26,7 @@ libpower_la_LIBADD = \
$(INDICATOR_LIBS)
libpower_la_LDFLAGS = \
- $(COVERAGE_LDFLAGS) \
+ $(COVERAGE_LDFLAGS) \
-module \
-avoid-version
diff --git a/src/device.c b/src/device.c
new file mode 100644
index 0000000..d52ce8a
--- /dev/null
+++ b/src/device.c
@@ -0,0 +1,330 @@
+/*
+
+A simple Device structure used internally by indicator-power
+
+Copyright 2012 Canonical Ltd.
+
+Authors:
+ Charles Kerr <charles.kerr@canonical.com>
+
+This library is free software; you can redistribute it and/or
+modify it under the terms of the GNU General Public License
+version 3.0 as published by the Free Software Foundation.
+
+This library is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License version 3.0 for more details.
+
+You should have received a copy of the GNU General Public
+License along with this library. If not, see
+<http://www.gnu.org/licenses/>.
+*/
+
+#include "device.h"
+
+struct _IndicatorPowerDevicePrivate
+{
+ UpDeviceKind kind;
+ UpDeviceState state;
+ gchar * object_path;
+ gchar * icon;
+ gdouble percentage;
+ time_t time;
+};
+
+#define INDICATOR_POWER_DEVICE_GET_PRIVATE(o) (INDICATOR_POWER_DEVICE(o)->priv)
+
+/* Properties */
+/* Enum for the properties so that they can be quickly found and looked up. */
+enum {
+ PROP_0,
+ PROP_KIND,
+ PROP_STATE,
+ PROP_OBJECT_PATH,
+ PROP_ICON,
+ PROP_PERCENTAGE,
+ PROP_TIME
+};
+
+/* GObject stuff */
+static void indicator_power_device_class_init (IndicatorPowerDeviceClass *klass);
+static void indicator_power_device_init (IndicatorPowerDevice *self);
+static void indicator_power_device_dispose (GObject *object);
+static void indicator_power_device_finalize (GObject *object);
+static void set_property (GObject*, guint prop_id, const GValue*, GParamSpec* );
+static void get_property (GObject*, guint prop_id, GValue*, GParamSpec* );
+
+G_DEFINE_TYPE (IndicatorPowerDevice, indicator_power_device, G_TYPE_OBJECT);
+
+static void
+indicator_power_device_class_init (IndicatorPowerDeviceClass *klass)
+{
+ GParamSpec * pspec;
+ GObjectClass *object_class = G_OBJECT_CLASS (klass);
+
+ g_type_class_add_private (klass, sizeof (IndicatorPowerDevicePrivate));
+
+ object_class->dispose = indicator_power_device_dispose;
+ object_class->finalize = indicator_power_device_finalize;
+ object_class->set_property = set_property;
+ object_class->get_property = get_property;
+
+ pspec = g_param_spec_int (INDICATOR_POWER_DEVICE_KIND, "kind", "The device's UpDeviceKind",
+ UP_DEVICE_KIND_UNKNOWN, UP_DEVICE_KIND_LAST, UP_DEVICE_KIND_UNKNOWN,
+ G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS);
+ g_object_class_install_property (object_class, PROP_KIND, pspec);
+
+ pspec = g_param_spec_int (INDICATOR_POWER_DEVICE_STATE, "state", "The device's UpDeviceState",
+ UP_DEVICE_STATE_UNKNOWN, UP_DEVICE_STATE_LAST, UP_DEVICE_STATE_UNKNOWN,
+ G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS);
+ g_object_class_install_property (object_class, PROP_STATE, pspec);
+
+ pspec = g_param_spec_string (INDICATOR_POWER_DEVICE_OBJECT_PATH, "object path", "The device's DBus object path", NULL,
+ G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS);
+ g_object_class_install_property (object_class, PROP_OBJECT_PATH, pspec);
+
+ pspec = g_param_spec_string (INDICATOR_POWER_DEVICE_ICON, "icon", "The device's icon", NULL,
+ G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS);
+ g_object_class_install_property (object_class, PROP_ICON, pspec);
+
+ pspec = g_param_spec_double (INDICATOR_POWER_DEVICE_PERCENTAGE, "percentage", "percent charged",
+ 0.0, 100.0, 0.0,
+ G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS);
+ g_object_class_install_property (object_class, PROP_PERCENTAGE, pspec);
+
+ pspec = g_param_spec_uint64 (INDICATOR_POWER_DEVICE_TIME, "time", "time left",
+ 0, G_MAXUINT64, 0,
+ G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS);
+ g_object_class_install_property (object_class, PROP_TIME, pspec);
+}
+
+/* Initialize an instance */
+static void
+indicator_power_device_init (IndicatorPowerDevice *self)
+{
+ IndicatorPowerDevicePrivate * priv;
+
+ priv = G_TYPE_INSTANCE_GET_PRIVATE (self,
+ INDICATOR_POWER_DEVICE_TYPE,
+ IndicatorPowerDevicePrivate);
+ priv->kind = UP_DEVICE_KIND_UNKNOWN;
+ priv->state = UP_DEVICE_STATE_UNKNOWN;
+ priv->object_path = NULL;
+ priv->icon = NULL;
+ priv->percentage = 0.0;
+ priv->time = 0;
+
+ self->priv = priv;
+}
+
+static void
+indicator_power_device_dispose (GObject *object)
+{
+ G_OBJECT_CLASS (indicator_power_device_parent_class)->dispose (object);
+}
+
+static void
+indicator_power_device_finalize (GObject *object)
+{
+ IndicatorPowerDevice * self = INDICATOR_POWER_DEVICE(object);
+ IndicatorPowerDevicePrivate * priv = self->priv;
+
+ g_clear_pointer (&priv->object_path, g_free);
+ g_clear_pointer (&priv->icon, g_free);
+}
+
+/***
+****
+***/
+
+static void
+get_property (GObject * o, guint prop_id, GValue * value, GParamSpec * pspec)
+{
+ IndicatorPowerDevice * self = INDICATOR_POWER_DEVICE(o);
+ IndicatorPowerDevicePrivate * priv = self->priv;
+
+ switch (prop_id)
+ {
+ case PROP_KIND:
+ g_return_if_fail (G_VALUE_HOLDS_INT(value));
+ g_value_set_int (value, priv->kind);
+ break;
+
+ case PROP_STATE:
+ g_return_if_fail (G_VALUE_HOLDS_INT(value));
+ g_value_set_int (value, priv->state);
+ break;
+
+ case PROP_OBJECT_PATH:
+ g_return_if_fail (G_VALUE_HOLDS_STRING(value));
+ g_value_set_string (value, priv->object_path);
+ break;
+
+ case PROP_ICON:
+ g_return_if_fail (G_VALUE_HOLDS_STRING(value));
+ g_value_set_string (value, priv->icon);
+ break;
+
+ case PROP_PERCENTAGE:
+ g_return_if_fail (G_VALUE_HOLDS_DOUBLE(value));
+ g_value_set_double (value, priv->percentage);
+ break;
+
+ case PROP_TIME:
+ g_return_if_fail (G_VALUE_HOLDS_UINT64(value));
+ g_value_set_uint64 (value, priv->time);
+ break;
+
+ default:
+ G_OBJECT_WARN_INVALID_PROPERTY_ID (o, prop_id, pspec);
+ break;
+ }
+}
+
+static void
+set_property (GObject * o, guint prop_id, const GValue * value, GParamSpec * pspec)
+{
+ IndicatorPowerDevice * self = INDICATOR_POWER_DEVICE(o);
+ IndicatorPowerDevicePrivate * priv = self->priv;
+
+ switch (prop_id)
+ {
+ case PROP_KIND:
+ g_return_if_fail (G_VALUE_HOLDS_INT(value));
+ priv->kind = g_value_get_int (value);
+ break;
+
+ case PROP_STATE:
+ g_return_if_fail (G_VALUE_HOLDS_INT(value));
+ priv->state = g_value_get_int (value);
+ break;
+
+ case PROP_OBJECT_PATH:
+ g_return_if_fail (G_VALUE_HOLDS_STRING(value));
+ g_free (priv->object_path);
+ priv->object_path = g_value_dup_string (value);
+ break;
+
+ case PROP_ICON:
+ g_return_if_fail (G_VALUE_HOLDS_STRING(value));
+ g_free (priv->icon);
+ priv->icon = g_value_dup_string (value);
+ break;
+
+ case PROP_PERCENTAGE:
+ g_return_if_fail (G_VALUE_HOLDS_DOUBLE(value));
+ priv->percentage = g_value_get_double (value);
+ break;
+
+ case PROP_TIME:
+ g_return_if_fail (G_VALUE_HOLDS_UINT64(value));
+ priv->time = g_value_get_uint64(value);
+ break;
+
+ default:
+ G_OBJECT_WARN_INVALID_PROPERTY_ID (o, prop_id, pspec);
+ break;
+ }
+}
+
+/***
+****
+***/
+
+UpDeviceKind
+indicator_power_device_get_kind (const IndicatorPowerDevice * device)
+{
+ g_return_val_if_fail (INDICATOR_IS_POWER_DEVICE(device), UP_DEVICE_KIND_UNKNOWN);
+
+ return device->priv->kind;
+}
+
+UpDeviceState
+indicator_power_device_get_state (const IndicatorPowerDevice * device)
+{
+ g_return_val_if_fail (INDICATOR_IS_POWER_DEVICE(device), UP_DEVICE_STATE_UNKNOWN);
+
+ return device->priv->state;
+}
+
+const gchar *
+indicator_power_device_get_object_path (const IndicatorPowerDevice * device)
+{
+ g_return_val_if_fail (INDICATOR_IS_POWER_DEVICE(device), UP_DEVICE_KIND_UNKNOWN);
+
+ return device->priv->object_path;
+}
+
+const gchar *
+indicator_power_device_get_icon (const IndicatorPowerDevice * device)
+{
+ g_return_val_if_fail (INDICATOR_IS_POWER_DEVICE(device), UP_DEVICE_KIND_UNKNOWN);
+
+ return device->priv->icon;
+}
+
+gdouble
+indicator_power_device_get_percentage (const IndicatorPowerDevice * device)
+{
+ g_return_val_if_fail (INDICATOR_IS_POWER_DEVICE(device), UP_DEVICE_KIND_UNKNOWN);
+
+ return device->priv->percentage;
+}
+
+time_t
+indicator_power_device_get_time (const IndicatorPowerDevice * device)
+{
+ g_return_val_if_fail (INDICATOR_IS_POWER_DEVICE(device), UP_DEVICE_KIND_UNKNOWN);
+
+ return device->priv->time;
+}
+
+/***
+****
+***/
+
+IndicatorPowerDevice *
+indicator_power_device_new (const gchar * object_path,
+ UpDeviceKind kind,
+ const gchar * icon_path,
+ gdouble percentage,
+ UpDeviceState state,
+ time_t timestamp)
+{
+ GObject * o = g_object_new (INDICATOR_POWER_DEVICE_TYPE,
+ INDICATOR_POWER_DEVICE_KIND, kind,
+ INDICATOR_POWER_DEVICE_STATE, state,
+ INDICATOR_POWER_DEVICE_OBJECT_PATH, object_path,
+ INDICATOR_POWER_DEVICE_ICON, icon_path,
+ INDICATOR_POWER_DEVICE_PERCENTAGE, percentage,
+ INDICATOR_POWER_DEVICE_TIME, (guint64)timestamp,
+ NULL);
+ return INDICATOR_POWER_DEVICE(o);
+}
+
+IndicatorPowerDevice *
+indicator_power_device_new_from_variant (GVariant * v)
+{
+ UpDeviceKind kind = UP_DEVICE_KIND_UNKNOWN;
+ UpDeviceState state = UP_DEVICE_STATE_UNKNOWN;
+ const gchar * icon = NULL;
+ const gchar * object_path = NULL;
+ gdouble percentage = 0;
+ guint64 time = 0;
+
+ g_variant_get (v, "(&su&sdut)",
+ &object_path,
+ &kind,
+ &icon,
+ &percentage,
+ &state,
+ &time);
+
+ return indicator_power_device_new (object_path,
+ kind,
+ icon,
+ percentage,
+ state,
+ time);
+}
diff --git a/src/device.h b/src/device.h
new file mode 100644
index 0000000..e9de044
--- /dev/null
+++ b/src/device.h
@@ -0,0 +1,100 @@
+/*
+
+A simple Device structure used internally by indicator-power
+
+Copyright 2012 Canonical Ltd.
+
+Authors:
+ Charles Kerr <charles.kerr@canonical.com>
+
+This library is free software; you can redistribute it and/or
+modify it under the terms of the GNU General Public License
+version 3.0 as published by the Free Software Foundation.
+
+This library is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License version 3.0 for more details.
+
+You should have received a copy of the GNU General Public
+License along with this library. If not, see
+<http://www.gnu.org/licenses/>.
+*/
+
+#ifndef __INDICATOR_POWER_DEVICE_H__
+#define __INDICATOR_POWER_DEVICE_H__
+
+#include <glib-object.h>
+#include <libupower-glib/upower.h>
+
+G_BEGIN_DECLS
+
+#define INDICATOR_POWER_DEVICE_TYPE (indicator_power_device_get_type ())
+#define INDICATOR_POWER_DEVICE(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), INDICATOR_POWER_DEVICE_TYPE, IndicatorPowerDevice))
+#define INDICATOR_POWER_DEVICE_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), INDICATOR_POWER_DEVICE_TYPE, IndicatorPowerDeviceClass))
+#define INDICATOR_IS_POWER_DEVICE(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), INDICATOR_POWER_DEVICE_TYPE))
+#define INDICATOR_IS_POWER_DEVICE_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), INDICATOR_POWER_DEVICE_TYPE))
+#define INDICATOR_POWER_DEVICE_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), INDICATOR_POWER_DEVICE_TYPE, IndicatorPowerDeviceClass))
+
+typedef struct _IndicatorPowerDevice IndicatorPowerDevice;
+typedef struct _IndicatorPowerDeviceClass IndicatorPowerDeviceClass;
+typedef struct _IndicatorPowerDevicePrivate IndicatorPowerDevicePrivate;
+
+#define INDICATOR_POWER_DEVICE_KIND "indicator-power-device-kind"
+#define INDICATOR_POWER_DEVICE_STATE "indicator-power-device-state"
+#define INDICATOR_POWER_DEVICE_OBJECT_PATH "indicator-power-device-object-path"
+#define INDICATOR_POWER_DEVICE_ICON "indicator-power-device-icon"
+#define INDICATOR_POWER_DEVICE_PERCENTAGE "indicator-power-device-percentage"
+#define INDICATOR_POWER_DEVICE_TIME "indicator-power-device-time"
+
+/**
+ * IndicatorPowerDeviceClass:
+ * @parent_class: #GObjectClass
+ */
+struct _IndicatorPowerDeviceClass
+{
+ GObjectClass parent_class;
+};
+
+/**
+ * IndicatorPowerDevice:
+ * @parent: #GObject
+ * @priv: A cached reference to the private data for the instance.
+*/
+struct _IndicatorPowerDevice
+{
+ GObject parent;
+ IndicatorPowerDevicePrivate * priv;
+};
+
+/***
+****
+***/
+
+GType indicator_power_device_get_type (void);
+
+IndicatorPowerDevice* indicator_power_device_new (const gchar * object_path,
+ UpDeviceKind kind,
+ const gchar * icon,
+ gdouble percentage,
+ UpDeviceState state,
+ time_t time);
+
+/**
+ * Convenience wrapper around indicator_power_device_new()
+ * @variant holds the same args as indicator_power_device_new() in "(susdut)"
+ */
+IndicatorPowerDevice* indicator_power_device_new_from_variant (GVariant * variant);
+
+
+UpDeviceKind indicator_power_device_get_kind (const IndicatorPowerDevice * device);
+UpDeviceState indicator_power_device_get_state (const IndicatorPowerDevice * device);
+const gchar * indicator_power_device_get_object_path (const IndicatorPowerDevice * device);
+const gchar * indicator_power_device_get_icon (const IndicatorPowerDevice * device);
+gdouble indicator_power_device_get_percentage (const IndicatorPowerDevice * device);
+time_t indicator_power_device_get_time (const IndicatorPowerDevice * device);
+
+
+G_END_DECLS
+
+#endif
diff --git a/tests/Makefile.am b/tests/Makefile.am
new file mode 100644
index 0000000..87dd606
--- /dev/null
+++ b/tests/Makefile.am
@@ -0,0 +1,38 @@
+TESTS =
+CLEANFILES =
+check_PROGRAMS =
+
+AM_CPPFLAGS = $(GTEST_CPPFLAGS) -I${top_srcdir}/src -Wall -Werror
+AM_CXXFLAGS = $(GTEST_CXXFLAGS)
+
+###
+###
+###
+
+# stock UMB tests on user-visible strings
+include $(srcdir)/Makefile.am.strings
+
+###
+###
+###
+
+TESTS += test-device
+check_PROGRAMS += test-device
+test_device_SOURCES = test-device.cc
+test_device_LDADD = \
+ $(top_builddir)/src/libpower.la \
+ $(INDICATOR_LIBS) \
+ $(UPOWER_LIBS) \
+ $(COVERAGE_LDFLAGS) \
+ libgtest.a
+
+test_device_CPPFLAGS = \
+ $(AM_CPPFLAGS) \
+ $(UPOWER_CFLAGS) \
+ $(INDICATOR_CFLAGS) \
+ $(COVERAGE_CFLAGS)
+
+check_LIBRARIES = libgtest.a
+nodist_libgtest_a_SOURCES = \
+ $(GTEST_SOURCE)/src/gtest-all.cc \
+ $(GTEST_SOURCE)/src/gtest_main.cc
diff --git a/tests/Makefile.am.strings b/tests/Makefile.am.strings
new file mode 100644
index 0000000..26a23a8
--- /dev/null
+++ b/tests/Makefile.am.strings
@@ -0,0 +1,38 @@
+TESTS += \
+ test-ellipsis \
+ test-space-ellipsis \
+ test-ascii-quotes
+
+#####
+# Tests for there being proper ellipsis instead of three periods in a row
+#####
+test-ellipsis: $(top_srcdir)/po
+ @echo "#!/bin/bash" > $@
+ @echo "(cd $(top_srcdir)/po && make $(GETTEXT_PACKAGE).pot)" >> $@
+ @echo "grep -c -e \"^msgid.*\.\.\.\\\"\" $(top_srcdir)/po/$(GETTEXT_PACKAGE).pot > /dev/null && echo \"Ellipsis found in user visible strings\" >&2 && exit 1" >> $@
+ @echo "exit 0" >> $@
+ @chmod +x $@
+
+#####
+# Tests for there being a space before an ellipsis
+#####
+test-space-ellipsis: $(top_srcdir)/po
+ @echo "#!/bin/bash" > $@
+ @echo "(cd $(top_srcdir)/po && make $(GETTEXT_PACKAGE).pot)" >> $@
+ @echo "grep -c -e \"^msgid.* …\\\"\" $(top_srcdir)/po/$(GETTEXT_PACKAGE).pot > /dev/null && echo \"Space before ellipsis found in user visible strings\" >&2 && exit 1" >> $@
+ @echo "exit 0" >> $@
+ @chmod +x $@
+
+#####
+# Tests for ASCII quote types
+#####
+test-ascii-quotes: $(top_srcdir)/po
+ @echo "#!/bin/bash" > $@
+ @echo "(cd $(top_srcdir)/po && make $(GETTEXT_PACKAGE).pot)" >> $@
+ @echo "grep -c -e \"^msgid \\\".*'.*\\\"\" $(top_srcdir)/po/$(GETTEXT_PACKAGE).pot > /dev/null && echo \"ASCII apostrophy found in user visible strings\" >&2 && exit 1" >> $@
+ @echo "grep -c -e \"^msgid \\\".*\\\".*\\\"\" $(top_srcdir)/po/$(GETTEXT_PACKAGE).pot > /dev/null && echo \"ASCII quote found in user visible strings\" >&2 && exit 1" >> $@
+ @echo "grep -c -e \"^msgid \\\".*\\\`.*\\\"\" $(top_srcdir)/po/$(GETTEXT_PACKAGE).pot > /dev/null && echo \"ASCII backtick found in user visible strings\" >&2 && exit 1" >> $@
+ @echo "exit 0" >> $@
+ @chmod +x $@
+
+CLEANFILES += $(TESTS)
diff --git a/tests/test-device.cc b/tests/test-device.cc
new file mode 100644
index 0000000..02516f4
--- /dev/null
+++ b/tests/test-device.cc
@@ -0,0 +1,99 @@
+/*
+Copyright 2012 Canonical Ltd.
+
+Authors:
+ Charles Kerr <charles.kerr@canonical.com>
+
+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 <http://www.gnu.org/licenses/>.
+*/
+
+#include <gtest/gtest.h>
+#include "device.h"
+
+namespace
+{
+ void ensure_glib_initialized ()
+ {
+ static bool initialized = false;
+
+ if (G_UNLIKELY(!initialized))
+ {
+ initialized = true;
+ g_type_init();
+ }
+ }
+}
+
+/***
+****
+***/
+
+TEST(DeviceTest, GObjectNew)
+{
+ ensure_glib_initialized ();
+
+ GObject * o = G_OBJECT (g_object_new (INDICATOR_POWER_DEVICE_TYPE, NULL));
+ ASSERT_TRUE (o != NULL);
+ ASSERT_TRUE (INDICATOR_IS_POWER_DEVICE(o));
+ g_clear_pointer (&o, g_object_unref);
+}
+
+TEST(DeviceTest, New)
+{
+ ensure_glib_initialized ();
+
+ IndicatorPowerDevice * device = indicator_power_device_new ("/object/path",
+ UP_DEVICE_KIND_BATTERY,
+ "icon",
+ 50.0,
+ UP_DEVICE_STATE_CHARGING,
+ 30);
+ ASSERT_TRUE (device != NULL);
+ ASSERT_TRUE (INDICATOR_IS_POWER_DEVICE(device));
+ ASSERT_EQ (indicator_power_device_get_kind(device), UP_DEVICE_KIND_BATTERY);
+ ASSERT_EQ (indicator_power_device_get_state(device), UP_DEVICE_STATE_CHARGING);
+ ASSERT_STREQ (indicator_power_device_get_object_path(device), "/object/path");
+ ASSERT_STREQ (indicator_power_device_get_icon(device), "icon");
+ ASSERT_EQ ((int)indicator_power_device_get_percentage(device), 50);
+ ASSERT_EQ (indicator_power_device_get_time(device), 30);
+
+ /* cleanup */
+ g_clear_pointer (&device, g_object_unref);
+}
+
+TEST(DeviceTest, NewFromVariant)
+{
+ ensure_glib_initialized ();
+
+ GVariant * variant = g_variant_new ("(susdut)",
+ "/object/path",
+ UP_DEVICE_KIND_BATTERY,
+ "icon",
+ 50.0,
+ UP_DEVICE_STATE_CHARGING,
+ 30);
+ IndicatorPowerDevice * device = indicator_power_device_new_from_variant (variant);
+ ASSERT_TRUE (variant != NULL);
+ ASSERT_TRUE (device != NULL);
+ ASSERT_TRUE (INDICATOR_IS_POWER_DEVICE(device));
+ ASSERT_EQ (indicator_power_device_get_kind(device), UP_DEVICE_KIND_BATTERY);
+ ASSERT_EQ (indicator_power_device_get_state(device), UP_DEVICE_STATE_CHARGING);
+ ASSERT_STREQ (indicator_power_device_get_object_path(device), "/object/path");
+ ASSERT_STREQ (indicator_power_device_get_icon(device), "icon");
+ ASSERT_EQ ((int)indicator_power_device_get_percentage(device), 50);
+ ASSERT_EQ (indicator_power_device_get_time(device), 30);
+
+ /* cleanup */
+ g_clear_pointer (&device, g_object_unref);
+ g_clear_pointer (&variant, g_variant_unref);
+}