#!/usr/bin/env vpython3 # Copyright 2021 The Chromium Authors # Use of this source code is governed by a BSD-style license that can be # found in the LICENSE file. from logging import exception import os import sys import unittest import tempfile import shutil sys.path.insert(0, os.path.join(os.path.dirname(__file__), os.pardir, 'perf')) from core import path_util path_util.AddPyUtilsToPath() path_util.AddTracingToPath() import py_utils import rename_breakpad import mock class RenameBreakpadFilesTestCase(unittest.TestCase): def setUp(self): self.breakpad_dir = tempfile.mkdtemp() self.breakpad_output_dir = tempfile.mkdtemp() # Directory to unzipped breakpad files. self.breakpad_unzip_dir = tempfile.mkdtemp(dir=self.breakpad_dir) def tearDown(self): shutil.rmtree(self.breakpad_dir) shutil.rmtree(self.breakpad_output_dir) def _listSubtree(self, root): """Returns absolute paths of files and dirs in root subtree. """ files = set() dirs = set() for topdir, subdirs, filenames in os.walk(root): for filename in filenames: files.add(os.path.join(topdir, filename)) for subdir in subdirs: dirs.add(os.path.join(topdir, subdir)) return dirs, files def _assertFilesInInputDir(self, expected_unmoved_files=frozenset(), expected_unmoved_dirs=frozenset()): """Ensures that |RenameBreakpadFiles| doesn't move files/dirs. Automatically adds |self.breakpad_unzip_dir| to |expected_unmoved_dirs| since this file should never be moved. """ breakpad_unzip_dir = {self.breakpad_unzip_dir} expected_unmoved_dirs = expected_unmoved_dirs.union(breakpad_unzip_dir) unmoved_dirs, unmoved_files = self._listSubtree(self.breakpad_dir) self.assertEqual(expected_unmoved_files, unmoved_files) self.assertEqual(expected_unmoved_dirs, unmoved_dirs) def _assertFilesInOutputDir(self, expected_moved_files=frozenset()): """Ensures that |RenameBreakpadFiles| correctly moves files. """ moved_files = set(os.listdir(self.breakpad_output_dir)) self.assertEqual(expected_moved_files, moved_files) def testRenameBreakpadFiles(self): breakpad_file1 = os.path.join(self.breakpad_unzip_dir, 'file1.breakpad') breakpad_file2 = os.path.join(self.breakpad_unzip_dir, 'file2.breakpad') with open(breakpad_file1, 'w') as file1: file1.write('MODULE Linux x86_64 34984AB4EF948C name1.so') with open(breakpad_file2, 'w') as file2: file2.write('MODULE mac x86_64 29e6f9a7ce00f name2.so') rename_breakpad.RenameBreakpadFiles(self.breakpad_dir, self.breakpad_output_dir) self._assertFilesInInputDir() expected_moved_files = {'34984AB4EF948C.breakpad', '29E6F9A7CE00F.breakpad'} self._assertFilesInOutputDir(expected_moved_files) def testRenameBreakpadFilesUpperCaseName(self): breakpad_file1 = os.path.join(self.breakpad_unzip_dir, 'file1.breakpad') with open(breakpad_file1, 'w') as file1: file1.write('MODULE Linux x86_64 12a345b6c7def890 name1.so') rename_breakpad.RenameBreakpadFiles(self.breakpad_dir, self.breakpad_output_dir) self._assertFilesInInputDir() expected_moved_files = {'12A345B6C7DEF890.breakpad'} self._assertFilesInOutputDir(expected_moved_files) def testRenameBreakpadFilesLinuxx86_64(self): breakpad_file1 = os.path.join(self.breakpad_unzip_dir, 'file1.breakpad.x64') with open(breakpad_file1, 'w') as file1: file1.write('MODULE Linux x86_64 34984AB4EF948C name1.so') rename_breakpad.RenameBreakpadFiles(self.breakpad_dir, self.breakpad_output_dir) self._assertFilesInInputDir() expected_moved_files = {'34984AB4EF948C.breakpad'} self._assertFilesInOutputDir(expected_moved_files) def testRenameBreakpadFilesMultipleSubdirs(self): subdir1 = tempfile.mkdtemp(dir=self.breakpad_unzip_dir) subdir2 = tempfile.mkdtemp(dir=self.breakpad_unzip_dir) breakpad_file1 = os.path.join(subdir1, 'file1.breakpad') breakpad_file2 = os.path.join(subdir2, 'file2.breakpad') breakpad_file3 = os.path.join(self.breakpad_unzip_dir, 'file3.breakpad') with open(breakpad_file1, 'w') as file1: file1.write('MODULE Linux x86_64 48537ABD name1.so') with open(breakpad_file2, 'w') as file2: file2.write('MODULE mac x86_64 38ABC9F name2.so') with open(breakpad_file3, 'w') as file3: file3.write('MODULE mac x86_64 45DFE name3.so') rename_breakpad.RenameBreakpadFiles(self.breakpad_dir, self.breakpad_output_dir) expected_unmoved_dirs = {subdir1, subdir2} self._assertFilesInInputDir(expected_unmoved_dirs=expected_unmoved_dirs) expected_moved_files = { '48537ABD.breakpad', '38ABC9F.breakpad', '45DFE.breakpad' } self._assertFilesInOutputDir(expected_moved_files) def testRenameBreakpadFilesNonBreakpad(self): valid_file = os.path.join(self.breakpad_unzip_dir, 'valid.breakpad') fake_file = os.path.join(self.breakpad_unzip_dir, 'fake.gz') empty_file = os.path.join(self.breakpad_unzip_dir, 'empty.json') random_dir = tempfile.mkdtemp(dir=self.breakpad_dir) non_breakpad_file = os.path.join(random_dir, 'random.txt') with open(valid_file, 'w') as file1: file1.write('MODULE mac x86_64 329FDEA987BC name.so') with open(fake_file, 'w') as file2: file2.write('random text blah blah blah') with open(empty_file, 'w'): pass with open(non_breakpad_file, 'w') as file3: file3.write('MODULE mac x86_64 329FDEA987BC name.so') rename_breakpad.RenameBreakpadFiles(self.breakpad_dir, self.breakpad_output_dir) expected_unmoved_files = {fake_file, empty_file, non_breakpad_file} expected_unmoved_dirs = {random_dir} self._assertFilesInInputDir(expected_unmoved_files, expected_unmoved_dirs) expected_moved_files = {'329FDEA987BC.breakpad'} self._assertFilesInOutputDir(expected_moved_files) def testRenameBreakpadFilesInvalidBreakpad(self): valid_file = os.path.join(self.breakpad_unzip_dir, 'valid.breakpad') empty_file = os.path.join(self.breakpad_unzip_dir, 'empty.breakpad') no_module_file = os.path.join(self.breakpad_unzip_dir, 'no-module.breakpad') short_file = os.path.join(self.breakpad_unzip_dir, 'short.breakpad') with open(valid_file, 'w') as file1: file1.write('MODULE mac x86_64 1240DF90E9AC39038EF400 Chrome Name') with open(empty_file, 'w'): pass with open(no_module_file, 'w') as file2: file2.write('NOTMODULE mac x86_64 1240DF90E9AC39038EF400 name') with open(short_file, 'w') as file3: file3.write('MODULE mac 1240DF90E9AC39038EF400 name') rename_breakpad.RenameBreakpadFiles(self.breakpad_dir, self.breakpad_output_dir) expected_unmoved_files = {empty_file, no_module_file, short_file} self._assertFilesInInputDir(expected_unmoved_files) expected_moved_files = {'1240DF90E9AC39038EF400.breakpad'} self._assertFilesInOutputDir(expected_moved_files) def testRenameBreakpadFilesOnlyNonBreakpadAndMisformat(self): fake_file = os.path.join(self.breakpad_unzip_dir, 'fake.breakpad') empty_file = os.path.join(self.breakpad_unzip_dir, 'empty.breakpad') no_module_file = os.path.join(self.breakpad_unzip_dir, 'no-module.breakpad') short_file = os.path.join(self.breakpad_unzip_dir, 'short.breakpad') random_dir = tempfile.mkdtemp(dir=self.breakpad_dir) non_breakpad_file = os.path.join(random_dir, 'random.txt') with open(fake_file, 'w') as file1: file1.write('random text blah blah blah') with open(empty_file, 'w'): pass with open(no_module_file, 'w') as file2: file2.write('NOTMODULE mac x86_64 1240DF90E9AC39038EF400 name') with open(short_file, 'w') as file3: file3.write('MODULE mac 1240DF90E9AC39038EF400 name') with open(non_breakpad_file, 'w') as file4: file4.write('MODULE mac x86_64 1240DF90E9AC39038EF400 Chrome Name') rename_breakpad.RenameBreakpadFiles(self.breakpad_dir, self.breakpad_output_dir) expected_unmoved_files = { fake_file, non_breakpad_file, empty_file, no_module_file, short_file } expected_unmoved_dirs = {random_dir} self._assertFilesInInputDir(expected_unmoved_files, expected_unmoved_dirs) self._assertFilesInOutputDir() def testRenameBreakpadFilesRepeatedModuleID(self): breakpad_file1 = os.path.join(self.breakpad_unzip_dir, 'file1.breakpad') breakpad_file2 = os.path.join(self.breakpad_unzip_dir, 'file2.breakpad') with open(breakpad_file1, 'w') as file1: file1.write('MODULE mac x86_64 12ABC8987DE name.so') with open(breakpad_file2, 'w') as file2: file2.write('MODULE mac x86_64 12ABC8987DE name.so') # Check that the right exception is raised. exception_msg = ('Symbol file modules ids are not unique') with self.assertRaises(AssertionError) as e: rename_breakpad.RenameBreakpadFiles(self.breakpad_dir, self.breakpad_output_dir) self.assertIn(exception_msg, str(e.exception)) # Check breakpad file with repeated module id is not moved. More # complicated because either of the breakpad files could be moved. self.assertTrue( os.path.isfile(breakpad_file1) ^ os.path.isfile(breakpad_file2)) # Ensure one of the breakpad module files got moved. No matter which # breakpad file got moved, it will have the same new module-based filename. expected_moved_files = {'12ABC8987DE.breakpad'} self._assertFilesInOutputDir(expected_moved_files) def testRenameBreakpadFilesRepeatedModuleIDMultipleSubdirs(self): subdir1 = tempfile.mkdtemp(dir=self.breakpad_unzip_dir) subdir2 = tempfile.mkdtemp(dir=self.breakpad_unzip_dir) breakpad_file1 = os.path.join(subdir1, 'file1.breakpad') breakpad_file2 = os.path.join(subdir2, 'file2.breakpad') with open(breakpad_file1, 'w') as file1: file1.write('MODULE mac x86_64 ABCE4853004895 name.so') with open(breakpad_file2, 'w') as file2: file2.write('MODULE mac x86_64 ABCE4853004895 name.so') # Check that the right exception is raised. exception_msg = ('Symbol file modules ids are not unique') with self.assertRaises(AssertionError) as e: rename_breakpad.RenameBreakpadFiles(self.breakpad_dir, self.breakpad_output_dir) self.assertIn(exception_msg, str(e.exception)) # Check breakpad file with repeated module id is not moved. More # complicated because either of the breakpad files could be moved. self.assertTrue( os.path.isfile(breakpad_file1) ^ os.path.isfile(breakpad_file2)) # Ensure one of the breakpad module files got moved. No matter which # breakpad file got moved, it will have the same new module-based filename. expected_moved_files = {'ABCE4853004895.breakpad'} self._assertFilesInOutputDir(expected_moved_files) def testRenameBreakpadFilesInputDirEqualsOutputDir(self): subdir = tempfile.mkdtemp(dir=self.breakpad_unzip_dir) breakpad_file1 = os.path.join(self.breakpad_unzip_dir, 'file1.breakpad') breakpad_file2 = os.path.join(subdir, 'file2.breakpad') with open(breakpad_file1, 'w') as file1: file1.write('MODULE Linux x86_64 34984AB4EF948C name1.so') with open(breakpad_file2, 'w') as file2: file2.write('MODULE mac x86_64 29e6f9a7ce00f name2.so') rename_breakpad.RenameBreakpadFiles(self.breakpad_dir, self.breakpad_dir) # All files should be moved into |self.breakpad_dir|. moved_breakpad1 = os.path.join(self.breakpad_dir, '34984AB4EF948C.breakpad') moved_breakpad2 = os.path.join(self.breakpad_dir, '29E6F9A7CE00F.breakpad') expected_files = {moved_breakpad1, moved_breakpad2} expected_unmoved_dirs = {subdir} self._assertFilesInInputDir(expected_files, expected_unmoved_dirs) # No files should be moved to |self.breakpad_output_dir|. self._assertFilesInOutputDir() def testRenameBreakpadFilesAllUnmoved(self): breakpad_file1 = os.path.join(self.breakpad_unzip_dir, 'file1.breakpad') breakpad_file2 = os.path.join(self.breakpad_unzip_dir, 'file2.breakpad') with open(breakpad_file1, 'w') as file1: file1.write('MODULE Linux x86_64 34984AB4EF948C name1.so') with open(breakpad_file2, 'w') as file2: file2.write('MODULE mac x86_64 29e6f9a7ce00f name2.so') rename_breakpad.RenameBreakpadFiles(self.breakpad_dir, self.breakpad_unzip_dir) # All files should be renamed but not moved. unmoved_breakpad1 = os.path.join(self.breakpad_unzip_dir, '34984AB4EF948C.breakpad') unmoved_breakpad2 = os.path.join(self.breakpad_unzip_dir, '29E6F9A7CE00F.breakpad') expected_renamed_files = {unmoved_breakpad1, unmoved_breakpad2} self._assertFilesInInputDir(expected_renamed_files) # No files should be moved to |self.breakpad_output_dir|. self._assertFilesInOutputDir() if __name__ == '__main__': unittest.main()