8710bb19ad47ff6a4ab9a13800c6320e7f86122a
[strongswan.git] / Source / charon / utils / 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 <string.h>
26 #include <pthread.h>
27 #include <sys/time.h>
28
29 #include "tester.h"
30
31 #include "allocator.h"
32 #include "linked_list.h"
33 #include "../queues/job_queue.h"
34
35 /**
36 * @brief Private Variables and Functions of tester class
37 *
38 */
39 typedef struct private_tester_s private_tester_t;
40
41 struct private_tester_s {
42 tester_t public;
43
44
45 /* Private functions */
46 void (*run_test) (tester_t *tester, void (*test_function) (tester_t * tester), char * test_name);
47
48
49 /* Private values */
50 FILE* output;
51 int tests_count;
52 int failed_tests_count;
53 int failed_asserts_count;
54 bool display_succeeded_asserts;
55 pthread_mutex_t mutex;
56 };
57
58 /*
59 * Implementation of function perform_tests
60 */
61 static status_t perform_tests(tester_t *tester,test_t **tests)
62 {
63 private_tester_t *this =(private_tester_t*) tester;
64 int current_test = 0;
65 fprintf(this->output,"\nStart testing...\n\n");
66 fprintf(this->output,"_____________________________________________________________________\n");
67 fprintf(this->output,"Testname | running time\n");
68 fprintf(this->output,"_______________________________________________________|_____________\n");
69
70 while (tests[current_test] != NULL)
71 {
72 this->run_test(tester,tests[current_test]->test_function,tests[current_test]->test_name);
73 current_test++;
74 }
75 fprintf(this->output,"=====================================================================\n");
76 fprintf(this->output,"End testing. %d of %d tests succeeded\n",this->tests_count - this->failed_tests_count,this->tests_count);
77 fprintf(this->output,"=====================================================================\n");
78 return SUCCESS;
79 }
80
81 /*
82 * Implementation of function perform_test
83 */
84 static status_t perform_test(tester_t *tester, test_t *test)
85 {
86 test_t *tests[] = {test, NULL};
87 return (perform_tests(tester,tests));
88 }
89
90 /**
91 * Returns the difference of to timeval structs in microseconds
92 *
93 * @param end_time end time
94 * @param start_time start time
95 *
96 * @warning this function is also defined in the event queue
97 * in later improvements, this function can be added to a general
98 * class type!
99 *
100 * @return difference in microseconds
101 */
102 static long time_difference(struct timeval *end_time, struct timeval *start_time)
103 {
104 long seconds, microseconds;
105
106 seconds = (end_time->tv_sec - start_time->tv_sec);
107 microseconds = (end_time->tv_usec - start_time->tv_usec);
108 return ((seconds * 1000000) + microseconds);
109 }
110
111
112 /**
113 * Implementation of function run_test
114 */
115 static void run_test(tester_t *tester, void (*test_function) (tester_t * tester), char * test_name)
116 {
117 struct timeval start_time, end_time;
118 long timediff;
119 private_tester_t *this = (private_tester_t *) tester;
120 this->tests_count++;
121 this->failed_asserts_count = 0;
122 fprintf(this->output,"%-55s\n", test_name);
123 gettimeofday(&start_time,NULL);
124 test_function(tester);
125 gettimeofday(&end_time,NULL);
126 timediff = time_difference(&end_time, &start_time);
127
128 if (this->failed_asserts_count > 0)
129 {
130 fprintf(this->output," =>Test failed: %-40s|%10ld us\n",test_name,timediff);
131 }else
132 {
133 fprintf(this->output,"\033[1A\033[55C|%10ld us\033[1B\033[80D",timediff);
134 }
135 if (this->failed_asserts_count > 0)
136 {
137 this->failed_tests_count++;
138 }
139 }
140
141
142 /**
143 * Implementation of function assert_true
144 */
145 static void assert_true(tester_t *tester, bool to_be_true,char * assert_name)
146 {
147 private_tester_t *this = (private_tester_t *) tester;
148
149 if (assert_name == NULL)
150 {
151 assert_name = "unknown";
152 }
153
154 pthread_mutex_lock(&(this->mutex));
155 if (!to_be_true)
156 {
157 this->failed_asserts_count++;
158 fprintf(this->output," check '%s' failed!\n", assert_name);
159 }else
160 {
161 if (this->display_succeeded_asserts)
162 {
163 fprintf(this->output," check '%s' succeeded\n", assert_name);
164 }
165 }
166 pthread_mutex_unlock(&(this->mutex));
167 }
168
169 /**
170 * Implementation of function assert_false
171 */
172 static void assert_false(tester_t *tester, bool to_be_false,char * assert_name)
173 {
174 tester->assert_true(tester,(!to_be_false),assert_name);
175 }
176
177 /**
178 * Implements the destroy function
179 */
180 static status_t destroy(tester_t *tester)
181 {
182 private_tester_t *this = (private_tester_t*) tester;
183 pthread_mutex_destroy(&(this->mutex));
184 allocator_free(this);
185 return SUCCESS;
186 }
187
188 tester_t *tester_create(FILE *output, bool display_succeeded_asserts)
189 {
190 private_tester_t *this = allocator_alloc_thing(private_tester_t);
191
192 this->public.destroy = destroy;
193 this->public.perform_tests = perform_tests;
194 this->public.perform_test = perform_test;
195 this->public.assert_true = assert_true;
196 this->public.assert_false = assert_false;
197
198
199 this->run_test = run_test;
200 this->display_succeeded_asserts = display_succeeded_asserts;
201 this->failed_tests_count = 0;
202 this->tests_count = 0;
203 this->output = output;
204 pthread_mutex_init(&(this->mutex),NULL);
205
206 return &(this->public);
207 }