Skip to content
GitLab
Menu
Projects
Groups
Snippets
Help
Help
Support
Community forum
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in
Toggle navigation
Menu
Open sidebar
cogsys
Dare2Del
Demonstrator - Reasoning WebAPI
Commits
9d79deba
Commit
9d79deba
authored
Nov 12, 2020
by
Siebers, Michael
Browse files
added get_dict_typed/4 for getting and type checking dict values
parent
035b9839
Changes
3
Hide whitespace changes
Inline
Side-by-side
tests/web_api.plt
View file @
9d79deba
:-
use_module
(web_api)
.
/*************************************
*
*
*
Helpers
generating
correct
values
*
*
*
*************************************
/
%! type_is(?Type, -Value) is nondet
% Generates several Value's of type Type, If Type is unbound it is sequentially bound to
% the types atom, integer, string, chars, codes, text, and dict.
type_is
(atom, Value)
:-
member
(Value, [a, some_atom, 'an atom with spaces'])
.
type_is
(integer, Value)
:-
member
(Value, [-100, 0, 1, 5, 1000000000])
.
type_is
(string, Value)
:-
member
(Value, ["some", "random strings", ""])
.
type_is
(chars, Value)
:-
type_is
(atom, ValueAtom)
,
atom_chars
(ValueAtom, Value)
.
type_is
(chars, Value)
:-
type_is
(string, ValueStr)
,
string_chars
(ValueStr, Value)
.
type_is
(codes, Value)
:-
type_is
(atom, ValueAtom)
,
atom_codes
(ValueAtom, Value)
.
type_is
(codes, Value)
:-
type_is
(string, ValueStr)
,
string_codes
(ValueStr, Value)
.
type_is
(text, Value)
:-
type_is
(atom, Value)
;
type_is
(string, Value)
;
type_is
(codes, Value)
;
type_is
(chars, Value)
.
type_is
(dict, Value)
:-
between
(0,2,N)
,
type_is
(dict, N, Value)
.
type_is
(X, Value)
:-
X==dict_value,
!,
(type_is(atom, Value)
; type_is(integer, Value)
)
.
type_is
(dict, 0, _{})
.
type_is
(dict, 0, _{key: Value})
:-
type_is
(dict_value, Value)
.
type_is
(dict, 0, _{key1: Value1, key2: Value2})
:-
type_is
(dict_value, Value1)
,
type_is
(dict_value, Value2)
.
type_is
(dict, 1, _{key: Value})
:-
findall
(V, type_is(dict, 0, V), Vs)
,
length
(Vs, NVs)
,
randset
(3, NVs, ValueIndices)
,
member
(Pos, ValueIndices)
,
nth1
(Pos, Vs, Value)
.
type_is
(dict, 1, _{key1: Value1, key2: Value2})
:-
findall
(V, type_is(dict, 0, V), Vs)
,
length
(Vs, NVs)
,
randset
(3, NVs, ValueIndices1)
,
member
(Pos1, ValueIndices1)
,
nth1
(Pos1, Vs, Value1)
,
randset
(3, NVs, ValueIndices2)
,
member
(Pos2, ValueIndices2)
,
nth1
(Pos2, Vs, Value2)
.
type_is
(dict, 2, _{key: Value})
:-
findall
(V, type_is(dict, 1, V), Vs)
,
length
(Vs, NVs)
,
randset
(3, NVs, ValueIndices)
,
member
(Pos, ValueIndices)
,
nth1
(Pos, Vs, Value)
.
type_is
(dict, 2, _{key1: Value1, key2: Value2})
:-
findall
(V, type_is(dict, 1, V), Vs1)
,
findall
(V, type_is(dict, 0, V), V0s)
,
append
(V0s, Vs1, Vs2)
,
length
(Vs1, NVs1)
,
randset
(3, NVs1, ValueIndices1)
,
member
(Pos1, ValueIndices1)
,
nth1
(Pos1, Vs1, Value1)
,
length
(Vs2, NVs2)
,
randset
(10, NVs2, ValueIndices2)
,
member
(Pos2, ValueIndices2)
,
nth1
(Pos2, Vs2, Value2)
.
/***************************************
*
*
*
Helpers
generating
erroneous
values
*
*
*
***************************************
/
type_not
_
atom
(
Value) :- member(Value, [1, "test", 7.3, some(term)]).
type_not
_
dict
(
Value) :- member(Value, [
type_not
(
atom
,
Value)
:-
member
(Value, [1, "test", 7.3, some(term)])
.
type_not
(
dict
,
Value)
:-
member
(Value, [
1,
test,
"test",
...
...
@@ -15,7 +81,7 @@ type_not_dict(Value) :- member(Value, [
[key=value],
[key: value]
])
.
type_not
_
integer
(
Value) :- member(Value, [
type_not
(
integer
,
Value)
:-
member
(Value, [
an_atom,
"test",
1.0,
...
...
@@ -23,22 +89,28 @@ type_not_integer(Value) :- member(Value, [
some(term),
["test"]
])
.
type_not
_
list
(
Value) :- type_not_term('[|]'/2, Value).
type_not
_
text
(
Value) :- member(Value, [1, 7.3, some(term), ["test"]]).
type_not
(
list
,
Value)
:-
type_not_term
('[|]'/2, Value)
.
type_not
(
text
,
Value)
:-
member
(Value, [1, 7.3, some(term), ["test"]])
.
type_not
_
term(_,Value) :- member(Value, [1, "test", test, 7.3]).
type_not
_
term(P/A, ["test"]) :- P/A \= '[|]'/2.
type_not
_
term(P/A, some(term)) :- P/A \= some/1.
type_not
_
term(P/A, Value) :-
type_not
(
term(_
)
,Value)
:-
member
(Value, [1, "test", test, 7.3])
.
type_not
(
term(P/A
)
, ["test"])
:-
P
/A
\=
'
[
|
]
'
/2.
type_not
(
term(P/A
)
, some(term))
:-
P
/A
\=
some
/1.
type_not
(
term(P/A
)
, Value)
:-
succ
(TooFew, A)
,
between
(1,TooFew,N)
,
functor
(Value,P,N)
,
numbervars
(Value,0,_)
.
type_not
_
term(P/A, Value) :-
type_not
(
term(P/A
)
, Value)
:-
succ
(A,TooMany)
,
functor
(Value,P,TooMany)
,
numbervars
(Value,0,_)
.
type_not_atom
(Value)
:-
type_not
(atom, Value)
.
type_not_dict
(Value)
:-
type_not
(dict, Value)
.
type_not_integer
(Value)
:-
type_not
(integer, Value)
.
type_not_list
(Value)
:-
type_not
(list, Value)
.
type_not_text
(Value)
:-
type_not
(text, Value)
.
type_not_term
(P/A, Value)
:-
type_not
(term(P/A), Value)
.
:-
prolog_load_context
(directory, Dir)
,
path_segments_atom
(Dir/web_api/'*.plt',WebApiFiles)
,
...
...
tests/web_api/helpers.plt
View file @
9d79deba
...
...
@@ -89,5 +89,90 @@ test(text_to_string_type,
error(type_error(text,Text))
]) :-
web_api:text_to_string(Text,_String).
/********************
* get_dict_typed/4 *
********************/
% get_dict_typed(+Dict, +Key, +Type, -Value) succeeds with the correct value on
% correct input
test(get_dict_typed_happy,
[ forall((
type_is(dict, RandomDict),
type_is(atom, Key),
type_is(Type, ExpectedValue),
false
)),
blocked(takes_too_long),
true(ExpectedValue =@= ActualValue)
]) :-
Dict = RandomDict.put([Key=ExpectedValue]),
web_api:get_dict_typed(Dict, Key, Type, ActualValue).
% get_dict_typed(+Dict, +Key, +Type, -Value) throws instantiation_error if Dict,
% Key, or Type is unbound.
test(get_dict_typed_instantiation_Dict,
[ error(instantiation_error)
]) :-
web_api:get_dict_typed(_, some_key, some_type, _ActualValue).
test(get_dict_typed_instantiation_Key,
[ error(instantiation_error)
]) :-
web_api:get_dict_typed(_{some_key: some_value}, _, some_type, _ActualValue).
test(get_dict_typed_instantiation_Type,
[ error(instantiation_error)
]) :-
web_api:get_dict_typed(_{some_key: some_value}, some_key, _, _ActualValue).
% get_dict_typed(+Dict, +Key, +Type, -Value) throws type_error(dict, Dict) if
% Dict is no dict.
test(get_dict_typed_type_Dict,
[ forall(type_not_dict(NoDict)),
error(type_error(dict, NoDict))
]) :-
web_api:get_dict_typed(NoDict, some_key, some_type, _ActualValue).
% get_dict_typed(+Dict, +Key, +Type, -Value) throws
% existence_error(key, Key, Dict) if Dict does not contain the key Key.
test(get_dict_typed_existence,
[ forall((
type_is(dict, Dict)
)),
error(existence_error(key, some_key, Dict))
]) :-
web_api:get_dict_typed(Dict, some_key, some_type, _ActualValue).
% get_dict_typed(+Dict, +Key, +Type, -Value) throws key_instantiation_error(Key)
% if Value is insufficiently instantiated
test(get_dict_typed_key_instantiation,
[ forall((
type_is(dict, RandomDict),
type_is(atom, Key),
type_is(Type, _ExpectedValue)
)),
error(key_instantiation_error(Key))
]) :-
Dict = RandomDict.put([Key=_]),
web_api:get_dict_typed(Dict, Key, Type, _ActualValue).
% get_dict_typed(+Dict, +Key, +Type, -Value) throws
% key_type_error(Key, Type, Value) if Value is not of type Type.
test(get_dict_typed_key_type_error,
[ forall((
type_is(dict, RandomDict),
type_is(atom, Key),
bagof(1,V^type_is(Type,V),_),
type_not(Type, Value)
)),
error(key_type_error(Key, Type, Value))
]) :-
Dict = RandomDict.put([Key=Value]),
web_api:get_dict_typed(Dict, Key, Type, _ActualValue).
:- end_tests('web_api -> helpers').
web_api.pl
View file @
9d79deba
...
...
@@ -101,9 +101,8 @@ server_opts(Opts) :-
% explanation may be created.
% @throws bad_request(missing_key(Key)) If a required parameter was missing
% in the JSON payload.
% @throws bad_request(wrong_type(abs_path, atom, Value))) If the Value
% associated with the key
% abs_path is not an atom.
% @throws bad_request(wrong_type(abs_path, atom))) If abs_path's value
% is not an atom.
% @throws bad_request(unknown_key(KeyName)) The unknown key KeyName was supplied
% in the request's payload.
% @throw server_error(E,Context) if an exception occured which is not the user's
...
...
@@ -314,3 +313,33 @@ match_with(Tag, Field, Dict, Value) :- theory_bg:item(_,Dict), is_dict(Dict,Tag)
text_to_string
(
Text
,
String
)
:-
must_be
(
text
,
Text
),
format
(
string
(
String
),
'~s'
,
[
Text
]).
%! get_dict_typed(+Dict, +Key, +Type, -Value) is det
%
% Unify the value associated with Key in Dict with Value. Throws an existence
% error if Key does not appear in Dict. Additionally, validates whether Value
% is bound and of type Type. Type definitions are taken from must_be/2.
%
% @see get_dict/3
% @see must_be/2
% @error instantiation_error if Dict Key, or Type is unbound
% @error type_error(dict, Dict) if Dict is no dict
% @error existence_error(key, Key, Dict) if Dict does not contain the key Key
% @error key_instantiation_error(Key) if Value is insufficiently instantiated
% @error key_type_error(Key, Type, Value) if Value is not of type Type
get_dict_typed
(
Dict
,
Key
,
Type
,
Value
)
:-
(
nonvar
(
Key
)
->
true
;
throw
(
error
(
instantiation_error
,
_
))
),
must_be
(
dict
,
Dict
),
Value
=
Dict
.
Key
,
(
nonvar
(
Value
)
->
true
;
throw
(
error
(
key_instantiation_error
(
Key
),
_
))
),
(
is_of_type
(
Type
,
Value
)
->
true
;
throw
(
error
(
key_type_error
(
Key
,
Type
,
Value
),
_
))
).
Write
Preview
Supports
Markdown
0%
Try again
or
attach a new file
.
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment