(Trivial) Fix spellling in a comment.
[metze/wireshark/wip.git] / epan / tvbtest.c
1 /* Standalone program to test functionality of tvbuffs.
2  *
3  * tvbtest : tvbtest.o tvbuff.o except.o
4  *
5  * $Id$
6  *
7  * Copyright (c) 2000 by Gilbert Ramirez <gram@alumni.rice.edu>
8  *
9  * This program is free software; you can redistribute it and/or
10  * modify it under the terms of the GNU General Public License
11  * as published by the Free Software Foundation; either version 2
12  * of the License, or (at your option) any later version.
13  *
14  * This program is distributed in the hope that it will be useful,
15  * but WITHOUT ANY WARRANTY; without even the implied warranty of
16  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
17  * GNU General Public License for more details.
18  *
19  * You should have received a copy of the GNU General Public License
20  * along with this program; if not, write to the Free Software
21  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
22  *
23  */
24
25 #include "config.h"
26
27 #include <stdio.h>
28 #include <stdlib.h>
29 #include <string.h>
30
31 #include "tvbuff.h"
32 #include "exceptions.h"
33 #include "wsutil/pint.h"
34
35 gboolean failed = FALSE;
36
37 /* Tests a tvbuff against the expected pattern/length.
38  * Returns TRUE if all tests succeeed, FALSE if any test fails */
39 gboolean
40 test(tvbuff_t *tvb, const gchar* name,
41      guint8* expected_data, guint expected_length, guint expected_reported_length)
42 {
43         guint                   length;
44         guint                   reported_length;
45         guint8                  *ptr;
46         volatile gboolean       ex_thrown;
47         volatile guint32        val32;
48         guint32                 expected32;
49         guint                   incr, i;
50
51         length = tvb_length(tvb);
52
53         if (length != expected_length) {
54                 printf("01: Failed TVB=%s Length of tvb=%u while expected length=%u\n",
55                                 name, length, expected_length);
56                 failed = TRUE;
57                 return FALSE;
58         }
59
60         reported_length = tvb_reported_length(tvb);
61
62         if (reported_length != expected_reported_length) {
63                 printf("01: Failed TVB=%s Reported length of tvb=%u while expected reported length=%u\n",
64                                 name, reported_length, expected_reported_length);
65                 failed = TRUE;
66                 return FALSE;
67         }
68
69         /* Test boundary case. A BoundsError exception should be thrown. */
70         ex_thrown = FALSE;
71         TRY {
72                 tvb_get_ptr(tvb, 0, length + 1);
73         }
74         CATCH(BoundsError) {
75                 ex_thrown = TRUE;
76         }
77         CATCH(FragmentBoundsError) {
78                 printf("02: Caught wrong exception: FragmentBoundsError\n");
79         }
80         CATCH(ReportedBoundsError) {
81                 printf("02: Caught wrong exception: ReportedBoundsError\n");
82         }
83         CATCH_ALL {
84                 printf("02: Caught wrong exception: %lu, exc->except_id.except_code\n");
85         }
86         ENDTRY;
87
88         if (!ex_thrown) {
89                 printf("02: Failed TVB=%s No BoundsError when retrieving %u bytes\n",
90                                 name, length + 1);
91                 failed = TRUE;
92                 return FALSE;
93         }
94
95         /* Test boundary case with reported_length+1. A ReportedBoundsError
96            exception should be thrown. */
97         ex_thrown = FALSE;
98         TRY {
99                 tvb_get_ptr(tvb, 0, reported_length + 1);
100         }
101         CATCH(BoundsError) {
102                 printf("03: Caught wrong exception: BoundsError\n");
103         }
104         CATCH(FragmentBoundsError) {
105                 printf("03: Caught wrong exception: FragmentBoundsError\n");
106         }
107         CATCH(ReportedBoundsError) {
108                 ex_thrown = TRUE;
109         }
110         CATCH_ALL {
111                 printf("02: Caught wrong exception: %lu, exc->except_id.except_code\n");
112         }
113         ENDTRY;
114
115         if (!ex_thrown) {
116                 printf("03: Failed TVB=%s No ReportedBoundsError when retrieving %u bytes\n",
117                                 name, reported_length + 1);
118                 failed = TRUE;
119                 return FALSE;
120         }
121
122         /* Test boundary case. A BoundsError exception should be thrown. */
123         ex_thrown = FALSE;
124         TRY {
125                 tvb_get_ptr(tvb, -1, 2);
126         }
127         CATCH(BoundsError) {
128                 ex_thrown = TRUE;
129         }
130         CATCH(FragmentBoundsError) {
131                 printf("04: Caught wrong exception: FragmentBoundsError\n");
132         }
133         CATCH(ReportedBoundsError) {
134                 printf("04: Caught wrong exception: ReportedBoundsError\n");
135         }
136         CATCH_ALL {
137                 printf("02: Caught wrong exception: %lu, exc->except_id.except_code\n");
138         }
139         ENDTRY;
140
141         if (!ex_thrown) {
142                 printf("04: Failed TVB=%s No BoundsError when retrieving 2 bytes from"
143                                 " offset -1\n", name);
144                 failed = TRUE;
145                 return FALSE;
146         }
147
148         /* Test boundary case. A BoundsError exception should not be thrown. */
149         ex_thrown = FALSE;
150         TRY {
151                 tvb_get_ptr(tvb, 0, 1);
152         }
153         CATCH(BoundsError) {
154                 ex_thrown = TRUE;
155         }
156         CATCH(FragmentBoundsError) {
157                 printf("05: Caught wrong exception: FragmentBoundsError\n");
158         }
159         CATCH(ReportedBoundsError) {
160                 printf("05: Caught wrong exception: ReportedBoundsError\n");
161         }
162         CATCH_ALL {
163                 printf("02: Caught wrong exception: %lu, exc->except_id.except_code\n");
164         }
165         ENDTRY;
166
167         if (ex_thrown) {
168                 printf("05: Failed TVB=%s BoundsError when retrieving 1 bytes from"
169                                 " offset 0\n", name);
170                 failed = TRUE;
171                 return FALSE;
172         }
173
174         /* Test boundary case. A BoundsError exception should not be thrown. */
175         ex_thrown = FALSE;
176         TRY {
177                 tvb_get_ptr(tvb, -1, 1);
178         }
179         CATCH(BoundsError) {
180                 ex_thrown = TRUE;
181         }
182         CATCH(FragmentBoundsError) {
183                 printf("06: Caught wrong exception: FragmentBoundsError\n");
184         }
185         CATCH(ReportedBoundsError) {
186                 printf("06: Caught wrong exception: ReportedBoundsError\n");
187         }
188         CATCH_ALL {
189                 printf("02: Caught wrong exception: %lu, exc->except_id.except_code\n");
190         }
191         ENDTRY;
192
193         if (ex_thrown) {
194                 printf("06: Failed TVB=%s BoundsError when retrieving 1 bytes from"
195                                 " offset -1\n", name);
196                 failed = TRUE;
197                 return FALSE;
198         }
199
200
201         /* Check data at boundary. An exception should not be thrown. */
202         if (length >= 4) {
203                 ex_thrown = FALSE;
204                 TRY {
205                         val32 = tvb_get_ntohl(tvb, 0);
206                 }
207                 CATCH_ALL {
208                         ex_thrown = TRUE;
209                 }
210                 ENDTRY;
211
212                 if (ex_thrown) {
213                         printf("07: Failed TVB=%s Exception when retrieving "
214                                         "guint32 from offset 0\n", name);
215                         failed = TRUE;
216                         return FALSE;
217                 }
218
219                 expected32 = pntoh32(expected_data);
220                 if (val32 != expected32) {
221                         printf("08: Failed TVB=%s  guint32 @ 0 %u != expected %u\n",
222                                         name, val32, expected32);
223                         failed = TRUE;
224                         return FALSE;
225                 }
226         }
227
228         /* Check data at boundary. An exception should not be thrown. */
229         if (length >= 4) {
230                 ex_thrown = FALSE;
231                 TRY {
232                         val32 = tvb_get_ntohl(tvb, -4);
233                 }
234                 CATCH_ALL {
235                         ex_thrown = TRUE;
236                 }
237                 ENDTRY;
238
239                 if (ex_thrown) {
240                         printf("09: Failed TVB=%s Exception when retrieving "
241                                         "guint32 from offset 0\n", name);
242                         failed = TRUE;
243                         return FALSE;
244                 }
245
246                 expected32 = pntoh32(&expected_data[length-4]);
247                 if (val32 != expected32) {
248                         printf("10: Failed TVB=%s guint32 @ -4 %u != expected %u\n",
249                                         name, val32, expected32);
250                         failed = TRUE;
251                         return FALSE;
252                 }
253         }
254
255         /* Sweep across data in various sized increments checking
256          * tvb_memdup() */
257         for (incr = 1; incr < length; incr++) {
258                 for (i = 0; i < length - incr; i += incr) {
259                         ptr = tvb_memdup(NULL, tvb, i, incr);
260                         if (memcmp(ptr, &expected_data[i], incr) != 0) {
261                                 printf("11: Failed TVB=%s Offset=%d Length=%d "
262                                                 "Bad memdup\n",
263                                                 name, i, incr);
264                                 failed = TRUE;
265                                 g_free(ptr);
266                                 return FALSE;
267                         }
268                         g_free(ptr);
269                 }
270         }
271
272         /* One big memdup */
273         ptr = tvb_memdup(NULL, tvb, 0, -1);
274         if (memcmp(ptr, expected_data, length) != 0) {
275                 printf("12: Failed TVB=%s Offset=0 Length=-1 "
276                                 "Bad memdup\n", name);
277                 failed = TRUE;
278                 g_free(ptr);
279                 return FALSE;
280         }
281         g_free(ptr);
282
283
284         printf("Passed TVB=%s\n", name);
285
286         return TRUE;
287 }
288
289 gboolean
290 skip(tvbuff_t *tvb _U_, gchar* name,
291                 guint8* expected_data _U_, guint expected_length _U_)
292 {
293         printf("Skipping TVB=%s\n", name);
294         return FALSE;
295 }
296
297
298 void
299 run_tests(void)
300 {
301         int             i, j;
302
303         tvbuff_t        *tvb_parent;
304         tvbuff_t        *tvb_small[3];
305         tvbuff_t        *tvb_large[3];
306         tvbuff_t        *tvb_subset[6];
307         guint8          *small[3];
308         guint           small_length[3];
309         guint           small_reported_length[3];
310         guint8          *large[3];
311         guint           large_length[3];
312         guint           large_reported_length[3];
313         guint8          *subset[6];
314         guint           subset_length[6];
315         guint           subset_reported_length[6];
316         guint8          temp;
317         guint8          *comp[6];
318         tvbuff_t        *tvb_comp[6];
319         guint           comp_length[6];
320         guint           comp_reported_length[6];
321         int             len;
322
323         tvb_parent = tvb_new_real_data("", 0, 0);
324         for (i = 0; i < 3; i++) {
325                 small[i] = g_new(guint8, 16);
326
327                 temp = 16 * i;
328                 for (j = 0; j < 16; j++) {
329                         small[i][j] = temp + j;
330                 }
331                 small_length[i] = 16;
332                 small_reported_length[i] = 17;
333                 tvb_small[i] = tvb_new_child_real_data(tvb_parent, small[i], 16, 17);
334                 tvb_set_free_cb(tvb_small[i], g_free);
335         }
336
337         for (i = 0; i < 3; i++) {
338                 large[i] = g_new(guint8, 19);
339
340                 temp = 19 * i;
341                 for (j = 0; j < 19; j++) {
342                         large[i][j] = temp + j;
343                 }
344
345                 large_length[i] = 19;
346                 large_reported_length[i] = 20;
347                 tvb_large[i] = tvb_new_child_real_data(tvb_parent, large[i], 19, 20);
348                 tvb_set_free_cb(tvb_large[i], g_free);
349         }
350
351         /* Test the TVBUFF_REAL_DATA objects. */
352         test(tvb_small[0], "Small 0", small[0], small_length[0], small_reported_length[0]);
353         test(tvb_small[1], "Small 1", small[1], small_length[1], small_reported_length[1]);
354         test(tvb_small[2], "Small 2", small[2], small_length[2], small_reported_length[2]);
355
356         test(tvb_large[0], "Large 0", large[0], large_length[0], large_reported_length[0]);
357         test(tvb_large[1], "Large 1", large[1], large_length[1], large_reported_length[1]);
358         test(tvb_large[2], "Large 2", large[2], large_length[2], large_reported_length[2]);
359
360         subset_length[0]          = 8;
361         subset_reported_length[0] = 9;
362         tvb_subset[0]             = tvb_new_subset(tvb_small[0], 0, 8, 9);
363         subset[0]                 = &small[0][0];
364
365         subset_length[1]          = 10;
366         subset_reported_length[1] = 11;
367         tvb_subset[1]             = tvb_new_subset(tvb_large[0], -10, 10, 11);
368         subset[1]                 = &large[0][9];
369
370         subset_length[2]          = 16;
371         subset_reported_length[2] = 17;
372         tvb_subset[2]             = tvb_new_subset(tvb_small[1], -16, -1, 17);
373         subset[2]                 = &small[1][0];
374
375         subset_length[3]          = 3;
376         subset_reported_length[3] = 4;
377         tvb_subset[3]             = tvb_new_subset(tvb_subset[0], 0, 3, 4);
378         subset[3]                 = &small[0][0];
379
380         subset_length[4]          = 5;
381         subset_reported_length[4] = 6;
382         tvb_subset[4]             = tvb_new_subset(tvb_subset[1], -5, 5, 6);
383         subset[4]                 = &large[0][14];
384
385         subset_length[5]          = 8;
386         subset_reported_length[5] = 9;
387         tvb_subset[5]             = tvb_new_subset(tvb_subset[2], 4, 8, 9);
388         subset[5]                 = &small[1][4];
389
390         /* Test the TVBUFF_SUBSET objects. */
391         test(tvb_subset[0], "Subset 0", subset[0], subset_length[0], subset_reported_length[0]);
392         test(tvb_subset[1], "Subset 1", subset[1], subset_length[1], subset_reported_length[1]);
393         test(tvb_subset[2], "Subset 2", subset[2], subset_length[2], subset_reported_length[2]);
394         test(tvb_subset[3], "Subset 3", subset[3], subset_length[3], subset_reported_length[3]);
395         test(tvb_subset[4], "Subset 4", subset[4], subset_length[4], subset_reported_length[4]);
396         test(tvb_subset[5], "Subset 5", subset[5], subset_length[5], subset_reported_length[5]);
397
398         /* One Real */
399         printf("Making Composite 0\n");
400         tvb_comp[0]             = tvb_new_composite();
401         comp_length[0]          = small_length[0];
402         comp_reported_length[0] = small_reported_length[0];
403         comp[0]                 = small[0];
404         tvb_composite_append(tvb_comp[0], tvb_small[0]);
405         tvb_composite_finalize(tvb_comp[0]);
406
407         /* Two Reals */
408         printf("Making Composite 1\n");
409         tvb_comp[1]             = tvb_new_composite();
410         comp_length[1]          = small_length[0] + small_length[1];
411         comp_reported_length[1] = small_reported_length[0] + small_reported_length[1];
412         comp[1]                 = g_malloc(comp_length[1]);
413         memcpy(comp[1], small[0], small_length[0]);
414         memcpy(&comp[1][small_length[0]], small[1], small_length[1]);
415         tvb_composite_append(tvb_comp[1], tvb_small[0]);
416         tvb_composite_append(tvb_comp[1], tvb_small[1]);
417         tvb_composite_finalize(tvb_comp[1]);
418
419         /* One subset */
420         printf("Making Composite 2\n");
421         tvb_comp[2]             = tvb_new_composite();
422         comp_length[2]          = subset_length[1];
423         comp_reported_length[2] = subset_reported_length[1];
424         comp[2]                 = subset[1];
425         tvb_composite_append(tvb_comp[2], tvb_subset[1]);
426         tvb_composite_finalize(tvb_comp[2]);
427
428         /* Two subsets */
429         printf("Making Composite 3\n");
430         tvb_comp[3]             = tvb_new_composite();
431         comp_length[3]          = subset_length[4] + subset_length[5];
432         comp_reported_length[3] = subset_reported_length[4] + subset_reported_length[5];
433         comp[3]                 = g_malloc(comp_length[3]);
434         memcpy(comp[3], subset[4], subset_length[4]);
435         memcpy(&comp[3][subset_length[4]], subset[5], subset_length[5]);
436         tvb_composite_append(tvb_comp[3], tvb_subset[4]);
437         tvb_composite_append(tvb_comp[3], tvb_subset[5]);
438         tvb_composite_finalize(tvb_comp[3]);
439
440         /* One real, one subset */
441         printf("Making Composite 4\n");
442         tvb_comp[4]             = tvb_new_composite();
443         comp_length[4]          = small_length[0] + subset_length[1];
444         comp_reported_length[4] = small_reported_length[0] + subset_reported_length[1];
445         comp[4]                 = g_malloc(comp_length[4]);
446         memcpy(&comp[4][0], small[0], small_length[0]);
447         memcpy(&comp[4][small_length[0]], subset[1], subset_length[1]);
448         tvb_composite_append(tvb_comp[4], tvb_small[0]);
449         tvb_composite_append(tvb_comp[4], tvb_subset[1]);
450         tvb_composite_finalize(tvb_comp[4]);
451
452         /* 4 composites */
453         printf("Making Composite 5\n");
454         tvb_comp[5]             = tvb_new_composite();
455         comp_length[5]          = comp_length[0] +
456                                         comp_length[1] +
457                                         comp_length[2] +
458                                         comp_length[3];
459         comp_reported_length[5] = comp_reported_length[0] +
460                                         comp_reported_length[1] +
461                                         comp_reported_length[2] +
462                                         comp_reported_length[3];
463         comp[5]                 = g_malloc(comp_length[5]);
464
465         len = 0;
466         memcpy(&comp[5][len], comp[0], comp_length[0]);
467         len += comp_length[0];
468         memcpy(&comp[5][len], comp[1], comp_length[1]);
469         len += comp_length[1];
470         memcpy(&comp[5][len], comp[2], comp_length[2]);
471         len += comp_length[2];
472         memcpy(&comp[5][len], comp[3], comp_length[3]);
473
474         tvb_composite_append(tvb_comp[5], tvb_comp[0]);
475         tvb_composite_append(tvb_comp[5], tvb_comp[1]);
476         tvb_composite_append(tvb_comp[5], tvb_comp[2]);
477         tvb_composite_append(tvb_comp[5], tvb_comp[3]);
478         tvb_composite_finalize(tvb_comp[5]);
479
480         /* Test the TVBUFF_COMPOSITE objects. */
481         test(tvb_comp[0], "Composite 0", comp[0], comp_length[0], comp_reported_length[0]);
482         test(tvb_comp[1], "Composite 1", comp[1], comp_length[1], comp_reported_length[1]);
483         test(tvb_comp[2], "Composite 2", comp[2], comp_length[2], comp_reported_length[2]);
484         test(tvb_comp[3], "Composite 3", comp[3], comp_length[3], comp_reported_length[3]);
485         test(tvb_comp[4], "Composite 4", comp[4], comp_length[4], comp_reported_length[4]);
486         test(tvb_comp[5], "Composite 5", comp[5], comp_length[5], comp_reported_length[5]);
487
488         /* free memory. */
489         /* Don't free: comp[0] */
490         g_free(comp[1]);
491         /* Don't free: comp[2] */
492         g_free(comp[3]);
493         g_free(comp[4]);
494         g_free(comp[5]);
495
496         tvb_free_chain(tvb_parent);  /* should free all tvb's and associated data */
497 }
498
499 /* Note: valgrind can be used to check for tvbuff memory leaks */
500 int
501 main(void)
502 {
503         /* For valgrind: See GLib documentation: "Running GLib Applications" */
504         g_setenv("G_DEBUG", "gc-friendly", 1);
505         g_setenv("G_SLICE", "always-malloc", 1);
506
507         except_init();
508         run_tests();
509         except_deinit();
510         exit(failed?1:0);
511 }