Skip to content

Commit

Permalink
Optimize mock data rule match (#721)
Browse files Browse the repository at this point in the history
  • Loading branch information
yumiguan authored Dec 9, 2022
1 parent 96ccea2 commit 3e5b9ac
Show file tree
Hide file tree
Showing 2 changed files with 69 additions and 49 deletions.
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

0 comments on commit 3e5b9ac

Please sign in to comment.