Skip to content

Commit

Permalink
add support for random UDF for x-field-pattern fields (#467)
Browse files Browse the repository at this point in the history
* add support for random UDF for x-field-pattern fields

* adding description and correcting default for min

* modifying descriptions and correcting count and seed value

* changing description of seed

* fix typo

* refactoring x-field-uid code to follow features sequence for ordering of properties

* Update version

* addressing review comments

* fix lint
  • Loading branch information
Vibaswan authored Jul 23, 2024
1 parent 72c3196 commit 93cd89c
Show file tree
Hide file tree
Showing 8 changed files with 606 additions and 204 deletions.
6 changes: 4 additions & 2 deletions MODELGUIDE.md
Original file line number Diff line number Diff line change
Expand Up @@ -224,7 +224,7 @@ Flow.Ipv4:
x-field-pattern:
format: ipv4
default: 0.0.0.0
count: false
features: [count, random]
```
### Sample property after bundle
```yaml
Expand All @@ -240,7 +240,7 @@ Pattern.Flow.Ipv4.Address:
properties:
choice:
type: string
enum: [value, values, increment, decrement]
enum: [value, values, increment, decrement, random]
value:
type: string
format: ipv4
Expand All @@ -255,6 +255,8 @@ Pattern.Flow.Ipv4.Address:
$ref: '#/components/schemas/Pattern.Flow.Ipv4.Address.Counter'
decrement:
$ref: '#/components/schemas/Pattern.Flow.Ipv4.Address.Counter'
random:
$ref: '#/components/schemas/Pattern.Flow.Ipv4.Address.Random'
```
### Sample instantiation
```yaml
Expand Down
499 changes: 305 additions & 194 deletions openapiart/bundler.py

Large diffs are not rendered by default.

3 changes: 3 additions & 0 deletions openapiart/tests/config/config.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -332,6 +332,9 @@ components:
type: string
format: ipv4
x-field-uid: 60
ipv6_pattern_without_default:
$ref: "../pattern/pattern.yaml#/components/schemas/Ipv6PatternWithoutDefault"
x-field-uid: 61

WObject:
required: [w_name]
Expand Down
21 changes: 15 additions & 6 deletions openapiart/tests/pattern/pattern.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ components:
x-field-pattern:
format: ipv4
default: 0.0.0.0
features: [count]
features: [count, random]
x-field-uid: 1
Ipv6Pattern:
description: Test ipv6 pattern
Expand All @@ -18,7 +18,16 @@ components:
x-field-pattern:
format: ipv6
default: "::"
features: [count]
features: [count, random]
x-field-uid: 1
Ipv6PatternWithoutDefault:
description: Test ipv6 pattern
type: object
properties:
ipv6:
x-field-pattern:
format: ipv6
features: [count, random]
x-field-uid: 1
MacPattern:
description: Test mac pattern
Expand All @@ -28,7 +37,7 @@ components:
x-field-pattern:
format: mac
default: "00:00:00:00:00:00"
features: [count, auto]
features: [count, auto, random]
x-field-uid: 1
IntegerPattern:
description: Test integer pattern
Expand All @@ -39,7 +48,7 @@ components:
format: integer
default: 0
length: 8
features: [count]
features: [count, random]
x-field-uid: 1
ChecksumPattern:
description: Test checksum pattern
Expand Down Expand Up @@ -78,7 +87,7 @@ components:
x-field-pattern:
format: ipv4
default: "0.0.0.0"
features: [count, auto]
features: [auto, count]
auto:
$ref: "../config/config.yaml#/components/schemas/AutoIpOptions"
default: false
Expand All @@ -92,7 +101,7 @@ components:
x-field-pattern:
format: ipv4
default: "0.0.0.0"
features: [count, auto]
features: [auto, count]
auto:
$ref: "../config/config.yaml#/components/schemas/AutoIpDefault"
default: true
Expand Down
226 changes: 226 additions & 0 deletions openapiart/tests/test_random_pattern.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,226 @@
import importlib
import pytest

module = importlib.import_module("sanity")


def test_random_pattern_integer_format(default_config):
pat = default_config.integer_pattern.integer
val = pat._TYPES.get("value")
assert val.get("format") == "uint32"
rnd = pat.random

assert rnd._TYPES.get("min").get("format") == "uint32"
assert rnd._TYPES.get("min").get("type") == int
assert rnd._TYPES.get("min").get("maximum") == 255
assert rnd._DEFAULTS.get("min") == 0

assert rnd._TYPES.get("max").get("format") == "uint32"
assert rnd._TYPES.get("max").get("type") == int
assert rnd._TYPES.get("max").get("maximum") == 255
assert rnd._DEFAULTS.get("max") == 255

assert rnd._TYPES.get("count").get("format") == "uint32"
assert rnd._TYPES.get("count").get("type") == int
assert rnd._DEFAULTS.get("count") == 1

assert rnd._TYPES.get("seed").get("format") == "uint32"
assert rnd._TYPES.get("seed").get("type") == int
assert rnd._DEFAULTS.get("seed") == 1

data = default_config.serialize("dict")
intp = data["integer_pattern"]["integer"]
assert intp["choice"] == "random"
pat = intp["random"]
assert pat["count"] == 1
assert pat["max"] == 255
assert pat["min"] == 0
assert pat["seed"] == 1

config = module.Api().prefix_config()
config.deserialize(data)
intp = config.integer_pattern.integer
assert intp.choice == "random"
pat = intp.random
assert pat.count == 1
assert pat.seed == 1
assert pat.max == 255
assert pat.min == 0


def test_random_pattern_ipv4_format(default_config):
pat = default_config.ipv4_pattern.ipv4
val = pat._TYPES.get("value")
assert val.get("type") == str
rnd = pat.random

assert rnd._TYPES.get("min").get("type") == str
assert rnd._TYPES.get("min").get("format") == "ipv4"
assert rnd._DEFAULTS.get("min") == "0.0.0.0"

assert rnd._TYPES.get("max").get("format") == "ipv4"
assert rnd._TYPES.get("max").get("type") == str
assert rnd._DEFAULTS.get("max") == "255.255.255.255"

assert rnd._TYPES.get("count").get("format") == "uint32"
assert rnd._TYPES.get("count").get("type") == int
assert rnd._DEFAULTS.get("count") == 1

assert rnd._TYPES.get("seed").get("format") == "uint32"
assert rnd._TYPES.get("seed").get("type") == int
assert rnd._DEFAULTS.get("seed") == 1

data = default_config.serialize("dict")
intp = data["ipv4_pattern"]["ipv4"]
assert intp["choice"] == "random"
pat = intp["random"]
assert pat["count"] == 1
assert pat["max"] == "255.255.255.255"
assert pat["min"] == "0.0.0.0"
assert pat["seed"] == 1

config = module.Api().prefix_config()
config.deserialize(data)
intp = config.ipv4_pattern.ipv4
assert intp.choice == "random"
pat = intp.random
assert pat.count == 1
assert pat.seed == 1
assert pat.max == "255.255.255.255"
assert pat.min == "0.0.0.0"


def test_random_pattern_ipv6_format(default_config):
pat = default_config.ipv6_pattern.ipv6
val = pat._TYPES.get("value")
assert val.get("type") == str
rnd = pat.random

assert rnd._TYPES.get("min").get("type") == str
assert rnd._TYPES.get("min").get("format") == "ipv6"
assert rnd._DEFAULTS.get("min") == "::"

assert rnd._TYPES.get("max").get("format") == "ipv6"
assert rnd._TYPES.get("max").get("type") == str
assert (
rnd._DEFAULTS.get("max") == "ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff"
)

assert rnd._TYPES.get("count").get("format") == "uint32"
assert rnd._TYPES.get("count").get("type") == int
assert rnd._DEFAULTS.get("count") == 1

assert rnd._TYPES.get("seed").get("format") == "uint32"
assert rnd._TYPES.get("seed").get("type") == int
assert rnd._DEFAULTS.get("seed") == 1

data = default_config.serialize("dict")
intp = data["ipv6_pattern"]["ipv6"]
assert intp["choice"] == "random"
pat = intp["random"]
assert pat["count"] == 1
assert pat["max"] == "ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff"
assert pat["min"] == "::"
assert pat["seed"] == 1

config = module.Api().prefix_config()
config.deserialize(data)
intp = config.ipv6_pattern.ipv6
assert intp.choice == "random"
pat = intp.random
assert pat.count == 1
assert pat.seed == 1
assert pat.max == "ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff"
assert pat.min == "::"


def test_random_pattern_ipv6_format_without_default(default_config):
pat = default_config.ipv6_pattern_without_default.ipv6
val = pat._TYPES.get("value")
assert val.get("type") == str
rnd = pat.random

assert rnd._TYPES.get("min").get("type") == str
assert rnd._TYPES.get("min").get("format") == "ipv6"
assert rnd._DEFAULTS.get("min") is None

assert rnd._TYPES.get("max").get("format") == "ipv6"
assert rnd._TYPES.get("max").get("type") == str
assert (
rnd._DEFAULTS.get("max") == "ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff"
)

assert rnd._TYPES.get("count").get("format") == "uint32"
assert rnd._TYPES.get("count").get("type") == int
assert rnd._DEFAULTS.get("count") == 1

assert rnd._TYPES.get("seed").get("format") == "uint32"
assert rnd._TYPES.get("seed").get("type") == int
assert rnd._DEFAULTS.get("seed") == 1

data = default_config.serialize("dict")
intp = data["ipv6_pattern_without_default"]["ipv6"]
assert intp["choice"] == "random"
pat = intp["random"]
assert pat["count"] == 1
assert pat["max"] == "ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff"
assert pat["seed"] == 1

config = module.Api().prefix_config()
config.deserialize(data)
intp = config.ipv6_pattern_without_default.ipv6
assert intp.choice == "random"
pat = intp.random
assert pat.count == 1
assert pat.seed == 1
assert pat.max == "ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff"
assert pat.min is None


def test_random_pattern_mac_format(default_config):
pat = default_config.mac_pattern.mac
val = pat._TYPES.get("value")
assert val.get("type") == str
rnd = pat.random

assert rnd._TYPES.get("min").get("type") == str
assert rnd._TYPES.get("min").get("format") == "mac"
assert rnd._DEFAULTS.get("min") == "00:00:00:00:00:00"

assert rnd._TYPES.get("max").get("format") == "mac"
assert rnd._TYPES.get("max").get("type") == str
assert rnd._DEFAULTS.get("max") == "ff:ff:ff:ff:ff:ff"

assert rnd._TYPES.get("count").get("format") == "uint32"
assert rnd._TYPES.get("count").get("type") == int
assert rnd._DEFAULTS.get("count") == 1

assert rnd._TYPES.get("seed").get("format") == "uint32"
assert rnd._TYPES.get("seed").get("type") == int
assert rnd._DEFAULTS.get("seed") == 1

data = default_config.serialize("dict")
intp = data["mac_pattern"]["mac"]
assert intp["choice"] == "random"
pat = intp["random"]
assert pat["count"] == 1
assert pat["max"] == "ff:ff:ff:ff:ff:ff"
assert pat["min"] == "00:00:00:00:00:00"
assert pat["seed"] == 1

config = module.Api().prefix_config()
config.deserialize(data)
intp = config.mac_pattern.mac
assert intp.choice == "random"
pat = intp.random
assert pat.count == 1
assert pat.seed == 1
assert pat.max == "ff:ff:ff:ff:ff:ff"
assert pat.min == "00:00:00:00:00:00"


def test_random_should_not_be_populated_in_unknown_places(default_config):
at = default_config.auto_pattern.auto_ip
assert at._TYPES.get("random", None) is None
at = default_config.auto_pattern_default.auto_ip_default
assert at._TYPES.get("random", None) is None
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 @@ -28,7 +28,7 @@ def test_validate_pattern():
"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",
"components.schemas.Config.properties.wrong_features_value.x-field-pattern has unspported feature abc , valid features are ['count', 'auto', 'metric_tags']",
"components.schemas.Config.properties.wrong_features_value.x-field-pattern has unspported feature abc , valid features are ['count', 'auto', 'metric_tags', 'random']",
"ref is a mandatory property in Pattern.Config.WrongAutoValue, when auto property is specified",
"default is a mandatory property in Pattern.Config.WrongAutoValue, when auto property is specified",
"only boolean values are allowed for default in Pattern.Config.WrongAutoDefaultValue",
Expand Down
51 changes: 51 additions & 0 deletions pkg/unit1_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -26,3 +26,54 @@ func TestToAndFromProtoMsg(t *testing.T) {
assert.Equal(t, fObj_proto.GetFA(), "")

}

func TestRandomPatternForAllFormat(t *testing.T) {
config := openapiart.NewPrefixConfig()
config.SetA("asdf").SetB(12.2).SetC(1).SetH(true).SetI([]byte{1, 0, 0, 1, 0, 0, 1, 1})
config.RequiredObject().SetEA(1).SetEB(2)
config.SetIeee8021Qbb(true)
config.SetFullDuplex100Mb(2)
config.SetResponse(openapiart.PrefixConfigResponse.STATUS_200)
config.E().SetEA(1.1).SetEB(1.2).SetMParam1("Mparam1").SetMParam2("Mparam2")
config.IntegerPattern().Integer().Random()
config.Ipv4Pattern().Ipv4().Random()
config.Ipv6Pattern().Ipv6().Random()
config.MacPattern().Mac().Random()

json, err := config.Marshal().ToJson()
assert.Nil(t, err)

config2 := openapiart.NewPrefixConfig()
err = config2.Unmarshal().FromJson(json)
assert.Nil(t, err)

pat1 := config2.IntegerPattern().Integer().Random()
assert.Equal(t, pat1.Min(), uint32(0))
assert.Equal(t, pat1.Max(), uint32(255))
assert.Equal(t, pat1.Count(), uint32(1))
assert.Equal(t, pat1.Seed(), uint32(1))

pat2 := config2.Ipv4Pattern().Ipv4().Random()
assert.Equal(t, pat2.Min(), "0.0.0.0")
assert.Equal(t, pat2.Max(), "255.255.255.255")
assert.Equal(t, pat2.Count(), uint32(1))
assert.Equal(t, pat2.Seed(), uint32(1))

pat3 := config2.Ipv6Pattern().Ipv6().Random()
assert.Equal(t, pat3.Min(), "::")
assert.Equal(t, pat3.Max(), "ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff")
assert.Equal(t, pat3.Count(), uint32(1))
assert.Equal(t, pat3.Seed(), uint32(1))

pat4 := config2.MacPattern().Mac().Random()
assert.Equal(t, pat4.Min(), "00:00:00:00:00:00")
assert.Equal(t, pat4.Max(), "ff:ff:ff:ff:ff:ff")
assert.Equal(t, pat4.Count(), uint32(1))
assert.Equal(t, pat4.Seed(), uint32(1))

pat5 := config2.Ipv6PatternWithoutDefault().Ipv6().Random()
assert.Equal(t, pat5.HasMin(), false)
assert.Equal(t, pat5.Max(), "ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff")
assert.Equal(t, pat5.Count(), uint32(1))
assert.Equal(t, pat5.Seed(), uint32(1))
}
2 changes: 1 addition & 1 deletion setup.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
import setuptools

pkg_name = "openapiart"
version = "0.3.14"
version = "0.3.15"

base_dir = os.path.dirname(os.path.abspath(__file__))
with open(os.path.join(base_dir, "readme.md")) as fid:
Expand Down

0 comments on commit 93cd89c

Please sign in to comment.