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