moved to a CsvTester doing all tests
This commit is contained in:
parent
cdb954756f
commit
793f51be69
@ -38,7 +38,7 @@ class MptcptraceData:
|
||||
|
||||
# gets cell corresponding to flow with header column
|
||||
# flow 0 = first one, from 1=subflows
|
||||
def get(self, name):
|
||||
def get_csv(self, name):
|
||||
if hasattr(self,name):
|
||||
return getattr(self,name)
|
||||
else:
|
||||
|
@ -6,6 +6,7 @@ import csv
|
||||
|
||||
from io import StringIO
|
||||
import re
|
||||
import numpy as np
|
||||
|
||||
|
||||
|
||||
@ -15,43 +16,12 @@ class TcptraceData:
|
||||
self.pcap_file=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()))
|
||||
cells=list(tcptrace_reader)
|
||||
cells=np.array(list(tcptrace_reader))
|
||||
#drop header row
|
||||
cells= cells[1:]
|
||||
self.cells = cells
|
||||
self.headers=cells[0]
|
||||
self.flows=cells[1:]
|
||||
self.number_of_flows=len(self.flows)
|
||||
# gets cell corresponding to flow with header column
|
||||
# flow 0 = first one, from 1=subflows
|
||||
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)
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
def get_csv(self, name):
|
||||
return self.cells
|
||||
|
@ -47,72 +47,42 @@ class ExactValueValidation(Validation):
|
||||
self.value = value
|
||||
return self.compared==value
|
||||
|
||||
# individual flow validations (used with FlowsTest)
|
||||
###################################################
|
||||
|
||||
class MinDelayValidation(Validation):
|
||||
# receives flow_spec = (index, flows) where index is the index of the flow to validate, and flows is the array of flows
|
||||
def validate(self, flow_spec):
|
||||
(yml,trace) = flow_spec
|
||||
index=yml["index"]
|
||||
val = trace.first_packet(index)-trace.first_packet(0)
|
||||
self.value = val
|
||||
return self.compared<=val
|
||||
|
||||
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
|
||||
# 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])
|
||||
return self.compared<=self.value
|
||||
|
||||
class AttributeMaximumDifferenceValidation(AttributeValidation):
|
||||
def validate(self, flow_spec):
|
||||
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)
|
||||
class MinRowsValidation(Validation):
|
||||
def validate(self, value):
|
||||
self.value = len(value)
|
||||
return self.compared<=self.value
|
||||
|
||||
class AttributeMaximumRatioValidation(AttributeValidation):
|
||||
def validate(self, flow_spec):
|
||||
self.setup(flow_spec)
|
||||
self.value = float(self.val1)/float(self.val0)
|
||||
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]))
|
||||
return self.compared>=self.value
|
||||
|
||||
# mptcptrace csv validations
|
||||
############################
|
||||
|
||||
# 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.
|
||||
class IncreasingValueValidation(AttributeValidation):
|
||||
class IncreasingValuesValidation(Validation):
|
||||
def validate(self, values):
|
||||
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)
|
||||
if v<previous:
|
||||
self.value= "row " + str(i) # index of error row
|
||||
@ -122,15 +92,16 @@ class IncreasingValueValidation(AttributeValidation):
|
||||
return True
|
||||
|
||||
|
||||
|
||||
class Tester:
|
||||
def __init__(self, yml, trace):
|
||||
self.yml = yml["validations"]
|
||||
self.yml = yml
|
||||
self.trace = trace
|
||||
# performs a validation found in the yml file.
|
||||
def validate(self):
|
||||
is_ok = True
|
||||
self.logs = ""
|
||||
for val in self.yml:
|
||||
for val in self.yml["validations"]:
|
||||
tested_value = self.get_tested_value(val)
|
||||
klass_name=val["name"].title().replace("_","")+"Validation"
|
||||
tester_klass=globals()[klass_name]
|
||||
@ -156,36 +127,15 @@ class Tester:
|
||||
|
||||
|
||||
|
||||
# Base class testing tcptrace results
|
||||
# the inheriting class should implement get_tested_value(self, yml)
|
||||
# the get_tested_value should return the value that all validations of this test will use
|
||||
# the validations get this value as argument of their validate method
|
||||
# The validate method iterates one the validations mentioned for the test in the yml file.
|
||||
class TcptraceTest(Tester):
|
||||
pass
|
||||
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
|
||||
|
||||
# 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:
|
||||
def check(self):
|
||||
|
@ -1,56 +1,44 @@
|
||||
mptcptrace:
|
||||
- test: "column_values"
|
||||
- test: "csv"
|
||||
csv: "c2s_seq_1"
|
||||
columns: 2
|
||||
validations:
|
||||
- name: "increasing_value"
|
||||
csv: "c2s_seq_1"
|
||||
column: 2
|
||||
- name: "increasing_values"
|
||||
desc: "dummy: check sequence numbers grow"
|
||||
tcptrace:
|
||||
- test: "number_of_flows"
|
||||
- test: "csv"
|
||||
csv: "tcptrace"
|
||||
rows: [0,1]
|
||||
columns: [5]
|
||||
validations:
|
||||
- name: "min_value"
|
||||
- name: "min_difference"
|
||||
target: 2
|
||||
desc: "Open minimum 2 flows"
|
||||
- name: "max_value"
|
||||
target: 4
|
||||
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"
|
||||
desc: "minimum difference of opening time"
|
||||
- test: "csv"
|
||||
csv: "tcptrace"
|
||||
validations:
|
||||
# validates time between first packets of the first stream and the stream for which the index is passed.
|
||||
- name: "min_delay"
|
||||
index: 1
|
||||
- name: "min_rows"
|
||||
target: 2
|
||||
desc: "Minimum 2 seconds delay between opening of first and second flow"
|
||||
# validates time between first packets of streams for which the index is passed.
|
||||
# index is now a compound value, handled by the validate method of the class MinDelayBetweenValidation
|
||||
# first index value is the base flow we compare to
|
||||
# second index is the flow we want to validate
|
||||
- name: "min_delay_between"
|
||||
index:
|
||||
- 1
|
||||
- 2
|
||||
target: 1
|
||||
desc: "Minimum 1 second delay between opening of second and third flow"
|
||||
- name: "attribute_minimum_difference"
|
||||
attribute: "first_packet"
|
||||
# first index value is the base flow we compare to
|
||||
# second index is the flow we want to validate
|
||||
index:
|
||||
- 0
|
||||
- 1
|
||||
desc: "minimum number of flows"
|
||||
- name: "max_rows"
|
||||
target: 5
|
||||
desc: "minimum number of flows"
|
||||
- name: "exact_rows"
|
||||
target: 4
|
||||
desc: "minimum number of flows"
|
||||
- test: "csv"
|
||||
csv: "tcptrace"
|
||||
rows: [1,2]
|
||||
columns: [5]
|
||||
validations:
|
||||
- name: "min_difference"
|
||||
target: 2
|
||||
desc: "first packet delay 2nd flow"
|
||||
- name: "attribute_maximum_ratio"
|
||||
attribute: "total_packets_a2b"
|
||||
# first index value is the base flow we compare to
|
||||
# second index is the flow we want to validate
|
||||
index:
|
||||
- 0
|
||||
- 1
|
||||
# flows[1].packets_a2b/flows[2].packets_a2b < 5%
|
||||
desc: "minimum difference of opening time between flow 2 and 3"
|
||||
- test: "csv"
|
||||
csv: "tcptrace"
|
||||
rows: [0,1]
|
||||
columns: [7]
|
||||
validations:
|
||||
- name: "max_ratio"
|
||||
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."
|
||||
|
Loading…
Reference in New Issue
Block a user