summaryrefslogtreecommitdiffstats
path: root/ansible_collections/community/sap_libs/tests
diff options
context:
space:
mode:
Diffstat (limited to 'ansible_collections/community/sap_libs/tests')
-rw-r--r--ansible_collections/community/sap_libs/tests/integration/__init__.py0
-rw-r--r--ansible_collections/community/sap_libs/tests/integration/targets/__init__.py0
-rw-r--r--ansible_collections/community/sap_libs/tests/sanity/__init__.py0
-rw-r--r--ansible_collections/community/sap_libs/tests/sanity/ignore-2.10.txt9
-rw-r--r--ansible_collections/community/sap_libs/tests/sanity/ignore-2.11.txt9
-rw-r--r--ansible_collections/community/sap_libs/tests/sanity/ignore-2.12.txt9
-rw-r--r--ansible_collections/community/sap_libs/tests/sanity/ignore-2.13.txt9
-rw-r--r--ansible_collections/community/sap_libs/tests/sanity/ignore-2.14.txt9
-rw-r--r--ansible_collections/community/sap_libs/tests/sanity/ignore-2.15.txt9
-rw-r--r--ansible_collections/community/sap_libs/tests/sanity/ignore-2.9.txt9
-rw-r--r--ansible_collections/community/sap_libs/tests/unit/__init__.py0
-rw-r--r--ansible_collections/community/sap_libs/tests/unit/compat/__init__.py0
-rw-r--r--ansible_collections/community/sap_libs/tests/unit/compat/builtins.py33
-rw-r--r--ansible_collections/community/sap_libs/tests/unit/compat/mock.py122
-rw-r--r--ansible_collections/community/sap_libs/tests/unit/compat/unittest.py38
-rw-r--r--ansible_collections/community/sap_libs/tests/unit/mock/__init__.py0
-rw-r--r--ansible_collections/community/sap_libs/tests/unit/mock/loader.py102
-rw-r--r--ansible_collections/community/sap_libs/tests/unit/mock/path.py8
-rw-r--r--ansible_collections/community/sap_libs/tests/unit/mock/procenv.py76
-rw-r--r--ansible_collections/community/sap_libs/tests/unit/mock/vault_helper.py27
-rw-r--r--ansible_collections/community/sap_libs/tests/unit/mock/yaml_helper.py126
-rw-r--r--ansible_collections/community/sap_libs/tests/unit/plugins/__init__.py0
-rw-r--r--ansible_collections/community/sap_libs/tests/unit/plugins/modules/__init__.py0
-rw-r--r--ansible_collections/community/sap_libs/tests/unit/plugins/modules/test_sap_company.py136
-rw-r--r--ansible_collections/community/sap_libs/tests/unit/plugins/modules/test_sap_control_exec.py129
-rw-r--r--ansible_collections/community/sap_libs/tests/unit/plugins/modules/test_sap_hdbsql.py102
-rw-r--r--ansible_collections/community/sap_libs/tests/unit/plugins/modules/test_sap_pyrfc.py76
-rw-r--r--ansible_collections/community/sap_libs/tests/unit/plugins/modules/test_sap_snote.py181
-rw-r--r--ansible_collections/community/sap_libs/tests/unit/plugins/modules/test_sap_system_facts.py106
-rw-r--r--ansible_collections/community/sap_libs/tests/unit/plugins/modules/test_sap_task_list_execute.py89
-rw-r--r--ansible_collections/community/sap_libs/tests/unit/plugins/modules/test_sap_user.py189
-rw-r--r--ansible_collections/community/sap_libs/tests/unit/plugins/modules/test_sapcar_extract.py53
-rw-r--r--ansible_collections/community/sap_libs/tests/unit/plugins/modules/utils.py52
-rw-r--r--ansible_collections/community/sap_libs/tests/unit/requirements.txt7
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