From f8e89b3fefbda11932a2344fa1069a40b8c3726d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tina=20M=C3=BCller?= Date: Wed, 22 Sep 2021 01:18:03 +0200 Subject: [PATCH] Add a test for the YAML 1.1 types --- tests/data/yaml11.schema | 264 ++++++++++++++++++++++++++++++++++ tests/data/yaml11.schema-skip | 9 ++ tests/lib/test_schema.py | 152 ++++++++++++++++++++ tests/lib/test_yaml.py | 2 + 4 files changed, 427 insertions(+) create mode 100644 tests/data/yaml11.schema create mode 100644 tests/data/yaml11.schema-skip create mode 100644 tests/lib/test_schema.py diff --git a/tests/data/yaml11.schema b/tests/data/yaml11.schema new file mode 100644 index 00000000..e2791aa7 --- /dev/null +++ b/tests/data/yaml11.schema @@ -0,0 +1,264 @@ +# https://github.com/perlpunk/yaml-test-schema/blob/master/data/schema-yaml11.yaml +--- +'!!bool FALSE': ['bool', 'false()', 'false'] +'!!bool False': ['bool', 'false()', 'false'] +'!!bool N': ['bool', 'false()', "false"] +'!!bool NO': ['bool', 'false()', "false"] +'!!bool No': ['bool', 'false()', "false"] +'!!bool OFF': ['bool', 'false()', "false"] +'!!bool ON': ['bool', 'true()', "true"] +'!!bool Off': ['bool', 'false()', "false"] +'!!bool On': ['bool', 'true()', "true"] +'!!bool TRUE': ['bool', 'true()', 'true'] +'!!bool True': ['bool', 'true()', 'true'] +'!!bool Y': ['bool', 'true()', "true"] +'!!bool YES': ['bool', 'true()', "true"] +'!!bool Yes': ['bool', 'true()', "true"] +'!!bool false': ['bool', 'false()', 'false'] +'!!bool n': ['bool', 'false()', "false"] +'!!bool no': ['bool', 'false()', "false"] +'!!bool off': ['bool', 'false()', "false"] +'!!bool on': ['bool', 'true()', "true"] +'!!bool true': ['bool', 'true()', 'true'] +'!!bool y': ['bool', 'true()', "true"] +'!!bool yes': ['bool', 'true()', "true"] +'!!float +.INF': ['inf', 'inf()', '.inf'] +'!!float +.Inf': ['inf', 'inf()', '.inf'] +'!!float +.inf': ['inf', 'inf()', '.inf'] +'!!float +0.3e+3': ['float', '300.0', '300.0'] +'!!float -.INF': ['inf', 'inf-neg()', '-.inf'] +'!!float -.Inf': ['inf', 'inf-neg()', '-.inf'] +'!!float -.inf': ['inf', 'inf-neg()', '-.inf'] +'!!float -3.14': ['float', '-3.14', '-3.14'] +'!!float .0': ['float', '0.0', '0.0'] +'!!float .14': ['float', '0.14', '0.14'] +'!!float .1_4': ['float', '0.14', '0.14'] +'!!float .3E-1': ['float', '0.03', '0.03'] +'!!float .3e+3': ['float', '300.0', '300.0'] +'!!float .INF': ['inf', 'inf()', '.inf'] +'!!float .Inf': ['inf', 'inf()', '.inf'] +'!!float .NAN': ['nan', 'nan()', '.nan'] +'!!float .NaN': ['nan', 'nan()', '.nan'] +'!!float .inf': ['inf', 'inf()', '.inf'] +'!!float .nan': ['nan', 'nan()', '.nan'] +'!!float 0.0': ['float', '0.0', '0.0'] +'!!float 001.23': ['float', '1.23', '1.23'] +'!!float 190:20:30.15': ['float', '685230.15', '685230.15'] +'!!float 3.': ['float', '3.0', '3.0'] +'!!float 3.14': ['float', '3.14', '3.14'] +'!!float 3.3e+3': ['float', '3300.0', '3300.0'] +'!!float 85.230_15e+03': ['float', '85230.15', '85230.15'] +'!!float 85_230.15': ['float', '85230.15', '85230.15'] +'!!int +0': ['int', '0', '0'] +'!!int +0100_200': ['int', '32896', '32896'] +'!!int +0b100': ['int', '4', '4'] +'!!int +190:20:30': ['int', '685230', '685230'] +'!!int +23': ['int', '23', '23'] +'!!int -0': ['int', '0', '0'] +'!!int -0100_200': ['int', '-32896', '-32896'] +'!!int -0b101': ['int', '-5', '-5'] +'!!int -0x30': ['int', '-48', '-48'] +'!!int -190:20:30': ['int', '-685230', '-685230'] +'!!int -23': ['int', '-23', '-23'] +'!!int 0': ['int', '0', '0'] +'!!int 00': ['int', '0', '0'] +'!!int 0011': ['int', '9', '9'] +'!!int 010': ['int', '8', '8'] +'!!int 02_0': ['int', '16', '16'] +'!!int 07': ['int', '7', '7'] +'!!int 0b0': ['int', '0', '0'] +'!!int 0b100_101': ['int', '37', '37'] +'!!int 0x0': ['int', '0', '0'] +'!!int 0x10': ['int', '16', '16'] +'!!int 0x2_0': ['int', '32', '32'] +'!!int 0x42': ['int', '66', '66'] +'!!int 0xa': ['int', '10', '10'] +'!!int 100_000': ['int', '100000', '100000'] +'!!int 190:20:30': ['int', '685230', '685230'] +'!!int 23': ['int', '23', '23'] +'!!null #empty': ['null', 'null()', "null"] +'!!null NULL': ['null', 'null()', "null"] +'!!null Null': ['null', 'null()', "null"] +'!!null null': ['null', 'null()', 'null'] +'!!null ~': ['null', 'null()', 'null'] +'!!str #empty': ['str', '', "''"] +'!!str +.INF': ['str', '+.INF', "'+.INF'"] +'!!str +.Inf': ['str', '+.Inf', "'+.Inf'"] +'!!str +.inf': ['str', '+.inf', "'+.inf'"] +'!!str +0': ['str', '+0', "'+0'"] +'!!str +0.3e+3': ['str', '+0.3e+3', "'+0.3e+3'"] +'!!str +0.3e3': ['str', '+0.3e3', "+0.3e3"] +'!!str +0100_200': ['str', '+0100_200', "'+0100_200'"] +'!!str +0b100': ['str', '+0b100', "'+0b100'"] +'!!str +190:20:30': ['str', '+190:20:30', "'+190:20:30'"] +'!!str +23': ['str', '+23', "'+23'"] +'!!str -.INF': ['str', '-.INF', "'-.INF'"] +'!!str -.Inf': ['str', '-.Inf', "'-.Inf'"] +'!!str -.inf': ['str', '-.inf', "'-.inf'"] +'!!str -0': ['str', '-0', "'-0'"] +'!!str -0100_200': ['str', '-0100_200', "'-0100_200'"] +'!!str -0b101': ['str', '-0b101', "'-0b101'"] +'!!str -0x30': ['str', '-0x30', "'-0x30'"] +'!!str -190:20:30': ['str', '-190:20:30', "'-190:20:30'"] +'!!str -23': ['str', '-23', "'-23'"] +'!!str -3.14': ['str', '-3.14', "'-3.14'"] +'!!str .': ['str', '.', '.'] +'!!str .0': ['str', '.0', "'.0'"] +'!!str .14': ['str', '.14', "'.14'"] +'!!str .1_4': ['str', '.1_4', "'.1_4'"] +'!!str .3E-1': ['str', '.3E-1', "'.3E-1'"] +'!!str .3e+3': ['str', '.3e+3', "'.3e+3'"] +'!!str .3e3': ['str', '.3e3', ".3e3"] +'!!str .INF': ['str', '.INF', "'.INF'"] +'!!str .Inf': ['str', '.Inf', "'.Inf'"] +'!!str .NAN': ['str', '.NAN', "'.NAN'"] +'!!str .NaN': ['str', '.NaN', "'.NaN'"] +'!!str ._': ['str', '._', '._'] +'!!str ._14': ['str', '._14', '._14'] +'!!str .inf': ['str', '.inf', "'.inf'"] +'!!str .nan': ['str', '.nan', "'.nan'"] +'!!str 0': ['str', '0', "'0'"] +'!!str 0.0': ['str', '0.0', "'0.0'"] +'!!str 0.3e3': ['str', '0.3e3', "0.3e3"] +'!!str 00': ['str', '00', "'00'"] +'!!str 001.23': ['str', '001.23', "'001.23'"] +'!!str 0011': ['str', '0011', "'0011'"] +'!!str 010': ['str', '010', "'010'"] +'!!str 02_0': ['str', '02_0', "'02_0'"] +'!!str 07': ['str', '07', "'07'"] +'!!str 0b0': ['str', '0b0', "'0b0'"] +'!!str 0b100_101': ['str', '0b100_101', "'0b100_101'"] +'!!str 0o0': ['str', '0o0', "0o0"] +'!!str 0o10': ['str', '0o10', "0o10"] +'!!str 0o7': ['str', '0o7', "0o7"] +'!!str 0x0': ['str', '0x0', "'0x0'"] +'!!str 0x2_0': ['str', '0x2_0', "'0x2_0'"] +'!!str 0xa': ['str', '0xa', "'0xa'"] +'!!str 100_000': ['str', '100_000', "'100_000'"] +'!!str 190:20:30': ['str', '190:20:30', "'190:20:30'"] +'!!str 190:20:30.15': ['str', '190:20:30.15', "'190:20:30.15'"] +'!!str 23': ['str', '23', "'23'"] +'!!str 3.': ['str', '3.', "'3.'"] +'!!str 3.14': ['str', '3.14', "'3.14'"] +'!!str 3.3e+3': ['str', '3.3e+3', "'3.3e+3'"] +'!!str 85.230_15e+03': ['str', '85.230_15e+03', "'85.230_15e+03'"] +'!!str 85_230.15': ['str', '85_230.15', "'85_230.15'"] +'!!str FALSE': ['str', 'FALSE', "'FALSE'"] +'!!str False': ['str', 'False', "'False'"] +'!!str N': ['str', 'N', "'N'"] +'!!str NO': ['str', 'NO', "'NO'"] +'!!str NULL': ['str', 'NULL', "'NULL'"] +'!!str Null': ['str', 'Null', "'Null'"] +'!!str OFF': ['str', 'OFF', "'OFF'"] +'!!str ON': ['str', 'ON', "'ON'"] +'!!str Off': ['str', 'Off', "'Off'"] +'!!str On': ['str', 'On', "'On'"] +'!!str TRUE': ['str', 'TRUE', "'TRUE'"] +'!!str True': ['str', 'True', "'True'"] +'!!str Y': ['str', 'Y', "'Y'"] +'!!str YES': ['str', 'YES', "'YES'"] +'!!str Yes': ['str', 'Yes', "'Yes'"] +'!!str _._': ['str', '_._', '_._'] +'!!str false': ['str', 'false', "'false'"] +'!!str n': ['str', 'n', "'n'"] +'!!str no': ['str', 'no', "'no'"] +'!!str null': ['str', 'null', "'null'"] +'!!str off': ['str', 'off', "'off'"] +'!!str on': ['str', 'on', "'on'"] +'!!str true': ['str', 'true', "'true'"] +'!!str y': ['str', 'y', "'y'"] +'!!str yes': ['str', 'yes', "'yes'"] +'!!str ~': ['str', '~', "'~'"] +'#empty': ['null', 'null()', "null"] +'+.INF': ['inf', 'inf()', '.inf'] +'+.Inf': ['inf', 'inf()', '.inf'] +'+.inf': ['inf', 'inf()', '.inf'] +'+0': ['int', '0', '0'] +'+0.3e+3': ['float', '300.0', '300.0'] +'+0.3e3': ['str', '+0.3e3', '+0.3e3'] +'+0100_200': ['int', '32896', '32896'] +'+0b100': ['int', '4', '4'] +'+190:20:30': ['int', '685230', '685230'] +'+23': ['int', '23', '23'] +'+3.14': ['float', '3.14', '3.14'] +'-.INF': ['inf', 'inf-neg()', '-.inf'] +'-.Inf': ['inf', 'inf-neg()', '-.inf'] +'-.inf': ['inf', 'inf-neg()', '-.inf'] +'-0': ['int', '0', '0'] +'-0100_200': ['int', '-32896', '-32896'] +'-0b101': ['int', '-5', '-5'] +'-0x30': ['int', '-48', '-48'] +'-190:20:30': ['int', '-685230', '-685230'] +'-23': ['int', '-23', '-23'] +'-3.14': ['float', '-3.14', '-3.14'] +'.': ['str', '.', '.'] +'.0': ['float', '0.0', '0.0'] +'.14': ['float', '0.14', '0.14'] +'.1_4': ['float', '0.14', '0.14'] +'.3E-1': ['float', '0.03', '0.03'] +'.3e+3': ['float', '300.0', '300.0'] +'.3e3': ['str', '.3e3', '.3e3'] +'.INF': ['inf', 'inf()', '.inf'] +'.Inf': ['inf', 'inf()', '.inf'] +'.NAN': ['nan', 'nan()', '.nan'] +'.NaN': ['nan', 'nan()', '.nan'] +'._': ['str', '._', '._'] +'._14': ['str', '._14', '._14'] +'.inf': ['inf', 'inf()', '.inf'] +'.nan': ['nan', 'nan()', '.nan'] +'0': ['int', '0', '0'] +'0.0': ['float', '0.0', '0.0'] +'0.3e3': ['str', '0.3e3', '0.3e3'] +'00': ['int', '0', '0'] +'001.23': ['float', '1.23', '1.23'] +'0011': ['int', '9', '9'] +'010': ['int', '8', '8'] +'02_0': ['int', '16', '16'] +'07': ['int', '7', '7'] +'08': ['str', '08', '08'] +'0b0': ['int', '0', '0'] +'0b100_101': ['int', '37', '37'] +'0o0': ['str', '0o0', '0o0'] +'0o10': ['str', '0o10', '0o10'] +'0o7': ['str', '0o7', '0o7'] +'0x0': ['int', '0', '0'] +'0x10': ['int', '16', '16'] +'0x2_0': ['int', '32', '32'] +'0x42': ['int', '66', '66'] +'0xa': ['int', '10', '10'] +'100_000': ['int', '100000', '100000'] +'190:20:30': ['int', '685230', '685230'] +'190:20:30.15': ['float', '685230.15', '685230.15'] +'23': ['int', '23', '23'] +'3.': ['float', '3.0', '3.0'] +'3.14': ['float', '3.14', '3.14'] +'3.3e+3': ['float', '3300', '3300.0'] +'3e3': ['str', '3e3', '3e3'] +'85.230_15e+03': ['float', '85230.15', '85230.15'] +'85_230.15': ['float', '85230.15', '85230.15'] +'FALSE': ['bool', 'false()', 'false'] +'False': ['bool', 'false()', 'false'] +'N': ['bool', 'false()', "false"] +'NO': ['bool', 'false()', "false"] +'NULL': ['null', 'null()', "null"] +'Null': ['null', 'null()', "null"] +'OFF': ['bool', 'false()', "false"] +'ON': ['bool', 'true()', "true"] +'Off': ['bool', 'false()', "false"] +'On': ['bool', 'true()', "true"] +'TRUE': ['bool', 'true()', 'true'] +'True': ['bool', 'true()', 'true'] +'Y': ['bool', 'true()', "true"] +'YES': ['bool', 'true()', "true"] +'Yes': ['bool', 'true()', "true"] +'_._': ['str', '_._', '_._'] +'false': ['bool', 'false()', 'false'] +'n': ['bool', 'false()', "false"] +'no': ['bool', 'false()', "false"] +'null': ['null', 'null()', "null"] +'off': ['bool', 'false()', "false"] +'on': ['bool', 'true()', "true"] +'true': ['bool', 'true()', 'true'] +'y': ['bool', 'true()', "true"] +'yes': ['bool', 'true()', "true"] +'~': ['null', 'null()', "null"] diff --git a/tests/data/yaml11.schema-skip b/tests/data/yaml11.schema-skip new file mode 100644 index 00000000..4fe0f0bf --- /dev/null +++ b/tests/data/yaml11.schema-skip @@ -0,0 +1,9 @@ +load: { + 'Y': 1, 'y': 1, 'N': 1, 'n': 1, + '!!bool Y': 1, '!!bool N': 1, '!!bool n': 1, '!!bool y': 1, + '._', '!!str ._', + '._14', '!!str ._14' + } +dump: { + '!!str N': 1, '!!str Y': 1, '!!str n': 1, '!!str y': 1, + } diff --git a/tests/lib/test_schema.py b/tests/lib/test_schema.py new file mode 100644 index 00000000..f3370ec1 --- /dev/null +++ b/tests/lib/test_schema.py @@ -0,0 +1,152 @@ +import yaml +import sys +import pprint +import math + +def check_bool(value, expected): + if expected == 'false()' and value is False: + return 1 + if expected == 'true()' and value is True: + return 1 + print(value) + print(expected) + return 0 + +def check_int(value, expected): + if (int(expected) == value): + return 1 + print(value) + print(expected) + return 0 + +def check_float(value, expected): + if expected == 'inf()': + if value == math.inf: + return 1 + elif expected == 'inf-neg()': + if value == -math.inf: + return 1 + elif expected == 'nan()': + if math.isnan(value): + return 1 + elif (float(expected) == value): + return 1 + else: + print(value) + print(expected) + return 0 + +def check_str(value, expected): + if value == expected: + return 1 + print(value) + print(expected) + return 0 + + +def _fail(input, test): + print("Input: >>" + input + "<<") + print(test) + +# The tests/data/yaml11.schema file is copied from +# https://github.com/perlpunk/yaml-test-schema/blob/master/data/schema-yaml11.yaml +def test_implicit_resolver(data_filename, skip_filename, verbose=False): + types = { + 'str': [str, check_str], + 'int': [int, check_int], + 'float': [float, check_float], + 'inf': [float, check_float], + 'nan': [float, check_float], + 'bool': [bool, check_bool], + } + with open(skip_filename, 'rb') as file: + skipdata = yaml.load(file, Loader=yaml.SafeLoader) + skip_load = skipdata['load'] + skip_dump = skipdata['dump'] + if verbose: + print(skip_load) + with open(data_filename, 'rb') as file: + tests = yaml.load(file, Loader=yaml.SafeLoader) + + i = 0 + fail = 0 + for i, (input, test) in enumerate(sorted(tests.items())): + if verbose: + print('-------------------- ' + str(i)) + + # Skip known loader bugs + if input in skip_load: + continue + + exp_type = test[0] + data = test[1] + exp_dump = test[2] + + # Test loading + try: + loaded = yaml.safe_load(input) + except: + print("Error:", sys.exc_info()[0], '(', sys.exc_info()[1], ')') + fail+=1 + _fail(input, test) + continue + + if verbose: + print(input) + print(test) + print(loaded) + print(type(loaded)) + + if exp_type == 'null': + if loaded is None: + pass + else: + fail+=1 + _fail(input, test) + else: + t = types[exp_type][0] + code = types[exp_type][1] + if isinstance(loaded, t): + if code(loaded, data): + pass + else: + fail+=1 + _fail(input, test) + else: + fail+=1 + _fail(input, test) + + # Skip known dumper bugs + if input in skip_dump: + continue + + dump = yaml.safe_dump(loaded, explicit_end=False) + # strip trailing newlines and footers + if dump.endswith('\n...\n'): + dump = dump[:-5] + if dump.endswith('\n'): + dump = dump[:-1] + if dump == exp_dump: + pass + else: + print("Compare: >>" + dump + "<< >>" + exp_dump + "<<") + fail+=1 + _fail(input, test) + +# if i >= 80: +# break + + if fail > 0: + print("Failed " + str(fail) + " / " + str(i) + " tests") + assert(False) + else: + print("Passed " + str(i) + " tests") + print("Skipped " + str(len(skip_load)) + " load tests") + print("Skipped " + str(len(skip_dump)) + " dump tests") + +test_implicit_resolver.unittest = ['.schema', '.schema-skip'] + +if __name__ == '__main__': + import test_appliance + test_appliance.run(globals()) + diff --git a/tests/lib/test_yaml.py b/tests/lib/test_yaml.py index 352cd8d1..7b3d8f9d 100644 --- a/tests/lib/test_yaml.py +++ b/tests/lib/test_yaml.py @@ -14,6 +14,8 @@ from test_sort_keys import * from test_multi_constructor import * +from test_schema import * + if __name__ == '__main__': import test_appliance test_appliance.run(globals())