config_tools: check XML file structures on load

This patch validates the structure of the XML files given before they are
further used by the rest of the configurator. With this validation process,
the configurator confirms the XML files are well-structured and can thus
access certain nodes and contents without checking their existence or data
types.

Upon validation failure, an alert will pop up informing the user that the
given XML file is ill-formed. No further details are given as of now
because we assume users should not care about the internal structure of
those files.

Tracked-On: #6691
Signed-off-by: Junjie Mao <junjie.mao@intel.com>
This commit is contained in:
Junjie Mao
2022-05-18 13:44:13 +08:00
committed by acrnsi-robot
parent 54ff64acc1
commit 22a47fe795
10 changed files with 201 additions and 23 deletions

View File

@@ -50,7 +50,7 @@ class PipelineEngine:
all_uses = consumes.union(uses)
if not all_uses.issubset(self.available_data):
raise Exception(f"Data {uses - self.available_data} need by stage {stage.__class__.__name__} but not provided by the pipeline")
raise Exception(f"Data {all_uses - self.available_data} need by stage {stage.__class__.__name__} but not provided by the pipeline")
self.stages.append(stage)
self.available_data = self.available_data.difference(consumes).union(provides)

View File

@@ -71,7 +71,7 @@ class ScenarioValidator:
def __init__(self, schema_etree, datachecks_etree):
"""Initialize the validator with preprocessed schemas in ElementTree."""
self.schema = xmlschema.XMLSchema11(schema_etree)
self.datachecks = xmlschema.XMLSchema11(datachecks_etree)
self.datachecks = xmlschema.XMLSchema11(datachecks_etree) if datachecks_etree else None
def check_syntax(self, scenario_etree):
errors = []
@@ -88,14 +88,15 @@ class ScenarioValidator:
def check_semantics(self, board_etree, scenario_etree):
errors = []
unified_node = copy(scenario_etree.getroot())
parent_map = {c : p for p in unified_node.iter() for c in p}
unified_node.extend(board_etree.getroot())
it = self.datachecks.iter_errors(unified_node)
for error in it:
e = self.format_error(unified_node, parent_map, error)
e.log()
errors.append(e)
if self.datachecks:
unified_node = copy(scenario_etree.getroot())
parent_map = {c : p for p in unified_node.iter() for c in p}
unified_node.extend(board_etree.getroot())
it = self.datachecks.iter_errors(unified_node)
for error in it:
e = self.format_error(unified_node, parent_map, error)
e.log()
errors.append(e)
return errors
@@ -190,11 +191,14 @@ class ValidatorConstructionByFileStage(PipelineStage):
obj.set("validator", validator)
class SyntacticValidationStage(PipelineStage):
uses = {"validator", "scenario_etree"}
provides = {"syntactic_errors"}
def __init__(self, etree_tag = "scenario"):
self.etree_tag = f"{etree_tag}_etree"
self.uses = {"validator", self.etree_tag}
def run(self, obj):
errors = obj.get("validator").check_syntax(obj.get("scenario_etree"))
errors = obj.get("validator").check_syntax(obj.get(self.etree_tag))
obj.set("syntactic_errors", errors)
class SemanticValidationStage(PipelineStage):