# -*- coding: utf-8 -*- # Copyright (c) 2021 Ansible Project # GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt) from __future__ import absolute_import, division, print_function __metaclass__ = type import pytest from ansible.module_utils.common.arg_spec import ArgumentSpecValidator, ValidationResult # Each item is id, argument_spec, parameters, expected, valid parameter names VALID_SPECS = [ ( 'str-no-type-specified', {'name': {}}, {'name': 'rey'}, {'name': 'rey'}, set(('name',)), ), ( 'str', {'name': {'type': 'str'}}, {'name': 'rey'}, {'name': 'rey'}, set(('name',)), ), ( 'str-convert', {'name': {'type': 'str'}}, {'name': 5}, {'name': '5'}, set(('name',)), ), ( 'list', {'packages': {'type': 'list'}}, {'packages': ['vim', 'python']}, {'packages': ['vim', 'python']}, set(('packages',)), ), ( 'list-comma-string', {'packages': {'type': 'list'}}, {'packages': 'vim,python'}, {'packages': ['vim', 'python']}, set(('packages',)), ), ( 'list-comma-string-space', {'packages': {'type': 'list'}}, {'packages': 'vim, python'}, {'packages': ['vim', ' python']}, set(('packages',)), ), ( 'dict', {'user': {'type': 'dict'}}, { 'user': { 'first': 'rey', 'last': 'skywalker', } }, { 'user': { 'first': 'rey', 'last': 'skywalker', } }, set(('user',)), ), ( 'dict-k=v', {'user': {'type': 'dict'}}, {'user': 'first=rey,last=skywalker'}, { 'user': { 'first': 'rey', 'last': 'skywalker', } }, set(('user',)), ), ( 'dict-k=v-spaces', {'user': {'type': 'dict'}}, {'user': 'first=rey, last=skywalker'}, { 'user': { 'first': 'rey', 'last': 'skywalker', } }, set(('user',)), ), ( 'bool', { 'enabled': {'type': 'bool'}, 'disabled': {'type': 'bool'}, }, { 'enabled': True, 'disabled': False, }, { 'enabled': True, 'disabled': False, }, set(('enabled', 'disabled')), ), ( 'bool-ints', { 'enabled': {'type': 'bool'}, 'disabled': {'type': 'bool'}, }, { 'enabled': 1, 'disabled': 0, }, { 'enabled': True, 'disabled': False, }, set(('enabled', 'disabled')), ), ( 'bool-true-false', { 'enabled': {'type': 'bool'}, 'disabled': {'type': 'bool'}, }, { 'enabled': 'true', 'disabled': 'false', }, { 'enabled': True, 'disabled': False, }, set(('enabled', 'disabled')), ), ( 'bool-yes-no', { 'enabled': {'type': 'bool'}, 'disabled': {'type': 'bool'}, }, { 'enabled': 'yes', 'disabled': 'no', }, { 'enabled': True, 'disabled': False, }, set(('enabled', 'disabled')), ), ( 'bool-y-n', { 'enabled': {'type': 'bool'}, 'disabled': {'type': 'bool'}, }, { 'enabled': 'y', 'disabled': 'n', }, { 'enabled': True, 'disabled': False, }, set(('enabled', 'disabled')), ), ( 'bool-on-off', { 'enabled': {'type': 'bool'}, 'disabled': {'type': 'bool'}, }, { 'enabled': 'on', 'disabled': 'off', }, { 'enabled': True, 'disabled': False, }, set(('enabled', 'disabled')), ), ( 'bool-1-0', { 'enabled': {'type': 'bool'}, 'disabled': {'type': 'bool'}, }, { 'enabled': '1', 'disabled': '0', }, { 'enabled': True, 'disabled': False, }, set(('enabled', 'disabled')), ), ( 'bool-float', { 'enabled': {'type': 'bool'}, 'disabled': {'type': 'bool'}, }, { 'enabled': 1.0, 'disabled': 0.0, }, { 'enabled': True, 'disabled': False, }, set(('enabled', 'disabled')), ), ( 'float', {'digit': {'type': 'float'}}, {'digit': 3.14159}, {'digit': 3.14159}, set(('digit',)), ), ( 'float-str', {'digit': {'type': 'float'}}, {'digit': '3.14159'}, {'digit': 3.14159}, set(('digit',)), ), ( 'path', {'path': {'type': 'path'}}, {'path': '~/bin'}, {'path': '/home/ansible/bin'}, set(('path',)), ), ( 'raw', {'raw': {'type': 'raw'}}, {'raw': 0x644}, {'raw': 0x644}, set(('raw',)), ), ( 'bytes', {'bytes': {'type': 'bytes'}}, {'bytes': '2K'}, {'bytes': 2048}, set(('bytes',)), ), ( 'bits', {'bits': {'type': 'bits'}}, {'bits': '1Mb'}, {'bits': 1048576}, set(('bits',)), ), ( 'jsonarg', {'some_json': {'type': 'jsonarg'}}, {'some_json': '{"users": {"bob": {"role": "accountant"}}}'}, {'some_json': '{"users": {"bob": {"role": "accountant"}}}'}, set(('some_json',)), ), ( 'jsonarg-list', {'some_json': {'type': 'jsonarg'}}, {'some_json': ['one', 'two']}, {'some_json': '["one", "two"]'}, set(('some_json',)), ), ( 'jsonarg-dict', {'some_json': {'type': 'jsonarg'}}, {'some_json': {"users": {"bob": {"role": "accountant"}}}}, {'some_json': '{"users": {"bob": {"role": "accountant"}}}'}, set(('some_json',)), ), ( 'defaults', {'param': {'default': 'DEFAULT'}}, {}, {'param': 'DEFAULT'}, set(('param',)), ), ( 'elements', {'numbers': {'type': 'list', 'elements': 'int'}}, {'numbers': [55, 33, 34, '22']}, {'numbers': [55, 33, 34, 22]}, set(('numbers',)), ), ( 'aliases', {'src': {'aliases': ['path', 'source']}}, {'src': '/tmp'}, {'src': '/tmp'}, set(('src (path, source)',)), ) ] @pytest.mark.parametrize( ('arg_spec', 'parameters', 'expected', 'valid_params'), (i[1:] for i in VALID_SPECS), ids=[i[0] for i in VALID_SPECS] ) def test_valid_spec(arg_spec, parameters, expected, valid_params, mocker): mocker.patch('ansible.module_utils.common.validation.os.path.expanduser', return_value='/home/ansible/bin') mocker.patch('ansible.module_utils.common.validation.os.path.expandvars', return_value='/home/ansible/bin') v = ArgumentSpecValidator(arg_spec) result = v.validate(parameters) assert isinstance(result, ValidationResult) assert result.validated_parameters == expected assert result.unsupported_parameters == set() assert result.error_messages == [] assert v._valid_parameter_names == valid_params # Again to check caching assert v._valid_parameter_names == valid_params