1#!/usr/bin/env python3 2# Copyright 2022 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 bloaty configuration tooling.""" 16 17import unittest 18import os 19import logging 20import sys 21from pw_bloat.label import DataSourceMap, Label 22 23LIST_LABELS = [ 24 Label(name='main()', size=30, parents=tuple(['FLASH', '.code'])), 25 Label(name='foo()', size=100, parents=tuple(['RAM', '.heap'])), 26 Label(name='bar()', size=220, parents=tuple(['RAM', '.heap'])), 27] 28 29logger = logging.getLogger() 30logger.level = logging.DEBUG 31logger.addHandler(logging.StreamHandler(sys.stdout)) 32 33 34def get_test_map(): 35 pw_root = os.environ.get("PW ROOT") 36 filename = f"{pw_root}/pigweed/pw_bloat/test_label.csv" 37 with open(filename, 'r') as csvfile: 38 ds_map = DataSourceMap.from_bloaty_tsv(csvfile) 39 capacity_patterns = [("^__TEXT$", 459), ("^_", 920834)] 40 for cap_pattern, cap_size in capacity_patterns: 41 ds_map.add_capacity(cap_pattern, cap_size) 42 return ds_map 43 44 45class LabelStructTest(unittest.TestCase): 46 """Testing class for the label structs.""" 47 48 def test_data_source_total_size(self): 49 ds_map = DataSourceMap(['a', 'b', 'c']) 50 self.assertEqual(ds_map.get_total_size(), 0) 51 52 def test_data_source_single_insert_total_size(self): 53 ds_map = DataSourceMap(['a', 'b', 'c']) 54 ds_map.insert_label_hierarchy(['FLASH', '.code', 'main()'], 30) 55 self.assertEqual(ds_map.get_total_size(), 30) 56 57 def test_data_source_multiple_insert_total_size(self): 58 ds_map = DataSourceMap(['a', 'b', 'c']) 59 ds_map.insert_label_hierarchy(['FLASH', '.code', 'main()'], 30) 60 ds_map.insert_label_hierarchy(['RAM', '.code', 'foo()'], 100) 61 self.assertEqual(ds_map.get_total_size(), 130) 62 63 def test_parsing_generator_three_datasource_names(self): 64 ds_map = DataSourceMap(['a', 'b', 'c']) 65 for label in LIST_LABELS: 66 ds_map.insert_label_hierarchy( 67 [label.parents[0], label.parents[1], label.name], label.size 68 ) 69 list_labels_three = [*LIST_LABELS, Label(name='total', size=350)] 70 for label_hierarchy in ds_map.labels(): 71 self.assertIn(label_hierarchy, list_labels_three) 72 self.assertEqual(ds_map.get_total_size(), 350) 73 74 def test_parsing_generator_two_datasource_names(self): 75 ds_map = DataSourceMap(['a', 'b']) 76 ds_label_list = [ 77 Label(name='main()', size=30, parents=tuple(['FLASH'])), 78 Label(name='foo()', size=100, parents=tuple(['RAM'])), 79 Label(name='bar()', size=220, parents=tuple(['RAM'])), 80 ] 81 for label in ds_label_list: 82 ds_map.insert_label_hierarchy( 83 [label.parents[0], label.name], label.size 84 ) 85 list_labels_two = [*ds_label_list, Label(name='total', size=350)] 86 for label_hierarchy in ds_map.labels(): 87 self.assertIn(label_hierarchy, list_labels_two) 88 self.assertEqual(ds_map.get_total_size(), 350) 89 90 def test_parsing_generator_specified_datasource_1(self): 91 ds_map = DataSourceMap(['a', 'b', 'c']) 92 for label in LIST_LABELS: 93 ds_map.insert_label_hierarchy( 94 [label.parents[0], label.parents[1], label.name], label.size 95 ) 96 list_labels_ds_b = [ 97 Label(name='.code', size=30, parents=tuple(['FLASH'])), 98 Label(name='.heap', size=320, parents=tuple(['RAM'])), 99 ] 100 list_labels_ds_b += [Label(name='total', size=350)] 101 for label_hierarchy in ds_map.labels(1): 102 self.assertIn(label_hierarchy, list_labels_ds_b) 103 self.assertEqual(ds_map.get_total_size(), 350) 104 105 def test_parsing_generator_specified_datasource_str_2(self): 106 ds_map = DataSourceMap(['a', 'b', 'c']) 107 for label in LIST_LABELS: 108 ds_map.insert_label_hierarchy( 109 [label.parents[0], label.parents[1], label.name], label.size 110 ) 111 list_labels_ds_a = [ 112 Label(name='FLASH', size=30, parents=tuple([])), 113 Label(name='RAM', size=320, parents=tuple([])), 114 ] 115 list_labels_ds_a += [Label(name='total', size=350)] 116 for label_hierarchy in ds_map.labels(0): 117 self.assertIn(label_hierarchy, list_labels_ds_a) 118 self.assertEqual(ds_map.get_total_size(), 350) 119 120 def test_parsing_generator_specified_datasource_int(self): 121 ds_map = DataSourceMap(['a', 'b', 'c']) 122 for label in LIST_LABELS: 123 ds_map.insert_label_hierarchy( 124 [label.parents[0], label.parents[1], label.name], label.size 125 ) 126 list_labels_ds_a = [ 127 Label(name='FLASH', size=30, parents=tuple([])), 128 Label(name='RAM', size=320, parents=tuple([])), 129 ] 130 list_labels_ds_a += [Label(name='total', size=350)] 131 for label_hierarchy in ds_map.labels(0): 132 self.assertIn(label_hierarchy, list_labels_ds_a) 133 self.assertEqual(ds_map.get_total_size(), 350) 134 135 def test_parsing_generator_specified_datasource_int_2(self): 136 ds_map = DataSourceMap(['a', 'b', 'c']) 137 for label in LIST_LABELS: 138 ds_map.insert_label_hierarchy( 139 [label.parents[0], label.parents[1], label.name], label.size 140 ) 141 list_labels_ds_b = [ 142 Label(name='.code', size=30, parents=tuple(['FLASH'])), 143 Label(name='.heap', size=320, parents=tuple(['RAM'])), 144 ] 145 list_labels_ds_b += [Label(name='total', size=350)] 146 for label_hierarchy in ds_map.labels(1): 147 self.assertIn(label_hierarchy, list_labels_ds_b) 148 self.assertEqual(ds_map.get_total_size(), 350) 149 150 def test_diff_same_ds_labels_diff_sizes(self): 151 """Same map with different sizes.""" 152 ds_map = DataSourceMap(['a', 'b', 'c']) 153 for label in LIST_LABELS: 154 ds_map.insert_label_hierarchy( 155 [label.parents[0], label.parents[1], label.name], label.size 156 ) 157 158 ds_map2 = DataSourceMap(['a', 'b', 'c']) 159 for label in LIST_LABELS: 160 ds_map2.insert_label_hierarchy( 161 [label.parents[0], label.parents[1], label.name], 162 label.size + 10, 163 ) 164 165 list_labels_ds_b = [ 166 Label( 167 name='main()', 168 size=-10, 169 exists_both=True, 170 parents=tuple(['FLASH', '.code']), 171 ), 172 Label( 173 name='foo()', 174 size=-10, 175 exists_both=True, 176 parents=tuple(['RAM', '.heap']), 177 ), 178 Label( 179 name='bar()', 180 size=-10, 181 exists_both=True, 182 parents=tuple(['RAM', '.heap']), 183 ), 184 ] 185 186 ds_map_diff = ds_map.diff(ds_map2) 187 188 for label_hierarchy in ds_map_diff.labels(): 189 self.assertIn(label_hierarchy, list_labels_ds_b) 190 191 def test_diff_missing_ds_labels_diff_sizes(self): 192 """Different map with different sizes.""" 193 ds_map = DataSourceMap(['a', 'b', 'c']) 194 for label in LIST_LABELS: 195 ds_map.insert_label_hierarchy( 196 [label.parents[0], label.parents[1], label.name], label.size 197 ) 198 199 ds_map2 = DataSourceMap(['a', 'b', 'c']) 200 for label in LIST_LABELS[:-1]: 201 ds_map2.insert_label_hierarchy( 202 [label.parents[0], label.parents[1], label.name], 203 label.size + 20, 204 ) 205 ds_map2.insert_label_hierarchy( 206 [label.parents[0], label.parents[1], 'foobar()'], label.size + 20 207 ) 208 209 ds_map2.insert_label_hierarchy( 210 ["LOAD #5", 'random_load', 'func()'], 250 211 ) 212 213 list_labels_ds_b = [ 214 Label( 215 name='FLASH', 216 size=20, 217 capacity=None, 218 exists_both=True, 219 parents=(), 220 ), 221 Label( 222 name='RAM', 223 size=-80, 224 capacity=None, 225 exists_both=True, 226 parents=(), 227 ), 228 Label( 229 name='LOAD #5', 230 size=250, 231 capacity=None, 232 exists_both=False, 233 parents=(), 234 ), 235 ] 236 237 ds_map_diff = ds_map2.diff(ds_map) 238 239 for label_hierarchy in ds_map_diff.labels(0): 240 self.assertIn(label_hierarchy, list_labels_ds_b) 241 242 243if __name__ == '__main__': 244 unittest.main() 245