206 lines
5.4 KiB
Python
206 lines
5.4 KiB
Python
import uuid
|
|
|
|
import pytest
|
|
from pydantic import ValidationError
|
|
|
|
from control_backend.schemas.program import (
|
|
BasicNorm,
|
|
ConditionalNorm,
|
|
Goal,
|
|
InferredBelief,
|
|
KeywordBelief,
|
|
LogicalOperator,
|
|
Phase,
|
|
Plan,
|
|
Program,
|
|
SemanticBelief,
|
|
Trigger,
|
|
)
|
|
|
|
|
|
def base_norm() -> BasicNorm:
|
|
return BasicNorm(
|
|
id=uuid.uuid4(),
|
|
name="testNormName",
|
|
norm="testNormNorm",
|
|
critical=False,
|
|
)
|
|
|
|
|
|
def base_goal() -> Goal:
|
|
return Goal(
|
|
id=uuid.uuid4(),
|
|
name="testGoalName",
|
|
description="This description can be used to determine whether the goal has been achieved.",
|
|
plan=Plan(
|
|
id=uuid.uuid4(),
|
|
name="testGoalPlanName",
|
|
steps=[],
|
|
),
|
|
can_fail=False,
|
|
)
|
|
|
|
|
|
def base_trigger() -> Trigger:
|
|
return Trigger(
|
|
id=uuid.uuid4(),
|
|
name="testTriggerName",
|
|
condition=KeywordBelief(
|
|
id=uuid.uuid4(),
|
|
name="testTriggerKeywordBeliefTriggerName",
|
|
keyword="Keyword",
|
|
),
|
|
plan=Plan(
|
|
id=uuid.uuid4(),
|
|
name="testTriggerPlanName",
|
|
steps=[],
|
|
),
|
|
)
|
|
|
|
|
|
def base_phase() -> Phase:
|
|
return Phase(
|
|
id=uuid.uuid4(),
|
|
norms=[base_norm()],
|
|
goals=[base_goal()],
|
|
triggers=[base_trigger()],
|
|
)
|
|
|
|
|
|
def base_program() -> Program:
|
|
return Program(phases=[base_phase()])
|
|
|
|
|
|
def invalid_program() -> dict:
|
|
# wrong types inside phases list (not Phase objects)
|
|
return {
|
|
"phases": [
|
|
{"id": uuid.uuid4()}, # incomplete
|
|
{"not_a_phase": True},
|
|
]
|
|
}
|
|
|
|
|
|
def test_valid_program():
|
|
program = base_program()
|
|
validated = Program.model_validate(program)
|
|
assert isinstance(validated, Program)
|
|
assert validated.phases[0].norms[0].norm == "testNormNorm"
|
|
|
|
|
|
def test_valid_deepprogram():
|
|
program = base_program()
|
|
validated = Program.model_validate(program)
|
|
# validate nested components directly
|
|
phase = validated.phases[0]
|
|
assert isinstance(phase.goals[0], Goal)
|
|
assert isinstance(phase.triggers[0], Trigger)
|
|
assert isinstance(phase.norms[0], BasicNorm)
|
|
|
|
|
|
def test_invalid_program():
|
|
bad = invalid_program()
|
|
with pytest.raises(ValidationError):
|
|
Program.model_validate(bad)
|
|
|
|
|
|
def test_conditional_norm_parsing():
|
|
"""
|
|
Check that pydantic is able to preserve the type of the norm, that it doesn't lose its
|
|
"condition" field when serializing and deserializing.
|
|
"""
|
|
norm = ConditionalNorm(
|
|
name="testNormName",
|
|
id=uuid.uuid4(),
|
|
norm="testNormNorm",
|
|
critical=False,
|
|
condition=KeywordBelief(
|
|
name="testKeywordBelief",
|
|
id=uuid.uuid4(),
|
|
keyword="testKeywordBelief",
|
|
),
|
|
)
|
|
program = Program(
|
|
phases=[
|
|
Phase(
|
|
name="Some phase",
|
|
id=uuid.uuid4(),
|
|
norms=[norm],
|
|
goals=[],
|
|
triggers=[],
|
|
),
|
|
],
|
|
)
|
|
|
|
parsed_program = Program.model_validate_json(program.model_dump_json())
|
|
parsed_norm = parsed_program.phases[0].norms[0]
|
|
|
|
assert hasattr(parsed_norm, "condition")
|
|
assert isinstance(parsed_norm, ConditionalNorm)
|
|
|
|
|
|
def test_belief_type_parsing():
|
|
"""
|
|
Check that pydantic is able to discern between the different types of beliefs when serializing
|
|
and deserializing.
|
|
"""
|
|
keyword_belief = KeywordBelief(
|
|
name="testKeywordBelief",
|
|
id=uuid.uuid4(),
|
|
keyword="something",
|
|
)
|
|
semantic_belief = SemanticBelief(
|
|
name="testSemanticBelief",
|
|
id=uuid.uuid4(),
|
|
description="something",
|
|
)
|
|
inferred_belief = InferredBelief(
|
|
name="testInferredBelief",
|
|
id=uuid.uuid4(),
|
|
operator=LogicalOperator.OR,
|
|
left=keyword_belief,
|
|
right=semantic_belief,
|
|
)
|
|
|
|
program = Program(
|
|
phases=[
|
|
Phase(
|
|
name="Some phase",
|
|
id=uuid.uuid4(),
|
|
norms=[],
|
|
goals=[],
|
|
triggers=[
|
|
Trigger(
|
|
name="testTriggerKeywordTrigger",
|
|
id=uuid.uuid4(),
|
|
condition=keyword_belief,
|
|
plan=Plan(name="testTriggerPlanName", id=uuid.uuid4(), steps=[]),
|
|
),
|
|
Trigger(
|
|
name="testTriggerSemanticTrigger",
|
|
id=uuid.uuid4(),
|
|
condition=semantic_belief,
|
|
plan=Plan(name="testTriggerPlanName", id=uuid.uuid4(), steps=[]),
|
|
),
|
|
Trigger(
|
|
name="testTriggerInferredTrigger",
|
|
id=uuid.uuid4(),
|
|
condition=inferred_belief,
|
|
plan=Plan(name="testTriggerPlanName", id=uuid.uuid4(), steps=[]),
|
|
),
|
|
],
|
|
),
|
|
],
|
|
)
|
|
|
|
parsed_program = Program.model_validate_json(program.model_dump_json())
|
|
|
|
parsed_keyword_belief = parsed_program.phases[0].triggers[0].condition
|
|
assert isinstance(parsed_keyword_belief, KeywordBelief)
|
|
|
|
parsed_semantic_belief = parsed_program.phases[0].triggers[1].condition
|
|
assert isinstance(parsed_semantic_belief, SemanticBelief)
|
|
|
|
parsed_inferred_belief = parsed_program.phases[0].triggers[2].condition
|
|
assert isinstance(parsed_inferred_belief, InferredBelief)
|