blob: d9e23d2e6fd317c6a6bf4d9de202d8b0296371eb [file] [log] [blame]
# Copyright 2021 The Pigweed Authors
#
# 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
#
# https://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.
"""Tests for pw_console.text_formatting"""
import logging
import unittest
from datetime import datetime
from parameterized import parameterized # type: ignore
from pw_console.log_line import LogLine
from pw_console.widgets.table import TableView
_TIMESTAMP_FORMAT = '%Y%m%d %H:%M:%S'
_TIMESTAMP_SAMPLE = datetime(2021, 6, 30, 16, 10, 37, 818901)
_TIMESTAMP_SAMPLE_STRING = _TIMESTAMP_SAMPLE.strftime(_TIMESTAMP_FORMAT)
_TABLE_PADDING = ('', TableView.COLUMN_PADDING)
formatter = logging.Formatter(
'\x1b[30m\x1b[47m'
'%(asctime)s'
'\x1b[0m'
' '
'\x1b[33m\x1b[1m'
'%(levelname)s'
'\x1b[0m'
' '
'%(message)s', _TIMESTAMP_FORMAT)
def make_log(**kwargs):
"""Create a LogLine instance."""
# Construct a LogRecord
attributes = dict(name='testlogger',
levelno=logging.INFO,
levelname='INF',
msg='[%s] %.3f %s',
args=('MOD1', 3.14159, 'Real message here'),
created=_TIMESTAMP_SAMPLE.timestamp(),
filename='test.py',
lineno=42,
pathname='/home/user/test.py')
# Override any above attrs that are passed in.
attributes.update(kwargs)
# Create the record
record = logging.makeLogRecord(dict(attributes))
# Format
formatted_message = formatter.format(record)
log_line = LogLine(record=record,
formatted_log=formatted_message,
ansi_stripped_log='')
log_line.update_metadata()
return log_line
class TestTableView(unittest.TestCase):
"""Tests for rendering log lines into tables."""
def setUp(self):
# Show large diffs
self.maxDiff = None # pylint: disable=invalid-name
@parameterized.expand([
(
'Correct column widths with all fields set',
[
make_log(
args=('M1', 1.2345, 'Something happened'),
extra_metadata_fields=dict(module='M1', time=12)),
make_log(
args=('MD2', 567.5, 'Another cool event'),
extra_metadata_fields=dict(module='MD2', time=123)),
],
dict(module=len('MD2'), time=len('123')),
),
(
'Missing metadata fields on some rows',
[
make_log(
args=('M1', 54321.2, 'Something happened'),
extra_metadata_fields=dict(module='M1', time=54321.2)),
make_log(
args=('MOD2', 567.5, 'Another cool event'),
extra_metadata_fields=dict(module='MOD2')),
],
dict(module=len('MOD2'), time=len('54321.200')),
),
]) # yapf: disable
def test_column_widths(self, _name, logs, expected_widths) -> None:
"""Test colum widths calculation."""
table = TableView()
for log in logs:
table.update_metadata_column_widths(log)
# update_metadata_column_widths shoulp populate self.metadata.fields
self.assertEqual(log.metadata.fields,
log.record.extra_metadata_fields)
# Check expected column widths
self.assertEqual(dict(table.column_widths), expected_widths)
@parameterized.expand([
(
'Build header adding fields incrementally',
[
make_log(
args=('MODULE2', 567.5, 'Another cool event'),
extra_metadata_fields=dict(
# timestamp missing
module='MODULE2')),
make_log(
args=('MODULE1', 54321.2, 'Something happened'),
extra_metadata_fields=dict(
# timestamp added in
module='MODULE1', timestamp=54321.2)),
],
[
[('bold', 'Time '), _TABLE_PADDING,
('bold', 'Lvl'), _TABLE_PADDING,
('bold', 'Module '),
('bold', 'Message')],
[('bold', 'Time '), _TABLE_PADDING,
('bold', 'Lvl'), _TABLE_PADDING,
# timestamp added in
('bold', 'Timestamp '),
('bold', 'Module '),
('bold', 'Message')],
],
),
]) # yapf: disable
def test_formatted_header(self, _name, logs, expected_headers) -> None:
"""Test colum widths calculation."""
table = TableView()
for log, header in zip(logs, expected_headers):
table.update_metadata_column_widths(log)
self.assertEqual(table.formatted_header(), header)
@parameterized.expand([
(
'Build rows adding fields incrementally',
[
make_log(
args=('MODULE2', 567.5, 'Another cool event'),
extra_metadata_fields=dict(
# timestamp missing
module='MODULE2',
msg='Another cool event')),
make_log(
args=('MODULE2', 567.5, 'Another cool event'),
extra_metadata_fields=dict(
# timestamp and msg missing
module='MODULE2')),
make_log(
args=('MODULE1', 54321.2, 'Something happened'),
extra_metadata_fields=dict(
# timestamp added in
module='MODULE1', timestamp=54321.2,
msg='Something happened')),
],
[
[
('class:log-time', _TIMESTAMP_SAMPLE_STRING),
_TABLE_PADDING,
('class:log-level-20', 'INF'),
_TABLE_PADDING,
('class:log-table-column-3', 'MODULE2 '),
('', 'Another cool event'),
('', '\n')
],
[
('class:log-time', _TIMESTAMP_SAMPLE_STRING),
_TABLE_PADDING,
('class:log-level-20', 'INF'),
_TABLE_PADDING,
('class:log-table-column-3', 'MODULE2 '),
('', '[MODULE2] 567.500 Another cool event'),
('', '\n')
],
[
('class:log-time', _TIMESTAMP_SAMPLE_STRING),
_TABLE_PADDING,
('class:log-level-20', 'INF'),
_TABLE_PADDING,
('class:log-table-column-3', '54321.200 '),
('class:log-table-column-4', 'MODULE1 '),
('', 'Something happened'),
('', '\n')
],
],
),
]) # yapf: disable
def test_formatted_rows(self, _name, logs, expected_log_format) -> None:
"""Test colum widths calculation."""
table = TableView()
# Check each row meets expected formats incrementally.
for log, formatted_log in zip(logs, expected_log_format):
table.update_metadata_column_widths(log)
self.assertEqual(table.formatted_row(log), formatted_log)
if __name__ == '__main__':
unittest.main()