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

v2.11.0 feature/optimize-mock-data-rule-match #721

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
3 changes: 1 addition & 2 deletions lyrebird/manager.py
Original file line number Diff line number Diff line change
Expand Up @@ -228,8 +228,7 @@ def run(args: argparse.Namespace):
application.start_mock_server()

# auto open web browser
if not args.no_browser:
application.NO_BROSWER = args.no_browser
application.NO_BROSWER = args.no_browser

# main process is ready, publish system event
application.status_ready()
Expand Down
115 changes: 68 additions & 47 deletions lyrebird/mock/dm/match.py
Original file line number Diff line number Diff line change
@@ -1,47 +1,76 @@
from jsonschema import validate
from lyrebird import utils
from lyrebird.mock.dm.jsonpath import jsonpath


class MatchRules:
MATCH_SCHEMA = {
"type": "object",
"patternProperties": {
".": {
"anyOf": [
{"type": "string"},
{"type": "number"},
{"type": "boolean"},
{"type": "null"},
]
}
def validate_match(rules):
'''
{ 'request.url': 'pathA/pathB' }

Empty is allowed
'''
if not isinstance(rules, dict):
return False
for value in rules.values():
if not (isinstance(value, (str, int, float, bool)) or value is None):
return False
return True

BOOL_KEY = set(['must', 'must_not'])

def validate_exists(rules):
'''
[ "request.url", "request.data.name" ]

Empty is allowed
'''
if not isinstance(rules, list):
return False
for value in rules:
if not isinstance(value, str):
return False
return True

def validate_query(rules):
'''
{
"match": { ... },
"exists": [ ... ]
}
}

EXISTS_SCHEMA = {
"type": "array",
"items": {
"type": "string"
Empty is allowed
'''
if not isinstance(rules, dict):
return False
if set(rules.keys()) - set(MatchRules.QUERY_FUNC_MAP.keys()):
return False

for query_key, query_rule in rules.items():
if query_key == 'match':
if not MatchRules.validate_match(query_rule):
return False
elif query_key == 'exists':
if not MatchRules.validate_exists(query_rule):
return False
return True

def validate_bool(rules):
'''
{
"must": { ... },
"must_not": { ... }
}
}
'''
if not isinstance(rules, dict):
return False
if set(rules.keys()) - set(MatchRules.BOOL_FUNC_MAP.keys()):
return False

BOOL_SCHEMA = {
"type": "object",
"properties": {
"match": MATCH_SCHEMA,
"exists": EXISTS_SCHEMA
},
"additionalProperties": False
}
for search in rules.values():
if not MatchRules.validate_query(search):
return False

RULES_V2_SCHEMA = {
"type": "object",
"properties": {
"must": BOOL_SCHEMA,
"must_not": BOOL_SCHEMA,
},
"additionalProperties": False
}
return True

@staticmethod
def match(flow, rules):
Expand Down Expand Up @@ -76,29 +105,21 @@ def match(flow, rules):
if not isinstance(rules, dict):
return False

if MatchRules.is_rule_v1(rules):
return MatchRules._is_match_rule_v1(flow, rules)

if MatchRules.is_rule_v2(rules):
return MatchRules._is_match_rule_v2(flow, rules)

elif MatchRules.is_rule_v1(rules):
return MatchRules._is_match_rule_v1(flow, rules)

return False

@staticmethod
def is_rule_v1(rules):
try:
validate(instance=rules, schema=MatchRules.MATCH_SCHEMA)
return True
except Exception:
return False
return MatchRules.validate_match(rules)

@staticmethod
def is_rule_v2(rules):
try:
validate(instance=rules, schema=MatchRules.RULES_V2_SCHEMA)
return True
except Exception:
return False
return MatchRules.validate_bool(rules)

@staticmethod
def _is_match_rule_v1(flow, rules):
Expand Down