Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

making changes for supporting oid format #459

Merged
merged 3 commits into from
Jan 16, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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
Loading