server: intialize aux_header buffer to null if the data is missing.
[tridge/openchange.git] / branches / plugfest / utils / mapitest / mapitest_suite.c
1 /*
2    Stand-alone MAPI testsuite
3
4    OpenChange Project
5
6    Copyright (C) Julien Kerihuel 2008
7
8    This program is free software; you can redistribute it and/or modify
9    it under the terms of the GNU General Public License as published by
10    the Free Software Foundation; either version 3 of the License, or
11    (at your option) any later version.
12    
13    This program is distributed in the hope that it will be useful,
14    but WITHOUT ANY WARRANTY; without even the implied warranty of
15    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16    GNU General Public License for more details.
17    
18    You should have received a copy of the GNU General Public License
19    along with this program.  If not, see <http://www.gnu.org/licenses/>.
20 */
21
22 #include "utils/mapitest/mapitest.h"
23
24 /**
25         \file
26
27         mapitest test suite functions
28 */
29
30 /**
31    \details Initialize a mapitest suite
32    
33    \param mt the top-level mapitest structure
34    \param name the suite name
35    \param description the suite description
36    \param online whether this suite requires online (server) access
37
38    \return An allocated mapitest_suite pointer, otherwise NULL.
39  */
40 _PUBLIC_ struct mapitest_suite *mapitest_suite_init(struct mapitest *mt, 
41                                                     const char *name,
42                                                     const char *description,
43                                                     bool online)
44 {
45         struct mapitest_suite   *suite = NULL;
46
47         /* Sanity check */
48         if (!mt || !mt->mem_ctx) return NULL;
49         if (!name) return NULL;
50
51         suite = talloc_zero(mt->mem_ctx, struct mapitest_suite);
52         suite->tests = NULL;
53         suite->stat = mapitest_stat_init((TALLOC_CTX *)suite);
54
55         suite->name = talloc_strdup((TALLOC_CTX *) suite, name);
56         if (!description) {
57                 suite->description = NULL;
58         } else {
59                 suite->description = talloc_strdup((TALLOC_CTX *)suite, description);
60         }
61
62         suite->online = online;
63
64         return suite;
65 }
66
67
68 /**
69    \details Register a mapitest suite
70
71    \param mt the top-level mapitest structure
72    \param suite the mapitest suite we want to add
73
74    \return MAPITEST_SUCCESS on success, otherwise MAPITEST_ERROR
75
76    \sa mapitest_suite_init
77  */
78 _PUBLIC_ uint32_t mapitest_suite_register(struct mapitest *mt, 
79                                           struct mapitest_suite *suite)
80 {
81         struct mapitest_suite *el = NULL;
82
83         /* Sanity check */
84         if (!mt || !mt->mem_ctx) return MAPITEST_ERROR;
85         if (!suite) return MAPITEST_ERROR;
86
87         /* Ensure the name is not yet registered */
88         for (el = mt->mapi_suite; el; el = el->next) {
89                 if (el->name && !strcmp(el->name, suite->name)) {
90                         fprintf(stderr, "Suite already registered\n");
91                         return MAPITEST_ERROR;
92                 }
93         }
94
95         DLIST_ADD_END(mt->mapi_suite, suite, struct mapitest_suite *);
96
97         return MAPITEST_SUCCESS;
98 }
99
100 /**
101    \details add a test to the mapitest suite with description
102
103    \param suite pointer on the parent suite
104    \param name the test name
105    \param description the test description
106    \param run the test function
107
108    \return MAPITEST_SUCCESS on success, otherwise MAPITEST_ERROR
109    
110    \sa mapitest_suite_init, mapitest_suite_register
111    \sa mapitest_suite_add_test_flagged for an alternative function allowing the
112    test to only be run under some conditions.
113 */
114 _PUBLIC_ uint32_t mapitest_suite_add_test(struct mapitest_suite *suite,
115                                           const char *name, const char *description,
116                                           bool (*run) (struct mapitest *test))
117 {
118         return mapitest_suite_add_test_flagged(suite, name, description, run, ApplicableToAllVersions);
119 }
120
121 /**
122    \details add a test to the mapitest suite with description and flags
123
124    This is very similar to mapitest_suite_add_test(), except it allows a test to have
125    special applicability (e.g. to only run when a particular server configuration is available).
126    
127    \param suite pointer to the parent test suite
128    \param name the test name
129    \param description the test description
130    \param run the test function
131    \param applicability a set of applicability flags
132
133    \return MAPITEST_SUCCESS on success, otherwise MAPITEST_ERROR
134    
135    \sa mapitest_suite_init, mapitest_suite_register, mapitest_suite_add_test
136 */
137 _PUBLIC_ uint32_t mapitest_suite_add_test_flagged(struct mapitest_suite *suite,
138                                                   const char *name, const char *description,
139                                                   bool (*run) (struct mapitest *test),
140                                                   enum TestApplicabilityFlags applicability)
141 {
142         struct mapitest_test    *el = NULL;
143
144         /* Sanity check */
145         if (!suite || !name || !run || !description) return MAPITEST_ERROR;
146
147         /* Ensure the test is not yet registered */
148         for (el = suite->tests; el; el = el->next) {
149                 if (el->name && !strcmp(el->name, name)) {
150                         return MAPITEST_ERROR;
151                 }
152         }
153
154         el = talloc_zero((TALLOC_CTX *) suite, struct mapitest_test);
155         el->name = talloc_asprintf((TALLOC_CTX *)suite, "%s-%s", suite->name, name);
156         el->description = talloc_strdup((TALLOC_CTX *)suite, description);
157         el->fn = run;
158         el->flags = applicability;
159
160         DLIST_ADD_END(suite->tests, el, struct mapitest_test *);
161
162         return MAPITEST_SUCCESS;
163 }
164
165
166 /**
167    \details Find a suite given its name
168
169    \param mt top-level mapitest structure
170    \param name the suite name to be searched
171
172    \return Pointer on a suite on success, otherwise NULL
173  */
174 _PUBLIC_ struct mapitest_suite *mapitest_suite_find(struct mapitest *mt, 
175                                                     const char *name)
176 {
177         struct mapitest_suite   *suite = NULL;
178         
179         if (!name) return NULL;
180
181         for (suite = mt->mapi_suite; suite; suite = suite->next) {
182                 if (!strcmp(name, suite->name)) {
183                         return suite;
184                 }
185         }
186
187         return NULL;
188 }
189
190 /**
191    \details test whether a particular test is applicable
192
193    \param mt pointer to the top-level mapitest structure
194    \param el the test to check
195    
196    \return true if the test should be run, otherwise false
197 */
198 static bool mapitest_suite_test_is_applicable(struct mapitest *mt, struct mapitest_test *test)
199 {
200         uint16_t actualServerVer = mt->info.rgwServerVersion[0];
201
202         if ((test->flags & NotInExchange2010) && (actualServerVer >= Exchange2010SP0Version)) {
203                 return false;
204         }
205         if ((test->flags & NotInExchange2010SP0) && (actualServerVer == Exchange2010SP0Version)) {
206                 return false;
207         }
208         return true;
209 }
210
211 static bool run_test(struct mapitest *mt, struct mapitest_suite *suite, struct mapitest_test *el)
212 {
213         bool                    (*fn)(struct mapitest *);
214         bool                    ret = false;
215
216         if (!mapitest_suite_test_is_applicable(mt, el)) {
217                 mapitest_stat_add_skipped_test(suite, el->name, el->flags);
218         } else {
219                 errno = 0;
220                 mapitest_print_test_title_start(mt, el->name);
221                 
222                 fn = el->fn;
223                 ret = fn(mt);
224
225                 if (el->flags & ExpectedFail) {
226                         if (ret) {
227                                 mapitest_stat_add_result(suite, el->name, UnexpectedPass);
228                         } else {
229                                 mapitest_stat_add_result(suite, el->name, ExpectedFailure);
230                         }
231                 } else {
232                         if (ret) {
233                                 mapitest_stat_add_result(suite, el->name, Pass);
234                         } else {
235                                 mapitest_stat_add_result(suite, el->name, Fail);
236                         }
237                 }
238                 mapitest_print_test_title_end(mt);
239                 mapitest_print_test_result(mt, el->name, ret);
240         }
241         return ret;
242 }
243
244 /**
245    \details run a test from a suite given its name
246    
247    \param mt pointer on the top-level mapitest structure
248    \param suite pointer on the mapitest suite
249    \param name the name of the test to be run
250
251    \return true on success, otherwise false
252  */
253 _PUBLIC_ bool mapitest_suite_run_test(struct mapitest *mt,
254                                       struct mapitest_suite *suite, 
255                                       const char *name)
256 {
257         struct mapitest_test    *el;
258         bool                    ret;
259
260         if (!suite || !name) return false;
261
262         for (el = suite->tests; el; el = el->next) {
263                 if (!strcmp(el->name, name)) {
264                         ret = run_test(mt, suite, el);
265                         return ret;
266                 }
267         }
268
269         fprintf(stderr, "[ERROR] %s test doesn't exist\n", name);
270         return false;
271 }
272
273
274 /**
275    \details run the special SUITE-ALL test
276
277    \param mt the top-level mapitest structure
278    \param name the mapitest test name
279
280    \return true on success, otherwise -1
281  */
282 static bool mapitest_run_test_all(struct mapitest *mt, const char *name)
283 {
284         char                    *test_name;
285         char                    *sname;
286         char                    *tmp;
287         struct mapitest_test    *el;
288         struct mapitest_suite   *suite;
289         bool                    ret = false;
290
291         test_name = talloc_strdup(mt->mem_ctx, name);
292         if ((tmp = strtok(test_name, "-")) == NULL) {
293                 talloc_free(test_name);
294         }
295
296         sname = talloc_strdup(mt->mem_ctx, tmp);
297         if ((tmp = strtok(NULL, "-")) == NULL) {
298                 talloc_free(test_name);
299                 talloc_free(sname);
300                 return false;
301         }
302
303         if (!strcmp(tmp,"ALL")) {
304                 suite = mapitest_suite_find(mt, sname);
305
306                 if ((suite && (suite->online == mt->online)) || (suite && (suite->online == false))) {
307                         for (el = suite->tests; el; el = el->next) {
308                                 if (mapitest_suite_test_is_applicable(mt, el)) {
309                                         mapitest_suite_run_test(mt, suite, el->name);
310                                         ret = true;
311                                 } else {
312                                         printf("test is not applicable: %s\n", el->name);
313                                         return true;
314                                 }
315                         }
316                 }
317         }
318         talloc_free(sname);
319         talloc_free(test_name);
320         return ret;
321 }
322
323
324 /**
325    \details run a specific test from a particular suite
326
327    \param mt the top-level mapitest structure
328    \param name the mapitest test name
329
330    \return true on success, otherwise -1
331  */
332 _PUBLIC_ bool mapitest_run_test(struct mapitest *mt, const char *name)
333 {
334         struct mapitest_suite   *suite;
335         struct mapitest_test    *el;
336         bool                    ret;
337
338         /* sanity check */
339         if (!mt || !name) return false;
340
341         /* try to find the test */
342         for (suite = mt->mapi_suite; suite; suite = suite->next) {
343                 for (el = suite->tests; el; el = el->next) {
344                         if (!strcmp(name, el->name)) {
345                                 if (((mt->online == suite->online) && mt->session) || (suite->online == false)) {
346                                         errno = 0;
347                                         ret = mapitest_suite_run_test(mt, suite, name);
348                                         return ret;
349                                 } else {
350                                         fprintf(stderr, "Server is offline, skipping test: \"%s\"\n", name);
351                                         return true;
352                                 }
353                         }
354                 }
355         }
356         
357         /* if no name matches, look it it matches ALL */
358         ret = mapitest_run_test_all(mt, name);
359
360         if (ret != true) {
361                 fprintf(stderr, "[ERROR] Unknown test: \"%s\"\n", name);
362         }
363
364         return ret;
365 }
366
367 static void run_tests_in_suite(struct mapitest *mt, struct mapitest_suite *suite)
368 {
369         struct mapitest_test    *el;
370
371         for (el = suite->tests; el; el = el->next) {
372                 run_test(mt, suite, el);
373         }
374 }
375
376 /**
377    \details all tests from all suites
378
379    \param mt the top-level mapitest structure
380
381    \return true on success, otherwise -1
382  */
383 _PUBLIC_ void mapitest_run_all(struct mapitest *mt)
384 {
385         struct mapitest_suite   *suite;
386
387         for (suite = mt->mapi_suite; suite; suite = suite->next) {
388                 if (((mt->online == suite->online) && mt->session) || (suite->online == false)) {
389                         mapitest_print_module_title_start(mt, suite->name);
390
391                         run_tests_in_suite(mt, suite);
392
393                         mapitest_print_module_title_end(mt);
394                 }
395         }
396 }