• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1# Copyright 2021 The Pigweed Authors
2#
3# Licensed under the Apache License, Version 2.0 (the "License"); you may not
4# use this file except in compliance with the License. You may obtain a copy of
5# the License at
6#
7#     https://www.apache.org/licenses/LICENSE-2.0
8#
9# Unless required by applicable law or agreed to in writing, software
10# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
11# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
12# License for the specific language governing permissions and limitations under
13# the License.
14"""Tests for pw_console.log_store"""
15
16import logging
17import unittest
18from unittest.mock import MagicMock
19
20from pw_console.log_store import LogStore
21from pw_console.console_prefs import ConsolePrefs
22
23
24def _create_log_store():
25    log_store = LogStore(prefs=ConsolePrefs(
26        project_file=False, project_user_file=False, user_file=False))
27
28    assert not log_store.table.prefs.show_python_file
29    viewer = MagicMock()
30    viewer.new_logs_arrived = MagicMock()
31    log_store.register_viewer(viewer)
32    return log_store, viewer
33
34
35class TestLogStore(unittest.TestCase):
36    """Tests for LogStore."""
37    def setUp(self):
38        self.maxDiff = None  # pylint: disable=invalid-name
39
40    def test_get_total_count(self) -> None:
41        log_store, viewer = _create_log_store()
42        test_log = logging.getLogger('log_store.test')
43        # Must use the assertLogs context manager and the addHandler call.
44        with self.assertLogs(test_log, level='DEBUG') as log_context:
45            test_log.addHandler(log_store)
46            for i in range(5):
47                test_log.debug('Test log %s', i)
48
49        # Expected log message content
50        self.assertEqual(
51            ['DEBUG:log_store.test:Test log {}'.format(i) for i in range(5)],
52            log_context.output,
53        )
54        # LogStore state checks
55        viewer.new_logs_arrived.assert_called()
56        self.assertEqual(5, log_store.get_total_count())
57        self.assertEqual(4, log_store.get_last_log_index())
58
59        log_store.clear_logs()
60        self.assertEqual(0, log_store.get_total_count())
61
62    def test_channel_counts_and_prefix_width(self) -> None:
63        """Test logger names and prefix width calculations."""
64        log_store, _viewer = _create_log_store()
65
66        # Log some messagse on 3 separate logger instances
67        for i, logger_name in enumerate([
68                'log_store.test',
69                'log_store.dev',
70                'log_store.production',
71        ]):
72            test_log = logging.getLogger(logger_name)
73            with self.assertLogs(test_log, level='DEBUG') as _log_context:
74                test_log.addHandler(log_store)
75                test_log.debug('Test log message')
76                for j in range(i):
77                    test_log.debug('%s', j)
78
79        self.assertEqual(
80            {
81                'log_store.test': 1,
82                'log_store.dev': 2,
83                'log_store.production': 3,
84            },
85            log_store.channel_counts,
86        )
87        self.assertEqual(
88            'log_store.test: 1, log_store.dev: 2, log_store.production: 3',
89            log_store.get_channel_counts(),
90        )
91
92        self.assertRegex(
93            log_store.logs[0].ansi_stripped_log,
94            r'[0-9]{8} [0-9]{2}:[0-9]{2}:[0-9]{2} DEBUG Test log message',
95        )
96        self.assertEqual(
97            {
98                'log_store.test': 0,
99                'log_store.dev': 0,
100                'log_store.production': 0,
101            },
102            log_store.channel_formatted_prefix_widths,
103        )
104
105    def test_render_table_header_with_metadata(self) -> None:
106        log_store, _viewer = _create_log_store()
107        test_log = logging.getLogger('log_store.test')
108
109        # Log table with extra columns
110        with self.assertLogs(test_log, level='DEBUG') as _log_context:
111            test_log.addHandler(log_store)
112            test_log.debug('Test log %s',
113                           extra=dict(extra_metadata_fields={
114                               'planet': 'Jupiter',
115                               'galaxy': 'Milky Way'
116                           }))
117
118        self.assertEqual(
119            [
120                ('bold', 'Time             '),
121                ('', '  '),
122                ('bold', 'Level'),
123                ('', '  '),
124                ('bold', 'Planet '),
125                ('', '  '),
126                ('bold', 'Galaxy   '),
127                ('', '  '),
128                ('bold', 'Message'),
129            ],
130            log_store.render_table_header(),
131        )
132
133
134if __name__ == '__main__':
135    unittest.main()
136