log_printer_test.py 4.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137
  1. from __future__ import absolute_import
  2. from __future__ import unicode_literals
  3. import pytest
  4. import six
  5. from six.moves.queue import Queue
  6. from compose.cli.log_printer import consume_queue
  7. from compose.cli.log_printer import LogPrinter
  8. from compose.cli.log_printer import STOP
  9. from compose.cli.log_printer import wait_on_exit
  10. from compose.container import Container
  11. from tests import mock
  12. def build_mock_container(reader):
  13. return mock.Mock(
  14. spec=Container,
  15. name='myapp_web_1',
  16. name_without_project='web_1',
  17. has_api_logs=True,
  18. log_stream=None,
  19. logs=reader,
  20. wait=mock.Mock(return_value=0),
  21. )
  22. @pytest.fixture
  23. def output_stream():
  24. output = six.StringIO()
  25. output.flush = mock.Mock()
  26. return output
  27. @pytest.fixture
  28. def mock_container():
  29. def reader(*args, **kwargs):
  30. yield b"hello\nworld"
  31. return build_mock_container(reader)
  32. @pytest.mark.skipif(True, reason="wip")
  33. class TestLogPrinter(object):
  34. def test_single_container(self, output_stream, mock_container):
  35. LogPrinter([mock_container], output=output_stream, log_args={'follow': True}).run()
  36. output = output_stream.getvalue()
  37. assert 'hello' in output
  38. assert 'world' in output
  39. # Call count is 2 lines + "container exited line"
  40. assert output_stream.flush.call_count == 3
  41. def test_single_container_without_stream(self, output_stream, mock_container):
  42. LogPrinter([mock_container], output=output_stream).run()
  43. output = output_stream.getvalue()
  44. assert 'hello' in output
  45. assert 'world' in output
  46. # Call count is 2 lines
  47. assert output_stream.flush.call_count == 2
  48. def test_monochrome(self, output_stream, mock_container):
  49. LogPrinter([mock_container], output=output_stream, monochrome=True).run()
  50. assert '\033[' not in output_stream.getvalue()
  51. def test_polychrome(self, output_stream, mock_container):
  52. LogPrinter([mock_container], output=output_stream).run()
  53. assert '\033[' in output_stream.getvalue()
  54. def test_unicode(self, output_stream):
  55. glyph = u'\u2022'
  56. def reader(*args, **kwargs):
  57. yield glyph.encode('utf-8') + b'\n'
  58. container = build_mock_container(reader)
  59. LogPrinter([container], output=output_stream).run()
  60. output = output_stream.getvalue()
  61. if six.PY2:
  62. output = output.decode('utf-8')
  63. assert glyph in output
  64. def test_wait_on_exit(self):
  65. exit_status = 3
  66. mock_container = mock.Mock(
  67. spec=Container,
  68. name='cname',
  69. wait=mock.Mock(return_value=exit_status))
  70. expected = '{} exited with code {}\n'.format(mock_container.name, exit_status)
  71. assert expected == wait_on_exit(mock_container)
  72. def test_generator_with_no_logs(self, mock_container, output_stream):
  73. mock_container.has_api_logs = False
  74. mock_container.log_driver = 'none'
  75. LogPrinter([mock_container], output=output_stream).run()
  76. output = output_stream.getvalue()
  77. assert "WARNING: no logs are available with the 'none' log driver\n" in output
  78. assert "exited with code" not in output
  79. class TestConsumeQueue(object):
  80. def test_item_is_an_exception(self):
  81. class Problem(Exception):
  82. pass
  83. queue = Queue()
  84. error = Problem('oops')
  85. for item in ('a', None), ('b', None), (None, error):
  86. queue.put(item)
  87. generator = consume_queue(queue, False)
  88. assert generator.next() == 'a'
  89. assert generator.next() == 'b'
  90. with pytest.raises(Problem):
  91. generator.next()
  92. def test_item_is_stop_without_cascade_stop(self):
  93. queue = Queue()
  94. for item in (STOP, None), ('a', None), ('b', None):
  95. queue.put(item)
  96. generator = consume_queue(queue, False)
  97. assert generator.next() == 'a'
  98. assert generator.next() == 'b'
  99. def test_item_is_stop_with_cascade_stop(self):
  100. queue = Queue()
  101. for item in (STOP, None), ('a', None), ('b', None):
  102. queue.put(item)
  103. assert list(consume_queue(queue, True)) == []