Skip to content

Commit

Permalink
making changes for supporting oid format (#459)
Browse files Browse the repository at this point in the history
* making changes for supporting oid format

* updating mopdels guide

* fixing an error related to choice with no properties in python
  • Loading branch information
Vibaswan authored Jan 16, 2024
1 parent 8d1a2e8 commit a4e7964
Show file tree
Hide file tree
Showing 13 changed files with 309 additions and 9 deletions.
2 changes: 2 additions & 0 deletions MODELGUIDE.md
Original file line number Diff line number Diff line change
Expand Up @@ -173,6 +173,7 @@ x-field-pattern:
- ipv6
- integer
- checksum
- oid
length:
description: >-
The length of integer values in bits.
Expand Down Expand Up @@ -287,6 +288,7 @@ x-field-pattern:
- ipv6
- integer
- enum
- oid
length:
description: >-
The length of integer values in bits.
Expand Down
6 changes: 3 additions & 3 deletions openapiart/bundler.py
Original file line number Diff line number Diff line change
Expand Up @@ -618,7 +618,7 @@ def _length_restriction(self, value):
if (
len(intersect_keys) > 0
and "format" in value.keys()
and value["format"] in ["ipv4", "ipv6", "mac"]
and value["format"] in ["ipv4", "ipv6", "mac", "oid"]
):
stacks = inspect.stack()
property = "{}/{}/{}".format(
Expand Down Expand Up @@ -696,7 +696,7 @@ def _validate_x_field_pattern(self, xpattern_path):
str(xpattern["signed"]), str(xpattern_path.full_path)
)
)
valid_formats = ["integer", "ipv4", "ipv6", "mac", "checksum"]
valid_formats = ["integer", "ipv4", "ipv6", "mac", "checksum", "oid"]
if xpattern["format"] not in valid_formats:
self._errors.append(
"%s has unspported format %s , valid formats are %s"
Expand Down Expand Up @@ -746,7 +746,7 @@ def _resolve_x_field_pattern(self):
)
fmt = None
type_name = xpattern["format"]
if type_name in ["ipv4", "ipv6", "mac", "x-enum"]:
if type_name in ["ipv4", "ipv6", "mac", "x-enum", "oid"]:
fmt = type_name
type_name = "string"
description = "TBD"
Expand Down
21 changes: 21 additions & 0 deletions openapiart/common.go
Original file line number Diff line number Diff line change
Expand Up @@ -330,6 +330,21 @@ func (obj *validation) validateHex(hex string) error {
return nil
}

func (obj *validation) validateOid(oid string) error {
segments := strings.Split(oid, ".")
if len(segments) < 2 {
return fmt.Errorf(fmt.Sprintf("Invalid oid value %s", oid))
}

for _, segment := range segments {
number, err := strconv.Atoi(segment)
if err != nil || 0 > number || number > 4294967295 {
return fmt.Errorf(fmt.Sprintf("Invalid oid value %s", oid))
}
}
return nil
}

func (obj *validation) validateSlice(valSlice []string, sliceType string) error {
indices := []string{}
var err error
Expand All @@ -343,6 +358,8 @@ func (obj *validation) validateSlice(valSlice []string, sliceType string) error
err = obj.validateIpv6(val)
} else if sliceType == "hex" {
err = obj.validateHex(val)
} else if sliceType == "oid" {
err = obj.validateOid(val)
} else {
return fmt.Errorf(fmt.Sprintf("Invalid slice type received <%s>", sliceType))
}
Expand Down Expand Up @@ -375,6 +392,10 @@ func (obj *validation) validateHexSlice(hex []string) error {
return obj.validateSlice(hex, "hex")
}

func (obj *validation) validateOidSlice(oid []string) error {
return obj.validateSlice(oid, "oid")
}

// TODO: restore behavior
// func (obj *validation) createMap(objName string) {
// if obj.constraints == nil {
Expand Down
22 changes: 18 additions & 4 deletions openapiart/common.py
Original file line number Diff line number Diff line change
Expand Up @@ -487,6 +487,17 @@ def validate_binary(self, value):
]
)

def validate_oid(self, value):
segments = value.split(".")
if len(segments) < 2:
return False
for segment in segments:
if not segment.isnumeric():
return False
if not (0 <= int(segment) <= 4294967295):
return False
return True

def types_validation(
self,
value,
Expand Down Expand Up @@ -698,10 +709,13 @@ def _get_property(
"_DEFAULTS" in dir(self._properties[name])
and "choice" in self._properties[name]._DEFAULTS
):
getattr(
self._properties[name],
self._properties[name]._DEFAULTS["choice"],
)
choice_str = self._properties[name]._DEFAULTS["choice"]

if choice_str in self._properties[name]._TYPES:
getattr(
self._properties[name],
self._properties[name]._DEFAULTS["choice"],
)
else:
if default_value is None and name in self._DEFAULTS:
self._set_choice(name)
Expand Down
3 changes: 2 additions & 1 deletion openapiart/openapiartgo.py
Original file line number Diff line number Diff line change
Expand Up @@ -2702,7 +2702,8 @@ def _validate_types(self, new, field):
"ipv4",
"ipv6",
"hex",
] or field.format in ["mac", "ipv4", "ipv6", "hex"]:
"oid",
] or field.format in ["mac", "ipv4", "ipv6", "hex", "oid"]:
if field.format is None:
field.format = field.itemformat
inner_body = """
Expand Down
10 changes: 10 additions & 0 deletions openapiart/tests/config/config.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -310,6 +310,12 @@ components:
signed_integer_pattern:
$ref: "../pattern/pattern.yaml#/components/schemas/SignedIntegerPattern"
x-field-uid: 53
oid_pattern:
$ref: "../pattern/pattern.yaml#/components/schemas/OidPattern"
x-field-uid: 54
choice_default:
$ref: "#/components/schemas/ChoiceObject"
x-field-uid: 55

WObject:
required: [w_name]
Expand Down Expand Up @@ -565,6 +571,10 @@ components:
type: string
format: hex
x-field-uid: 8
oid:
type: string
format: oid
x-field-uid: 9
Mandate:
description: "Object to Test required Parameter"
type: object
Expand Down
9 changes: 9 additions & 0 deletions openapiart/tests/pattern/pattern.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -61,3 +61,12 @@ components:
length: 8
features: [count]
x-field-uid: 1
OidPattern:
description: Test oid pattern
type: object
properties:
oid:
x-field-pattern:
format: oid
default: "0.1"
x-field-uid: 1
28 changes: 28 additions & 0 deletions openapiart/tests/test_choice_with_no_property.py
Original file line number Diff line number Diff line change
Expand Up @@ -90,6 +90,34 @@ def test_choice_in_choice_heirarchy(api):
assert c_obj.f_obj.choice == "f_c"


def test_choice_in_choice_default(api):
config = api.prefix_config()

# default choice with no properties should be set properly
c_obj = config.choice_default
assert c_obj.choice == "no_obj"
assert len(c_obj._properties) == 1

# acesing of objects with choice set to choice with no property should work
f_obj = c_obj.f_obj

# check default in child
assert f_obj.choice == "f_a"
assert f_obj._properties.get("f_a", None) is not None

# setting choice with no properties in child as well
f_obj.choice = "f_c"
assert f_obj._properties.get("choice", None) == "f_c"
len(f_obj._properties) == 1

# serialize and deserialize should have no problem
s_c_obj = c_obj.serialize()
c_obj.deserialize(s_c_obj)
assert c_obj.choice == "f_obj"
assert c_obj._properties.get("f_obj") is not None
assert c_obj.f_obj.choice == "f_c"


def test_choice_with_invalid_enum_and_none_value(api):
config = api.prefix_config()
f_obj = config.f
Expand Down
111 changes: 111 additions & 0 deletions openapiart/tests/test_oid_format.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,111 @@
import importlib
import pytest

module = importlib.import_module("sanity")


def test_oid_in_normal_attr(default_config):
default_config.m_object.string_param = "abc"
default_config.m_object.integer = 44
default_config.m_object.float = 1.23
default_config.m_object.double = 3.45
default_config.m_object.mac = "00:00:00:00:00:00"
default_config.m_object.ipv4 = "1.2.3.4"
default_config.m_object.ipv6 = "::"
default_config.m_object.hex = "0f"
default_config.m_object.oid = "."

with pytest.raises(Exception) as execinfo:
default_config.serialize("dict")
error_value = execinfo.value.args[0]
assert "Invalid . format, expected oid" in error_value

default_config.m_object.oid = "1."
with pytest.raises(Exception) as execinfo:
default_config.serialize("dict")
error_value = execinfo.value.args[0]
assert "Invalid 1. format, expected oid" in error_value

default_config.m_object.oid = "0.42949672967.22.44.55"
with pytest.raises(Exception) as execinfo:
default_config.serialize("dict")
error_value = execinfo.value.args[0]
assert "Invalid 0.42949672967.22.44.55 format, expected oid" in error_value

default_config.m_object.oid = "1.2.abcd"
with pytest.raises(Exception) as execinfo:
default_config.serialize("dict")
error_value = execinfo.value.args[0]
assert "Invalid 1.2.abcd format, expected oid" in error_value

default_config.m_object.oid = "1.2.3.4.5"
data = default_config.serialize("dict")

data["m_object"]["oid"] = "."
with pytest.raises(Exception) as execinfo:
default_config.deserialize(data)
error_value = execinfo.value.args[0]
assert "Invalid . format, expected oid" in error_value

data["m_object"]["oid"] = "1."
with pytest.raises(Exception) as execinfo:
default_config.deserialize(data)
error_value = execinfo.value.args[0]
assert "Invalid 1. format, expected oid" in error_value

data["m_object"]["oid"] = "0.42949672967.22.44.55"
with pytest.raises(Exception) as execinfo:
default_config.deserialize(data)
error_value = execinfo.value.args[0]
assert "Invalid 0.42949672967.22.44.55 format, expected oid" in error_value

data["m_object"]["oid"] = "1.2.3.4"
default_config.deserialize(data)


def test_oid_x_field_pattern(default_config):
default_config.oid_pattern.oid.value = "1."

with pytest.raises(Exception) as execinfo:
default_config.serialize("dict")
error_value = execinfo.value.args[0]
assert "Invalid 1. format, expected oid" in error_value

default_config.oid_pattern.oid.value = "1.2.3.4"
data = default_config.serialize("dict")

data["oid_pattern"]["oid"]["value"] = "1."
with pytest.raises(Exception) as execinfo:
default_config.deserialize(data)
error_value = execinfo.value.args[0]
assert "Invalid 1. format, expected oid" in error_value

default_config.oid_pattern.oid.values = [
"0.42949672967.22.44.55",
"1.2.3.4.5",
"0.",
".",
"44.55555.77777",
]
with pytest.raises(Exception) as execinfo:
default_config.serialize("dict")
error_value = execinfo.value.args[0]
assert "['0.42949672967.22.44.55', '0.', '.'] are not valid" in error_value

default_config.oid_pattern.oid.values = ["1.2.3.4.5", "66.789.6789.56789"]
data = default_config.serialize("dict")

data["oid_pattern"]["oid"]["values"] = [
"0.42949672967.22.44.55",
"1.2.3.4.5",
"0.",
".",
"44.55555.77777",
]
with pytest.raises(Exception) as execinfo:
default_config.deserialize(data)
error_value = execinfo.value.args[0]
assert "['0.42949672967.22.44.55', '0.', '.'] are not valid" in error_value

data["oid_pattern"]["oid"]["values"] = ["1.2.3.4.5", "66.789.6789.56789"]
default_config.deserialize(data)
2 changes: 1 addition & 1 deletion openapiart/tests/test_validate_x_field_pattern.py
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ def str_compare(validte_str, entire_str):
def test_validate_pattern():
error_msgs = [
"components.schemas.Config.properties.integer.x-field-pattern property using x-field-pattern with format integer must contain length property",
"components.schemas.Config.properties.wrong.x-field-pattern has unspported format random , valid formats are ['integer', 'ipv4', 'ipv6', 'mac', 'checksum']",
"components.schemas.Config.properties.wrong.x-field-pattern has unspported format random , valid formats are ['integer', 'ipv4', 'ipv6', 'mac', 'checksum', 'oid']",
"components.schemas.Config.properties.int_128.x-field-pattern property using x-field-pattern with format integer cannot have length greater than 64",
"signed property can only be used if the format is set to integer in property components.schemas.Config.properties.signed_value_without_int.x-field-pattern",
"invalid value 45 in components.schemas.Config.properties.wrong_int_signed_value.x-field-pattern, signed property can either be true or false",
Expand Down
29 changes: 29 additions & 0 deletions pkg/choice_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -94,3 +94,32 @@ func TestChoiceWithNoPropertiesForChoiceHeirarchy(t *testing.T) {
_, err = choiceObj.Marshal().ToYaml()
assert.Nil(t, err)
}

func TestChoiceWithNoPropertiesForChoiceDefault(t *testing.T) {
config := openapiart.NewPrefixConfig()

choiceObj := config.ChoiceObject().Add()

// check default should be no_obj
assert.Equal(t, choiceObj.Choice(), openapiart.ChoiceObjectChoice.NO_OBJ)
_, err := choiceObj.Marshal().ToYaml()
assert.Nil(t, err)

fObj := choiceObj.FObj()

// check default for child obj
assert.Equal(t, choiceObj.Choice(), openapiart.ChoiceObjectChoice.F_OBJ)
assert.Equal(t, fObj.Choice(), openapiart.FObjectChoice.F_A)
assert.True(t, fObj.HasFA())
assert.Equal(t, fObj.FA(), "some string")

// set choice with no properties in child obj
fObj.FC()
assert.Equal(t, fObj.Choice(), openapiart.FObjectChoice.F_C)
assert.False(t, fObj.HasFA())
assert.False(t, fObj.HasFB())

// validate the whole object
_, err = choiceObj.Marshal().ToYaml()
assert.Nil(t, err)
}
21 changes: 21 additions & 0 deletions pkg/common.go
Original file line number Diff line number Diff line change
Expand Up @@ -331,6 +331,21 @@ func (obj *validation) validateHex(hex string) error {
return nil
}

func (obj *validation) validateOid(oid string) error {
segments := strings.Split(oid, ".")
if len(segments) < 2 {
return fmt.Errorf(fmt.Sprintf("Invalid oid value %s", oid))
}

for _, segment := range segments {
number, err := strconv.Atoi(segment)
if err != nil || 0 > number || number > 4294967295 {
return fmt.Errorf(fmt.Sprintf("Invalid oid value %s", oid))
}
}
return nil
}

func (obj *validation) validateSlice(valSlice []string, sliceType string) error {
indices := []string{}
var err error
Expand All @@ -344,6 +359,8 @@ func (obj *validation) validateSlice(valSlice []string, sliceType string) error
err = obj.validateIpv6(val)
} else if sliceType == "hex" {
err = obj.validateHex(val)
} else if sliceType == "oid" {
err = obj.validateOid(val)
} else {
return fmt.Errorf(fmt.Sprintf("Invalid slice type received <%s>", sliceType))
}
Expand Down Expand Up @@ -376,6 +393,10 @@ func (obj *validation) validateHexSlice(hex []string) error {
return obj.validateSlice(hex, "hex")
}

func (obj *validation) validateOidSlice(oid []string) error {
return obj.validateSlice(oid, "oid")
}

// TODO: restore behavior
// func (obj *validation) createMap(objName string) {
// if obj.constraints == nil {
Expand Down
Loading

0 comments on commit a4e7964

Please sign in to comment.