Back to index

dbus-test-runner  12.10.0
task.c
Go to the documentation of this file.
00001 /*
00002 Copyright 2012 Canonical Ltd.
00003 
00004 Authors:
00005     Ted Gould <ted@canonical.com>
00006 
00007 This program is free software: you can redistribute it and/or modify it 
00008 under the terms of the GNU General Public License version 3, as published 
00009 by the Free Software Foundation.
00010 
00011 This program is distributed in the hope that it will be useful, but 
00012 WITHOUT ANY WARRANTY; without even the implied warranties of 
00013 MERCHANTABILITY, SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR 
00014 PURPOSE.  See the GNU General Public License for more details.
00015 
00016 You should have received a copy of the GNU General Public License along 
00017 with this program.  If not, see <http://www.gnu.org/licenses/>.
00018 */
00019 
00020 #ifdef HAVE_CONFIG_H
00021 #include "config.h"
00022 #endif
00023 
00024 #include "dbus-test.h"
00025 #include <gio/gio.h>
00026 
00027 struct _DbusTestTaskPrivate {
00028        DbusTestTaskReturn return_type;
00029 
00030        gchar * wait_for;
00031        guint wait_task;
00032 
00033        gchar * name;
00034        gchar * name_padded;
00035        glong padding_cnt;
00036 
00037        gboolean been_run;
00038 };
00039 
00040 /* Signals */
00041 enum {
00042        STATE_CHANGED,
00043        LAST_SIGNAL /* Don't touch! */
00044 };
00045 
00046 #define DBUS_TEST_TASK_GET_PRIVATE(o) \
00047 (G_TYPE_INSTANCE_GET_PRIVATE ((o), DBUS_TEST_TYPE_TASK, DbusTestTaskPrivate))
00048 
00049 static void dbus_test_task_class_init (DbusTestTaskClass *klass);
00050 static void dbus_test_task_init       (DbusTestTask *self);
00051 static void dbus_test_task_dispose    (GObject *object);
00052 static void dbus_test_task_finalize   (GObject *object);
00053 
00054 G_DEFINE_TYPE (DbusTestTask, dbus_test_task, G_TYPE_OBJECT);
00055 
00056 static guint signals[LAST_SIGNAL] = {0};
00057 
00058 static void
00059 dbus_test_task_class_init (DbusTestTaskClass *klass)
00060 {
00061        GObjectClass *object_class = G_OBJECT_CLASS (klass);
00062 
00063        g_type_class_add_private (klass, sizeof (DbusTestTaskPrivate));
00064 
00065        object_class->dispose = dbus_test_task_dispose;
00066        object_class->finalize = dbus_test_task_finalize;
00067 
00068        klass->run = NULL;
00069        klass->get_state = NULL;
00070        klass->get_passed = NULL;
00071 
00072        signals[STATE_CHANGED]  = g_signal_new(DBUS_TEST_TASK_SIGNAL_STATE_CHANGED,
00073                                               G_TYPE_FROM_CLASS (klass),
00074                                               G_SIGNAL_RUN_LAST,
00075                                               G_STRUCT_OFFSET (DbusTestTaskClass, state_changed),
00076                                               NULL, NULL,
00077                                               g_cclosure_marshal_VOID__INT,
00078                                               G_TYPE_NONE, 1, G_TYPE_INT, G_TYPE_NONE);
00079 
00080        return;
00081 }
00082 
00083 static void
00084 dbus_test_task_init (DbusTestTask *self)
00085 {
00086        static gint task_count = 0;
00087 
00088        self->priv = DBUS_TEST_TASK_GET_PRIVATE(self);
00089 
00090        self->priv->return_type = DBUS_TEST_TASK_RETURN_NORMAL;
00091 
00092        self->priv->wait_for = NULL;
00093        self->priv->wait_task = 0;
00094 
00095        self->priv->name = g_strdup_printf("task-%d", task_count++);
00096        self->priv->name_padded = NULL;
00097        self->priv->padding_cnt = 0;
00098 
00099        self->priv->been_run = FALSE;
00100 
00101        return;
00102 }
00103 
00104 static void
00105 dbus_test_task_dispose (GObject *object)
00106 {
00107        g_return_if_fail(DBUS_TEST_IS_TASK(object));
00108        DbusTestTask * self = DBUS_TEST_TASK(object);
00109 
00110        if (self->priv->wait_task != 0) {
00111               g_bus_unwatch_name(self->priv->wait_task);
00112               self->priv->wait_task = 0;
00113        }
00114 
00115        G_OBJECT_CLASS (dbus_test_task_parent_class)->dispose (object);
00116        return;
00117 }
00118 
00119 static void
00120 dbus_test_task_finalize (GObject *object)
00121 {
00122        g_return_if_fail(DBUS_TEST_IS_TASK(object));
00123        DbusTestTask * self = DBUS_TEST_TASK(object);
00124 
00125        g_free(self->priv->name);
00126        g_free(self->priv->name_padded);
00127        g_free(self->priv->wait_for);
00128 
00129        G_OBJECT_CLASS (dbus_test_task_parent_class)->finalize (object);
00130        return;
00131 }
00132 
00133 DbusTestTask *
00134 dbus_test_task_new (void)
00135 {
00136        DbusTestTask * task = g_object_new(DBUS_TEST_TYPE_TASK,
00137                                           NULL);
00138 
00139        return task;
00140 }
00141 
00142 void
00143 dbus_test_task_set_name (DbusTestTask * task, const gchar * name)
00144 {
00145        g_return_if_fail(DBUS_TEST_IS_TASK(task));
00146 
00147        g_free(task->priv->name);
00148        g_free(task->priv->name_padded);
00149 
00150        task->priv->name = g_strdup(name);
00151        if (task->priv->padding_cnt != 0 && task->priv->name != NULL) {
00152               gchar * fillstr = g_strnfill(task->priv->padding_cnt - g_utf8_strlen(task->priv->name, -1), ' ');
00153               task->priv->name_padded = g_strconcat(task->priv->name, fillstr, NULL);
00154               g_free(fillstr);
00155        } else {
00156               task->priv->name_padded = NULL;
00157        }
00158 
00159        return;
00160 }
00161 
00162 void
00163 dbus_test_task_set_name_spacing (DbusTestTask * task, glong chars)
00164 {
00165        g_return_if_fail(DBUS_TEST_IS_TASK(task));
00166 
00167        g_free(task->priv->name_padded);
00168        task->priv->padding_cnt = chars;
00169 
00170        g_return_if_fail(task->priv->padding_cnt >= g_utf8_strlen(task->priv->name, -1));
00171 
00172        if (chars != 0 && task->priv->name != NULL) {
00173               gchar * fillstr = g_strnfill(task->priv->padding_cnt - g_utf8_strlen(task->priv->name, -1), ' ');
00174               task->priv->name_padded = g_strconcat(task->priv->name, fillstr, NULL);
00175               g_free(fillstr);
00176        } else {
00177               task->priv->name_padded = NULL;
00178        }
00179 
00180        return;
00181 }
00182 
00183 void
00184 dbus_test_task_set_wait_for (DbusTestTask * task, const gchar * dbus_name)
00185 {
00186        g_return_if_fail(DBUS_TEST_IS_TASK(task));
00187 
00188        if (task->priv->wait_for != NULL) {
00189               g_free(task->priv->wait_for);
00190               task->priv->wait_for = NULL;
00191        }
00192 
00193        if (dbus_name == NULL) {
00194               return;
00195        }
00196 
00197        task->priv->wait_for = g_strdup(dbus_name);
00198 
00199        return;
00200 }
00201 
00202 void
00203 dbus_test_task_set_return (DbusTestTask * task, DbusTestTaskReturn ret)
00204 {
00205        g_return_if_fail(DBUS_TEST_IS_TASK(task));
00206 
00207        if (ret != task->priv->return_type && dbus_test_task_get_state(task) == DBUS_TEST_TASK_STATE_FINISHED) {
00208               g_warning("Changing return type after the task has finished");
00209        }
00210 
00211        task->priv->return_type = ret;
00212        return;
00213 }
00214 
00215 void
00216 dbus_test_task_print (DbusTestTask * task, const gchar * message)
00217 {
00218        g_return_if_fail(DBUS_TEST_IS_TASK(task));
00219        g_return_if_fail(message != NULL);
00220 
00221        gchar * name = task->priv->name;
00222        if (task->priv->name_padded != NULL) {
00223               name = task->priv->name_padded;
00224        }
00225 
00226        g_print("%s: %s\n", name, message);
00227 
00228        return;
00229 }
00230 
00231 DbusTestTaskState
00232 dbus_test_task_get_state (DbusTestTask * task)
00233 {
00234        g_return_val_if_fail(DBUS_TEST_IS_TASK(task), DBUS_TEST_TASK_STATE_FINISHED);
00235 
00236        if (task->priv->wait_task != 0) {
00237               return DBUS_TEST_TASK_STATE_WAITING;
00238        }
00239 
00240        DbusTestTaskClass * klass = DBUS_TEST_TASK_GET_CLASS(task);
00241        if (klass->get_state != NULL) {
00242               return klass->get_state(task);
00243        }
00244 
00245        if (task->priv->been_run) {
00246               return DBUS_TEST_TASK_STATE_FINISHED;
00247        } else {
00248               return DBUS_TEST_TASK_STATE_INIT;
00249        }
00250 }
00251 
00252 DbusTestTaskReturn
00253 dbus_test_task_get_return (DbusTestTask * task)
00254 {
00255        g_return_val_if_fail(DBUS_TEST_IS_TASK(task), DBUS_TEST_TASK_RETURN_IGNORE);
00256 
00257        return task->priv->return_type;
00258 }
00259 
00260 static void
00261 wait_for_found (GDBusConnection * connection, const gchar * name, const gchar * name_owner, gpointer user_data)
00262 {
00263        g_return_if_fail(DBUS_TEST_IS_TASK(user_data));
00264        DbusTestTask * task = DBUS_TEST_TASK(user_data);
00265 
00266        g_bus_unwatch_name(task->priv->wait_task);
00267        task->priv->wait_task = 0;
00268 
00269        DbusTestTaskClass * klass = DBUS_TEST_TASK_GET_CLASS(task);
00270        if (klass->run != NULL) {
00271               klass->run(task);
00272        } else {
00273               task->priv->been_run = TRUE;
00274               g_signal_emit(G_OBJECT(task), signals[STATE_CHANGED], 0, DBUS_TEST_TASK_STATE_FINISHED, NULL);
00275        }
00276 
00277        return;
00278 }
00279 
00280 void
00281 dbus_test_task_run (DbusTestTask * task)
00282 {
00283        g_return_if_fail(DBUS_TEST_IS_TASK(task));
00284 
00285        /* We're going to process the waiting at this level if we've been
00286           asked to do so */
00287        if (task->priv->wait_for != NULL) {
00288               task->priv->wait_task = g_bus_watch_name(G_BUS_TYPE_SESSION,
00289                                                        task->priv->wait_for,
00290                                                        G_BUS_NAME_WATCHER_FLAGS_NONE,
00291                                                        wait_for_found,
00292                                                        NULL,
00293                                                        task,
00294                                                        NULL);
00295               g_signal_emit(G_OBJECT(task), signals[STATE_CHANGED], 0, DBUS_TEST_TASK_STATE_WAITING, NULL);
00296               return;
00297        }
00298 
00299        DbusTestTaskClass * klass = DBUS_TEST_TASK_GET_CLASS(task);
00300        if (klass->run != NULL) {
00301               klass->run(task);
00302        } else {
00303               task->priv->been_run = TRUE;
00304               g_signal_emit(G_OBJECT(task), signals[STATE_CHANGED], 0, DBUS_TEST_TASK_STATE_FINISHED, NULL);
00305        }
00306 
00307        return;
00308 }
00309 
00310 gboolean
00311 dbus_test_task_passed (DbusTestTask * task)
00312 {
00313        g_return_val_if_fail(DBUS_TEST_IS_TASK(task), FALSE);
00314 
00315        /* If we don't care, we always pass */
00316        if (task->priv->return_type == DBUS_TEST_TASK_RETURN_IGNORE) {
00317               return TRUE;
00318        }
00319 
00320        DbusTestTaskClass * klass = DBUS_TEST_TASK_GET_CLASS(task);
00321        if (klass->get_passed == NULL) {
00322               return FALSE;
00323        }
00324 
00325        gboolean subret = klass->get_passed(task);
00326 
00327        if (task->priv->return_type == DBUS_TEST_TASK_RETURN_INVERT) {
00328               return !subret;
00329        }
00330 
00331        return subret;
00332 }
00333 
00334 const gchar *
00335 dbus_test_task_get_name (DbusTestTask * task)
00336 {
00337        g_return_val_if_fail(DBUS_TEST_IS_TASK(task), NULL);
00338 
00339        return task->priv->name;
00340 }
00341 
00342 const gchar *
00343 dbus_test_task_get_wait_for (DbusTestTask * task)
00344 {
00345        g_return_val_if_fail(DBUS_TEST_IS_TASK(task), NULL);
00346 
00347        return task->priv->wait_for;
00348 }