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