Line data Source code
1 : /*********************************** LICENSE **********************************\
2 : * Copyright 2017 Morphux *
3 : * *
4 : * Licensed under the Apache License, Version 2.0 (the "License"); *
5 : * you may not use this file except in compliance with the License. *
6 : * You may obtain a copy of the License at *
7 : * *
8 : * http://www.apache.org/licenses/LICENSE-2.0 *
9 : * *
10 : * Unless required by applicable law or agreed to in writing, software *
11 : * distributed under the License is distributed on an "AS IS" BASIS, *
12 : * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. *
13 : * See the License for the specific language governing permissions and *
14 : * limitations under the License. *
15 : \******************************************************************************/
16 :
17 : #include <m_test.h>
18 :
19 : static mlist_t *tests = NULL;
20 :
21 : /*!
22 : * \brief Print a title
23 : * \param s Title name
24 : */
25 16 : void title(char *s) {
26 16 : u8_t len = TITLE_LEN;
27 : int i;
28 :
29 16 : len -= strlen(s);
30 16 : for (i = 0; i < len / 2; i++, write(1, "=", 1))
31 : ;
32 16 : write(1, " ", 1);
33 16 : write(1, s, strlen(s));
34 16 : write(1, " ", 1);
35 16 : for (; i < len; i++, write(1, "=", 1));
36 16 : write(1, "\n", 1);
37 16 : }
38 :
39 30 : void print_result(const char *title, u32_t success, u32_t failed) {
40 30 : u32_t total = success + failed;
41 30 : u32_t percent = success * 100 / total;
42 :
43 30 : m_info("%s:", title);
44 30 : fflush(stdout);
45 1798 : for (u32_t i = LINE_SIZE - strlen(title) + 1 - 14; i > 0; i--)
46 1768 : write(1, " ", 1);
47 30 : fprintf(stdout, "%02d/%02d [", success, total);
48 30 : fflush(stdout);
49 30 : if (percent == 100) {
50 20 : fprintf(stdout, "\033[1;32m");
51 10 : } else if (percent >= 90) {
52 2 : fprintf(stdout, "\033[1;33m");
53 : } else {
54 8 : fprintf(stdout, "\033[1;31m");
55 : }
56 30 : fflush(stdout);
57 30 : fprintf(stdout, "%03d%%\033[0;m]\n", percent);
58 30 : fflush(stdout);
59 30 : }
60 :
61 : /*!
62 : * \brief Register a test
63 : * \param group Group name
64 : * \param fn_test Test function
65 : * \param name Test name
66 : *
67 : * \note Do not call this function directly, use test_reg macro instead.
68 : */
69 122 : void register_test(char *group, char *(*fn_test)(void), char *name) {
70 : mtest_t *ptr;
71 :
72 : /* Allocate test */
73 122 : ptr = malloc(sizeof(mtest_t));
74 122 : assert(ptr);
75 122 : ptr->group = malloc(strlen(group) + 1);
76 122 : ptr->name = malloc(strlen(name) + 1);
77 122 : assert(ptr->group && ptr->name);
78 :
79 : /* Copy name and group */
80 122 : memcpy(ptr->group, group, strlen(group));
81 122 : memcpy(ptr->name, name, strlen(name));
82 122 : ptr->name[strlen(name)] = 0;
83 122 : ptr->group[strlen(group)] = 0;
84 122 : assert(ptr->group && ptr->name);
85 122 : ptr->fn_test = fn_test;
86 :
87 : /* Add to the list of tests */
88 122 : list_add(tests, ptr, sizeof(mtest_t));
89 122 : free(ptr);
90 122 : }
91 :
92 : /*!
93 : * \brief Test an entire group of tests
94 : * \param group Group name
95 : */
96 12 : mtest_results_t test_group(char *group) {
97 : mlist_t *tmp;
98 : mtest_t *ptr;
99 : mtest_results_t res;
100 : u32_t tab;
101 : char *s_tmp;
102 :
103 12 : res.total = res.success = res.failed = 0;
104 12 : res.group_name = NULL;
105 12 : title(group);
106 :
107 12 : if (tests == NULL)
108 : {
109 2 : m_warning("Could not find any registered tests in %s group.\n", group);
110 2 : return res;
111 : }
112 :
113 : /* Iterate over each test */
114 492 : list_for_each(tests, tmp, ptr) {
115 482 : if (strcmp(ptr->group, group) == 0) {
116 122 : res.total++;
117 122 : m_info("Testing %s ...", ptr->name);
118 :
119 6228 : for (tab = strlen(ptr->name); tab < TITLE_LEN - 18;
120 5984 : tab++, printf(" "))
121 : ;
122 :
123 122 : if ((s_tmp = ptr->fn_test()) != TEST_SUCCESS) {
124 2 : printf("[ \033[1;31mKO\033[0m ]\n");
125 2 : m_warning("\033[0;37m%s\033[0m\n", s_tmp);
126 2 : free(s_tmp);
127 2 : res.failed++;
128 : } else {
129 120 : printf("[ \033[1;32mOK\033[0m ]\n");
130 120 : res.success++;
131 : }
132 : }
133 : }
134 :
135 10 : print_result("Group Results", res.success, res.failed);
136 10 : return res;
137 : }
138 :
139 : /*!
140 : * \brief Test all registered tests
141 : * \return Numbers of tests failed
142 : */
143 6 : u32_t test_all(void) {
144 6 : mlist_t *tmp, *groups = NULL, *tests_results = NULL;
145 : mtest_t *ptr;
146 : mtest_results_t res, *ptr2;
147 6 : u32_t total = 0, success = 0, failed = 0;
148 :
149 6 : if (tests == NULL)
150 : {
151 2 : m_warning("No tests registered, skipping.\n");
152 2 : return 0;
153 : }
154 126 : list_for_each(tests, tmp, ptr) {
155 122 : if (list_get(groups, ptr->group, strlen(ptr->group)) == NULL) {
156 10 : res = test_group(ptr->group);
157 :
158 10 : res.group_name = malloc(sizeof(char) * strlen(ptr->group) + 1);
159 10 : strcpy(res.group_name, ptr->group);
160 10 : total += res.total;
161 10 : success += res.success;
162 10 : failed += res.failed;
163 10 : list_add(groups, ptr->group, strlen(ptr->group));
164 10 : list_add(tests_results, &res, sizeof(res));
165 : }
166 : }
167 :
168 4 : title("Results");
169 14 : list_for_each(tests_results, tmp, ptr2) {
170 10 : print_result(ptr2->group_name, ptr2->success, ptr2->failed);
171 : }
172 4 : print_result("Total", success, failed);
173 :
174 4 : list_free(groups, NULL);
175 4 : list_free(tests_results, &single_result_free);
176 :
177 4 : return failed;
178 : }
179 :
180 : /*!
181 : * \brief Free all the test
182 : */
183 6 : void test_free(void) {
184 6 : list_free(tests, &single_test_free);
185 6 : tests = NULL;
186 6 : }
187 :
188 : /*!
189 : * \brief Free a single test
190 : * \note Used in test_free, as a list_free callback
191 : */
192 122 : int single_test_free(void *ptr) {
193 122 : mtest_t *tmp = ptr;
194 :
195 122 : if (ptr) {
196 122 : free(tmp->group);
197 122 : free(tmp->name);
198 : }
199 122 : return 1;
200 : }
201 :
202 : /*!
203 : * \brief Free a mtest_results_t
204 : * \note Used in test_all, as a list_free callback
205 : */
206 10 : int single_result_free(void *ptr) {
207 10 : mtest_results_t *tmp = ptr;
208 10 : if (ptr) {
209 10 : free(tmp->group_name);
210 : }
211 10 : return 1;
212 : }
|