mirror of
https://github.com/valitydev/jesse.git
synced 2024-11-06 09:35:23 +00:00
Merge branch 'master' into std-formats
Conflicts: test/jesse_tests_draft4_SUITE.erl
This commit is contained in:
commit
79fa984755
12
README.md
12
README.md
@ -5,10 +5,16 @@
|
||||
jesse (JSON Schema Erlang) is an implementation of a JSON Schema validator
|
||||
for Erlang.
|
||||
|
||||
jesse implements [Draft 03] (http://tools.ietf.org/html/draft-zyp-json-schema-03) and [Draft 04] (http://tools.ietf.org/html/draft-zyp-json-schema-04) of
|
||||
the specification. It supports all core schema definitions except:
|
||||
jesse implements the following specifications:
|
||||
|
||||
* format
|
||||
* [Draft 03](http://tools.ietf.org/html/draft-zyp-json-schema-03)
|
||||
* [Draft 04](http://tools.ietf.org/html/draft-zyp-json-schema-04)
|
||||
|
||||
## Erlang API Docs
|
||||
|
||||
Automatically generated docs are available https://dev.erldocs.com/github.com/for-get/jesse/ .
|
||||
|
||||
Please keep in mind that the public API is the `jesse.erl` module alone.
|
||||
|
||||
## Quick start - CLI
|
||||
|
||||
|
@ -30,6 +30,7 @@
|
||||
%% JSON-Schema-Test-Suite attributes definitions
|
||||
-define(DATA, <<"data">>).
|
||||
-define(DESCRIPTION, <<"description">>).
|
||||
-define(OPTIONS, <<"options">>).
|
||||
-define(SCHEMA, <<"schema">>).
|
||||
-define(TESTS, <<"tests">>).
|
||||
-define(VALID, <<"valid">>).
|
||||
@ -57,26 +58,29 @@ do_test(Key, Config) ->
|
||||
Description = get_path(?DESCRIPTION, Test),
|
||||
Schema = get_path(?SCHEMA, Test),
|
||||
SchemaTests = get_path(?TESTS, Test),
|
||||
Options = get_path(?OPTIONS, Test),
|
||||
ct:pal( "** Description: ~s~n"
|
||||
"** Options: ~p~n"
|
||||
"** Schema: ~p~n"
|
||||
"** Schema tests: ~p~n"
|
||||
, [Description, Schema, SchemaTests]
|
||||
, [Description, Options, Schema, SchemaTests]
|
||||
),
|
||||
test_schema(DefaultSchema, Schema, SchemaTests)
|
||||
test_schema(DefaultSchema, Options, Schema, SchemaTests)
|
||||
end
|
||||
, Tests
|
||||
).
|
||||
|
||||
%%% Internal functions
|
||||
|
||||
test_schema(DefaultSchema, Schema, SchemaTests) ->
|
||||
test_schema(DefaultSchema, Opts0, Schema, SchemaTests) ->
|
||||
Opts1 = make_options(Opts0),
|
||||
lists:foreach( fun(Test) ->
|
||||
Description = get_path(?DESCRIPTION, Test),
|
||||
Instance = get_path(?DATA, Test),
|
||||
ct:pal("* Test case: ~s~n", [Description]),
|
||||
Opts = [ {default_schema_ver, DefaultSchema}
|
||||
, {schema_loader_fun, fun load_schema/1}
|
||||
],
|
||||
] ++ Opts1,
|
||||
try jesse:validate_with_schema(Schema, Instance, Opts) of
|
||||
Result ->
|
||||
ct:pal("Result: ~p~n", [Result]),
|
||||
@ -96,6 +100,21 @@ test_schema(DefaultSchema, Schema, SchemaTests) ->
|
||||
, SchemaTests
|
||||
).
|
||||
|
||||
make_options(Options) ->
|
||||
lists:map( fun ({Key0, Value0}) ->
|
||||
Key = case is_binary(Key0) of
|
||||
true -> list_to_existing_atom(binary_to_list(Key0));
|
||||
false -> Key0
|
||||
end,
|
||||
Value = case is_binary(Value0) of
|
||||
true -> list_to_existing_atom(binary_to_list(Value0));
|
||||
false -> Value0
|
||||
end,
|
||||
{Key, Value}
|
||||
end
|
||||
, Options
|
||||
).
|
||||
|
||||
testfile_to_key(TestFile) ->
|
||||
filename:rootname(filename:basename(TestFile)).
|
||||
|
||||
|
@ -487,7 +487,7 @@ get_additional_properties(Value, Properties, PatternProperties) ->
|
||||
%% @private
|
||||
filter_extra_names(Pattern, ExtraNames) ->
|
||||
Filter = fun(ExtraName) ->
|
||||
case re:run(ExtraName, Pattern, [{capture, none}]) of
|
||||
case re:run(ExtraName, Pattern, [{capture, none}, unicode]) of
|
||||
match -> false;
|
||||
nomatch -> true
|
||||
end
|
||||
|
@ -490,7 +490,7 @@ get_additional_properties(Value, Properties, PatternProperties) ->
|
||||
%% @private
|
||||
filter_extra_names(Pattern, ExtraNames) ->
|
||||
Filter = fun(ExtraName) ->
|
||||
case re:run(ExtraName, Pattern, [{capture, none}]) of
|
||||
case re:run(ExtraName, Pattern, [{capture, none}, unicode]) of
|
||||
match -> false;
|
||||
nomatch -> true
|
||||
end
|
||||
@ -968,11 +968,13 @@ check_format(Value, _Format = <<"email">>, State) when is_binary(Value) ->
|
||||
nomatch -> handle_data_invalid(?wrong_format, Value, State)
|
||||
end;
|
||||
check_format(Value, _Format = <<"ip-address">>, State) when is_binary(Value) ->
|
||||
%% avoiding inet:parse_ipv4strict_address to maintain R15 compatibility
|
||||
case inet_parse:ipv4strict_address(binary_to_list(Value)) of
|
||||
{ok, _IPv4Address} -> State;
|
||||
{error, einval} -> handle_data_invalid(?wrong_format, Value, State)
|
||||
end;
|
||||
check_format(Value, _Format = <<"ipv6">>, State) when is_binary(Value) ->
|
||||
%% avoiding inet:parse_ipv6strict_address to maintain R15 compatibility
|
||||
case inet_parse:ipv6strict_address(binary_to_list(Value)) of
|
||||
{ok, _IPv6Address} -> State;
|
||||
{error, einval} -> handle_data_invalid(?wrong_format, Value, State)
|
||||
@ -1134,7 +1136,11 @@ check_any_of_(Value, [], State) ->
|
||||
handle_data_invalid(?any_schemas_not_valid, Value, State);
|
||||
check_any_of_(Value, [Schema | Schemas], State) ->
|
||||
case validate_schema(Value, Schema, State) of
|
||||
{true, NewState} -> NewState;
|
||||
{true, NewState} ->
|
||||
case jesse_state:get_error_list(NewState) of
|
||||
[] -> NewState;
|
||||
_ -> check_any_of_(Value, Schemas, State)
|
||||
end;
|
||||
{false, _} -> check_any_of_(Value, Schemas, State)
|
||||
end.
|
||||
|
||||
@ -1168,7 +1174,10 @@ check_one_of_(Value, _Schemas, State, Valid) when Valid > 1 ->
|
||||
check_one_of_(Value, [Schema | Schemas], State, Valid) ->
|
||||
case validate_schema(Value, Schema, State) of
|
||||
{true, NewState} ->
|
||||
check_one_of_(Value, Schemas, NewState, Valid + 1);
|
||||
case jesse_state:get_error_list(NewState) of
|
||||
[] -> check_one_of_(Value, Schemas, NewState, Valid + 1);
|
||||
_ -> check_one_of_(Value, Schemas, State, Valid)
|
||||
end;
|
||||
{false, _} ->
|
||||
check_one_of_(Value, Schemas, State, Valid)
|
||||
end.
|
||||
@ -1335,6 +1344,7 @@ remove_last_from_path(State) ->
|
||||
%% @private
|
||||
valid_date(<<Year:4/bytes, $-, Month:2/bytes, $-, Day:2/bytes>>) ->
|
||||
try
|
||||
%% avoiding binary_to_integer to maintain R15 compatibility
|
||||
calendar:valid_date( list_to_integer(binary_to_list(Year))
|
||||
, list_to_integer(binary_to_list(Month))
|
||||
, list_to_integer(binary_to_list(Day))
|
||||
@ -1346,6 +1356,7 @@ valid_date(_Other) -> false.
|
||||
|
||||
%% @private
|
||||
valid_time(<<Hour:2/bytes, $:, Minute:2/bytes, $:, Second:2/bytes>>) ->
|
||||
%% avoiding binary_to_integer to maintain R15 compatibility
|
||||
try { list_to_integer(binary_to_list(Hour))
|
||||
, list_to_integer(binary_to_list(Minute))
|
||||
, list_to_integer(binary_to_list(Second))
|
||||
|
@ -0,0 +1,21 @@
|
||||
{
|
||||
"description": "using non-ascii regex additionalProperties being false does not allow other properties ",
|
||||
"schema": {
|
||||
"patternProperties": {
|
||||
"^á": {}
|
||||
},
|
||||
"additionalProperties": false
|
||||
},
|
||||
"tests": [
|
||||
{
|
||||
"description": "non-ascii patternProperties matching the pattern is valid",
|
||||
"data": {"ármányos": 2},
|
||||
"valid": true
|
||||
},
|
||||
{
|
||||
"description": "additional non-ascii patternProperties not matching the pattern is invalid",
|
||||
"data": {"élmény": 2},
|
||||
"valid": false
|
||||
}
|
||||
]
|
||||
}
|
@ -0,0 +1,75 @@
|
||||
[
|
||||
{
|
||||
"description": "anyOf/oneOf with allowed_errors",
|
||||
"options": {
|
||||
"allowed_errors": "infinity"
|
||||
},
|
||||
"schema": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"anyOf": {
|
||||
"anyOf": [
|
||||
{
|
||||
"enum": [0]
|
||||
}, {
|
||||
"enum": [0, 1]
|
||||
}
|
||||
]
|
||||
},
|
||||
"oneOf": {
|
||||
"oneOf": [
|
||||
{
|
||||
"enum": [0]
|
||||
}, {
|
||||
"enum": [0, 1]
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
},
|
||||
"tests": [
|
||||
{
|
||||
"description": "anyOf: all valid",
|
||||
"data": {
|
||||
"anyOf": 0
|
||||
},
|
||||
"valid": true
|
||||
},
|
||||
{
|
||||
"description": "anyOf: one valid",
|
||||
"data": {
|
||||
"anyOf": 1
|
||||
},
|
||||
"valid": true
|
||||
},
|
||||
{
|
||||
"description": "anyOf: invalid",
|
||||
"data": {
|
||||
"anyOf": 2
|
||||
},
|
||||
"valid": false
|
||||
},
|
||||
{
|
||||
"description": "oneOf: all valid",
|
||||
"data": {
|
||||
"oneOf": 0
|
||||
},
|
||||
"valid": false
|
||||
},
|
||||
{
|
||||
"description": "oneOf: one valid",
|
||||
"data": {
|
||||
"oneOf": 1
|
||||
},
|
||||
"valid": true
|
||||
},
|
||||
{
|
||||
"description": "oneOf: invalid",
|
||||
"data": {
|
||||
"oneOf": 2
|
||||
},
|
||||
"valid": false
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
@ -0,0 +1,75 @@
|
||||
[
|
||||
{
|
||||
"description": "anyOf/oneOf with allowed_errors",
|
||||
"options": {
|
||||
"allowed_errors": 1
|
||||
},
|
||||
"schema": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"anyOf": {
|
||||
"anyOf": [
|
||||
{
|
||||
"enum": [0]
|
||||
}, {
|
||||
"enum": [0, 1]
|
||||
}
|
||||
]
|
||||
},
|
||||
"oneOf": {
|
||||
"oneOf": [
|
||||
{
|
||||
"enum": [0]
|
||||
}, {
|
||||
"enum": [0, 1]
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
},
|
||||
"tests": [
|
||||
{
|
||||
"description": "anyOf: all valid",
|
||||
"data": {
|
||||
"anyOf": 0
|
||||
},
|
||||
"valid": true
|
||||
},
|
||||
{
|
||||
"description": "anyOf: one valid",
|
||||
"data": {
|
||||
"anyOf": 1
|
||||
},
|
||||
"valid": true
|
||||
},
|
||||
{
|
||||
"description": "anyOf: invalid",
|
||||
"data": {
|
||||
"anyOf": 2
|
||||
},
|
||||
"valid": false
|
||||
},
|
||||
{
|
||||
"description": "oneOf: all valid",
|
||||
"data": {
|
||||
"oneOf": 0
|
||||
},
|
||||
"valid": false
|
||||
},
|
||||
{
|
||||
"description": "oneOf: one valid",
|
||||
"data": {
|
||||
"oneOf": 1
|
||||
},
|
||||
"valid": true
|
||||
},
|
||||
{
|
||||
"description": "oneOf: invalid",
|
||||
"data": {
|
||||
"oneOf": 2
|
||||
},
|
||||
"valid": false
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
@ -0,0 +1,75 @@
|
||||
[
|
||||
{
|
||||
"description": "anyOf/oneOf with allowed_errors",
|
||||
"options": {
|
||||
"allowed_errors": 0
|
||||
},
|
||||
"schema": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"anyOf": {
|
||||
"anyOf": [
|
||||
{
|
||||
"enum": [0]
|
||||
}, {
|
||||
"enum": [0, 1]
|
||||
}
|
||||
]
|
||||
},
|
||||
"oneOf": {
|
||||
"oneOf": [
|
||||
{
|
||||
"enum": [0]
|
||||
}, {
|
||||
"enum": [0, 1]
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
},
|
||||
"tests": [
|
||||
{
|
||||
"description": "anyOf: all valid",
|
||||
"data": {
|
||||
"anyOf": 0
|
||||
},
|
||||
"valid": true
|
||||
},
|
||||
{
|
||||
"description": "anyOf: one valid",
|
||||
"data": {
|
||||
"anyOf": 1
|
||||
},
|
||||
"valid": true
|
||||
},
|
||||
{
|
||||
"description": "anyOf: invalid",
|
||||
"data": {
|
||||
"anyOf": 2
|
||||
},
|
||||
"valid": false
|
||||
},
|
||||
{
|
||||
"description": "oneOf: all valid",
|
||||
"data": {
|
||||
"oneOf": 0
|
||||
},
|
||||
"valid": false
|
||||
},
|
||||
{
|
||||
"description": "oneOf: one valid",
|
||||
"data": {
|
||||
"oneOf": 1
|
||||
},
|
||||
"valid": true
|
||||
},
|
||||
{
|
||||
"description": "oneOf: invalid",
|
||||
"data": {
|
||||
"oneOf": 2
|
||||
},
|
||||
"valid": false
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
@ -0,0 +1,21 @@
|
||||
{
|
||||
"description": "using non-ascii regex additionalProperties being false does not allow other properties ",
|
||||
"schema": {
|
||||
"patternProperties": {
|
||||
"^á": {}
|
||||
},
|
||||
"additionalProperties": false
|
||||
},
|
||||
"tests": [
|
||||
{
|
||||
"description": "non-ascii patternProperties matching the pattern is valid",
|
||||
"data": {"ármányos": 2},
|
||||
"valid": true
|
||||
},
|
||||
{
|
||||
"description": "additional non-ascii patternProperties not matching the pattern is invalid",
|
||||
"data": {"élmény": 2},
|
||||
"valid": false
|
||||
}
|
||||
]
|
||||
}
|
@ -140,3 +140,6 @@ itemsExtra(Config) ->
|
||||
|
||||
remoteRefExtra(Config) ->
|
||||
do_test("remoteRefExtra", Config).
|
||||
|
||||
unicodePatternProperties(Config) ->
|
||||
do_test("unicodePatternProperties", Config).
|
||||
|
@ -156,6 +156,18 @@ itemsExtra(Config) ->
|
||||
remoteRefExtra(Config) ->
|
||||
do_test("remoteRefExtra", Config).
|
||||
|
||||
anyOfOneOfAllowedErrorsZeroExtra(Config) ->
|
||||
do_test("anyOfOneOfAllowedErrorsZeroExtra", Config).
|
||||
|
||||
anyOfOneOfAllowedErrorsOneExtra(Config) ->
|
||||
do_test("anyOfOneOfAllowedErrorsOneExtra", Config).
|
||||
|
||||
anyOfOneOfAllowedErrorsInfinityExtra(Config) ->
|
||||
do_test("anyOfOneOfAllowedErrorsInfinityExtra", Config).
|
||||
|
||||
unicodePatternProperties(Config) ->
|
||||
do_test("unicodePatternProperties", Config).
|
||||
|
||||
dateFormat(Config) ->
|
||||
do_test("dateFormat", Config).
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user