1 /* mutest-spec.c: Specifications
2  *
3  * µTest - Copyright 2019  Emmanuele Bassi
4  *
5  * SPDX-License-Identifier: MIT
6  */
7 
8 #include "mutest-private.h"
9 
10 #include <string.h>
11 #include <stdlib.h>
12 #include <stdio.h>
13 
14 void
mutest_it_full(const char * file,int line,const char * func_name,const char * description,mutest_spec_func_t func)15 mutest_it_full (const char *file,
16                 int line,
17                 const char *func_name,
18                 const char *description,
19                 mutest_spec_func_t func)
20 {
21   if (description == NULL)
22     mutest_assert_if_reached ("missing spec description");
23 
24   if (func == NULL)
25     mutest_assert_if_reached ("missing spec functions");
26 
27   if (mutest_get_current_suite () == NULL)
28     mutest_assert_if_reached ("missing suite");
29 
30   mutest_spec_t spec = {
31     .description = description,
32     .file = file,
33     .line = line,
34     .func_name = func_name,
35     .skip_all = false,
36     .n_expects = 0,
37     .pass = 0,
38     .fail = 0,
39     .skip = 0,
40   };
41 
42   mutest_format_spec_preamble (&spec);
43 
44   mutest_set_current_spec (&spec);
45 
46   mutest_suite_t *suite = mutest_get_current_suite ();
47 
48   if (suite->before_each_hook != NULL)
49     suite->before_each_hook ();
50 
51   /* If mutest_spec_skip() was called inside the before_each() hook,
52    * then we don't call func(), and mark the whole spec as skipped
53    */
54   if (spec.skip_all)
55     {
56       spec.n_expects = 1;
57       spec.skip = 1;
58     }
59   else
60     {
61       spec.start_time = mutest_get_current_time ();
62       func (&spec);
63       spec.end_time = mutest_get_current_time ();
64 
65       /* If mutest_spec_skip() was called in func() then we mark the
66        * whole spec as skipped regardless of how many expectations
67        * were actually ran
68        */
69       if (spec.skip_all)
70         {
71           spec.n_expects = 1;
72           spec.skip = 1;
73         }
74     }
75 
76   mutest_suite_add_spec_results (suite, &spec);
77 
78   if (suite->after_each_hook != NULL)
79     suite->after_each_hook ();
80 
81   mutest_set_current_spec (NULL);
82 
83   mutest_format_spec_results (&spec);
84 }
85 
86 void
mutest_spec_skip(const char * reason)87 mutest_spec_skip (const char *reason)
88 {
89   mutest_spec_t *spec = mutest_get_current_spec ();
90   if (spec == NULL)
91     mutest_assert_if_reached ("skip called without a spec");
92 
93   spec->skip_all = true;
94   spec->skip_reason = reason;
95 }
96 
97 void
mutest_spec_add_expect_result(mutest_spec_t * spec,mutest_expect_t * expect)98 mutest_spec_add_expect_result (mutest_spec_t *spec,
99                                mutest_expect_t *expect)
100 {
101   switch (expect->result)
102     {
103     case MUTEST_RESULT_PASS:
104       spec->n_expects += 1;
105       spec->pass += 1;
106       break;
107 
108     case MUTEST_RESULT_FAIL:
109       spec->n_expects += 1;
110       spec->fail += 1;
111       break;
112 
113     case MUTEST_RESULT_SKIP:
114       spec->n_expects += 1;
115       spec->skip += 1;
116       break;
117     }
118 }
119