moved to a CsvTester doing all tests

This commit is contained in:
Raphael Bauduin 2015-05-27 10:59:35 -07:00
parent cdb954756f
commit 793f51be69
4 changed files with 80 additions and 172 deletions

View File

@ -38,7 +38,7 @@ class MptcptraceData:
# gets cell corresponding to flow with header column # gets cell corresponding to flow with header column
# flow 0 = first one, from 1=subflows # flow 0 = first one, from 1=subflows
def get(self, name): def get_csv(self, name):
if hasattr(self,name): if hasattr(self,name):
return getattr(self,name) return getattr(self,name)
else: else:

View File

@ -6,6 +6,7 @@ import csv
from io import StringIO from io import StringIO
import re import re
import numpy as np
@ -15,43 +16,12 @@ class TcptraceData:
self.pcap_file=pcap_file self.pcap_file=pcap_file
csv_content = check_output(["tcptrace", "-l", "--csv", pcap_file]) csv_content = check_output(["tcptrace", "-l", "--csv", pcap_file])
tcptrace_reader = csv.reader(filter(lambda l: len(l)>0 and l[0]!="#",csv_content.splitlines())) tcptrace_reader = csv.reader(filter(lambda l: len(l)>0 and l[0]!="#",csv_content.splitlines()))
cells=list(tcptrace_reader) cells=np.array(list(tcptrace_reader))
#drop header row
cells= cells[1:]
self.cells = cells
self.headers=cells[0] self.headers=cells[0]
self.flows=cells[1:] self.flows=cells[1:]
self.number_of_flows=len(self.flows) self.number_of_flows=len(self.flows)
# gets cell corresponding to flow with header column def get_csv(self, name):
# flow 0 = first one, from 1=subflows return self.cells
def get(self, flow, column):
if flow>self.number_of_flows-1:
raise Exception("Bad flow index")
value = self.flows[flow][self.headers.index(column)]
if re.search("[a-zA-Z]", value):
return value
elif re.search("\.", value):
return float(value)
elif re.search("^[0-9]+$", value):
return int(value)
else:
return value
# returns first packet time of flow
def first_packet(self, flow):
return float(self.flows[flow][self.header_index("first_packet")])-float(self.flows[0][self.header_index("first_packet")])
# util: get column index based on header name
def header_index(self, column):
return self.headers.index(column)
#t = TcptraceData("client.pcap")
#print t.number_of_flows
#print t.first_packet(1)

View File

@ -47,72 +47,42 @@ class ExactValueValidation(Validation):
self.value = value self.value = value
return self.compared==value return self.compared==value
# individual flow validations (used with FlowsTest)
###################################################
class MinDelayValidation(Validation): # the method get_tested_value of the tester returns the value passed to validate.
# receives flow_spec = (index, flows) where index is the index of the flow to validate, and flows is the array of flows # the CsvTester returns an array of values
def validate(self, flow_spec): class MinDifferenceValidation(Validation):
(yml,trace) = flow_spec def validate(self, value):
index=yml["index"] v = value.flatten()
val = trace.first_packet(index)-trace.first_packet(0) if len(v)>2:
self.value = val raise Exception("MinDifferenceValidation requires 2 values maximum, not "+ str(len(v)))
return self.compared<=val self.value = float(v[1])-float(v[0])
class MinDelayBetweenValidation(Validation):
# gets flow_spec = ( [ index0, index1] , flows) where:
# - index0 is the index of the flow taken as reference for timing
# - index1 is the flow for which we want to validate the timing
# - flows is the array of flows
def validate(self, flow_spec):
(yml ,trace) = flow_spec
[index0, index1] = yml["index"]
val = trace.first_packet(index1)-trace.first_packet(index0)
self.value = val
return self.compared<=val
class AttributeValidation(Validation):
def setup(self, flow_spec):
(yml ,trace) = flow_spec
[index0, index1] = yml["index"]
self.val0 = trace.get(index0, yml["attribute"])
self.val1 = trace.get(index1, yml["attribute"])
class AttributeMinimumDifferenceValidation(AttributeValidation):
def validate(self, flow_spec):
self.setup(flow_spec)
self.value = self.val1 - self.val0
return self.compared<=self.value return self.compared<=self.value
class MinRowsValidation(Validation):
class AttributeMaximumDifferenceValidation(AttributeValidation): def validate(self, value):
def validate(self, flow_spec): self.value = len(value)
self.setup(flow_spec)
self.value = self.val1 - self.val0
return self.compared>=self.value
class AttributeMinimumRatioValidation(AttributeValidation):
def validate(self, flow_spec):
self.setup(flow_spec)
self.value = float(self.val1)/+float(self.val1)
return self.compared<=self.value return self.compared<=self.value
class MaxRowsValidation(Validation):
class AttributeMaximumRatioValidation(AttributeValidation): def validate(self, value):
def validate(self, flow_spec): self.value = len(value)
self.setup(flow_spec) return self.compared>=self.value
self.value = float(self.val1)/float(self.val0) 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]))
return self.compared>=self.value return self.compared>=self.value
# mptcptrace csv validations
############################
# validates all values passed have increasing values # validates all values passed have increasing values
# it is the Tester's get_tested_value method that does the work # it is the Tester's get_tested_value method that does the work
# to extract the values list from the trace. # to extract the values list from the trace.
class IncreasingValueValidation(AttributeValidation): class IncreasingValuesValidation(Validation):
def validate(self, values): def validate(self, values):
previous = 0 previous = 0
for i,v in enumerate(values): for i,v in enumerate(values.flatten()):
#print i, "{:10.6f}".format(previous), "{:10.6f}".format(v) #print i, "{:10.6f}".format(previous), "{:10.6f}".format(v)
if v<previous: if v<previous:
self.value= "row " + str(i) # index of error row self.value= "row " + str(i) # index of error row
@ -122,15 +92,16 @@ class IncreasingValueValidation(AttributeValidation):
return True return True
class Tester: class Tester:
def __init__(self, yml, trace): def __init__(self, yml, trace):
self.yml = yml["validations"] self.yml = yml
self.trace = trace self.trace = trace
# performs a validation found in the yml file. # performs a validation found in the yml file.
def validate(self): def validate(self):
is_ok = True is_ok = True
self.logs = "" self.logs = ""
for val in self.yml: for val in self.yml["validations"]:
tested_value = self.get_tested_value(val) tested_value = self.get_tested_value(val)
klass_name=val["name"].title().replace("_","")+"Validation" klass_name=val["name"].title().replace("_","")+"Validation"
tester_klass=globals()[klass_name] tester_klass=globals()[klass_name]
@ -156,36 +127,15 @@ class Tester:
# Base class testing tcptrace results class CsvTest(Tester):
# the inheriting class should implement get_tested_value(self, yml) def get_tested_value(self, validation):
# the get_tested_value should return the value that all validations of this test will use a = self.trace.get_csv(self.yml["csv"])
# the validations get this value as argument of their validate method if "rows" in self.yml:
# The validate method iterates one the validations mentioned for the test in the yml file. a = a[self.yml["rows"]]
class TcptraceTest(Tester): if "columns" in self.yml:
pass a = a[:,self.yml["columns"]]
return a
# get_tested_value returns the number of flows
class NumberOfFlowsTest(TcptraceTest):
def get_tested_value(self, yml):
return self.trace.number_of_flows
# get_tested_value returns index of the flow to validate, and the list of flows
# index can be a compound value, as in the case of min_delay_between where it is an array of indexes
class FlowsTest(TcptraceTest):
def get_tested_value(self, yml):
return (yml,self.trace)
class MptcptraceTest(Tester):
pass
# get_tested_value returns the number of flows
class ColumnValuesTest(TcptraceTest):
def get_tested_value(self, yml):
a = self.trace.get(yml["csv"])
return a[:,yml["column"]]
class Checker: class Checker:
def check(self): def check(self):

View File

@ -1,56 +1,44 @@
mptcptrace: mptcptrace:
- test: "column_values" - test: "csv"
validations:
- name: "increasing_value"
csv: "c2s_seq_1" csv: "c2s_seq_1"
column: 2 columns: 2
validations:
- name: "increasing_values"
desc: "dummy: check sequence numbers grow" desc: "dummy: check sequence numbers grow"
tcptrace: tcptrace:
- test: "number_of_flows" - test: "csv"
csv: "tcptrace"
rows: [0,1]
columns: [5]
validations: validations:
- name: "min_value" - name: "min_difference"
target: 2 target: 2
desc: "Open minimum 2 flows" desc: "minimum difference of opening time"
- name: "max_value" - test: "csv"
target: 4 csv: "tcptrace"
desc: "Open maximum 4 flows"
- name: "exact_value"
target: 4
desc: "Open exactly 4 flows"
# This tests the flows opened by the connection. See class FlowsTest
- test: "flows"
validations: validations:
# validates time between first packets of the first stream and the stream for which the index is passed. - name: "min_rows"
- name: "min_delay"
index: 1
target: 2 target: 2
desc: "Minimum 2 seconds delay between opening of first and second flow" desc: "minimum number of flows"
# validates time between first packets of streams for which the index is passed. - name: "max_rows"
# index is now a compound value, handled by the validate method of the class MinDelayBetweenValidation target: 5
# first index value is the base flow we compare to desc: "minimum number of flows"
# second index is the flow we want to validate - name: "exact_rows"
- name: "min_delay_between" target: 4
index: desc: "minimum number of flows"
- 1 - test: "csv"
- 2 csv: "tcptrace"
target: 1 rows: [1,2]
desc: "Minimum 1 second delay between opening of second and third flow" columns: [5]
- name: "attribute_minimum_difference" validations:
attribute: "first_packet" - name: "min_difference"
# first index value is the base flow we compare to
# second index is the flow we want to validate
index:
- 0
- 1
target: 2 target: 2
desc: "first packet delay 2nd flow" desc: "minimum difference of opening time between flow 2 and 3"
- name: "attribute_maximum_ratio" - test: "csv"
attribute: "total_packets_a2b" csv: "tcptrace"
# first index value is the base flow we compare to rows: [0,1]
# second index is the flow we want to validate columns: [7]
index: validations:
- 0 - name: "max_ratio"
- 1
# flows[1].packets_a2b/flows[2].packets_a2b < 5%
target: 0.05 target: 0.05
desc: "a->b packet ration flow 2 compard to flow1" desc: "max ration of packet a->b on flow 1 compared to flow 0."