Commit 6ef2ee73 authored by Siebers, Michael's avatar Siebers, Michael
Browse files

written explain_explanation_to_json/2 and tests for it

parent 6082eb14
......@@ -474,7 +474,17 @@ test(explain_message_to_json_message_type_referenceid, % reference id no integer
]) :-
web_api:explain_message_to_json([reference("text",OtherTypeValue)],
_ActualJSON).
% explain_message_to_json(Message, JSON) throws uninstantiation_error(JSON)
% if JSON is bound and cannot be unified with result
test(explain_message_to_json_uninstantiaton,
[
forall(member(BoundJSON,[_{un: expected}, tag{text: "some text"}])),
error(uninstantiation_error(BoundJSON))
]) :-
web_api:explain_message_to_json(["some text"], BoundJSON).
%%
%% explain_references_to_json/2
%%
......@@ -622,10 +632,276 @@ test(explain_reference_to_json_message_type_entityproperty, % entity property no
% if JSON is bound and cannot be unified with result
test(explain_reference_to_json_uninstantiaton,
[
forall(member(BoundJSON,[_{un: expected}])),
forall(member(BoundJSON,[[_{un: expected}],
[tag{id: 0,
referenced_entities: [entity{ abs_path: "some_path",
property: "name"
}]
}],
[reference{id: 0,
referenced_entities: [tag{ abs_path: "some_path",
property: "name"
}]
}]
])),
error(uninstantiation_error(BoundJSON))
]) :-
References = [ref(0,[entity("some_path","name")])],
web_api:explain_reference_to_json(References, BoundJSON).
web_api:explain_reference_to_json(References, BoundJSON).
%%
%% explain_explanation_to_json/2
%%
% explain_explanation_to_json(Explanation, JSON) succedes deterministically with
% correct results given valid message input.
test(explain_explanation_to_json_happy,
[ true(ActualJSON = ExpectedJSON) ]) :-
AbsPath = "some_path",
Message = [ "some arbitrary", reference("message",0) ],
Details = [
[ "first", "detailed", "message"],
[ "second message", reference(referencing, 1), "something" ],
[ "some", reference("thing",0) ]
],
References = [ ref(0,[entity("another/path","name")]),
ref(1,[entity("yet/some/other/path", "property")])
],
ExpectedJSON = _{
abs_path: AbsPath,
reasoning: [ _{ text: "some arbitrary"},
_{ ref_id: 0, text: "message"}],
reasoning_details: [
[ _{ text: "first"},
_{ text: "detailed"},
_{ text: "message"}],
[ _{ text: "second message"},
_{ text: "referencing", ref_id: 1},
_{ text: "something"}],
[ _{ text: "some"},
_{ text: "thing", ref_id: 0}]
],
references: [
_{ id: 0,
referenced_entities: [
_{ abs_path: "another/path",
property: "name" }
]},
_{ id: 1,
referenced_entities: [
_{ abs_path: "yet/some/other/path",
property: "property" }
]}
]
},
web_api:explain_explanation_to_json(
explanation(AbsPath,Message,Details,References), ActualJSON).
% explain_explanation_to_json(Explanation, JSON) throws
% instantiation_error if Explanation is unbound.
test(explain_explanation_to_json_instantiation,
[ error(instantiation_error)]) :-
web_api:explain_explanation_to_json(_Explanation, _ActualJSON).
% explain_explanation_to_json(Explanation, JSON) throws
% type_error(explanation(_,_,_,_),Explanation) if Explanation is not of the
% expected type.
test(explain_explanation_to_json_type,
[
forall(member(OtherTypeValue, [1, 7.3, some(binary,term),
["test"],
explanation(one_arg),
explanation(two,args),
explanation(only,three,args),
explanation(way,too,many,arguments,given)])),
error(type_error(explanation(_,_,_,_),OtherTypeValue)) ]) :-
web_api:explain_explanation_to_json(OtherTypeValue, _ActualJSON).
% explain_explanation_to_json(Explanation, JSON) throws
% instantiation_error if the absolute path name of the explanation or the
% list of detail messages is unbound.
test(explain_explanation_to_json_abspath_instantiation,
[ error(instantiation_error) ]) :-
Message = [ "some arbitrary", reference("message",0) ],
Details = [
[ "first", "detailed", "message"],
[ "second message", reference(referencing, 1), "something" ],
[ "some", reference("thing",0) ]
],
References = [ ref(0,[entity("another/path","name")]),
ref(1,[entity("yet/some/other/path", "property")])
],
web_api:explain_explanation_to_json(
explanation(_AbsPath,Message,Details,References), _ActualJSON).
% explain_explanation_to_json(Explanation, JSON) throws
% type_error(text,AbsPath) if the absolute path name of the explanation is
% no text type.
test(explain_explanation_to_json_abspath_type,
[
forall(member(OtherTypeValue, [1, 7.3, some(term), ["test"]])),
error(type_error(text,OtherTypeValue))
]) :-
Message = [ "some arbitrary", reference("message",0) ],
Details = [
[ "first", "detailed", "message"],
[ "second message", reference(referencing, 1), "something" ],
[ "some", reference("thing",0) ]
],
References = [ ref(0,[entity("another/path","name")]),
ref(1,[entity("yet/some/other/path", "property")])
],
web_api:explain_explanation_to_json(
explanation(OtherTypeValue,Message,Details,References), _ActualJSON).
% explain_explanation_to_json(Explanation, JSON) throws
% type_error(list,Details) if the detail messages of the explanation is no list.
test(explain_explanation_to_json_details_type,
[
forall(member(OtherTypeValue, [1, "test", test, 7.3, some(term)])),
error(type_error(list,OtherTypeValue))
]) :-
AbsPath = "some_path",
Message = [ "some arbitrary", reference("message",0) ],
References = [ ref(0,[entity("another/path","name")]),
ref(1,[entity("yet/some/other/path", "property")])
],
web_api:explain_explanation_to_json(
explanation(AbsPath,Message,OtherTypeValue,References), _ActualJSON).
% explain_explanation_to_json(Explanation, JSON) throws
% uninstantiation_error(JSON) if JSON is bound and cannot be unified with result
test(explain_explanation_to_json_bound,
[
forall((BoundJSON = _{un: expected},
BoundJSON = tag{
abs_path: AbsPath,
reasoning: [ _{ text: "some arbitrary"},
_{ ref_id: 0, text: "message"}],
reasoning_details: [
[ _{ text: "first"},
_{ text: "detailed"},
_{ text: "message"}],
[ _{ text: "second message"},
_{ text: "referencing", ref_id: 1},
_{ text: "something"}],
[ _{ text: "some"},
_{ text: "thing", ref_id: 0}]
],
references: [
_{ id: 0,
referenced_entities: [
_{ abs_path: "another/path",
property: "name" }
]},
_{ id: 1,
referenced_entities: [
_{ abs_path: "yet/some/other/path",
property: "property" }
]}
]
}
; BoundJSON = _{
abs_path: AbsPath,
reasoning: [ _{ text: "some arbitrary"},
_{ ref_id: 0, text: "message"}],
references: [
_{ id: 0,
referenced_entities: [
_{ abs_path: "another/path",
property: "name" }
]},
_{ id: 1,
referenced_entities: [
_{ abs_path: "yet/some/other/path",
property: "property" }
]}
]
}
; BoundJSON = _{
abs_path: "another path",
reasoning: [ _{ text: "some arbitrary"},
_{ ref_id: 0, text: "message"}],
reasoning_details: [
[ _{ text: "first"},
_{ text: "detailed"},
_{ text: "message"}],
[ _{ text: "second message"},
_{ text: "referencing", ref_id: 1},
_{ text: "something"}],
[ _{ text: "some"},
_{ text: "thing", ref_id: 0}]
],
references: [
_{ id: 0,
referenced_entities: [
_{ abs_path: "another/path",
property: "name" }
]},
_{ id: 1,
referenced_entities: [
_{ abs_path: "yet/some/other/path",
property: "property" }
]}
]
}
; BoundJSON = _{
abs_path: AbsPath,
reasoning: [ _{ text: "some arbitrary"},
_{ ref_id: 0, text: "message"}],
reasoning_details: [
[ _{ text: "first"},
_{ text: "detailed"},
_{ text: "message"}],
[ _{ text: "second message"},
_{ text: "referencing", ref_id: 1},
_{ text: "something"}],
[ _{ text: "some"},
_{ text: "thing", ref_id: 0}]
],
references: [
_{ id: 0,
referenced_entities: [
_{ abs_path: "another/path",
property: "name" }
]},
_{ id: 1,
referenced_entities: [
some_deeply_hidden_tag{
abs_path: "yet/some/other/path",
property: "property" }
]}
]
})
),
error(uninstantiation_error(BoundJSON)) ]) :-
AbsPath = "some_path",
Message = [ "some arbitrary", reference("message",0) ],
Details = [
[ "first", "detailed", "message"],
[ "second message", reference(referencing, 1), "something" ],
[ "some", reference("thing",0) ]
],
References = [ ref(0,[entity("another/path","name")]),
ref(1,[entity("yet/some/other/path", "property")])
],
web_api:explain_explanation_to_json(
explanation(AbsPath,Message,Details,References), BoundJSON).
% explain_explanation_to_json(explanation(AbsPath,Message,Details,Refs), JSON)
% might throw further errors as documented. However, the documentation states
% that the sub-parts Message, the members of Details, and the references Refs
% are parsed using explain_message_to_json/2, explain_message_to_json/2, and
% explain_reference_to_json/2. As these methods are also thouroughly tested,
% no further tests are required.
test(explain_explanation_to_json_further_errors) :- true.
:- end_tests(web_api_expl_integration).
......@@ -104,30 +104,93 @@ handle_explain(Req) :-
Exceeded = true,
reply_json(json([explanations=AllExplanations,'answers-exceeded'=Exceeded])).
%! explain_explanation_to_json(++Explanation, --JSON) is det
%
% Transforms an explanation to a term suitable to be transformed into a JSON
% string. The sub-transformations of the explanation message and details are
% carried out by explain_message_to_json/2. The references are transformed by
% explain_reference_to_json/2.
%
% @see do_handle_explain/3 for the expected format of Explanation
% @error instantiation_error if Explanation or any part of it is unbound
% @error type_error(Type,Part) if Explanation or any Part of it has not the
% expected type
% @error uninstantiation_error(Part) if (part of) JSON is instantiated and
% cannot be unified with the correct answer.
explain_explanation_to_json(explanation(AbsPath,Message,Details,References),
JSONDict) :-
text_to_string(AbsPath,AbsPathStr),
explain_message_to_json(Message, MessageJSON),
must_be(list,Details),
maplist(explain_message_to_json,Details, DetailsJSON),
explain_reference_to_json(References, ReferencesJSON),
( JSONDict = explanation{
abs_path: AbsPathStr,
reasoning: MessageJSON,
reasoning_details: DetailsJSON,
references: ReferencesJSON
}
-> true
; uninstantiation_error(JSONDict)
), !.
explain_explanation_to_json(Explanation,_JSON) :-
type_error(explanation(_,_,_,_),Explanation).
%! explain_message_to_json(++Message:list, -JSON) is det
/*
explain_reference_to_json_(ref(RefId,ListOfEntities), JSONDict) :-
must_be(integer,RefId),
must_be(list, ListOfEntities),
maplist(explain_entity_to_json, ListOfEntities, JSONEntities),
( JSONDict = reference{id: RefId, referenced_entities: JSONEntities}
-> true
; uninstantiation_error(JSONDict)
),
!.
explain_reference_to_json_(Reference,_JSON) :-
type_error(ref(_,_), Reference).
*/
%! explain_message_to_json(++Message:list, --JSON) is det
%
% Transforms an explanation (detailed) message to a term suitable to be
% transformed into a JSON string.
%
% @see do_handle_explain/3 for the expected format of Message
% @error instantiation_error if Message or any part of it is unbound
% @error type_error(Type,Part) if Message or any Part of it has not the expected type
% @error type_error(Type,Part) if Message or any Part of it has not the expected
% type
% @error uninstantiation_error(Part) if (part of) JSON is instantiated and
% cannot be unified with the correct answer.
explain_message_to_json(Message, JSON) :-
must_be(list, Message),
maplist(explain_message_to_json_, Message, JSON).
maplist(explain_message_to_json_, Message, JSONTrue),
( JSON=JSONTrue
-> true
; uninstantiation_error(JSON)
).
explain_message_to_json_(reference(M,Ref), J) :-
explain_message_to_json_(reference(M,Ref), JSON) :-
text_to_string(M, MStr),
must_be(integer, Ref),
dict_create(J, message, [text=MStr, ref_id=Ref]),
( JSON = J
-> true
; uninstantiation_error(JSON)
),
!.
explain_message_to_json_(M, J) :-
explain_message_to_json_(M, JSON) :-
text_to_string(M, MStr),
dict_create(J, message, [text=MStr]).
dict_create(J, message, [text=MStr]),
( JSON = J
-> true
; uninstantiation_error(JSON)
).
%! explain_reference_to_json(++References:list, -JSON) is det
%! explain_reference_to_json(++References:list, --JSON) is det
%
% Transforms explanation references to a term suitable to be
% transformed into a JSON string.
......
Supports Markdown
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment