xref: /aosp_15_r20/external/pigweed/pw_snapshot/py/metadata_test.py (revision 61c4878ac05f98d0ceed94b57d316916de578985)
1#!/usr/bin/env python3
2# Copyright 2021 The Pigweed Authors
3#
4# Licensed under the Apache License, Version 2.0 (the "License"); you may not
5# use this file except in compliance with the License. You may obtain a copy of
6# the License at
7#
8#     https://www.apache.org/licenses/LICENSE-2.0
9#
10# Unless required by applicable law or agreed to in writing, software
11# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
12# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
13# License for the specific language governing permissions and limitations under
14# the License.
15"""Tests for snapshot metadata processing."""
16
17import base64
18import unittest
19import pw_tokenizer
20from pw_snapshot_metadata.metadata import MetadataProcessor, process_snapshot
21from pw_snapshot_protos import snapshot_pb2
22from pw_tokenizer import tokens
23
24
25class MetadataProcessorTest(unittest.TestCase):
26    """Tests that the metadata processor produces expected results."""
27
28    def setUp(self):
29        super().setUp()
30        self.detok = pw_tokenizer.Detokenizer(
31            tokens.Database(
32                [
33                    tokens.TokenizedStringEntry(
34                        0x3A9BC4C3, 'Assert failed: 1+1 == 42'
35                    ),
36                    tokens.TokenizedStringEntry(0x01170923, 'gShoe'),
37                ]
38            )
39        )
40
41        snapshot = snapshot_pb2.Snapshot()
42        snapshot.metadata.reason = b'\xc3\xc4\x9b\x3a'
43        snapshot.metadata.project_name = b'$' + base64.b64encode(
44            b'\x23\x09\x17\x01'
45        )
46        snapshot.metadata.device_name = b'hyper-fast-gshoe'
47        snapshot.metadata.software_version = 'gShoe-debug-1.2.1-6f23412b+'
48        snapshot.metadata.snapshot_uuid = b'\x00\x00\x00\x01'
49
50        self.snapshot = snapshot
51
52    def test_reason_tokenized(self):
53        meta = MetadataProcessor(self.snapshot.metadata, self.detok)
54        self.assertEqual(meta.reason(), 'Assert failed: 1+1 == 42')
55
56    def test_reason_log_format(self):
57        self.snapshot.metadata.reason = (
58            '■msg♦Assert failed :(' '■file♦rpc_services/crash.cc'
59        ).encode('utf-8')
60        meta = MetadataProcessor(self.snapshot.metadata, self.detok)
61        self.assertEqual(
62            meta.reason(), 'rpc_services/crash.cc: Assert failed :('
63        )
64
65    def test_project_name_tokenized(self):
66        meta = MetadataProcessor(self.snapshot.metadata, self.detok)
67        self.assertEqual(meta.project_name(), 'gShoe')
68
69    def test_device_name_not_tokenized(self):
70        meta = MetadataProcessor(self.snapshot.metadata, self.detok)
71        self.assertEqual(meta.device_name(), 'hyper-fast-gshoe')
72
73    def test_default_non_fatal(self):
74        meta = MetadataProcessor(self.snapshot.metadata, self.detok)
75        self.assertFalse(meta.is_fatal())
76
77    def test_fw_version(self):
78        meta = MetadataProcessor(self.snapshot.metadata, self.detok)
79        self.assertEqual(
80            meta.device_fw_version(), 'gShoe-debug-1.2.1-6f23412b+'
81        )
82
83    def test_snapshot_uuid(self):
84        meta = MetadataProcessor(self.snapshot.metadata, self.detok)
85        self.assertEqual(meta.snapshot_uuid(), '00000001')
86
87    def test_fw_uuid_default(self):
88        meta = MetadataProcessor(self.snapshot.metadata, self.detok)
89        self.assertEqual(meta.fw_build_uuid(), '')
90
91    def test_as_str(self):
92        meta = MetadataProcessor(self.snapshot.metadata, self.detok)
93        expected = '\n'.join(
94            (
95                'Snapshot capture reason:',
96                '    Assert failed: 1+1 == 42',
97                '',
98                'Reason token:      0x3a9bc4c3',
99                'Project name:      gShoe',
100                'Device:            hyper-fast-gshoe',
101                'Device FW version: gShoe-debug-1.2.1-6f23412b+',
102                'Snapshot UUID:     00000001',
103            )
104        )
105        self.assertEqual(expected, str(meta))
106
107    def test_as_str_fatal(self):
108        self.snapshot.metadata.fatal = True
109        meta = MetadataProcessor(self.snapshot.metadata, self.detok)
110        expected = '\n'.join(
111            (
112                '                            ▪▄▄▄ ▄▄▄· ▄▄▄▄▄ ▄▄▄· ▄ ·',
113                '                            █▄▄▄▐█ ▀█ • █▌ ▐█ ▀█ █',
114                '                            █ ▪ ▄█▀▀█   █. ▄█▀▀█ █',
115                '                            ▐▌ .▐█ ▪▐▌ ▪▐▌·▐█ ▪▐▌▐▌',
116                '                            ▀    ▀  ▀ ·  ▀  ▀  ▀ .▀▀',
117                '',
118                'Device crash cause:',
119                '    Assert failed: 1+1 == 42',
120                '',
121                'Reason token:      0x3a9bc4c3',
122                'Project name:      gShoe',
123                'Device:            hyper-fast-gshoe',
124                'Device FW version: gShoe-debug-1.2.1-6f23412b+',
125                'Snapshot UUID:     00000001',
126            )
127        )
128        self.assertEqual(expected, str(meta))
129
130    def test_no_reason(self):
131        snapshot = snapshot_pb2.Snapshot()
132        snapshot.metadata.fatal = True
133        meta = MetadataProcessor(snapshot.metadata, self.detok)
134        meta.set_pretty_format_width(40)
135        expected = '\n'.join(
136            (
137                '        ▪▄▄▄ ▄▄▄· ▄▄▄▄▄ ▄▄▄· ▄ ·',
138                '        █▄▄▄▐█ ▀█ • █▌ ▐█ ▀█ █',
139                '        █ ▪ ▄█▀▀█   █. ▄█▀▀█ █',
140                '        ▐▌ .▐█ ▪▐▌ ▪▐▌·▐█ ▪▐▌▐▌',
141                '        ▀    ▀  ▀ ·  ▀  ▀  ▀ .▀▀',
142                '',
143                'Device crash cause:',
144                '    UNKNOWN (field missing)',
145                '',
146            )
147        )
148        self.assertEqual(expected, str(meta))
149
150    def test_no_token_db(self):
151        meta = MetadataProcessor(self.snapshot.metadata)
152        expected = '\n'.join(
153            (
154                'Snapshot capture reason:',
155                '    $w8SbOg==',
156                '',
157                'Reason token:      0x3a9bc4c3',
158                'Project name:      $IwkXAQ==',
159                'Device:            hyper-fast-gshoe',
160                'Device FW version: gShoe-debug-1.2.1-6f23412b+',
161                'Snapshot UUID:     00000001',
162            )
163        )
164        self.assertEqual(expected, str(meta))
165
166    def test_serialized_snapshot(self):
167        self.snapshot.tags['type'] = 'obviously a crash'
168        expected = '\n'.join(
169            (
170                'Snapshot capture reason:',
171                '    Assert failed: 1+1 == 42',
172                '',
173                'Reason token:      0x3a9bc4c3',
174                'Project name:      gShoe',
175                'Device:            hyper-fast-gshoe',
176                'Device FW version: gShoe-debug-1.2.1-6f23412b+',
177                'Snapshot UUID:     00000001',
178                '',
179                'Tags:',
180                '  type: obviously a crash',
181                '',
182            )
183        )
184        self.assertEqual(
185            expected,
186            process_snapshot(self.snapshot.SerializeToString(), self.detok),
187        )
188
189
190if __name__ == '__main__':
191    unittest.main()
192