Skip to content

Commit

Permalink
Merge pull request #10 from amorenoz/ut
Browse files Browse the repository at this point in the history
fix unit_tests
  • Loading branch information
amorenoz authored Jul 29, 2021
2 parents 2a800c4 + 7f994a3 commit e720c91
Show file tree
Hide file tree
Showing 7 changed files with 59 additions and 79 deletions.
3 changes: 0 additions & 3 deletions ovs_dbg/decoders.py
Original file line number Diff line number Diff line change
Expand Up @@ -17,9 +17,6 @@ def decode_default(value):
It tries to convert into an integer value and, if it fails, just
returns the string.
"""
if not value:
return True

try:
ival = int(value, 0)
return ival
Expand Down
117 changes: 50 additions & 67 deletions ovs_dbg/ofparse/filter.py → ovs_dbg/filter.py
Original file line number Diff line number Diff line change
@@ -1,94 +1,77 @@
#!/bin/python3
""" Defines a Flow Filtering syntax
"""
import pyparsing as pp
import netaddr

from ovs_dbg.decoders import decode_default, decode_int, decode_mac, decode_ip
from ovs_dbg.decoders import decode_default
from ovs_dbg.fields import field_decoders


class ClauseExpression:
type_decoders = {
"int": decode_int,
"IPMask": decode_ip,
"IPAddress": decode_ip,
"EthMask": decode_mac,
"EUI": decode_mac,
"bool": bool,
operators = {}
decoders = {
"nw_src": netaddr.IPNetwork,
**field_decoders,
}

def __init__(self, tokens):
self.field = tokens[0]
self.value = ""
self.operator = ""

if len(tokens) > 1:
if len(tokens) <= 1:
self.operator = "="
self.value_raw = True
self.value = True
else:
self.operator = tokens[1]
self.value = tokens[2]
self.value_raw = tokens[2]
self.value = (
self.decoders.get(self.field)(self.value_raw)
if self.decoders.get(self.field)
else decode_default(self.value_raw)
)
if isinstance(self.value, str) and self.value == "true":
self.value = True
elif isinstance(self.value, str) and self.value == "false":
self.value = False

def __repr__(self):
return "{}(field: {}, operator: {}, value: {})".format(
self.__class__.__name__, self.field, self.operator, self.value
self.__class__.__name__, self.field, self.operator, self.value_raw
)

def _find_data_in_kv(self, kv_list):
"""Find a value for evaluation in a list of KeyValue
Args:
kv_list (list[KeyValue]): list of KeyValue to look into
"""
key_parts = self.field.split(".")
field = key_parts[0]
kvs = [kv for kv in kv_list if kv.key == field]
if not kvs:
return None

for kv in kvs:
if kv.key == self.field:
# exact match
return kv.value
elif len(key_parts) > 1:
data = kv.value
for subkey in key_parts[1:]:
try:
data = data.get(subkey)
except Exception:
data = None
break
if not data:
break
if data:
return data

def _find_data(self, flow):
"""Finds the key-value to use for evaluation"""
for section in flow.sections:
data = self._find_data_in_kv(section.data)
if data:
return data
return None

def evaluate(self, flow):
data = self._find_data(flow)
if not data:
return False
data = flow.info.get(self.field) or flow.match.get(self.field)

if not self.value and not self.operator:
# just asserting the existance of the key
return True

# Decode the value based on the type of data
data_type = data.__class__.__name__
decoder = self.type_decoders.get(data_type) or decode_default
decoded_value = decoder(self.value)
if not data:
# search in actions
act_parts = self.field.split(".")
act_name = act_parts[0]
actions = [act for act in flow.actions_kv if act.key == act_name]
if not actions:
return False

# Look into arguments
for action in actions:
if action.key == self.field:
# exact match
data = action.value
break
elif len(act_parts) > 1:
data = action.value
for key in act_parts[1:]:
data = data.get(key)
if not data:
break
if not data:
return False

if self.operator == "=":
return decoded_value == data
return self.value == data
elif self.operator == "<":
return data < decoded_value
return data < self.value
elif self.operator == ">":
return data > decoded_value
return data > self.value
elif self.operator == "~=":
return decoded_value in data
return self.value in data


class BoolNot:
Expand Down
2 changes: 1 addition & 1 deletion ovs_dbg/flow.py
Original file line number Diff line number Diff line change
Expand Up @@ -61,7 +61,7 @@ def __init__(self, sections, orig=""):

def section(self, name):
"""Return the section by name"""
return next((sect for sect in self._sections if sect.name == name))
return next((sect for sect in self._sections if sect.name == name), None)

@property
def sections(self):
Expand Down
2 changes: 1 addition & 1 deletion ovs_dbg/ofparse/main.py
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import click
import sys

from ovs_dbg.ofparse.filter import OFFilter
from ovs_dbg.filter import OFFilter


class Options(dict):
Expand Down
2 changes: 1 addition & 1 deletion tests/test_filter.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import pytest

from ovs_dbg.ofparse.filter import OFFilter
from ovs_dbg.filter import OFFilter
from ovs_dbg.ofp import OFPFlow


Expand Down
8 changes: 4 additions & 4 deletions tests/test_odp.py
Original file line number Diff line number Diff line change
Expand Up @@ -143,8 +143,8 @@ def test_odp_fields(input_string, expected):
assert expected[i].value == match[i].value

# Assert positions relative to action string are OK
mpos = odp.meta.mpos
mstring = odp.meta.mstring
mpos = odp.section("match").pos
mstring = odp.section("match").string

kpos = match[i].meta.kpos
kstr = match[i].meta.kstring
Expand Down Expand Up @@ -526,8 +526,8 @@ def test_odp_actions(input_string, expected):
assert expected[i].value == actions[i].value

# Assert positions relative to action string are OK
apos = odp.meta.apos
astring = odp.meta.astring
apos = odp.section("actions").pos
astring= odp.section("actions").string

kpos = actions[i].meta.kpos
kstr = actions[i].meta.kstring
Expand Down
4 changes: 2 additions & 2 deletions tests/test_ofp.py
Original file line number Diff line number Diff line change
Expand Up @@ -360,8 +360,8 @@ def test_act(input_string, expected):
assert expected[i].value == actions[i].value

# Assert positions relative to action string are OK
apos = ofp.meta.apos
astring = ofp.meta.astring
apos = ofp.section("actions").pos
astring = ofp.section("actions").string

kpos = actions[i].meta.kpos
kstr = actions[i].meta.kstring
Expand Down

0 comments on commit e720c91

Please sign in to comment.