diff options
Diffstat (limited to 'ansible_collections/community/sap_libs/tests')
34 files changed, 1715 insertions, 0 deletions
diff --git a/ansible_collections/community/sap_libs/tests/integration/__init__.py b/ansible_collections/community/sap_libs/tests/integration/__init__.py new file mode 100644 index 00000000..e69de29b --- /dev/null +++ b/ansible_collections/community/sap_libs/tests/integration/__init__.py diff --git a/ansible_collections/community/sap_libs/tests/integration/targets/__init__.py b/ansible_collections/community/sap_libs/tests/integration/targets/__init__.py new file mode 100644 index 00000000..e69de29b --- /dev/null +++ b/ansible_collections/community/sap_libs/tests/integration/targets/__init__.py diff --git a/ansible_collections/community/sap_libs/tests/sanity/__init__.py b/ansible_collections/community/sap_libs/tests/sanity/__init__.py new file mode 100644 index 00000000..e69de29b --- /dev/null +++ b/ansible_collections/community/sap_libs/tests/sanity/__init__.py diff --git a/ansible_collections/community/sap_libs/tests/sanity/ignore-2.10.txt b/ansible_collections/community/sap_libs/tests/sanity/ignore-2.10.txt new file mode 100644 index 00000000..89508ad7 --- /dev/null +++ b/ansible_collections/community/sap_libs/tests/sanity/ignore-2.10.txt @@ -0,0 +1,9 @@ +plugins/modules/sap_pyrfc.py validate-modules:missing-gplv3-license # Licensed under Apache 2.0 +plugins/modules/sap_company.py validate-modules:missing-gplv3-license # Licensed under Apache 2.0 +plugins/modules/sap_control_exec.py validate-modules:missing-gplv3-license # Licensed under Apache 2.0 +plugins/modules/sap_hdbsql.py validate-modules:missing-gplv3-license # Licensed under Apache 2.0 +plugins/modules/sap_snote.py validate-modules:missing-gplv3-license # Licensed under Apache 2.0 +plugins/modules/sap_system_facts.py validate-modules:missing-gplv3-license # Licensed under Apache 2.0 +plugins/modules/sap_task_list_execute.py validate-modules:missing-gplv3-license # Licensed under Apache 2.0 +plugins/modules/sap_user.py validate-modules:missing-gplv3-license # Licensed under Apache 2.0 +plugins/modules/sapcar_extract.py validate-modules:missing-gplv3-license # Licensed under Apache 2.0 diff --git a/ansible_collections/community/sap_libs/tests/sanity/ignore-2.11.txt b/ansible_collections/community/sap_libs/tests/sanity/ignore-2.11.txt new file mode 100644 index 00000000..89508ad7 --- /dev/null +++ b/ansible_collections/community/sap_libs/tests/sanity/ignore-2.11.txt @@ -0,0 +1,9 @@ +plugins/modules/sap_pyrfc.py validate-modules:missing-gplv3-license # Licensed under Apache 2.0 +plugins/modules/sap_company.py validate-modules:missing-gplv3-license # Licensed under Apache 2.0 +plugins/modules/sap_control_exec.py validate-modules:missing-gplv3-license # Licensed under Apache 2.0 +plugins/modules/sap_hdbsql.py validate-modules:missing-gplv3-license # Licensed under Apache 2.0 +plugins/modules/sap_snote.py validate-modules:missing-gplv3-license # Licensed under Apache 2.0 +plugins/modules/sap_system_facts.py validate-modules:missing-gplv3-license # Licensed under Apache 2.0 +plugins/modules/sap_task_list_execute.py validate-modules:missing-gplv3-license # Licensed under Apache 2.0 +plugins/modules/sap_user.py validate-modules:missing-gplv3-license # Licensed under Apache 2.0 +plugins/modules/sapcar_extract.py validate-modules:missing-gplv3-license # Licensed under Apache 2.0 diff --git a/ansible_collections/community/sap_libs/tests/sanity/ignore-2.12.txt b/ansible_collections/community/sap_libs/tests/sanity/ignore-2.12.txt new file mode 100644 index 00000000..3883757f --- /dev/null +++ b/ansible_collections/community/sap_libs/tests/sanity/ignore-2.12.txt @@ -0,0 +1,9 @@ +plugins/modules/sap_pyrfc.py validate-modules:missing-gplv3-license # Licensed under Apache 2.0 +plugins/modules/sap_company.py validate-modules:missing-gplv3-license # Licensed under Apache 2.0 +plugins/modules/sap_control_exec.py validate-modules:missing-gplv3-license # Licensed under Apache 2.0 +plugins/modules/sap_hdbsql.py validate-modules:missing-gplv3-license # Licensed under Apache 2.0 +plugins/modules/sap_snote.py validate-modules:missing-gplv3-license # Licensed under Apache 2.0 +plugins/modules/sap_system_facts.py validate-modules:missing-gplv3-license # Licensed under Apache 2.0 +plugins/modules/sap_task_list_execute.py validate-modules:missing-gplv3-license # Licensed under Apache 2.0 +plugins/modules/sap_user.py validate-modules:missing-gplv3-license # Licensed under Apache 2.0 +plugins/modules/sapcar_extract.py validate-modules:missing-gplv3-license # Licensed under Apache 2.0
\ No newline at end of file diff --git a/ansible_collections/community/sap_libs/tests/sanity/ignore-2.13.txt b/ansible_collections/community/sap_libs/tests/sanity/ignore-2.13.txt new file mode 100644 index 00000000..3883757f --- /dev/null +++ b/ansible_collections/community/sap_libs/tests/sanity/ignore-2.13.txt @@ -0,0 +1,9 @@ +plugins/modules/sap_pyrfc.py validate-modules:missing-gplv3-license # Licensed under Apache 2.0 +plugins/modules/sap_company.py validate-modules:missing-gplv3-license # Licensed under Apache 2.0 +plugins/modules/sap_control_exec.py validate-modules:missing-gplv3-license # Licensed under Apache 2.0 +plugins/modules/sap_hdbsql.py validate-modules:missing-gplv3-license # Licensed under Apache 2.0 +plugins/modules/sap_snote.py validate-modules:missing-gplv3-license # Licensed under Apache 2.0 +plugins/modules/sap_system_facts.py validate-modules:missing-gplv3-license # Licensed under Apache 2.0 +plugins/modules/sap_task_list_execute.py validate-modules:missing-gplv3-license # Licensed under Apache 2.0 +plugins/modules/sap_user.py validate-modules:missing-gplv3-license # Licensed under Apache 2.0 +plugins/modules/sapcar_extract.py validate-modules:missing-gplv3-license # Licensed under Apache 2.0
\ No newline at end of file diff --git a/ansible_collections/community/sap_libs/tests/sanity/ignore-2.14.txt b/ansible_collections/community/sap_libs/tests/sanity/ignore-2.14.txt new file mode 100644 index 00000000..3883757f --- /dev/null +++ b/ansible_collections/community/sap_libs/tests/sanity/ignore-2.14.txt @@ -0,0 +1,9 @@ +plugins/modules/sap_pyrfc.py validate-modules:missing-gplv3-license # Licensed under Apache 2.0 +plugins/modules/sap_company.py validate-modules:missing-gplv3-license # Licensed under Apache 2.0 +plugins/modules/sap_control_exec.py validate-modules:missing-gplv3-license # Licensed under Apache 2.0 +plugins/modules/sap_hdbsql.py validate-modules:missing-gplv3-license # Licensed under Apache 2.0 +plugins/modules/sap_snote.py validate-modules:missing-gplv3-license # Licensed under Apache 2.0 +plugins/modules/sap_system_facts.py validate-modules:missing-gplv3-license # Licensed under Apache 2.0 +plugins/modules/sap_task_list_execute.py validate-modules:missing-gplv3-license # Licensed under Apache 2.0 +plugins/modules/sap_user.py validate-modules:missing-gplv3-license # Licensed under Apache 2.0 +plugins/modules/sapcar_extract.py validate-modules:missing-gplv3-license # Licensed under Apache 2.0
\ No newline at end of file diff --git a/ansible_collections/community/sap_libs/tests/sanity/ignore-2.15.txt b/ansible_collections/community/sap_libs/tests/sanity/ignore-2.15.txt new file mode 100644 index 00000000..3883757f --- /dev/null +++ b/ansible_collections/community/sap_libs/tests/sanity/ignore-2.15.txt @@ -0,0 +1,9 @@ +plugins/modules/sap_pyrfc.py validate-modules:missing-gplv3-license # Licensed under Apache 2.0 +plugins/modules/sap_company.py validate-modules:missing-gplv3-license # Licensed under Apache 2.0 +plugins/modules/sap_control_exec.py validate-modules:missing-gplv3-license # Licensed under Apache 2.0 +plugins/modules/sap_hdbsql.py validate-modules:missing-gplv3-license # Licensed under Apache 2.0 +plugins/modules/sap_snote.py validate-modules:missing-gplv3-license # Licensed under Apache 2.0 +plugins/modules/sap_system_facts.py validate-modules:missing-gplv3-license # Licensed under Apache 2.0 +plugins/modules/sap_task_list_execute.py validate-modules:missing-gplv3-license # Licensed under Apache 2.0 +plugins/modules/sap_user.py validate-modules:missing-gplv3-license # Licensed under Apache 2.0 +plugins/modules/sapcar_extract.py validate-modules:missing-gplv3-license # Licensed under Apache 2.0
\ No newline at end of file diff --git a/ansible_collections/community/sap_libs/tests/sanity/ignore-2.9.txt b/ansible_collections/community/sap_libs/tests/sanity/ignore-2.9.txt new file mode 100644 index 00000000..89508ad7 --- /dev/null +++ b/ansible_collections/community/sap_libs/tests/sanity/ignore-2.9.txt @@ -0,0 +1,9 @@ +plugins/modules/sap_pyrfc.py validate-modules:missing-gplv3-license # Licensed under Apache 2.0 +plugins/modules/sap_company.py validate-modules:missing-gplv3-license # Licensed under Apache 2.0 +plugins/modules/sap_control_exec.py validate-modules:missing-gplv3-license # Licensed under Apache 2.0 +plugins/modules/sap_hdbsql.py validate-modules:missing-gplv3-license # Licensed under Apache 2.0 +plugins/modules/sap_snote.py validate-modules:missing-gplv3-license # Licensed under Apache 2.0 +plugins/modules/sap_system_facts.py validate-modules:missing-gplv3-license # Licensed under Apache 2.0 +plugins/modules/sap_task_list_execute.py validate-modules:missing-gplv3-license # Licensed under Apache 2.0 +plugins/modules/sap_user.py validate-modules:missing-gplv3-license # Licensed under Apache 2.0 +plugins/modules/sapcar_extract.py validate-modules:missing-gplv3-license # Licensed under Apache 2.0 diff --git a/ansible_collections/community/sap_libs/tests/unit/__init__.py b/ansible_collections/community/sap_libs/tests/unit/__init__.py new file mode 100644 index 00000000..e69de29b --- /dev/null +++ b/ansible_collections/community/sap_libs/tests/unit/__init__.py diff --git a/ansible_collections/community/sap_libs/tests/unit/compat/__init__.py b/ansible_collections/community/sap_libs/tests/unit/compat/__init__.py new file mode 100644 index 00000000..e69de29b --- /dev/null +++ b/ansible_collections/community/sap_libs/tests/unit/compat/__init__.py diff --git a/ansible_collections/community/sap_libs/tests/unit/compat/builtins.py b/ansible_collections/community/sap_libs/tests/unit/compat/builtins.py new file mode 100644 index 00000000..f60ee678 --- /dev/null +++ b/ansible_collections/community/sap_libs/tests/unit/compat/builtins.py @@ -0,0 +1,33 @@ +# (c) 2014, Toshio Kuratomi <tkuratomi@ansible.com> +# +# 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 <http://www.gnu.org/licenses/>. + +# Make coding more python3-ish +from __future__ import (absolute_import, division, print_function) +__metaclass__ = type + +# +# Compat for python2.7 +# + +# One unittest needs to import builtins via __import__() so we need to have +# the string that represents it +try: + import __builtin__ +except ImportError: + BUILTINS = 'builtins' +else: + BUILTINS = '__builtin__' diff --git a/ansible_collections/community/sap_libs/tests/unit/compat/mock.py b/ansible_collections/community/sap_libs/tests/unit/compat/mock.py new file mode 100644 index 00000000..0972cd2e --- /dev/null +++ b/ansible_collections/community/sap_libs/tests/unit/compat/mock.py @@ -0,0 +1,122 @@ +# (c) 2014, Toshio Kuratomi <tkuratomi@ansible.com> +# +# 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 <http://www.gnu.org/licenses/>. + +# Make coding more python3-ish +from __future__ import (absolute_import, division, print_function) +__metaclass__ = type + +''' +Compat module for Python3.x's unittest.mock module +''' +import sys + +# Python 2.7 + +# Note: Could use the pypi mock library on python3.x as well as python2.x. It +# is the same as the python3 stdlib mock library + +try: + # Allow wildcard import because we really do want to import all of mock's + # symbols into this compat shim + # pylint: disable=wildcard-import,unused-wildcard-import + from unittest.mock import * +except ImportError: + # Python 2 + # pylint: disable=wildcard-import,unused-wildcard-import + try: + from mock import * + except ImportError: + print('You need the mock library installed on python2.x to run tests') + + +# Prior to 3.4.4, mock_open cannot handle binary read_data +if sys.version_info >= (3,) and sys.version_info < (3, 4, 4): + file_spec = None + + def _iterate_read_data(read_data): + # Helper for mock_open: + # Retrieve lines from read_data via a generator so that separate calls to + # readline, read, and readlines are properly interleaved + sep = b'\n' if isinstance(read_data, bytes) else '\n' + data_as_list = [l + sep for l in read_data.split(sep)] + + if data_as_list[-1] == sep: + # If the last line ended in a newline, the list comprehension will have an + # extra entry that's just a newline. Remove this. + data_as_list = data_as_list[:-1] + else: + # If there wasn't an extra newline by itself, then the file being + # emulated doesn't have a newline to end the last line remove the + # newline that our naive format() added + data_as_list[-1] = data_as_list[-1][:-1] + + for line in data_as_list: + yield line + + def mock_open(mock=None, read_data=''): + """ + A helper function to create a mock to replace the use of `open`. It works + for `open` called directly or used as a context manager. + + The `mock` argument is the mock object to configure. If `None` (the + default) then a `MagicMock` will be created for you, with the API limited + to methods or attributes available on standard file handles. + + `read_data` is a string for the `read` methoddline`, and `readlines` of the + file handle to return. This is an empty string by default. + """ + def _readlines_side_effect(*args, **kwargs): + if handle.readlines.return_value is not None: + return handle.readlines.return_value + return list(_data) + + def _read_side_effect(*args, **kwargs): + if handle.read.return_value is not None: + return handle.read.return_value + return type(read_data)().join(_data) + + def _readline_side_effect(): + if handle.readline.return_value is not None: + while True: + yield handle.readline.return_value + for line in _data: + yield line + + global file_spec + if file_spec is None: + import _io + file_spec = list(set(dir(_io.TextIOWrapper)).union(set(dir(_io.BytesIO)))) + + if mock is None: + mock = MagicMock(name='open', spec=open) + + handle = MagicMock(spec=file_spec) + handle.__enter__.return_value = handle + + _data = _iterate_read_data(read_data) + + handle.write.return_value = None + handle.read.return_value = None + handle.readline.return_value = None + handle.readlines.return_value = None + + handle.read.side_effect = _read_side_effect + handle.readline.side_effect = _readline_side_effect() + handle.readlines.side_effect = _readlines_side_effect + + mock.return_value = handle + return mock diff --git a/ansible_collections/community/sap_libs/tests/unit/compat/unittest.py b/ansible_collections/community/sap_libs/tests/unit/compat/unittest.py new file mode 100644 index 00000000..98f08ad6 --- /dev/null +++ b/ansible_collections/community/sap_libs/tests/unit/compat/unittest.py @@ -0,0 +1,38 @@ +# (c) 2014, Toshio Kuratomi <tkuratomi@ansible.com> +# +# 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 <http://www.gnu.org/licenses/>. + +# Make coding more python3-ish +from __future__ import (absolute_import, division, print_function) +__metaclass__ = type + +''' +Compat module for Python2.7's unittest module +''' + +import sys + +# Allow wildcard import because we really do want to import all of +# unittests's symbols into this compat shim +# pylint: disable=wildcard-import,unused-wildcard-import +if sys.version_info < (2, 7): + try: + # Need unittest2 on python2.6 + from unittest2 import * + except ImportError: + print('You need unittest2 installed on python2.6.x to run tests') +else: + from unittest import * diff --git a/ansible_collections/community/sap_libs/tests/unit/mock/__init__.py b/ansible_collections/community/sap_libs/tests/unit/mock/__init__.py new file mode 100644 index 00000000..e69de29b --- /dev/null +++ b/ansible_collections/community/sap_libs/tests/unit/mock/__init__.py diff --git a/ansible_collections/community/sap_libs/tests/unit/mock/loader.py b/ansible_collections/community/sap_libs/tests/unit/mock/loader.py new file mode 100644 index 00000000..5389bdcb --- /dev/null +++ b/ansible_collections/community/sap_libs/tests/unit/mock/loader.py @@ -0,0 +1,102 @@ +# (c) 2012-2014, Michael DeHaan <michael.dehaan@gmail.com> +# +# 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 os + +from ansible.errors import AnsibleParserError +from ansible.parsing.dataloader import DataLoader +from ansible.module_utils.common.text.converters import to_bytes, to_text + + +class DictDataLoader(DataLoader): + + def __init__(self, file_mapping=None): + file_mapping = {} if file_mapping is None else file_mapping + assert type(file_mapping) == dict + + super(DictDataLoader, self).__init__() + + self._file_mapping = file_mapping + self._build_known_directories() + self._vault_secrets = None + + def load_from_file(self, path, cache=True, unsafe=False): + path = to_text(path) + if path in self._file_mapping: + return self.load(self._file_mapping[path], path) + return None + + # TODO: the real _get_file_contents returns a bytestring, so we actually convert the + # unicode/text it's created with to utf-8 + def _get_file_contents(self, file_name): + path = to_text(file_name) + if path in self._file_mapping: + return (to_bytes(self._file_mapping[path]), False) + else: + raise AnsibleParserError("file not found: %s" % path) + + def path_exists(self, path): + path = to_text(path) + return path in self._file_mapping or path in self._known_directories + + def is_file(self, path): + path = to_text(path) + return path in self._file_mapping + + def is_directory(self, path): + path = to_text(path) + return path in self._known_directories + + def list_directory(self, path): + ret = [] + path = to_text(path) + for x in (list(self._file_mapping.keys()) + self._known_directories): + if x.startswith(path): + if os.path.dirname(x) == path: + ret.append(os.path.basename(x)) + return ret + + def is_executable(self, path): + # FIXME: figure out a way to make paths return true for this + return False + + def _add_known_directory(self, directory): + if directory not in self._known_directories: + self._known_directories.append(directory) + + def _build_known_directories(self): + self._known_directories = [] + for path in self._file_mapping: + dirname = os.path.dirname(path) + while dirname not in ('/', ''): + self._add_known_directory(dirname) + dirname = os.path.dirname(dirname) + + def push(self, path, content): + rebuild_dirs = False + if path not in self._file_mapping: + rebuild_dirs = True + + self._file_mapping[path] = content + + if rebuild_dirs: + self._build_known_directories() + + def pop(self, path): + if path in self._file_mapping: + del self._file_mapping[path] + self._build_known_directories() + + def clear(self): + self._file_mapping = dict() + self._known_directories = [] + + def get_basedir(self): + return os.getcwd() + + def set_vault_secrets(self, vault_secrets): + self._vault_secrets = vault_secrets diff --git a/ansible_collections/community/sap_libs/tests/unit/mock/path.py b/ansible_collections/community/sap_libs/tests/unit/mock/path.py new file mode 100644 index 00000000..c1c075bc --- /dev/null +++ b/ansible_collections/community/sap_libs/tests/unit/mock/path.py @@ -0,0 +1,8 @@ +from __future__ import (absolute_import, division, print_function) +__metaclass__ = type + +from ansible_collections.community.general.tests.unit.compat.mock import MagicMock +from ansible.utils.path import unfrackpath + + +mock_unfrackpath_noop = MagicMock(spec_set=unfrackpath, side_effect=lambda x, *args, **kwargs: x) diff --git a/ansible_collections/community/sap_libs/tests/unit/mock/procenv.py b/ansible_collections/community/sap_libs/tests/unit/mock/procenv.py new file mode 100644 index 00000000..5673863e --- /dev/null +++ b/ansible_collections/community/sap_libs/tests/unit/mock/procenv.py @@ -0,0 +1,76 @@ +# (c) 2016, Matt Davis <mdavis@ansible.com> +# (c) 2016, Toshio Kuratomi <tkuratomi@ansible.com> +# +# 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 sys +import json + +from contextlib import contextmanager +from io import BytesIO, StringIO +from ansible_collections.community.general.tests.unit.compat import unittest +from ansible.module_utils.six import PY3 +from ansible.module_utils.common.text.converters import to_bytes + + +@contextmanager +def swap_stdin_and_argv(stdin_data='', argv_data=tuple()): + """ + context manager that temporarily masks the test runner's values for stdin and argv + """ + real_stdin = sys.stdin + real_argv = sys.argv + + if PY3: + fake_stream = StringIO(stdin_data) + fake_stream.buffer = BytesIO(to_bytes(stdin_data)) + else: + fake_stream = BytesIO(to_bytes(stdin_data)) + + try: + sys.stdin = fake_stream + sys.argv = argv_data + + yield + finally: + sys.stdin = real_stdin + sys.argv = real_argv + + +@contextmanager +def swap_stdout(): + """ + context manager that temporarily replaces stdout for tests that need to verify output + """ + old_stdout = sys.stdout + + if PY3: + fake_stream = StringIO() + else: + fake_stream = BytesIO() + + try: + sys.stdout = fake_stream + + yield fake_stream + finally: + sys.stdout = old_stdout + + +class ModuleTestCase(unittest.TestCase): + def setUp(self, module_args=None): + if module_args is None: + module_args = {'_ansible_remote_tmp': '/tmp', '_ansible_keep_remote_files': False} + + args = json.dumps(dict(ANSIBLE_MODULE_ARGS=module_args)) + + # unittest doesn't have a clean place to use a context manager, so we have to enter/exit manually + self.stdin_swap = swap_stdin_and_argv(stdin_data=args) + self.stdin_swap.__enter__() + + def tearDown(self): + # unittest doesn't have a clean place to use a context manager, so we have to enter/exit manually + self.stdin_swap.__exit__(None, None, None) diff --git a/ansible_collections/community/sap_libs/tests/unit/mock/vault_helper.py b/ansible_collections/community/sap_libs/tests/unit/mock/vault_helper.py new file mode 100644 index 00000000..6bd2db9c --- /dev/null +++ b/ansible_collections/community/sap_libs/tests/unit/mock/vault_helper.py @@ -0,0 +1,27 @@ +# 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 + +from ansible.module_utils.common.text.converters import to_bytes + +from ansible.parsing.vault import VaultSecret + + +class TextVaultSecret(VaultSecret): + '''A secret piece of text. ie, a password. Tracks text encoding. + + The text encoding of the text may not be the default text encoding so + we keep track of the encoding so we encode it to the same bytes.''' + + def __init__(self, text, encoding=None, errors=None, _bytes=None): + super(TextVaultSecret, self).__init__() + self.text = text + self.encoding = encoding or 'utf-8' + self._bytes = _bytes + self.errors = errors or 'strict' + + @property + def bytes(self): + '''The text encoded with encoding, unless we specifically set _bytes.''' + return self._bytes or to_bytes(self.text, encoding=self.encoding, errors=self.errors) diff --git a/ansible_collections/community/sap_libs/tests/unit/mock/yaml_helper.py b/ansible_collections/community/sap_libs/tests/unit/mock/yaml_helper.py new file mode 100644 index 00000000..a646c024 --- /dev/null +++ b/ansible_collections/community/sap_libs/tests/unit/mock/yaml_helper.py @@ -0,0 +1,126 @@ +# 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 io +import yaml + +from ansible.module_utils.six import PY3 +from ansible.parsing.yaml.loader import AnsibleLoader +from ansible.parsing.yaml.dumper import AnsibleDumper + + +class YamlTestUtils(object): + """Mixin class to combine with a unittest.TestCase subclass.""" + def _loader(self, stream): + """Vault related tests will want to override this. + + Vault cases should setup a AnsibleLoader that has the vault password.""" + return AnsibleLoader(stream) + + def _dump_stream(self, obj, stream, dumper=None): + """Dump to a py2-unicode or py3-string stream.""" + if PY3: + return yaml.dump(obj, stream, Dumper=dumper) + else: + return yaml.dump(obj, stream, Dumper=dumper, encoding=None) + + def _dump_string(self, obj, dumper=None): + """Dump to a py2-unicode or py3-string""" + if PY3: + return yaml.dump(obj, Dumper=dumper) + else: + return yaml.dump(obj, Dumper=dumper, encoding=None) + + def _dump_load_cycle(self, obj): + # Each pass though a dump or load revs the 'generation' + # obj to yaml string + string_from_object_dump = self._dump_string(obj, dumper=AnsibleDumper) + + # wrap a stream/file like StringIO around that yaml + stream_from_object_dump = io.StringIO(string_from_object_dump) + loader = self._loader(stream_from_object_dump) + # load the yaml stream to create a new instance of the object (gen 2) + obj_2 = loader.get_data() + + # dump the gen 2 objects directory to strings + string_from_object_dump_2 = self._dump_string(obj_2, + dumper=AnsibleDumper) + + # The gen 1 and gen 2 yaml strings + self.assertEqual(string_from_object_dump, string_from_object_dump_2) + # the gen 1 (orig) and gen 2 py object + self.assertEqual(obj, obj_2) + + # again! gen 3... load strings into py objects + stream_3 = io.StringIO(string_from_object_dump_2) + loader_3 = self._loader(stream_3) + obj_3 = loader_3.get_data() + + string_from_object_dump_3 = self._dump_string(obj_3, dumper=AnsibleDumper) + + self.assertEqual(obj, obj_3) + # should be transitive, but... + self.assertEqual(obj_2, obj_3) + self.assertEqual(string_from_object_dump, string_from_object_dump_3) + + def _old_dump_load_cycle(self, obj): + '''Dump the passed in object to yaml, load it back up, dump again, compare.''' + stream = io.StringIO() + + yaml_string = self._dump_string(obj, dumper=AnsibleDumper) + self._dump_stream(obj, stream, dumper=AnsibleDumper) + + yaml_string_from_stream = stream.getvalue() + + # reset stream + stream.seek(0) + + loader = self._loader(stream) + # loader = AnsibleLoader(stream, vault_password=self.vault_password) + obj_from_stream = loader.get_data() + + stream_from_string = io.StringIO(yaml_string) + loader2 = self._loader(stream_from_string) + # loader2 = AnsibleLoader(stream_from_string, vault_password=self.vault_password) + obj_from_string = loader2.get_data() + + stream_obj_from_stream = io.StringIO() + stream_obj_from_string = io.StringIO() + + if PY3: + yaml.dump(obj_from_stream, stream_obj_from_stream, Dumper=AnsibleDumper) + yaml.dump(obj_from_stream, stream_obj_from_string, Dumper=AnsibleDumper) + else: + yaml.dump(obj_from_stream, stream_obj_from_stream, Dumper=AnsibleDumper, encoding=None) + yaml.dump(obj_from_stream, stream_obj_from_string, Dumper=AnsibleDumper, encoding=None) + + yaml_string_stream_obj_from_stream = stream_obj_from_stream.getvalue() + yaml_string_stream_obj_from_string = stream_obj_from_string.getvalue() + + stream_obj_from_stream.seek(0) + stream_obj_from_string.seek(0) + + if PY3: + yaml_string_obj_from_stream = yaml.dump(obj_from_stream, Dumper=AnsibleDumper) + yaml_string_obj_from_string = yaml.dump(obj_from_string, Dumper=AnsibleDumper) + else: + yaml_string_obj_from_stream = yaml.dump(obj_from_stream, Dumper=AnsibleDumper, encoding=None) + yaml_string_obj_from_string = yaml.dump(obj_from_string, Dumper=AnsibleDumper, encoding=None) + + assert yaml_string == yaml_string_obj_from_stream + assert yaml_string == yaml_string_obj_from_stream == yaml_string_obj_from_string + assert (yaml_string == yaml_string_obj_from_stream == yaml_string_obj_from_string == yaml_string_stream_obj_from_stream == + yaml_string_stream_obj_from_string) + assert obj == obj_from_stream + assert obj == obj_from_string + assert obj == yaml_string_obj_from_stream + assert obj == yaml_string_obj_from_string + assert obj == obj_from_stream == obj_from_string == yaml_string_obj_from_stream == yaml_string_obj_from_string + return {'obj': obj, + 'yaml_string': yaml_string, + 'yaml_string_from_stream': yaml_string_from_stream, + 'obj_from_stream': obj_from_stream, + 'obj_from_string': obj_from_string, + 'yaml_string_obj_from_string': yaml_string_obj_from_string} diff --git a/ansible_collections/community/sap_libs/tests/unit/plugins/__init__.py b/ansible_collections/community/sap_libs/tests/unit/plugins/__init__.py new file mode 100644 index 00000000..e69de29b --- /dev/null +++ b/ansible_collections/community/sap_libs/tests/unit/plugins/__init__.py diff --git a/ansible_collections/community/sap_libs/tests/unit/plugins/modules/__init__.py b/ansible_collections/community/sap_libs/tests/unit/plugins/modules/__init__.py new file mode 100644 index 00000000..e69de29b --- /dev/null +++ b/ansible_collections/community/sap_libs/tests/unit/plugins/modules/__init__.py diff --git a/ansible_collections/community/sap_libs/tests/unit/plugins/modules/test_sap_company.py b/ansible_collections/community/sap_libs/tests/unit/plugins/modules/test_sap_company.py new file mode 100644 index 00000000..b6b7dd11 --- /dev/null +++ b/ansible_collections/community/sap_libs/tests/unit/plugins/modules/test_sap_company.py @@ -0,0 +1,136 @@ +# 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 sys +from ansible_collections.community.sap_libs.tests.unit.compat.mock import patch, MagicMock +from ansible_collections.community.sap_libs.tests.unit.plugins.modules.utils import AnsibleExitJson, AnsibleFailJson, ModuleTestCase, set_module_args + +sys.modules['pyrfc'] = MagicMock() +sys.modules['pyrfc.Connection'] = MagicMock() + +from ansible_collections.community.sap_libs.plugins.modules import sap_company + + +class TestSAPRfcModule(ModuleTestCase): + + def setUp(self): + super(TestSAPRfcModule, self).setUp() + self.module = sap_company + + def tearDown(self): + super(TestSAPRfcModule, self).tearDown() + + def define_rfc_connect(self, mocker): + return mocker.patch(self.module.call_rfc_method) + + def test_without_required_parameters(self): + """Failure must occurs when all parameters are missing""" + with self.assertRaises(AnsibleFailJson): + set_module_args({}) + self.module.main() + + def test_error_user_create(self): + """test fail to create company""" + + set_module_args({ + "conn_username": "DDIC", + "conn_password": "Test1234", + "host": "10.1.8.9", + "company_id": "Comp_ID", + "name": "Test_comp", + "name_2": "LTD", + "country": "DE", + "time_zone": "UTC", + "city": "City", + "post_code": "12345", + "street": "test_street", + "street_no": "1", + "e_mail": "test@test.de", + }) + with patch.object(self.module, 'call_rfc_method') as RAW: + RAW.return_value = {'RETURN': [{'FIELD': '', 'ID': '01', 'LOG_MSG_NO': '000000', + 'LOG_NO': '', 'MESSAGE': 'Something went wrong', 'MESSAGE_V1': 'ADMIN', + 'MESSAGE_V2': '', 'MESSAGE_V3': '', 'MESSAGE_V4': '', 'NUMBER': '199', + 'PARAMETER': '', 'ROW': 0, 'SYSTEM': '', 'TYPE': 'E'}]} + + with self.assertRaises(AnsibleFailJson) as result: + sap_company.main() + self.assertEqual(result.exception.args[0]['msg'], 'Something went wrong') + + def test_success(self): + """test execute company create success""" + + set_module_args({ + "conn_username": "DDIC", + "conn_password": "Test1234", + "host": "10.1.8.9", + "company_id": "Comp_ID", + "name": "Test_comp", + "name_2": "LTD", + "country": "DE", + "time_zone": "UTC", + "city": "City", + "post_code": "12345", + "street": "test_street", + "street_no": "1", + "e_mail": "test@test.de", + }) + with patch.object(self.module, 'call_rfc_method') as RAW: + RAW.return_value = {'RETURN': [{'FIELD': '', 'ID': '01', 'LOG_MSG_NO': '000000', + 'LOG_NO': '', 'MESSAGE': 'Company address COMP_ID created', 'MESSAGE_V1': 'ADMIN', + 'MESSAGE_V2': '', 'MESSAGE_V3': '', 'MESSAGE_V4': '', 'NUMBER': '102', + 'PARAMETER': '', 'ROW': 0, 'SYSTEM': '', 'TYPE': 'S'}]} + + with self.assertRaises(AnsibleExitJson) as result: + sap_company.main() + self.assertEqual(result.exception.args[0]['msg'], 'Company address COMP_ID created') + + def test_no_changes(self): + """test execute company no changes""" + + set_module_args({ + "conn_username": "DDIC", + "conn_password": "Test1234", + "host": "10.1.8.9", + "company_id": "Comp_ID", + "name": "Test_comp", + "name_2": "LTD", + "country": "DE", + "time_zone": "UTC", + "city": "City", + "post_code": "12345", + "street": "test_street", + "street_no": "1", + "e_mail": "test@test.de", + }) + with patch.object(self.module, 'call_rfc_method') as RAW: + RAW.return_value = {'RETURN': [{'FIELD': '', 'ID': '01', 'LOG_MSG_NO': '000000', + 'LOG_NO': '', 'MESSAGE': 'Company address COMP_ID changed', 'MESSAGE_V1': 'ADMIN', + 'MESSAGE_V2': '', 'MESSAGE_V3': '', 'MESSAGE_V4': '', 'NUMBER': '079', + 'PARAMETER': '', 'ROW': 0, 'SYSTEM': '', 'TYPE': 'S'}]} + + with self.assertRaises(AnsibleExitJson) as result: + sap_company.main() + self.assertEqual(result.exception.args[0]['msg'], 'No changes where made.') + + def test_absent(self): + """test execute company delete success""" + + set_module_args({ + "state": "absent", + "conn_username": "DDIC", + "conn_password": "Test1234", + "host": "10.1.8.9", + "company_id": "Comp_ID", + }) + with patch.object(self.module, 'call_rfc_method') as RAW: + RAW.return_value = {'RETURN': [{'FIELD': '', 'ID': '01', 'LOG_MSG_NO': '000000', + 'LOG_NO': '', 'MESSAGE': 'Company address COMP_ID deleted', 'MESSAGE_V1': 'ADMIN', + 'MESSAGE_V2': '', 'MESSAGE_V3': '', 'MESSAGE_V4': '', 'NUMBER': '080', + 'PARAMETER': '', 'ROW': 0, 'SYSTEM': '', 'TYPE': 'S'}]} + + with self.assertRaises(AnsibleExitJson) as result: + sap_company.main() + self.assertEqual(result.exception.args[0]['msg'], 'Company address COMP_ID deleted') diff --git a/ansible_collections/community/sap_libs/tests/unit/plugins/modules/test_sap_control_exec.py b/ansible_collections/community/sap_libs/tests/unit/plugins/modules/test_sap_control_exec.py new file mode 100644 index 00000000..272beaf4 --- /dev/null +++ b/ansible_collections/community/sap_libs/tests/unit/plugins/modules/test_sap_control_exec.py @@ -0,0 +1,129 @@ +# 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 sys +from ansible_collections.community.sap_libs.tests.unit.compat.mock import patch, MagicMock, Mock +from ansible_collections.community.sap_libs.tests.unit.plugins.modules.utils import AnsibleExitJson, AnsibleFailJson, ModuleTestCase, set_module_args + +sys.modules['suds.client'] = MagicMock() +sys.modules['suds.sudsobject'] = MagicMock() +sys.modules['suds'] = MagicMock() + +from ansible_collections.community.sap_libs.plugins.modules import sap_control_exec + + +class TestSapcontrolModule(ModuleTestCase): + + def setUp(self): + super(TestSapcontrolModule, self).setUp() + self.module = sap_control_exec + + def tearDown(self): + super(TestSapcontrolModule, self).tearDown() + + def define_rfc_connect(self, mocker): + return mocker.patch(self.module.call_rfc_method) + + def test_without_required_parameters(self): + """Failure must occurs when all parameters are missing""" + with self.assertRaises(AnsibleFailJson): + set_module_args({}) + self.module.main() + + def test_error_module_not_found(self): + """tests fail module error""" + + set_module_args({ + "hostname": "192.168.8.15", + "sysnr": "01", + "function": "GetProcessList" + }) + with self.assertRaises(AnsibleFailJson) as result: + self.module.HAS_SUDS_LIBRARY = False + self.module.SUDS_LIBRARY_IMPORT_ERROR = 'Module not found' + self.module.main() + self.assertEqual(result.exception.args[0]['exception'], 'Module not found') + + def test_error_connection(self): + """tests fail module exception""" + + set_module_args({ + "hostname": "192.168.8.15", + "sysnr": "01", + "function": "GetProcessList" + }) + with self.assertRaises(AnsibleFailJson) as result: + self.module.Client.side_effect = Mock(side_effect=Exception('Test')) + self.module.main() + self.assertEqual(result.exception.args[0]['msg'], 'Something went wrong connecting to the SAPCONTROL SOAP API.') + + def test_error_port_sysnr(self): + """tests fail multi provide parameters""" + + set_module_args({ + "hostname": "192.168.8.15", + "sysnr": "01", + "port": "50113", + "function": "GetProcessList" + }) + with self.assertRaises(AnsibleFailJson) as result: + self.module.main() + self.assertEqual(result.exception.args[0]['msg'], 'parameters are mutually exclusive: sysnr|port') + + def test_error_missing_force(self): + """tests fail missing force""" + + set_module_args({ + "hostname": "192.168.8.15", + "sysnr": "01", + "function": "Stop" + }) + + with self.assertRaises(AnsibleFailJson) as result: + self.module.main() + self.assertEqual(result.exception.args[0]['msg'], 'Stop function requires force: True') + + def test_success_sysnr(self): + """test success with sysnr""" + + set_module_args({ + "hostname": "192.168.8.15", + "sysnr": "01", + "function": "GetProcessList" + }) + with patch.object(self.module, 'recursive_dict') as ret: + ret.return_value = {'item': [{'name': 'hdbdaemon', 'value': '1'}]} + with self.assertRaises(AnsibleExitJson) as result: + self.module.main() + self.assertEqual(result.exception.args[0]['out'], [{'item': [{'name': 'hdbdaemon', 'value': '1'}]}]) + + def test_success_port(self): + """test success with port""" + + set_module_args({ + "hostname": "192.168.8.15", + "port": "50113", + "function": "GetProcessList" + }) + with patch.object(self.module, 'recursive_dict') as ret: + ret.return_value = {'item': [{'name': 'hdbdaemon', 'value': '1'}]} + with self.assertRaises(AnsibleExitJson) as result: + self.module.main() + self.assertEqual(result.exception.args[0]['out'], [{'item': [{'name': 'hdbdaemon', 'value': '1'}]}]) + + def test_success_string(self): + """test success with sysnr""" + + set_module_args({ + "hostname": "192.168.8.15", + "sysnr": "01", + "function": "ParameterValue", + "parameter": "ztta/short_area" + }) + with patch.object(self.module, 'connection') as ret: + ret.return_value = '1600000' + with self.assertRaises(AnsibleExitJson) as result: + self.module.main() + self.assertEqual(result.exception.args[0]['out'], ['1600000']) diff --git a/ansible_collections/community/sap_libs/tests/unit/plugins/modules/test_sap_hdbsql.py b/ansible_collections/community/sap_libs/tests/unit/plugins/modules/test_sap_hdbsql.py new file mode 100644 index 00000000..2232273f --- /dev/null +++ b/ansible_collections/community/sap_libs/tests/unit/plugins/modules/test_sap_hdbsql.py @@ -0,0 +1,102 @@ +# -*- coding: utf-8 -*- + +# Copyright: (c) 2021, Rainer Leber (@rainerleber) <rainerleber@gmail.com> +# 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 + +from ansible_collections.community.sap_libs.plugins.modules import sap_hdbsql +from ansible_collections.community.sap_libs.tests.unit.plugins.modules.utils import ( + AnsibleExitJson, + AnsibleFailJson, + ModuleTestCase, + set_module_args, +) +from ansible_collections.community.sap_libs.tests.unit.compat.mock import patch +from ansible.module_utils import basic + + +def get_bin_path(*args, **kwargs): + """Function to return path of hdbsql""" + return "/usr/sap/HDB/HDB01/exe/hdbsql" + + +class Testsap_hdbsql(ModuleTestCase): + """Main class for testing sap_hdbsql module.""" + + def setUp(self): + """Setup.""" + super(Testsap_hdbsql, self).setUp() + self.module = sap_hdbsql + self.mock_get_bin_path = patch.object(basic.AnsibleModule, 'get_bin_path', get_bin_path) + self.mock_get_bin_path.start() + self.addCleanup(self.mock_get_bin_path.stop) # ensure that the patching is 'undone' + + def tearDown(self): + """Teardown.""" + super(Testsap_hdbsql, self).tearDown() + + def test_without_required_parameters(self): + """Failure must occurs when all parameters are missing.""" + with self.assertRaises(AnsibleFailJson): + set_module_args({}) + self.module.main() + + def test_sap_hdbsql(self): + """Check that result is processed.""" + set_module_args({ + 'sid': "HDB", + 'instance': "01", + 'encrypted': False, + 'host': "localhost", + 'user': "SYSTEM", + 'password': "1234Qwer", + 'database': "HDB", + 'query': "SELECT * FROM users;" + }) + with patch.object(basic.AnsibleModule, 'run_command') as run_command: + run_command.return_value = 0, 'username,name\n testuser,test user \n myuser, my user \n', '' + with self.assertRaises(AnsibleExitJson) as result: + sap_hdbsql.main() + self.assertEqual(result.exception.args[0]['query_result'], [[ + {'username': 'testuser', 'name': 'test user'}, + {'username': 'myuser', 'name': 'my user'}, + ]]) + self.assertEqual(run_command.call_count, 1) + + def test_hana_userstore_query(self): + """Check that result is processed with userstore.""" + set_module_args({ + 'sid': "HDB", + 'instance': "01", + 'encrypted': False, + 'host': "localhost", + 'user': "SYSTEM", + 'userstore': True, + 'database': "HDB", + 'query': "SELECT * FROM users;" + }) + with patch.object(basic.AnsibleModule, 'run_command') as run_command: + run_command.return_value = 0, 'username,name\n testuser,test user \n myuser, my user \n', '' + with self.assertRaises(AnsibleExitJson) as result: + sap_hdbsql.main() + self.assertEqual(result.exception.args[0]['query_result'], [[ + {'username': 'testuser', 'name': 'test user'}, + {'username': 'myuser', 'name': 'my user'}, + ]]) + self.assertEqual(run_command.call_count, 1) + + def test_hana_failed_no_passwd(self): + """Check that result is failed with no password.""" + with self.assertRaises(AnsibleFailJson): + set_module_args({ + 'sid': "HDB", + 'instance': "01", + 'encrypted': False, + 'host': "localhost", + 'user': "SYSTEM", + 'database': "HDB", + 'query': "SELECT * FROM users;" + }) + self.module.main() diff --git a/ansible_collections/community/sap_libs/tests/unit/plugins/modules/test_sap_pyrfc.py b/ansible_collections/community/sap_libs/tests/unit/plugins/modules/test_sap_pyrfc.py new file mode 100644 index 00000000..2e206b36 --- /dev/null +++ b/ansible_collections/community/sap_libs/tests/unit/plugins/modules/test_sap_pyrfc.py @@ -0,0 +1,76 @@ +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# http://www.apache.org/licenses/LICENSE-2.0 +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +from __future__ import (absolute_import, division, print_function) + +__metaclass__ = type + +import sys +from ansible_collections.community.sap_libs.tests.unit.compat.mock import patch, MagicMock +from ansible_collections.community.sap_libs.tests.unit.plugins.modules.utils import AnsibleExitJson, AnsibleFailJson, ModuleTestCase, set_module_args + +sys.modules['pyrfc'] = MagicMock() +sys.modules['pyrfc.Connection'] = MagicMock() +from ansible_collections.community.sap_libs.plugins.modules import sap_pyrfc + + +class TestSAPRfcModule(ModuleTestCase): + + def setUp(self): + super(TestSAPRfcModule, self).setUp() + self.module = sap_pyrfc + + def tearDown(self): + super(TestSAPRfcModule, self).tearDown() + + def test_without_required_parameters(self): + """Failure must occurs when all parameters are missing""" + with self.assertRaises(AnsibleFailJson): + set_module_args({}) + self.module.main() + + def test_error_module_not_found(self): + """tests fail module error""" + + set_module_args({ + "function": "STFC_CONNECTION", + "parameters": {"REQUTEXT": "Hello SAP!"}, + "connection": {"ashost": "s4hana.poc.cloud", + "sysnr": "01", + "client": "400", + "user": "DDIC", + "passwd": "Password1", + "lang": "EN"} + }) + + with self.assertRaises(AnsibleFailJson) as result: + self.module.HAS_PYRFC_LIBRARY = False + self.module.PYRFC_LIBRARY_IMPORT_ERROR = 'Module not found' + self.module.main() + self.assertEqual( + result.exception.args[0]['exception'], 'Module not found') + + def test_success_communication(self): + """tests success""" + set_module_args({ + "function": "STFC_CONNECTION", + "parameters": {"REQUTEXT": "Hello SAP!"}, + "connection": {"ashost": "s4hana.poc.cloud", + "sysnr": "01", + "client": "400", + "user": "DDIC", + "passwd": "Password1", + "lang": "EN"} + }) + with patch.object(self.module, 'get_connection') as patch_call: + patch_call.call.return_value = 'Patched' + with self.assertRaises(AnsibleExitJson) as result: + self.module.main() + self.assertEqual(result.exception.args[0]['changed'], True) diff --git a/ansible_collections/community/sap_libs/tests/unit/plugins/modules/test_sap_snote.py b/ansible_collections/community/sap_libs/tests/unit/plugins/modules/test_sap_snote.py new file mode 100644 index 00000000..95ce6df3 --- /dev/null +++ b/ansible_collections/community/sap_libs/tests/unit/plugins/modules/test_sap_snote.py @@ -0,0 +1,181 @@ +# 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 sys +from ansible_collections.community.sap_libs.tests.unit.compat.mock import patch, MagicMock, Mock +from ansible_collections.community.sap_libs.tests.unit.plugins.modules.utils import AnsibleExitJson, AnsibleFailJson, ModuleTestCase, set_module_args + +sys.modules['pyrfc'] = MagicMock() +sys.modules['pyrfc.Connection'] = MagicMock() + +from ansible_collections.community.sap_libs.plugins.modules import sap_snote + + +class TestSAPRfcModule(ModuleTestCase): + + def setUp(self): + super(TestSAPRfcModule, self).setUp() + self.module = sap_snote + + def tearDown(self): + super(TestSAPRfcModule, self).tearDown() + + def define_rfc_connect(self, mocker): + return mocker.patch(self.module.call_rfc_method) + + def test_without_required_parameters(self): + """Failure must occurs when all parameters are missing""" + with self.assertRaises(AnsibleFailJson): + set_module_args({}) + self.module.main() + + def test_error_module_not_found(self): + """tests fail module error""" + + set_module_args({ + "conn_username": "ADMIN", + "conn_password": "Test1234", + "host": "10.1.8.9", + "snote_path": "/user/sap/trans/temp/000123456.txt" + }) + with self.assertRaises(AnsibleFailJson) as result: + self.module.HAS_PYRFC_LIBRARY = False + self.module.ANOTHER_LIBRARY_IMPORT_ERROR = 'Module not found' + self.module.main() + self.assertEqual(result.exception.args[0]['exception'], 'Module not found') + + def test_error_connection(self): + """tests fail module error""" + + set_module_args({ + "conn_username": "ADMIN", + "conn_password": "Test1234", + "host": "10.1.8.9", + "snote_path": "/user/sap/trans/temp/000123456.txt" + }) + with self.assertRaises(AnsibleFailJson) as result: + self.module.Connection.side_effect = Mock(side_effect=Exception('Test')) + self.module.main() + self.assertEqual(result.exception.args[0]['msg'], 'Something went wrong connecting to the SAP system.') + + def test_error_wrong_path(self): + """tests fail wrong path extension""" + + set_module_args({ + "conn_username": "ADMIN", + "conn_password": "Test1234", + "host": "10.1.8.9", + "snote_path": "/user/sap/trans/temp/000123456_00.tx" + }) + + with self.assertRaises(AnsibleFailJson) as result: + self.module.main() + self.assertEqual(result.exception.args[0]['msg'], 'The path must include the extracted snote file and ends with txt.') + + def test_error_wrong_user(self): + """tests fail wrong path extension""" + + set_module_args({ + "conn_username": "DDIC", + "conn_password": "Test1234", + "host": "10.1.8.9", + "snote_path": "/user/sap/trans/temp/000123456_00.tx" + }) + + with self.assertRaises(AnsibleFailJson) as result: + self.module.main() + self.assertEqual(result.exception.args[0]['msg'], 'User C(DDIC) or C(SAP*) not allowed for this operation.') + + def test_success_absent(self): + """test absent execute snote""" + + set_module_args({ + "conn_username": "ADMIN", + "conn_password": "Test1234", + "host": "10.1.8.9", + "state": "absent", + "snote_path": "/user/sap/trans/temp/000123456.txt" + }) + with patch.object(self.module, 'call_rfc_method') as call: + call.return_value = {'EV_RC': 0} + with self.assertRaises(AnsibleExitJson) as result: + with patch.object(self.module, 'check_implementation') as check: + check.side_effect = [True, False] + self.module.main() + self.assertEqual(result.exception.args[0]['msg'], 'SNOTE "000123456" deimplemented.') + + def test_success_absent_snot_only(self): + """test absent execute snote""" + + set_module_args({ + "conn_username": "ADMIN", + "conn_password": "Test1234", + "host": "10.1.8.9", + "state": "absent", + "snote": "000123456" + }) + with patch.object(self.module, 'call_rfc_method') as call: + call.return_value = {'EV_RC': 0} + with self.assertRaises(AnsibleExitJson) as result: + with patch.object(self.module, 'check_implementation') as check: + check.side_effect = [True, False] + self.module.main() + self.assertEqual(result.exception.args[0]['msg'], 'SNOTE "000123456" deimplemented.') + + def test_nothing_to_do(self): + """test nothing to do""" + + set_module_args({ + "conn_username": "ADMIN", + "conn_password": "Test1234", + "host": "10.1.8.9", + "state": "present", + "snote_path": "/user/sap/trans/temp/000123456.txt" + }) + with patch.object(self.module, 'check_implementation') as check: + check.return_value = True + with self.assertRaises(AnsibleExitJson) as result: + self.module.main() + self.assertEqual(result.exception.args[0]['msg'], 'Nothing to do.') + + def test_success_present_with_copy(self): + """test present execute snote""" + + set_module_args({ + "conn_username": "ADMIN", + "conn_password": "Test1234", + "host": "10.1.8.9", + "state": "present", + "snote_path": "/user/sap/trans/temp/000123456.txt" + }) + with patch.object(self.module, 'call_rfc_method') as call: + call.return_value = {'EV_RC': 0} + with self.assertRaises(AnsibleExitJson) as result: + with patch.object(self.module, 'check_implementation') as check: + check.side_effect = [False, True] + with patch.object(self.module, 'call_rfc_method') as callrfc: + callrfc.side_effect = [{'EV_RC': 0}, {'EV_RC': 0}, {'ET_MANUAL_ACTIVITIES': ''}] + self.module.main() + self.assertEqual(result.exception.args[0]['msg'], 'SNOTE "000123456" implemented.') + + def test_success_present_implement_only(self): + """test present implement snote""" + + set_module_args({ + "conn_username": "ADMIN", + "conn_password": "Test1234", + "host": "10.1.8.9", + "state": "present", + "snote": "000123456" + }) + with patch.object(self.module, 'call_rfc_method') as call: + call.return_value = {'EV_RC': 0} + with self.assertRaises(AnsibleExitJson) as result: + with patch.object(self.module, 'check_implementation') as check: + check.side_effect = [False, True] + with patch.object(self.module, 'call_rfc_method') as callrfc: + callrfc.side_effect = [{'EV_RC': 0}, {'ET_MANUAL_ACTIVITIES': ''}] + self.module.main() + self.assertEqual(result.exception.args[0]['msg'], 'SNOTE "000123456" implemented.') diff --git a/ansible_collections/community/sap_libs/tests/unit/plugins/modules/test_sap_system_facts.py b/ansible_collections/community/sap_libs/tests/unit/plugins/modules/test_sap_system_facts.py new file mode 100644 index 00000000..85a57aa7 --- /dev/null +++ b/ansible_collections/community/sap_libs/tests/unit/plugins/modules/test_sap_system_facts.py @@ -0,0 +1,106 @@ +# -*- coding: utf-8 -*- + +# Copyright: (c) 2021, Rainer Leber (@rainerleber) <rainerleber@gmail.com> +# 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 + +import mock +__metaclass__ = type + +from ansible_collections.community.sap_libs.plugins.modules import sap_system_facts +from ansible_collections.community.sap_libs.tests.unit.plugins.modules.utils import AnsibleExitJson, ModuleTestCase +from ansible_collections.community.sap_libs.tests.unit.compat.mock import patch, MagicMock +from ansible.module_utils import basic + + +def get_bin_path(*args, **kwargs): + """Function to return path of sapcontrol""" + return "/usr/sap/hostctrl/exe/sapcontrol" + + +class Testsap_system_facts(ModuleTestCase): + """Main class for testing sap_system_facts module.""" + + def setUp(self): + """Setup.""" + super(Testsap_system_facts, self).setUp() + self.module = sap_system_facts + self.mock_get_bin_path = patch.object(basic.AnsibleModule, 'get_bin_path', get_bin_path) + self.mock_get_bin_path.start() + self.addCleanup(self.mock_get_bin_path.stop) + + def tearDown(self): + """Teardown.""" + super(Testsap_system_facts, self).tearDown() + + def test_no_systems_available(self): + """No SAP Systems""" + with self.assertRaises(AnsibleExitJson) as result: + self.module.main() + self.assertEqual(result.exception.args[0]['ansible_facts'], {}) + + def test_sap_system_facts_all(self): + """Check that result is changed when all is one system.""" + with patch.object(self.module, 'get_all_hana_sid') as get_all_hana_sid: + get_all_hana_sid.return_value = ['HDB'] + with patch.object(self.module, 'get_hana_nr') as get_hana_nr: + get_hana_nr.return_value = [{"InstanceType": "HANA", "NR": "01", "SID": "HDB", "TYPE": "HDB"}] + with patch.object(self.module, 'get_all_nw_sid') as get_all_nw_sid: + get_all_nw_sid.return_value = ['ABC'] + with patch.object(self.module, 'get_nw_nr') as get_nw_nr: + get_nw_nr.return_value = [{"InstanceType": "NW", "NR": "00", "SID": "ABC", "TYPE": "ASCS"}, + {"InstanceType": "NW", "NR": "01", "SID": "ABC", "TYPE": "PAS"}] + with self.assertRaises(AnsibleExitJson) as result: + self.module.main() + self.assertEqual(result.exception.args[0]['ansible_facts'], {'sap': [{"InstanceType": "HANA", "NR": "01", "SID": "HDB", "TYPE": "HDB"}, + {"InstanceType": "NW", "NR": "00", "SID": "ABC", "TYPE": "ASCS"}, + {"InstanceType": "NW", "NR": "01", "SID": "ABC", "TYPE": "PAS"}]}) + + def test_sap_system_facts_command_hana(self): + """Check that result for HANA is correct.""" + with patch.object(self.module, 'get_all_hana_sid') as mock_all_hana_sid: + mock_all_hana_sid.return_value = ['HDB'] + with patch.object(self.module.os, 'listdir') as mock_listdir: + mock_listdir.return_value = ['HDB01'] + with patch.object(basic.AnsibleModule, 'run_command') as run_command: + run_command.return_value = [0, '', ''] + with self.assertRaises(AnsibleExitJson) as result: + self.module.main() + self.assertEqual(result.exception.args[0]['ansible_facts'], {'sap': [{"InstanceType": "HANA", "NR": "01", "SID": "HDB", "TYPE": "HDB"}]}) + + def test_sap_system_facts_pas_nw(self): + """Check that result for NW is correct.""" + with patch.object(self.module, 'get_all_nw_sid') as mock_all_nw_sid: + mock_all_nw_sid.return_value = ['ABC'] + with patch.object(self.module.os, 'listdir') as mock_listdir: + mock_listdir.return_value = ['D00'] + with patch.object(basic.AnsibleModule, 'run_command') as run_command: + run_command.return_value = [0, 'SAP\nINSTANCE_NAME, Attribute, D00\nSAP', ''] + with self.assertRaises(AnsibleExitJson) as result: + self.module.main() + self.assertEqual(result.exception.args[0]['ansible_facts'], {'sap': [{'InstanceType': 'NW', 'NR': '00', 'SID': 'ABC', 'TYPE': 'PAS'}]}) + + def test_sap_system_facts_future_nw(self): + """Check that future apps for NW are correct handled.""" + with patch.object(self.module, 'get_all_nw_sid') as mock_all_nw_sid: + mock_all_nw_sid.return_value = ['ABC'] + with patch.object(self.module.os, 'listdir') as mock_listdir: + mock_listdir.return_value = ['XY00'] + with patch.object(basic.AnsibleModule, 'run_command') as run_command: + run_command.return_value = [0, 'SAP\nINSTANCE_NAME, Attribute, XY00\nSAP', ''] + with self.assertRaises(AnsibleExitJson) as result: + self.module.main() + self.assertEqual(result.exception.args[0]['ansible_facts'], {'sap': [{'InstanceType': 'NW', 'NR': '00', 'SID': 'ABC', 'TYPE': 'XXX'}]}) + + def test_sap_system_facts_wd_nw(self): + """Check that WD for NW is correct handled.""" + with patch.object(self.module, 'get_all_nw_sid') as mock_all_nw_sid: + mock_all_nw_sid.return_value = ['ABC'] + with patch.object(self.module.os, 'listdir') as mock_listdir: + mock_listdir.return_value = ['WD80'] + with patch.object(basic.AnsibleModule, 'run_command') as run_command: + run_command.return_value = [0, 'SAP\nINSTANCE_NAME, Attribute, WD80\nSAP', ''] + with self.assertRaises(AnsibleExitJson) as result: + self.module.main() + self.assertEqual(result.exception.args[0]['ansible_facts'], {'sap': [{'InstanceType': 'NW', 'NR': '80', 'SID': 'ABC', 'TYPE': 'WebDisp'}]}) diff --git a/ansible_collections/community/sap_libs/tests/unit/plugins/modules/test_sap_task_list_execute.py b/ansible_collections/community/sap_libs/tests/unit/plugins/modules/test_sap_task_list_execute.py new file mode 100644 index 00000000..a7ac42e5 --- /dev/null +++ b/ansible_collections/community/sap_libs/tests/unit/plugins/modules/test_sap_task_list_execute.py @@ -0,0 +1,89 @@ +# 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 sys +from ansible_collections.community.sap_libs.tests.unit.compat.mock import patch, MagicMock +from ansible_collections.community.sap_libs.tests.unit.plugins.modules.utils import AnsibleExitJson, AnsibleFailJson, ModuleTestCase, set_module_args + +sys.modules['pyrfc'] = MagicMock() +sys.modules['pyrfc.Connection'] = MagicMock() +sys.modules['xmltodict'] = MagicMock() +sys.modules['xmltodict.parse'] = MagicMock() + +from ansible_collections.community.sap_libs.plugins.modules import sap_task_list_execute + + +class TestSAPRfcModule(ModuleTestCase): + + def setUp(self): + super(TestSAPRfcModule, self).setUp() + self.module = sap_task_list_execute + + def tearDown(self): + super(TestSAPRfcModule, self).tearDown() + + def define_rfc_connect(self, mocker): + return mocker.patch(self.module.call_rfc_method) + + def test_without_required_parameters(self): + """Failure must occurs when all parameters are missing""" + with self.assertRaises(AnsibleFailJson): + set_module_args({}) + self.module.main() + + def test_error_no_task_list(self): + """tests fail to exec task list""" + + set_module_args({ + "conn_username": "DDIC", + "conn_password": "Test1234", + "host": "10.1.8.9", + "task_to_execute": "SAP_BASIS_SSL_CHECK" + }) + + with patch.object(self.module, 'Connection') as conn: + conn.return_value = '' + with self.assertRaises(AnsibleFailJson) as result: + self.module.main() + self.assertEqual(result.exception.args[0]['msg'], 'The task list does not exist.') + + def test_success(self): + """test execute task list success""" + + set_module_args({ + "conn_username": "DDIC", + "conn_password": "Test1234", + "host": "10.1.8.9", + "task_to_execute": "SAP_BASIS_SSL_CHECK" + }) + with patch.object(self.module, 'xml_to_dict') as XML: + XML.return_value = {'item': [{'TASK': {'CHECK_STATUS_DESCR': 'Check successfully', + 'STATUS_DESCR': 'Executed successfully', 'TASKNAME': 'CL_STCT_CHECK_SEC_CRYPTO', + 'LNR': '1', 'DESCRIPTION': 'Check SAP Cryptographic Library', 'DOCU_EXIST': 'X', + 'LOG_EXIST': 'X', 'ACTION_SKIP': None, 'ACTION_UNSKIP': None, 'ACTION_CONFIRM': None, + 'ACTION_MAINTAIN': None}}]} + + with self.assertRaises(AnsibleExitJson) as result: + sap_task_list_execute.main() + self.assertEqual(result.exception.args[0]['out'], {'item': [{'TASK': {'CHECK_STATUS_DESCR': 'Check successfully', + 'STATUS_DESCR': 'Executed successfully', 'TASKNAME': 'CL_STCT_CHECK_SEC_CRYPTO', + 'LNR': '1', 'DESCRIPTION': 'Check SAP Cryptographic Library', 'DOCU_EXIST': 'X', + 'LOG_EXIST': 'X', 'ACTION_SKIP': None, 'ACTION_UNSKIP': None, + 'ACTION_CONFIRM': None, 'ACTION_MAINTAIN': None}}]}) + + def test_success_no_log(self): + """test execute task list success without logs""" + + set_module_args({ + "conn_username": "DDIC", + "conn_password": "Test1234", + "host": "10.1.8.9", + "task_to_execute": "SAP_BASIS_SSL_CHECK" + }) + with patch.object(self.module, 'xml_to_dict') as XML: + XML.return_value = "No logs available." + with self.assertRaises(AnsibleExitJson) as result: + sap_task_list_execute.main() + self.assertEqual(result.exception.args[0]['out'], 'No logs available.') diff --git a/ansible_collections/community/sap_libs/tests/unit/plugins/modules/test_sap_user.py b/ansible_collections/community/sap_libs/tests/unit/plugins/modules/test_sap_user.py new file mode 100644 index 00000000..51f57d94 --- /dev/null +++ b/ansible_collections/community/sap_libs/tests/unit/plugins/modules/test_sap_user.py @@ -0,0 +1,189 @@ +# 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 sys +from ansible_collections.community.sap_libs.tests.unit.compat.mock import patch, MagicMock +from ansible_collections.community.sap_libs.tests.unit.plugins.modules.utils import AnsibleExitJson, AnsibleFailJson, ModuleTestCase, set_module_args + +sys.modules['pyrfc'] = MagicMock() +sys.modules['pyrfc.Connection'] = MagicMock() + +from ansible_collections.community.sap_libs.plugins.modules import sap_user + + +class TestSAPRfcModule(ModuleTestCase): + + def setUp(self): + super(TestSAPRfcModule, self).setUp() + self.module = sap_user + + def tearDown(self): + super(TestSAPRfcModule, self).tearDown() + + def define_rfc_connect(self, mocker): + return mocker.patch(self.module.call_rfc_method) + + def test_without_required_parameters(self): + """Failure must occurs when all parameters are missing""" + with self.assertRaises(AnsibleFailJson): + set_module_args({}) + self.module.main() + + def test_error_user_create(self): + """test fail to create user""" + + set_module_args({ + "conn_username": "DDIC", + "conn_password": "Test1234", + "host": "10.1.8.9", + "username": "ADMIN", + "firstname": "first_admin", + "lastname": "last_admin", + "email": "admin@test.de", + "password": "Test123456", + "useralias": "ADMIN", + "company": "DEFAULT_COMPANY" + }) + + with patch.object(self.module, 'check_user') as check: + check.return_value = False + + with patch.object(self.module, 'call_rfc_method') as RAW: + RAW.return_value = {'RETURN': [{'FIELD': 'BNAME', 'ID': '01', 'LOG_MSG_NO': '000000', + 'LOG_NO': '', 'MESSAGE': 'Something went wrong', 'MESSAGE_V1': 'ADMIN', + 'MESSAGE_V2': '', 'MESSAGE_V3': '', 'MESSAGE_V4': '', 'NUMBER': '199', + 'PARAMETER': '', 'ROW': 0, 'SYSTEM': '', 'TYPE': 'E'}]} + + with self.assertRaises(AnsibleFailJson) as result: + sap_user.main() + self.assertEqual(result.exception.args[0]['msg'], 'Something went wrong') + + def test_success(self): + """test execute user create success""" + + set_module_args({ + "conn_username": "DDIC", + "conn_password": "Test1234", + "host": "10.1.8.9", + "username": "ADMIN", + "firstname": "first_admin", + "lastname": "last_admin", + "email": "admin@test.de", + "password": "Test123456", + "useralias": "ADMIN", + "company": "DEFAULT_COMPANY" + }) + with patch.object(self.module, 'check_user') as check: + check.return_value = False + + with patch.object(self.module, 'call_rfc_method') as RAW: + RAW.return_value = {'RETURN': [{'FIELD': 'BNAME', 'ID': '01', 'LOG_MSG_NO': '000000', + 'LOG_NO': '', 'MESSAGE': 'User ADMIN created', 'MESSAGE_V1': 'ADMIN', + 'MESSAGE_V2': '', 'MESSAGE_V3': '', 'MESSAGE_V4': '', 'NUMBER': '102', + 'PARAMETER': '', 'ROW': 0, 'SYSTEM': '', 'TYPE': 'S'}]} + + with self.assertRaises(AnsibleExitJson) as result: + sap_user.main() + self.assertEqual(result.exception.args[0]['msg'], 'User ADMIN created') + + def test_no_changes(self): + """test execute user no changes""" + + set_module_args({ + "conn_username": "DDIC", + "conn_password": "Test1234", + "host": "10.1.8.9", + "username": "ADMIN", + "firstname": "first_admin", + "lastname": "last_admin", + "email": "admin@test.de", + "password": "Test123456", + "useralias": "ADMIN", + "company": "DEFAULT_COMPANY" + }) + with patch.object(self.module, 'check_user') as check: + check.return_value = True + + with patch.object(self.module, 'call_rfc_method') as RAW: + RAW.return_value = {'RETURN': [{'FIELD': 'BNAME', 'ID': '01', 'LOG_MSG_NO': '000000', + 'LOG_NO': '', 'MESSAGE': '', 'MESSAGE_V1': 'ADMIN', + 'MESSAGE_V2': '', 'MESSAGE_V3': '', 'MESSAGE_V4': '', 'NUMBER': '029', + 'PARAMETER': '', 'ROW': 0, 'SYSTEM': '', 'TYPE': 'S'}]} + + with patch.object(self.module, 'all') as DETAIL: + DETAIL.return_value = True + + with self.assertRaises(AnsibleExitJson) as result: + sap_user.main() + self.assertEqual(result.exception.args[0]['msg'], 'No changes where made.') + + def test_absent(self): + """test execute user delete success""" + + set_module_args({ + "state": "absent", + "conn_username": "DDIC", + "conn_password": "Test1234", + "host": "10.1.8.9", + "username": "ADMIN", + }) + with patch.object(self.module, 'check_user') as check: + check.return_value = True + + with patch.object(self.module, 'call_rfc_method') as RAW: + RAW.return_value = {'RETURN': [{'FIELD': 'BNAME', 'ID': '01', 'LOG_MSG_NO': '000000', + 'LOG_NO': '', 'MESSAGE': 'User ADMIN deleted', 'MESSAGE_V1': 'ADMIN', + 'MESSAGE_V2': '', 'MESSAGE_V3': '', 'MESSAGE_V4': '', 'NUMBER': '102', + 'PARAMETER': '', 'ROW': 0, 'SYSTEM': '', 'TYPE': 'S'}]} + + with self.assertRaises(AnsibleExitJson) as result: + sap_user.main() + self.assertEqual(result.exception.args[0]['msg'], 'User ADMIN deleted') + + def test_lock(self): + """test execute user lock success""" + + set_module_args({ + "state": "lock", + "conn_username": "DDIC", + "conn_password": "Test1234", + "host": "10.1.8.9", + "username": "ADMIN", + }) + with patch.object(self.module, 'check_user') as check: + check.return_value = True + + with patch.object(self.module, 'call_rfc_method') as RAW: + RAW.return_value = {'RETURN': [{'FIELD': 'BNAME', 'ID': '01', 'LOG_MSG_NO': '000000', + 'LOG_NO': '', 'MESSAGE': 'User ADMIN locked', 'MESSAGE_V1': 'ADMIN', + 'MESSAGE_V2': '', 'MESSAGE_V3': '', 'MESSAGE_V4': '', 'NUMBER': '206', + 'PARAMETER': '', 'ROW': 0, 'SYSTEM': '', 'TYPE': 'S'}]} + + with self.assertRaises(AnsibleExitJson) as result: + sap_user.main() + self.assertEqual(result.exception.args[0]['msg'], 'User ADMIN locked') + + def test_unlock(self): + """test execute user lock success""" + + set_module_args({ + "state": "lock", + "conn_username": "DDIC", + "conn_password": "Test1234", + "host": "10.1.8.9", + "username": "ADMIN", + }) + with patch.object(self.module, 'check_user') as check: + check.return_value = True + + with patch.object(self.module, 'call_rfc_method') as RAW: + RAW.return_value = {'RETURN': [{'FIELD': 'BNAME', 'ID': '01', 'LOG_MSG_NO': '000000', + 'LOG_NO': '', 'MESSAGE': 'User ADMIN unlocked', 'MESSAGE_V1': 'ADMIN', + 'MESSAGE_V2': '', 'MESSAGE_V3': '', 'MESSAGE_V4': '', 'NUMBER': '210', + 'PARAMETER': '', 'ROW': 0, 'SYSTEM': '', 'TYPE': 'S'}]} + + with self.assertRaises(AnsibleExitJson) as result: + sap_user.main() + self.assertEqual(result.exception.args[0]['msg'], 'User ADMIN unlocked') diff --git a/ansible_collections/community/sap_libs/tests/unit/plugins/modules/test_sapcar_extract.py b/ansible_collections/community/sap_libs/tests/unit/plugins/modules/test_sapcar_extract.py new file mode 100644 index 00000000..77695e40 --- /dev/null +++ b/ansible_collections/community/sap_libs/tests/unit/plugins/modules/test_sapcar_extract.py @@ -0,0 +1,53 @@ +# -*- coding: utf-8 -*- + +# Copyright: (c) 2021, Rainer Leber (@rainerleber) <rainerleber@gmail.com> +# 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 + +from ansible_collections.community.sap_libs.plugins.modules import sapcar_extract +from ansible_collections.community.sap_libs.tests.unit.plugins.modules.utils import AnsibleExitJson, AnsibleFailJson, ModuleTestCase, set_module_args +from ansible_collections.community.sap_libs.tests.unit.compat.mock import patch +from ansible.module_utils import basic + + +def get_bin_path(*args, **kwargs): + """Function to return path of SAPCAR""" + return "/tmp/sapcar" + + +class Testsapcar_extract(ModuleTestCase): + """Main class for testing sapcar_extract module.""" + + def setUp(self): + """Setup.""" + super(Testsapcar_extract, self).setUp() + self.module = sapcar_extract + self.mock_get_bin_path = patch.object(basic.AnsibleModule, 'get_bin_path', get_bin_path) + self.mock_get_bin_path.start() + self.addCleanup(self.mock_get_bin_path.stop) # ensure that the patching is 'undone' + + def tearDown(self): + """Teardown.""" + super(Testsapcar_extract, self).tearDown() + + def test_without_required_parameters(self): + """Failure must occurs when all parameters are missing.""" + with self.assertRaises(AnsibleFailJson): + set_module_args({}) + self.module.main() + + def test_sapcar_extract(self): + """Check that result is changed.""" + set_module_args({ + 'path': "/tmp/HANA_CLIENT_REV2_00_053_00_LINUX_X86_64.SAR", + 'dest': "/tmp/test2", + 'binary_path': "/tmp/sapcar" + }) + with patch.object(basic.AnsibleModule, 'run_command') as run_command: + run_command.return_value = 0, '', '' # successful execution, no output + with self.assertRaises(AnsibleExitJson) as result: + sapcar_extract.main() + self.assertTrue(result.exception.args[0]['changed']) + self.assertEqual(run_command.call_count, 1) diff --git a/ansible_collections/community/sap_libs/tests/unit/plugins/modules/utils.py b/ansible_collections/community/sap_libs/tests/unit/plugins/modules/utils.py new file mode 100644 index 00000000..5a8ec563 --- /dev/null +++ b/ansible_collections/community/sap_libs/tests/unit/plugins/modules/utils.py @@ -0,0 +1,52 @@ +# 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 json + +from ansible_collections.community.sap_libs.tests.unit.compat import unittest +from ansible_collections.community.sap_libs.tests.unit.compat.mock import patch +from ansible.module_utils import basic +from ansible.module_utils.common.text.converters import to_bytes + + +def set_module_args(args): + if '_ansible_remote_tmp' not in args: + args['_ansible_remote_tmp'] = '/tmp' + if '_ansible_keep_remote_files' not in args: + args['_ansible_keep_remote_files'] = False + + args = json.dumps({'ANSIBLE_MODULE_ARGS': args}) + basic._ANSIBLE_ARGS = to_bytes(args) + + +class AnsibleExitJson(Exception): + pass + + +class AnsibleFailJson(Exception): + pass + + +def exit_json(*args, **kwargs): + if 'changed' not in kwargs: + kwargs['changed'] = False + raise AnsibleExitJson(kwargs) + + +def fail_json(*args, **kwargs): + kwargs['failed'] = True + raise AnsibleFailJson(kwargs) + + +class ModuleTestCase(unittest.TestCase): + + def setUp(self): + self.mock_module = patch.multiple(basic.AnsibleModule, exit_json=exit_json, fail_json=fail_json) + self.mock_module.start() + self.mock_sleep = patch('time.sleep') + self.mock_sleep.start() + set_module_args({}) + self.addCleanup(self.mock_module.stop) + self.addCleanup(self.mock_sleep.stop) diff --git a/ansible_collections/community/sap_libs/tests/unit/requirements.txt b/ansible_collections/community/sap_libs/tests/unit/requirements.txt new file mode 100644 index 00000000..49654b8b --- /dev/null +++ b/ansible_collections/community/sap_libs/tests/unit/requirements.txt @@ -0,0 +1,7 @@ +unittest2 ; python_version < '2.7' +importlib ; python_version < '2.7' + +# requirement sap_task_list_execute +lxml < 4.3.0 ; python_version < '2.7' # lxml 4.3.0 and later require python 2.7 or later +lxml ; python_version >= '2.7' +argparse ; python_version >= '2.6'
\ No newline at end of file |