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