- test output improved
[strongswan.git] / Source / charon / tester.c
1 /**
2 * @file tester.c
3 *
4 * @brief Test module for automatic testing
5 *
6 */
7
8 /*
9 * Copyright (C) 2005 Jan Hutter, Martin Willi
10 * Hochschule fuer Technik Rapperswil
11 *
12 * This program is free software; you can redistribute it and/or modify it
13 * under the terms of the GNU General Public License as published by the
14 * Free Software Foundation; either version 2 of the License, or (at your
15 * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
16 *
17 * This program is distributed in the hope that it will be useful, but
18 * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
19 * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
20 * for more details.
21 */
22
23
24 #include <stdlib.h>
25 #include <freeswan.h>
26 #include <pluto/constants.h>
27 #include <pluto/defs.h>
28 #include <string.h>
29 #include <pthread.h>
30 #include <sys/time.h>
31
32 #include "allocator.h"
33 #include "tester.h"
34 #include "linked_list.h"
35 #include "thread_pool.h"
36 #include "job_queue.h"
37
38 /**
39 * @brief Private Variables and Functions of tester class
40 *
41 */
42 typedef struct private_tester_s private_tester_t;
43
44 struct private_tester_s {
45 tester_t public;
46
47
48 /* Private functions */
49 void (*run_test) (tester_t *tester, void (*test_function) (tester_t * tester), char * test_name);
50
51
52 /* Private values */
53 FILE* output;
54 int tests_count;
55 int failed_tests_count;
56 int failed_asserts_count;
57 bool display_succeeded_asserts;
58 pthread_mutex_t mutex;
59 };
60
61 /*
62 * Implementation of function perform_tests
63 */
64 static status_t perform_tests(tester_t *tester,test_t **tests)
65 {
66 private_tester_t *this =(private_tester_t*) tester;
67 int current_test = 0;
68 fprintf(this->output,"\nStart testing...\n\n");
69 fprintf(this->output,"_____________________________________________________________________\n");
70 fprintf(this->output,"Testname | running time\n");
71 fprintf(this->output,"_______________________________________________________|_____________\n");
72
73 while (tests[current_test] != NULL)
74 {
75 this->run_test(tester,tests[current_test]->test_function,tests[current_test]->test_name);
76 current_test++;
77 }
78 fprintf(this->output,"=====================================================================\n");
79 fprintf(this->output,"End testing. %d of %d tests succeeded\n",this->tests_count - this->failed_tests_count,this->tests_count);
80 fprintf(this->output,"=====================================================================\n");
81 return SUCCESS;
82 }
83
84 /*
85 * Implementation of function perform_test
86 */
87 static status_t perform_test(tester_t *tester, test_t *test)
88 {
89 test_t *tests[] = {test, NULL};
90 return (perform_tests(tester,tests));
91 }
92
93 /**
94 * Returns the difference of to timeval structs in microseconds
95 *
96 * @param end_time end time
97 * @param start_time start time
98 *
99 * @warning this function is also defined in the event queue
100 * in later improvements, this function can be added to a general
101 * class type!
102 *
103 * @return difference in microseconds
104 */
105 static long time_difference(struct timeval *end_time, struct timeval *start_time)
106 {
107 long seconds, microseconds;
108
109 seconds = (end_time->tv_sec - start_time->tv_sec);
110 microseconds = (end_time->tv_usec - start_time->tv_usec);
111 return ((seconds * 1000000) + microseconds);
112 }
113
114
115 /**
116 * Implementation of function run_test
117 */
118 static void run_test(tester_t *tester, void (*test_function) (tester_t * tester), char * test_name)
119 {
120 struct timeval start_time, end_time;
121 long timediff;
122 private_tester_t *this = (private_tester_t *) tester;
123 this->tests_count++;
124 this->failed_asserts_count = 0;
125 fprintf(this->output,"%-55s", test_name);
126 gettimeofday(&start_time,NULL);
127 test_function(tester);
128 gettimeofday(&end_time,NULL);
129 timediff = time_difference(&end_time, &start_time);
130
131 if (this->failed_asserts_count > 0)
132 {
133 fprintf(this->output,"FAILED: %-47s|%10ld ms\n",test_name,timediff);
134 }else
135 {
136 fprintf(this->output,"|%10ld ms\n",timediff);
137 }
138 if (this->failed_asserts_count > 0)
139 {
140 this->failed_tests_count++;
141 }
142 }
143
144 /**
145 * Implementation of function assert_true
146 */
147 static void assert_true(tester_t *tester, bool to_be_true,char * assert_name)
148 {
149 private_tester_t *this = (private_tester_t *) tester;
150
151 if (assert_name == NULL)
152 {
153 assert_name = "unknown";
154 }
155
156 pthread_mutex_lock(&(this->mutex));
157 if (!to_be_true)
158 {
159 this->failed_asserts_count++;
160 fprintf(this->output," check '%s' failed!\n", assert_name);
161 }else
162 {
163 if (this->display_succeeded_asserts)
164 {
165 fprintf(this->output," check '%s' succeeded\n", assert_name);
166 }
167 }
168 pthread_mutex_unlock(&(this->mutex));
169 }
170
171 /**
172 * Implementation of function assert_false
173 */
174 static void assert_false(tester_t *tester, bool to_be_false,char * assert_name)
175 {
176 tester->assert_true(tester,(!to_be_false),assert_name);
177 }
178
179 /**
180 * Implements the destroy function
181 */
182 static status_t destroy(tester_t *tester)
183 {
184 private_tester_t *this = (private_tester_t*) tester;
185 pthread_mutex_destroy(&(this->mutex));
186 allocator_free(this);
187 return SUCCESS;
188 }
189
190 tester_t *tester_create(FILE *output, bool display_succeeded_asserts)
191 {
192 private_tester_t *this = allocator_alloc_thing(private_tester_t);
193
194 this->public.destroy = destroy;
195 this->public.perform_tests = perform_tests;
196 this->public.perform_test = perform_test;
197 this->public.assert_true = assert_true;
198 this->public.assert_false = assert_false;
199
200
201 this->run_test = run_test;
202 this->display_succeeded_asserts = display_succeeded_asserts;
203 this->failed_tests_count = 0;
204 this->tests_count = 0;
205 this->output = output;
206 pthread_mutex_init(&(this->mutex),NULL);
207
208 return &(this->public);
209 }