1/* ==========================================
2    Unity Project - A Test Framework for C
3    Copyright (c) 2007 Mike Karlesky, Mark VanderVoord, Greg Williams
4    [Released under MIT License. Please refer to license.txt for details]
5========================================== */
6
7#include <setjmp.h>
8#include <stdio.h>
9#include "unity.h"
10#include "types_for_test.h"
11
12/* Include Passthroughs for Linking Tests */
13void putcharSpy(int c) { (void)putchar(c);}
14void flushSpy(void) {}
15
16#define EXPECT_ABORT_BEGIN \
17    if (TEST_PROTECT())    \
18    {
19
20#define VERIFY_FAILS_END                                                       \
21    }                                                                          \
22    Unity.CurrentTestFailed = (Unity.CurrentTestFailed != 0) ? 0 : 1;          \
23    if (Unity.CurrentTestFailed == 1) {                                        \
24      SetToOneMeanWeAlreadyCheckedThisGuy = 1;                                 \
25      UnityPrintNumberUnsigned(Unity.CurrentTestLineNumber);                   \
26      UNITY_OUTPUT_CHAR(':');                                                  \
27      UnityPrint(Unity.CurrentTestName);                                       \
28      UnityPrint(":FAIL: [[[[ Test Should Have Failed But Did Not ]]]]");      \
29      UNITY_OUTPUT_CHAR('\n');                                                 \
30    }
31
32#define VERIFY_IGNORES_END                                                     \
33    }                                                                          \
34    Unity.CurrentTestFailed = (Unity.CurrentTestIgnored != 0) ? 0 : 1;         \
35    Unity.CurrentTestIgnored = 0;                                              \
36    if (Unity.CurrentTestFailed == 1) {                                        \
37      SetToOneMeanWeAlreadyCheckedThisGuy = 1;                                 \
38      UnityPrintNumberUnsigned(Unity.CurrentTestLineNumber);                   \
39      UNITY_OUTPUT_CHAR(':');                                                  \
40      UnityPrint(Unity.CurrentTestName);                                       \
41      UnityPrint(":FAIL: [[[[ Test Should Have Ignored But Did Not ]]]]");     \
42      UNITY_OUTPUT_CHAR('\n');                                                 \
43    }
44
45static int SetToOneToFailInTearDown;
46static int SetToOneMeanWeAlreadyCheckedThisGuy;
47static unsigned NextExpectedStringIndex;
48static unsigned NextExpectedCharIndex;
49static unsigned NextExpectedSpaceIndex;
50
51void suiteSetUp(void)
52{
53    NextExpectedStringIndex = 0;
54    NextExpectedCharIndex = 0;
55    NextExpectedSpaceIndex = 0;
56}
57
58void setUp(void)
59{
60  SetToOneToFailInTearDown = 0;
61  SetToOneMeanWeAlreadyCheckedThisGuy = 0;
62}
63
64void tearDown(void)
65{
66  if (SetToOneToFailInTearDown == 1)
67    TEST_FAIL_MESSAGE("<= Failed in tearDown");
68  if ((SetToOneMeanWeAlreadyCheckedThisGuy == 0) && (Unity.CurrentTestFailed > 0))
69  {
70    UnityPrint(": [[[[ Test Should Have Passed But Did Not ]]]]");
71    UNITY_OUTPUT_CHAR('\n');
72  }
73}
74
75TEST_CASE(0)
76TEST_CASE(44)
77TEST_CASE((90)+9)
78void test_TheseShouldAllPass(int Num)
79{
80    TEST_ASSERT_TRUE(Num < 100);
81}
82
83TEST_CASE(3)
84TEST_CASE(77)
85TEST_CASE( (99) + 1 - (1))
86void test_TheseShouldAllFail(int Num)
87{
88    EXPECT_ABORT_BEGIN
89    TEST_ASSERT_TRUE(Num > 100);
90    VERIFY_FAILS_END
91}
92
93TEST_CASE(1)
94TEST_CASE(44)
95TEST_CASE(99)
96TEST_CASE(98)
97void test_TheseAreEveryOther(int Num)
98{
99    if (Num & 1)
100    {
101        EXPECT_ABORT_BEGIN
102        TEST_ASSERT_TRUE(Num > 100);
103        VERIFY_FAILS_END
104    }
105    else
106    {
107        TEST_ASSERT_TRUE(Num < 100);
108    }
109}
110
111void test_NormalPassesStillWork(void)
112{
113    TEST_ASSERT_TRUE(1);
114}
115
116void test_NormalFailsStillWork(void)
117{
118    EXPECT_ABORT_BEGIN
119    TEST_ASSERT_TRUE(0);
120    VERIFY_FAILS_END
121}
122
123TEST_CASE(0, "abc")
124TEST_CASE(1, "{")
125TEST_CASE(2, "}")
126TEST_CASE(3, ";")
127TEST_CASE(4, "\"quoted\"")
128void test_StringsArePreserved(unsigned index, const char * str)
129{
130    static const char * const expected[] =
131    {
132        "abc",
133        "{",
134        "}",
135        ";",
136        "\"quoted\""
137    };
138
139    /* Ensure that no test cases are skipped by tracking the next expected index */
140    TEST_ASSERT_EQUAL_UINT32(NextExpectedStringIndex, index);
141    TEST_ASSERT_LESS_THAN(sizeof(expected) / sizeof(expected[0]), index);
142    TEST_ASSERT_EQUAL_STRING(expected[index], str);
143
144    NextExpectedStringIndex++;
145}
146
147TEST_CASE(0, 'x')
148TEST_CASE(1, '{')
149TEST_CASE(2, '}')
150TEST_CASE(3, ';')
151TEST_CASE(4, '\'')
152TEST_CASE(5, '"')
153void test_CharsArePreserved(unsigned index, char c)
154{
155    static const char expected[] =
156    {
157        'x',
158        '{',
159        '}',
160        ';',
161        '\'',
162        '"'
163    };
164
165    /* Ensure that no test cases are skipped by tracking the next expected index */
166    TEST_ASSERT_EQUAL_UINT32(NextExpectedCharIndex, index);
167    TEST_ASSERT_LESS_THAN(sizeof(expected) / sizeof(expected[0]), index);
168    TEST_ASSERT_EQUAL(expected[index], c);
169
170    NextExpectedCharIndex++;
171}
172
173TEST_RANGE([0, 10, 2])
174void test_SingleRange(unsigned value)
175{
176  TEST_ASSERT_EQUAL(0, value % 2);
177  TEST_ASSERT_LESS_OR_EQUAL(10, value);
178}
179
180TEST_RANGE([1, 2, 1], [2, 1, -1])
181void test_TwoRanges(unsigned first, unsigned second)
182{
183  TEST_ASSERT_LESS_OR_EQUAL(4, first * second);
184}
185
186TEST_RANGE(<0, 10, 2>)
187void test_SingleExclusiveRange(unsigned value)
188{
189  TEST_ASSERT_EQUAL(0, value % 2);
190  TEST_ASSERT_LESS_THAN(10, value);
191}
192
193TEST_RANGE([2, 4, 1], <1, 2, 1>)
194void test_BothInclusiveAndExclusiveRange(unsigned first, unsigned second)
195{
196  TEST_ASSERT_LESS_THAN(first, second);
197}
198
199TEST_CASE(0,
200
201          1)
202TEST_CASE(1,
203
204          2
205
206  )
207TEST_RANGE([2,
208            5  ,
209            1], [6, 6, 1])
210TEST_CASE(
211
212  6 , 7)
213TEST_MATRIX([7,
214             8   ,
215
216             9, 10],
217    [
218      11]
219
220      )
221void test_SpaceInTestCase(unsigned index, unsigned bigger)
222{
223  TEST_ASSERT_EQUAL_UINT32(NextExpectedSpaceIndex, index);
224  TEST_ASSERT_LESS_THAN(bigger, index);
225
226  NextExpectedSpaceIndex++;
227}
228
229TEST_MATRIX([1, 5, (2*2)+1, 4])
230void test_SingleMatix(unsigned value)
231{
232  TEST_ASSERT_LESS_OR_EQUAL(10, value);
233}
234
235TEST_MATRIX([2, 5l, 4u+3, 4ul], [-2, 3])
236void test_TwoMatrices(unsigned first, signed second)
237{
238  static unsigned idx = 0;
239  static const unsigned expected[] =
240  {
241  // -2   3
242     -4,  6, // 2
243    -10, 15, // 5
244    -14, 21, // 7
245     -8, 12, // 4
246  };
247  TEST_ASSERT_EQUAL_INT(expected[idx++], first * second);
248}
249
250TEST_MATRIX(["String1", "String,2", "Stri" "ng3", "String[4]", "String\"5\""], [-5, 12.5f])
251void test_StringsAndNumbersMatrices(const char* str, float number)
252{
253  static unsigned idx = 0;
254  static const char* expected[] =
255  {
256    "String1_-05.00",
257    "String1_+12.50",
258    "String,2_-05.00",
259    "String,2_+12.50",
260    "String3_-05.00",
261    "String3_+12.50",
262    "String[4]_-05.00",
263    "String[4]_+12.50",
264    "String\"5\"_-05.00",
265    "String\"5\"_+12.50",
266  };
267  char buf[200] = {0};
268  snprintf(buf, sizeof(buf), "%s_%+06.2f", str, number);
269  TEST_ASSERT_EQUAL_STRING(expected[idx++], buf);
270}
271
272TEST_MATRIX(
273  [ENUM_A, ENUM_4, ENUM_C],
274  [test_arr[0], 7.8f, test_arr[2]],
275  ['a', 'f', '[', ']', '\'', '"'],
276)
277void test_EnumCharAndArrayMatrices(test_enum_t e, float n, char c)
278{
279  static unsigned enum_idx = 0;
280  static const test_enum_t exp_enum[3] = {
281    ENUM_A, ENUM_4, ENUM_C,
282  };
283
284  static unsigned float_idx = 0;
285  float exp_float[3] = {0};
286  exp_float[0] = test_arr[0];
287  exp_float[1] = 7.8f;
288  exp_float[2] = test_arr[2];
289
290  static unsigned char_idx = 0;
291  static const test_enum_t exp_char[] = {
292    'a', 'f', '[', ']', '\'', '"'
293  };
294
295  TEST_ASSERT_EQUAL_INT(exp_enum[enum_idx], e);
296  TEST_ASSERT_EQUAL_FLOAT(exp_float[float_idx], n);
297  TEST_ASSERT_EQUAL_CHAR(exp_char[char_idx], c);
298
299  char_idx = (char_idx + 1) % 6;
300  if (char_idx == 0.0f)
301  {
302    float_idx = (float_idx + 1) % 3;
303    if (float_idx == 0.0f)
304    {
305      enum_idx = (enum_idx + 1) % 3;
306    }
307  }
308}
309