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 24 : void title(char *s) {
26 24 : u8_t len = TITLE_LEN;
27 : int i;
28 :
29 24 : len -= strlen(s);
30 24 : for (i = 0; i < len / 2; i++, write(1, "=", 1))
31 : ;
32 24 : write(1, " ", 1);
33 24 : write(1, s, strlen(s));
34 24 : write(1, " ", 1);
35 24 : for (; i < len; i++, write(1, "=", 1));
36 24 : write(1, "\n", 1);
37 24 : }
38 :
39 45 : void print_result(const char *title, u32_t success, u32_t failed) {
40 45 : u32_t total = success + failed;
41 45 : u32_t percent = success * 100 / total;
42 :
43 45 : m_info("%s:", title);
44 45 : fflush(stdout);
45 2697 : for (u32_t i = LINE_SIZE - strlen(title) + 1 - 14; i > 0; i--)
46 2652 : write(1, " ", 1);
47 45 : fprintf(stdout, "%02d/%02d [", success, total);
48 45 : fflush(stdout);
49 45 : if (percent == 100) {
50 30 : fprintf(stdout, "\033[1;32m");
51 15 : } else if (percent >= 90) {
52 3 : fprintf(stdout, "\033[1;33m");
53 : } else {
54 12 : fprintf(stdout, "\033[1;31m");
55 : }
56 45 : fflush(stdout);
57 45 : fprintf(stdout, "%03d%%\033[0;m]\n", percent);
58 45 : fflush(stdout);
59 45 : }
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 189 : void register_test(char *group, char *(*fn_test)(void), char *name) {
70 : mtest_t *ptr;
71 :
72 : /* Allocate test */
73 189 : ptr = malloc(sizeof(mtest_t));
74 189 : assert(ptr);
75 189 : ptr->group = malloc(strlen(group) + 1);
76 189 : ptr->name = malloc(strlen(name) + 1);
77 189 : assert(ptr->group && ptr->name);
78 :
79 : /* Copy name and group */
80 189 : memcpy(ptr->group, group, strlen(group));
81 189 : memcpy(ptr->name, name, strlen(name));
82 189 : ptr->name[strlen(name)] = 0;
83 189 : ptr->group[strlen(group)] = 0;
84 189 : assert(ptr->group && ptr->name);
85 189 : ptr->fn_test = fn_test;
86 :
87 : /* Add to the list of tests */
88 189 : list_add(tests, ptr, sizeof(mtest_t));
89 189 : free(ptr);
90 189 : }
91 :
92 : /*!
93 : * \brief Test an entire group of tests
94 : * \param group Group name
95 : */
96 18 : 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 18 : res.total = res.success = res.failed = 0;
104 18 : res.group_name = NULL;
105 18 : title(group);
106 :
107 18 : if (tests == NULL)
108 : {
109 3 : m_warning("Could not find any registered tests in %s group.\n", group);
110 3 : return res;
111 : }
112 :
113 : /* Iterate over each test */
114 762 : list_for_each(tests, tmp, ptr) {
115 747 : if (strcmp(ptr->group, group) == 0) {
116 189 : res.total++;
117 189 : m_info("Testing %s ...", ptr->name);
118 :
119 9627 : for (tab = strlen(ptr->name); tab < TITLE_LEN - 18;
120 9249 : tab++, printf(" "))
121 : ;
122 :
123 189 : if ((s_tmp = ptr->fn_test()) != TEST_SUCCESS) {
124 3 : printf("[ \033[1;31mKO\033[0m ]\n");
125 3 : m_warning("\033[0;37m%s\033[0m\n", s_tmp);
126 3 : free(s_tmp);
127 3 : res.failed++;
128 : } else {
129 186 : printf("[ \033[1;32mOK\033[0m ]\n");
130 186 : res.success++;
131 : }
132 : }
133 : }
134 :
135 15 : print_result("Group Results", res.success, res.failed);
136 15 : return res;
137 : }
138 :
139 : /*!
140 : * \brief Test all registered tests
141 : * \return Numbers of tests failed
142 : */
143 9 : u32_t test_all(void) {
144 9 : mlist_t *tmp, *groups = NULL, *tests_results = NULL;
145 : mtest_t *ptr;
146 : mtest_results_t res, *ptr2;
147 9 : u32_t total = 0, success = 0, failed = 0;
148 :
149 9 : if (tests == NULL)
150 : {
151 3 : m_warning("No tests registered, skipping.\n");
152 3 : return 0;
153 : }
154 195 : list_for_each(tests, tmp, ptr) {
155 189 : if (list_get(groups, ptr->group, strlen(ptr->group)) == NULL) {
156 15 : res = test_group(ptr->group);
157 :
158 15 : res.group_name = malloc(sizeof(char) * strlen(ptr->group) + 1);
159 15 : strcpy(res.group_name, ptr->group);
160 15 : total += res.total;
161 15 : success += res.success;
162 15 : failed += res.failed;
163 15 : list_add(groups, ptr->group, strlen(ptr->group));
164 15 : list_add(tests_results, &res, sizeof(res));
165 : }
166 : }
167 :
168 6 : title("Results");
169 21 : list_for_each(tests_results, tmp, ptr2) {
170 15 : print_result(ptr2->group_name, ptr2->success, ptr2->failed);
171 : }
172 6 : print_result("Total", success, failed);
173 :
174 6 : list_free(groups, NULL);
175 6 : list_free(tests_results, &single_result_free);
176 :
177 6 : return failed;
178 : }
179 :
180 : /*!
181 : * \brief Free all the test
182 : */
183 9 : void test_free(void) {
184 9 : list_free(tests, &single_test_free);
185 9 : tests = NULL;
186 9 : }
187 :
188 : /*!
189 : * \brief Free a single test
190 : * \note Used in test_free, as a list_free callback
191 : */
192 189 : int single_test_free(void *ptr) {
193 189 : mtest_t *tmp = ptr;
194 :
195 189 : if (ptr) {
196 189 : free(tmp->group);
197 189 : free(tmp->name);
198 : }
199 189 : 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 15 : int single_result_free(void *ptr) {
207 15 : mtest_results_t *tmp = ptr;
208 15 : if (ptr) {
209 15 : free(tmp->group_name);
210 : }
211 15 : return 1;
212 : }
|