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
|
# 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:
|
||||||
|
@ -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)
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
@ -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):
|
||||||
|
@ -1,56 +1,44 @@
|
|||||||
mptcptrace:
|
mptcptrace:
|
||||||
- test: "column_values"
|
- test: "csv"
|
||||||
|
csv: "c2s_seq_1"
|
||||||
|
columns: 2
|
||||||
validations:
|
validations:
|
||||||
- name: "increasing_value"
|
- name: "increasing_values"
|
||||||
csv: "c2s_seq_1"
|
|
||||||
column: 2
|
|
||||||
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."
|
||||||
|
Loading…
Reference in New Issue
Block a user