#!/usr/bin/env python3 # -*- coding: utf-8 -*- # Copyright 2018 The Chromium OS Authors. All rights reserved. # Use of this source code is governed by a BSD-style license that can be # found in the LICENSE file. """Tests for redact_profile.py.""" from __future__ import division, print_function import io import unittest from afdo_redaction import redact_profile _redact_limit = redact_profile.dedup_records.__defaults__[0] def _redact(input_lines, summary_to=None): if isinstance(input_lines, str): input_lines = input_lines.splitlines() if summary_to is None: summary_to = io.StringIO() output_to = io.StringIO() redact_profile.run( profile_input_file=input_lines, summary_output_file=summary_to, profile_output_file=output_to) return output_to.getvalue() def _redact_with_summary(input_lines): summary = io.StringIO() result = _redact(input_lines, summary_to=summary) return result, summary.getvalue() def _generate_repeated_function_body(repeats, fn_name='_some_name'): # Arbitrary function body ripped from a textual AFDO profile. function_header = fn_name + ':1234:185' function_body = [ ' 6: 83', ' 15: 126', ' 62832: 126', ' 6: _ZNK5blink10PaintLayer14GroupedMappingEv:2349', ' 1: 206', ' 1: _ZNK5blink10PaintLayer14GroupedMappersEv:2060', ' 1: 206', ' 11: _ZNK5blink10PaintLayer25GetCompositedLayerMappingEv:800', ' 2.1: 80', ] # Be sure to zfill this, so the functions are output in sorted order. num_width = len(str(repeats)) lines = [] for i in range(repeats): num = str(i).zfill(num_width) lines.append(num + function_header) lines.extend(function_body) return lines class Tests(unittest.TestCase): """All of our tests for redact_profile.""" def test_no_input_works(self): self.assertEqual(_redact(''), '') def test_single_function_works(self): lines = _generate_repeated_function_body(1) result_file = '\n'.join(lines) + '\n' self.assertEqual(_redact(lines), result_file) def test_duplicate_of_single_function_works(self): lines = _generate_repeated_function_body(2) result_file = '\n'.join(lines) + '\n' self.assertEqual(_redact(lines), result_file) def test_not_too_many_duplicates_of_single_function_redacts_none(self): lines = _generate_repeated_function_body(_redact_limit - 1) result_file = '\n'.join(lines) + '\n' self.assertEqual(_redact(lines), result_file) def test_many_duplicates_of_single_function_redacts_them_all(self): lines = _generate_repeated_function_body(_redact_limit) self.assertEqual(_redact(lines), '') def test_many_duplicates_of_single_function_leaves_other_functions(self): kept_lines = _generate_repeated_function_body(1, fn_name='_keep_me') # Something to distinguish us from the rest. Just bump a random counter. kept_lines[1] += '1' result_file = '\n'.join(kept_lines) + '\n' lines = _generate_repeated_function_body( _redact_limit, fn_name='_discard_me') self.assertEqual(_redact(kept_lines + lines), result_file) self.assertEqual(_redact(lines + kept_lines), result_file) more_lines = _generate_repeated_function_body( _redact_limit, fn_name='_and_discard_me') self.assertEqual(_redact(lines + kept_lines + more_lines), result_file) self.assertEqual(_redact(lines + more_lines), '') def test_correct_summary_is_printed_when_nothing_is_redacted(self): lines = _generate_repeated_function_body(1) _, summary = _redact_with_summary(lines) self.assertIn('Retained 1/1 functions', summary) self.assertIn('Retained 827/827 samples, total', summary) # Note that top-level samples == "samples without inlining taken into # account," not "sum(entry_counts)" self.assertIn('Retained 335/335 top-level samples', summary) def test_correct_summary_is_printed_when_everything_is_redacted(self): lines = _generate_repeated_function_body(_redact_limit) _, summary = _redact_with_summary(lines) self.assertIn('Retained 0/100 functions', summary) self.assertIn('Retained 0/82,700 samples, total', summary) self.assertIn('Retained 0/33,500 top-level samples', summary) def test_correct_summary_is_printed_when_most_everything_is_redacted(self): kept_lines = _generate_repeated_function_body(1, fn_name='_keep_me') kept_lines[1] += '1' lines = _generate_repeated_function_body(_redact_limit) _, summary = _redact_with_summary(kept_lines + lines) self.assertIn('Retained 1/101 functions', summary) self.assertIn('Retained 1,575/84,275 samples, total', summary) self.assertIn('Retained 1,083/34,583 top-level samples', summary) if __name__ == '__main__': unittest.main()