1 /* -*- Mode: C; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*
3  *  Copyright (C) 2008-2014  Kouhei Sutou <kou@clear-code.com>
4  *
5  *  This library is free software: you can redistribute it and/or modify
6  *  it under the terms of the GNU Lesser General Public License as published by
7  *  the Free Software Foundation, either version 3 of the License, or
8  *  (at your option) any later version.
9  *
10  *  This library is distributed in the hope that it will be useful,
11  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
12  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13  *  GNU Lesser General Public License for more details.
14  *
15  *  You should have received a copy of the GNU Lesser General Public License
16  *  along with this program.  If not, see <http://www.gnu.org/licenses/>.
17  *
18  */
19 
20 #ifdef HAVE_CONFIG_H
21 #  include <config.h>
22 #endif /* HAVE_CONFIG_H */
23 
24 #include <glib.h>
25 #include <glib-compatible/glib-compatible.h>
26 
27 #include <string.h>
28 
29 #include "cut-run-context.h"
30 #include "cut-runner.h"
31 #include "cut-listener.h"
32 #include "cut-repository.h"
33 #include "cut-test-case.h"
34 #include "cut-test-result.h"
35 #include "cut-glib-compatible.h"
36 
37 #include "cut-enum-types.h"
38 #include <gcutter/gcut-marshalers.h>
39 
40 #ifdef ERROR
41 #  undef ERROR /* for Windows */
42 #endif
43 
44 #if !GLIB_CHECK_VERSION(2, 18, 0)
45 #  define g_set_error_literal(error, domain, code, message) \
46     g_set_error(error, domain, code, "%s", message)
47 #endif
48 
49 #define CUT_RUN_CONTEXT_GET_PRIVATE(obj) (G_TYPE_INSTANCE_GET_PRIVATE ((obj), CUT_TYPE_RUN_CONTEXT, CutRunContextPrivate))
50 
51 typedef struct _CutRunContextPrivate	CutRunContextPrivate;
52 struct _CutRunContextPrivate
53 {
54     guint n_tests;
55     guint n_assertions;
56     guint n_successes;
57     guint n_failures;
58     guint n_errors;
59     guint n_pendings;
60     guint n_notifications;
61     guint n_omissions;
62     gdouble elapsed;
63     GTimer *timer;
64     GList *results;
65     GList *reversed_results;
66     gboolean use_multi_thread;
67     gboolean is_multi_thread;
68     gboolean max_threads;
69     gboolean handle_signals;
70     GMutex *mutex;
71     gboolean crashed;
72     gchar *backtrace;
73     gchar *test_directory;
74     gchar **exclude_files;
75     gchar **exclude_directories;
76     gchar *source_directory;
77     gchar *log_directory;
78     gchar **target_test_case_names;
79     gchar **target_test_names;
80     GList *loader_customizers;
81     gboolean canceled;
82     CutTestSuite *test_suite;
83     GList *listeners;
84     CutOrder test_case_order;
85     gchar **command_line_args;
86     gboolean completed;
87     gboolean fatal_failures;
88     gboolean keep_opening_modules;
89     gboolean enable_convenience_attribute_definition;
90     gboolean stop_before_test;
91 };
92 
93 enum
94 {
95     PROP_0,
96     PROP_N_TESTS,
97     PROP_N_ASSERTIONS,
98     PROP_N_SUCCESSES,
99     PROP_N_FAILURES,
100     PROP_N_ERRORS,
101     PROP_N_PENDINGS,
102     PROP_N_NOTIFICATIONS,
103     PROP_N_OMISSIONS,
104     PROP_USE_MULTI_THREAD,
105     PROP_IS_MULTI_THREAD,
106     PROP_MAX_THREADS,
107     PROP_HANDLE_SIGNALS,
108     PROP_TEST_CASE_ORDER,
109     PROP_TEST_DIRECTORY,
110     PROP_SOURCE_DIRECTORY,
111     PROP_LOG_DIRECTORY,
112     PROP_TARGET_TEST_CASE_NAMES,
113     PROP_TARGET_TEST_NAMES,
114     PROP_EXCLUDE_FILES,
115     PROP_EXCLUDE_DIRECTORIES,
116     PROP_COMMAND_LINE_ARGS,
117     PROP_FATAL_FAILURES,
118     PROP_KEEP_OPENING_MODULES,
119     PROP_ENABLE_CONVENIENCE_ATTRIBUTE_DEFINITION,
120     PROP_STOP_BEFORE_TEST
121 };
122 
123 enum
124 {
125     START_SIGNAL,
126 
127     START_RUN,
128     READY_TEST_SUITE,
129     START_TEST_SUITE,
130     READY_TEST_CASE,
131     START_TEST_CASE,
132     READY_TEST_ITERATOR,
133     START_TEST_ITERATOR,
134     START_TEST,
135     START_ITERATED_TEST,
136 
137     PASS_ASSERTION,
138 
139     SUCCESS_TEST,
140     FAILURE_TEST,
141     ERROR_TEST,
142     PENDING_TEST,
143     NOTIFICATION_TEST,
144     OMISSION_TEST,
145     CRASH_TEST,
146 
147     SUCCESS_TEST_ITERATOR,
148     FAILURE_TEST_ITERATOR,
149     ERROR_TEST_ITERATOR,
150     PENDING_TEST_ITERATOR,
151     NOTIFICATION_TEST_ITERATOR,
152     OMISSION_TEST_ITERATOR,
153     CRASH_TEST_ITERATOR,
154 
155     SUCCESS_TEST_CASE,
156     FAILURE_TEST_CASE,
157     ERROR_TEST_CASE,
158     PENDING_TEST_CASE,
159     NOTIFICATION_TEST_CASE,
160     OMISSION_TEST_CASE,
161     CRASH_TEST_CASE,
162 
163     FAILURE_IN_TEST_CASE,
164     ERROR_IN_TEST_CASE,
165     PENDING_IN_TEST_CASE,
166     NOTIFICATION_IN_TEST_CASE,
167     OMISSION_IN_TEST_CASE,
168     CRASH_IN_TEST_CASE,
169 
170     CRASH_TEST_SUITE,
171 
172     COMPLETE_ITERATED_TEST,
173     COMPLETE_TEST,
174     COMPLETE_TEST_ITERATOR,
175     COMPLETE_TEST_CASE,
176     COMPLETE_TEST_SUITE,
177     COMPLETE_RUN,
178 
179     ERROR,
180 
181     LAST_SIGNAL
182 };
183 
184 static gint signals[LAST_SIGNAL] = {0};
185 static CutRunnerIface *parent_runner_iface;
186 
187 static GQuark detail_delegate;
188 
189 static void runner_init (CutRunnerIface *iface);
190 
191 G_DEFINE_ABSTRACT_TYPE_WITH_CODE(CutRunContext, cut_run_context, G_TYPE_OBJECT,
192                                  G_IMPLEMENT_INTERFACE(CUT_TYPE_RUNNER,
193                                                        runner_init));
194 
195 static void dispose        (GObject         *object);
196 static void set_property   (GObject         *object,
197                             guint            prop_id,
198                             const GValue    *value,
199                             GParamSpec      *pspec);
200 static void get_property   (GObject         *object,
201                             guint            prop_id,
202                             GValue          *value,
203                             GParamSpec      *pspec);
204 
205 static void start_run      (CutRunContext   *context);
206 
207 static void start_iterated_test
208                            (CutRunContext   *context,
209                             CutIteratedTest *iterated_test,
210                             CutTestContext  *test_context);
211 static void start_test     (CutRunContext   *context,
212                             CutTest         *test,
213                             CutTestContext  *test_context);
214 static void pass_assertion (CutRunContext   *context,
215                             CutTest         *test,
216                             CutTestContext  *test_context);
217 static void success_test   (CutRunContext   *context,
218                             CutTest         *test,
219                             CutTestContext  *test_context,
220                             CutTestResult   *result);
221 static void failure_test   (CutRunContext   *context,
222                             CutTest         *test,
223                             CutTestContext  *test_context,
224                             CutTestResult   *result);
225 static void error_test     (CutRunContext   *context,
226                             CutTest         *test,
227                             CutTestContext  *test_context,
228                             CutTestResult   *result);
229 static void pending_test   (CutRunContext   *context,
230                             CutTest         *test,
231                             CutTestContext  *test_context,
232                             CutTestResult   *result);
233 static void notification_test
234                            (CutRunContext   *context,
235                             CutTest         *test,
236                             CutTestContext  *test_context,
237                             CutTestResult   *result);
238 static void omission_test  (CutRunContext   *context,
239                             CutTest         *test,
240                             CutTestContext  *test_context,
241                             CutTestResult   *result);
242 static void crash_test     (CutRunContext   *context,
243                             CutTest         *test,
244                             CutTestContext  *test_context,
245                             CutTestResult   *result);
246 static void complete_test  (CutRunContext   *context,
247                             CutTest         *test,
248                             CutTestContext  *test_context,
249                             gboolean         success);
250 static void complete_iterated_test
251                            (CutRunContext   *context,
252                             CutIteratedTest *iterated_test,
253                             CutTestContext  *test_context,
254                             gboolean         success);
255 
256 static void failure_in_test_case
257                            (CutRunContext   *context,
258                             CutTestCase     *test_case,
259                             CutTestResult   *result);
260 static void error_in_test_case
261                            (CutRunContext   *context,
262                             CutTestCase     *test_case,
263                             CutTestResult   *result);
264 static void pending_in_test_case
265                            (CutRunContext   *context,
266                             CutTestCase     *test_case,
267                             CutTestResult   *result);
268 static void notification_in_test_case
269                            (CutRunContext   *context,
270                             CutTestCase     *test_case,
271                             CutTestResult   *result);
272 static void omission_in_test_case
273                            (CutRunContext   *context,
274                             CutTestCase     *test_case,
275                             CutTestResult   *result);
276 static void crash_in_test_case
277                            (CutRunContext   *context,
278                             CutTestCase     *test_case,
279                             CutTestResult   *result);
280 
281 static void crash_test_suite
282                            (CutRunContext   *context,
283                             CutTestSuite    *test_suite,
284                             CutTestResult   *result);
285 
286 static void complete_run   (CutRunContext   *context,
287                             gboolean         success);
288 
289 static gboolean runner_run (CutRunner *runner);
290 
291 static void
cut_run_context_class_init(CutRunContextClass * klass)292 cut_run_context_class_init (CutRunContextClass *klass)
293 {
294     GObjectClass *gobject_class;
295     GParamSpec *spec;
296 
297     gobject_class = G_OBJECT_CLASS(klass);
298 
299     gobject_class->dispose      = dispose;
300     gobject_class->set_property = set_property;
301     gobject_class->get_property = get_property;
302 
303     klass->start_run         = start_run;
304 
305     klass->start_iterated_test = start_iterated_test;
306     klass->start_test        = start_test;
307     klass->pass_assertion    = pass_assertion;
308     klass->success_test      = success_test;
309     klass->failure_test      = failure_test;
310     klass->error_test        = error_test;
311     klass->pending_test      = pending_test;
312     klass->notification_test = notification_test;
313     klass->omission_test     = omission_test;
314     klass->crash_test        = crash_test;
315     klass->complete_test     = complete_test;
316     klass->complete_iterated_test = complete_iterated_test;
317 
318     klass->failure_in_test_case = failure_in_test_case;
319     klass->error_in_test_case   = error_in_test_case;
320     klass->pending_in_test_case = pending_in_test_case;
321     klass->notification_in_test_case = notification_in_test_case;
322     klass->omission_in_test_case = omission_in_test_case;
323     klass->crash_in_test_case = crash_in_test_case;
324 
325     klass->crash_test_suite  = crash_test_suite;
326 
327     klass->complete_run      = complete_run;
328 
329     spec = g_param_spec_uint("n-tests",
330                              "Number of tests",
331                              "The number of tests of the run context",
332                              0, G_MAXUINT32, 0,
333                              G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY);
334     g_object_class_install_property(gobject_class, PROP_N_TESTS, spec);
335 
336     spec = g_param_spec_uint("n-assertions",
337                              "Number of assertions",
338                              "The number of assertions of the run context",
339                              0, G_MAXUINT32, 0,
340                              G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY);
341     g_object_class_install_property(gobject_class, PROP_N_ASSERTIONS, spec);
342 
343     spec = g_param_spec_uint("n-successes",
344                              "Number of successes",
345                              "The number of successes of the run context",
346                              0, G_MAXUINT32, 0,
347                              G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY);
348     g_object_class_install_property(gobject_class, PROP_N_SUCCESSES, spec);
349 
350     spec = g_param_spec_uint("n-failures",
351                              "Number of failures",
352                              "The number of failures of the run context",
353                              0, G_MAXUINT32, 0,
354                              G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY);
355     g_object_class_install_property(gobject_class, PROP_N_FAILURES, spec);
356 
357     spec = g_param_spec_uint("n-errors",
358                              "Number of errors",
359                              "The number of errors of the run context",
360                              0, G_MAXUINT32, 0,
361                              G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY);
362     g_object_class_install_property(gobject_class, PROP_N_ERRORS, spec);
363 
364     spec = g_param_spec_uint("n-pendings",
365                              "Number of pendings",
366                              "The number of pendings of the run context",
367                              0, G_MAXUINT32, 0,
368                              G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY);
369     g_object_class_install_property(gobject_class, PROP_N_PENDINGS, spec);
370 
371     spec = g_param_spec_uint("n-notifications",
372                              "Number of notifications",
373                              "The number of notifications of the run context",
374                              0, G_MAXUINT32, 0,
375                              G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY);
376     g_object_class_install_property(gobject_class, PROP_N_NOTIFICATIONS, spec);
377 
378     spec = g_param_spec_uint("n-omissions",
379                              "Number of omissions",
380                              "The number of omissions of the run context",
381                              0, G_MAXUINT32, 0,
382                              G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY);
383     g_object_class_install_property(gobject_class, PROP_N_OMISSIONS, spec);
384 
385     spec = g_param_spec_boolean("use-multi-thread",
386                                 "Use multi thread",
387                                 "Whether use multi thread or not in the run context",
388                                 FALSE,
389                                 G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY);
390     g_object_class_install_property(gobject_class, PROP_USE_MULTI_THREAD, spec);
391 
392     spec = g_param_spec_boolean("is-multi-thread",
393                                 "Is multi thread?",
394                                 "Whether the run context is running tests with multi thread",
395                                 FALSE,
396                                 G_PARAM_READWRITE);
397     g_object_class_install_property(gobject_class, PROP_IS_MULTI_THREAD, spec);
398 
399     spec = g_param_spec_int("max-threads",
400                             "Max number of threads",
401                             "How many threads are used concurrently at a maximum",
402                             -1, G_MAXINT32, 10,
403                             G_PARAM_READWRITE);
404     g_object_class_install_property(gobject_class, PROP_MAX_THREADS, spec);
405 
406     spec = g_param_spec_boolean("handle-signals",
407                                 "Whether handle signals",
408                                 "Whether the run context handles signals",
409                                 TRUE,
410                                 G_PARAM_READWRITE);
411     g_object_class_install_property(gobject_class, PROP_HANDLE_SIGNALS, spec);
412 
413     spec = g_param_spec_enum("test-case-order",
414                              "Test case order",
415                              "Sort key for test case",
416                              CUT_TYPE_ORDER,
417                              CUT_ORDER_NONE_SPECIFIED,
418                              G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY);
419     g_object_class_install_property(gobject_class, PROP_TEST_CASE_ORDER, spec);
420 
421     spec = g_param_spec_string("test-directory",
422                                "Test directory",
423                                "The directory name in which test cases are stored",
424                                NULL,
425                                G_PARAM_READWRITE);
426     g_object_class_install_property(gobject_class, PROP_TEST_DIRECTORY, spec);
427 
428     spec = g_param_spec_string("source-directory",
429                                "Source directory",
430                                "The directory name in which source files are stored",
431                                NULL,
432                                G_PARAM_READWRITE);
433     g_object_class_install_property(gobject_class, PROP_SOURCE_DIRECTORY, spec);
434 
435     spec = g_param_spec_string("log-directory",
436                                "Log directory",
437                                "The directory name in which log files are stored",
438                                NULL,
439                                G_PARAM_READWRITE);
440     g_object_class_install_property(gobject_class, PROP_LOG_DIRECTORY, spec);
441 
442     spec = g_param_spec_pointer("target-test-case-names",
443                                 "Test case names",
444                                 "The names of the target test case",
445                                 G_PARAM_READWRITE);
446     g_object_class_install_property(gobject_class, PROP_TARGET_TEST_CASE_NAMES, spec);
447 
448     spec = g_param_spec_pointer("target-test-names",
449                                 "Test names",
450                                 "The names of the target test",
451                                 G_PARAM_READWRITE);
452     g_object_class_install_property(gobject_class, PROP_TARGET_TEST_NAMES, spec);
453 
454     spec = g_param_spec_pointer("exclude-files",
455                                 "Exclude files",
456                                 "The file names of excluding from the target",
457                                 G_PARAM_READWRITE);
458     g_object_class_install_property(gobject_class, PROP_EXCLUDE_FILES, spec);
459 
460     spec = g_param_spec_pointer("exclude-directories",
461                                 "Exclude directories",
462                                 "The directory names of excluding from target",
463                                 G_PARAM_READWRITE);
464     g_object_class_install_property(gobject_class, PROP_EXCLUDE_DIRECTORIES, spec);
465 
466     spec = g_param_spec_pointer("command-line-args",
467                                 "Command line arguments",
468                                 "The argument strings from command line",
469                                 G_PARAM_READWRITE);
470     g_object_class_install_property(gobject_class, PROP_COMMAND_LINE_ARGS, spec);
471 
472     spec = g_param_spec_boolean("fatal-failures",
473                                 "Fatal failures",
474                                 "Treat failures as fatal problem",
475                                 FALSE,
476                                 G_PARAM_READWRITE);
477     g_object_class_install_property(gobject_class, PROP_FATAL_FAILURES, spec);
478 
479     spec = g_param_spec_boolean("keep-opening-modules",
480                                 "Keep opening modules",
481                                 "Keep opening loaded modules to resolve symbols "
482                                 "for debugging",
483                                 FALSE,
484                                 G_PARAM_READWRITE);
485     g_object_class_install_property(gobject_class, PROP_KEEP_OPENING_MODULES,
486                                     spec);
487 
488     spec = g_param_spec_boolean("enable-convenience-attribute-definition",
489                                 "Enable convenience attribute definition",
490                                 "Enable convenience but dangerous "
491                                 "'#{ATTRIBUTE_NAME}_#{TEST_NAME - 'test_' PREFIX}' "
492                                 "attribute set function",
493                                 FALSE,
494                                 G_PARAM_READWRITE);
495     g_object_class_install_property(gobject_class,
496                                     PROP_ENABLE_CONVENIENCE_ATTRIBUTE_DEFINITION,
497                                     spec);
498 
499     spec = g_param_spec_boolean("stop-before-test",
500                                 "Stops before a test",
501                                 "Set breakpoint before invoking a test",
502                                 FALSE,
503                                 G_PARAM_READWRITE);
504     g_object_class_install_property(gobject_class,
505                                     PROP_STOP_BEFORE_TEST,
506                                     spec);
507 
508     signals[START_RUN]
509         = g_signal_new("start-run",
510                        G_TYPE_FROM_CLASS(klass),
511                        G_SIGNAL_RUN_LAST | G_SIGNAL_DETAILED,
512                        G_STRUCT_OFFSET(CutRunContextClass, start_run),
513                        NULL, NULL,
514                        g_cclosure_marshal_VOID__VOID,
515                        G_TYPE_NONE, 0);
516 
517     signals[READY_TEST_SUITE]
518         = g_signal_new ("ready-test-suite",
519                         G_TYPE_FROM_CLASS (klass),
520                         G_SIGNAL_RUN_LAST | G_SIGNAL_DETAILED,
521                         G_STRUCT_OFFSET (CutRunContextClass, ready_test_suite),
522                         NULL, NULL,
523                         _gcut_marshal_VOID__OBJECT_UINT_UINT,
524                         G_TYPE_NONE, 3,
525                         CUT_TYPE_TEST_SUITE, G_TYPE_UINT, G_TYPE_UINT);
526 
527     signals[START_TEST_SUITE]
528         = g_signal_new ("start-test-suite",
529                         G_TYPE_FROM_CLASS (klass),
530                         G_SIGNAL_RUN_LAST | G_SIGNAL_DETAILED,
531                         G_STRUCT_OFFSET (CutRunContextClass, start_test_suite),
532                         NULL, NULL,
533                         g_cclosure_marshal_VOID__OBJECT,
534                         G_TYPE_NONE, 1, CUT_TYPE_TEST_SUITE);
535 
536     signals[READY_TEST_CASE]
537         = g_signal_new ("ready-test-case",
538                         G_TYPE_FROM_CLASS (klass),
539                         G_SIGNAL_RUN_LAST | G_SIGNAL_DETAILED,
540                         G_STRUCT_OFFSET (CutRunContextClass, ready_test_case),
541                         NULL, NULL,
542                         _gcut_marshal_VOID__OBJECT_UINT,
543                         G_TYPE_NONE, 2, CUT_TYPE_TEST_CASE, G_TYPE_UINT);
544 
545     signals[START_TEST_CASE]
546         = g_signal_new ("start-test-case",
547                         G_TYPE_FROM_CLASS(klass),
548                         G_SIGNAL_RUN_LAST | G_SIGNAL_DETAILED,
549                         G_STRUCT_OFFSET(CutRunContextClass, start_test_case),
550                         NULL, NULL,
551                         g_cclosure_marshal_VOID__OBJECT,
552                         G_TYPE_NONE, 1, CUT_TYPE_TEST_CASE);
553 
554     signals[READY_TEST_ITERATOR]
555         = g_signal_new ("ready-test-iterator",
556                         G_TYPE_FROM_CLASS(klass),
557                         G_SIGNAL_RUN_LAST | G_SIGNAL_DETAILED,
558                         G_STRUCT_OFFSET(CutRunContextClass, ready_test_iterator),
559                         NULL, NULL,
560                         _gcut_marshal_VOID__OBJECT_UINT,
561                         G_TYPE_NONE, 2, CUT_TYPE_TEST_ITERATOR, G_TYPE_UINT);
562 
563     signals[START_TEST_ITERATOR]
564         = g_signal_new ("start-test-iterator",
565                         G_TYPE_FROM_CLASS(klass),
566                         G_SIGNAL_RUN_LAST | G_SIGNAL_DETAILED,
567                         G_STRUCT_OFFSET(CutRunContextClass, start_test_iterator),
568                         NULL, NULL,
569                         g_cclosure_marshal_VOID__OBJECT,
570                         G_TYPE_NONE, 1, CUT_TYPE_TEST_ITERATOR);
571 
572     signals[START_TEST]
573         = g_signal_new ("start-test",
574                         G_TYPE_FROM_CLASS (klass),
575                         G_SIGNAL_RUN_LAST | G_SIGNAL_DETAILED,
576                         G_STRUCT_OFFSET (CutRunContextClass, start_test),
577                         NULL, NULL,
578                         _gcut_marshal_VOID__OBJECT_OBJECT,
579                         G_TYPE_NONE, 2,
580                         CUT_TYPE_TEST, CUT_TYPE_TEST_CONTEXT);
581 
582     signals[START_ITERATED_TEST]
583         = g_signal_new("start-iterated-test",
584                        G_TYPE_FROM_CLASS(klass),
585                        G_SIGNAL_RUN_LAST | G_SIGNAL_DETAILED,
586                        G_STRUCT_OFFSET(CutRunContextClass, start_iterated_test),
587                        NULL, NULL,
588                        _gcut_marshal_VOID__OBJECT_OBJECT,
589                        G_TYPE_NONE, 2,
590                        CUT_TYPE_ITERATED_TEST, CUT_TYPE_TEST_CONTEXT);
591 
592     signals[PASS_ASSERTION]
593         = g_signal_new ("pass-assertion",
594                         G_TYPE_FROM_CLASS (klass),
595                         G_SIGNAL_RUN_LAST | G_SIGNAL_DETAILED,
596                         G_STRUCT_OFFSET (CutRunContextClass, pass_assertion),
597                         NULL, NULL,
598                         _gcut_marshal_VOID__OBJECT_OBJECT,
599                         G_TYPE_NONE, 2, CUT_TYPE_TEST, CUT_TYPE_TEST_CONTEXT);
600 
601     signals[SUCCESS_TEST]
602         = g_signal_new ("success-test",
603                         G_TYPE_FROM_CLASS (klass),
604                         G_SIGNAL_RUN_LAST | G_SIGNAL_DETAILED,
605                         G_STRUCT_OFFSET (CutRunContextClass, success_test),
606                         NULL, NULL,
607                         _gcut_marshal_VOID__OBJECT_OBJECT_OBJECT,
608                         G_TYPE_NONE, 3,
609                         CUT_TYPE_TEST, CUT_TYPE_TEST_CONTEXT,
610                         CUT_TYPE_TEST_RESULT);
611 
612     signals[FAILURE_TEST]
613         = g_signal_new ("failure-test",
614                         G_TYPE_FROM_CLASS (klass),
615                         G_SIGNAL_RUN_LAST | G_SIGNAL_DETAILED,
616                         G_STRUCT_OFFSET (CutRunContextClass, failure_test),
617                         NULL, NULL,
618                         _gcut_marshal_VOID__OBJECT_OBJECT_OBJECT,
619                         G_TYPE_NONE, 3,
620                         CUT_TYPE_TEST, CUT_TYPE_TEST_CONTEXT,
621                         CUT_TYPE_TEST_RESULT);
622 
623     signals[ERROR_TEST]
624         = g_signal_new ("error-test",
625                         G_TYPE_FROM_CLASS (klass),
626                         G_SIGNAL_RUN_LAST | G_SIGNAL_DETAILED,
627                         G_STRUCT_OFFSET (CutRunContextClass, error_test),
628                         NULL, NULL,
629                         _gcut_marshal_VOID__OBJECT_OBJECT_OBJECT,
630                         G_TYPE_NONE, 3,
631                         CUT_TYPE_TEST, CUT_TYPE_TEST_CONTEXT,
632                         CUT_TYPE_TEST_RESULT);
633 
634     signals[PENDING_TEST]
635         = g_signal_new ("pending-test",
636                         G_TYPE_FROM_CLASS (klass),
637                         G_SIGNAL_RUN_LAST | G_SIGNAL_DETAILED,
638                         G_STRUCT_OFFSET (CutRunContextClass, pending_test),
639                         NULL, NULL,
640                         _gcut_marshal_VOID__OBJECT_OBJECT_OBJECT,
641                         G_TYPE_NONE, 3,
642                         CUT_TYPE_TEST, CUT_TYPE_TEST_CONTEXT,
643                         CUT_TYPE_TEST_RESULT);
644 
645     signals[NOTIFICATION_TEST]
646         = g_signal_new ("notification-test",
647                         G_TYPE_FROM_CLASS (klass),
648                         G_SIGNAL_RUN_LAST | G_SIGNAL_DETAILED,
649                         G_STRUCT_OFFSET (CutRunContextClass, notification_test),
650                         NULL, NULL,
651                         _gcut_marshal_VOID__OBJECT_OBJECT_OBJECT,
652                         G_TYPE_NONE, 3,
653                         CUT_TYPE_TEST, CUT_TYPE_TEST_CONTEXT,
654                         CUT_TYPE_TEST_RESULT);
655 
656     signals[OMISSION_TEST]
657         = g_signal_new("omission-test",
658                        G_TYPE_FROM_CLASS(klass),
659                        G_SIGNAL_RUN_LAST | G_SIGNAL_DETAILED,
660                        G_STRUCT_OFFSET(CutRunContextClass, omission_test),
661                        NULL, NULL,
662                        _gcut_marshal_VOID__OBJECT_OBJECT_OBJECT,
663                        G_TYPE_NONE, 3,
664                        CUT_TYPE_TEST, CUT_TYPE_TEST_CONTEXT,
665                        CUT_TYPE_TEST_RESULT);
666 
667     signals[CRASH_TEST]
668         = g_signal_new("crash-test",
669                        G_TYPE_FROM_CLASS(klass),
670                        G_SIGNAL_RUN_LAST | G_SIGNAL_DETAILED,
671                        G_STRUCT_OFFSET(CutRunContextClass, crash_test),
672                        NULL, NULL,
673                        _gcut_marshal_VOID__OBJECT_OBJECT_OBJECT,
674                        G_TYPE_NONE, 3,
675                        CUT_TYPE_TEST, CUT_TYPE_TEST_CONTEXT,
676                        CUT_TYPE_TEST_RESULT);
677 
678     signals[COMPLETE_ITERATED_TEST]
679         = g_signal_new("complete-iterated-test",
680                        G_TYPE_FROM_CLASS(klass),
681                        G_SIGNAL_RUN_LAST | G_SIGNAL_DETAILED,
682                        G_STRUCT_OFFSET(CutRunContextClass,
683                                        complete_iterated_test),
684                        NULL, NULL,
685                        _gcut_marshal_VOID__OBJECT_OBJECT_BOOLEAN,
686                        G_TYPE_NONE,
687                        3, CUT_TYPE_ITERATED_TEST, CUT_TYPE_TEST_CONTEXT,
688                        G_TYPE_BOOLEAN);
689 
690     signals[COMPLETE_TEST]
691         = g_signal_new("complete-test",
692                        G_TYPE_FROM_CLASS(klass),
693                        G_SIGNAL_RUN_LAST | G_SIGNAL_DETAILED,
694                        G_STRUCT_OFFSET(CutRunContextClass, complete_test),
695                        NULL, NULL,
696                        _gcut_marshal_VOID__OBJECT_OBJECT_BOOLEAN,
697                        G_TYPE_NONE,
698                        3, CUT_TYPE_TEST, CUT_TYPE_TEST_CONTEXT, G_TYPE_BOOLEAN);
699 
700     signals[SUCCESS_TEST_ITERATOR]
701         = g_signal_new("success-test-iterator",
702                        G_TYPE_FROM_CLASS(klass),
703                        G_SIGNAL_RUN_LAST | G_SIGNAL_DETAILED,
704                        G_STRUCT_OFFSET(CutRunContextClass, success_test_iterator),
705                        NULL, NULL,
706                        _gcut_marshal_VOID__OBJECT_OBJECT,
707                        G_TYPE_NONE,
708                        2, CUT_TYPE_TEST_ITERATOR, CUT_TYPE_TEST_RESULT);
709 
710     signals[FAILURE_TEST_ITERATOR]
711         = g_signal_new("failure-test-iterator",
712                        G_TYPE_FROM_CLASS(klass),
713                        G_SIGNAL_RUN_LAST | G_SIGNAL_DETAILED,
714                        G_STRUCT_OFFSET(CutRunContextClass, failure_test_iterator),
715                        NULL, NULL,
716                        _gcut_marshal_VOID__OBJECT_OBJECT,
717                        G_TYPE_NONE,
718                        2, CUT_TYPE_TEST_ITERATOR, CUT_TYPE_TEST_RESULT);
719 
720     signals[ERROR_TEST_ITERATOR]
721         = g_signal_new("error-test-iterator",
722                        G_TYPE_FROM_CLASS(klass),
723                        G_SIGNAL_RUN_LAST | G_SIGNAL_DETAILED,
724                        G_STRUCT_OFFSET(CutRunContextClass, error_test_iterator),
725                        NULL, NULL,
726                        _gcut_marshal_VOID__OBJECT_OBJECT,
727                        G_TYPE_NONE,
728                        2, CUT_TYPE_TEST_ITERATOR, CUT_TYPE_TEST_RESULT);
729 
730     signals[PENDING_TEST_ITERATOR]
731         = g_signal_new("pending-test-iterator",
732                        G_TYPE_FROM_CLASS(klass),
733                        G_SIGNAL_RUN_LAST | G_SIGNAL_DETAILED,
734                        G_STRUCT_OFFSET(CutRunContextClass, pending_test_iterator),
735                        NULL, NULL,
736                        _gcut_marshal_VOID__OBJECT_OBJECT,
737                        G_TYPE_NONE,
738                        2, CUT_TYPE_TEST_ITERATOR, CUT_TYPE_TEST_RESULT);
739 
740     signals[NOTIFICATION_TEST_ITERATOR]
741         = g_signal_new("notification-test-iterator",
742                        G_TYPE_FROM_CLASS(klass),
743                        G_SIGNAL_RUN_LAST | G_SIGNAL_DETAILED,
744                        G_STRUCT_OFFSET(CutRunContextClass, notification_test_iterator),
745                        NULL, NULL,
746                        _gcut_marshal_VOID__OBJECT_OBJECT,
747                        G_TYPE_NONE,
748                        2, CUT_TYPE_TEST_ITERATOR, CUT_TYPE_TEST_RESULT);
749 
750     signals[OMISSION_TEST_ITERATOR]
751         = g_signal_new("omission-test-iterator",
752                        G_TYPE_FROM_CLASS (klass),
753                        G_SIGNAL_RUN_LAST | G_SIGNAL_DETAILED,
754                        G_STRUCT_OFFSET(CutRunContextClass, omission_test_iterator),
755                        NULL, NULL,
756                        _gcut_marshal_VOID__OBJECT_OBJECT,
757                        G_TYPE_NONE, 2, CUT_TYPE_TEST_ITERATOR, CUT_TYPE_TEST_RESULT);
758 
759     signals[CRASH_TEST_ITERATOR]
760         = g_signal_new("crash-test-iterator",
761                        G_TYPE_FROM_CLASS (klass),
762                        G_SIGNAL_RUN_LAST | G_SIGNAL_DETAILED,
763                        G_STRUCT_OFFSET(CutRunContextClass, crash_test_iterator),
764                        NULL, NULL,
765                        _gcut_marshal_VOID__OBJECT_OBJECT,
766                        G_TYPE_NONE, 2, CUT_TYPE_TEST_ITERATOR, CUT_TYPE_TEST_RESULT);
767 
768     signals[COMPLETE_TEST_ITERATOR]
769         = g_signal_new("complete-test-iterator",
770                        G_TYPE_FROM_CLASS(klass),
771                        G_SIGNAL_RUN_LAST | G_SIGNAL_DETAILED,
772                        G_STRUCT_OFFSET(CutRunContextClass,
773                                        complete_test_iterator),
774                        NULL, NULL,
775                        _gcut_marshal_VOID__OBJECT_BOOLEAN,
776                        G_TYPE_NONE, 2, CUT_TYPE_TEST_ITERATOR, G_TYPE_BOOLEAN);
777 
778     signals[SUCCESS_TEST_CASE]
779         = g_signal_new("success-test-case",
780                        G_TYPE_FROM_CLASS(klass),
781                        G_SIGNAL_RUN_LAST | G_SIGNAL_DETAILED,
782                        G_STRUCT_OFFSET(CutRunContextClass, success_test_case),
783                        NULL, NULL,
784                        _gcut_marshal_VOID__OBJECT_OBJECT,
785                        G_TYPE_NONE, 2, CUT_TYPE_TEST_CASE, CUT_TYPE_TEST_RESULT);
786 
787     signals[FAILURE_TEST_CASE]
788         = g_signal_new("failure-test-case",
789                        G_TYPE_FROM_CLASS(klass),
790                        G_SIGNAL_RUN_LAST | G_SIGNAL_DETAILED,
791                        G_STRUCT_OFFSET(CutRunContextClass, failure_test_case),
792                        NULL, NULL,
793                        _gcut_marshal_VOID__OBJECT_OBJECT,
794                        G_TYPE_NONE, 2, CUT_TYPE_TEST_CASE, CUT_TYPE_TEST_RESULT);
795 
796     signals[ERROR_TEST_CASE]
797         = g_signal_new("error-test-case",
798                        G_TYPE_FROM_CLASS(klass),
799                        G_SIGNAL_RUN_LAST | G_SIGNAL_DETAILED,
800                        G_STRUCT_OFFSET(CutRunContextClass, error_test_case),
801                        NULL, NULL,
802                        _gcut_marshal_VOID__OBJECT_OBJECT,
803                        G_TYPE_NONE, 2, CUT_TYPE_TEST_CASE, CUT_TYPE_TEST_RESULT);
804 
805     signals[PENDING_TEST_CASE]
806         = g_signal_new("pending-test-case",
807                        G_TYPE_FROM_CLASS(klass),
808                        G_SIGNAL_RUN_LAST | G_SIGNAL_DETAILED,
809                        G_STRUCT_OFFSET(CutRunContextClass, pending_test_case),
810                        NULL, NULL,
811                        _gcut_marshal_VOID__OBJECT_OBJECT,
812                        G_TYPE_NONE, 2, CUT_TYPE_TEST_CASE, CUT_TYPE_TEST_RESULT);
813 
814     signals[NOTIFICATION_TEST_CASE]
815         = g_signal_new("notification-test-case",
816                        G_TYPE_FROM_CLASS(klass),
817                        G_SIGNAL_RUN_LAST | G_SIGNAL_DETAILED,
818                        G_STRUCT_OFFSET(CutRunContextClass, notification_test_case),
819                        NULL, NULL,
820                        _gcut_marshal_VOID__OBJECT_OBJECT,
821                        G_TYPE_NONE, 2, CUT_TYPE_TEST_CASE, CUT_TYPE_TEST_RESULT);
822 
823     signals[OMISSION_TEST_CASE]
824         = g_signal_new("omission-test-case",
825                        G_TYPE_FROM_CLASS (klass),
826                        G_SIGNAL_RUN_LAST | G_SIGNAL_DETAILED,
827                        G_STRUCT_OFFSET(CutRunContextClass, omission_test_case),
828                        NULL, NULL,
829                        _gcut_marshal_VOID__OBJECT_OBJECT,
830                        G_TYPE_NONE, 2, CUT_TYPE_TEST_CASE, CUT_TYPE_TEST_RESULT);
831 
832     signals[CRASH_TEST_CASE]
833         = g_signal_new("crash-test-case",
834                        G_TYPE_FROM_CLASS (klass),
835                        G_SIGNAL_RUN_LAST | G_SIGNAL_DETAILED,
836                        G_STRUCT_OFFSET(CutRunContextClass, crash_test_case),
837                        NULL, NULL,
838                        _gcut_marshal_VOID__OBJECT_OBJECT,
839                        G_TYPE_NONE, 2, CUT_TYPE_TEST_CASE, CUT_TYPE_TEST_RESULT);
840 
841     signals[FAILURE_IN_TEST_CASE]
842         = g_signal_new("failure-in-test-case",
843                        G_TYPE_FROM_CLASS(klass),
844                        G_SIGNAL_RUN_LAST | G_SIGNAL_DETAILED,
845                        G_STRUCT_OFFSET(CutRunContextClass, failure_in_test_case),
846                        NULL, NULL,
847                        _gcut_marshal_VOID__OBJECT_OBJECT,
848                        G_TYPE_NONE, 2, CUT_TYPE_TEST_CASE, CUT_TYPE_TEST_RESULT);
849 
850     signals[ERROR_IN_TEST_CASE]
851         = g_signal_new("error-in-test-case",
852                        G_TYPE_FROM_CLASS(klass),
853                        G_SIGNAL_RUN_LAST | G_SIGNAL_DETAILED,
854                        G_STRUCT_OFFSET(CutRunContextClass, error_in_test_case),
855                        NULL, NULL,
856                        _gcut_marshal_VOID__OBJECT_OBJECT,
857                        G_TYPE_NONE, 2, CUT_TYPE_TEST_CASE, CUT_TYPE_TEST_RESULT);
858 
859     signals[PENDING_IN_TEST_CASE]
860         = g_signal_new("pending-in-test-case",
861                        G_TYPE_FROM_CLASS(klass),
862                        G_SIGNAL_RUN_LAST | G_SIGNAL_DETAILED,
863                        G_STRUCT_OFFSET(CutRunContextClass, pending_in_test_case),
864                        NULL, NULL,
865                        _gcut_marshal_VOID__OBJECT_OBJECT,
866                        G_TYPE_NONE, 2, CUT_TYPE_TEST_CASE, CUT_TYPE_TEST_RESULT);
867 
868     signals[NOTIFICATION_IN_TEST_CASE]
869         = g_signal_new("notification-in-test-case",
870                        G_TYPE_FROM_CLASS(klass),
871                        G_SIGNAL_RUN_LAST | G_SIGNAL_DETAILED,
872                        G_STRUCT_OFFSET(CutRunContextClass,
873                                        notification_in_test_case),
874                        NULL, NULL,
875                        _gcut_marshal_VOID__OBJECT_OBJECT,
876                        G_TYPE_NONE, 2, CUT_TYPE_TEST_CASE, CUT_TYPE_TEST_RESULT);
877 
878     signals[OMISSION_IN_TEST_CASE]
879         = g_signal_new("omission-in-test-case",
880                        G_TYPE_FROM_CLASS (klass),
881                        G_SIGNAL_RUN_LAST | G_SIGNAL_DETAILED,
882                        G_STRUCT_OFFSET(CutRunContextClass,
883                                        omission_in_test_case),
884                        NULL, NULL,
885                        _gcut_marshal_VOID__OBJECT_OBJECT,
886                        G_TYPE_NONE, 2, CUT_TYPE_TEST_CASE, CUT_TYPE_TEST_RESULT);
887 
888     signals[CRASH_IN_TEST_CASE]
889         = g_signal_new("crash-in-test-case",
890                        G_TYPE_FROM_CLASS (klass),
891                        G_SIGNAL_RUN_LAST | G_SIGNAL_DETAILED,
892                        G_STRUCT_OFFSET(CutRunContextClass,
893                                        crash_in_test_case),
894                        NULL, NULL,
895                        _gcut_marshal_VOID__OBJECT_OBJECT,
896                        G_TYPE_NONE, 2, CUT_TYPE_TEST_CASE, CUT_TYPE_TEST_RESULT);
897 
898     signals[COMPLETE_TEST_CASE]
899         = g_signal_new("complete-test-case",
900                        G_TYPE_FROM_CLASS(klass),
901                        G_SIGNAL_RUN_LAST | G_SIGNAL_DETAILED,
902                        G_STRUCT_OFFSET(CutRunContextClass, complete_test_case),
903                        NULL, NULL,
904                        _gcut_marshal_VOID__OBJECT_BOOLEAN,
905                        G_TYPE_NONE, 2, CUT_TYPE_TEST_CASE, G_TYPE_BOOLEAN);
906 
907     signals[CRASH_TEST_SUITE]
908         = g_signal_new("crash-test-suite",
909                        G_TYPE_FROM_CLASS(klass),
910                        G_SIGNAL_RUN_LAST | G_SIGNAL_DETAILED,
911                        G_STRUCT_OFFSET(CutRunContextClass, crash_test_suite),
912                        NULL, NULL,
913                        _gcut_marshal_VOID__OBJECT_OBJECT,
914                        G_TYPE_NONE, 2, CUT_TYPE_TEST_SUITE, CUT_TYPE_TEST_RESULT);
915 
916     signals[COMPLETE_TEST_SUITE]
917         = g_signal_new("complete-test-suite",
918                        G_TYPE_FROM_CLASS(klass),
919                        G_SIGNAL_RUN_LAST | G_SIGNAL_DETAILED,
920                        G_STRUCT_OFFSET(CutRunContextClass, complete_test_suite),
921                        NULL, NULL,
922                        _gcut_marshal_VOID__OBJECT_BOOLEAN,
923                        G_TYPE_NONE, 2, CUT_TYPE_TEST_SUITE, G_TYPE_BOOLEAN);
924 
925     signals[COMPLETE_RUN]
926         = g_signal_new("complete-run",
927                        G_TYPE_FROM_CLASS(klass),
928                        G_SIGNAL_RUN_LAST | G_SIGNAL_DETAILED,
929                        G_STRUCT_OFFSET(CutRunContextClass, complete_run),
930                        NULL, NULL,
931                        g_cclosure_marshal_VOID__BOOLEAN,
932                        G_TYPE_NONE, 1, G_TYPE_BOOLEAN);
933 
934     signals[ERROR]
935         = g_signal_new("error",
936                        G_TYPE_FROM_CLASS(klass),
937                        G_SIGNAL_RUN_LAST | G_SIGNAL_DETAILED,
938                        G_STRUCT_OFFSET(CutRunContextClass, error),
939                        NULL, NULL,
940                         g_cclosure_marshal_VOID__POINTER,
941                        G_TYPE_NONE, 1, G_TYPE_POINTER);
942 
943     g_type_class_add_private(gobject_class, sizeof(CutRunContextPrivate));
944 }
945 
946 static void
cut_run_context_init(CutRunContext * context)947 cut_run_context_init (CutRunContext *context)
948 {
949     CutRunContextPrivate *priv = CUT_RUN_CONTEXT_GET_PRIVATE(context);
950 
951     priv->n_tests = 0;
952     priv->n_assertions = 0;
953     priv->n_successes = 0;
954     priv->n_failures = 0;
955     priv->n_errors = 0;
956     priv->n_pendings = 0;
957     priv->n_notifications = 0;
958     priv->n_omissions = 0;
959     priv->elapsed = 0.0;
960     priv->timer = NULL;
961     priv->results = NULL;
962     priv->reversed_results = NULL;
963     priv->use_multi_thread = FALSE;
964     priv->is_multi_thread = FALSE;
965     priv->max_threads = 10;
966     priv->handle_signals = TRUE;
967     priv->mutex = g_mutex_new();
968     priv->crashed = FALSE;
969     priv->test_directory = NULL;
970     priv->source_directory = NULL;
971     priv->log_directory = NULL;
972     priv->exclude_files = NULL;
973     priv->exclude_directories = NULL;
974     priv->target_test_case_names = NULL;
975     priv->target_test_names = NULL;
976     priv->loader_customizers = NULL;
977     priv->canceled = FALSE;
978     priv->test_suite = NULL;
979     priv->listeners = NULL;
980     priv->command_line_args = NULL;
981     priv->completed = FALSE;
982     priv->fatal_failures = FALSE;
983     priv->keep_opening_modules = FALSE;
984     priv->enable_convenience_attribute_definition = FALSE;
985     priv->stop_before_test = FALSE;
986 }
987 
988 static void
remove_listener(CutListener * listener,CutRunContext * context)989 remove_listener (CutListener *listener, CutRunContext *context)
990 {
991     cut_listener_detach_from_run_context(listener, context);
992     g_object_unref(listener);
993 }
994 
995 static void
dispose(GObject * object)996 dispose (GObject *object)
997 {
998     CutRunContextPrivate *priv = CUT_RUN_CONTEXT_GET_PRIVATE(object);
999 
1000     if (priv->timer) {
1001         g_timer_destroy(priv->timer);
1002         priv->timer = NULL;
1003     }
1004 
1005     if (priv->results) {
1006         g_list_foreach(priv->results, (GFunc)g_object_unref, NULL);
1007         g_list_free(priv->results);
1008         priv->results = NULL;
1009     }
1010 
1011     if (priv->reversed_results) {
1012         g_list_free(priv->reversed_results);
1013         priv->reversed_results = NULL;
1014     }
1015 
1016     if (priv->mutex) {
1017         g_mutex_free(priv->mutex);
1018         priv->mutex = NULL;
1019     }
1020 
1021     if (priv->test_suite) {
1022         g_object_unref(priv->test_suite);
1023         priv->test_suite = NULL;
1024     }
1025 
1026     if (priv->listeners) {
1027         g_list_foreach(priv->listeners,
1028                        (GFunc)remove_listener, CUT_RUN_CONTEXT(object));
1029         g_list_free(priv->listeners);
1030         priv->listeners = NULL;
1031     }
1032 
1033     g_free(priv->backtrace);
1034     priv->backtrace = NULL;
1035 
1036     g_free(priv->source_directory);
1037     priv->source_directory = NULL;
1038 
1039     g_free(priv->log_directory);
1040     priv->log_directory = NULL;
1041 
1042     g_free(priv->test_directory);
1043     priv->test_directory = NULL;
1044 
1045     g_strfreev(priv->exclude_files);
1046     priv->exclude_files = NULL;
1047 
1048     g_strfreev(priv->exclude_directories);
1049     priv->exclude_directories = NULL;
1050 
1051     g_strfreev(priv->target_test_case_names);
1052     priv->target_test_case_names = NULL;
1053 
1054     g_strfreev(priv->target_test_names);
1055     priv->target_test_names = NULL;
1056 
1057     g_list_foreach(priv->loader_customizers, (GFunc)g_object_unref, NULL);
1058     g_list_free(priv->loader_customizers);
1059     priv->loader_customizers = NULL;
1060 
1061     g_strfreev(priv->command_line_args);
1062     priv->command_line_args = NULL;
1063 
1064     G_OBJECT_CLASS(cut_run_context_parent_class)->dispose(object);
1065 }
1066 
1067 static void
set_property(GObject * object,guint prop_id,const GValue * value,GParamSpec * pspec)1068 set_property (GObject      *object,
1069               guint         prop_id,
1070               const GValue *value,
1071               GParamSpec   *pspec)
1072 {
1073     CutRunContextPrivate *priv = CUT_RUN_CONTEXT_GET_PRIVATE(object);
1074 
1075     switch (prop_id) {
1076       case PROP_N_TESTS:
1077         priv->n_tests = g_value_get_uint(value);
1078         break;
1079       case PROP_N_ASSERTIONS:
1080         priv->n_assertions = g_value_get_uint(value);
1081         break;
1082       case PROP_N_SUCCESSES:
1083         priv->n_successes = g_value_get_uint(value);
1084         break;
1085       case PROP_N_FAILURES:
1086         priv->n_failures = g_value_get_uint(value);
1087         break;
1088       case PROP_N_ERRORS:
1089         priv->n_errors = g_value_get_uint(value);
1090         break;
1091       case PROP_N_PENDINGS:
1092         priv->n_pendings = g_value_get_uint(value);
1093         break;
1094       case PROP_N_NOTIFICATIONS:
1095         priv->n_notifications = g_value_get_uint(value);
1096         break;
1097       case PROP_N_OMISSIONS:
1098         priv->n_omissions = g_value_get_uint(value);
1099         break;
1100       case PROP_USE_MULTI_THREAD:
1101         priv->use_multi_thread = g_value_get_boolean(value);
1102         break;
1103       case PROP_IS_MULTI_THREAD:
1104         priv->is_multi_thread = g_value_get_boolean(value);
1105         break;
1106       case PROP_MAX_THREADS:
1107         priv->max_threads = g_value_get_int(value);
1108         break;
1109       case PROP_HANDLE_SIGNALS:
1110         priv->handle_signals = g_value_get_boolean(value);
1111         break;
1112       case PROP_TEST_CASE_ORDER:
1113         priv->test_case_order = g_value_get_enum(value);
1114         break;
1115       case PROP_TEST_DIRECTORY:
1116         priv->test_directory = g_value_dup_string(value);
1117         break;
1118       case PROP_SOURCE_DIRECTORY:
1119         priv->source_directory = g_value_dup_string(value);
1120         break;
1121       case PROP_LOG_DIRECTORY:
1122         priv->log_directory = g_value_dup_string(value);
1123         break;
1124       case PROP_TARGET_TEST_CASE_NAMES:
1125         priv->target_test_case_names = g_strdupv(g_value_get_pointer(value));
1126         break;
1127       case PROP_TARGET_TEST_NAMES:
1128         priv->target_test_names = g_strdupv(g_value_get_pointer(value));
1129         break;
1130       case PROP_EXCLUDE_FILES:
1131         priv->exclude_files = g_strdupv(g_value_get_pointer(value));
1132         break;
1133       case PROP_EXCLUDE_DIRECTORIES:
1134         priv->exclude_directories = g_strdupv(g_value_get_pointer(value));
1135         break;
1136       case PROP_COMMAND_LINE_ARGS:
1137         priv->command_line_args = g_strdupv(g_value_get_pointer(value));
1138         break;
1139       case PROP_FATAL_FAILURES:
1140         priv->fatal_failures = g_value_get_boolean(value);
1141         break;
1142       case PROP_KEEP_OPENING_MODULES:
1143         priv->keep_opening_modules = g_value_get_boolean(value);
1144         break;
1145       case PROP_ENABLE_CONVENIENCE_ATTRIBUTE_DEFINITION:
1146         priv->enable_convenience_attribute_definition = g_value_get_boolean(value);
1147         break;
1148       case PROP_STOP_BEFORE_TEST:
1149         priv->stop_before_test = g_value_get_boolean(value);
1150         break;
1151       default:
1152         G_OBJECT_WARN_INVALID_PROPERTY_ID(object, prop_id, pspec);
1153         break;
1154     }
1155 }
1156 
1157 static void
get_property(GObject * object,guint prop_id,GValue * value,GParamSpec * pspec)1158 get_property (GObject    *object,
1159               guint       prop_id,
1160               GValue     *value,
1161               GParamSpec *pspec)
1162 {
1163     CutRunContextPrivate *priv = CUT_RUN_CONTEXT_GET_PRIVATE(object);
1164 
1165     switch (prop_id) {
1166       case PROP_N_TESTS:
1167         g_value_set_uint(value, priv->n_tests);
1168         break;
1169       case PROP_N_ASSERTIONS:
1170         g_value_set_uint(value, priv->n_assertions);
1171         break;
1172       case PROP_N_SUCCESSES:
1173         g_value_set_uint(value, priv->n_successes);
1174         break;
1175       case PROP_N_FAILURES:
1176         g_value_set_uint(value, priv->n_failures);
1177         break;
1178       case PROP_N_ERRORS:
1179         g_value_set_uint(value, priv->n_errors);
1180         break;
1181       case PROP_N_PENDINGS:
1182         g_value_set_uint(value, priv->n_pendings);
1183         break;
1184       case PROP_N_NOTIFICATIONS:
1185         g_value_set_uint(value, priv->n_notifications);
1186         break;
1187       case PROP_N_OMISSIONS:
1188         g_value_set_uint(value, priv->n_omissions);
1189         break;
1190       case PROP_USE_MULTI_THREAD:
1191         g_value_set_boolean(value, priv->use_multi_thread);
1192         break;
1193       case PROP_IS_MULTI_THREAD:
1194         g_value_set_boolean(value, priv->is_multi_thread);
1195         break;
1196       case PROP_MAX_THREADS:
1197         g_value_set_int(value, priv->max_threads);
1198         break;
1199       case PROP_HANDLE_SIGNALS:
1200         g_value_set_boolean(value, priv->handle_signals);
1201         break;
1202       case PROP_TEST_CASE_ORDER:
1203         g_value_set_enum(value, priv->test_case_order);
1204         break;
1205       case PROP_TEST_DIRECTORY:
1206         g_value_set_string(value, priv->test_directory);
1207         break;
1208       case PROP_SOURCE_DIRECTORY:
1209         g_value_set_string(value, priv->source_directory);
1210         break;
1211       case PROP_LOG_DIRECTORY:
1212         g_value_set_string(value, priv->log_directory);
1213         break;
1214       case PROP_TARGET_TEST_CASE_NAMES:
1215         g_value_set_pointer(value, priv->target_test_case_names);
1216         break;
1217       case PROP_TARGET_TEST_NAMES:
1218         g_value_set_pointer(value, priv->target_test_names);
1219         break;
1220       case PROP_EXCLUDE_FILES:
1221         g_value_set_pointer(value, priv->exclude_files);
1222         break;
1223       case PROP_EXCLUDE_DIRECTORIES:
1224         g_value_set_pointer(value, priv->exclude_directories);
1225         break;
1226       case PROP_COMMAND_LINE_ARGS:
1227         g_value_set_pointer(value, priv->command_line_args);
1228         break;
1229       case PROP_FATAL_FAILURES:
1230         g_value_set_boolean(value, priv->fatal_failures);
1231         break;
1232       case PROP_KEEP_OPENING_MODULES:
1233         g_value_set_boolean(value, priv->keep_opening_modules);
1234         break;
1235       case PROP_ENABLE_CONVENIENCE_ATTRIBUTE_DEFINITION:
1236         g_value_set_boolean(value, priv->enable_convenience_attribute_definition);
1237         break;
1238       case PROP_STOP_BEFORE_TEST:
1239         g_value_set_boolean(value, priv->stop_before_test);
1240         break;
1241       default:
1242         G_OBJECT_WARN_INVALID_PROPERTY_ID(object, prop_id, pspec);
1243         break;
1244     }
1245 }
1246 
1247 static void
runner_init(CutRunnerIface * iface)1248 runner_init (CutRunnerIface *iface)
1249 {
1250     parent_runner_iface = g_type_interface_peek_parent(iface);
1251     iface->run = runner_run;
1252 }
1253 
1254 static gboolean
runner_run(CutRunner * runner)1255 runner_run (CutRunner *runner)
1256 {
1257     if (parent_runner_iface->run)
1258         return parent_runner_iface->run(runner);
1259 
1260     return FALSE;
1261 }
1262 
1263 static void
start_run(CutRunContext * context)1264 start_run (CutRunContext *context)
1265 {
1266     CutRunContextPrivate *priv;
1267 
1268     priv = CUT_RUN_CONTEXT_GET_PRIVATE(context);
1269     g_mutex_lock(priv->mutex);
1270     priv->completed = FALSE;
1271     if (priv->timer)
1272         g_timer_destroy(priv->timer);
1273     priv->timer = g_timer_new();
1274     g_mutex_unlock(priv->mutex);
1275 }
1276 
1277 static void
start_test(CutRunContext * context,CutTest * test,CutTestContext * test_context)1278 start_test (CutRunContext   *context,
1279             CutTest         *test,
1280             CutTestContext  *test_context)
1281 {
1282     CutRunContextPrivate *priv;
1283 
1284     priv = CUT_RUN_CONTEXT_GET_PRIVATE(context);
1285     g_mutex_lock(priv->mutex);
1286     priv->n_tests++;
1287     g_mutex_unlock(priv->mutex);
1288 }
1289 
1290 static void
start_iterated_test(CutRunContext * context,CutIteratedTest * iterated_test,CutTestContext * test_context)1291 start_iterated_test (CutRunContext   *context,
1292                      CutIteratedTest *iterated_test,
1293                      CutTestContext  *test_context)
1294 {
1295     CutRunContextPrivate *priv;
1296 
1297     priv = CUT_RUN_CONTEXT_GET_PRIVATE(context);
1298     g_mutex_lock(priv->mutex);
1299     priv->n_tests++;
1300     g_mutex_unlock(priv->mutex);
1301 }
1302 
1303 static void
pass_assertion(CutRunContext * context,CutTest * test,CutTestContext * test_context)1304 pass_assertion (CutRunContext   *context,
1305                 CutTest         *test,
1306                 CutTestContext  *test_context)
1307 {
1308     CutRunContextPrivate *priv;
1309 
1310     priv = CUT_RUN_CONTEXT_GET_PRIVATE(context);
1311     g_mutex_lock(priv->mutex);
1312     priv->n_assertions++;
1313     g_mutex_unlock(priv->mutex);
1314 }
1315 
1316 static void
register_success_result(CutRunContext * context,CutTestResult * result)1317 register_success_result (CutRunContext *context, CutTestResult *result)
1318 {
1319     CutRunContextPrivate *priv;
1320 
1321     priv = CUT_RUN_CONTEXT_GET_PRIVATE(context);
1322     g_mutex_lock(priv->mutex);
1323     priv->results = g_list_prepend(priv->results, g_object_ref(result));
1324     priv->n_successes++;
1325     g_mutex_unlock(priv->mutex);
1326 }
1327 
1328 static void
register_failure_result(CutRunContext * context,CutTestResult * result)1329 register_failure_result (CutRunContext *context, CutTestResult *result)
1330 {
1331     CutRunContextPrivate *priv = CUT_RUN_CONTEXT_GET_PRIVATE(context);
1332 
1333     g_mutex_lock(priv->mutex);
1334     priv->results = g_list_prepend(priv->results, g_object_ref(result));
1335     priv->n_failures++;
1336     g_mutex_unlock(priv->mutex);
1337 }
1338 
1339 static void
register_error_result(CutRunContext * context,CutTestResult * result)1340 register_error_result (CutRunContext *context, CutTestResult *result)
1341 {
1342     CutRunContextPrivate *priv;
1343 
1344     priv = CUT_RUN_CONTEXT_GET_PRIVATE(context);
1345     g_mutex_lock(priv->mutex);
1346     priv->results = g_list_prepend(priv->results, g_object_ref(result));
1347     priv->n_errors++;
1348     g_mutex_unlock(priv->mutex);
1349 }
1350 
1351 static void
register_pending_result(CutRunContext * context,CutTestResult * result)1352 register_pending_result (CutRunContext *context, CutTestResult *result)
1353 {
1354     CutRunContextPrivate *priv;
1355 
1356     priv = CUT_RUN_CONTEXT_GET_PRIVATE(context);
1357     g_mutex_lock(priv->mutex);
1358     priv->results = g_list_prepend(priv->results, g_object_ref(result));
1359     priv->n_pendings++;
1360     g_mutex_unlock(priv->mutex);
1361 }
1362 
1363 static void
register_notification_result(CutRunContext * context,CutTestResult * result)1364 register_notification_result (CutRunContext  *context, CutTestResult *result)
1365 {
1366     CutRunContextPrivate *priv;
1367 
1368     priv = CUT_RUN_CONTEXT_GET_PRIVATE(context);
1369     g_mutex_lock(priv->mutex);
1370     priv->results = g_list_prepend(priv->results, g_object_ref(result));
1371     priv->n_notifications++;
1372     g_mutex_unlock(priv->mutex);
1373 }
1374 
1375 static void
register_omission_result(CutRunContext * context,CutTestResult * result)1376 register_omission_result (CutRunContext *context, CutTestResult *result)
1377 {
1378     CutRunContextPrivate *priv;
1379 
1380     priv = CUT_RUN_CONTEXT_GET_PRIVATE(context);
1381     g_mutex_lock(priv->mutex);
1382     priv->results = g_list_prepend(priv->results, g_object_ref(result));
1383     priv->n_omissions++;
1384     g_mutex_unlock(priv->mutex);
1385 }
1386 
1387 static void
register_crash_result(CutRunContext * context,CutTestResult * result)1388 register_crash_result (CutRunContext *context, CutTestResult *result)
1389 {
1390     CutRunContextPrivate *priv;
1391 
1392     priv = CUT_RUN_CONTEXT_GET_PRIVATE(context);
1393     priv->crashed = TRUE;
1394     g_mutex_lock(priv->mutex);
1395     priv->results = g_list_prepend(priv->results, g_object_ref(result));
1396     g_mutex_unlock(priv->mutex);
1397 }
1398 
1399 static void
success_test(CutRunContext * context,CutTest * test,CutTestContext * test_context,CutTestResult * result)1400 success_test (CutRunContext   *context,
1401               CutTest         *test,
1402               CutTestContext  *test_context,
1403               CutTestResult   *result)
1404 {
1405     register_success_result(context, result);
1406 }
1407 
1408 static void
failure_test(CutRunContext * context,CutTest * test,CutTestContext * test_context,CutTestResult * result)1409 failure_test (CutRunContext   *context,
1410               CutTest         *test,
1411               CutTestContext  *test_context,
1412               CutTestResult   *result)
1413 {
1414     register_failure_result(context, result);
1415 }
1416 
1417 static void
error_test(CutRunContext * context,CutTest * test,CutTestContext * test_context,CutTestResult * result)1418 error_test (CutRunContext   *context,
1419             CutTest         *test,
1420             CutTestContext  *test_context,
1421             CutTestResult   *result)
1422 {
1423     register_error_result(context, result);
1424 }
1425 
1426 static void
pending_test(CutRunContext * context,CutTest * test,CutTestContext * test_context,CutTestResult * result)1427 pending_test (CutRunContext   *context,
1428               CutTest         *test,
1429               CutTestContext  *test_context,
1430               CutTestResult   *result)
1431 {
1432     register_pending_result(context, result);
1433 }
1434 
1435 static void
notification_test(CutRunContext * context,CutTest * test,CutTestContext * test_context,CutTestResult * result)1436 notification_test (CutRunContext   *context,
1437                    CutTest         *test,
1438                    CutTestContext  *test_context,
1439                    CutTestResult   *result)
1440 {
1441     register_notification_result(context, result);
1442 }
1443 
1444 static void
omission_test(CutRunContext * context,CutTest * test,CutTestContext * test_context,CutTestResult * result)1445 omission_test (CutRunContext   *context,
1446                CutTest         *test,
1447                CutTestContext  *test_context,
1448                CutTestResult   *result)
1449 {
1450     register_omission_result(context, result);
1451 }
1452 
1453 static void
crash_test(CutRunContext * context,CutTest * test,CutTestContext * test_context,CutTestResult * result)1454 crash_test (CutRunContext   *context,
1455             CutTest         *test,
1456             CutTestContext  *test_context,
1457             CutTestResult   *result)
1458 {
1459     register_crash_result(context, result);
1460 }
1461 
1462 static void
failure_in_test_case(CutRunContext * context,CutTestCase * test,CutTestResult * result)1463 failure_in_test_case (CutRunContext   *context,
1464                       CutTestCase     *test,
1465                       CutTestResult   *result)
1466 {
1467     register_failure_result(context, result);
1468 }
1469 
1470 static void
error_in_test_case(CutRunContext * context,CutTestCase * test,CutTestResult * result)1471 error_in_test_case (CutRunContext   *context,
1472                     CutTestCase     *test,
1473                     CutTestResult   *result)
1474 {
1475     register_error_result(context, result);
1476 }
1477 
1478 static void
pending_in_test_case(CutRunContext * context,CutTestCase * test,CutTestResult * result)1479 pending_in_test_case (CutRunContext   *context,
1480                       CutTestCase     *test,
1481                       CutTestResult   *result)
1482 {
1483     register_pending_result(context, result);
1484 }
1485 
1486 static void
notification_in_test_case(CutRunContext * context,CutTestCase * test,CutTestResult * result)1487 notification_in_test_case (CutRunContext   *context,
1488                            CutTestCase     *test,
1489                            CutTestResult   *result)
1490 {
1491     register_notification_result(context, result);
1492 }
1493 
1494 static void
omission_in_test_case(CutRunContext * context,CutTestCase * test,CutTestResult * result)1495 omission_in_test_case (CutRunContext   *context,
1496                        CutTestCase     *test,
1497                        CutTestResult   *result)
1498 {
1499     register_omission_result(context, result);
1500 }
1501 
1502 static void
crash_in_test_case(CutRunContext * context,CutTestCase * test,CutTestResult * result)1503 crash_in_test_case (CutRunContext   *context,
1504                     CutTestCase     *test,
1505                     CutTestResult   *result)
1506 {
1507     register_crash_result(context, result);
1508 }
1509 
1510 static void
crash_test_suite(CutRunContext * context,CutTestSuite * test_suite,CutTestResult * result)1511 crash_test_suite (CutRunContext   *context,
1512                   CutTestSuite    *test_suite,
1513                   CutTestResult   *result)
1514 {
1515     register_crash_result(context, result);
1516 }
1517 
1518 static void
complete_iterated_test(CutRunContext * context,CutIteratedTest * iterated_test,CutTestContext * test_context,gboolean success)1519 complete_iterated_test (CutRunContext   *context,
1520                         CutIteratedTest *iterated_test,
1521                         CutTestContext  *test_context,
1522                         gboolean         success)
1523 {
1524     CutRunContextPrivate *priv;
1525 
1526     priv = CUT_RUN_CONTEXT_GET_PRIVATE(context);
1527     g_mutex_lock(priv->mutex);
1528     priv->elapsed += cut_test_get_elapsed(CUT_TEST(iterated_test));
1529     g_mutex_unlock(priv->mutex);
1530 }
1531 
1532 static void
complete_test(CutRunContext * context,CutTest * test,CutTestContext * test_context,gboolean success)1533 complete_test (CutRunContext   *context,
1534                CutTest         *test,
1535                CutTestContext  *test_context,
1536                gboolean         success)
1537 {
1538     CutRunContextPrivate *priv;
1539 
1540     priv = CUT_RUN_CONTEXT_GET_PRIVATE(context);
1541     g_mutex_lock(priv->mutex);
1542     priv->elapsed += cut_test_get_elapsed(test);
1543     g_mutex_unlock(priv->mutex);
1544 }
1545 
1546 static void
complete_run(CutRunContext * context,gboolean success)1547 complete_run (CutRunContext *context, gboolean success)
1548 {
1549     CutRunContextPrivate *priv;
1550 
1551     priv = CUT_RUN_CONTEXT_GET_PRIVATE(context);
1552     g_mutex_lock(priv->mutex);
1553     if (priv->timer)
1554         g_timer_stop(priv->timer);
1555     priv->completed = TRUE;
1556     g_mutex_unlock(priv->mutex);
1557 }
1558 
1559 
1560 void
cut_run_context_set_test_directory(CutRunContext * context,const gchar * directory)1561 cut_run_context_set_test_directory (CutRunContext *context,
1562                                     const gchar *directory)
1563 {
1564     CutRunContextPrivate *priv = CUT_RUN_CONTEXT_GET_PRIVATE(context);
1565 
1566     g_free(priv->test_directory);
1567     priv->test_directory = g_strdup(directory);
1568 }
1569 
1570 const gchar *
cut_run_context_get_test_directory(CutRunContext * context)1571 cut_run_context_get_test_directory (CutRunContext *context)
1572 {
1573     return CUT_RUN_CONTEXT_GET_PRIVATE(context)->test_directory;
1574 }
1575 
1576 void
cut_run_context_set_source_directory(CutRunContext * context,const gchar * directory)1577 cut_run_context_set_source_directory (CutRunContext *context,
1578                                       const gchar *directory)
1579 {
1580     CutRunContextPrivate *priv = CUT_RUN_CONTEXT_GET_PRIVATE(context);
1581 
1582     g_free(priv->source_directory);
1583     priv->source_directory = g_strdup(directory);
1584 }
1585 
1586 const gchar *
cut_run_context_get_source_directory(CutRunContext * context)1587 cut_run_context_get_source_directory (CutRunContext *context)
1588 {
1589     return CUT_RUN_CONTEXT_GET_PRIVATE(context)->source_directory;
1590 }
1591 
1592 void
cut_run_context_set_log_directory(CutRunContext * context,const gchar * directory)1593 cut_run_context_set_log_directory (CutRunContext *context,
1594                                    const gchar *directory)
1595 {
1596     CutRunContextPrivate *priv = CUT_RUN_CONTEXT_GET_PRIVATE(context);
1597 
1598     g_free(priv->log_directory);
1599     priv->log_directory = g_strdup(directory);
1600 }
1601 
1602 const gchar *
cut_run_context_get_log_directory(CutRunContext * context)1603 cut_run_context_get_log_directory (CutRunContext *context)
1604 {
1605     return CUT_RUN_CONTEXT_GET_PRIVATE(context)->log_directory;
1606 }
1607 
1608 void
cut_run_context_set_multi_thread(CutRunContext * context,gboolean use_multi_thread)1609 cut_run_context_set_multi_thread (CutRunContext *context,
1610                                   gboolean use_multi_thread)
1611 {
1612     CutRunContextPrivate *priv = CUT_RUN_CONTEXT_GET_PRIVATE(context);
1613 
1614     g_mutex_lock(priv->mutex);
1615     priv->use_multi_thread = use_multi_thread;
1616     if (use_multi_thread)
1617         priv->is_multi_thread = TRUE;
1618     g_mutex_unlock(priv->mutex);
1619 }
1620 
1621 gboolean
cut_run_context_get_multi_thread(CutRunContext * context)1622 cut_run_context_get_multi_thread (CutRunContext *context)
1623 {
1624     return CUT_RUN_CONTEXT_GET_PRIVATE(context)->use_multi_thread;
1625 }
1626 
1627 gboolean
cut_run_context_is_multi_thread(CutRunContext * context)1628 cut_run_context_is_multi_thread (CutRunContext *context)
1629 {
1630     return CUT_RUN_CONTEXT_GET_PRIVATE(context)->is_multi_thread;
1631 }
1632 
1633 void
cut_run_context_set_max_threads(CutRunContext * context,gint max_threads)1634 cut_run_context_set_max_threads (CutRunContext *context, gint max_threads)
1635 {
1636     CutRunContextPrivate *priv = CUT_RUN_CONTEXT_GET_PRIVATE(context);
1637 
1638     priv->max_threads = max_threads;
1639 }
1640 
1641 gint
cut_run_context_get_max_threads(CutRunContext * context)1642 cut_run_context_get_max_threads (CutRunContext *context)
1643 {
1644     return CUT_RUN_CONTEXT_GET_PRIVATE(context)->max_threads;
1645 }
1646 
1647 void
cut_run_context_set_handle_signals(CutRunContext * context,gboolean handle_signals)1648 cut_run_context_set_handle_signals (CutRunContext *context,
1649                                     gboolean handle_signals)
1650 {
1651     CUT_RUN_CONTEXT_GET_PRIVATE(context)->handle_signals = handle_signals;
1652 }
1653 
1654 gboolean
cut_run_context_get_handle_signals(CutRunContext * context)1655 cut_run_context_get_handle_signals (CutRunContext *context)
1656 {
1657     return CUT_RUN_CONTEXT_GET_PRIVATE(context)->handle_signals;
1658 }
1659 
1660 void
cut_run_context_set_exclude_files(CutRunContext * context,const gchar ** files)1661 cut_run_context_set_exclude_files (CutRunContext *context, const gchar **files)
1662 {
1663     CutRunContextPrivate *priv = CUT_RUN_CONTEXT_GET_PRIVATE(context);
1664 
1665     g_strfreev(priv->exclude_files);
1666     priv->exclude_files = g_strdupv((gchar **)files);
1667 }
1668 
1669 const gchar **
cut_run_context_get_exclude_files(CutRunContext * context)1670 cut_run_context_get_exclude_files (CutRunContext *context)
1671 {
1672     CutRunContextPrivate *priv = CUT_RUN_CONTEXT_GET_PRIVATE(context);
1673     return (const gchar **)priv->exclude_files;
1674 }
1675 
1676 void
cut_run_context_set_exclude_directories(CutRunContext * context,const gchar ** directories)1677 cut_run_context_set_exclude_directories (CutRunContext *context,
1678                                          const gchar **directories)
1679 {
1680     CutRunContextPrivate *priv = CUT_RUN_CONTEXT_GET_PRIVATE(context);
1681 
1682     g_strfreev(priv->exclude_directories);
1683     priv->exclude_directories = g_strdupv((gchar **)directories);
1684 }
1685 
1686 const gchar **
cut_run_context_get_exclude_directories(CutRunContext * context)1687 cut_run_context_get_exclude_directories (CutRunContext *context)
1688 {
1689     CutRunContextPrivate *priv = CUT_RUN_CONTEXT_GET_PRIVATE(context);
1690     return (const gchar **)priv->exclude_directories;
1691 }
1692 
1693 void
cut_run_context_set_target_test_case_names(CutRunContext * context,const gchar ** names)1694 cut_run_context_set_target_test_case_names (CutRunContext *context,
1695                                             const gchar **names)
1696 {
1697     CutRunContextPrivate *priv = CUT_RUN_CONTEXT_GET_PRIVATE(context);
1698 
1699     g_strfreev(priv->target_test_case_names);
1700     priv->target_test_case_names = g_strdupv((gchar **)names);
1701 }
1702 
1703 const gchar **
cut_run_context_get_target_test_case_names(CutRunContext * context)1704 cut_run_context_get_target_test_case_names (CutRunContext *context)
1705 {
1706     CutRunContextPrivate *priv = CUT_RUN_CONTEXT_GET_PRIVATE(context);
1707     return (const gchar **)priv->target_test_case_names;
1708 }
1709 
1710 void
cut_run_context_set_target_test_names(CutRunContext * context,const gchar ** names)1711 cut_run_context_set_target_test_names (CutRunContext *context,
1712                                        const gchar **names)
1713 {
1714     CutRunContextPrivate *priv = CUT_RUN_CONTEXT_GET_PRIVATE(context);
1715 
1716     g_strfreev(priv->target_test_names);
1717     priv->target_test_names = g_strdupv((gchar **)names);
1718 }
1719 
1720 const gchar **
cut_run_context_get_target_test_names(CutRunContext * context)1721 cut_run_context_get_target_test_names (CutRunContext *context)
1722 {
1723     CutRunContextPrivate *priv = CUT_RUN_CONTEXT_GET_PRIVATE(context);
1724     return (const gchar **)priv->target_test_names;
1725 }
1726 
1727 void
cut_run_context_add_loader_customizer(CutRunContext * context,CutLoaderCustomizer * customizer)1728 cut_run_context_add_loader_customizer (CutRunContext *context,
1729                                        CutLoaderCustomizer *customizer)
1730 {
1731     CutRunContextPrivate *priv = CUT_RUN_CONTEXT_GET_PRIVATE(context);
1732 
1733     g_object_ref(customizer);
1734     priv->loader_customizers = g_list_append(priv->loader_customizers,
1735                                              customizer);
1736 }
1737 
1738 const GList *
cut_run_context_get_loader_customizers(CutRunContext * context)1739 cut_run_context_get_loader_customizers (CutRunContext *context)
1740 {
1741     CutRunContextPrivate *priv = CUT_RUN_CONTEXT_GET_PRIVATE(context);
1742     return priv->loader_customizers;
1743 }
1744 
1745 guint
cut_run_context_get_n_tests(CutRunContext * context)1746 cut_run_context_get_n_tests (CutRunContext *context)
1747 {
1748     return CUT_RUN_CONTEXT_GET_PRIVATE(context)->n_tests;
1749 }
1750 
1751 guint
cut_run_context_get_n_assertions(CutRunContext * context)1752 cut_run_context_get_n_assertions (CutRunContext *context)
1753 {
1754     return CUT_RUN_CONTEXT_GET_PRIVATE(context)->n_assertions;
1755 }
1756 
1757 guint
cut_run_context_get_n_successes(CutRunContext * context)1758 cut_run_context_get_n_successes (CutRunContext *context)
1759 {
1760     return CUT_RUN_CONTEXT_GET_PRIVATE(context)->n_successes;
1761 }
1762 
1763 guint
cut_run_context_get_n_failures(CutRunContext * context)1764 cut_run_context_get_n_failures (CutRunContext *context)
1765 {
1766     return CUT_RUN_CONTEXT_GET_PRIVATE(context)->n_failures;
1767 }
1768 
1769 guint
cut_run_context_get_n_errors(CutRunContext * context)1770 cut_run_context_get_n_errors (CutRunContext *context)
1771 {
1772     return CUT_RUN_CONTEXT_GET_PRIVATE(context)->n_errors;
1773 }
1774 
1775 guint
cut_run_context_get_n_pendings(CutRunContext * context)1776 cut_run_context_get_n_pendings (CutRunContext *context)
1777 {
1778     return CUT_RUN_CONTEXT_GET_PRIVATE(context)->n_pendings;
1779 }
1780 
1781 guint
cut_run_context_get_n_notifications(CutRunContext * context)1782 cut_run_context_get_n_notifications (CutRunContext *context)
1783 {
1784     return CUT_RUN_CONTEXT_GET_PRIVATE(context)->n_notifications;
1785 }
1786 
1787 guint
cut_run_context_get_n_omissions(CutRunContext * context)1788 cut_run_context_get_n_omissions (CutRunContext *context)
1789 {
1790     return CUT_RUN_CONTEXT_GET_PRIVATE(context)->n_omissions;
1791 }
1792 
1793 CutTestResultStatus
cut_run_context_get_status(CutRunContext * context)1794 cut_run_context_get_status (CutRunContext *context)
1795 {
1796     CutRunContextPrivate *priv;
1797     CutTestResultStatus status;
1798 
1799     priv = CUT_RUN_CONTEXT_GET_PRIVATE(context);
1800 
1801     if (priv->crashed) {
1802         status = CUT_TEST_RESULT_CRASH;
1803     } else if (priv->n_errors > 0) {
1804         status = CUT_TEST_RESULT_ERROR;
1805     } else if (priv->n_failures > 0) {
1806         status = CUT_TEST_RESULT_FAILURE;
1807     } else if (priv->n_pendings > 0) {
1808         status = CUT_TEST_RESULT_PENDING;
1809     } else if (priv->n_omissions > 0) {
1810         status = CUT_TEST_RESULT_OMISSION;
1811     } else if (priv->n_notifications > 0) {
1812         status = CUT_TEST_RESULT_NOTIFICATION;
1813     } else {
1814         status = CUT_TEST_RESULT_SUCCESS;
1815     }
1816 
1817     return status;
1818 }
1819 
1820 gdouble
cut_run_context_get_elapsed(CutRunContext * context)1821 cut_run_context_get_elapsed (CutRunContext *context)
1822 {
1823     CutRunContextPrivate *priv;
1824 
1825     priv = CUT_RUN_CONTEXT_GET_PRIVATE(context);
1826     if (priv->timer)
1827         return g_timer_elapsed(priv->timer, NULL);
1828     else
1829         return 0.0;
1830 }
1831 
1832 gdouble
cut_run_context_get_total_elapsed(CutRunContext * context)1833 cut_run_context_get_total_elapsed (CutRunContext *context)
1834 {
1835     return CUT_RUN_CONTEXT_GET_PRIVATE(context)->elapsed;
1836 }
1837 
1838 const GList *
cut_run_context_get_results(CutRunContext * context)1839 cut_run_context_get_results (CutRunContext *context)
1840 {
1841     CutRunContextPrivate *priv;
1842 
1843     priv = CUT_RUN_CONTEXT_GET_PRIVATE(context);
1844     if (priv->reversed_results)
1845         g_list_free(priv->reversed_results);
1846 
1847     priv->reversed_results = g_list_reverse(g_list_copy(priv->results));
1848     return priv->reversed_results;
1849 }
1850 
1851 gboolean
cut_run_context_is_crashed(CutRunContext * context)1852 cut_run_context_is_crashed (CutRunContext *context)
1853 {
1854     return CUT_RUN_CONTEXT_GET_PRIVATE(context)->crashed;
1855 }
1856 
1857 void
cut_run_context_cancel(CutRunContext * context)1858 cut_run_context_cancel (CutRunContext *context)
1859 {
1860     CUT_RUN_CONTEXT_GET_PRIVATE(context)->canceled = TRUE;
1861 }
1862 
1863 gboolean
cut_run_context_is_canceled(CutRunContext * context)1864 cut_run_context_is_canceled (CutRunContext *context)
1865 {
1866     CutRunContextPrivate *priv;
1867 
1868     priv = CUT_RUN_CONTEXT_GET_PRIVATE(context);
1869     return priv->canceled || priv->crashed;
1870 }
1871 
1872 CutTestSuite *
cut_run_context_create_test_suite(CutRunContext * context)1873 cut_run_context_create_test_suite (CutRunContext *context)
1874 {
1875     CutRunContextPrivate *priv;
1876     CutRepository *repository;
1877     CutTestSuite *suite;
1878     const gchar **exclude_files, **exclude_directories;
1879     GList *node;
1880 
1881     priv = CUT_RUN_CONTEXT_GET_PRIVATE(context);
1882     repository = cut_repository_new(priv->test_directory);
1883     cut_repository_set_keep_opening_modules(repository,
1884                                             priv->keep_opening_modules);
1885     cut_repository_set_enable_convenience_attribute_definition(repository,
1886                                                                priv->enable_convenience_attribute_definition);
1887     exclude_files = (const gchar **)priv->exclude_files;
1888     cut_repository_set_exclude_files(repository, exclude_files);
1889     exclude_directories = (const gchar **)priv->exclude_directories;
1890     cut_repository_set_exclude_directories(repository, exclude_directories);
1891     for (node = priv->loader_customizers; node; node = g_list_next(node)) {
1892         CutLoaderCustomizer *customizer = node->data;
1893         cut_repository_add_loader_customizer(repository, customizer);
1894     }
1895 
1896     suite = cut_repository_create_test_suite(repository);
1897     g_object_unref(repository);
1898 
1899     return suite;
1900 }
1901 
1902 CutTestSuite *
cut_run_context_get_test_suite(CutRunContext * context)1903 cut_run_context_get_test_suite (CutRunContext *context)
1904 {
1905     CutRunContextPrivate *priv;
1906 
1907     priv = CUT_RUN_CONTEXT_GET_PRIVATE(context);
1908     if (!priv->test_suite)
1909         priv->test_suite = cut_run_context_create_test_suite(context);
1910 
1911     return priv->test_suite;
1912 }
1913 
1914 void
cut_run_context_set_test_suite(CutRunContext * context,CutTestSuite * suite)1915 cut_run_context_set_test_suite (CutRunContext *context, CutTestSuite *suite)
1916 {
1917     CutRunContextPrivate *priv;
1918 
1919     priv = CUT_RUN_CONTEXT_GET_PRIVATE(context);
1920     if (priv->test_suite)
1921         g_object_unref(priv->test_suite);
1922 
1923     if (suite)
1924         g_object_ref(suite);
1925     priv->test_suite = suite;
1926 }
1927 
1928 void
cut_run_context_add_listener(CutRunContext * context,CutListener * listener)1929 cut_run_context_add_listener (CutRunContext *context, CutListener *listener)
1930 {
1931     CutRunContextPrivate *priv = CUT_RUN_CONTEXT_GET_PRIVATE(context);
1932 
1933     priv->listeners = g_list_prepend(priv->listeners, g_object_ref(listener));
1934 }
1935 
1936 void
cut_run_context_remove_listener(CutRunContext * context,CutListener * listener)1937 cut_run_context_remove_listener (CutRunContext *context, CutListener *listener)
1938 {
1939     CutRunContextPrivate *priv = CUT_RUN_CONTEXT_GET_PRIVATE(context);
1940     priv->listeners = g_list_remove(priv->listeners, listener);
1941     remove_listener(listener, context);
1942 }
1943 
1944 static void
attach_listener(CutListener * listener,CutRunContext * context)1945 attach_listener (CutListener *listener, CutRunContext *context)
1946 {
1947     cut_listener_attach_to_run_context(listener, context);
1948 }
1949 
1950 void
cut_run_context_attach_listeners(CutRunContext * context)1951 cut_run_context_attach_listeners (CutRunContext *context)
1952 {
1953     CutRunContextPrivate *priv = CUT_RUN_CONTEXT_GET_PRIVATE(context);
1954 
1955     g_list_foreach(priv->listeners, (GFunc)attach_listener, context);
1956 }
1957 
1958 static void
detach_listener(CutListener * listener,CutRunContext * context)1959 detach_listener (CutListener *listener, CutRunContext *context)
1960 {
1961     cut_listener_detach_from_run_context(listener, context);
1962 }
1963 
1964 void
cut_run_context_detach_listeners(CutRunContext * context)1965 cut_run_context_detach_listeners (CutRunContext *context)
1966 {
1967     CutRunContextPrivate *priv = CUT_RUN_CONTEXT_GET_PRIVATE(context);
1968 
1969     g_list_foreach(priv->listeners, (GFunc)detach_listener, context);
1970 }
1971 
1972 gchar *
cut_run_context_build_source_filename(CutRunContext * context,const gchar * filename)1973 cut_run_context_build_source_filename (CutRunContext *context,
1974                                        const gchar *filename)
1975 {
1976     const gchar *source_directory;
1977     gchar *source_filename;
1978 
1979     source_directory = cut_run_context_get_source_directory(context);
1980     if (source_directory) {
1981         source_filename = g_build_filename(source_directory,
1982                                            filename,
1983                                            NULL);
1984     } else {
1985         source_filename = g_strdup(filename);
1986     }
1987     return source_filename;
1988 }
1989 
1990 void
cut_run_context_set_test_case_order(CutRunContext * context,CutOrder order)1991 cut_run_context_set_test_case_order (CutRunContext *context, CutOrder order)
1992 {
1993     CutRunContextPrivate *priv;
1994 
1995     priv = CUT_RUN_CONTEXT_GET_PRIVATE(context);
1996     g_mutex_lock(priv->mutex);
1997     priv->test_case_order = order;
1998     g_mutex_unlock(priv->mutex);
1999 }
2000 
2001 CutOrder
cut_run_context_get_test_case_order(CutRunContext * context)2002 cut_run_context_get_test_case_order (CutRunContext *context)
2003 {
2004     return CUT_RUN_CONTEXT_GET_PRIVATE(context)->test_case_order;
2005 }
2006 
2007 static gint
compare_test_cases_by_name(gconstpointer a,gconstpointer b,gpointer user_data)2008 compare_test_cases_by_name (gconstpointer a, gconstpointer b, gpointer user_data)
2009 {
2010     CutTestCase *test_case1, *test_case2;
2011     const gchar *test_case_name1, *test_case_name2;
2012     gboolean ascending;
2013 
2014     test_case1 = CUT_TEST_CASE(a);
2015     test_case2 = CUT_TEST_CASE(b);
2016     test_case_name1 = cut_test_get_name(CUT_TEST(test_case1));
2017     test_case_name2 = cut_test_get_name(CUT_TEST(test_case2));
2018     ascending = *(gboolean *)user_data;
2019 
2020     if (ascending)
2021         return strcmp(test_case_name1, test_case_name2);
2022     else
2023         return strcmp(test_case_name2, test_case_name1);
2024 }
2025 
2026 GList *
cut_run_context_sort_test_cases(CutRunContext * context,GList * test_cases)2027 cut_run_context_sort_test_cases (CutRunContext *context, GList *test_cases)
2028 {
2029     CutRunContextPrivate *priv;
2030     GList *sorted_test_cases = NULL;
2031     gboolean ascending;
2032 
2033     priv = CUT_RUN_CONTEXT_GET_PRIVATE(context);
2034     switch (priv->test_case_order) {
2035       case CUT_ORDER_NONE_SPECIFIED:
2036         sorted_test_cases = test_cases;
2037         break;
2038       case CUT_ORDER_NAME_ASCENDING:
2039         ascending = TRUE;
2040         sorted_test_cases = g_list_sort_with_data(test_cases,
2041                                                   compare_test_cases_by_name,
2042                                                   &ascending);
2043         break;
2044       case CUT_ORDER_NAME_DESCENDING:
2045         ascending = FALSE;
2046         sorted_test_cases = g_list_sort_with_data(test_cases,
2047                                                   compare_test_cases_by_name,
2048                                                   &ascending);
2049         break;
2050     }
2051 
2052     return sorted_test_cases;
2053 }
2054 
2055 gboolean
cut_run_context_start(CutRunContext * context)2056 cut_run_context_start (CutRunContext *context)
2057 {
2058     gboolean success;
2059 
2060     CUT_RUN_CONTEXT_GET_PRIVATE(context)->elapsed = 0.0;
2061     cut_run_context_attach_listeners(context);
2062     success = cut_runner_run(CUT_RUNNER(context));
2063     cut_run_context_detach_listeners(context);
2064 
2065     return success;
2066 }
2067 
2068 static void
cb_complete_run(CutRunContext * context,gboolean success,gpointer user_data)2069 cb_complete_run (CutRunContext *context, gboolean success, gpointer user_data)
2070 {
2071     g_signal_handlers_disconnect_by_func(context,
2072                                          G_CALLBACK(cb_complete_run),
2073                                          user_data);
2074     cut_run_context_detach_listeners(context);
2075 }
2076 
2077 void
cut_run_context_start_async(CutRunContext * context)2078 cut_run_context_start_async (CutRunContext *context)
2079 {
2080     CUT_RUN_CONTEXT_GET_PRIVATE(context)->elapsed = 0.0;
2081     cut_run_context_attach_listeners(context);
2082     g_signal_connect(context, "complete-run", G_CALLBACK(cb_complete_run), NULL);
2083     cut_runner_run_async(CUT_RUNNER(context));
2084 }
2085 
2086 gboolean
cut_run_context_emit_complete_run(CutRunContext * context,gboolean success)2087 cut_run_context_emit_complete_run (CutRunContext *context, gboolean success)
2088 {
2089     CutTestResultStatus status;
2090 
2091     status = cut_run_context_get_status(context);
2092     if (cut_test_result_status_is_critical(status))
2093         success = FALSE;
2094     g_signal_emit_by_name(context, "complete-run", success);
2095 
2096     return success;
2097 }
2098 
2099 void
cut_run_context_emit_error(CutRunContext * context,GQuark domain,gint code,GError * sub_error,const gchar * format,...)2100 cut_run_context_emit_error (CutRunContext *context,
2101                             GQuark         domain,
2102                             gint           code,
2103                             GError        *sub_error,
2104                             const gchar   *format,
2105                             ...)
2106 {
2107     GString *message;
2108     va_list var_args;
2109     GError *error = NULL;
2110 
2111     message = g_string_new(NULL);
2112 
2113     va_start(var_args, format);
2114     g_string_append_vprintf(message, format, var_args);
2115     va_end(var_args);
2116 
2117     if (sub_error) {
2118         g_string_append_printf(message,
2119                                ": %s:%d",
2120                                g_quark_to_string(sub_error->domain),
2121                                sub_error->code);
2122         if (sub_error->message)
2123             g_string_append_printf(message, ": %s", sub_error->message);
2124 
2125         g_error_free(sub_error);
2126     }
2127 
2128     g_set_error_literal(&error, domain, code, message->str);
2129     g_string_free(message, TRUE);
2130     g_signal_emit(context, signals[ERROR], 0, error);
2131 
2132     g_error_free(error);
2133 }
2134 
2135 void
cut_run_context_set_command_line_args(CutRunContext * context,gchar ** args)2136 cut_run_context_set_command_line_args (CutRunContext *context, gchar **args)
2137 {
2138     CutRunContextPrivate *priv = CUT_RUN_CONTEXT_GET_PRIVATE(context);
2139 
2140     g_strfreev(priv->command_line_args);
2141     priv->command_line_args = g_strdupv(args);
2142 }
2143 
2144 const gchar **
cut_run_context_get_command_line_args(CutRunContext * context)2145 cut_run_context_get_command_line_args (CutRunContext *context)
2146 {
2147     CutRunContextPrivate *priv = CUT_RUN_CONTEXT_GET_PRIVATE(context);
2148     return (const gchar **)priv->command_line_args;
2149 }
2150 
2151 static void
cb_delegate_ready_test_case(CutRunContext * context,CutTestCase * test_case,guint n_tests,gpointer user_data)2152 cb_delegate_ready_test_case (CutRunContext *context, CutTestCase *test_case,
2153                              guint n_tests, gpointer user_data)
2154 {
2155     CutRunContext *other_context = user_data;
2156     g_signal_emit(other_context, signals[READY_TEST_CASE], detail_delegate,
2157                   test_case, n_tests);
2158 }
2159 
2160 static void
cb_delegate_start_test_case(CutRunContext * context,CutTestCase * test_case,gpointer user_data)2161 cb_delegate_start_test_case (CutRunContext *context, CutTestCase *test_case,
2162                              gpointer user_data)
2163 {
2164     CutRunContext *other_context = user_data;
2165     g_signal_emit(other_context, signals[START_TEST_CASE], detail_delegate,
2166                   test_case);
2167 }
2168 
2169 static void
cb_delegate_ready_test_iterator(CutRunContext * context,CutTestIterator * test_iterator,guint n_tests,gpointer user_data)2170 cb_delegate_ready_test_iterator (CutRunContext *context,
2171                                  CutTestIterator *test_iterator,
2172                                  guint n_tests,
2173                                  gpointer user_data)
2174 {
2175     CutRunContext *other_context = user_data;
2176     g_signal_emit(other_context, signals[READY_TEST_ITERATOR], detail_delegate,
2177                   test_iterator, n_tests);
2178 }
2179 
2180 static void
cb_delegate_start_test_iterator(CutRunContext * context,CutTestIterator * test_iterator,gpointer user_data)2181 cb_delegate_start_test_iterator (CutRunContext *context,
2182                                  CutTestIterator *test_iterator,
2183                                  gpointer user_data)
2184 {
2185     CutRunContext *other_context = user_data;
2186     g_signal_emit(other_context, signals[START_TEST_ITERATOR], detail_delegate,
2187                   test_iterator);
2188 }
2189 
2190 
2191 static void
cb_delegate_start_test(CutRunContext * context,CutTest * test,CutTestContext * test_context,gpointer user_data)2192 cb_delegate_start_test (CutRunContext *context,
2193                         CutTest *test, CutTestContext *test_context,
2194                         gpointer user_data)
2195 {
2196     CutRunContext *other_context = user_data;
2197     g_signal_emit(other_context, signals[START_TEST], detail_delegate,
2198                   test, test_context);
2199 }
2200 
2201 static void
cb_delegate_start_iterated_test(CutRunContext * context,CutIteratedTest * iterated_test,CutTestContext * test_context,gpointer user_data)2202 cb_delegate_start_iterated_test (CutRunContext *context,
2203                                  CutIteratedTest *iterated_test,
2204                                  CutTestContext *test_context,
2205                                  gpointer user_data)
2206 {
2207     CutRunContext *other_context = user_data;
2208     g_signal_emit(other_context, signals[START_ITERATED_TEST], detail_delegate,
2209                   iterated_test, test_context);
2210 }
2211 
2212 
2213 static void
cb_delegate_pass_assertion(CutRunContext * context,CutTest * test,CutTestContext * test_context,gpointer user_data)2214 cb_delegate_pass_assertion (CutRunContext *context,
2215                             CutTest *test,
2216                             CutTestContext *test_context,
2217                             gpointer user_data)
2218 {
2219     CutRunContext *other_context = user_data;
2220     g_signal_emit(other_context, signals[PASS_ASSERTION], detail_delegate,
2221                   test, test_context);
2222 }
2223 
2224 static void
cb_delegate_success_test(CutRunContext * context,CutTest * test,CutTestContext * test_context,CutTestResult * result,gpointer user_data)2225 cb_delegate_success_test (CutRunContext *context,
2226                           CutTest *test,
2227                           CutTestContext *test_context,
2228                           CutTestResult *result,
2229                           gpointer user_data)
2230 {
2231     CutRunContext *other_context = user_data;
2232     g_signal_emit(other_context, signals[SUCCESS_TEST], detail_delegate,
2233                   test, test_context, result);
2234 }
2235 
2236 static void
cb_delegate_failure_test(CutRunContext * context,CutTest * test,CutTestContext * test_context,CutTestResult * result,gpointer user_data)2237 cb_delegate_failure_test (CutRunContext *context,
2238                           CutTest *test,
2239                           CutTestContext *test_context,
2240                           CutTestResult *result,
2241                           gpointer user_data)
2242 {
2243     CutRunContext *other_context = user_data;
2244     g_signal_emit(other_context, signals[FAILURE_TEST], detail_delegate,
2245                   test, test_context, result);
2246 }
2247 
2248 static void
cb_delegate_error_test(CutRunContext * context,CutTest * test,CutTestContext * test_context,CutTestResult * result,gpointer user_data)2249 cb_delegate_error_test (CutRunContext *context,
2250                         CutTest *test,
2251                         CutTestContext *test_context,
2252                         CutTestResult *result,
2253                         gpointer user_data)
2254 {
2255     CutRunContext *other_context = user_data;
2256     g_signal_emit(other_context, signals[ERROR_TEST], detail_delegate,
2257                   test, test_context, result);
2258 }
2259 
2260 static void
cb_delegate_pending_test(CutRunContext * context,CutTest * test,CutTestContext * test_context,CutTestResult * result,gpointer user_data)2261 cb_delegate_pending_test (CutRunContext *context,
2262                           CutTest *test,
2263                           CutTestContext *test_context,
2264                           CutTestResult *result,
2265                           gpointer user_data)
2266 {
2267     CutRunContext *other_context = user_data;
2268     g_signal_emit(other_context, signals[PENDING_TEST], detail_delegate,
2269                   test, test_context, result);
2270 }
2271 
2272 static void
cb_delegate_notification_test(CutRunContext * context,CutTest * test,CutTestContext * test_context,CutTestResult * result,gpointer user_data)2273 cb_delegate_notification_test (CutRunContext *context,
2274                                CutTest *test,
2275                                CutTestContext *test_context,
2276                                CutTestResult *result,
2277                                gpointer user_data)
2278 {
2279     CutRunContext *other_context = user_data;
2280     g_signal_emit(other_context, signals[NOTIFICATION_TEST], detail_delegate,
2281                   test, test_context, result);
2282 }
2283 
2284 static void
cb_delegate_omission_test(CutRunContext * context,CutTest * test,CutTestContext * test_context,CutTestResult * result,gpointer user_data)2285 cb_delegate_omission_test (CutRunContext *context,
2286                            CutTest *test,
2287                            CutTestContext *test_context,
2288                            CutTestResult *result,
2289                            gpointer user_data)
2290 {
2291     CutRunContext *other_context = user_data;
2292     g_signal_emit(other_context, signals[OMISSION_TEST], detail_delegate,
2293                   test, test_context, result);
2294 }
2295 
2296 static void
cb_delegate_crash_test(CutRunContext * context,CutTest * test,CutTestContext * test_context,CutTestResult * result,gpointer user_data)2297 cb_delegate_crash_test (CutRunContext *context,
2298                         CutTest *test,
2299                         CutTestContext *test_context,
2300                         CutTestResult *result,
2301                         gpointer user_data)
2302 {
2303     CutRunContext *other_context = user_data;
2304     g_signal_emit(other_context, signals[CRASH_TEST], detail_delegate,
2305                   test, test_context, result);
2306 }
2307 
2308 
2309 static void
cb_delegate_complete_test(CutRunContext * context,CutTest * test,CutTestContext * test_context,gboolean success,gpointer user_data)2310 cb_delegate_complete_test (CutRunContext *context,
2311                            CutTest *test,
2312                            CutTestContext *test_context,
2313                            gboolean success,
2314                            gpointer user_data)
2315 {
2316     CutRunContext *other_context = user_data;
2317     g_signal_emit(other_context, signals[COMPLETE_TEST], detail_delegate,
2318                   test, test_context, success);
2319 }
2320 
2321 static void
cb_delegate_complete_iterated_test(CutRunContext * context,CutIteratedTest * iterated_test,CutTestContext * test_context,gboolean success,gpointer user_data)2322 cb_delegate_complete_iterated_test (CutRunContext *context,
2323                                     CutIteratedTest *iterated_test,
2324                                     CutTestContext *test_context,
2325                                     gboolean success,
2326                                     gpointer user_data)
2327 {
2328     CutRunContext *other_context = user_data;
2329     g_signal_emit(other_context, signals[COMPLETE_ITERATED_TEST],
2330                   detail_delegate, iterated_test, test_context, success);
2331 }
2332 
2333 static void
cb_delegate_success_test_iterator(CutRunContext * context,CutTestIterator * test_iterator,CutTestResult * result,gpointer user_data)2334 cb_delegate_success_test_iterator (CutRunContext *context,
2335                                    CutTestIterator *test_iterator,
2336                                    CutTestResult *result,
2337                                    gpointer user_data)
2338 {
2339     CutRunContext *other_context = user_data;
2340     g_signal_emit(other_context, signals[SUCCESS_TEST_ITERATOR], detail_delegate,
2341                   test_iterator, result);
2342 }
2343 
2344 static void
cb_delegate_failure_test_iterator(CutRunContext * context,CutTestIterator * test_iterator,CutTestResult * result,gpointer user_data)2345 cb_delegate_failure_test_iterator (CutRunContext *context,
2346                                    CutTestIterator *test_iterator,
2347                                    CutTestResult *result,
2348                                    gpointer user_data)
2349 {
2350     CutRunContext *other_context = user_data;
2351     g_signal_emit(other_context, signals[FAILURE_TEST_ITERATOR], detail_delegate,
2352                   test_iterator, result);
2353 }
2354 
2355 static void
cb_delegate_error_test_iterator(CutRunContext * context,CutTestIterator * test_iterator,CutTestResult * result,gpointer user_data)2356 cb_delegate_error_test_iterator (CutRunContext *context,
2357                                  CutTestIterator *test_iterator,
2358                                  CutTestResult *result,
2359                                  gpointer user_data)
2360 {
2361     CutRunContext *other_context = user_data;
2362     g_signal_emit(other_context, signals[ERROR_TEST_ITERATOR], detail_delegate,
2363                   test_iterator, result);
2364 }
2365 
2366 static void
cb_delegate_pending_test_iterator(CutRunContext * context,CutTestIterator * test_iterator,CutTestResult * result,gpointer user_data)2367 cb_delegate_pending_test_iterator (CutRunContext *context,
2368                                    CutTestIterator *test_iterator,
2369                                    CutTestResult *result,
2370                                    gpointer user_data)
2371 {
2372     CutRunContext *other_context = user_data;
2373     g_signal_emit(other_context, signals[PENDING_TEST_ITERATOR], detail_delegate,
2374                   test_iterator, result);
2375 }
2376 
2377 static void
cb_delegate_notification_test_iterator(CutRunContext * context,CutTestIterator * test_iterator,CutTestResult * result,gpointer user_data)2378 cb_delegate_notification_test_iterator (CutRunContext *context,
2379                                         CutTestIterator *test_iterator,
2380                                         CutTestResult *result,
2381                                         gpointer user_data)
2382 {
2383     CutRunContext *other_context = user_data;
2384     g_signal_emit(other_context, signals[NOTIFICATION_TEST_ITERATOR],
2385                   detail_delegate,
2386                   test_iterator, result);
2387 }
2388 
2389 static void
cb_delegate_omission_test_iterator(CutRunContext * context,CutTestIterator * test_iterator,CutTestResult * result,gpointer user_data)2390 cb_delegate_omission_test_iterator (CutRunContext *context,
2391                                     CutTestIterator *test_iterator,
2392                                     CutTestResult *result,
2393                                     gpointer user_data)
2394 {
2395     CutRunContext *other_context = user_data;
2396     g_signal_emit(other_context, signals[OMISSION_TEST_ITERATOR],
2397                   detail_delegate,
2398                   test_iterator, result);
2399 }
2400 
2401 static void
cb_delegate_crash_test_iterator(CutRunContext * context,CutTestIterator * test_iterator,CutTestResult * result,gpointer user_data)2402 cb_delegate_crash_test_iterator (CutRunContext *context,
2403                                  CutTestIterator *test_iterator,
2404                                  CutTestResult *result,
2405                                  gpointer user_data)
2406 {
2407     CutRunContext *other_context = user_data;
2408     g_signal_emit(other_context, signals[CRASH_TEST_ITERATOR],
2409                   detail_delegate,
2410                   test_iterator, result);
2411 }
2412 
2413 static void
cb_delegate_complete_test_iterator(CutRunContext * context,CutTestIterator * test_iterator,gboolean success,gpointer user_data)2414 cb_delegate_complete_test_iterator (CutRunContext *context,
2415                                     CutTestIterator *test_iterator,
2416                                     gboolean success,
2417                                     gpointer user_data)
2418 {
2419     CutRunContext *other_context = user_data;
2420     g_signal_emit(other_context, signals[COMPLETE_TEST_ITERATOR],
2421                   detail_delegate, test_iterator, success);
2422 }
2423 
2424 static void
cb_delegate_success_test_case(CutRunContext * context,CutTestCase * test_case,CutTestResult * result,gpointer user_data)2425 cb_delegate_success_test_case (CutRunContext *context,
2426                                CutTestCase *test_case,
2427                                CutTestResult *result,
2428                                gpointer user_data)
2429 {
2430     CutRunContext *other_context = user_data;
2431     g_signal_emit(other_context, signals[SUCCESS_TEST_CASE], detail_delegate,
2432                   test_case, result);
2433 }
2434 
2435 static void
cb_delegate_failure_test_case(CutRunContext * context,CutTestCase * test_case,CutTestResult * result,gpointer user_data)2436 cb_delegate_failure_test_case (CutRunContext *context,
2437                                CutTestCase *test_case,
2438                                CutTestResult *result,
2439                                gpointer user_data)
2440 {
2441     CutRunContext *other_context = user_data;
2442     g_signal_emit(other_context, signals[FAILURE_TEST_CASE], detail_delegate,
2443                   test_case, result);
2444 }
2445 
2446 static void
cb_delegate_error_test_case(CutRunContext * context,CutTestCase * test_case,CutTestResult * result,gpointer user_data)2447 cb_delegate_error_test_case (CutRunContext *context,
2448                              CutTestCase *test_case,
2449                              CutTestResult *result,
2450                              gpointer user_data)
2451 {
2452     CutRunContext *other_context = user_data;
2453     g_signal_emit(other_context, signals[ERROR_TEST_CASE], detail_delegate,
2454                   test_case, result);
2455 }
2456 
2457 static void
cb_delegate_pending_test_case(CutRunContext * context,CutTestCase * test_case,CutTestResult * result,gpointer user_data)2458 cb_delegate_pending_test_case (CutRunContext *context,
2459                                CutTestCase *test_case,
2460                                CutTestResult *result,
2461                                gpointer user_data)
2462 {
2463     CutRunContext *other_context = user_data;
2464     g_signal_emit(other_context, signals[PENDING_TEST_CASE], detail_delegate,
2465                   test_case, result);
2466 }
2467 
2468 static void
cb_delegate_notification_test_case(CutRunContext * context,CutTestCase * test_case,CutTestResult * result,gpointer user_data)2469 cb_delegate_notification_test_case (CutRunContext *context,
2470                                     CutTestCase *test_case,
2471                                     CutTestResult *result,
2472                                     gpointer user_data)
2473 {
2474     CutRunContext *other_context = user_data;
2475     g_signal_emit(other_context, signals[NOTIFICATION_TEST_CASE],
2476                   detail_delegate,
2477                   test_case, result);
2478 }
2479 
2480 static void
cb_delegate_omission_test_case(CutRunContext * context,CutTestCase * test_case,CutTestResult * result,gpointer user_data)2481 cb_delegate_omission_test_case (CutRunContext *context,
2482                                 CutTestCase *test_case,
2483                                 CutTestResult *result,
2484                                 gpointer user_data)
2485 {
2486     CutRunContext *other_context = user_data;
2487     g_signal_emit(other_context, signals[OMISSION_TEST_CASE], detail_delegate,
2488                   test_case, result);
2489 }
2490 
2491 static void
cb_delegate_crash_test_case(CutRunContext * context,CutTestCase * test_case,CutTestResult * result,gpointer user_data)2492 cb_delegate_crash_test_case (CutRunContext *context,
2493                              CutTestCase *test_case,
2494                              CutTestResult *result,
2495                              gpointer user_data)
2496 {
2497     CutRunContext *other_context = user_data;
2498     g_signal_emit(other_context, signals[CRASH_TEST_CASE], detail_delegate,
2499                   test_case, result);
2500 }
2501 
2502 static void
cb_delegate_complete_test_case(CutRunContext * context,CutTestCase * test_case,gboolean success,gpointer user_data)2503 cb_delegate_complete_test_case (CutRunContext *context,
2504                                 CutTestCase *test_case,
2505                                 gboolean success,
2506                                 gpointer user_data)
2507 {
2508     CutRunContext *other_context = user_data;
2509     g_signal_emit(other_context, signals[COMPLETE_TEST_CASE], detail_delegate,
2510                   test_case, success);
2511 }
2512 
2513 
2514 static void
cb_delegate_error(CutRunContext * context,GError * error,gpointer user_data)2515 cb_delegate_error (CutRunContext *context, GError *error, gpointer user_data)
2516 {
2517     CutRunContext *other_context = user_data;
2518     g_signal_emit(other_context, signals[ERROR], detail_delegate,
2519                   error);
2520 }
2521 
2522 
2523 static void
cb_delegate_complete_run(CutRunContext * context,gboolean success,gpointer user_data)2524 cb_delegate_complete_run (CutRunContext *context, gboolean success,
2525                           gpointer user_data)
2526 {
2527     CutRunContext *other_context = user_data;
2528 #define DISCONNECT_DELEGATE_SIGNAL(name)                                \
2529     g_signal_handlers_disconnect_by_func(context,                       \
2530                                          cb_delegate_ ## name,          \
2531                                          other_context)
2532 
2533     DISCONNECT_DELEGATE_SIGNAL(ready_test_case);
2534     DISCONNECT_DELEGATE_SIGNAL(start_test_case);
2535     DISCONNECT_DELEGATE_SIGNAL(ready_test_iterator);
2536     DISCONNECT_DELEGATE_SIGNAL(start_test_iterator);
2537 
2538     DISCONNECT_DELEGATE_SIGNAL(start_test);
2539     DISCONNECT_DELEGATE_SIGNAL(start_iterated_test);
2540 
2541     DISCONNECT_DELEGATE_SIGNAL(pass_assertion);
2542     DISCONNECT_DELEGATE_SIGNAL(success_test);
2543     DISCONNECT_DELEGATE_SIGNAL(failure_test);
2544     DISCONNECT_DELEGATE_SIGNAL(error_test);
2545     DISCONNECT_DELEGATE_SIGNAL(pending_test);
2546     DISCONNECT_DELEGATE_SIGNAL(notification_test);
2547     DISCONNECT_DELEGATE_SIGNAL(omission_test);
2548     DISCONNECT_DELEGATE_SIGNAL(crash_test);
2549 
2550     DISCONNECT_DELEGATE_SIGNAL(complete_test);
2551     DISCONNECT_DELEGATE_SIGNAL(complete_iterated_test);
2552 
2553     DISCONNECT_DELEGATE_SIGNAL(success_test_iterator);
2554     DISCONNECT_DELEGATE_SIGNAL(failure_test_iterator);
2555     DISCONNECT_DELEGATE_SIGNAL(error_test_iterator);
2556     DISCONNECT_DELEGATE_SIGNAL(pending_test_iterator);
2557     DISCONNECT_DELEGATE_SIGNAL(notification_test_iterator);
2558     DISCONNECT_DELEGATE_SIGNAL(omission_test_iterator);
2559     DISCONNECT_DELEGATE_SIGNAL(crash_test_iterator);
2560     DISCONNECT_DELEGATE_SIGNAL(complete_test_iterator);
2561 
2562     DISCONNECT_DELEGATE_SIGNAL(success_test_case);
2563     DISCONNECT_DELEGATE_SIGNAL(failure_test_case);
2564     DISCONNECT_DELEGATE_SIGNAL(error_test_case);
2565     DISCONNECT_DELEGATE_SIGNAL(pending_test_case);
2566     DISCONNECT_DELEGATE_SIGNAL(notification_test_case);
2567     DISCONNECT_DELEGATE_SIGNAL(omission_test_case);
2568     DISCONNECT_DELEGATE_SIGNAL(crash_test_case);
2569     DISCONNECT_DELEGATE_SIGNAL(complete_test_case);
2570 
2571     DISCONNECT_DELEGATE_SIGNAL(error);
2572 
2573     DISCONNECT_DELEGATE_SIGNAL(complete_run);
2574 
2575 #undef DISCONNECT_DELEGATE_SIGNAL
2576 }
2577 
2578 
2579 void
cut_run_context_delegate_signals(CutRunContext * context,CutRunContext * other_context)2580 cut_run_context_delegate_signals (CutRunContext *context,
2581                                   CutRunContext *other_context)
2582 {
2583     detail_delegate = g_quark_from_static_string("delegate");
2584 
2585 #define CONNECT_DELEGATE_SIGNAL(name)                                   \
2586     g_signal_connect(context, #name,                                    \
2587                      G_CALLBACK(cb_delegate_ ## name),                  \
2588                      other_context)
2589 
2590     CONNECT_DELEGATE_SIGNAL(ready_test_case);
2591     CONNECT_DELEGATE_SIGNAL(start_test_case);
2592     CONNECT_DELEGATE_SIGNAL(ready_test_iterator);
2593     CONNECT_DELEGATE_SIGNAL(start_test_iterator);
2594 
2595     CONNECT_DELEGATE_SIGNAL(start_test);
2596     CONNECT_DELEGATE_SIGNAL(start_iterated_test);
2597 
2598     CONNECT_DELEGATE_SIGNAL(pass_assertion);
2599     CONNECT_DELEGATE_SIGNAL(success_test);
2600     CONNECT_DELEGATE_SIGNAL(failure_test);
2601     CONNECT_DELEGATE_SIGNAL(error_test);
2602     CONNECT_DELEGATE_SIGNAL(pending_test);
2603     CONNECT_DELEGATE_SIGNAL(notification_test);
2604     CONNECT_DELEGATE_SIGNAL(omission_test);
2605     CONNECT_DELEGATE_SIGNAL(crash_test);
2606 
2607     CONNECT_DELEGATE_SIGNAL(complete_test);
2608     CONNECT_DELEGATE_SIGNAL(complete_iterated_test);
2609 
2610     CONNECT_DELEGATE_SIGNAL(success_test_iterator);
2611     CONNECT_DELEGATE_SIGNAL(failure_test_iterator);
2612     CONNECT_DELEGATE_SIGNAL(error_test_iterator);
2613     CONNECT_DELEGATE_SIGNAL(pending_test_iterator);
2614     CONNECT_DELEGATE_SIGNAL(notification_test_iterator);
2615     CONNECT_DELEGATE_SIGNAL(omission_test_iterator);
2616     CONNECT_DELEGATE_SIGNAL(crash_test_iterator);
2617     CONNECT_DELEGATE_SIGNAL(complete_test_iterator);
2618 
2619     CONNECT_DELEGATE_SIGNAL(success_test_case);
2620     CONNECT_DELEGATE_SIGNAL(failure_test_case);
2621     CONNECT_DELEGATE_SIGNAL(error_test_case);
2622     CONNECT_DELEGATE_SIGNAL(pending_test_case);
2623     CONNECT_DELEGATE_SIGNAL(notification_test_case);
2624     CONNECT_DELEGATE_SIGNAL(omission_test_case);
2625     CONNECT_DELEGATE_SIGNAL(crash_test_case);
2626     CONNECT_DELEGATE_SIGNAL(complete_test_case);
2627 
2628     CONNECT_DELEGATE_SIGNAL(error);
2629 
2630     CONNECT_DELEGATE_SIGNAL(complete_run);
2631 #undef CONNECT_DELEGATE_SIGNAL
2632 }
2633 
2634 gboolean
cut_run_context_is_completed(CutRunContext * context)2635 cut_run_context_is_completed (CutRunContext *context)
2636 {
2637     return CUT_RUN_CONTEXT_GET_PRIVATE(context)->completed;
2638 }
2639 
2640 void
cut_run_context_set_fatal_failures(CutRunContext * context,gboolean fatal_failures)2641 cut_run_context_set_fatal_failures (CutRunContext *context,
2642                                     gboolean       fatal_failures)
2643 {
2644     CUT_RUN_CONTEXT_GET_PRIVATE(context)->fatal_failures = fatal_failures;
2645 }
2646 
2647 gboolean
cut_run_context_get_fatal_failures(CutRunContext * context)2648 cut_run_context_get_fatal_failures (CutRunContext *context)
2649 {
2650     return CUT_RUN_CONTEXT_GET_PRIVATE(context)->fatal_failures;
2651 }
2652 
2653 void
cut_run_context_set_keep_opening_modules(CutRunContext * context,gboolean keep_opening)2654 cut_run_context_set_keep_opening_modules (CutRunContext *context,
2655                                           gboolean       keep_opening)
2656 {
2657     CUT_RUN_CONTEXT_GET_PRIVATE(context)->keep_opening_modules = keep_opening;
2658 }
2659 
2660 gboolean
cut_run_context_get_keep_opening_modules(CutRunContext * context)2661 cut_run_context_get_keep_opening_modules (CutRunContext *context)
2662 {
2663     return CUT_RUN_CONTEXT_GET_PRIVATE(context)->keep_opening_modules;
2664 }
2665 
2666 void
cut_run_context_set_enable_convenience_attribute_definition(CutRunContext * context,gboolean enable_convenience_attribute_definition)2667 cut_run_context_set_enable_convenience_attribute_definition (CutRunContext *context,
2668                                                              gboolean       enable_convenience_attribute_definition)
2669 {
2670     CUT_RUN_CONTEXT_GET_PRIVATE(context)->enable_convenience_attribute_definition =
2671         enable_convenience_attribute_definition;
2672 }
2673 
2674 gboolean
cut_run_context_get_enable_convenience_attribute_definition(CutRunContext * context)2675 cut_run_context_get_enable_convenience_attribute_definition (CutRunContext *context)
2676 {
2677     return CUT_RUN_CONTEXT_GET_PRIVATE(context)->enable_convenience_attribute_definition;
2678 }
2679 
2680 void
cut_run_context_set_stop_before_test(CutRunContext * context,gboolean stop)2681 cut_run_context_set_stop_before_test (CutRunContext *context,
2682                                       gboolean       stop)
2683 {
2684     CUT_RUN_CONTEXT_GET_PRIVATE(context)->stop_before_test = stop;
2685 }
2686 
2687 gboolean
cut_run_context_get_stop_before_test(CutRunContext * context)2688 cut_run_context_get_stop_before_test (CutRunContext *context)
2689 {
2690     return CUT_RUN_CONTEXT_GET_PRIVATE(context)->stop_before_test;
2691 }
2692 
2693 /*
2694 vi:ts=4:nowrap:ai:expandtab:sw=4
2695 */
2696