Skip to content

Commit

Permalink
Merge pull request #441 from dodona-edu/feature/yaml-merge
Browse files Browse the repository at this point in the history
Enable definitions blocks in DSL for YAML anchor/alias/merge
  • Loading branch information
niknetniko authored Sep 22, 2023
2 parents 5e3508c + 0600e88 commit 432153e
Show file tree
Hide file tree
Showing 4 changed files with 58 additions and 117 deletions.
44 changes: 11 additions & 33 deletions tested/dsl/schema.json
Original file line number Diff line number Diff line change
Expand Up @@ -40,10 +40,6 @@
"type" : "object",
"unevaluatedProperties" : false,
"properties" : {
"config" : {
"$ref" : "#/$defs/globalConfig",
"description" : "Configuration applicable to the whole test suite."
},
"files" : {
"type" : "array",
"items" : {
Expand Down Expand Up @@ -71,6 +67,10 @@
}
],
"default" : "tested"
},
"definitions": {
"description": "Define hashes to use elsewhere.",
"type": "object"
}
},
"oneOf" : [
Expand All @@ -90,10 +90,6 @@
"type" : "object",
"unevaluatedProperties" : false,
"properties" : {
"config" : {
"$ref" : "#/$defs/globalConfig",
"description" : "Configuration applicable to this unit/tab"
},
"files" : {
"type" : "array",
"items" : {
Expand Down Expand Up @@ -123,6 +119,10 @@
},
"testcases" : {
"$ref" : "#/$defs/_scriptList"
},
"definitions": {
"description": "Define hashes to use elsewhere.",
"type": "object"
}
},
"oneOf" : [
Expand Down Expand Up @@ -166,10 +166,6 @@
"type" : "object",
"unevaluatedProperties" : false,
"properties" : {
"config" : {
"$ref" : "#/$defs/globalConfig",
"description" : "Configuration settings at context level"
},
"files" : {
"type" : "array",
"items" : {
Expand Down Expand Up @@ -280,10 +276,6 @@
"description" : "Expected output at stdout",
"$ref" : "#/$defs/textOutputChannel"
},
"config" : {
"$ref" : "#/$defs/globalConfig",
"description" : "Configuration settings at testcase level"
},
"exit_code" : {
"type" : "integer",
"description" : "Expected exit code for the run"
Expand Down Expand Up @@ -339,9 +331,6 @@
"integer",
"boolean"
]
},
"config" : {
"$ref" : "#/$defs/textConfigurationOptions"
}
},
"oneOf" : [
Expand All @@ -352,6 +341,9 @@
"enum" : [
"builtin"
]
},
"config" : {
"$ref" : "#/$defs/textConfigurationOptions"
}
}
},
Expand Down Expand Up @@ -494,20 +486,6 @@
}
}
},
"globalConfig" : {
"type" : "object",
"description" : "Global configuration properties",
"minProperties" : 1,
"unevaluatedProperties" : false,
"properties" : {
"stdout" : {
"$ref" : "#/$defs/textConfigurationOptions"
},
"stderr" : {
"$ref" : "#/$defs/textConfigurationOptions"
}
}
},
"file" : {
"type" : "object",
"description" : "Path to a file for input.",
Expand Down
43 changes: 11 additions & 32 deletions tested/dsl/schema_draft7.json
Original file line number Diff line number Diff line change
Expand Up @@ -39,10 +39,6 @@
"_rootObject" : {
"type" : "object",
"properties" : {
"config" : {
"$ref" : "#/definitions/globalConfig",
"description" : "Configuration applicable to the whole test suite."
},
"files" : {
"type" : "array",
"items" : {
Expand Down Expand Up @@ -70,6 +66,10 @@
}
],
"default" : "tested"
},
"definitions": {
"description": "Define hashes to use elsewhere.",
"type": "object"
}
},
"oneOf" : [
Expand All @@ -88,10 +88,6 @@
"unit" : {
"type" : "object",
"properties" : {
"config" : {
"$ref" : "#/definitions/globalConfig",
"description" : "Configuration applicable to this unit/tab"
},
"files" : {
"type" : "array",
"items" : {
Expand Down Expand Up @@ -121,6 +117,10 @@
},
"testcases" : {
"$ref" : "#/definitions/_scriptList"
},
"definitions": {
"description": "Define hashes to use elsewhere.",
"type": "object"
}
},
"oneOf" : [
Expand Down Expand Up @@ -163,10 +163,6 @@
"testcase" : {
"type" : "object",
"properties" : {
"config" : {
"$ref" : "#/definitions/globalConfig",
"description" : "Configuration settings at context level"
},
"files" : {
"type" : "array",
"items" : {
Expand Down Expand Up @@ -276,10 +272,6 @@
"description" : "Expected output at stdout",
"$ref" : "#/definitions/textOutputChannel"
},
"config" : {
"$ref" : "#/definitions/globalConfig",
"description" : "Configuration settings at testcase level"
},
"exitCode" : {
"type" : "integer",
"description" : "Expected exit code for the run"
Expand Down Expand Up @@ -334,9 +326,6 @@
"integer",
"boolean"
]
},
"config" : {
"$ref" : "#/definitions/textConfigurationOptions"
}
},
"oneOf" : [
Expand All @@ -347,6 +336,9 @@
"enum" : [
"builtin"
]
},
"config" : {
"$ref" : "#/definitions/textConfigurationOptions"
}
}
},
Expand Down Expand Up @@ -487,19 +479,6 @@
}
}
},
"globalConfig" : {
"type" : "object",
"description" : "Global configuration properties",
"minProperties" : 1,
"properties" : {
"stdout" : {
"$ref" : "#/definitions/textConfigurationOptions"
},
"stderr" : {
"$ref" : "#/definitions/textConfigurationOptions"
}
}
},
"file" : {
"type" : "object",
"description" : "Path to a file for input.",
Expand Down
45 changes: 10 additions & 35 deletions tested/dsl/translate_parser.py
Original file line number Diff line number Diff line change
Expand Up @@ -60,7 +60,7 @@
TextOutputChannel,
ValueOutputChannel,
)
from tested.utils import get_args, recursive_dict_merge
from tested.utils import get_args

OptionDict = dict[str, int | bool]
YamlDict = dict[str, "YamlObject"]
Expand Down Expand Up @@ -136,48 +136,28 @@ class DslContext:
Carries context in each level.
"""

config: dict
files: list[FileUrl]
language: SupportedLanguage | Literal["tested"] = "tested"

def deepen_context(
self,
new_level: YamlDict | None,
include_config=True,
include_files=True,
merge_with: str | None = None,
) -> "DslContext":
def deepen_context(self, new_level: YamlDict | None) -> "DslContext":
"""
Merge certain fields of the new object with the current context, resulting
in a new context for the new level.
:param new_level: The new object from the DSL to get information from.
:param include_config: If config should be considered.
:param include_files: If files should be considered.
:param merge_with: If merging configs, the key of the subsection to update.
:return: A new context.
"""
if new_level is None:
return self

new_config = self.config
if include_config and "config" in new_level:
assert isinstance(new_level["config"], dict)
if merge_with:
original_config = self.config.get(merge_with, {})
else:
original_config = self.config

new_config = recursive_dict_merge(original_config, new_level["config"])

new_files = self.files
if include_files and "files" in new_level:
if "files" in new_level:
assert isinstance(new_level["files"], list)
additional_files = {_convert_file(f) for f in new_level["files"]}
new_files = list(set(self.files) | additional_files)

return evolve(self, config=new_config, files=new_files)
return evolve(self, files=new_files)


def convert_validation_error_to_group(
Expand Down Expand Up @@ -317,20 +297,15 @@ def _convert_custom_check_oracle(stream: dict) -> CustomCheckOracle:
)


def _convert_text_output_channel(
stream: YamlObject, context: DslContext, config_name: str
) -> TextOutputChannel:
def _convert_text_output_channel(stream: YamlObject) -> TextOutputChannel:
if isinstance(stream, str):
data = stream
config = context.config.get(config_name, {})
return TextOutputChannel(data=data, oracle=GenericTextOracle(options=config))
return TextOutputChannel(data=data, oracle=GenericTextOracle())
else:
assert isinstance(stream, dict)
data = str(stream["data"])
if "oracle" not in stream or stream["oracle"] == "builtin":
config = context.deepen_context(
stream, include_files=False, merge_with=config_name
).config
config = cast(dict, stream.get("config", {}))
return TextOutputChannel(
data=data, oracle=GenericTextOracle(options=config)
)
Expand Down Expand Up @@ -430,9 +405,9 @@ def _convert_testcase(testcase: YamlDict, context: DslContext) -> Testcase:
output.result = return_channel

if (stdout := testcase.get("stdout")) is not None:
output.stdout = _convert_text_output_channel(stdout, context, "stdout")
output.stdout = _convert_text_output_channel(stdout)
if (stderr := testcase.get("stderr")) is not None:
output.stderr = _convert_text_output_channel(stderr, context, "stderr")
output.stderr = _convert_text_output_channel(stderr)
if (exception := testcase.get("exception")) is not None:
if isinstance(exception, str):
message = exception
Expand Down Expand Up @@ -525,7 +500,7 @@ def _convert_dsl(dsl_object: YamlObject) -> Suite:
:param dsl_object: A validated DSL test suite object.
:return: A full test suite.
"""
context = DslContext(config={}, files=[])
context = DslContext(files=[])
if isinstance(dsl_object, list):
namespace = None
tab_list = dsl_object
Expand Down
Loading

0 comments on commit 432153e

Please sign in to comment.