http://bugs.ethereal.com/bugzilla/show_bug.cgi?id=377
[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$
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 retval:
211                         tethereal_failed = 1
212
213                 if tethereal_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 ethereal 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
1019         tests = [
1020                 ck_eq_1,
1021                 ck_eq_2,
1022                 ck_gt_1,
1023                 ck_gt_2,
1024                 ck_gt_3,
1025                 ck_ge_1,
1026                 ck_ge_2,
1027                 ck_ge_3,
1028                 ck_lt_1,
1029                 ck_lt_2,
1030                 ck_lt_3,
1031                 ck_le_1,
1032                 ck_le_2,
1033                 ck_le_3,
1034 # XXX
1035 #               ck_slice_1,
1036 #               ck_slice_2,
1037 #               ck_slice_3,
1038 #               ck_slice_4,
1039 #               ck_slice_5,
1040 #               ck_slice_6,
1041 #               ck_slice_7,
1042 #               ck_slice_8,
1043                 ck_stringz_1,
1044                 ck_stringz_2,
1045                 ck_contains_1,
1046                 ck_contains_2,
1047                 ck_contains_3,
1048                 ck_contains_4,
1049                 ck_contains_5,
1050                 ]
1051
1052
1053 class Time(Test):
1054         """Tests routines in ftype-time.c"""
1055
1056         def ck_eq_1(self):
1057                 return self.DFilterCount(pkt_http,
1058                         'frame.time == "Dec 31, 2002 07:55:31.3"', 1)
1059
1060         def ck_eq_2(self):
1061                 return self.DFilterCount(pkt_http,
1062                         'frame.time == "Jan 31, 2002 07:55:31.3"', 0)
1063
1064         def ck_ne_1(self):
1065                 return self.DFilterCount(pkt_http,
1066                         'frame.time != "Dec 31, 2002 07:55:31.3"', 0)
1067
1068         def ck_ne_2(self):
1069                 return self.DFilterCount(pkt_http,
1070                         'frame.time != "Jan 31, 2002 07:55:31.3"', 1)
1071
1072         def ck_gt_1(self):
1073                 return self.DFilterCount(pkt_http,
1074                         'frame.time > "Dec 31, 2002 07:54:31.3"', 1)
1075
1076         def ck_gt_2(self):
1077                 return self.DFilterCount(pkt_http,
1078                         'frame.time > "Dec 31, 2002 07:55:31.3"', 0)
1079
1080         def ck_gt_3(self):
1081                 return self.DFilterCount(pkt_http,
1082                         'frame.time > "Dec 31, 2002 07:56:31.3"', 0)
1083
1084         def ck_ge_1(self):
1085                 return self.DFilterCount(pkt_http,
1086                         'frame.time >= "Dec 31, 2002 07:54:31.3"', 1)
1087
1088         def ck_ge_2(self):
1089                 return self.DFilterCount(pkt_http,
1090                         'frame.time >= "Dec 31, 2002 07:55:31.3"', 1)
1091
1092         def ck_ge_3(self):
1093                 return self.DFilterCount(pkt_http,
1094                         'frame.time >= "Dec 31, 2002 07:56:31.3"', 0)
1095
1096         def ck_lt_1(self):
1097                 return self.DFilterCount(pkt_http,
1098                         'frame.time < "Dec 31, 2002 07:54:31.3"', 0)
1099
1100         def ck_lt_2(self):
1101                 return self.DFilterCount(pkt_http,
1102                         'frame.time < "Dec 31, 2002 07:55:31.3"', 0)
1103
1104         def ck_lt_3(self):
1105                 return self.DFilterCount(pkt_http,
1106                         'frame.time < "Dec 31, 2002 07:56:31.3"', 1)
1107
1108         def ck_le_1(self):
1109                 return self.DFilterCount(pkt_http,
1110                         'frame.time <= "Dec 31, 2002 07:54:31.3"', 0)
1111
1112         def ck_le_2(self):
1113                 return self.DFilterCount(pkt_http,
1114                         'frame.time <= "Dec 31, 2002 07:55:31.3"', 1)
1115
1116         def ck_le_3(self):
1117                 return self.DFilterCount(pkt_http,
1118                         'frame.time <= "Dec 31, 2002 07:56:31.3"', 1)
1119
1120         def ck_relative_time_1(self):
1121                 return self.DFilterCount(pkt_nfs,
1122                         "frame.time_delta == 0.7", 1)
1123
1124         def ck_relative_time_2(self):
1125                 return self.DFilterCount(pkt_nfs,
1126                         "frame.time_delta > 0.7", 0)
1127
1128         def ck_relative_time_3(self):
1129                 return self.DFilterCount(pkt_nfs,
1130                         "frame.time_delta < 0.7", 1)
1131
1132         tests = [
1133                 ck_eq_1,
1134                 ck_eq_2,
1135                 ck_ne_1,
1136                 ck_ne_2,
1137                 ck_gt_1,
1138                 ck_gt_2,
1139                 ck_gt_3,
1140                 ck_ge_1,
1141                 ck_ge_2,
1142                 ck_ge_3,
1143                 ck_lt_1,
1144                 ck_lt_2,
1145                 ck_lt_3,
1146                 ck_le_1,
1147                 ck_le_2,
1148                 ck_le_3,
1149                 ck_relative_time_1,
1150                 ck_relative_time_2,
1151                 ck_relative_time_3,
1152                 ]
1153
1154 class TVB(Test):
1155         """Tests routines in ftype-tvb.c"""
1156
1157         def ck_eq_1(self):
1158                 # We expect 0 because even though this byte
1159                 # string matches the 'eth' protocol, protocols cannot
1160                 # work in an '==' comparison yet.
1161                 return self.DFilterCount(pkt_http,
1162                         "eth == 00:e0:81:00:b0:28:00:09:6b:88:f6:c9:08:00", None)
1163
1164         def ck_eq_2(self):
1165                 # We expect 0 because even though this byte
1166                 # string matches the 'eth' protocol, protocols cannot
1167                 # work in an '==' comparison yet.
1168                 return self.DFilterCount(pkt_http,
1169                         "00:e0:81:00:b0:28:00:09:6b:88:f6:c9:08:00 == eth", None)
1170
1171         def ck_slice_1(self):
1172                 return self.DFilterCount(pkt_http,
1173                         "ip[0:2] == 45:00", 1)
1174
1175         def ck_slice_2(self):
1176                 return self.DFilterCount(pkt_http,
1177                         "ip[0:2] == 00:00", 0)
1178
1179         def ck_slice_3(self):
1180                 return self.DFilterCount(pkt_http,
1181                         "ip[2:2] == 00:c1", 1)
1182
1183         # These don't work yet in Ethereal
1184         def ck_slice_4(self):
1185                 return self.DFilterCount(pkt_http,
1186                         "ip[-5] == 0x86", 1)
1187
1188         def ck_slice_5(self):
1189                 return self.DFilterCount(pkt_http,
1190                         "ip[-1] == 0x86", 0)
1191
1192
1193         def ck_contains_1(self):
1194                 return self.DFilterCount(pkt_http,
1195                         "eth contains 6b", 1)
1196
1197         def ck_contains_2(self):
1198                 return self.DFilterCount(pkt_http,
1199                         "eth contains 09:6b:88", 1)
1200
1201         def ck_contains_3(self):
1202                 return self.DFilterCount(pkt_http,
1203                         "eth contains 00:e0:81:00:b0:28:00:09:6b:88:f5:c9:08:00", 1)
1204
1205         def ck_contains_4(self):
1206                 return self.DFilterCount(pkt_http,
1207                         "eth contains ff:ff:ff", 0)
1208
1209         def ck_contains_5(self):
1210                 return self.DFilterCount(pkt_http,
1211                         'http contains "HEAD"', 1)
1212
1213
1214         tests = [
1215                 ck_eq_1,
1216                 ck_eq_2,
1217
1218                 ck_slice_1,
1219                 ck_slice_2,
1220                 ck_slice_3,
1221 # XXX
1222 #               ck_slice_4,
1223 #               ck_slice_5,
1224                 ck_contains_1,
1225                 ck_contains_2,
1226                 ck_contains_3,
1227                 ck_contains_4,
1228                 ck_contains_5,
1229                 ]
1230
1231
1232 class Scanner(Test):
1233         """Tests routines in scanner.l"""
1234
1235         def __init__(self):
1236                 print "Note: Scanner test does not yet test embedded double-quote."
1237
1238         def ck_dquote_1(self):
1239                 return self.DFilterCount(pkt_http,
1240                         'http.request.method == "HEAD"', 1)
1241
1242         def ck_dquote_2(self):
1243                 return self.DFilterCount(pkt_http,
1244                         'http.request.method == "\\x48EAD"', 1)
1245
1246         def ck_dquote_3(self):
1247                 return self.DFilterCount(pkt_http,
1248                         'http.request.method == "\\x58EAD"', 0)
1249
1250         def ck_dquote_4(self):
1251                 return self.DFilterCount(pkt_http,
1252                         'http.request.method == "\\110EAD"', 1)
1253
1254         def ck_dquote_5(self):
1255                 return self.DFilterCount(pkt_http,
1256                         'http.request.method == "\\111EAD"', 0)
1257
1258         def ck_dquote_6(self):
1259                 return self.DFilterCount(pkt_http,
1260                         'http.request.method == "\\HEAD"', 1)
1261
1262         tests = [
1263                 ck_dquote_1,
1264                 ck_dquote_2,
1265                 ck_dquote_3,
1266                 ck_dquote_4,
1267                 ck_dquote_5,
1268                 ]
1269
1270 ################################################################################
1271
1272 # These are the test objects to run.
1273 # Keep these in alphabetical order so the help message
1274 # shows them in order.
1275 all_tests = [
1276         Bytes(),
1277         Double(),
1278         Integer(),
1279         IPv4(),
1280         Scanner(),
1281         String(),
1282         Time(),
1283         TVB(),
1284         ]
1285
1286 def usage():
1287         print "usage: %s [OPTS] [TEST ...]" % (sys.argv[0],)
1288         print "\t-p PATH : path to find both tethereal and text2pcap (DEFAULT: . )"
1289         print "\t-t FILE : location of tethereal binary"
1290         print "\t-x FILE : location of text2pcap binary"
1291         print "\t-k      : keep temporary files"
1292         print "\t-v      : verbose"
1293         print
1294         print "By not mentioning a test name, all tests are run."
1295         print "Available tests are:"
1296         for test in all_tests:
1297                 print "\t", test.__class__.__name__
1298         sys.exit(1)
1299
1300 def main():
1301
1302         global TETHEREAL
1303         global TEXT2PCAP
1304         global VERBOSE
1305         global REMOVE_TEMP_FILES
1306
1307         # Parse the command-line options
1308         optstring = "p:t:x:kv"
1309         longopts = []
1310         
1311         try:
1312                 opts, specific_tests = getopt.getopt(sys.argv[1:], optstring, longopts)
1313         except getopt.GetoptError:
1314                 usage()
1315
1316         for opt, arg in opts:
1317                 if opt == "-t":
1318                         TETHEREAL = arg
1319                 elif opt == "-x":
1320                         TEXT2PCAP = arg
1321                 elif opt == "-v":
1322                         VERBOSE = 1
1323                 elif opt == "-p":
1324                         TEXT2PCAP = os.path.join(arg, "text2pcap")
1325                         TETHEREAL = os.path.join(arg, "tethereal")
1326                 elif opt == "-k":
1327                         REMOVE_TEMP_FILES = 0
1328                 else:
1329                         print "Un-handled option:", opt
1330                         usage()
1331
1332         # Sanity test
1333         if not os.path.exists(TETHEREAL):
1334                 sys.exit("tethereal program '%s' does not exist." % (TETHEREAL,))
1335
1336         if not os.path.exists(TEXT2PCAP):
1337                 sys.exit("text2pcap program '%s' does not exist." % (TEXT2PCAP,))
1338
1339
1340         # Determine which tests to run.
1341         tests_to_run = []
1342         if specific_tests:
1343                 # Go through the tests looking for the ones whose names
1344                 # match the command-line arguments.
1345                 all_ok = 1
1346                 for test_name in specific_tests:
1347                         for test in all_tests:
1348                                 if test_name == test.__class__.__name__:
1349                                         tests_to_run.append(test)
1350                                         break
1351                         else:
1352                                 print >> sys.stderr, "%s is unrecognized as a test." % \
1353                                         (test_name,)
1354                                 all_ok = 0
1355
1356                 if not all_ok:
1357                         sys.exit(1)
1358         else:
1359                 tests_to_run = all_tests
1360
1361         # Run the tests and keep score.
1362         tot_run = 0
1363         tot_succeeded = 0
1364         for test in tests_to_run:
1365                 print test.__class__.__name__
1366                 (run, succeeded) = test.Run()
1367                 tot_run += run
1368                 tot_succeeded += succeeded
1369                 print
1370
1371         print
1372         print "Total Tests Run:", tot_run
1373         print "Total Tests Succeeded:", tot_succeeded
1374         print "Total Tests Failed:", tot_run - tot_succeeded
1375
1376         if tot_succeeded == tot_run:
1377                 sys.exit(0)
1378         else:
1379                 sys.exit(1)
1380
1381 if __name__ == "__main__":
1382         try:
1383                 main()
1384         except KeyboardInterrupt:
1385                 print "\nInterrupted by user."