xref: /aosp_15_r20/external/pigweed/pw_bloat/py/label_test.py (revision 61c4878ac05f98d0ceed94b57d316916de578985)
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