96af2edd4e8655a2cabb016eb3432622addb791f
[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,"Start testing\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
76 fprintf(this->output,"End testing. %d of %d tests succeeded\n",this->tests_count - this->failed_tests_count,this->tests_count);
77
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,"Start Test '%s'\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 fprintf(this->output,"End Test '%s' in %ld microseconds\n", test_name,timediff);
129 if (this->failed_asserts_count > 0)
130 {
131 this->failed_tests_count++;
132 }
133 }
134
135 /**
136 * Implementation of function assert_true
137 */
138 static void assert_true(tester_t *tester, bool to_be_true,char * assert_name)
139 {
140 private_tester_t *this = (private_tester_t *) tester;
141
142 if (assert_name == NULL)
143 {
144 assert_name = "unknown";
145 }
146
147 pthread_mutex_lock(&(this->mutex));
148 if (!to_be_true)
149 {
150 this->failed_asserts_count++;
151 fprintf(this->output," Assert '%s' failed!\n", assert_name);
152 }else
153 {
154 if (this->display_succeeded_asserts)
155 {
156 fprintf(this->output," Assert '%s' succeeded\n", assert_name);
157 }
158 }
159 pthread_mutex_unlock(&(this->mutex));
160 }
161
162 /**
163 * Implementation of function assert_false
164 */
165 static void assert_false(tester_t *tester, bool to_be_false,char * assert_name)
166 {
167 tester->assert_true(tester,(!to_be_false),assert_name);
168 }
169
170 /**
171 * Implements the destroy function
172 */
173 static status_t destroy(tester_t *tester)
174 {
175 private_tester_t *this = (private_tester_t*) tester;
176 pthread_mutex_destroy(&(this->mutex));
177 allocator_free(this);
178 return SUCCESS;
179 }
180
181 tester_t *tester_create(FILE *output, bool display_succeeded_asserts)
182 {
183 private_tester_t *this = allocator_alloc_thing(private_tester_t);
184
185 this->public.destroy = destroy;
186 this->public.perform_tests = perform_tests;
187 this->public.perform_test = perform_test;
188 this->public.assert_true = assert_true;
189 this->public.assert_false = assert_false;
190
191
192 this->run_test = run_test;
193 this->display_succeeded_asserts = display_succeeded_asserts;
194 this->failed_tests_count = 0;
195 this->tests_count = 0;
196 this->output = output;
197 pthread_mutex_init(&(this->mutex),NULL);
198
199 return &(this->public);
200 }