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 <stdlib.h>
25 #include <string.h>
26 #include <glib.h>
27
28 #include "cut-stream-parser.h"
29 #include "cut-backtrace-entry.h"
30
31 typedef enum {
32 IN_TOP_LEVEL,
33 IN_TOP_LEVEL_RESULT,
34
35 IN_STREAM,
36 IN_STREAM_SUCCESS,
37
38 IN_TEST_SUITE,
39 IN_TEST_CASE,
40 IN_TEST_ITERATOR,
41 IN_TEST,
42 IN_ITERATED_TEST,
43 IN_TEST_DATA,
44
45 IN_TEST_NAME,
46 IN_TEST_DESCRIPTION,
47 IN_TEST_OPTION,
48 IN_TEST_START_TIME,
49 IN_TEST_ELAPSED,
50
51 IN_TEST_DATA_NAME,
52
53 IN_TEST_OPTION_NAME,
54 IN_TEST_OPTION_VALUE,
55
56 IN_TEST_CONTEXT,
57 IN_TEST_CONTEXT_FAILED,
58
59 IN_READY_TEST_SUITE,
60 IN_READY_TEST_SUITE_N_TEST_CASES,
61 IN_READY_TEST_SUITE_N_TESTS,
62
63 IN_START_TEST_SUITE,
64
65 IN_READY_TEST_CASE,
66 IN_READY_TEST_CASE_N_TESTS,
67
68 IN_READY_TEST_ITERATOR,
69 IN_READY_TEST_ITERATOR_N_TESTS,
70
71 IN_START_TEST_CASE,
72
73 IN_START_TEST_ITERATOR,
74
75 IN_START_TEST,
76
77 IN_START_ITERATED_TEST,
78
79 IN_PASS_ASSERTION,
80
81 IN_TEST_RESULT,
82
83 IN_RESULT,
84 IN_RESULT_STATUS,
85 IN_RESULT_DETAIL,
86 IN_RESULT_BACKTRACE,
87 IN_RESULT_BACKTRACE_ENTRY,
88 IN_RESULT_BACKTRACE_ENTRY_FILE,
89 IN_RESULT_BACKTRACE_ENTRY_LINE,
90 IN_RESULT_BACKTRACE_ENTRY_INFO,
91 IN_RESULT_START_TIME,
92 IN_RESULT_ELAPSED,
93 IN_RESULT_EXPECTED,
94 IN_RESULT_ACTUAL,
95 IN_RESULT_DIFF,
96 IN_RESULT_FOLDED_DIFF,
97
98 IN_COMPLETE_ITERATED_TEST,
99
100 IN_COMPLETE_TEST,
101
102 IN_TEST_ITERATOR_RESULT,
103
104 IN_TEST_CASE_RESULT,
105
106 IN_COMPLETE_TEST_ITERATOR,
107
108 IN_COMPLETE_TEST_CASE,
109
110 IN_COMPLETE_TEST_SUITE,
111
112 IN_COMPLETE_SUCCESS
113 } ParseState;
114
115 #define CUT_STREAM_PARSER_GET_PRIVATE(obj) \
116 (G_TYPE_INSTANCE_GET_PRIVATE((obj), CUT_TYPE_STREAM_PARSER, \
117 CutStreamParserPrivate))
118
119 typedef struct _ReadyTestSuite ReadyTestSuite;
120 struct _ReadyTestSuite
121 {
122 CutTestSuite *test_suite;
123 gint n_test_cases;
124 gint n_tests;
125 };
126
127 typedef struct _ReadyTestCase ReadyTestCase;
128 struct _ReadyTestCase
129 {
130 CutTestCase *test_case;
131 gint n_tests;
132 };
133
134 typedef struct _ReadyTestIterator ReadyTestIterator;
135 struct _ReadyTestIterator
136 {
137 CutTestIterator *test_iterator;
138 gint n_tests;
139 };
140
141 typedef struct _StartTest StartTest;
142 struct _StartTest
143 {
144 CutTest *test;
145 CutTestContext *test_context;
146 };
147
148 typedef struct _StartIteratedTest StartIteratedTest;
149 struct _StartIteratedTest
150 {
151 CutIteratedTest *iterated_test;
152 CutTestContext *test_context;
153 };
154
155 typedef struct _PassAssertion PassAssertion;
156 struct _PassAssertion
157 {
158 CutTest *test;
159 CutTestContext *test_context;
160 };
161
162 typedef struct _TestResult TestResult;
163 struct _TestResult
164 {
165 CutTest *test;
166 CutTestContext *test_context;
167 CutTestResult *result;
168 };
169
170 typedef struct _CompleteIteratedTest CompleteIteratedTest;
171 struct _CompleteIteratedTest
172 {
173 CutIteratedTest *iterated_test;
174 CutTestContext *test_context;
175 };
176
177 typedef struct _CompleteTest CompleteTest;
178 struct _CompleteTest
179 {
180 CutTest *test;
181 CutTestContext *test_context;
182 };
183
184 typedef struct _TestIteratorResult TestIteratorResult;
185 struct _TestIteratorResult
186 {
187 CutTestIterator *test_iterator;
188 CutTestResult *result;
189 };
190
191 typedef struct _TestCaseResult TestCaseResult;
192 struct _TestCaseResult
193 {
194 CutTestCase *test_case;
195 CutTestResult *result;
196 };
197
198 typedef struct _CutStreamParserPrivate CutStreamParserPrivate;
199 struct _CutStreamParserPrivate
200 {
201 GMarkupParseContext *context;
202 CutRunContext *run_context;
203
204 GQueue *states;
205 GQueue *iterated_tests;
206 GQueue *tests;
207 GQueue *test_iterators;
208 GQueue *test_cases;
209 GQueue *test_suites;
210 GQueue *test_contexts;
211 GQueue *test_data;
212
213 ReadyTestSuite *ready_test_suite;
214 ReadyTestCase *ready_test_case;
215 ReadyTestIterator *ready_test_iterator;
216 StartTest *start_test;
217 StartIteratedTest *start_iterated_test;
218 PassAssertion *pass_assertion;
219 TestResult *test_result;
220 CompleteIteratedTest *complete_iterated_test;
221 CompleteTest *complete_test;
222 TestIteratorResult *test_iterator_result;
223 TestCaseResult *test_case_result;
224
225 CutTestResult *result;
226 GList *backtrace;
227 CutBacktraceEntry *backtrace_entry;
228 gchar *option_name;
229 gchar *option_value;
230 gboolean complete_success;
231 gboolean stream_success;
232
233 GQueue *element_stack;
234 };
235
236 #define PUSH_STATE(priv, state) \
237 (g_queue_push_head((priv)->states, GINT_TO_POINTER(state)))
238 #define POP_STATE(priv) \
239 (GPOINTER_TO_INT(g_queue_pop_head((priv)->states)))
240 #define DROP_STATE(priv) \
241 (g_queue_pop_head((priv)->states))
242 #define PEEK_STATE(priv) \
243 (GPOINTER_TO_INT(g_queue_peek_head((priv)->states)))
244 #define PEEK_NTH_STATE(priv, n) \
245 (GPOINTER_TO_INT(g_queue_peek_nth((priv)->states, n)))
246
247 #define PUSH_TEST(priv, test) \
248 (g_queue_push_head((priv)->tests, g_object_ref(test)))
249 #define POP_TEST(priv) \
250 (g_queue_pop_head((priv)->tests))
251 #define DROP_TEST(priv) \
252 (g_object_unref(POP_TEST(priv)))
253 #define PEEK_TEST(priv) \
254 (g_queue_peek_head((priv)->tests))
255
256 #define PUSH_TEST_ITERATOR(priv, test_iterator) \
257 (g_queue_push_head((priv)->test_iterators, g_object_ref(test_iterator)))
258 #define POP_TEST_ITERATOR(priv) \
259 (g_queue_pop_head((priv)->test_iterators))
260 #define DROP_TEST_ITERATOR(priv) \
261 (g_object_unref(POP_TEST_ITERATOR(priv)))
262 #define PEEK_TEST_ITERATOR(priv) \
263 (g_queue_peek_head((priv)->test_iterators))
264
265 #define PUSH_TEST_CASE(priv, test_case) \
266 (g_queue_push_head((priv)->test_cases, g_object_ref(test_case)))
267 #define POP_TEST_CASE(priv) \
268 (g_queue_pop_head((priv)->test_cases))
269 #define DROP_TEST_CASE(priv) \
270 (g_object_unref(POP_TEST_CASE(priv)))
271 #define PEEK_TEST_CASE(priv) \
272 (g_queue_peek_head((priv)->test_cases))
273
274 #define PUSH_TEST_SUITE(priv, test_suite) \
275 (g_queue_push_head((priv)->test_suites, g_object_ref(test_suite)))
276 #define POP_TEST_SUITE(priv) \
277 (g_queue_pop_head((priv)->test_suites))
278 #define DROP_TEST_SUITE(priv) \
279 (g_object_unref(POP_TEST_SUITE(priv)))
280 #define PEEK_TEST_SUITE(priv) \
281 (g_queue_peek_head((priv)->test_suites))
282
283 #define PUSH_TEST_CONTEXT(priv, test_context) \
284 (g_queue_push_head((priv)->test_contexts, g_object_ref(test_context)))
285 #define POP_TEST_CONTEXT(priv) \
286 (g_queue_pop_head((priv)->test_contexts))
287 #define DROP_TEST_CONTEXT(priv) \
288 (g_object_unref(POP_TEST_CONTEXT(priv)))
289 #define PEEK_TEST_CONTEXT(priv) \
290 (g_queue_peek_head((priv)->test_contexts))
291
292 #define PUSH_TEST_DATA(priv, current_test_data) \
293 (g_queue_push_head((priv)->test_data, g_object_ref(current_test_data)))
294 #define POP_TEST_DATA(priv) \
295 (g_queue_pop_head((priv)->test_data))
296 #define DROP_TEST_DATA(priv) \
297 (g_object_unref(POP_TEST_DATA(priv)))
298 #define PEEK_TEST_DATA(priv) \
299 (g_queue_peek_head((priv)->test_data))
300
301 enum
302 {
303 PROP_0,
304 PROP_RUN_CONTEXT,
305 };
306
307 enum
308 {
309 RESULT,
310 LAST_SIGNAL
311 };
312
313 static gint signals[LAST_SIGNAL] = {0};
314
315 G_DEFINE_TYPE(CutStreamParser, cut_stream_parser, G_TYPE_OBJECT)
316
317 static void dispose (GObject *object);
318 static void set_property (GObject *object,
319 guint prop_id,
320 const GValue *value,
321 GParamSpec *pspec);
322 static void get_property (GObject *object,
323 guint prop_id,
324 GValue *value,
325 GParamSpec *pspec);
326
327 static void start_element_handler (GMarkupParseContext *context,
328 const gchar *element_name,
329 const gchar **attribute_names,
330 const gchar **attribute_values,
331 gpointer user_data,
332 GError **error);
333 static void end_element_handler (GMarkupParseContext *context,
334 const gchar *element_name,
335 gpointer user_data,
336 GError **error);
337 static void text_handler (GMarkupParseContext *context,
338 const gchar *text,
339 gsize text_len,
340 gpointer user_data,
341 GError **error);
342 static void error_handler (GMarkupParseContext *context,
343 GError *error,
344 gpointer user_data);
345
346 static GMarkupParser markup_parser = {
347 start_element_handler,
348 end_element_handler,
349 text_handler,
350 NULL,
351 error_handler,
352 };
353
354 static void
cut_stream_parser_class_init(CutStreamParserClass * klass)355 cut_stream_parser_class_init (CutStreamParserClass *klass)
356 {
357 GObjectClass *gobject_class;
358 GParamSpec *spec;
359
360 gobject_class = G_OBJECT_CLASS(klass);
361
362 gobject_class->dispose = dispose;
363 gobject_class->set_property = set_property;
364 gobject_class->get_property = get_property;
365
366 spec = g_param_spec_object("run-context",
367 "run context",
368 "The run context of the stream parser",
369 CUT_TYPE_RUN_CONTEXT,
370 G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY);
371 g_object_class_install_property(gobject_class, PROP_RUN_CONTEXT, spec);
372
373 signals[RESULT]
374 = g_signal_new("result",
375 G_TYPE_FROM_CLASS(klass),
376 G_SIGNAL_RUN_LAST,
377 G_STRUCT_OFFSET(CutStreamParserClass, result),
378 NULL, NULL,
379 g_cclosure_marshal_VOID__OBJECT,
380 G_TYPE_NONE, 1, CUT_TYPE_TEST_RESULT);
381
382 g_type_class_add_private(gobject_class, sizeof(CutStreamParserPrivate));
383 }
384
385 static void
cut_stream_parser_init(CutStreamParser * stream_parser)386 cut_stream_parser_init (CutStreamParser *stream_parser)
387 {
388 CutStreamParserPrivate *priv = CUT_STREAM_PARSER_GET_PRIVATE(stream_parser);
389
390 priv->context = g_markup_parse_context_new(&markup_parser,
391 G_MARKUP_TREAT_CDATA_AS_TEXT,
392 stream_parser, NULL);
393 priv->run_context = NULL;
394
395 priv->states = g_queue_new();
396 PUSH_STATE(priv, IN_TOP_LEVEL);
397 priv->iterated_tests = g_queue_new();
398 priv->tests = g_queue_new();
399 priv->test_cases = g_queue_new();
400 priv->test_iterators = g_queue_new();
401 priv->test_suites = g_queue_new();
402 priv->test_contexts = g_queue_new();
403 priv->test_data = g_queue_new();
404
405 priv->ready_test_suite = NULL;
406 priv->ready_test_case = NULL;
407 priv->ready_test_iterator = NULL;
408 priv->start_test = NULL;
409 priv->start_iterated_test = NULL;
410 priv->pass_assertion = NULL;
411 priv->complete_iterated_test = NULL;
412 priv->complete_test = NULL;
413 priv->test_result = NULL;
414 priv->test_iterator_result = NULL;
415 priv->test_case_result = NULL;
416
417 priv->result = NULL;
418 priv->backtrace = NULL;
419 priv->backtrace_entry = NULL;
420 priv->option_name = NULL;
421 priv->option_value = NULL;
422 priv->complete_success = TRUE;
423 priv->stream_success = TRUE;
424
425 priv->element_stack = g_queue_new();
426 }
427
428 static ReadyTestSuite *
ready_test_suite_new(void)429 ready_test_suite_new (void)
430 {
431 return g_slice_new0(ReadyTestSuite);
432 }
433
434 static void
ready_test_suite_free(ReadyTestSuite * ready_test_suite)435 ready_test_suite_free (ReadyTestSuite *ready_test_suite)
436 {
437 if (ready_test_suite->test_suite)
438 g_object_unref(ready_test_suite->test_suite);
439 g_slice_free(ReadyTestSuite, ready_test_suite);
440 }
441
442 static ReadyTestCase *
ready_test_case_new(void)443 ready_test_case_new (void)
444 {
445 return g_slice_new0(ReadyTestCase);
446 }
447
448 static void
ready_test_case_free(ReadyTestCase * ready_test_case)449 ready_test_case_free (ReadyTestCase *ready_test_case)
450 {
451 if (ready_test_case->test_case)
452 g_object_unref(ready_test_case->test_case);
453 g_slice_free(ReadyTestCase, ready_test_case);
454 }
455
456 static ReadyTestIterator *
ready_test_iterator_new(void)457 ready_test_iterator_new (void)
458 {
459 return g_slice_new0(ReadyTestIterator);
460 }
461
462 static void
ready_test_iterator_free(ReadyTestIterator * ready_test_iterator)463 ready_test_iterator_free (ReadyTestIterator *ready_test_iterator)
464 {
465 if (ready_test_iterator->test_iterator)
466 g_object_unref(ready_test_iterator->test_iterator);
467 g_slice_free(ReadyTestIterator, ready_test_iterator);
468 }
469
470 static StartTest *
start_test_new(void)471 start_test_new (void)
472 {
473 return g_slice_new0(StartTest);
474 }
475
476 static void
start_test_free(StartTest * start_test)477 start_test_free (StartTest *start_test)
478 {
479 if (start_test->test)
480 g_object_unref(start_test->test);
481 if (start_test->test_context)
482 g_object_unref(start_test->test_context);
483 g_slice_free(StartTest, start_test);
484 }
485
486 static StartIteratedTest *
start_iterated_test_new(void)487 start_iterated_test_new (void)
488 {
489 return g_slice_new0(StartIteratedTest);
490 }
491
492 static void
start_iterated_test_free(StartIteratedTest * start_iterated_test)493 start_iterated_test_free (StartIteratedTest *start_iterated_test)
494 {
495 if (start_iterated_test->iterated_test)
496 g_object_unref(start_iterated_test->iterated_test);
497 if (start_iterated_test->test_context)
498 g_object_unref(start_iterated_test->test_context);
499 g_slice_free(StartIteratedTest, start_iterated_test);
500 }
501
502 static PassAssertion *
pass_assertion_new(void)503 pass_assertion_new (void)
504 {
505 return g_slice_new0(PassAssertion);
506 }
507
508 static void
pass_assertion_free(PassAssertion * pass_assertion)509 pass_assertion_free (PassAssertion *pass_assertion)
510 {
511 if (pass_assertion->test)
512 g_object_unref(pass_assertion->test);
513 if (pass_assertion->test_context)
514 g_object_unref(pass_assertion->test_context);
515 g_slice_free(PassAssertion, pass_assertion);
516 }
517
518 static TestResult *
test_result_new(void)519 test_result_new (void)
520 {
521 return g_slice_new0(TestResult);
522 }
523
524 static void
test_result_free(TestResult * test_result)525 test_result_free (TestResult *test_result)
526 {
527 if (test_result->test)
528 g_object_unref(test_result->test);
529 if (test_result->test_context)
530 g_object_unref(test_result->test_context);
531 if (test_result->result)
532 g_object_unref(test_result->result);
533 g_slice_free(TestResult, test_result);
534 }
535
536 static CompleteIteratedTest *
complete_iterated_test_new(void)537 complete_iterated_test_new (void)
538 {
539 return g_slice_new0(CompleteIteratedTest);
540 }
541
542 static void
complete_iterated_test_free(CompleteIteratedTest * complete_iterated_test)543 complete_iterated_test_free (CompleteIteratedTest *complete_iterated_test)
544 {
545 if (complete_iterated_test->iterated_test)
546 g_object_unref(complete_iterated_test->iterated_test);
547 if (complete_iterated_test->test_context)
548 g_object_unref(complete_iterated_test->test_context);
549 g_slice_free(CompleteIteratedTest, complete_iterated_test);
550 }
551
552 static CompleteTest *
complete_test_new(void)553 complete_test_new (void)
554 {
555 return g_slice_new0(CompleteTest);
556 }
557
558 static void
complete_test_free(CompleteTest * complete_test)559 complete_test_free (CompleteTest *complete_test)
560 {
561 if (complete_test->test)
562 g_object_unref(complete_test->test);
563 if (complete_test->test_context)
564 g_object_unref(complete_test->test_context);
565 g_slice_free(CompleteTest, complete_test);
566 }
567
568 static TestIteratorResult *
test_iterator_result_new(void)569 test_iterator_result_new (void)
570 {
571 return g_slice_new0(TestIteratorResult);
572 }
573
574 static void
test_iterator_result_free(TestIteratorResult * test_iterator_result)575 test_iterator_result_free (TestIteratorResult *test_iterator_result)
576 {
577 if (test_iterator_result->test_iterator)
578 g_object_unref(test_iterator_result->test_iterator);
579 if (test_iterator_result->result)
580 g_object_unref(test_iterator_result->result);
581 g_slice_free(TestIteratorResult, test_iterator_result);
582 }
583
584 static TestCaseResult *
test_case_result_new(void)585 test_case_result_new (void)
586 {
587 return g_slice_new0(TestCaseResult);
588 }
589
590 static void
test_case_result_free(TestCaseResult * test_case_result)591 test_case_result_free (TestCaseResult *test_case_result)
592 {
593 if (test_case_result->test_case)
594 g_object_unref(test_case_result->test_case);
595 if (test_case_result->result)
596 g_object_unref(test_case_result->result);
597 g_slice_free(TestCaseResult, test_case_result);
598 }
599
600 static void
run_context_weak_notify(gpointer data,GObject * where_the_object_was)601 run_context_weak_notify (gpointer data, GObject *where_the_object_was)
602 {
603 CutStreamParser *parser = data;
604 CutStreamParserPrivate *priv;
605
606 priv = CUT_STREAM_PARSER_GET_PRIVATE(parser);
607 priv->run_context = NULL;
608 }
609
610 static void
dispose(GObject * object)611 dispose (GObject *object)
612 {
613 CutStreamParserPrivate *priv = CUT_STREAM_PARSER_GET_PRIVATE(object);
614
615 if (priv->context) {
616 g_markup_parse_context_free(priv->context);
617 priv->context = NULL;
618 }
619
620 if (priv->run_context) {
621 g_object_weak_unref(G_OBJECT(priv->run_context),
622 run_context_weak_notify, object);
623 priv->run_context = NULL;
624 }
625
626 if (priv->states) {
627 g_queue_free(priv->states);
628 priv->states = NULL;
629 }
630
631 if (priv->iterated_tests) {
632 g_queue_foreach(priv->iterated_tests, (GFunc)g_object_unref, NULL);
633 g_queue_free(priv->iterated_tests);
634 priv->iterated_tests = NULL;
635 }
636
637 if (priv->tests) {
638 g_queue_foreach(priv->tests, (GFunc)g_object_unref, NULL);
639 g_queue_free(priv->tests);
640 priv->tests = NULL;
641 }
642
643 if (priv->test_cases) {
644 g_queue_foreach(priv->test_cases, (GFunc)g_object_unref, NULL);
645 g_queue_free(priv->test_cases);
646 priv->test_cases = NULL;
647 }
648
649 if (priv->test_suites) {
650 g_queue_foreach(priv->test_suites, (GFunc)g_object_unref, NULL);
651 g_queue_free(priv->test_suites);
652 priv->test_suites = NULL;
653 }
654
655 if (priv->test_contexts) {
656 g_queue_foreach(priv->test_contexts, (GFunc)g_object_unref, NULL);
657 g_queue_free(priv->test_contexts);
658 priv->test_contexts = NULL;
659 }
660
661 if (priv->test_data) {
662 g_queue_foreach(priv->test_data, (GFunc)g_object_unref, NULL);
663 g_queue_free(priv->test_data);
664 priv->test_data = NULL;
665 }
666
667 if (priv->ready_test_suite) {
668 ready_test_suite_free(priv->ready_test_suite);
669 priv->ready_test_suite = NULL;
670 }
671
672 if (priv->ready_test_case) {
673 ready_test_case_free(priv->ready_test_case);
674 priv->ready_test_case = NULL;
675 }
676
677 if (priv->start_test) {
678 start_test_free(priv->start_test);
679 priv->start_test = NULL;
680 }
681
682 if (priv->start_iterated_test) {
683 start_iterated_test_free(priv->start_iterated_test);
684 priv->start_iterated_test = NULL;
685 }
686
687 if (priv->pass_assertion) {
688 pass_assertion_free(priv->pass_assertion);
689 priv->pass_assertion = NULL;
690 }
691
692 if (priv->test_result) {
693 test_result_free(priv->test_result);
694 priv->test_result = NULL;
695 }
696
697 if (priv->complete_iterated_test) {
698 complete_iterated_test_free(priv->complete_iterated_test);
699 priv->complete_iterated_test = NULL;
700 }
701
702 if (priv->complete_test) {
703 complete_test_free(priv->complete_test);
704 priv->complete_test = NULL;
705 }
706
707 if (priv->test_case_result) {
708 test_case_result_free(priv->test_case_result);
709 priv->test_case_result = NULL;
710 }
711
712 if (priv->result) {
713 g_object_unref(priv->result);
714 priv->result = NULL;
715 }
716
717 if (priv->backtrace) {
718 g_list_foreach(priv->backtrace, (GFunc)g_object_unref, NULL);
719 g_list_free(priv->backtrace);
720 priv->backtrace = NULL;
721 }
722
723 if (priv->backtrace_entry) {
724 g_object_unref(priv->backtrace_entry);
725 priv->backtrace_entry = NULL;
726 }
727
728 if (priv->option_name) {
729 g_free(priv->option_name);
730 priv->option_name = NULL;
731 }
732
733 if (priv->option_value) {
734 g_free(priv->option_value);
735 priv->option_value = NULL;
736 }
737
738 if (priv->element_stack) {
739 g_queue_foreach(priv->element_stack, (GFunc)g_free, NULL);
740 g_queue_free(priv->element_stack);
741 priv->element_stack = NULL;
742 }
743
744 G_OBJECT_CLASS(cut_stream_parser_parent_class)->dispose(object);
745 }
746
747 static void
set_property(GObject * object,guint prop_id,const GValue * value,GParamSpec * pspec)748 set_property (GObject *object,
749 guint prop_id,
750 const GValue *value,
751 GParamSpec *pspec)
752 {
753 CutStreamParserPrivate *priv = CUT_STREAM_PARSER_GET_PRIVATE(object);
754
755 switch (prop_id) {
756 case PROP_RUN_CONTEXT:
757 priv->run_context = g_value_get_object(value);
758 if (priv->run_context)
759 g_object_weak_ref(G_OBJECT(priv->run_context),
760 run_context_weak_notify, object);
761 break;
762 default:
763 G_OBJECT_WARN_INVALID_PROPERTY_ID(object, prop_id, pspec);
764 break;
765 }
766 }
767
768 static void
get_property(GObject * object,guint prop_id,GValue * value,GParamSpec * pspec)769 get_property (GObject *object,
770 guint prop_id,
771 GValue *value,
772 GParamSpec *pspec)
773 {
774 CutStreamParserPrivate *priv = CUT_STREAM_PARSER_GET_PRIVATE(object);
775
776 switch (prop_id) {
777 case PROP_RUN_CONTEXT:
778 g_value_set_object(value, priv->run_context);
779 break;
780 default:
781 G_OBJECT_WARN_INVALID_PROPERTY_ID(object, prop_id, pspec);
782 break;
783 }
784 }
785
786 CutStreamParser *
cut_stream_parser_new(CutRunContext * run_context)787 cut_stream_parser_new (CutRunContext *run_context)
788 {
789 return g_object_new(CUT_TYPE_STREAM_PARSER,
790 "run-context", run_context,
791 NULL);
792 }
793
794 CutStreamParser *
cut_test_result_parser_new(void)795 cut_test_result_parser_new (void)
796 {
797 CutStreamParser *parser;
798 CutStreamParserPrivate *priv;
799
800 parser = cut_stream_parser_new(NULL);
801 priv = CUT_STREAM_PARSER_GET_PRIVATE(parser);
802
803 DROP_STATE(priv);
804 PUSH_STATE(priv, IN_TOP_LEVEL_RESULT);
805
806 return parser;
807 }
808
809 gboolean
cut_stream_parser_parse(CutStreamParser * stream_parser,const gchar * text,gssize text_len,GError ** error)810 cut_stream_parser_parse (CutStreamParser *stream_parser,
811 const gchar *text, gssize text_len, GError **error)
812 {
813 CutStreamParserPrivate *priv = CUT_STREAM_PARSER_GET_PRIVATE(stream_parser);
814
815 return g_markup_parse_context_parse(priv->context, text, text_len, error);
816 }
817
818 gboolean
cut_stream_parser_end_parse(CutStreamParser * stream_parser,GError ** error)819 cut_stream_parser_end_parse (CutStreamParser *stream_parser, GError **error)
820 {
821 CutStreamParserPrivate *priv = CUT_STREAM_PARSER_GET_PRIVATE(stream_parser);
822
823 return g_markup_parse_context_end_parse(priv->context, error);
824 }
825
826 static gchar *
element_path(const GList * elements)827 element_path (const GList *elements)
828 {
829 GString *string;
830 const GList *node;
831
832 string = g_string_new(NULL);
833 for (node = elements; node; node = g_list_next(node)) {
834 g_string_append(string, "/");
835 g_string_append(string, node->data);
836 }
837
838 return g_string_free(string, FALSE);
839 }
840
841 static void
set_parse_error(CutStreamParserPrivate * priv,GMarkupParseContext * context,GError ** error,const gchar * format,...)842 set_parse_error (CutStreamParserPrivate *priv,
843 GMarkupParseContext *context,
844 GError **error,
845 const gchar *format, ...)
846 {
847 gint line = 0, chr = 0;
848 gchar *message, *path;
849 va_list var_args;
850
851 va_start(var_args, format);
852 message = g_strdup_vprintf(format, var_args);
853 va_end(var_args);
854
855 g_markup_parse_context_get_position(context, &line, &chr);
856 path = element_path(priv->element_stack->head);
857 g_set_error(error, G_MARKUP_ERROR, G_MARKUP_ERROR_PARSE,
858 "Error on line %d char %d: %s: %s",
859 line, chr, path, message);
860 g_free(path);
861 g_free(message);
862 }
863
864 static void
invalid_element(CutStreamParserPrivate * priv,GMarkupParseContext * context,GError ** error)865 invalid_element (CutStreamParserPrivate *priv,
866 GMarkupParseContext *context, GError **error)
867 {
868 set_parse_error(priv, context, error, "invalid element");
869 }
870
871 static void
start_top_level(CutStreamParserPrivate * priv,GMarkupParseContext * context,const gchar * element_name,GError ** error)872 start_top_level (CutStreamParserPrivate *priv, GMarkupParseContext *context,
873 const gchar *element_name, GError **error)
874 {
875 if (g_str_equal("stream", element_name)) {
876 PUSH_STATE(priv, IN_STREAM);
877 if (priv->run_context)
878 g_signal_emit_by_name(priv->run_context, "start-run");
879 } else {
880 invalid_element(priv, context, error);
881 }
882 }
883
884 static void
start_stream(CutStreamParserPrivate * priv,GMarkupParseContext * context,const gchar * element_name,GError ** error)885 start_stream (CutStreamParserPrivate *priv,
886 GMarkupParseContext *context,
887 const gchar *element_name, GError **error)
888 {
889 if (g_str_equal("pass-assertion", element_name)) {
890 PUSH_STATE(priv, IN_PASS_ASSERTION);
891 priv->pass_assertion = pass_assertion_new();
892 } else if (g_str_equal("test-result", element_name)) {
893 PUSH_STATE(priv, IN_TEST_RESULT);
894 priv->test_result = test_result_new();
895 } else if (g_str_equal("ready-test-suite", element_name)) {
896 PUSH_STATE(priv, IN_READY_TEST_SUITE);
897 priv->ready_test_suite = ready_test_suite_new();
898 } else if (g_str_equal("start-test-suite", element_name)) {
899 PUSH_STATE(priv, IN_START_TEST_SUITE);
900 PUSH_TEST_SUITE(priv, cut_test_suite_new_empty());
901 } else if (g_str_equal("ready-test-case", element_name)) {
902 PUSH_STATE(priv, IN_READY_TEST_CASE);
903 priv->ready_test_case = ready_test_case_new();;
904 } else if (g_str_equal("start-test-case", element_name)) {
905 PUSH_STATE(priv, IN_START_TEST_CASE);
906 PUSH_TEST_CASE(priv, cut_test_case_new_empty());
907 } else if (g_str_equal("ready-test-iterator", element_name)) {
908 PUSH_STATE(priv, IN_READY_TEST_ITERATOR);
909 priv->ready_test_iterator = ready_test_iterator_new();;
910 } else if (g_str_equal("start-test-iterator", element_name)) {
911 PUSH_STATE(priv, IN_START_TEST_ITERATOR);
912 PUSH_TEST_ITERATOR(priv, cut_test_iterator_new_empty());
913 } else if (g_str_equal("start-test", element_name)) {
914 PUSH_STATE(priv, IN_START_TEST);
915 priv->start_test = start_test_new();
916 } else if (g_str_equal("start-iterated-test", element_name)) {
917 PUSH_STATE(priv, IN_START_ITERATED_TEST);
918 priv->start_iterated_test = start_iterated_test_new();
919 } else if (g_str_equal("complete-iterated-test", element_name)) {
920 PUSH_STATE(priv, IN_COMPLETE_ITERATED_TEST);
921 priv->complete_iterated_test = complete_iterated_test_new();
922 } else if (g_str_equal("complete-test", element_name)) {
923 PUSH_STATE(priv, IN_COMPLETE_TEST);
924 priv->complete_test = complete_test_new();
925 } else if (g_str_equal("test-iterator-result", element_name)) {
926 PUSH_STATE(priv, IN_TEST_ITERATOR_RESULT);
927 priv->test_iterator_result = test_iterator_result_new();
928 } else if (g_str_equal("complete-test-iterator", element_name)) {
929 PUSH_STATE(priv, IN_COMPLETE_TEST_ITERATOR);
930 } else if (g_str_equal("test-case-result", element_name)) {
931 PUSH_STATE(priv, IN_TEST_CASE_RESULT);
932 priv->test_case_result = test_case_result_new();
933 } else if (g_str_equal("complete-test-case", element_name)) {
934 PUSH_STATE(priv, IN_COMPLETE_TEST_CASE);
935 } else if (g_str_equal("complete-test-suite", element_name)) {
936 PUSH_STATE(priv, IN_COMPLETE_TEST_SUITE);
937 } else if (g_str_equal("success", element_name)) {
938 PUSH_STATE(priv, IN_STREAM_SUCCESS);
939 } else {
940 invalid_element(priv, context, error);
941 }
942 }
943
944 static void
start_ready_test_suite(CutStreamParserPrivate * priv,GMarkupParseContext * context,const gchar * element_name,GError ** error)945 start_ready_test_suite (CutStreamParserPrivate *priv,
946 GMarkupParseContext *context,
947 const gchar *element_name, GError **error)
948 {
949 if (g_str_equal("test-suite", element_name)) {
950 PUSH_STATE(priv, IN_TEST_SUITE);
951 priv->ready_test_suite->test_suite = cut_test_suite_new_empty();
952 PUSH_TEST_SUITE(priv, priv->ready_test_suite->test_suite);
953 } else if (g_str_equal("n-test-cases", element_name)) {
954 PUSH_STATE(priv, IN_READY_TEST_SUITE_N_TEST_CASES);
955 } else if (g_str_equal("n-tests", element_name)) {
956 PUSH_STATE(priv, IN_READY_TEST_SUITE_N_TESTS);
957 } else {
958 invalid_element(priv, context, error);
959 }
960 }
961
962 static void
start_start_test_suite(CutStreamParserPrivate * priv,GMarkupParseContext * context,const gchar * element_name,GError ** error)963 start_start_test_suite (CutStreamParserPrivate *priv,
964 GMarkupParseContext *context,
965 const gchar *element_name, GError **error)
966 {
967 if (g_str_equal("test-suite", element_name)) {
968 PUSH_STATE(priv, IN_TEST_SUITE);
969 PUSH_TEST_SUITE(priv, cut_test_suite_new_empty());
970 } else {
971 invalid_element(priv, context, error);
972 }
973 }
974
975 static void
start_ready_test_case(CutStreamParserPrivate * priv,GMarkupParseContext * context,const gchar * element_name,GError ** error)976 start_ready_test_case (CutStreamParserPrivate *priv,
977 GMarkupParseContext *context,
978 const gchar *element_name, GError **error)
979 {
980 if (g_str_equal("test-case", element_name)) {
981 PUSH_STATE(priv, IN_TEST_CASE);
982 priv->ready_test_case->test_case = cut_test_case_new_empty();
983 PUSH_TEST_CASE(priv, priv->ready_test_case->test_case);
984 } else if (g_str_equal("n-tests", element_name)) {
985 PUSH_STATE(priv, IN_READY_TEST_CASE_N_TESTS);
986 } else {
987 invalid_element(priv, context, error);
988 }
989 }
990
991 static void
start_start_test_case(CutStreamParserPrivate * priv,GMarkupParseContext * context,const gchar * element_name,GError ** error)992 start_start_test_case (CutStreamParserPrivate *priv,
993 GMarkupParseContext *context,
994 const gchar *element_name, GError **error)
995 {
996 if (g_str_equal("test-case", element_name)) {
997 PUSH_STATE(priv, IN_TEST_CASE);
998 PUSH_TEST_CASE(priv, cut_test_case_new_empty());
999 } else {
1000 invalid_element(priv, context, error);
1001 }
1002 }
1003
1004 static void
start_ready_test_iterator(CutStreamParserPrivate * priv,GMarkupParseContext * context,const gchar * element_name,GError ** error)1005 start_ready_test_iterator (CutStreamParserPrivate *priv,
1006 GMarkupParseContext *context,
1007 const gchar *element_name, GError **error)
1008 {
1009 if (g_str_equal("test-iterator", element_name)) {
1010 PUSH_STATE(priv, IN_TEST_ITERATOR);
1011 priv->ready_test_iterator->test_iterator = cut_test_iterator_new_empty();
1012 PUSH_TEST_ITERATOR(priv, priv->ready_test_iterator->test_iterator);
1013 } else if (g_str_equal("n-tests", element_name)) {
1014 PUSH_STATE(priv, IN_READY_TEST_ITERATOR_N_TESTS);
1015 } else {
1016 invalid_element(priv, context, error);
1017 }
1018 }
1019
1020 static void
start_start_test_iterator(CutStreamParserPrivate * priv,GMarkupParseContext * context,const gchar * element_name,GError ** error)1021 start_start_test_iterator (CutStreamParserPrivate *priv,
1022 GMarkupParseContext *context,
1023 const gchar *element_name, GError **error)
1024 {
1025 if (g_str_equal("test-iterator", element_name)) {
1026 PUSH_STATE(priv, IN_TEST_ITERATOR);
1027 PUSH_TEST_ITERATOR(priv, cut_test_iterator_new_empty());
1028 } else {
1029 invalid_element(priv, context, error);
1030 }
1031 }
1032
1033 static void
start_start_test(CutStreamParserPrivate * priv,GMarkupParseContext * context,const gchar * element_name,GError ** error)1034 start_start_test (CutStreamParserPrivate *priv,
1035 GMarkupParseContext *context,
1036 const gchar *element_name, GError **error)
1037 {
1038 if (g_str_equal("test", element_name)) {
1039 PUSH_STATE(priv, IN_TEST);
1040 priv->start_test->test = cut_test_new_empty();
1041 PUSH_TEST(priv, priv->start_test->test);
1042 } else if (g_str_equal("test-context", element_name)) {
1043 PUSH_STATE(priv, IN_TEST_CONTEXT);
1044 priv->start_test->test_context = cut_test_context_new_empty();
1045 PUSH_TEST_CONTEXT(priv, priv->start_test->test_context);
1046 } else {
1047 invalid_element(priv, context, error);
1048 }
1049 }
1050
1051 static void
start_start_iterated_test(CutStreamParserPrivate * priv,GMarkupParseContext * context,const gchar * element_name,GError ** error)1052 start_start_iterated_test (CutStreamParserPrivate *priv,
1053 GMarkupParseContext *context,
1054 const gchar *element_name, GError **error)
1055 {
1056 if (g_str_equal("iterated-test", element_name)) {
1057 PUSH_STATE(priv, IN_ITERATED_TEST);
1058 priv->start_iterated_test->iterated_test = cut_iterated_test_new_empty();
1059 PUSH_TEST(priv, CUT_TEST(priv->start_iterated_test->iterated_test));
1060 } else if (g_str_equal("test-context", element_name)) {
1061 PUSH_STATE(priv, IN_TEST_CONTEXT);
1062 priv->start_iterated_test->test_context = cut_test_context_new_empty();
1063 PUSH_TEST_CONTEXT(priv, priv->start_iterated_test->test_context);
1064 } else {
1065 invalid_element(priv, context, error);
1066 }
1067 }
1068
1069 static void
start_pass_assertion(CutStreamParserPrivate * priv,GMarkupParseContext * context,const gchar * element_name,GError ** error)1070 start_pass_assertion (CutStreamParserPrivate *priv,
1071 GMarkupParseContext *context,
1072 const gchar *element_name, GError **error)
1073 {
1074 if (g_str_equal("test", element_name)) {
1075 PUSH_STATE(priv, IN_TEST);
1076 priv->pass_assertion->test = cut_test_new_empty();
1077 PUSH_TEST(priv, priv->pass_assertion->test);
1078 } else if (g_str_equal("iterated-test", element_name)) {
1079 PUSH_STATE(priv, IN_ITERATED_TEST);
1080 priv->pass_assertion->test = CUT_TEST(cut_iterated_test_new_empty());
1081 PUSH_TEST(priv, priv->pass_assertion->test);
1082 } else if (g_str_equal("test-context", element_name)) {
1083 PUSH_STATE(priv, IN_TEST_CONTEXT);
1084 priv->pass_assertion->test_context = cut_test_context_new_empty();
1085 PUSH_TEST_CONTEXT(priv, priv->pass_assertion->test_context);
1086 } else {
1087 invalid_element(priv, context, error);
1088 }
1089 }
1090
1091 static void
start_test_result(CutStreamParserPrivate * priv,GMarkupParseContext * context,const gchar * element_name,GError ** error)1092 start_test_result (CutStreamParserPrivate *priv,
1093 GMarkupParseContext *context,
1094 const gchar *element_name, GError **error)
1095 {
1096 if (g_str_equal("test", element_name)) {
1097 PUSH_STATE(priv, IN_TEST);
1098 priv->test_result->test = cut_test_new_empty();
1099 PUSH_TEST(priv, priv->test_result->test);
1100 } else if (g_str_equal("iterated-test", element_name)) {
1101 PUSH_STATE(priv, IN_ITERATED_TEST);
1102 priv->test_result->test = CUT_TEST(cut_iterated_test_new_empty());
1103 PUSH_TEST(priv, priv->test_result->test);
1104 } else if (g_str_equal("test-context", element_name)) {
1105 PUSH_STATE(priv, IN_TEST_CONTEXT);
1106 priv->test_result->test_context = cut_test_context_new_empty();
1107 PUSH_TEST_CONTEXT(priv, priv->test_result->test_context);
1108 } else if (g_str_equal("result", element_name)) {
1109 PUSH_STATE(priv, IN_RESULT);
1110 priv->test_result->result = cut_test_result_new_empty();
1111 priv->result = g_object_ref(priv->test_result->result);
1112 } else {
1113 invalid_element(priv, context, error);
1114 }
1115 }
1116
1117 static void
start_top_level_result(CutStreamParserPrivate * priv,GMarkupParseContext * context,const gchar * element_name,GError ** error)1118 start_top_level_result (CutStreamParserPrivate *priv,
1119 GMarkupParseContext *context,
1120 const gchar *element_name, GError **error)
1121 {
1122 if (g_str_equal("result", element_name)) {
1123 PUSH_STATE(priv, IN_RESULT);
1124 priv->result = cut_test_result_new_empty();
1125 } else {
1126 invalid_element(priv, context, error);
1127 }
1128 }
1129
1130 static void
start_result(CutStreamParserPrivate * priv,GMarkupParseContext * context,const gchar * element_name,GError ** error)1131 start_result (CutStreamParserPrivate *priv, GMarkupParseContext *context,
1132 const gchar *element_name, GError **error)
1133 {
1134 if (g_str_equal("test-case", element_name)) {
1135 CutTestCase *test_case;
1136
1137 PUSH_STATE(priv, IN_TEST_CASE);
1138 test_case = cut_test_case_new_empty();
1139 cut_test_result_set_test_case(priv->result, test_case);
1140 PUSH_TEST_CASE(priv, test_case);
1141 g_object_unref(test_case);
1142 } else if (g_str_equal("test-iterator", element_name)) {
1143 CutTestIterator *test_iterator;
1144
1145 PUSH_STATE(priv, IN_TEST_ITERATOR);
1146 test_iterator = cut_test_iterator_new_empty();
1147 cut_test_result_set_test_iterator(priv->result, test_iterator);
1148 PUSH_TEST_ITERATOR(priv, test_iterator);
1149 g_object_unref(test_iterator);
1150 } else if (g_str_equal("test", element_name) ||
1151 g_str_equal("iterated-test", element_name)) {
1152 CutTest *test;
1153
1154 PUSH_STATE(priv, IN_TEST);
1155 if (g_str_equal("iterated-test", element_name))
1156 test = CUT_TEST(cut_iterated_test_new_empty());
1157 else
1158 test = cut_test_new_empty();
1159 cut_test_result_set_test(priv->result, test);
1160 PUSH_TEST(priv, test);
1161 g_object_unref(test);
1162 } else if (g_str_equal("test-data", element_name)) {
1163 CutTestData *test_data;
1164
1165 PUSH_STATE(priv, IN_TEST_DATA);
1166 test_data = cut_test_data_new_empty();
1167 cut_test_result_set_test_data(priv->result, test_data);
1168 PUSH_TEST_DATA(priv, test_data);
1169 g_object_unref(test_data);
1170 } else if (g_str_equal("status", element_name)) {
1171 PUSH_STATE(priv, IN_RESULT_STATUS);
1172 } else if (g_str_equal("detail", element_name)) {
1173 PUSH_STATE(priv, IN_RESULT_DETAIL);
1174 } else if (g_str_equal("backtrace", element_name)) {
1175 PUSH_STATE(priv, IN_RESULT_BACKTRACE);
1176 } else if (g_str_equal("start-time", element_name)) {
1177 PUSH_STATE(priv, IN_RESULT_START_TIME);
1178 } else if (g_str_equal("elapsed", element_name)) {
1179 PUSH_STATE(priv, IN_RESULT_ELAPSED);
1180 } else if (g_str_equal("expected", element_name)) {
1181 PUSH_STATE(priv, IN_RESULT_EXPECTED);
1182 } else if (g_str_equal("actual", element_name)) {
1183 PUSH_STATE(priv, IN_RESULT_ACTUAL);
1184 } else if (g_str_equal("diff", element_name)) {
1185 PUSH_STATE(priv, IN_RESULT_DIFF);
1186 } else if (g_str_equal("folded-diff", element_name)) {
1187 PUSH_STATE(priv, IN_RESULT_FOLDED_DIFF);
1188 } else {
1189 invalid_element(priv, context, error);
1190 }
1191 }
1192
1193 static void
start_complete_iterated_test(CutStreamParserPrivate * priv,GMarkupParseContext * context,const gchar * element_name,GError ** error)1194 start_complete_iterated_test (CutStreamParserPrivate *priv,
1195 GMarkupParseContext *context,
1196 const gchar *element_name, GError **error)
1197 {
1198 if (g_str_equal("iterated-test", element_name)) {
1199 PUSH_STATE(priv, IN_ITERATED_TEST);
1200 priv->complete_iterated_test->iterated_test =
1201 cut_iterated_test_new_empty();
1202 PUSH_TEST(priv, CUT_TEST(priv->complete_iterated_test->iterated_test));
1203 } else if (g_str_equal("test-context", element_name)) {
1204 PUSH_STATE(priv, IN_TEST_CONTEXT);
1205 priv->complete_iterated_test->test_context =
1206 cut_test_context_new_empty();
1207 PUSH_TEST_CONTEXT(priv, priv->complete_iterated_test->test_context);
1208 } else if (g_str_equal("success", element_name)) {
1209 PUSH_STATE(priv, IN_COMPLETE_SUCCESS);
1210 } else {
1211 invalid_element(priv, context, error);
1212 }
1213 }
1214
1215 static void
start_complete_test(CutStreamParserPrivate * priv,GMarkupParseContext * context,const gchar * element_name,GError ** error)1216 start_complete_test (CutStreamParserPrivate *priv, GMarkupParseContext *context,
1217 const gchar *element_name, GError **error)
1218 {
1219 if (g_str_equal("test", element_name)) {
1220 PUSH_STATE(priv, IN_TEST);
1221 priv->complete_test->test = cut_test_new_empty();
1222 PUSH_TEST(priv, priv->complete_test->test);
1223 } else if (g_str_equal("test-context", element_name)) {
1224 PUSH_STATE(priv, IN_TEST_CONTEXT);
1225 priv->complete_test->test_context = cut_test_context_new_empty();
1226 PUSH_TEST_CONTEXT(priv, priv->complete_test->test_context);
1227 } else if (g_str_equal("success", element_name)) {
1228 PUSH_STATE(priv, IN_COMPLETE_SUCCESS);
1229 } else {
1230 invalid_element(priv, context, error);
1231 }
1232 }
1233
1234 static void
start_test_iterator_result(CutStreamParserPrivate * priv,GMarkupParseContext * context,const gchar * element_name,GError ** error)1235 start_test_iterator_result (CutStreamParserPrivate *priv,
1236 GMarkupParseContext *context,
1237 const gchar *element_name, GError **error)
1238 {
1239 if (g_str_equal("test-iterator", element_name)) {
1240 PUSH_STATE(priv, IN_TEST_ITERATOR);
1241 priv->test_iterator_result->test_iterator =
1242 cut_test_iterator_new_empty();
1243 PUSH_TEST_ITERATOR(priv, priv->test_iterator_result->test_iterator);
1244 } else if (g_str_equal("result", element_name)) {
1245 PUSH_STATE(priv, IN_RESULT);
1246 priv->test_iterator_result->result = cut_test_result_new_empty();
1247 priv->result = g_object_ref(priv->test_iterator_result->result);
1248 } else {
1249 invalid_element(priv, context, error);
1250 }
1251 }
1252
1253 static void
start_complete_test_iterator(CutStreamParserPrivate * priv,GMarkupParseContext * context,const gchar * element_name,GError ** error)1254 start_complete_test_iterator (CutStreamParserPrivate *priv,
1255 GMarkupParseContext *context,
1256 const gchar *element_name, GError **error)
1257 {
1258 if (g_str_equal("test-iterator", element_name)) {
1259 PUSH_STATE(priv, IN_TEST_ITERATOR);
1260 PUSH_TEST_ITERATOR(priv, cut_test_iterator_new_empty());
1261 } else if (g_str_equal("success", element_name)) {
1262 PUSH_STATE(priv, IN_COMPLETE_SUCCESS);
1263 } else {
1264 invalid_element(priv, context, error);
1265 }
1266 }
1267
1268 static void
start_test_case_result(CutStreamParserPrivate * priv,GMarkupParseContext * context,const gchar * element_name,GError ** error)1269 start_test_case_result (CutStreamParserPrivate *priv,
1270 GMarkupParseContext *context,
1271 const gchar *element_name, GError **error)
1272 {
1273 if (g_str_equal("test-case", element_name)) {
1274 PUSH_STATE(priv, IN_TEST_CASE);
1275 priv->test_case_result->test_case = cut_test_case_new_empty();
1276 PUSH_TEST_CASE(priv, priv->test_case_result->test_case);
1277 } else if (g_str_equal("result", element_name)) {
1278 PUSH_STATE(priv, IN_RESULT);
1279 priv->test_case_result->result = cut_test_result_new_empty();
1280 priv->result = g_object_ref(priv->test_case_result->result);
1281 } else {
1282 invalid_element(priv, context, error);
1283 }
1284 }
1285
1286 static void
start_complete_test_case(CutStreamParserPrivate * priv,GMarkupParseContext * context,const gchar * element_name,GError ** error)1287 start_complete_test_case (CutStreamParserPrivate *priv,
1288 GMarkupParseContext *context,
1289 const gchar *element_name, GError **error)
1290 {
1291 if (g_str_equal("test-case", element_name)) {
1292 PUSH_STATE(priv, IN_TEST_CASE);
1293 PUSH_TEST_CASE(priv, cut_test_case_new_empty());
1294 } else if (g_str_equal("success", element_name)) {
1295 PUSH_STATE(priv, IN_COMPLETE_SUCCESS);
1296 } else {
1297 invalid_element(priv, context, error);
1298 }
1299 }
1300
1301 static void
start_complete_test_suite(CutStreamParserPrivate * priv,GMarkupParseContext * context,const gchar * element_name,GError ** error)1302 start_complete_test_suite (CutStreamParserPrivate *priv,
1303 GMarkupParseContext *context,
1304 const gchar *element_name, GError **error)
1305 {
1306 if (g_str_equal("test-suite", element_name)) {
1307 PUSH_STATE(priv, IN_TEST_SUITE);
1308 PUSH_TEST_SUITE(priv, cut_test_suite_new_empty());
1309 } else if (g_str_equal("success", element_name)) {
1310 PUSH_STATE(priv, IN_COMPLETE_SUCCESS);
1311 } else {
1312 invalid_element(priv, context, error);
1313 }
1314 }
1315
1316 static void
start_test_object(CutStreamParserPrivate * priv,GMarkupParseContext * context,const gchar * element_name,GError ** error)1317 start_test_object (CutStreamParserPrivate *priv, GMarkupParseContext *context,
1318 const gchar *element_name, GError **error)
1319 {
1320 if (g_str_equal("name", element_name)) {
1321 PUSH_STATE(priv, IN_TEST_NAME);
1322 } else if (g_str_equal("description", element_name)) {
1323 PUSH_STATE(priv, IN_TEST_DESCRIPTION);
1324 } else if (g_str_equal("option", element_name)) {
1325 PUSH_STATE(priv, IN_TEST_OPTION);
1326 } else if (g_str_equal("start-time", element_name)) {
1327 PUSH_STATE(priv, IN_TEST_START_TIME);
1328 } else if (g_str_equal("elapsed", element_name)) {
1329 PUSH_STATE(priv, IN_TEST_ELAPSED);
1330 } else {
1331 invalid_element(priv, context, error);
1332 }
1333 }
1334
1335 static void
start_test_option(CutStreamParserPrivate * priv,GMarkupParseContext * context,const gchar * element_name,GError ** error)1336 start_test_option (CutStreamParserPrivate *priv, GMarkupParseContext *context,
1337 const gchar *element_name, GError **error)
1338 {
1339 if (g_str_equal("name", element_name)) {
1340 PUSH_STATE(priv, IN_TEST_OPTION_NAME);
1341 } else if (g_str_equal("value", element_name)) {
1342 PUSH_STATE(priv, IN_TEST_OPTION_VALUE);
1343 } else {
1344 invalid_element(priv, context, error);
1345 }
1346 }
1347
1348 static void
start_result_backtrace(CutStreamParserPrivate * priv,GMarkupParseContext * context,const gchar * element_name,GError ** error)1349 start_result_backtrace (CutStreamParserPrivate *priv,
1350 GMarkupParseContext *context,
1351 const gchar *element_name, GError **error)
1352 {
1353 if (g_str_equal("entry", element_name)) {
1354 PUSH_STATE(priv, IN_RESULT_BACKTRACE_ENTRY);
1355 priv->backtrace_entry = cut_backtrace_entry_new_empty();
1356 } else {
1357 invalid_element(priv, context, error);
1358 }
1359 }
1360
1361 static void
start_result_backtrace_entry(CutStreamParserPrivate * priv,GMarkupParseContext * context,const gchar * element_name,GError ** error)1362 start_result_backtrace_entry (CutStreamParserPrivate *priv,
1363 GMarkupParseContext *context,
1364 const gchar *element_name, GError **error)
1365 {
1366 if (g_str_equal("file", element_name)) {
1367 PUSH_STATE(priv, IN_RESULT_BACKTRACE_ENTRY_FILE);
1368 } else if (g_str_equal("line", element_name)) {
1369 PUSH_STATE(priv, IN_RESULT_BACKTRACE_ENTRY_LINE);
1370 } else if (g_str_equal("info", element_name)) {
1371 PUSH_STATE(priv, IN_RESULT_BACKTRACE_ENTRY_INFO);
1372 } else {
1373 invalid_element(priv, context, error);
1374 }
1375 }
1376
1377 static void
start_test_context(CutStreamParserPrivate * priv,GMarkupParseContext * context,const gchar * element_name,GError ** error)1378 start_test_context (CutStreamParserPrivate *priv, GMarkupParseContext *context,
1379 const gchar *element_name, GError **error)
1380 {
1381 if (g_str_equal("test-suite", element_name)) {
1382 CutTestSuite *test_suite;
1383
1384 PUSH_STATE(priv, IN_TEST_SUITE);
1385 test_suite = cut_test_suite_new_empty();
1386 cut_test_context_set_test_suite(PEEK_TEST_CONTEXT(priv), test_suite);
1387 PUSH_TEST_SUITE(priv, test_suite);
1388 g_object_unref(test_suite);
1389 } else if (g_str_equal("test-case", element_name)) {
1390 CutTestCase *test_case;
1391
1392 PUSH_STATE(priv, IN_TEST_CASE);
1393 test_case = cut_test_case_new_empty();
1394 cut_test_context_set_test_case(PEEK_TEST_CONTEXT(priv), test_case);
1395 PUSH_TEST_CASE(priv, test_case);
1396 g_object_unref(test_case);
1397 } else if (g_str_equal("test-iterator", element_name)) {
1398 CutTestIterator *test_iterator;
1399
1400 PUSH_STATE(priv, IN_TEST_ITERATOR);
1401 test_iterator = cut_test_iterator_new_empty();
1402 cut_test_context_set_test_iterator(PEEK_TEST_CONTEXT(priv),
1403 test_iterator);
1404 PUSH_TEST_ITERATOR(priv, test_iterator);
1405 g_object_unref(test_iterator);
1406 } else if (g_str_equal("test", element_name)) {
1407 CutTest *test;
1408
1409 PUSH_STATE(priv, IN_TEST);
1410 test = cut_test_new_empty();
1411 cut_test_context_set_test(PEEK_TEST_CONTEXT(priv), test);
1412 PUSH_TEST(priv, test);
1413 g_object_unref(test);
1414 } else if (g_str_equal("iterated-test", element_name)) {
1415 CutIteratedTest *iterated_test;
1416
1417 PUSH_STATE(priv, IN_ITERATED_TEST);
1418 iterated_test = cut_iterated_test_new_empty();
1419 cut_test_context_set_test(PEEK_TEST_CONTEXT(priv),
1420 CUT_TEST(iterated_test));
1421 PUSH_TEST(priv, CUT_TEST(iterated_test));
1422 g_object_unref(iterated_test);
1423 } else if (g_str_equal("test-data", element_name)) {
1424 CutTestData *test_data;
1425
1426 PUSH_STATE(priv, IN_TEST_DATA);
1427 test_data = cut_test_data_new_empty();
1428 cut_test_context_set_data(PEEK_TEST_CONTEXT(priv), test_data);
1429 PUSH_TEST_DATA(priv, test_data);
1430 g_object_unref(test_data);
1431 } else if (g_str_equal("failed", element_name)) {
1432 PUSH_STATE(priv, IN_TEST_CONTEXT_FAILED);
1433 } else {
1434 invalid_element(priv, context, error);
1435 }
1436 }
1437
1438 static void
start_test_data(CutStreamParserPrivate * priv,GMarkupParseContext * context,const gchar * element_name,GError ** error)1439 start_test_data (CutStreamParserPrivate *priv, GMarkupParseContext *context,
1440 const gchar *element_name, GError **error)
1441 {
1442 if (g_str_equal("name", element_name)) {
1443 PUSH_STATE(priv, IN_TEST_DATA_NAME);
1444 } else {
1445 invalid_element(priv, context, error);
1446 }
1447 }
1448
1449 static void
start_element_handler(GMarkupParseContext * context,const gchar * element_name,const gchar ** attr_names,const gchar ** attr_values,gpointer user_data,GError ** error)1450 start_element_handler (GMarkupParseContext *context,
1451 const gchar *element_name,
1452 const gchar **attr_names,
1453 const gchar **attr_values,
1454 gpointer user_data,
1455 GError **error)
1456 {
1457 CutStreamParser *parser = user_data;
1458 CutStreamParserPrivate *priv;
1459 ParseState state;
1460
1461 priv = CUT_STREAM_PARSER_GET_PRIVATE(parser);
1462 g_queue_push_tail(priv->element_stack, g_strdup(element_name));
1463
1464 state = PEEK_STATE(priv);
1465 switch (state) {
1466 case IN_TOP_LEVEL:
1467 start_top_level(priv, context, element_name, error);
1468 break;
1469 case IN_STREAM:
1470 start_stream(priv, context, element_name, error);
1471 break;
1472 case IN_READY_TEST_SUITE:
1473 start_ready_test_suite(priv, context, element_name, error);
1474 break;
1475 case IN_START_TEST_SUITE:
1476 start_start_test_suite(priv, context, element_name, error);
1477 break;
1478 case IN_READY_TEST_CASE:
1479 start_ready_test_case(priv, context, element_name, error);
1480 break;
1481 case IN_START_TEST_CASE:
1482 start_start_test_case(priv, context, element_name, error);
1483 break;
1484 case IN_READY_TEST_ITERATOR:
1485 start_ready_test_iterator(priv, context, element_name, error);
1486 break;
1487 case IN_START_TEST_ITERATOR:
1488 start_start_test_iterator(priv, context, element_name, error);
1489 break;
1490 case IN_START_TEST:
1491 start_start_test(priv, context, element_name, error);
1492 break;
1493 case IN_START_ITERATED_TEST:
1494 start_start_iterated_test(priv, context, element_name, error);
1495 break;
1496 case IN_PASS_ASSERTION:
1497 start_pass_assertion(priv, context, element_name, error);
1498 break;
1499 case IN_TEST_RESULT:
1500 start_test_result(priv, context, element_name, error);
1501 break;
1502 case IN_TOP_LEVEL_RESULT:
1503 start_top_level_result(priv, context, element_name, error);
1504 break;
1505 case IN_RESULT:
1506 start_result(priv, context, element_name, error);
1507 break;
1508 case IN_COMPLETE_ITERATED_TEST:
1509 start_complete_iterated_test(priv, context, element_name, error);
1510 break;
1511 case IN_COMPLETE_TEST:
1512 start_complete_test(priv, context, element_name, error);
1513 break;
1514 case IN_TEST_ITERATOR_RESULT:
1515 start_test_iterator_result(priv, context, element_name, error);
1516 break;
1517 case IN_COMPLETE_TEST_ITERATOR:
1518 start_complete_test_iterator(priv, context, element_name, error);
1519 break;
1520 case IN_TEST_CASE_RESULT:
1521 start_test_case_result(priv, context, element_name, error);
1522 break;
1523 case IN_COMPLETE_TEST_CASE:
1524 start_complete_test_case(priv, context, element_name, error);
1525 break;
1526 case IN_COMPLETE_TEST_SUITE:
1527 start_complete_test_suite(priv, context, element_name, error);
1528 break;
1529 case IN_TEST_SUITE:
1530 case IN_TEST_CASE:
1531 case IN_TEST_ITERATOR:
1532 case IN_TEST:
1533 case IN_ITERATED_TEST:
1534 start_test_object(priv, context, element_name, error);
1535 break;
1536 case IN_TEST_OPTION:
1537 start_test_option(priv, context, element_name, error);
1538 break;
1539 case IN_RESULT_BACKTRACE:
1540 start_result_backtrace(priv, context, element_name, error);
1541 break;
1542 case IN_RESULT_BACKTRACE_ENTRY:
1543 start_result_backtrace_entry(priv, context, element_name, error);
1544 break;
1545 case IN_TEST_CONTEXT:
1546 start_test_context(priv, context, element_name, error);
1547 break;
1548 case IN_TEST_DATA:
1549 start_test_data(priv, context, element_name, error);
1550 break;
1551 default:
1552 invalid_element(priv, context, error);
1553 break;
1554 }
1555 }
1556
1557 static void
end_top_level_result(CutStreamParser * parser,CutStreamParserPrivate * priv,GMarkupParseContext * context,const gchar * element_name,GError ** error)1558 end_top_level_result (CutStreamParser *parser, CutStreamParserPrivate *priv,
1559 GMarkupParseContext *context,
1560 const gchar *element_name, GError **error)
1561 {
1562 if (priv->result) {
1563 g_object_unref(priv->result);
1564 priv->result = NULL;
1565 }
1566 }
1567
1568 static void
end_stream(CutStreamParser * parser,CutStreamParserPrivate * priv,GMarkupParseContext * context,const gchar * element_name,GError ** error)1569 end_stream (CutStreamParser *parser, CutStreamParserPrivate *priv,
1570 GMarkupParseContext *context,
1571 const gchar *element_name, GError **error)
1572 {
1573 if (priv->run_context)
1574 cut_run_context_emit_complete_run(priv->run_context,
1575 priv->stream_success);
1576 }
1577
1578 static void
end_result(CutStreamParser * parser,CutStreamParserPrivate * priv,GMarkupParseContext * context,const gchar * element_name,GError ** error)1579 end_result (CutStreamParser *parser, CutStreamParserPrivate *priv,
1580 GMarkupParseContext *context,
1581 const gchar *element_name, GError **error)
1582 {
1583 if (priv->result)
1584 g_signal_emit_by_name(parser, "result", priv->result);
1585 }
1586
1587 static void
end_test_context(CutStreamParser * parser,CutStreamParserPrivate * priv,GMarkupParseContext * context,const gchar * element_name,GError ** error)1588 end_test_context (CutStreamParser *parser, CutStreamParserPrivate *priv,
1589 GMarkupParseContext *context,
1590 const gchar *element_name, GError **error)
1591 {
1592 CutTestContext *test_context;
1593
1594 test_context = PEEK_TEST_CONTEXT(priv);
1595
1596 if (cut_test_context_get_test_suite(test_context))
1597 DROP_TEST_SUITE(priv);
1598 if (cut_test_context_get_test_case(test_context))
1599 DROP_TEST_CASE(priv);
1600 if (cut_test_context_get_test_iterator(test_context))
1601 DROP_TEST_ITERATOR(priv);
1602 if (cut_test_context_get_test(test_context))
1603 DROP_TEST(priv);
1604 if (cut_test_context_have_data(test_context))
1605 DROP_TEST_DATA(priv);
1606 }
1607
1608 static void
end_test_option(CutStreamParser * parser,CutStreamParserPrivate * priv,GMarkupParseContext * context,const gchar * element_name,GError ** error)1609 end_test_option (CutStreamParser *parser, CutStreamParserPrivate *priv,
1610 GMarkupParseContext *context,
1611 const gchar *element_name, GError **error)
1612 {
1613 if (!priv->option_name) {
1614 set_parse_error(priv, context, error, "option name is not set");
1615 } else if (!priv->option_value) {
1616 set_parse_error(priv, context, error, "option value is not set");
1617 } else {
1618 cut_test_set_attribute(PEEK_TEST(priv),
1619 priv->option_name,
1620 priv->option_value);
1621 }
1622
1623 if (priv->option_name) {
1624 g_free(priv->option_name);
1625 priv->option_name = NULL;
1626 }
1627
1628 if (priv->option_value) {
1629 g_free(priv->option_value);
1630 priv->option_value = NULL;
1631 }
1632 }
1633
1634 static void
end_result_backtrace(CutStreamParser * parser,CutStreamParserPrivate * priv,GMarkupParseContext * context,const gchar * element_name,GError ** error)1635 end_result_backtrace (CutStreamParser *parser, CutStreamParserPrivate *priv,
1636 GMarkupParseContext *context,
1637 const gchar *element_name, GError **error)
1638 {
1639 if (!priv->backtrace)
1640 return;
1641
1642 priv->backtrace = g_list_reverse(priv->backtrace);
1643 if (priv->result)
1644 cut_test_result_set_backtrace(priv->result, priv->backtrace);
1645
1646 g_list_foreach(priv->backtrace, (GFunc)g_object_unref, NULL);
1647 g_list_free(priv->backtrace);
1648 priv->backtrace = NULL;
1649 }
1650
1651 static void
end_result_backtrace_entry(CutStreamParser * parser,CutStreamParserPrivate * priv,GMarkupParseContext * context,const gchar * element_name,GError ** error)1652 end_result_backtrace_entry (CutStreamParser *parser,
1653 CutStreamParserPrivate *priv,
1654 GMarkupParseContext *context,
1655 const gchar *element_name, GError **error)
1656 {
1657 if (!priv->backtrace_entry)
1658 return; /* should check file name, line, info? */
1659
1660 priv->backtrace = g_list_prepend(priv->backtrace, priv->backtrace_entry);
1661 priv->backtrace_entry = NULL;
1662 }
1663
1664 static void
end_ready_test_suite(CutStreamParser * parser,CutStreamParserPrivate * priv,GMarkupParseContext * context,const gchar * element_name,GError ** error)1665 end_ready_test_suite (CutStreamParser *parser, CutStreamParserPrivate *priv,
1666 GMarkupParseContext *context,
1667 const gchar *element_name, GError **error)
1668 {
1669 if (!priv->ready_test_suite)
1670 return;
1671
1672 if (priv->run_context) {
1673 g_signal_emit_by_name(priv->run_context, "ready-test-suite",
1674 priv->ready_test_suite->test_suite,
1675 priv->ready_test_suite->n_test_cases,
1676 priv->ready_test_suite->n_tests);
1677 }
1678
1679 if (priv->ready_test_suite->test_suite)
1680 DROP_TEST_SUITE(priv);
1681 ready_test_suite_free(priv->ready_test_suite);
1682 priv->ready_test_suite = NULL;
1683 }
1684
1685 static void
end_start_test_suite(CutStreamParser * parser,CutStreamParserPrivate * priv,GMarkupParseContext * context,const gchar * element_name,GError ** error)1686 end_start_test_suite (CutStreamParser *parser, CutStreamParserPrivate *priv,
1687 GMarkupParseContext *context,
1688 const gchar *element_name, GError **error)
1689 {
1690 CutTestSuite *test_suite;
1691
1692 test_suite = POP_TEST_SUITE(priv);
1693 if (!test_suite)
1694 return;
1695
1696 if (priv->run_context)
1697 g_signal_emit_by_name(priv->run_context, "start-test-suite", test_suite);
1698 g_object_unref(test_suite);
1699 }
1700
1701 static void
end_ready_test_case(CutStreamParser * parser,CutStreamParserPrivate * priv,GMarkupParseContext * context,const gchar * element_name,GError ** error)1702 end_ready_test_case (CutStreamParser *parser, CutStreamParserPrivate *priv,
1703 GMarkupParseContext *context,
1704 const gchar *element_name, GError **error)
1705 {
1706 if (!priv->ready_test_case)
1707 return;
1708
1709 if (priv->run_context) {
1710 g_signal_emit_by_name(priv->run_context, "ready-test-case",
1711 priv->ready_test_case->test_case,
1712 priv->ready_test_case->n_tests);
1713 }
1714
1715 if (priv->ready_test_case->test_case)
1716 DROP_TEST_CASE(priv);
1717 ready_test_case_free(priv->ready_test_case);
1718 priv->ready_test_case = NULL;
1719 }
1720
1721 static void
end_start_test_case(CutStreamParser * parser,CutStreamParserPrivate * priv,GMarkupParseContext * context,const gchar * element_name,GError ** error)1722 end_start_test_case (CutStreamParser *parser, CutStreamParserPrivate *priv,
1723 GMarkupParseContext *context,
1724 const gchar *element_name, GError **error)
1725 {
1726 CutTestCase *test_case;
1727
1728 test_case = POP_TEST_CASE(priv);
1729 if (!test_case)
1730 return;
1731
1732 if (priv->run_context)
1733 g_signal_emit_by_name(priv->run_context, "start-test-case", test_case);
1734
1735 g_object_unref(test_case);
1736 }
1737
1738 static void
end_ready_test_iterator(CutStreamParser * parser,CutStreamParserPrivate * priv,GMarkupParseContext * context,const gchar * element_name,GError ** error)1739 end_ready_test_iterator (CutStreamParser *parser, CutStreamParserPrivate *priv,
1740 GMarkupParseContext *context,
1741 const gchar *element_name, GError **error)
1742 {
1743 if (!priv->ready_test_iterator)
1744 return;
1745
1746 if (priv->run_context) {
1747 g_signal_emit_by_name(priv->run_context, "ready-test-iterator",
1748 priv->ready_test_iterator->test_iterator,
1749 priv->ready_test_iterator->n_tests);
1750 }
1751
1752 if (priv->ready_test_iterator->test_iterator)
1753 DROP_TEST_ITERATOR(priv);
1754 ready_test_iterator_free(priv->ready_test_iterator);
1755 priv->ready_test_iterator = NULL;
1756 }
1757
1758 static void
end_start_test_iterator(CutStreamParser * parser,CutStreamParserPrivate * priv,GMarkupParseContext * context,const gchar * element_name,GError ** error)1759 end_start_test_iterator (CutStreamParser *parser, CutStreamParserPrivate *priv,
1760 GMarkupParseContext *context,
1761 const gchar *element_name, GError **error)
1762 {
1763 CutTestIterator *test_iterator;
1764
1765 test_iterator = POP_TEST_ITERATOR(priv);
1766 if (!test_iterator)
1767 return;
1768
1769 if (priv->run_context)
1770 g_signal_emit_by_name(priv->run_context,
1771 "start-test-iterator",
1772 test_iterator);
1773
1774 g_object_unref(test_iterator);
1775 }
1776
1777 static void
end_start_test(CutStreamParser * parser,CutStreamParserPrivate * priv,GMarkupParseContext * context,const gchar * element_name,GError ** error)1778 end_start_test (CutStreamParser *parser, CutStreamParserPrivate *priv,
1779 GMarkupParseContext *context,
1780 const gchar *element_name, GError **error)
1781 {
1782 if (!priv->start_test)
1783 return;
1784
1785 if (priv->run_context) {
1786 g_signal_emit_by_name(priv->run_context, "start-test",
1787 priv->start_test->test,
1788 priv->start_test->test_context);
1789 }
1790
1791 if (priv->start_test->test)
1792 DROP_TEST(priv);
1793 if (priv->start_test->test_context)
1794 DROP_TEST_CONTEXT(priv);
1795 start_test_free(priv->start_test);
1796 priv->start_test = NULL;
1797 }
1798
1799 static void
end_start_iterated_test(CutStreamParser * parser,CutStreamParserPrivate * priv,GMarkupParseContext * context,const gchar * element_name,GError ** error)1800 end_start_iterated_test (CutStreamParser *parser, CutStreamParserPrivate *priv,
1801 GMarkupParseContext *context,
1802 const gchar *element_name, GError **error)
1803 {
1804 if (!priv->start_iterated_test)
1805 return;
1806
1807 if (priv->run_context) {
1808 g_signal_emit_by_name(priv->run_context, "start-iterated-test",
1809 priv->start_iterated_test->iterated_test,
1810 priv->start_iterated_test->test_context);
1811 }
1812
1813 if (priv->start_iterated_test->iterated_test)
1814 DROP_TEST(priv);
1815 if (priv->start_iterated_test->test_context)
1816 DROP_TEST_CONTEXT(priv);
1817 start_iterated_test_free(priv->start_iterated_test);
1818 priv->start_iterated_test = NULL;
1819 }
1820
1821 static void
end_pass_assertion(CutStreamParser * parser,CutStreamParserPrivate * priv,GMarkupParseContext * context,const gchar * element_name,GError ** error)1822 end_pass_assertion (CutStreamParser *parser, CutStreamParserPrivate *priv,
1823 GMarkupParseContext *context,
1824 const gchar *element_name, GError **error)
1825 {
1826 if (!priv->pass_assertion)
1827 return;
1828
1829 if (priv->run_context)
1830 g_signal_emit_by_name(priv->run_context, "pass-assertion",
1831 priv->pass_assertion->test,
1832 priv->pass_assertion->test_context);
1833
1834 if (priv->pass_assertion->test)
1835 DROP_TEST(priv);
1836 if (priv->pass_assertion->test_context)
1837 DROP_TEST_CONTEXT(priv);
1838 pass_assertion_free(priv->pass_assertion);
1839 priv->pass_assertion = NULL;
1840 }
1841
1842 static void
end_test_result(CutStreamParser * parser,CutStreamParserPrivate * priv,GMarkupParseContext * context,const gchar * element_name,GError ** error)1843 end_test_result (CutStreamParser *parser, CutStreamParserPrivate *priv,
1844 GMarkupParseContext *context,
1845 const gchar *element_name, GError **error)
1846 {
1847 if (!priv->test_result)
1848 return;
1849
1850 if (priv->run_context) {
1851 CutTestResult *result;
1852 CutTestResultStatus status;
1853 const gchar *signal_name;
1854 gchar *full_signal_name;
1855
1856 result = priv->test_result->result;
1857 status = cut_test_result_get_status(result);
1858 signal_name = cut_test_result_status_to_signal_name(status);
1859 full_signal_name = g_strdup_printf("%s-test", signal_name);
1860 g_signal_emit_by_name(priv->run_context, full_signal_name,
1861 priv->test_result->test,
1862 priv->test_result->test_context,
1863 result);
1864 g_free(full_signal_name);
1865 }
1866
1867 if (priv->test_result->test)
1868 DROP_TEST(priv);
1869 if (priv->test_result->test_context)
1870 DROP_TEST_CONTEXT(priv);
1871 test_result_free(priv->test_result);
1872 priv->test_result = NULL;
1873 priv->result = NULL;
1874 }
1875
1876 static void
end_complete_iterated_test(CutStreamParser * parser,CutStreamParserPrivate * priv,GMarkupParseContext * context,const gchar * element_name,GError ** error)1877 end_complete_iterated_test (CutStreamParser *parser,
1878 CutStreamParserPrivate *priv,
1879 GMarkupParseContext *context,
1880 const gchar *element_name, GError **error)
1881 {
1882 if (!priv->complete_iterated_test)
1883 return;
1884
1885 if (priv->run_context)
1886 g_signal_emit_by_name(priv->run_context, "complete-iterated-test",
1887 priv->complete_iterated_test->iterated_test,
1888 priv->complete_iterated_test->test_context,
1889 priv->complete_success);
1890
1891 if (priv->complete_iterated_test->iterated_test)
1892 DROP_TEST(priv);
1893 if (priv->complete_iterated_test->test_context)
1894 DROP_TEST_CONTEXT(priv);
1895 complete_iterated_test_free(priv->complete_iterated_test);
1896 priv->complete_iterated_test = NULL;
1897 }
1898
1899 static void
end_complete_test(CutStreamParser * parser,CutStreamParserPrivate * priv,GMarkupParseContext * context,const gchar * element_name,GError ** error)1900 end_complete_test (CutStreamParser *parser, CutStreamParserPrivate *priv,
1901 GMarkupParseContext *context,
1902 const gchar *element_name, GError **error)
1903 {
1904 if (!priv->complete_test)
1905 return;
1906
1907 if (priv->run_context)
1908 g_signal_emit_by_name(priv->run_context, "complete-test",
1909 priv->complete_test->test,
1910 priv->complete_test->test_context,
1911 priv->complete_success);
1912
1913 if (priv->complete_test->test)
1914 DROP_TEST(priv);
1915 if (priv->complete_test->test_context)
1916 DROP_TEST_CONTEXT(priv);
1917 complete_test_free(priv->complete_test);
1918 priv->complete_test = NULL;
1919 priv->complete_success = TRUE;
1920 }
1921
1922 static void
end_test_iterator_result(CutStreamParser * parser,CutStreamParserPrivate * priv,GMarkupParseContext * context,const gchar * element_name,GError ** error)1923 end_test_iterator_result (CutStreamParser *parser, CutStreamParserPrivate *priv,
1924 GMarkupParseContext *context,
1925 const gchar *element_name, GError **error)
1926 {
1927 if (!priv->test_iterator_result)
1928 return;
1929
1930 if (priv->run_context) {
1931 CutTestResult *result;
1932 CutTestResultStatus status;
1933 const gchar *signal_name;
1934 gchar *full_signal_name;
1935
1936 result = priv->test_iterator_result->result;
1937 status = cut_test_result_get_status(result);
1938 signal_name = cut_test_result_status_to_signal_name(status);
1939 full_signal_name = g_strdup_printf("%s-test-iterator", signal_name);
1940 g_signal_emit_by_name(priv->run_context, full_signal_name,
1941 priv->test_iterator_result->test_iterator,
1942 priv->test_iterator_result->result);
1943 g_free(full_signal_name);
1944 }
1945
1946 if (priv->test_iterator_result->test_iterator)
1947 DROP_TEST_ITERATOR(priv);
1948 test_iterator_result_free(priv->test_iterator_result);
1949 priv->test_iterator_result = NULL;
1950 g_object_unref(priv->result);
1951 priv->result = NULL;
1952 }
1953
1954 static void
end_complete_test_iterator(CutStreamParser * parser,CutStreamParserPrivate * priv,GMarkupParseContext * context,const gchar * element_name,GError ** error)1955 end_complete_test_iterator (CutStreamParser *parser,
1956 CutStreamParserPrivate *priv,
1957 GMarkupParseContext *context,
1958 const gchar *element_name, GError **error)
1959 {
1960 CutTestIterator *test_iterator;
1961
1962 test_iterator = POP_TEST_ITERATOR(priv);
1963 if (!test_iterator)
1964 return;
1965
1966 if (priv->run_context)
1967 g_signal_emit_by_name(priv->run_context,
1968 "complete-test-iterator", test_iterator,
1969 priv->complete_success);
1970 g_object_unref(test_iterator);
1971 priv->complete_success = TRUE;
1972 }
1973
1974 static void
end_test_case_result(CutStreamParser * parser,CutStreamParserPrivate * priv,GMarkupParseContext * context,const gchar * element_name,GError ** error)1975 end_test_case_result (CutStreamParser *parser, CutStreamParserPrivate *priv,
1976 GMarkupParseContext *context,
1977 const gchar *element_name, GError **error)
1978 {
1979 if (!priv->test_case_result)
1980 return;
1981
1982 if (priv->run_context) {
1983 CutTestResult *result;
1984 CutTestResultStatus status;
1985 const gchar *signal_name;
1986 gchar *full_signal_name;
1987
1988 result = priv->test_case_result->result;
1989 status = cut_test_result_get_status(result);
1990 signal_name = cut_test_result_status_to_signal_name(status);
1991 full_signal_name = g_strdup_printf("%s-test-case", signal_name);
1992 g_signal_emit_by_name(priv->run_context, full_signal_name,
1993 priv->test_case_result->test_case,
1994 priv->test_case_result->result);
1995 g_free(full_signal_name);
1996 }
1997
1998 if (priv->test_case_result->test_case)
1999 DROP_TEST_CASE(priv);
2000 test_case_result_free(priv->test_case_result);
2001 priv->test_case_result = NULL;
2002 g_object_unref(priv->result);
2003 priv->result = NULL;
2004 }
2005
2006 static void
end_complete_test_case(CutStreamParser * parser,CutStreamParserPrivate * priv,GMarkupParseContext * context,const gchar * element_name,GError ** error)2007 end_complete_test_case (CutStreamParser *parser, CutStreamParserPrivate *priv,
2008 GMarkupParseContext *context,
2009 const gchar *element_name, GError **error)
2010 {
2011 CutTestCase *test_case;
2012
2013 test_case = POP_TEST_CASE(priv);
2014 if (!test_case)
2015 return;
2016
2017 if (priv->run_context)
2018 g_signal_emit_by_name(priv->run_context,
2019 "complete-test-case", test_case,
2020 priv->complete_success);
2021 g_object_unref(test_case);
2022 priv->complete_success = TRUE;
2023 }
2024
2025 static void
end_complete_test_suite(CutStreamParser * parser,CutStreamParserPrivate * priv,GMarkupParseContext * context,const gchar * element_name,GError ** error)2026 end_complete_test_suite (CutStreamParser *parser, CutStreamParserPrivate *priv,
2027 GMarkupParseContext *context,
2028 const gchar *element_name, GError **error)
2029 {
2030 CutTestSuite *test_suite;
2031
2032 test_suite = POP_TEST_SUITE(priv);
2033 if (!test_suite)
2034 return;
2035
2036 if (priv->run_context)
2037 g_signal_emit_by_name(priv->run_context,
2038 "complete-test-suite", test_suite,
2039 priv->complete_success);
2040 g_object_unref(test_suite);
2041 priv->complete_success = TRUE;
2042 }
2043
2044 static void
end_element_handler(GMarkupParseContext * context,const gchar * element_name,gpointer user_data,GError ** error)2045 end_element_handler (GMarkupParseContext *context,
2046 const gchar *element_name,
2047 gpointer user_data,
2048 GError **error)
2049 {
2050 CutStreamParser *parser = user_data;
2051 CutStreamParserPrivate *priv;
2052 ParseState state;
2053
2054 priv = CUT_STREAM_PARSER_GET_PRIVATE(parser);
2055
2056 state = POP_STATE(priv);
2057 switch (state) {
2058 case IN_TOP_LEVEL_RESULT:
2059 end_top_level_result(parser, priv, context, element_name, error);
2060 break;
2061 case IN_STREAM:
2062 end_stream(parser, priv, context, element_name, error);
2063 break;
2064 case IN_RESULT:
2065 end_result(parser, priv, context, element_name, error);
2066 break;
2067 case IN_TEST_CONTEXT:
2068 end_test_context(parser, priv, context, element_name, error);
2069 break;
2070 case IN_TEST_OPTION:
2071 end_test_option(parser, priv, context, element_name, error);
2072 break;
2073 case IN_RESULT_BACKTRACE:
2074 end_result_backtrace(parser, priv, context, element_name, error);
2075 break;
2076 case IN_RESULT_BACKTRACE_ENTRY:
2077 end_result_backtrace_entry(parser, priv, context, element_name, error);
2078 break;
2079 case IN_READY_TEST_SUITE:
2080 end_ready_test_suite(parser, priv, context, element_name, error);
2081 break;
2082 case IN_START_TEST_SUITE:
2083 end_start_test_suite(parser, priv, context, element_name, error);
2084 break;
2085 case IN_READY_TEST_CASE:
2086 end_ready_test_case(parser, priv, context, element_name, error);
2087 break;
2088 case IN_START_TEST_CASE:
2089 end_start_test_case(parser, priv, context, element_name, error);
2090 break;
2091 case IN_READY_TEST_ITERATOR:
2092 end_ready_test_iterator(parser, priv, context, element_name, error);
2093 break;
2094 case IN_START_TEST_ITERATOR:
2095 end_start_test_iterator(parser, priv, context, element_name, error);
2096 break;
2097 case IN_START_TEST:
2098 end_start_test(parser, priv, context, element_name, error);
2099 break;
2100 case IN_START_ITERATED_TEST:
2101 end_start_iterated_test(parser, priv, context, element_name, error);
2102 break;
2103 case IN_PASS_ASSERTION:
2104 end_pass_assertion(parser, priv, context, element_name, error);
2105 break;
2106 case IN_TEST_RESULT:
2107 end_test_result(parser, priv, context, element_name, error);
2108 break;
2109 case IN_COMPLETE_ITERATED_TEST:
2110 end_complete_iterated_test(parser, priv, context, element_name, error);
2111 break;
2112 case IN_COMPLETE_TEST:
2113 end_complete_test(parser, priv, context, element_name, error);
2114 break;
2115 case IN_TEST_ITERATOR_RESULT:
2116 end_test_iterator_result(parser, priv, context, element_name, error);
2117 break;
2118 case IN_COMPLETE_TEST_ITERATOR:
2119 end_complete_test_iterator(parser, priv, context, element_name, error);
2120 break;
2121 case IN_TEST_CASE_RESULT:
2122 end_test_case_result(parser, priv, context, element_name, error);
2123 break;
2124 case IN_COMPLETE_TEST_CASE:
2125 end_complete_test_case(parser, priv, context, element_name, error);
2126 break;
2127 case IN_COMPLETE_TEST_SUITE:
2128 end_complete_test_suite(parser, priv, context, element_name, error);
2129 break;
2130 default:
2131 break;
2132 }
2133
2134 g_free(g_queue_pop_tail(priv->element_stack));
2135 }
2136
2137 static CutTestResultStatus
result_name_to_status(const gchar * name)2138 result_name_to_status (const gchar *name)
2139 {
2140 if (g_str_equal(name, "success"))
2141 return CUT_TEST_RESULT_SUCCESS;
2142 else if (g_str_equal(name, "failure"))
2143 return CUT_TEST_RESULT_FAILURE;
2144 else if (g_str_equal(name, "error"))
2145 return CUT_TEST_RESULT_ERROR;
2146 else if (g_str_equal(name, "pending"))
2147 return CUT_TEST_RESULT_PENDING;
2148 else if (g_str_equal(name, "notification"))
2149 return CUT_TEST_RESULT_NOTIFICATION;
2150 else if (g_str_equal(name, "omission"))
2151 return CUT_TEST_RESULT_OMISSION;
2152 else if (g_str_equal(name, "crash"))
2153 return CUT_TEST_RESULT_CRASH;
2154
2155 return CUT_TEST_RESULT_INVALID;
2156 }
2157
2158 static gboolean
is_integer(const gchar * str)2159 is_integer (const gchar *str)
2160 {
2161 gint i = 0;
2162
2163 if (!str)
2164 return FALSE;
2165
2166 while (str[i]) {
2167 if (!g_ascii_isdigit(str[i]))
2168 return FALSE;
2169 i++;
2170 }
2171 return TRUE;
2172 }
2173
2174 static gboolean
is_boolean(const gchar * str)2175 is_boolean (const gchar *str)
2176 {
2177 if (!str)
2178 return FALSE;
2179
2180 return g_ascii_strcasecmp(str, "true") == 0 ||
2181 g_ascii_strcasecmp(str, "false") == 0;
2182 }
2183
2184 static gboolean
string_to_boolean(const gchar * string)2185 string_to_boolean (const gchar *string)
2186 {
2187 return g_ascii_strcasecmp("true", string) == 0;
2188 }
2189
2190 static CutTest *
target_test_object(CutStreamParserPrivate * priv,ParseState parent_state)2191 target_test_object (CutStreamParserPrivate *priv, ParseState parent_state)
2192 {
2193 CutTest *target = NULL;
2194
2195 switch (parent_state) {
2196 case IN_TEST_SUITE:
2197 target = CUT_TEST(PEEK_TEST_SUITE(priv));
2198 break;
2199 case IN_TEST_CASE:
2200 target = CUT_TEST(PEEK_TEST_CASE(priv));
2201 break;
2202 case IN_TEST_ITERATOR:
2203 target = CUT_TEST(PEEK_TEST_ITERATOR(priv));
2204 break;
2205 case IN_TEST:
2206 case IN_ITERATED_TEST:
2207 target = PEEK_TEST(priv);
2208 break;
2209 default:
2210 break;
2211 }
2212
2213 return target;
2214 }
2215
2216 static void
text_test_name(CutStreamParserPrivate * priv,GMarkupParseContext * context,const gchar * text,gsize text_len,GError ** error)2217 text_test_name (CutStreamParserPrivate *priv, GMarkupParseContext *context,
2218 const gchar *text, gsize text_len, GError **error)
2219 {
2220 CutTest *target;
2221
2222 target = target_test_object(priv, PEEK_NTH_STATE(priv, 1));
2223 if (target) {
2224 cut_test_set_name(target, text);
2225 } else {
2226 set_parse_error(priv, context, error, "can't find test name target");
2227 }
2228 }
2229
2230 static void
text_test_description(CutStreamParserPrivate * priv,GMarkupParseContext * context,const gchar * text,gsize text_len,GError ** error)2231 text_test_description (CutStreamParserPrivate *priv,
2232 GMarkupParseContext *context,
2233 const gchar *text, gsize text_len, GError **error)
2234 {
2235 CutTest *target;
2236
2237 target = target_test_object(priv, PEEK_NTH_STATE(priv, 1));
2238 if (target) {
2239 cut_test_set_attribute(target, "description", text);
2240 } else {
2241 set_parse_error(priv, context, error,
2242 "can't find test description target");
2243 }
2244 }
2245
2246 static void
text_test_option_name(CutStreamParserPrivate * priv,GMarkupParseContext * context,const gchar * text,gsize text_len,GError ** error)2247 text_test_option_name (CutStreamParserPrivate *priv,
2248 GMarkupParseContext *context,
2249 const gchar *text, gsize text_len, GError **error)
2250 {
2251 if (priv->option_name) {
2252 set_parse_error(priv, context, error, "multiple option name: %s", text);
2253 } else {
2254 priv->option_name = g_strdup(text);
2255 }
2256 }
2257
2258 static void
text_test_option_value(CutStreamParserPrivate * priv,GMarkupParseContext * context,const gchar * text,gsize text_len,GError ** error)2259 text_test_option_value (CutStreamParserPrivate *priv,
2260 GMarkupParseContext *context,
2261 const gchar *text, gsize text_len, GError **error)
2262 {
2263 if (priv->option_value) {
2264 set_parse_error(priv, context, error, "multiple option value: %s", text);
2265 } else {
2266 priv->option_value = g_strdup(text);
2267 }
2268 }
2269
2270 static void
text_test_start_time(CutStreamParserPrivate * priv,GMarkupParseContext * context,const gchar * text,gsize text_len,GError ** error)2271 text_test_start_time (CutStreamParserPrivate *priv,
2272 GMarkupParseContext *context,
2273 const gchar *text, gsize text_len, GError **error)
2274 {
2275 CutTest *target;
2276
2277 target = target_test_object(priv, PEEK_NTH_STATE(priv, 1));
2278 if (target) {
2279 GTimeVal start_time;
2280
2281 if (g_time_val_from_iso8601(text, &start_time)) {
2282 cut_test_set_start_time(target, &start_time);
2283 } else {
2284 set_parse_error(priv, context, error,
2285 "invalid start-time value (not ISO 8601 format): %s",
2286 text);
2287 }
2288 } else {
2289 set_parse_error(priv, context, error,
2290 "can't find test start time target");
2291 }
2292 }
2293
2294 static void
text_test_elapsed(CutStreamParserPrivate * priv,GMarkupParseContext * context,const gchar * text,gsize text_len,GError ** error)2295 text_test_elapsed (CutStreamParserPrivate *priv,
2296 GMarkupParseContext *context,
2297 const gchar *text, gsize text_len, GError **error)
2298 {
2299 CutTest *target;
2300
2301 target = target_test_object(priv, PEEK_NTH_STATE(priv, 1));
2302 if (target) {
2303 gdouble elapsed;
2304 gchar *end_position;
2305
2306 elapsed = g_ascii_strtod(text, &end_position);
2307 if (text != end_position && end_position[0] == '\0') {
2308 cut_test_set_elapsed(target, elapsed);
2309 } else {
2310 set_parse_error(priv, context, error,
2311 "invalid elapsed value: %s", text);
2312 }
2313 } else {
2314 set_parse_error(priv, context, error, "can't find test elapsed target");
2315 }
2316 }
2317
2318 static void
text_result_status(CutStreamParserPrivate * priv,GMarkupParseContext * context,const gchar * text,gsize text_len,GError ** error)2319 text_result_status (CutStreamParserPrivate *priv, GMarkupParseContext *context,
2320 const gchar *text, gsize text_len, GError **error)
2321 {
2322 CutTestResultStatus status;
2323
2324 status = result_name_to_status(text);
2325 if (status == CUT_TEST_RESULT_INVALID) {
2326 set_parse_error(priv, context, error, "invalid status: %s", text);
2327 } else {
2328 cut_test_result_set_status(priv->result, status);
2329 }
2330 }
2331
2332 static void
text_result_detail(CutStreamParserPrivate * priv,GMarkupParseContext * context,const gchar * text,gsize text_len,GError ** error)2333 text_result_detail (CutStreamParserPrivate *priv, GMarkupParseContext *context,
2334 const gchar *text, gsize text_len, GError **error)
2335 {
2336 cut_test_result_set_message(priv->result, text);
2337 }
2338
2339 static void
text_result_backtrace_entry_file(CutStreamParserPrivate * priv,GMarkupParseContext * context,const gchar * text,gsize text_len,GError ** error)2340 text_result_backtrace_entry_file (CutStreamParserPrivate *priv,
2341 GMarkupParseContext *context,
2342 const gchar *text, gsize text_len,
2343 GError **error)
2344 {
2345 cut_backtrace_entry_set_file(priv->backtrace_entry, text);
2346 }
2347
2348 static void
text_result_backtrace_entry_line(CutStreamParserPrivate * priv,GMarkupParseContext * context,const gchar * text,gsize text_len,GError ** error)2349 text_result_backtrace_entry_line (CutStreamParserPrivate *priv,
2350 GMarkupParseContext *context,
2351 const gchar *text, gsize text_len,
2352 GError **error)
2353 {
2354 if (is_integer(text)) {
2355 cut_backtrace_entry_set_line(priv->backtrace_entry, atoi(text));
2356 } else {
2357 set_parse_error(priv, context, error, "invalid line number: %s", text);
2358 }
2359 }
2360
2361 static void
text_result_backtrace_entry_info(CutStreamParserPrivate * priv,GMarkupParseContext * context,const gchar * text,gsize text_len,GError ** error)2362 text_result_backtrace_entry_info (CutStreamParserPrivate *priv,
2363 GMarkupParseContext *context,
2364 const gchar *text, gsize text_len,
2365 GError **error)
2366 {
2367 const gchar *info_start;
2368
2369 info_start = strstr(text, "):");
2370 if (info_start) {
2371 gchar *function;
2372
2373 function = g_strndup(text, info_start - text + strlen(")"));
2374 info_start += strlen("):");
2375 while (info_start[0] && info_start[0] == ' ')
2376 info_start++;
2377 cut_backtrace_entry_set_function(priv->backtrace_entry, function);
2378 cut_backtrace_entry_set_info(priv->backtrace_entry, info_start);
2379 g_free(function);
2380 } else if (g_str_has_suffix(text, ")") && strstr(text, "(")) {
2381 cut_backtrace_entry_set_function(priv->backtrace_entry, text);
2382 } else {
2383 cut_backtrace_entry_set_info(priv->backtrace_entry, text);
2384 }
2385 }
2386
2387
2388 static void
text_result_start_time(CutStreamParserPrivate * priv,GMarkupParseContext * context,const gchar * text,gsize text_len,GError ** error)2389 text_result_start_time (CutStreamParserPrivate *priv,
2390 GMarkupParseContext *context,
2391 const gchar *text, gsize text_len, GError **error)
2392 {
2393 GTimeVal start_time;
2394
2395 if (g_time_val_from_iso8601(text, &start_time)) {
2396 cut_test_result_set_start_time(priv->result, &start_time);
2397 } else {
2398 set_parse_error(priv, context, error,
2399 "invalid start-time value (not ISO 8601 format): %s",
2400 text);
2401 }
2402 }
2403
2404 static void
text_result_elapsed(CutStreamParserPrivate * priv,GMarkupParseContext * context,const gchar * text,gsize text_len,GError ** error)2405 text_result_elapsed (CutStreamParserPrivate *priv, GMarkupParseContext *context,
2406 const gchar *text, gsize text_len, GError **error)
2407 {
2408 gdouble elapsed;
2409 gchar *end_position;
2410
2411 elapsed = g_ascii_strtod(text, &end_position);
2412 if (text != end_position && end_position[0] == '\0') {
2413 cut_test_result_set_elapsed(priv->result, elapsed);
2414 } else {
2415 set_parse_error(priv, context, error, "invalid elapsed value: %s", text);
2416 }
2417 }
2418
2419 static void
text_result_expected(CutStreamParserPrivate * priv,GMarkupParseContext * context,const gchar * text,gsize text_len,GError ** error)2420 text_result_expected (CutStreamParserPrivate *priv, GMarkupParseContext *context,
2421 const gchar *text, gsize text_len, GError **error)
2422 {
2423 cut_test_result_set_expected(priv->result, text);
2424 }
2425
2426 static void
text_result_actual(CutStreamParserPrivate * priv,GMarkupParseContext * context,const gchar * text,gsize text_len,GError ** error)2427 text_result_actual (CutStreamParserPrivate *priv, GMarkupParseContext *context,
2428 const gchar *text, gsize text_len, GError **error)
2429 {
2430 cut_test_result_set_actual(priv->result, text);
2431 }
2432
2433 static void
text_result_diff(CutStreamParserPrivate * priv,GMarkupParseContext * context,const gchar * text,gsize text_len,GError ** error)2434 text_result_diff (CutStreamParserPrivate *priv, GMarkupParseContext *context,
2435 const gchar *text, gsize text_len, GError **error)
2436 {
2437 cut_test_result_set_diff(priv->result, text);
2438 }
2439
2440 static void
text_result_folded_diff(CutStreamParserPrivate * priv,GMarkupParseContext * context,const gchar * text,gsize text_len,GError ** error)2441 text_result_folded_diff (CutStreamParserPrivate *priv,
2442 GMarkupParseContext *context,
2443 const gchar *text, gsize text_len, GError **error)
2444 {
2445 cut_test_result_set_folded_diff(priv->result, text);
2446 }
2447
2448 static void
text_ready_test_suite_n_test_cases(CutStreamParserPrivate * priv,GMarkupParseContext * context,const gchar * text,gsize text_len,GError ** error)2449 text_ready_test_suite_n_test_cases (CutStreamParserPrivate *priv,
2450 GMarkupParseContext *context,
2451 const gchar *text, gsize text_len,
2452 GError **error)
2453 {
2454 if (is_integer(text)) {
2455 priv->ready_test_suite->n_test_cases = atoi(text);
2456 } else {
2457 set_parse_error(priv, context, error,
2458 "invalid # of test cases: %s", text);
2459 }
2460 }
2461
2462 static void
text_ready_test_suite_n_tests(CutStreamParserPrivate * priv,GMarkupParseContext * context,const gchar * text,gsize text_len,GError ** error)2463 text_ready_test_suite_n_tests (CutStreamParserPrivate *priv,
2464 GMarkupParseContext *context,
2465 const gchar *text, gsize text_len,
2466 GError **error)
2467 {
2468 if (is_integer(text)) {
2469 priv->ready_test_suite->n_tests = atoi(text);
2470 } else {
2471 set_parse_error(priv, context, error, "invalid # of tests: %s", text);
2472 }
2473 }
2474
2475 static void
text_ready_test_case_n_tests(CutStreamParserPrivate * priv,GMarkupParseContext * context,const gchar * text,gsize text_len,GError ** error)2476 text_ready_test_case_n_tests (CutStreamParserPrivate *priv,
2477 GMarkupParseContext *context,
2478 const gchar *text, gsize text_len, GError **error)
2479 {
2480 if (is_integer(text)) {
2481 priv->ready_test_case->n_tests = atoi(text);
2482 } else {
2483 set_parse_error(priv, context, error, "invalid # of tests: %s", text);
2484 }
2485 }
2486
2487 static void
text_ready_test_iterator_n_tests(CutStreamParserPrivate * priv,GMarkupParseContext * context,const gchar * text,gsize text_len,GError ** error)2488 text_ready_test_iterator_n_tests (CutStreamParserPrivate *priv,
2489 GMarkupParseContext *context,
2490 const gchar *text, gsize text_len,
2491 GError **error)
2492 {
2493 if (is_integer(text)) {
2494 priv->ready_test_iterator->n_tests = atoi(text);
2495 } else {
2496 set_parse_error(priv, context, error, "invalid # of tests: %s", text);
2497 }
2498 }
2499
2500 static void
text_test_data_name(CutStreamParserPrivate * priv,GMarkupParseContext * context,const gchar * text,gsize text_len,GError ** error)2501 text_test_data_name (CutStreamParserPrivate *priv,
2502 GMarkupParseContext *context,
2503 const gchar *text, gsize text_len, GError **error)
2504 {
2505 CutTestData *test_data;
2506
2507 test_data = PEEK_TEST_DATA(priv);
2508 cut_test_data_set_name(test_data, text);
2509 }
2510
2511 static void
text_test_context_failed(CutStreamParserPrivate * priv,GMarkupParseContext * context,const gchar * text,gsize text_len,GError ** error)2512 text_test_context_failed (CutStreamParserPrivate *priv,
2513 GMarkupParseContext *context,
2514 const gchar *text, gsize text_len, GError **error)
2515 {
2516 if (is_boolean(text)) {
2517 cut_test_context_set_failed(PEEK_TEST_CONTEXT(priv),
2518 string_to_boolean(text));
2519 } else {
2520 set_parse_error(priv, context, error, "invalid boolean value: %s", text);
2521 }
2522 }
2523
2524 static void
text_complete_success(CutStreamParserPrivate * priv,GMarkupParseContext * context,const gchar * text,gsize text_len,GError ** error)2525 text_complete_success (CutStreamParserPrivate *priv,
2526 GMarkupParseContext *context,
2527 const gchar *text, gsize text_len, GError **error)
2528 {
2529 if (is_boolean(text)) {
2530 priv->complete_success = string_to_boolean(text);
2531 } else {
2532 set_parse_error(priv, context, error, "invalid boolean value: %s", text);
2533 }
2534 }
2535
2536 static void
text_stream_success(CutStreamParserPrivate * priv,GMarkupParseContext * context,const gchar * text,gsize text_len,GError ** error)2537 text_stream_success (CutStreamParserPrivate *priv, GMarkupParseContext *context,
2538 const gchar *text, gsize text_len, GError **error)
2539 {
2540 if (is_boolean(text)) {
2541 priv->stream_success = string_to_boolean(text);
2542 } else {
2543 set_parse_error(priv, context, error, "invalid boolean value: %s", text);
2544 }
2545 }
2546
2547 static void
text_handler(GMarkupParseContext * context,const gchar * text,gsize text_len,gpointer user_data,GError ** error)2548 text_handler (GMarkupParseContext *context,
2549 const gchar *text,
2550 gsize text_len,
2551 gpointer user_data,
2552 GError **error)
2553 {
2554 CutStreamParser *parser = user_data;
2555 CutStreamParserPrivate *priv;
2556 ParseState state;
2557
2558 priv = CUT_STREAM_PARSER_GET_PRIVATE(parser);
2559
2560 state = PEEK_STATE(priv);
2561 switch (state) {
2562 case IN_TEST_NAME:
2563 text_test_name(priv, context, text, text_len, error);
2564 break;
2565 case IN_TEST_DESCRIPTION:
2566 text_test_description(priv, context, text, text_len, error);
2567 break;
2568 case IN_TEST_OPTION_NAME:
2569 text_test_option_name(priv, context, text, text_len, error);
2570 break;
2571 case IN_TEST_OPTION_VALUE:
2572 text_test_option_value(priv, context, text, text_len, error);
2573 break;
2574 case IN_TEST_START_TIME:
2575 text_test_start_time(priv, context, text, text_len, error);
2576 break;
2577 case IN_TEST_ELAPSED:
2578 text_test_elapsed(priv, context, text, text_len, error);
2579 break;
2580 case IN_RESULT_STATUS:
2581 text_result_status(priv, context, text, text_len, error);
2582 break;
2583 case IN_RESULT_DETAIL:
2584 text_result_detail(priv, context, text, text_len, error);
2585 break;
2586 case IN_RESULT_BACKTRACE_ENTRY_FILE:
2587 text_result_backtrace_entry_file(priv, context, text, text_len, error);
2588 break;
2589 case IN_RESULT_BACKTRACE_ENTRY_LINE:
2590 text_result_backtrace_entry_line(priv, context, text, text_len, error);
2591 break;
2592 case IN_RESULT_BACKTRACE_ENTRY_INFO:
2593 text_result_backtrace_entry_info(priv, context, text, text_len, error);
2594 break;
2595 case IN_RESULT_START_TIME:
2596 text_result_start_time(priv, context, text, text_len, error);
2597 break;
2598 case IN_RESULT_ELAPSED:
2599 text_result_elapsed(priv, context, text, text_len, error);
2600 break;
2601 case IN_RESULT_EXPECTED:
2602 text_result_expected(priv, context, text, text_len, error);
2603 break;
2604 case IN_RESULT_ACTUAL:
2605 text_result_actual(priv, context, text, text_len, error);
2606 break;
2607 case IN_RESULT_DIFF:
2608 text_result_diff(priv, context, text, text_len, error);
2609 break;
2610 case IN_RESULT_FOLDED_DIFF:
2611 text_result_folded_diff(priv, context, text, text_len, error);
2612 break;
2613 case IN_READY_TEST_SUITE_N_TEST_CASES:
2614 text_ready_test_suite_n_test_cases(priv, context, text, text_len, error);
2615 break;
2616 case IN_READY_TEST_SUITE_N_TESTS:
2617 text_ready_test_suite_n_tests(priv, context, text, text_len, error);
2618 break;
2619 case IN_READY_TEST_CASE_N_TESTS:
2620 text_ready_test_case_n_tests(priv, context, text, text_len, error);
2621 break;
2622 case IN_READY_TEST_ITERATOR_N_TESTS:
2623 text_ready_test_iterator_n_tests(priv, context, text, text_len, error);
2624 break;
2625 case IN_TEST_DATA_NAME:
2626 text_test_data_name(priv, context, text, text_len, error);
2627 break;
2628 case IN_TEST_CONTEXT_FAILED:
2629 text_test_context_failed(priv, context, text, text_len, error);
2630 break;
2631 case IN_COMPLETE_SUCCESS:
2632 text_complete_success(priv, context, text, text_len, error);
2633 case IN_STREAM_SUCCESS:
2634 text_stream_success(priv, context, text, text_len, error);
2635 break;
2636 default:
2637 break;
2638 }
2639 }
2640
2641 static void
error_handler(GMarkupParseContext * context,GError * error,gpointer user_data)2642 error_handler (GMarkupParseContext *context,
2643 GError *error,
2644 gpointer user_data)
2645 {
2646 /* should emit error signal to run_context? */
2647 }
2648
2649 /*
2650 vi:ts=4:nowrap:ai:expandtab:sw=4
2651 */
2652