summaryrefslogtreecommitdiffstats
path: root/test/units/utils/test_display.py
diff options
context:
space:
mode:
Diffstat (limited to 'test/units/utils/test_display.py')
-rw-r--r--test/units/utils/test_display.py135
1 files changed, 135 insertions, 0 deletions
diff --git a/test/units/utils/test_display.py b/test/units/utils/test_display.py
new file mode 100644
index 0000000..6b1914b
--- /dev/null
+++ b/test/units/utils/test_display.py
@@ -0,0 +1,135 @@
+# -*- coding: utf-8 -*-
+# (c) 2020 Matt Martz <matt@sivel.net>
+# 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 locale
+import sys
+import unicodedata
+from unittest.mock import MagicMock
+
+import pytest
+
+from ansible.utils.display import _LIBC, _MAX_INT, Display, get_text_width
+from ansible.utils.multiprocessing import context as multiprocessing_context
+
+
+@pytest.fixture
+def problematic_wcswidth_chars():
+ problematic = []
+ try:
+ locale.setlocale(locale.LC_ALL, 'C.UTF-8')
+ except Exception:
+ return problematic
+
+ candidates = set(chr(c) for c in range(sys.maxunicode) if unicodedata.category(chr(c)) == 'Cf')
+ for c in candidates:
+ if _LIBC.wcswidth(c, _MAX_INT) == -1:
+ problematic.append(c)
+
+ return problematic
+
+
+def test_get_text_width():
+ locale.setlocale(locale.LC_ALL, '')
+ assert get_text_width(u'コンニチハ') == 10
+ assert get_text_width(u'abコcd') == 6
+ assert get_text_width(u'café') == 4
+ assert get_text_width(u'four') == 4
+ assert get_text_width(u'\u001B') == 0
+ assert get_text_width(u'ab\u0000') == 2
+ assert get_text_width(u'abコ\u0000') == 4
+ assert get_text_width(u'🚀🐮') == 4
+ assert get_text_width(u'\x08') == 0
+ assert get_text_width(u'\x08\x08') == 0
+ assert get_text_width(u'ab\x08cd') == 3
+ assert get_text_width(u'ab\x1bcd') == 3
+ assert get_text_width(u'ab\x7fcd') == 3
+ assert get_text_width(u'ab\x94cd') == 3
+
+ pytest.raises(TypeError, get_text_width, 1)
+ pytest.raises(TypeError, get_text_width, b'four')
+
+
+def test_get_text_width_no_locale(problematic_wcswidth_chars):
+ if not problematic_wcswidth_chars:
+ pytest.skip("No problmatic wcswidth chars")
+ locale.setlocale(locale.LC_ALL, 'C.UTF-8')
+ pytest.raises(EnvironmentError, get_text_width, problematic_wcswidth_chars[0])
+
+
+def test_Display_banner_get_text_width(monkeypatch):
+ locale.setlocale(locale.LC_ALL, '')
+ display = Display()
+ display_mock = MagicMock()
+ monkeypatch.setattr(display, 'display', display_mock)
+
+ display.banner(u'🚀🐮', color=False, cows=False)
+ args, kwargs = display_mock.call_args
+ msg = args[0]
+ stars = u' %s' % (75 * u'*')
+ assert msg.endswith(stars)
+
+
+def test_Display_banner_get_text_width_fallback(monkeypatch):
+ locale.setlocale(locale.LC_ALL, 'C.UTF-8')
+ display = Display()
+ display_mock = MagicMock()
+ monkeypatch.setattr(display, 'display', display_mock)
+
+ display.banner(u'\U000110cd', color=False, cows=False)
+ args, kwargs = display_mock.call_args
+ msg = args[0]
+ stars = u' %s' % (78 * u'*')
+ assert msg.endswith(stars)
+
+
+def test_Display_set_queue_parent():
+ display = Display()
+ pytest.raises(RuntimeError, display.set_queue, 'foo')
+
+
+def test_Display_set_queue_fork():
+ def test():
+ display = Display()
+ display.set_queue('foo')
+ assert display._final_q == 'foo'
+ p = multiprocessing_context.Process(target=test)
+ p.start()
+ p.join()
+ assert p.exitcode == 0
+
+
+def test_Display_display_fork():
+ def test():
+ queue = MagicMock()
+ display = Display()
+ display.set_queue(queue)
+ display.display('foo')
+ queue.send_display.assert_called_once_with(
+ 'foo', color=None, stderr=False, screen_only=False, log_only=False, newline=True
+ )
+
+ p = multiprocessing_context.Process(target=test)
+ p.start()
+ p.join()
+ assert p.exitcode == 0
+
+
+def test_Display_display_lock(monkeypatch):
+ lock = MagicMock()
+ display = Display()
+ monkeypatch.setattr(display, '_lock', lock)
+ display.display('foo')
+ lock.__enter__.assert_called_once_with()
+
+
+def test_Display_display_lock_fork(monkeypatch):
+ lock = MagicMock()
+ display = Display()
+ monkeypatch.setattr(display, '_lock', lock)
+ monkeypatch.setattr(display, '_final_q', MagicMock())
+ display.display('foo')
+ lock.__enter__.assert_not_called()