From cf5ce972758f93cbc06feb465cc7b6c81b10ba3a Mon Sep 17 00:00:00 2001 From: Toshio Kuratomi Date: Wed, 15 Oct 2014 18:35:16 -0400 Subject: [PATCH] Somehow, git mv only rm'd test/v2 and didn't add v2/test --- v2/test/__init__.py | 0 v2/test/compat.py | 51 +++++++++++++ v2/test/errors/__init__.py | 18 +++++ v2/test/errors/test_errors.py | 48 +++++++++++++ v2/test/parsing/__init__.py | 16 +++++ v2/test/parsing/test_general.py | 102 ++++++++++++++++++++++++++ v2/test/parsing/test_mod_args.py | 104 +++++++++++++++++++++++++++ v2/test/parsing/test_mod_args.py.py3 | 104 +++++++++++++++++++++++++++ v2/test/parsing/yaml/__init__.py | 16 +++++ v2/test/parsing/yaml/test_yaml.py | 96 +++++++++++++++++++++++++ v2/test/playbook/__init__.py | 16 +++++ v2/test/playbook/test_task.py | 84 ++++++++++++++++++++++ v2/test/test.yml | 2 + 13 files changed, 657 insertions(+) create mode 100644 v2/test/__init__.py create mode 100644 v2/test/compat.py create mode 100644 v2/test/errors/__init__.py create mode 100644 v2/test/errors/test_errors.py create mode 100644 v2/test/parsing/__init__.py create mode 100644 v2/test/parsing/test_general.py create mode 100644 v2/test/parsing/test_mod_args.py create mode 100644 v2/test/parsing/test_mod_args.py.py3 create mode 100644 v2/test/parsing/yaml/__init__.py create mode 100644 v2/test/parsing/yaml/test_yaml.py create mode 100644 v2/test/playbook/__init__.py create mode 100644 v2/test/playbook/test_task.py create mode 100644 v2/test/test.yml diff --git a/v2/test/__init__.py b/v2/test/__init__.py new file mode 100644 index 00000000000..e69de29bb2d diff --git a/v2/test/compat.py b/v2/test/compat.py new file mode 100644 index 00000000000..6c122f2fad6 --- /dev/null +++ b/v2/test/compat.py @@ -0,0 +1,51 @@ +# (c) 2012-2014, Michael DeHaan +# +# This file is part of Ansible +# +# Ansible is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# Ansible is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with Ansible. If not, see . + +import unittest + +# +# Compat for python2.6 +# + +if sys.version_info < (2, 7): + try: + # Need unittest2 on python2.6 + import unittest2 as unittest + except ImportError: + print('You need unittest2 installed on python2.x') +else: + import unittest + + +# +# Compat for python2.7 +# + +# Could use the pypi mock library on py3 as well as py2. They are the same +try: + from unittest.mock import mock_open, patch +except ImportError: + # Python2 + from mock import mock_open, patch + +try: + import __builtin__ +except ImportError: + BUILTINS = 'builtins' +else: + BUILTINS = '__builtin__' + diff --git a/v2/test/errors/__init__.py b/v2/test/errors/__init__.py new file mode 100644 index 00000000000..674334b15a3 --- /dev/null +++ b/v2/test/errors/__init__.py @@ -0,0 +1,18 @@ +# (c) 2012-2014, Michael DeHaan +# +# This file is part of Ansible +# +# Ansible is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# Ansible is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with Ansible. If not, see . + + diff --git a/v2/test/errors/test_errors.py b/v2/test/errors/test_errors.py new file mode 100644 index 00000000000..ff3b562d25c --- /dev/null +++ b/v2/test/errors/test_errors.py @@ -0,0 +1,48 @@ +# (c) 2012-2014, Michael DeHaan +# +# This file is part of Ansible +# +# Ansible is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# Ansible is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with Ansible. If not, see . + +from ..compat import unittest + +from ansible.parsing.yaml.objects import AnsibleBaseYAMLObject +from ansible.errors import AnsibleError + +from .. compat import BUILTINS, mock_open, patch + +class TestErrors(unittest.TestCase): + + def setUp(self): + self.message = 'this is the error message' + + def tearDown(self): + pass + + def test_basic_error(self): + e = AnsibleError(self.message) + self.assertEqual(e.message, self.message) + + def test_error_with_object(self): + obj = AnsibleBaseYAMLObject() + obj._data_source = 'foo.yml' + obj._line_number = 1 + obj._column_number = 1 + + m = mock_open() + m.return_value.readlines.return_value = ['this is line 1\n', 'this is line 2\n', 'this is line 3\n'] + with patch('{0}.open'.format(BUILTINS), m): + e = AnsibleError(self.message, obj) + + self.assertEqual(e.message, 'this is the error message\nThe error occurred on line 1 of the file foo.yml:\nthis is line 1\n^') diff --git a/v2/test/parsing/__init__.py b/v2/test/parsing/__init__.py new file mode 100644 index 00000000000..1f84012e014 --- /dev/null +++ b/v2/test/parsing/__init__.py @@ -0,0 +1,16 @@ +# (c) 2012-2014, Michael DeHaan +# +# This file is part of Ansible +# +# Ansible is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# Ansible is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with Ansible. If not, see . diff --git a/v2/test/parsing/test_general.py b/v2/test/parsing/test_general.py new file mode 100644 index 00000000000..377aa886935 --- /dev/null +++ b/v2/test/parsing/test_general.py @@ -0,0 +1,102 @@ +# (c) 2012-2014, Michael DeHaan +# +# This file is part of Ansible +# +# Ansible is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# Ansible is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with Ansible. If not, see . + +from ..compat import unittest +from ansible.parsing import load +from ansible.errors import AnsibleParserError + +import json + +from io import FileIO + +class MockFile(FileIO): + + def __init__(self, ds, method='json'): + self.ds = ds + self.method = method + + def read(self): + if method == 'json': + return json.dumps(ds) + elif method == 'yaml': + return yaml.dumps(ds) + elif method == 'fail': + return """ + AAARGGGGH + THIS WON'T PARSE !!! + NOOOOOOOOOOOOOOOOOO + """ + else: + raise Exception("untestable serializer") + + def close(self): + pass + +class TestGeneralParsing(unittest.TestCase): + + def __init__(self): + pass + + def setUp(self): + pass + + def tearDown(self): + pass + + def parse_json_from_string(self): + input = """ + { + "asdf" : "1234", + "jkl" : 5678 + } + """ + output = load(input) + self.assertEqual(output['asdf'], '1234') + self.assertEqual(output['jkl'], 5678) + + def parse_json_from_file(self): + output = load(MockFile(dict(a=1,b=2,c=3)),'json') + self.assertEqual(ouput, dict(a=1,b=2,c=3)) + + def parse_yaml_from_dict(self): + input = """ + asdf: '1234' + jkl: 5678 + """ + output = load(input) + self.assertEqual(output['asdf'], '1234') + self.assertEqual(output['jkl'], 5678) + + def parse_yaml_from_file(self): + output = load(MockFile(dict(a=1,b=2,c=3),'yaml')) + self.assertEqual(output, dict(a=1,b=2,c=3)) + + def parse_fail(self): + input = """ + TEXT + *** + NOT VALID + """ + self.assertRaises(load(input), AnsibleParserError) + + def parse_fail_from_file(self): + self.assertRaises(load(MockFile(None,'fail')), AnsibleParserError) + + def parse_fail_invalid_type(self): + self.assertRaises(3000, AnsibleParsingError) + self.assertRaises(dict(a=1,b=2,c=3), AnsibleParserError) + diff --git a/v2/test/parsing/test_mod_args.py b/v2/test/parsing/test_mod_args.py new file mode 100644 index 00000000000..b52b6f9cc3e --- /dev/null +++ b/v2/test/parsing/test_mod_args.py @@ -0,0 +1,104 @@ +# (c) 2012-2014, Michael DeHaan +# +# This file is part of Ansible +# +# Ansible is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# Ansible is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with Ansible. If not, see . + +from ansible.parsing.mod_args import ModuleArgsParser + +from .. compat import CompatTestCase + +class TestModArgsDwim(CompatTestCase): + + # TODO: add tests that construct ModuleArgsParser with a task reference + # TODO: verify the AnsibleError raised on failure knows the task + # and the task knows the line numbers + + def setUp(self): + self.m = ModuleArgsParser() + pass + + def _debug(self, mod, args, to): + print("RETURNED module = {0}".format(mod)) + print(" args = {0}".format(args)) + print(" to = {0}".format(to)) + + def tearDown(self): + pass + + def test_basic_shell(self): + mod, args, to = self.m.parse(dict(shell='echo hi')) + self._debug(mod, args, to) + self.assertEqual(mod, 'command') + self.assertEqual(args, dict( + _raw_params = 'echo hi', + _uses_shell = True, + )) + self.assertIsNone(to) + + def test_basic_command(self): + mod, args, to = self.m.parse(dict(command='echo hi')) + self._debug(mod, args, to) + self.assertEqual(mod, 'command') + self.assertEqual(args, dict( + _raw_params = 'echo hi', + )) + self.assertIsNone(to) + + def test_shell_with_modifiers(self): + mod, args, to = self.m.parse(dict(shell='/bin/foo creates=/tmp/baz removes=/tmp/bleep')) + self._debug(mod, args, to) + self.assertEqual(mod, 'command') + self.assertEqual(args, dict( + creates = '/tmp/baz', + removes = '/tmp/bleep', + _raw_params = '/bin/foo', + _uses_shell = True, + )) + self.assertIsNone(to) + + def test_normal_usage(self): + mod, args, to = self.m.parse(dict(copy='src=a dest=b')) + self._debug(mod, args, to) + self.assertEqual(mod, 'copy') + self.assertEqual(args, dict(src='a', dest='b')) + self.assertIsNone(to) + + def test_complex_args(self): + mod, args, to = self.m.parse(dict(copy=dict(src='a', dest='b'))) + self._debug(mod, args, to) + self.assertEqual(mod, 'copy') + self.assertEqual(args, dict(src='a', dest='b')) + self.assertIsNone(to) + + def test_action_with_complex(self): + mod, args, to = self.m.parse(dict(action=dict(module='copy', src='a', dest='b'))) + self._debug(mod, args, to) + self.assertEqual(mod, 'copy') + self.assertEqual(args, dict(src='a', dest='b')) + self.assertIsNone(to) + + def test_action_with_complex_and_complex_args(self): + mod, args, to = self.m.parse(dict(action=dict(module='copy', args=dict(src='a', dest='b')))) + self._debug(mod, args, to) + self.assertEqual(mod, 'copy') + self.assertEqual(args, dict(src='a', dest='b')) + self.assertIsNone(to) + + def test_local_action_string(self): + mod, args, to = self.m.parse(dict(local_action='copy src=a dest=b')) + self._debug(mod, args, to) + self.assertEqual(mod, 'copy') + self.assertEqual(args, dict(src='a', dest='b')) + self.assertIs(to, 'localhost') diff --git a/v2/test/parsing/test_mod_args.py.py3 b/v2/test/parsing/test_mod_args.py.py3 new file mode 100644 index 00000000000..b52b6f9cc3e --- /dev/null +++ b/v2/test/parsing/test_mod_args.py.py3 @@ -0,0 +1,104 @@ +# (c) 2012-2014, Michael DeHaan +# +# This file is part of Ansible +# +# Ansible is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# Ansible is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with Ansible. If not, see . + +from ansible.parsing.mod_args import ModuleArgsParser + +from .. compat import CompatTestCase + +class TestModArgsDwim(CompatTestCase): + + # TODO: add tests that construct ModuleArgsParser with a task reference + # TODO: verify the AnsibleError raised on failure knows the task + # and the task knows the line numbers + + def setUp(self): + self.m = ModuleArgsParser() + pass + + def _debug(self, mod, args, to): + print("RETURNED module = {0}".format(mod)) + print(" args = {0}".format(args)) + print(" to = {0}".format(to)) + + def tearDown(self): + pass + + def test_basic_shell(self): + mod, args, to = self.m.parse(dict(shell='echo hi')) + self._debug(mod, args, to) + self.assertEqual(mod, 'command') + self.assertEqual(args, dict( + _raw_params = 'echo hi', + _uses_shell = True, + )) + self.assertIsNone(to) + + def test_basic_command(self): + mod, args, to = self.m.parse(dict(command='echo hi')) + self._debug(mod, args, to) + self.assertEqual(mod, 'command') + self.assertEqual(args, dict( + _raw_params = 'echo hi', + )) + self.assertIsNone(to) + + def test_shell_with_modifiers(self): + mod, args, to = self.m.parse(dict(shell='/bin/foo creates=/tmp/baz removes=/tmp/bleep')) + self._debug(mod, args, to) + self.assertEqual(mod, 'command') + self.assertEqual(args, dict( + creates = '/tmp/baz', + removes = '/tmp/bleep', + _raw_params = '/bin/foo', + _uses_shell = True, + )) + self.assertIsNone(to) + + def test_normal_usage(self): + mod, args, to = self.m.parse(dict(copy='src=a dest=b')) + self._debug(mod, args, to) + self.assertEqual(mod, 'copy') + self.assertEqual(args, dict(src='a', dest='b')) + self.assertIsNone(to) + + def test_complex_args(self): + mod, args, to = self.m.parse(dict(copy=dict(src='a', dest='b'))) + self._debug(mod, args, to) + self.assertEqual(mod, 'copy') + self.assertEqual(args, dict(src='a', dest='b')) + self.assertIsNone(to) + + def test_action_with_complex(self): + mod, args, to = self.m.parse(dict(action=dict(module='copy', src='a', dest='b'))) + self._debug(mod, args, to) + self.assertEqual(mod, 'copy') + self.assertEqual(args, dict(src='a', dest='b')) + self.assertIsNone(to) + + def test_action_with_complex_and_complex_args(self): + mod, args, to = self.m.parse(dict(action=dict(module='copy', args=dict(src='a', dest='b')))) + self._debug(mod, args, to) + self.assertEqual(mod, 'copy') + self.assertEqual(args, dict(src='a', dest='b')) + self.assertIsNone(to) + + def test_local_action_string(self): + mod, args, to = self.m.parse(dict(local_action='copy src=a dest=b')) + self._debug(mod, args, to) + self.assertEqual(mod, 'copy') + self.assertEqual(args, dict(src='a', dest='b')) + self.assertIs(to, 'localhost') diff --git a/v2/test/parsing/yaml/__init__.py b/v2/test/parsing/yaml/__init__.py new file mode 100644 index 00000000000..1f84012e014 --- /dev/null +++ b/v2/test/parsing/yaml/__init__.py @@ -0,0 +1,16 @@ +# (c) 2012-2014, Michael DeHaan +# +# This file is part of Ansible +# +# Ansible is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# Ansible is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with Ansible. If not, see . diff --git a/v2/test/parsing/yaml/test_yaml.py b/v2/test/parsing/yaml/test_yaml.py new file mode 100644 index 00000000000..b8d7771c7cb --- /dev/null +++ b/v2/test/parsing/yaml/test_yaml.py @@ -0,0 +1,96 @@ +# (c) 2012-2014, Michael DeHaan +# +# This file is part of Ansible +# +# Ansible is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# Ansible is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with Ansible. If not, see . + +from ..compat import unittest + +from yaml.scanner import ScannerError + +from ansible.parsing.yaml import safe_load +from ansible.parsing.yaml.objects import AnsibleMapping + +# a single dictionary instance +data1 = '''--- +key: value +''' + +# multiple dictionary instances +data2 = '''--- +- key1: value1 +- key2: value2 + +- key3: value3 + + +- key4: value4 +''' + +# multiple dictionary instances with other nested +# dictionaries contained within those +data3 = '''--- +- key1: + subkey1: subvalue1 + subkey2: subvalue2 + subkey3: + subsubkey1: subsubvalue1 +- key2: + subkey4: subvalue4 +- list1: + - list1key1: list1value1 + list1key2: list1value2 + list1key3: list1value3 +''' + +bad_data1 = '''--- +foo: bar + bam: baz +''' + +class TestSafeLoad(unittest.TestCase): + + def setUp(self): + pass + + def tearDown(self): + pass + + def test_safe_load_bad(self): + # test the loading of bad yaml data + self.assertRaises(ScannerError, safe_load, bad_data1) + + def test_safe_load(self): + # test basic dictionary + res = safe_load(data1) + self.assertEqual(type(res), AnsibleMapping) + self.assertEqual(res._line_number, 2) + + # test data with multiple dictionaries + res = safe_load(data2) + self.assertEqual(len(res), 4) + self.assertEqual(res[0]._line_number, 2) + self.assertEqual(res[1]._line_number, 3) + self.assertEqual(res[2]._line_number, 5) + self.assertEqual(res[3]._line_number, 8) + + # test data with multiple sub-dictionaries + res = safe_load(data3) + self.assertEqual(len(res), 3) + self.assertEqual(res[0]._line_number, 2) + self.assertEqual(res[1]._line_number, 7) + self.assertEqual(res[2]._line_number, 9) + self.assertEqual(res[0]['key1']._line_number, 3) + self.assertEqual(res[1]['key2']._line_number, 8) + self.assertEqual(res[2]['list1'][0]._line_number, 10) diff --git a/v2/test/playbook/__init__.py b/v2/test/playbook/__init__.py new file mode 100644 index 00000000000..1f84012e014 --- /dev/null +++ b/v2/test/playbook/__init__.py @@ -0,0 +1,16 @@ +# (c) 2012-2014, Michael DeHaan +# +# This file is part of Ansible +# +# Ansible is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# Ansible is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with Ansible. If not, see . diff --git a/v2/test/playbook/test_task.py b/v2/test/playbook/test_task.py new file mode 100644 index 00000000000..ec7ce9012e8 --- /dev/null +++ b/v2/test/playbook/test_task.py @@ -0,0 +1,84 @@ +# (c) 2012-2014, Michael DeHaan +# +# This file is part of Ansible +# +# Ansible is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# Ansible is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with Ansible. If not, see . + +from ansible.playbook.task import Task +from ..compat import unittest + +basic_shell_task = dict( + name = 'Test Task', + shell = 'echo hi' +) + +kv_shell_task = dict( + action = 'shell echo hi' +) + +class TestTask(unittest.TestCase): + + def setUp(self): + pass + + def tearDown(self): + pass + + def test_construct_empty_task(self): + t = Task() + + def test_construct_task_with_role(self): + pass + + def test_construct_task_with_block(self): + pass + + def test_construct_task_with_role_and_block(self): + pass + + def test_load_task_simple(self): + t = Task.load(basic_shell_task) + assert t is not None + self.assertEqual(t.name, basic_shell_task['name']) + self.assertEqual(t.action, 'command') + self.assertEqual(t.args, dict(_raw_params='echo hi', _uses_shell=True)) + + def test_load_task_kv_form(self): + t = Task.load(kv_shell_task) + print("task action is %s" % t.action) + self.assertEqual(t.action, 'command') + self.assertEqual(t.args, dict(_raw_params='echo hi', _uses_shell=True)) + + def test_task_auto_name(self): + assert 'name' not in kv_shell_task + t = Task.load(kv_shell_task) + #self.assertEqual(t.name, 'shell echo hi') + + def test_task_auto_name_with_role(self): + pass + + def test_load_task_complex_form(self): + pass + + def test_can_load_module_complex_form(self): + pass + + def test_local_action_implies_delegate(self): + pass + + def test_local_action_conflicts_with_delegate(self): + pass + + def test_delegate_to_parses(self): + pass diff --git a/v2/test/test.yml b/v2/test/test.yml new file mode 100644 index 00000000000..299b66610d1 --- /dev/null +++ b/v2/test/test.yml @@ -0,0 +1,2 @@ +- name: Test +filename: /usr/cafĂ©/˙/are_doing_this_to_me