From Cristian Constantin:
[obnox/wireshark/wip.git] / tools / dfilter-test.py
1 #!/usr/bin/env python
2 """
3 Test-suite to test wireshark's dfilter mechanism.
4 """
5
6 #
7 # $Id$
8 #
9 # Copyright (C) 2003 by Gilbert Ramirez <gram@alumni.rice.edu>
10 #  
11 # This program is free software; you can redistribute it and/or
12 # modify it under the terms of the GNU General Public License
13 # as published by the Free Software Foundation; either version 2
14 # of the License, or (at your option) any later version.
15
16 # This program is distributed in the hope that it will be useful,
17 # but WITHOUT ANY WARRANTY; without even the implied warranty of
18 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
19 # GNU General Public License for more details.
20
21 # You should have received a copy of the GNU General Public License
22 # along with this program; if not, write to the Free Software
23 # Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
24
25 import os
26 import sys
27 import atexit
28 import tempfile
29 import types
30 import getopt
31
32 # Global variables that can be overridden by user
33
34 REMOVE_TEMP_FILES = 1
35 VERBOSE = 0
36 TEXT2PCAP = os.path.join(".", "text2pcap")
37 TSHARK = os.path.join(".", "tshark")
38
39 # Some DLT values. Add more from <net/bpf.h> if you need to.
40
41 DLT_NULL        = 0       # no link-layer encapsulation
42 DLT_EN10MB      = 1       # Ethernet (10Mb)
43 DLT_EN3MB       = 2       # Experimental Ethernet (3Mb)
44 DLT_AX25        = 3       # Amateur Radio AX.25
45 DLT_PRONET      = 4       # Proteon ProNET Token Ring
46 DLT_CHAOS       = 5       # Chaos
47 DLT_IEEE802     = 6       # IEEE 802 Networks
48 DLT_ARCNET      = 7       # ARCNET
49 DLT_SLIP        = 8       # Serial Line IP
50 DLT_PPP         = 9       # Point-to-point Protocol
51 DLT_FDDI        = 10      # FDDI
52 DLT_FRELAY      = 107     # Frame Relay
53
54 ################################################################################
55
56 class RunCommandError:
57         """The exception that run_cmd can produce."""
58         pass
59
60 def run_cmd(cmd):
61         """Run a command. 'cmd' is either a string or
62         a tuple/array of strings. Returns a tuple of
63         the output of the command and the return value.
64         If an error did not occur, the return value is None, not 0.
65         If an error occured while trying to run the command,
66         RunCommandError is raised.
67         Both, or either, the output and the return value, may
68         be None if RunCommandError is raised.."""
69
70         if type(cmd) == types.TupleType:
71                 cmd = ' '.join(cmd)
72
73         output = None
74         error = None
75
76         if VERBOSE:
77                 print "Running", cmd
78
79         try:
80                 pipe = os.popen(cmd)
81                 output = pipe.readlines()
82                 error = pipe.close()
83
84         except OSError:
85                 raise RunCommandError
86
87         return (output, error)
88
89
90 def remove_file(filename):
91         """Remove a file. No exceptions are produced even
92         when the file cannot be removed."""
93         try:
94                 os.remove(filename)
95         except OSError:
96                 pass
97
98
99 class Packet:
100         """Knows how to convert a string representing the
101         hex-dump of packet into a libpcap file."""
102
103         def __init__(self, linklayer):
104                 """Linklayer is a DLT value."""
105                 self.linklayer = linklayer
106                 self.data = None
107                 self.filename = None
108                 self.time_fmt = None
109
110         def Filename(self):
111                 """Returns the filename of the packet trace.
112                 The first time this is called, the libpcap trace
113                 file is created. During subsequent calls, the libpcap
114                 tracee file already exists, so the filename is simply
115                 returned.  Care is taken so that the libpcap trace file
116                 is automatically deleted when this Python process
117                 exits."""
118                 if not self.filename:
119                         # Create the temporary text file.
120                         hex_filename = tempfile.mktemp("-dfilter-test.txt")
121
122                         # Tell Python to remove the file when exiting
123                         if REMOVE_TEMP_FILES:
124                                 atexit.register(remove_file, hex_filename)
125
126                         try:
127                                 hex_fh = open(hex_filename, "w")
128                                 hex_fh.write(self.data)
129                                 hex_fh.write("\n")
130                                 hex_fh.close()
131                         except IOError, err:
132                                 sys.exit("Could not write to %s: %s" % \
133                                         (hex_filename, err))
134
135
136                         # Create the pcap file
137                         self.filename = tempfile.mktemp("-dfilter-test.cap")
138
139                         # Tell Python to remove the file when exiting
140                         if REMOVE_TEMP_FILES:
141                                 atexit.register(remove_file, self.filename)
142
143                         cmd = (TEXT2PCAP, "-q -l", str(self.linklayer))
144
145                         if self.time_fmt:
146                                 cmd = cmd + ("-t", "'" + self.time_fmt + "'")
147
148                         cmd = cmd + (hex_filename, self.filename)
149
150                         try:
151                                 (output, error) = run_cmd(cmd)
152                         except RunCommandError:
153                                 sys.exit("Could not produce trace file.")
154
155                         if error != None:
156                                 sys.exit("Could not produce trace file.")
157
158
159                 if not REMOVE_TEMP_FILES:
160                         print "(", self.filename, ") ...",
161
162                 return self.filename
163                         
164         
165 OK = 0
166 FAILED = 1
167
168 class Test:
169         """Base class for test classes."""
170
171         def Run(self):
172                 """Run the tests listed in self.tests.
173                 Return the score."""
174
175                 num_run = 0
176                 num_succeeded = 0
177
178                 for test in self.tests:
179                         print "\t", test.__name__ , "...",
180                         retval = test(self)
181                         if retval == OK:
182                                 print "OK"
183                                 num_succeeded += 1
184                         else:
185                                 print "FAILED"
186                         num_run += 1
187
188                 return (num_run, num_succeeded)
189
190
191         def DFilterCount(self, packet, dfilter, num_lines_expected):
192                 """Run a dfilter on a packet file and expect
193                 a certain number of output lines. If num_lines_expected
194                 is None, then the tshark command is expected to fail
195                 with a non-zero return value."""
196
197                 packet_file = packet.Filename()
198
199                 cmd = (TSHARK, "-n -r", packet_file, "-R '", dfilter, "'")
200
201                 tshark_failed = 0
202
203                 try:
204                         (output, retval) = run_cmd(cmd)
205                 except RunCommandError:
206                         tshark_failed = 1
207
208 #               print "GOT", len(output), "lines:", output, retval
209
210                 if retval:
211                         tshark_failed = 1
212
213                 if tshark_failed:
214                         if num_lines_expected == None:
215                                 if VERBOSE:
216                                         print "\nGot:", output
217                                 return OK
218                         else:
219                                 print "\nGot:", output
220                                 return FAILED
221
222                 elif len(output) == num_lines_expected:
223                         if VERBOSE:
224                                 print "\nGot:", output
225                         return OK
226                 else:
227                         print "\nGot:", output
228                         return FAILED
229
230
231 ################################################################################
232 # Add packets here
233 # Watch out for trailing backslashes. If the last character in the line is a
234 # backslash, the data won't convert properly. Just remove the backslash or
235 # replace it with another character. I haven't determined if this is due to
236 # Python's "here-document" parsing, or due to text2pcap.
237 ################################################################################
238
239 # IPX RIP Response
240 pkt_ipx_rip = Packet(DLT_EN10MB)
241 pkt_ipx_rip.data = """
242 0000  ff ff ff ff ff ff 00 aa  00 a3 e3 a4 00 28 ff ff   ........ .....(..
243 0010  00 28 00 01 00 00 00 28  ff ff ff ff ff ff 04 53   .(.....( .......S
244 0020  00 00 00 28 00 aa 00 a3  e3 a4 04 53 00 02 39 17   ...(.... ...S..9.
245 0030  29 e2 00 01 00 02 00 00  00 00 00 00               )....... ....
246 """
247
248 # IPv6
249 pkt_ipv6 = Packet(DLT_EN10MB)
250 pkt_ipv6.data = """
251 0000  33 33 00 00 99 99 00 00  86 05 80 fa 86 dd 60 00   33...... ......`.
252 0010  00 00 00 20 00 01 fe 80  00 00 00 00 00 00 02 00   ... .... ........
253 0020  86 ff fe 05 80 fa ff 05  00 00 00 00 00 00 00 00   ........ ........
254 0030  00 00 00 00 99 99 3a 00  01 00 05 02 00 00 83 00   ......:. ........
255 0040  44 ed 00 00 00 00 ff 05  00 00 00 00 00 00 00 00   D....... ........
256 0050  00 00 00 00 99 99                                  ......           
257 """
258
259 # ARP
260 pkt_arp = Packet(DLT_FRELAY)
261 pkt_arp.data = """
262 0000  18 41 03 00 80 00 00 00  08 06 00 0f 08 00 02 04   .A...... ........
263 0010  00 08 00 00 0a ce 01 02  00 64 00 00 00 00         ........ .d....  
264 """
265
266 # NFS
267 pkt_nfs = Packet(DLT_FDDI)
268 pkt_nfs.time_fmt = "%Y-%m-%d %H:%M:%S."
269 pkt_nfs.data = """
270 2002-12-31 07:55:31.3
271 0000  51 10 00 d4 cd 59 6f 00  07 4a 01 6e 00 aa aa 03   Q....Yo. .J.n....
272 0010  00 00 00 08 00 45 00 00  b4 1c cf 40 00 fc 11 a4   .....E.. ...@....
273 0020  cd ac 19 64 0e c6 5f e6  14 03 ff 08 01 00 a0 79   ...d.._. .......y
274 0030  f9 7b 55 8a eb 00 00 00  00 00 00 00 02 00 01 86   .{U..... ........
275 0040  a3 00 00 00 03 00 00 00  01 00 00 00 01 00 00 00   ........ ........
276 0050  4c 36 db 91 97 00 00 00  0a 61 74 6d 63 6c 69 65   L6...... .atmclie
277 0060  6e 74 32 00 00 00 00 00  00 00 00 00 01 00 00 00   nt2..... ........
278 0070  0b 00 00 00 01 00 00 00  00 00 00 00 02 00 00 00   ........ ........
279 0080  03 00 00 00 04 00 00 00  05 00 00 00 06 00 00 00   ........ ........
280 0090  07 00 00 00 08 00 00 00  09 00 00 00 0c 00 00 00   ........ ........
281 00a0  00 00 00 00 00 00 00 00  20 21 92 13 00 a7 92 59   ........  !.....Y
282 00b0  07 20 00 00 00 00 02 4a  77 db b5 19 01 19 00 00   . .....J w.......
283 00c0  00 01 a4 06 00 97 1b 05  00                        ........ .       
284
285 2002-12-31 07:55:32.0
286 0000  51 00 07 4a 01 6e 00 10  00 d4 cd 59 6f aa aa 03   Q..J.n.. ...Yo...
287 0010  00 00 00 08 00 45 00 00  8c 6d 3c 00 00 40 11 50   .....E.. .m<..@.P
288 0020  89 c6 5f e6 14 ac 19 64  0e 08 01 03 ff 00 78 1d   .._....d ......x.
289 0030  99 7b 55 8a eb 00 00 00  01 00 00 00 00 00 00 00   .{U..... ........
290 0040  00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00   ........ ........
291 0050  01 00 00 01 ed 00 00 00  01 00 00 00 00 00 00 00   ........ ........
292 0060  1e 00 00 00 00 00 04 07  60 00 00 00 00 00 04 20   ........ `...... 
293 0070  00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00   ........ ........
294 0080  19 00 00 00 00 00 02 4a  77 36 db 94 da 0c 84 5c   .......J w6......
295 0090  68 32 1e 28 e9 00 00 00  00 32 23 d4 10 0a 21 fe   h2.(.... .2#...!.
296 00a0  80  
297 """
298
299 # NTP
300 pkt_ntp = Packet(DLT_EN10MB)
301 pkt_ntp.data = """
302 0000  08 00 2b 91 e8 3a 08 00  2b e4 c4 43 08 00 45 00   ..+..:.. +..C..E.
303 0010  00 4c 64 4c 00 00 1e 11  02 47 82 dc 18 3e 82 dc   .LdL.... .G...>..
304 0020  18 18 00 7b 00 7b 00 38  ee 1c 1b 04 06 f5 00 00   ...{.{.8 ........
305 0030  10 0d 00 00 05 57 82 dc  18 18 ba 29 66 36 7d d0   .....W.. ...)f6}.
306 0040  00 00 ba 29 66 36 7d 58  40 00 ba 29 66 36 7d d0   ...)f6}X @..)f6}.
307 0050  00 00 ba 29 66 76 7d 50  50 00                     ...)fv}P P.      
308 """
309
310
311 # HTTP
312 pkt_http = Packet(DLT_EN10MB)
313 pkt_http.time_fmt = "%Y-%m-%d %H:%M:%S."
314 pkt_http.data = """
315 2002-12-31 07:55:31.3
316 0000  00 e0 81 00 b0 28 00 09  6b 88 f5 c9 08 00 45 00   .....(.. k.....E.
317 0010  00 c1 d2 49 40 00 80 06  c8 5b 0a 00 00 05 cf 2e   ...I@... .[......
318 0020  86 5e 0c c3 00 50 a8 00  76 87 7d e0 14 02 50 18   .^...P.. v.}...P.
319 0030  fa f0 ad 62 00 00 48 45  41 44 20 2f 76 34 2f 69   ...b..HE AD /v4/i
320 0040  75 69 64 65 6e 74 2e 63  61 62 3f 30 33 30 37 30   uident.c ab?03070
321 0050  31 31 32 30 38 20 48 54  54 50 2f 31 2e 31 0d 0a   11208 HT TP/1.1..
322 0060  41 63 63 65 70 74 3a 20  2a 2f 2a 0d 0a 55 73 65   Accept:  */*..Use
323 0070  72 2d 41 67 65 6e 74 3a  20 49 6e 64 75 73 74 72   r-Agent:  Industr
324 0080  79 20 55 70 64 61 74 65  20 43 6f 6e 74 72 6f 6c   y Update  Control
325 0090  0d 0a 48 6f 73 74 3a 20  77 69 6e 64 6f 77 73 75   ..Host:  windowsu
326 00a0  70 64 61 74 65 2e 6d 69  63 72 6f 73 6f 66 74 2e   pdate.mi crosoft.
327 00b0  63 6f 6d 0d 0a 43 6f 6e  6e 65 63 74 69 6f 6e 3a   com..Con nection:
328 00c0  20 4b 65 65 70 2d 41 6c  69 76 65 0d 0a 0d 0a       Keep-Al ive....
329 """
330
331
332 # TFTP
333 pkt_tftp = Packet(DLT_IEEE802)
334 pkt_tftp.data = """
335 0000  10 40 00 20 35 01 2b 59  00 06 29 17 93 f8 aa aa   .@. 5.+Y ..).....
336 0010  03 00 00 00 08 00 45 00  00 37 f9 39 00 00 40 11   ......E. .7.9..@.
337 0020  a6 db c0 a8 2c 7b c0 a8  2c d5 f9 39 00 45 00 23   ....,{.. ,..9.E.#
338 0030  8d 73 00 01 43 3a 5c 49  42 4d 54 43 50 49 50 5c   .s..C:\I BMTCPIP.
339 0040  6c 63 63 6d 2e 31 00 6f  63 74 65 74 00            lccm.1.o ctet.   
340 """
341
342
343 ################################################################################
344 # Add tests here
345 ################################################################################
346
347 class Bytes(Test):
348         """Tests routines in ftype-bytes.c"""
349
350         def __init__(self):
351                 print "Note: Bytes test does not yet test FT_INT64."
352
353         def ck_eq_1(self):
354                 return self.DFilterCount(pkt_ipx_rip,
355                         "eth.dst == ff:ff:ff:ff:ff:ff", 1)
356
357         def ck_eq_2(self):
358                 return self.DFilterCount(pkt_ipx_rip,
359                         "eth.src == ff:ff:ff:ff:ff:ff", 0)
360
361         def ck_ne_1(self):
362                 return self.DFilterCount(pkt_ipx_rip,
363                         "eth.dst != ff:ff:ff:ff:ff:ff", 0)
364
365         def ck_ne_2(self):
366                 return self.DFilterCount(pkt_ipx_rip,
367                         "eth.src != ff:ff:ff:ff:ff:ff", 1)
368
369         def ck_gt_1(self):
370                 return self.DFilterCount(pkt_ipx_rip,
371                         "eth.src > 00:aa:00:a3:e3:ff", 0)
372
373         def ck_gt_2(self):
374                 return self.DFilterCount(pkt_ipx_rip,
375                         "eth.src > 00:aa:00:a3:e3:a4", 0)
376
377         def ck_gt_3(self):
378                 return self.DFilterCount(pkt_ipx_rip,
379                         "eth.src > 00:aa:00:a3:e3:00", 1)
380
381         def ck_ge_1(self):
382                 return self.DFilterCount(pkt_ipx_rip,
383                         "eth.src >= 00:aa:00:a3:e3:ff", 0)
384
385         def ck_ge_2(self):
386                 return self.DFilterCount(pkt_ipx_rip,
387                         "eth.src >= 00:aa:00:a3:e3:a4", 1)
388
389         def ck_ge_3(self):
390                 return self.DFilterCount(pkt_ipx_rip,
391                         "eth.src >= 00:aa:00:a3:e3:00", 1)
392
393         def ck_lt_1(self):
394                 return self.DFilterCount(pkt_ipx_rip,
395                         "eth.src < 00:aa:00:a3:e3:ff", 1)
396
397         def ck_lt_2(self):
398                 return self.DFilterCount(pkt_ipx_rip,
399                         "eth.src < 00:aa:00:a3:e3:a4", 0)
400
401         def ck_lt_3(self):
402                 return self.DFilterCount(pkt_ipx_rip,
403                         "eth.src < 00:aa:00:a3:e3:00", 0)
404
405         def ck_le_1(self):
406                 return self.DFilterCount(pkt_ipx_rip,
407                         "eth.src <= 00:aa:00:a3:e3:ff", 1)
408
409         def ck_le_2(self):
410                 return self.DFilterCount(pkt_ipx_rip,
411                         "eth.src <= 00:aa:00:a3:e3:a4", 1)
412
413         def ck_le_3(self):
414                 return self.DFilterCount(pkt_ipx_rip,
415                         "eth.src <= 00:aa:00:a3:e3:00", 0)
416
417         def ck_slice_1(self):
418                 return self.DFilterCount(pkt_ipx_rip,
419                         "eth.src[0:3] == 00:aa:00", 1)
420
421         def ck_slice_2(self):
422                 return self.DFilterCount(pkt_ipx_rip,
423                         "eth.src[-3:3] == a3:e3:a4", 1)
424
425         def ck_slice_3(self):
426                 return self.DFilterCount(pkt_ipx_rip,
427                         "eth.src[1:4] == aa:00:a3:e3", 1)
428
429         def ck_slice_4(self):
430                 return self.DFilterCount(pkt_ipx_rip,
431                         "eth.src[0] == 00", 1)
432
433         def ck_ipv6_1(self):
434                 return self.DFilterCount(pkt_ipv6,
435                         "ipv6.dst == ff05::9999", 1)
436
437         def ck_ipv6_2(self):
438                 return self.DFilterCount(pkt_ipv6,
439                         "ipv6.dst == ff05::9990", 0)
440
441         # ck_eq_1 checks FT_ETHER; this checks FT_BYTES
442         def ck_bytes_1(self):
443                 return self.DFilterCount(pkt_arp,
444                         "arp.dst.hw == 00:64", 1)
445
446         # ck_eq_2 checks FT_ETHER; this checks FT_BYTES
447         def ck_bytes_2(self):
448                 return self.DFilterCount(pkt_arp,
449                         "arp.dst.hw == 00:00", 0)
450
451         # ck_eq_1 checks FT_ETHER; this checks FT_UINT64
452         def ck_uint64_1(self):
453                 return self.DFilterCount(pkt_nfs,
454                         "nfs.fattr3.size == 264032", 1)
455
456         # ck_eq_2 checks FT_ETHER; this checks FT_UINT64
457         def ck_uint64_2(self):
458                 return self.DFilterCount(pkt_nfs,
459                         "nfs.fattr3.size == 264000", 0)
460
461         def ck_contains_1(self):
462                 return self.DFilterCount(pkt_ipx_rip,
463                         "ipx.src.node contains a3", 1)
464
465         def ck_contains_2(self):
466                 return self.DFilterCount(pkt_ipx_rip,
467                         "ipx.src.node contains a3:e3", 1)
468
469         def ck_contains_3(self):
470                 return self.DFilterCount(pkt_ipx_rip,
471                         "ipx.src.node contains 00:aa:00:a3:e3:a4", 1)
472
473         def ck_contains_4(self):
474                 return self.DFilterCount(pkt_ipx_rip,
475                         "ipx.src.node contains aa:e3", 0)
476
477
478         tests = [
479                 ck_eq_1,
480                 ck_eq_2,
481                 ck_ne_1,
482                 ck_ne_2,
483                 ck_gt_1,
484                 ck_gt_2,
485                 ck_gt_3,
486                 ck_ge_1,
487                 ck_ge_2,
488                 ck_ge_3,
489                 ck_lt_1,
490                 ck_lt_2,
491                 ck_lt_3,
492                 ck_le_1,
493                 ck_le_2,
494                 ck_le_3,
495                 ck_slice_1,
496                 ck_slice_2,
497                 ck_slice_3,
498                 ck_slice_4,
499                 ck_ipv6_1,
500                 ck_ipv6_2,
501                 ck_bytes_1,
502                 ck_bytes_2,
503                 ck_uint64_1,
504                 ck_uint64_2,
505                 ck_contains_1,
506                 ck_contains_2,
507                 ck_contains_3,
508                 ck_contains_4,
509                 ]
510
511
512 class Double(Test):
513         """Tests routines in ftype-double.c"""
514
515         def ck_eq_1(self):
516                 # This works on ia32/Linux
517                 # http://www.cslab.vt.edu/manuals/glibc-2.2.3/html_node/libc_673.html
518                 return self.DFilterCount(pkt_ntp,
519                         "ntp.rootdelay == 0.0626983642578125", 1)
520
521         def ck_eq_2(self):
522                 return self.DFilterCount(pkt_ntp,
523                         "ntp.rootdelay == 0.0626", 0)
524
525         def ck_gt_1(self):
526                 return self.DFilterCount(pkt_ntp,
527                         "ntp.rootdelay > 1.0626", 0)
528
529         def ck_gt_2(self):
530                 return self.DFilterCount(pkt_ntp,
531                         "ntp.rootdelay > 0.0626983642578125", 0)
532
533         def ck_gt_3(self):
534                 return self.DFilterCount(pkt_ntp,
535                         "ntp.rootdelay > 0.0026", 1)
536
537         def ck_ge_1(self):
538                 return self.DFilterCount(pkt_ntp,
539                         "ntp.rootdelay >= 1.0626", 0)
540
541         def ck_ge_2(self):
542                 return self.DFilterCount(pkt_ntp,
543                         "ntp.rootdelay >= 0.0626983642578125", 1)
544
545         def ck_ge_3(self):
546                 return self.DFilterCount(pkt_ntp,
547                         "ntp.rootdelay > 0.0026", 1)
548
549         def ck_lt_1(self):
550                 return self.DFilterCount(pkt_ntp,
551                         "ntp.rootdelay < 1.0626", 1)
552
553         def ck_lt_2(self):
554                 return self.DFilterCount(pkt_ntp,
555                         "ntp.rootdelay < 0.0626983642578125", 0)
556
557         def ck_lt_3(self):
558                 return self.DFilterCount(pkt_ntp,
559                         "ntp.rootdelay < 0.0026", 0)
560
561         def ck_le_1(self):
562                 return self.DFilterCount(pkt_ntp,
563                         "ntp.rootdelay <= 1.0626", 1)
564
565         def ck_le_2(self):
566                 return self.DFilterCount(pkt_ntp,
567                         "ntp.rootdelay <= 0.0626983642578125", 1)
568
569         def ck_le_3(self):
570                 return self.DFilterCount(pkt_ntp,
571                         "ntp.rootdelay <= 0.0026", 0)
572
573
574         tests = [
575                 ck_eq_1,
576                 ck_eq_2,
577                 ck_gt_1,
578                 ck_gt_2,
579                 ck_gt_3,
580                 ck_ge_1,
581                 ck_ge_2,
582                 ck_ge_3,
583                 ck_lt_1,
584                 ck_lt_2,
585                 ck_lt_3,
586                 ck_le_1,
587                 ck_le_2,
588                 ck_le_3,
589                 ]
590
591 class Integer(Test):
592         """Tests routines in ftype-integer.c"""
593
594         def ck_eq_1(self):
595                 return self.DFilterCount(pkt_ntp,
596                         "ip.version == 4", 1)
597
598         def ck_eq_2(self):
599                 return self.DFilterCount(pkt_ntp,
600                         "ip.version == 6", 0)
601
602         def ck_ne_1(self):
603                 return self.DFilterCount(pkt_ntp,
604                         "ip.version != 0", 1)
605
606         def ck_ne_2(self):
607                 return self.DFilterCount(pkt_ntp,
608                         "ip.version != 4", 0)
609
610         def ck_u_gt_1(self):
611                 return self.DFilterCount(pkt_ntp,
612                         "ip.version > 3", 1)
613
614         def ck_u_gt_2(self):
615                 return self.DFilterCount(pkt_ntp,
616                         "ip.version > 4", 0)
617
618         def ck_u_gt_3(self):
619                 return self.DFilterCount(pkt_ntp,
620                         "ip.version > 5", 0)
621
622         def ck_u_ge_1(self):
623                 return self.DFilterCount(pkt_ntp,
624                         "ip.version >= 3", 1)
625
626         def ck_u_ge_2(self):
627                 return self.DFilterCount(pkt_ntp,
628                         "ip.version >= 4", 1)
629
630         def ck_u_ge_3(self):
631                 return self.DFilterCount(pkt_ntp,
632                         "ip.version >= 5", 0)
633
634         def ck_u_lt_1(self):
635                 return self.DFilterCount(pkt_ntp,
636                         "ip.version < 3", 0)
637
638         def ck_u_lt_2(self):
639                 return self.DFilterCount(pkt_ntp,
640                         "ip.version < 4", 0)
641
642         def ck_u_lt_3(self):
643                 return self.DFilterCount(pkt_ntp,
644                         "ip.version < 5", 1)
645
646         def ck_u_le_1(self):
647                 return self.DFilterCount(pkt_ntp,
648                         "ip.version <= 3", 0)
649
650         def ck_u_le_2(self):
651                 return self.DFilterCount(pkt_ntp,
652                         "ip.version <= 4", 1)
653
654         def ck_u_le_3(self):
655                 return self.DFilterCount(pkt_ntp,
656                         "ip.version <= 5", 1)
657
658         def ck_s_gt_1(self):
659                 return self.DFilterCount(pkt_ntp,
660                         "ntp.precision > -12", 1)
661
662         def ck_s_gt_2(self):
663                 return self.DFilterCount(pkt_ntp,
664                         "ntp.precision > -11", 0)
665
666         def ck_s_gt_3(self):
667                 return self.DFilterCount(pkt_ntp,
668                         "ntp.precision > -10", 0)
669
670         def ck_s_ge_1(self):
671                 return self.DFilterCount(pkt_ntp,
672                         "ntp.precision >= -12", 1)
673
674         def ck_s_ge_2(self):
675                 return self.DFilterCount(pkt_ntp,
676                         "ntp.precision >= -11", 1)
677
678         def ck_s_ge_3(self):
679                 return self.DFilterCount(pkt_ntp,
680                         "ntp.precision >= -10", 0)
681
682         def ck_s_lt_1(self):
683                 return self.DFilterCount(pkt_ntp,
684                         "ntp.precision < -12", 0)
685
686         def ck_s_lt_2(self):
687                 return self.DFilterCount(pkt_ntp,
688                         "ntp.precision < -11", 0)
689
690         def ck_s_lt_3(self):
691                 return self.DFilterCount(pkt_ntp,
692                         "ntp.precision < -10", 1)
693
694         def ck_s_le_1(self):
695                 return self.DFilterCount(pkt_ntp,
696                         "ntp.precision <= -12", 0)
697
698         def ck_s_le_2(self):
699                 return self.DFilterCount(pkt_ntp,
700                         "ntp.precision <= -11", 1)
701
702         def ck_s_le_3(self):
703                 return self.DFilterCount(pkt_ntp,
704                         "ntp.precision <= -10", 1)
705
706         def ck_bool_eq_1(self):
707                 return self.DFilterCount(pkt_ntp,
708                         "ip.flags.df == 0", 1)
709
710         def ck_bool_eq_2(self):
711                 return self.DFilterCount(pkt_ntp,
712                         "ip.flags.df == 1", 0)
713
714         def ck_bool_ne_1(self):
715                 return self.DFilterCount(pkt_ntp,
716                         "ip.flags.df != 1", 1)
717
718         def ck_bool_ne_2(self):
719                 return self.DFilterCount(pkt_ntp,
720                         "ip.flags.df != 0", 0)
721
722         def ck_ipx_1(self):
723                 return self.DFilterCount(pkt_ipx_rip,
724                         "ipx.src.net == 0x28", 1)
725
726         def ck_ipx_2(self):
727                 return self.DFilterCount(pkt_ipx_rip,
728                         "ipx.src.net == 0x29", 0)
729
730
731         tests = [
732                 ck_eq_1,
733                 ck_eq_2,
734                 ck_ne_1,
735                 ck_ne_2,
736                 ck_u_gt_1,
737                 ck_u_gt_2,
738                 ck_u_gt_3,
739                 ck_u_ge_1,
740                 ck_u_ge_2,
741                 ck_u_ge_3,
742                 ck_u_lt_1,
743                 ck_u_lt_2,
744                 ck_u_lt_3,
745                 ck_u_le_1,
746                 ck_u_le_2,
747                 ck_u_le_3,
748                 ck_s_gt_1,
749                 ck_s_gt_2,
750                 ck_s_gt_3,
751                 ck_s_ge_1,
752                 ck_s_ge_2,
753                 ck_s_ge_3,
754                 ck_s_lt_1,
755                 ck_s_lt_2,
756                 ck_s_lt_3,
757                 ck_s_le_1,
758                 ck_s_le_2,
759                 ck_s_le_3,
760                 ck_bool_eq_1,
761                 ck_bool_eq_2,
762                 ck_bool_ne_1,
763                 ck_bool_ne_2,
764                 ck_ipx_1,
765                 ck_ipx_2,
766                 ]
767
768 class IPv4(Test):
769         """Tests routines in ftype-ipv4.c"""
770
771         def ck_eq_1(self):
772                 return self.DFilterCount(pkt_nfs,
773                         "ip.src == 172.25.100.14", 1)
774
775         def ck_eq_2(self):
776                 return self.DFilterCount(pkt_nfs,
777                         "ip.src == 255.255.255.255", 0)
778
779         def ck_ne_1(self):
780                 return self.DFilterCount(pkt_nfs,
781                         "ip.src != 172.25.100.14", 1)
782
783         def ck_ne_2(self):
784                 return self.DFilterCount(pkt_nfs,
785                         "ip.src != 255.255.255.255", 2)
786
787         def ck_gt_1(self):
788                 return self.DFilterCount(pkt_nfs,
789                         "ip.dst > 198.95.230.200", 0)
790
791         def ck_gt_2(self):
792                 return self.DFilterCount(pkt_nfs,
793                         "ip.dst > 198.95.230.20", 0)
794
795         def ck_gt_3(self):
796                 return self.DFilterCount(pkt_nfs,
797                         "ip.dst > 198.95.230.10", 1)
798
799         def ck_ge_1(self):
800                 return self.DFilterCount(pkt_nfs,
801                         "ip.dst >= 198.95.230.200", 0)
802
803         def ck_ge_2(self):
804                 return self.DFilterCount(pkt_nfs,
805                         "ip.dst >= 198.95.230.20", 1)
806
807         def ck_ge_3(self):
808                 return self.DFilterCount(pkt_nfs,
809                         "ip.dst >= 198.95.230.10", 1)
810
811         def ck_lt_1(self):
812                 return self.DFilterCount(pkt_nfs,
813                         "ip.src < 172.25.100.140", 1)
814
815         def ck_lt_2(self):
816                 return self.DFilterCount(pkt_nfs,
817                         "ip.src < 172.25.100.14", 0)
818
819         def ck_lt_3(self):
820                 return self.DFilterCount(pkt_nfs,
821                         "ip.src < 172.25.100.10", 0)
822
823         def ck_le_1(self):
824                 return self.DFilterCount(pkt_nfs,
825                         "ip.src <= 172.25.100.140", 1)
826
827         def ck_le_2(self):
828                 return self.DFilterCount(pkt_nfs,
829                         "ip.src <= 172.25.100.14", 1)
830
831         def ck_le_3(self):
832                 return self.DFilterCount(pkt_nfs,
833                         "ip.src <= 172.25.100.10", 0)
834
835         def ck_cidr_eq_1(self):
836                 return self.DFilterCount(pkt_nfs,
837                         "ip.src == 172.25.100.14/32", 1)
838
839         def ck_cidr_eq_2(self):
840                 return self.DFilterCount(pkt_nfs,
841                         "ip.src == 172.25.100.0/24", 1)
842
843         def ck_cidr_eq_3(self):
844                 return self.DFilterCount(pkt_nfs,
845                         "ip.src == 172.25.0.0/16", 1)
846
847         def ck_cidr_eq_4(self):
848                 return self.DFilterCount(pkt_nfs,
849                         "ip.src == 172.0.0.0/8", 1)
850
851         def ck_cidr_ne_1(self):
852                 return self.DFilterCount(pkt_nfs,
853                         "ip.src != 172.25.100.14/32", 1)
854
855         def ck_cidr_ne_2(self):
856                 return self.DFilterCount(pkt_nfs,
857                         "ip.src != 172.25.100.0/24", 1)
858
859         def ck_cidr_ne_3(self):
860                 return self.DFilterCount(pkt_nfs,
861                         "ip.src != 172.25.0.0/16", 1)
862
863         def ck_cidr_ne_4(self):
864                 return self.DFilterCount(pkt_nfs,
865                         "ip.src != 200.0.0.0/8", 2)
866
867         tests = [
868                 ck_eq_1,
869                 ck_eq_2,
870                 ck_ne_1,
871                 ck_ne_2,
872                 ck_gt_1,
873                 ck_gt_2,
874                 ck_gt_3,
875                 ck_ge_1,
876                 ck_ge_2,
877                 ck_ge_3,
878                 ck_lt_1,
879                 ck_lt_2,
880                 ck_lt_3,
881                 ck_le_1,
882                 ck_le_2,
883                 ck_le_3,
884                 ck_cidr_eq_1,
885                 ck_cidr_eq_2,
886                 ck_cidr_eq_3,
887                 ck_cidr_eq_4,
888                 ck_cidr_ne_1,
889                 ck_cidr_ne_2,
890                 ck_cidr_ne_3,
891                 ck_cidr_ne_4,
892                 ]
893
894 class String(Test):
895         """Tests routines in ftype-string.c"""
896
897         def ck_eq_1(self):
898                 return self.DFilterCount(pkt_http,
899                         'http.request.method == "HEAD"', 1)
900
901         def ck_eq_2(self):
902                 return self.DFilterCount(pkt_http,
903                         'http.request.method == "POST"', 0)
904
905         def ck_gt_1(self):
906                 return self.DFilterCount(pkt_http,
907                         'http.request.method > "HEAC"', 1)
908
909         def ck_gt_2(self):
910                 return self.DFilterCount(pkt_http,
911                         'http.request.method > "HEAD"', 0)
912
913         def ck_gt_3(self):
914                 return self.DFilterCount(pkt_http,
915                         'http.request.method > "HEAE"', 0)
916
917         def ck_ge_1(self):
918                 return self.DFilterCount(pkt_http,
919                         'http.request.method >= "HEAC"', 1)
920
921         def ck_ge_2(self):
922                 return self.DFilterCount(pkt_http,
923                         'http.request.method >= "HEAD"', 1)
924
925         def ck_ge_3(self):
926                 return self.DFilterCount(pkt_http,
927                         'http.request.method >= "HEAE"', 0)
928
929         def ck_lt_1(self):
930                 return self.DFilterCount(pkt_http,
931                         'http.request.method < "HEAC"', 0)
932
933         def ck_lt_2(self):
934                 return self.DFilterCount(pkt_http,
935                         'http.request.method < "HEAD"', 0)
936
937         def ck_lt_3(self):
938                 return self.DFilterCount(pkt_http,
939                         'http.request.method < "HEAE"', 1)
940
941         def ck_le_1(self):
942                 return self.DFilterCount(pkt_http,
943                         'http.request.method <= "HEAC"', 0)
944
945         def ck_le_2(self):
946                 return self.DFilterCount(pkt_http,
947                         'http.request.method <= "HEAD"', 1)
948
949         def ck_le_3(self):
950                 return self.DFilterCount(pkt_http,
951                         'http.request.method <= "HEAE"', 1)
952
953         # XXX - this isn't handled in wireshark yet
954         def ck_slice_1(self):
955                 return self.DFilterCount(pkt_http,
956                         'http.request.method[0] == "H"', 1)
957
958         def ck_slice_2(self):
959                 return self.DFilterCount(pkt_http,
960                         'http.request.method[0] == "P"', 0)
961
962         def ck_slice_3(self):
963                 return self.DFilterCount(pkt_http,
964                         'http.request.method[0:4] == "HEAD"', 1)
965
966         def ck_slice_4(self):
967                 return self.DFilterCount(pkt_http,
968                         'http.request.method[0:4] != "HEAD"', 0)
969
970         def ck_slice_5(self):
971                 return self.DFilterCount(pkt_http,
972                         'http.request.method[1:2] == "EA"', 1)
973
974         def ck_slice_6(self):
975                 return self.DFilterCount(pkt_http,
976                         'http.request.method[1:2] > "EA"', 0)
977
978         def ck_slice_7(self):
979                 return self.DFilterCount(pkt_http,
980                         'http.request.method[-1] == "D"', 1)
981
982         def ck_slice_8(self):
983                 return self.DFilterCount(pkt_http,
984                         'http.request.method[-2] == "D"', 0)
985
986         def ck_stringz_1(self):
987                 return self.DFilterCount(pkt_tftp,
988                         'tftp.type == "octet"', 1)
989
990         def ck_stringz_2(self):
991                 return self.DFilterCount(pkt_tftp,
992                         'tftp.type == "junk"', 0)
993
994         def ck_contains_1(self):
995                 return self.DFilterCount(pkt_http,
996                         'http.request.method contains "E"', 1)
997
998         def ck_contains_2(self):
999                 return self.DFilterCount(pkt_http,
1000                         'http.request.method contains "EA"', 1)
1001
1002         def ck_contains_3(self):
1003                 return self.DFilterCount(pkt_http,
1004                         'http.request.method contains "HEAD"', 1)
1005
1006         def ck_contains_4(self):
1007                 return self.DFilterCount(pkt_http,
1008                         'http.request.method contains "POST"', 0)
1009
1010         def ck_contains_5(self):
1011                 return self.DFilterCount(pkt_http,
1012                         'http.request.method contains 50:4f:53:54"', None) # "POST"
1013
1014         def ck_contains_6(self):
1015                 return self.DFilterCount(pkt_http,
1016         'http.request.method contains 48:45:41:44"', 1) # "HEAD"
1017
1018         def ck_contains_fail_0(self):
1019                 return self.DFilterCount(pkt_http,
1020                         'http.user_agent contains "update"', 0)
1021
1022         def ck_contains_fail_1(self):
1023                 return self.DFilterCount(pkt_http,
1024                         'http.user_agent contains "UPDATE"', 0)
1025
1026         def ck_contains_upper_0(self):
1027                 return self.DFilterCount(pkt_http,
1028                         'upper(http.user_agent) contains "UPDATE"', 1)
1029
1030         def ck_contains_upper_1(self):
1031                 return self.DFilterCount(pkt_http,
1032                         'upper(http.user_agent) contains "update"', 0)
1033
1034         def ck_contains_upper_2(self):
1035                 return self.DFilterCount(pkt_http,
1036                         'upper(tcp.seq) == 4', None)
1037
1038         def ck_contains_lower_0(self):
1039                 return self.DFilterCount(pkt_http,
1040                         'lower(http.user_agent) contains "UPDATE"', 0)
1041
1042         def ck_contains_lower_1(self):
1043                 return self.DFilterCount(pkt_http,
1044                         'lower(http.user_agent) contains "update"', 1)
1045
1046         def ck_contains_lower_2(self):
1047                 return self.DFilterCount(pkt_http,
1048                         'lower(tcp.seq) == 4', None)
1049
1050
1051         tests = [
1052                 ck_eq_1,
1053                 ck_eq_2,
1054                 ck_gt_1,
1055                 ck_gt_2,
1056                 ck_gt_3,
1057                 ck_ge_1,
1058                 ck_ge_2,
1059                 ck_ge_3,
1060                 ck_lt_1,
1061                 ck_lt_2,
1062                 ck_lt_3,
1063                 ck_le_1,
1064                 ck_le_2,
1065                 ck_le_3,
1066 # XXX
1067 #               ck_slice_1,
1068 #               ck_slice_2,
1069 #               ck_slice_3,
1070 #               ck_slice_4,
1071 #               ck_slice_5,
1072 #               ck_slice_6,
1073 #               ck_slice_7,
1074 #               ck_slice_8,
1075                 ck_stringz_1,
1076                 ck_stringz_2,
1077                 ck_contains_1,
1078                 ck_contains_2,
1079                 ck_contains_3,
1080                 ck_contains_4,
1081                 ck_contains_5,
1082                 ck_contains_fail_0,
1083                 ck_contains_fail_1,
1084                 ck_contains_upper_0,
1085                 ck_contains_upper_1,
1086                 ck_contains_upper_2,
1087                 ck_contains_lower_0,
1088                 ck_contains_lower_1,
1089                 ck_contains_lower_2,
1090                 ]
1091
1092
1093 class Time(Test):
1094         """Tests routines in ftype-time.c"""
1095
1096         def ck_eq_1(self):
1097                 return self.DFilterCount(pkt_http,
1098                         'frame.time == "Dec 31, 2002 07:55:31.3"', 1)
1099
1100         def ck_eq_2(self):
1101                 return self.DFilterCount(pkt_http,
1102                         'frame.time == "Jan 31, 2002 07:55:31.3"', 0)
1103
1104         def ck_ne_1(self):
1105                 return self.DFilterCount(pkt_http,
1106                         'frame.time != "Dec 31, 2002 07:55:31.3"', 0)
1107
1108         def ck_ne_2(self):
1109                 return self.DFilterCount(pkt_http,
1110                         'frame.time != "Jan 31, 2002 07:55:31.3"', 1)
1111
1112         def ck_gt_1(self):
1113                 return self.DFilterCount(pkt_http,
1114                         'frame.time > "Dec 31, 2002 07:54:31.3"', 1)
1115
1116         def ck_gt_2(self):
1117                 return self.DFilterCount(pkt_http,
1118                         'frame.time > "Dec 31, 2002 07:55:31.3"', 0)
1119
1120         def ck_gt_3(self):
1121                 return self.DFilterCount(pkt_http,
1122                         'frame.time > "Dec 31, 2002 07:56:31.3"', 0)
1123
1124         def ck_ge_1(self):
1125                 return self.DFilterCount(pkt_http,
1126                         'frame.time >= "Dec 31, 2002 07:54:31.3"', 1)
1127
1128         def ck_ge_2(self):
1129                 return self.DFilterCount(pkt_http,
1130                         'frame.time >= "Dec 31, 2002 07:55:31.3"', 1)
1131
1132         def ck_ge_3(self):
1133                 return self.DFilterCount(pkt_http,
1134                         'frame.time >= "Dec 31, 2002 07:56:31.3"', 0)
1135
1136         def ck_lt_1(self):
1137                 return self.DFilterCount(pkt_http,
1138                         'frame.time < "Dec 31, 2002 07:54:31.3"', 0)
1139
1140         def ck_lt_2(self):
1141                 return self.DFilterCount(pkt_http,
1142                         'frame.time < "Dec 31, 2002 07:55:31.3"', 0)
1143
1144         def ck_lt_3(self):
1145                 return self.DFilterCount(pkt_http,
1146                         'frame.time < "Dec 31, 2002 07:56:31.3"', 1)
1147
1148         def ck_le_1(self):
1149                 return self.DFilterCount(pkt_http,
1150                         'frame.time <= "Dec 31, 2002 07:54:31.3"', 0)
1151
1152         def ck_le_2(self):
1153                 return self.DFilterCount(pkt_http,
1154                         'frame.time <= "Dec 31, 2002 07:55:31.3"', 1)
1155
1156         def ck_le_3(self):
1157                 return self.DFilterCount(pkt_http,
1158                         'frame.time <= "Dec 31, 2002 07:56:31.3"', 1)
1159
1160         def ck_relative_time_1(self):
1161                 return self.DFilterCount(pkt_nfs,
1162                         "frame.time_delta == 0.7", 1)
1163
1164         def ck_relative_time_2(self):
1165                 return self.DFilterCount(pkt_nfs,
1166                         "frame.time_delta > 0.7", 0)
1167
1168         def ck_relative_time_3(self):
1169                 return self.DFilterCount(pkt_nfs,
1170                         "frame.time_delta < 0.7", 1)
1171
1172         tests = [
1173                 ck_eq_1,
1174                 ck_eq_2,
1175                 ck_ne_1,
1176                 ck_ne_2,
1177                 ck_gt_1,
1178                 ck_gt_2,
1179                 ck_gt_3,
1180                 ck_ge_1,
1181                 ck_ge_2,
1182                 ck_ge_3,
1183                 ck_lt_1,
1184                 ck_lt_2,
1185                 ck_lt_3,
1186                 ck_le_1,
1187                 ck_le_2,
1188                 ck_le_3,
1189                 ck_relative_time_1,
1190                 ck_relative_time_2,
1191                 ck_relative_time_3,
1192                 ]
1193
1194 class TVB(Test):
1195         """Tests routines in ftype-tvb.c"""
1196
1197         def ck_eq_1(self):
1198                 # We expect 0 because even though this byte
1199                 # string matches the 'eth' protocol, protocols cannot
1200                 # work in an '==' comparison yet.
1201                 return self.DFilterCount(pkt_http,
1202                         "eth == 00:e0:81:00:b0:28:00:09:6b:88:f6:c9:08:00", 0)
1203
1204         def ck_slice_1(self):
1205                 return self.DFilterCount(pkt_http,
1206                         "ip[0:2] == 45:00", 1)
1207
1208         def ck_slice_2(self):
1209                 return self.DFilterCount(pkt_http,
1210                         "ip[0:2] == 00:00", 0)
1211
1212         def ck_slice_3(self):
1213                 return self.DFilterCount(pkt_http,
1214                         "ip[2:2] == 00:c1", 1)
1215
1216         # These don't work yet in Wireshark
1217         def ck_slice_4(self):
1218                 return self.DFilterCount(pkt_http,
1219                         "ip[-5] == 0x86", 1)
1220
1221         def ck_slice_5(self):
1222                 return self.DFilterCount(pkt_http,
1223                         "ip[-1] == 0x86", 0)
1224
1225
1226         def ck_contains_1(self):
1227                 return self.DFilterCount(pkt_http,
1228                         "eth contains 6b", 1)
1229
1230         def ck_contains_2(self):
1231                 return self.DFilterCount(pkt_http,
1232                         "eth contains 09:6b:88", 1)
1233
1234         def ck_contains_3(self):
1235                 return self.DFilterCount(pkt_http,
1236                         "eth contains 00:e0:81:00:b0:28:00:09:6b:88:f5:c9:08:00", 1)
1237
1238         def ck_contains_4(self):
1239                 return self.DFilterCount(pkt_http,
1240                         "eth contains ff:ff:ff", 0)
1241
1242         def ck_contains_5(self):
1243                 return self.DFilterCount(pkt_http,
1244                         'http contains "HEAD"', 1)
1245
1246
1247         tests = [
1248                 ck_eq_1,
1249
1250                 ck_slice_1,
1251                 ck_slice_2,
1252                 ck_slice_3,
1253 # XXX
1254 #               ck_slice_4,
1255 #               ck_slice_5,
1256                 ck_contains_1,
1257                 ck_contains_2,
1258                 ck_contains_3,
1259                 ck_contains_4,
1260                 ck_contains_5,
1261                 ]
1262
1263
1264 class Scanner(Test):
1265         """Tests routines in scanner.l"""
1266
1267         def __init__(self):
1268                 print "Note: Scanner test does not yet test embedded double-quote."
1269
1270         def ck_dquote_1(self):
1271                 return self.DFilterCount(pkt_http,
1272                         'http.request.method == "HEAD"', 1)
1273
1274         def ck_dquote_2(self):
1275                 return self.DFilterCount(pkt_http,
1276                         'http.request.method == "\\x48EAD"', 1)
1277
1278         def ck_dquote_3(self):
1279                 return self.DFilterCount(pkt_http,
1280                         'http.request.method == "\\x58EAD"', 0)
1281
1282         def ck_dquote_4(self):
1283                 return self.DFilterCount(pkt_http,
1284                         'http.request.method == "\\110EAD"', 1)
1285
1286         def ck_dquote_5(self):
1287                 return self.DFilterCount(pkt_http,
1288                         'http.request.method == "\\111EAD"', 0)
1289
1290         def ck_dquote_6(self):
1291                 return self.DFilterCount(pkt_http,
1292                         'http.request.method == "\\HEAD"', 1)
1293
1294         tests = [
1295                 ck_dquote_1,
1296                 ck_dquote_2,
1297                 ck_dquote_3,
1298                 ck_dquote_4,
1299                 ck_dquote_5,
1300                 ]
1301
1302 ################################################################################
1303
1304 # These are the test objects to run.
1305 # Keep these in alphabetical order so the help message
1306 # shows them in order.
1307 all_tests = [
1308         Bytes(),
1309         Double(),
1310         Integer(),
1311         IPv4(),
1312         Scanner(),
1313         String(),
1314         Time(),
1315         TVB(),
1316         ]
1317
1318 def usage():
1319         print "usage: %s [OPTS] [TEST ...]" % (sys.argv[0],)
1320         print "\t-p PATH : path to find both tshark and text2pcap (DEFAULT: . )"
1321         print "\t-t FILE : location of tshark binary"
1322         print "\t-x FILE : location of text2pcap binary"
1323         print "\t-k      : keep temporary files"
1324         print "\t-v      : verbose"
1325         print
1326         print "By not mentioning a test name, all tests are run."
1327         print "Available tests are:"
1328         for test in all_tests:
1329                 print "\t", test.__class__.__name__
1330         sys.exit(1)
1331
1332 def main():
1333
1334         global TSHARK
1335         global TEXT2PCAP
1336         global VERBOSE
1337         global REMOVE_TEMP_FILES
1338
1339         # Parse the command-line options
1340         optstring = "p:t:x:kv"
1341         longopts = []
1342         
1343         try:
1344                 opts, specific_tests = getopt.getopt(sys.argv[1:], optstring, longopts)
1345         except getopt.GetoptError:
1346                 usage()
1347
1348         for opt, arg in opts:
1349                 if opt == "-t":
1350                         TSHARK = arg
1351                 elif opt == "-x":
1352                         TEXT2PCAP = arg
1353                 elif opt == "-v":
1354                         VERBOSE = 1
1355                 elif opt == "-p":
1356                         TEXT2PCAP = os.path.join(arg, "text2pcap")
1357                         TSHARK = os.path.join(arg, "tshark")
1358                 elif opt == "-k":
1359                         REMOVE_TEMP_FILES = 0
1360                 else:
1361                         print "Un-handled option:", opt
1362                         usage()
1363
1364         # Sanity test
1365         if not os.path.exists(TSHARK):
1366                 sys.exit("tshark program '%s' does not exist." % (TSHARK,))
1367
1368         if not os.path.exists(TEXT2PCAP):
1369                 sys.exit("text2pcap program '%s' does not exist." % (TEXT2PCAP,))
1370
1371
1372         # Determine which tests to run.
1373         tests_to_run = []
1374         if specific_tests:
1375                 # Go through the tests looking for the ones whose names
1376                 # match the command-line arguments.
1377                 all_ok = 1
1378                 for test_name in specific_tests:
1379                         for test in all_tests:
1380                                 if test_name == test.__class__.__name__:
1381                                         tests_to_run.append(test)
1382                                         break
1383                         else:
1384                                 print >> sys.stderr, "%s is unrecognized as a test." % \
1385                                         (test_name,)
1386                                 all_ok = 0
1387
1388                 if not all_ok:
1389                         sys.exit(1)
1390         else:
1391                 tests_to_run = all_tests
1392
1393         # Run the tests and keep score.
1394         tot_run = 0
1395         tot_succeeded = 0
1396         for test in tests_to_run:
1397                 print test.__class__.__name__
1398                 (run, succeeded) = test.Run()
1399                 tot_run += run
1400                 tot_succeeded += succeeded
1401                 print
1402
1403         print
1404         print "Total Tests Run:", tot_run
1405         print "Total Tests Succeeded:", tot_succeeded
1406         print "Total Tests Failed:", tot_run - tot_succeeded
1407
1408         if tot_succeeded == tot_run:
1409                 sys.exit(0)
1410         else:
1411                 sys.exit(1)
1412
1413 if __name__ == "__main__":
1414         try:
1415                 main()
1416         except KeyboardInterrupt:
1417                 print "\nInterrupted by user."