2015-05-20 18:37:50 +00:00
from mpTcptraceData import *
2015-07-29 12:18:35 +00:00
from subprocess import check_output
2015-05-20 18:37:50 +00:00
2015-05-26 23:28:19 +00:00
import numpy as np
2015-05-20 18:37:50 +00:00
2015-05-27 16:13:31 +00:00
# to get a REPL:
#import code
#code.interact(local=locals())
2015-05-20 18:37:50 +00:00
# A checker runs tests, and a test is made of multiple validations
# For a validation, the value to compare to is the target value from the yaml
# The validation takes place in the validate method, which takes
# as argument a value from which to extract the value to compare or the value itself
class Validation :
def __init__ ( self , yml ) :
2015-05-27 16:13:31 +00:00
if " target " in yml :
self . compared = yml [ " target " ]
else :
self . compared = None
2015-05-20 18:37:50 +00:00
def name ( self ) :
return self . __class__ . __name__
2015-05-20 19:29:48 +00:00
def validate ( self , value ) :
raise Exception ( " Method not implemented " )
2015-05-26 19:19:16 +00:00
def setup ( self ) :
raise Exception ( " Method not implemented " )
2015-05-20 18:37:50 +00:00
# checks a value passed is greater or equal (generic)
class MinValueValidation ( Validation ) :
def validate ( self , value ) :
2015-05-26 19:00:03 +00:00
self . value = value
2015-05-20 18:37:50 +00:00
return self . compared < = value
2015-05-26 16:43:53 +00:00
# checks a value passed is greater or equal (generic)
class MaxValueValidation ( Validation ) :
def validate ( self , value ) :
2015-05-26 19:00:03 +00:00
self . value = value
2015-05-26 16:43:53 +00:00
return self . compared > = value
# checks a value passed is greater or equal (generic)
class ExactValueValidation ( Validation ) :
def validate ( self , value ) :
2015-05-26 19:00:03 +00:00
self . value = value
2015-05-26 16:43:53 +00:00
return self . compared == value
2015-05-20 18:37:50 +00:00
2015-05-26 19:19:16 +00:00
2015-05-27 17:59:35 +00:00
# the method get_tested_value of the tester returns the value passed to validate.
# the CsvTester returns an array of values
class MinDifferenceValidation ( Validation ) :
def validate ( self , value ) :
v = value . flatten ( )
if len ( v ) > 2 :
raise Exception ( " MinDifferenceValidation requires 2 values maximum, not " + str ( len ( v ) ) )
self . value = float ( v [ 1 ] ) - float ( v [ 0 ] )
2015-05-26 19:19:16 +00:00
return self . compared < = self . value
2015-05-27 17:59:35 +00:00
class MinRowsValidation ( Validation ) :
def validate ( self , value ) :
self . value = len ( value )
return self . compared < = self . value
class MaxRowsValidation ( Validation ) :
def validate ( self , value ) :
self . value = len ( value )
return self . compared > = self . value
class ExactRowsValidation ( Validation ) :
def validate ( self , value ) :
self . value = len ( value )
return self . compared == self . value
class MaxRatioValidation ( Validation ) :
def validate ( self , value ) :
v = value . flatten ( )
if len ( v ) > 2 :
raise Exception ( " MinDifferenceValidation requires 2 values maximum, not " + str ( len ( v ) ) )
self . value = float ( v [ 1 ] ) / ( float ( v [ 0 ] ) + float ( v [ 1 ] ) )
2015-05-26 19:19:16 +00:00
return self . compared > = self . value
2015-05-27 16:13:31 +00:00
# validates all values passed have increasing values
# it is the Tester's get_tested_value method that does the work
# to extract the values list from the trace.
2015-05-27 17:59:35 +00:00
class IncreasingValuesValidation ( Validation ) :
2015-05-26 23:28:19 +00:00
def validate ( self , values ) :
previous = 0
2015-05-27 17:59:35 +00:00
for i , v in enumerate ( values . flatten ( ) ) :
2015-05-26 23:28:19 +00:00
#print i, "{:10.6f}".format(previous), "{:10.6f}".format(v)
if v < previous :
2015-05-27 16:13:31 +00:00
self . value = " row " + str ( i ) # index of error row
2015-05-26 23:28:19 +00:00
return False
else :
previous = v
2015-05-27 16:13:31 +00:00
return True
2015-05-26 23:28:19 +00:00
2015-05-26 19:19:16 +00:00
2015-05-27 17:59:35 +00:00
2015-05-26 22:04:15 +00:00
class Tester :
2015-05-26 23:28:19 +00:00
def __init__ ( self , yml , trace ) :
2015-05-27 17:59:35 +00:00
self . yml = yml
2015-05-26 23:28:19 +00:00
self . trace = trace
2015-05-20 18:37:50 +00:00
# performs a validation found in the yml file.
def validate ( self ) :
is_ok = True
self . logs = " "
2015-05-27 17:59:35 +00:00
for val in self . yml [ " validations " ] :
2015-05-20 18:37:50 +00:00
tested_value = self . get_tested_value ( val )
klass_name = val [ " name " ] . title ( ) . replace ( " _ " , " " ) + " Validation "
tester_klass = globals ( ) [ klass_name ]
tester = tester_klass ( val )
2015-05-27 16:13:31 +00:00
if " target " in val :
target = val [ " target " ]
else :
target = None
2015-05-26 17:44:34 +00:00
try :
if tester . validate ( tested_value ) :
2015-05-27 16:13:31 +00:00
self . logs = self . logs + " " + " OK : " + val [ " desc " ] + " - " + tester . name ( ) + " value : " + str ( tester . value ) + ( " " if target == None else " vs target " + str ( val [ " target " ] ) ) + " \n "
2015-05-26 17:44:34 +00:00
else :
2015-05-27 16:13:31 +00:00
self . logs = self . logs + " " + " FAIL: " + val [ " desc " ] + " - " + tester . name ( ) + " value : " + str ( tester . value ) + ( " " if target == None else " vs target " + str ( val [ " target " ] ) ) + " \n "
2015-05-26 17:44:34 +00:00
is_ok = False
except Exception as e :
2015-05-26 19:00:03 +00:00
self . logs = self . logs + ( " " if self . logs == " " else " \n " ) + " EXCP: " + val [ " desc " ] + " - " + tester . name ( ) + " " + str ( e ) + " \n "
2015-05-20 18:37:50 +00:00
return is_ok
def name ( self ) :
return self . __class__ . __name__
2015-05-20 19:29:48 +00:00
def get_tested_value ( self , yml ) :
raise Exception ( " Method not implemented " )
2015-05-20 18:37:50 +00:00
2015-05-26 22:04:15 +00:00
2015-08-03 18:10:28 +00:00
# applies provided filter to Checker's trace, and returns number of lines in output(ie number of packets)
2015-07-29 12:18:35 +00:00
class FilterTest ( Tester ) :
def get_tested_value ( self , yml ) :
if " filter " in self . yml :
ret = check_output ( [ " tshark " , " -r " , self . trace , " -Y " , self . yml [ " filter " ] ] )
2015-08-03 18:10:28 +00:00
# -1 : substract line of sudo error message printed by tshark
2015-07-29 12:18:35 +00:00
return len ( ret . split ( " \n " ) ) - 1
else :
raise Exception ( " Test requires a filter. " )
2015-05-26 22:04:15 +00:00
2015-05-27 17:59:35 +00:00
class CsvTest ( Tester ) :
def get_tested_value ( self , validation ) :
a = self . trace . get_csv ( self . yml [ " csv " ] )
if " rows " in self . yml :
a = a [ self . yml [ " rows " ] ]
if " columns " in self . yml :
a = a [ : , self . yml [ " columns " ] ]
return a
2015-05-26 23:28:19 +00:00
2015-05-26 22:04:15 +00:00
class Checker :
2015-05-20 18:37:50 +00:00
def check ( self ) :
is_ok = True
self . logs = self . test_id + " \n "
2015-06-01 17:19:30 +00:00
if self . yml != None :
for test in self . yml :
name = test [ " test " ] . title ( ) . replace ( " _ " , " " ) + " Test "
klass = globals ( ) [ name ]
r = klass ( test , self . trace )
if r . validate ( ) :
self . logs = self . logs + " * " + self . test_id + " " + r . name ( ) + " SUCCESS \n "
self . logs = self . logs + r . logs
else :
self . logs = self . logs + " * " + self . test_id + " " + r . name ( ) + " FAIL \n "
self . logs = self . logs + r . logs
2015-05-20 18:37:50 +00:00
2015-05-26 22:04:15 +00:00
# Runs tests based on tcptrace
# It (in the method inherited from its parent class) instanciates the ...Test class passing it the TcptraceData instance
class TcptraceChecker ( Checker ) :
def __init__ ( self , yml , test_id , destDir ) :
self . yml = yml [ " tcptrace " ]
self . trace = TcptraceData ( destDir + " /client.pcap " )
self . test_id = test_id
2015-08-03 18:10:28 +00:00
# Runs tests based on the tcpdump trace itself
2015-07-29 12:18:35 +00:00
class TsharkChecker ( Checker ) :
def __init__ ( self , yml , test_id , destDir ) :
self . yml = yml [ " tshark " ]
self . trace = destDir + " /client.pcap "
self . test_id = test_id
2015-05-26 23:28:19 +00:00
from mpMptcptraceData import *
2015-05-26 22:04:15 +00:00
# Runs tests based on mptcptrace
# It (in the method inherited from its parent class) instanciates the ...Test class passing it the MptcptraceData instance
class MptcptraceChecker ( Checker ) :
def __init__ ( self , yml , test_id , destDir ) :
self . yml = yml [ " mptcptrace " ]
self . trace = MptcptraceData ( destDir + " /client.pcap " )
self . test_id = test_id
2015-05-20 18:37:50 +00:00