1
0
Fork 0
mirror of https://github.com/ansible-collections/community.general.git synced 2024-09-14 20:13:21 +02:00
community.general/test/units/module_utils/basic/test_log.py
nitzmahone 5b336832af add _load_params debug overrides for module args/file passed on cmdline
Updated python module wrapper explode method to drop 'args' file next to module.
Both execute() and excommunicate() debug methods now pass the module args via file to enable debuggers that are picky about stdin.
Updated unit tests to use a context manager for masking/restoring default streams and argv.
2016-04-18 11:06:46 -07:00

267 lines
9.9 KiB
Python

# -*- coding: utf-8 -*-
# (c) 2012-2014, Michael DeHaan <michael.dehaan@gmail.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)
__metaclass__ = type
import sys
import json
import syslog
from ansible.compat.tests import unittest
from ansible.compat.tests.mock import patch, MagicMock
from units.mock.procenv import swap_stdin_and_argv
from ansible.module_utils import basic
try:
# Python 3.4+
from importlib import reload
except ImportError:
# Python 2 has reload as a builtin
# Ignoring python3.0-3.3 (those have imp.reload if we decide we care)
pass
class TestAnsibleModuleSysLogSmokeTest(unittest.TestCase):
def setUp(self):
args = json.dumps(dict(ANSIBLE_MODULE_ARGS={}, ANSIBLE_MODULE_CONSTANTS={}))
# 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__()
self.am = basic.AnsibleModule(
argument_spec = dict(),
)
self.has_journal = basic.has_journal
if self.has_journal:
# Systems with journal can still test syslog
basic.has_journal = False
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)
basic.has_journal = self.has_journal
def test_smoketest_syslog(self):
# These talk to the live daemons on the system. Need to do this to
# show that what we send doesn't cause an issue once it gets to the
# daemon. These are just smoketests to test that we don't fail.
self.am.log(u'Text string')
self.am.log(u'Toshio くらとみ non-ascii test')
self.am.log(b'Byte string')
self.am.log(u'Toshio くらとみ non-ascii test'.encode('utf-8'))
self.am.log(b'non-utf8 :\xff: test')
class TestAnsibleModuleJournaldSmokeTest(unittest.TestCase):
def setUp(self):
args = json.dumps(dict(ANSIBLE_MODULE_ARGS={}, ANSIBLE_MODULE_CONSTANTS={}))
# 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__()
self.am = basic.AnsibleModule(
argument_spec = dict(),
)
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)
@unittest.skipUnless(basic.has_journal, 'python systemd bindings not installed')
def test_smoketest_journal(self):
# These talk to the live daemons on the system. Need to do this to
# show that what we send doesn't cause an issue once it gets to the
# daemon. These are just smoketests to test that we don't fail.
self.am.log(u'Text string')
self.am.log(u'Toshio くらとみ non-ascii test')
self.am.log(b'Byte string')
self.am.log(u'Toshio くらとみ non-ascii test'.encode('utf-8'))
self.am.log(b'non-utf8 :\xff: test')
class TestAnsibleModuleLogSyslog(unittest.TestCase):
"""Test the AnsibleModule Log Method"""
py2_output_data = {
u'Text string': b'Text string',
u'Toshio くらとみ non-ascii test': u'Toshio くらとみ non-ascii test'.encode('utf-8'),
b'Byte string': b'Byte string',
u'Toshio くらとみ non-ascii test'.encode('utf-8'): u'Toshio くらとみ non-ascii test'.encode('utf-8'),
b'non-utf8 :\xff: test': b'non-utf8 :\xff: test'.decode('utf-8', 'replace').encode('utf-8'),
}
py3_output_data = {
u'Text string': u'Text string',
u'Toshio くらとみ non-ascii test': u'Toshio くらとみ non-ascii test',
b'Byte string': u'Byte string',
u'Toshio くらとみ non-ascii test'.encode('utf-8'): u'Toshio くらとみ non-ascii test',
b'non-utf8 :\xff: test': b'non-utf8 :\xff: test'.decode('utf-8', 'replace')
}
def setUp(self):
args = json.dumps(dict(ANSIBLE_MODULE_ARGS={}, ANSIBLE_MODULE_CONSTANTS={}))
# 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__()
self.am = basic.AnsibleModule(
argument_spec = dict(),
)
self.has_journal = basic.has_journal
if self.has_journal:
# Systems with journal can still test syslog
basic.has_journal = False
def tearDown(self):
# teardown/reset
basic.has_journal = self.has_journal
# 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)
@patch('syslog.syslog', autospec=True)
def test_no_log(self, mock_func):
no_log = self.am.no_log
self.am.no_log = True
self.am.log('unittest no_log')
self.assertFalse(mock_func.called)
self.am.no_log = False
self.am.log('unittest no_log')
mock_func.assert_called_once_with(syslog.LOG_INFO, 'unittest no_log')
self.am.no_log = no_log
def test_output_matches(self):
if sys.version_info >= (3,):
output_data = self.py3_output_data
else:
output_data = self.py2_output_data
for msg, param in output_data.items():
with patch('syslog.syslog', autospec=True) as mock_func:
self.am.log(msg)
mock_func.assert_called_once_with(syslog.LOG_INFO, param)
class TestAnsibleModuleLogJournal(unittest.TestCase):
"""Test the AnsibleModule Log Method"""
output_data = {
u'Text string': u'Text string',
u'Toshio くらとみ non-ascii test': u'Toshio くらとみ non-ascii test',
b'Byte string': u'Byte string',
u'Toshio くらとみ non-ascii test'.encode('utf-8'): u'Toshio くらとみ non-ascii test',
b'non-utf8 :\xff: test': b'non-utf8 :\xff: test'.decode('utf-8', 'replace')
}
# overriding run lets us use context managers for setup/teardown-esque behavior
def setUp(self):
args = json.dumps(dict(ANSIBLE_MODULE_ARGS={}, ANSIBLE_MODULE_CONSTANTS={}))
# 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__()
self.am = basic.AnsibleModule(
argument_spec = dict(),
)
self.has_journal = basic.has_journal
if self.has_journal:
# Systems with journal can still test syslog
basic.has_journal = False
self.module_patcher = None
# In case systemd-python is not installed
if not self.has_journal:
self.module_patcher = patch.dict('sys.modules', {'systemd': MagicMock(), 'systemd.journal': MagicMock()})
self.module_patcher.start()
try:
reload(basic)
except NameError:
self._fake_out_reload(basic)
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)
# teardown/reset
basic.has_journal = self.has_journal
if self.module_patcher:
self.module_patcher.stop()
reload(basic)
@patch('systemd.journal.send')
def test_no_log(self, mock_func):
no_log = self.am.no_log
self.am.no_log = True
self.am.log('unittest no_log')
self.assertFalse(mock_func.called)
self.am.no_log = False
self.am.log('unittest no_log')
self.assertEqual(mock_func.called, 1)
# Message
# call_args is a 2-tuple of (arg_list, kwarg_dict)
self.assertTrue(mock_func.call_args[0][0].endswith('unittest no_log'), msg='Message was not sent to log')
# log adds this journal field
self.assertIn('MODULE', mock_func.call_args[1])
self.assertIn('basic.py', mock_func.call_args[1]['MODULE'])
self.am.no_log = no_log
def test_output_matches(self):
for msg, param in self.output_data.items():
with patch('systemd.journal.send', autospec=True) as mock_func:
self.am.log(msg)
self.assertEqual(mock_func.call_count, 1, msg='journal.send not called exactly once')
self.assertTrue(mock_func.call_args[0][0].endswith(param))
@patch('systemd.journal.send')
def test_log_args(self, mock_func):
self.am.log('unittest log_args', log_args=dict(TEST='log unittest'))
self.assertEqual(mock_func.called, 1)
self.assertTrue(mock_func.call_args[0][0].endswith('unittest log_args'), msg='Message was not sent to log')
# log adds this journal field
self.assertIn('MODULE', mock_func.call_args[1])
self.assertIn('basic.py', mock_func.call_args[1]['MODULE'])
# We added this journal field
self.assertIn('TEST', mock_func.call_args[1])
self.assertIn('log unittest', mock_func.call_args[1]['TEST'])