| #!/usr/bin/env python3 | 
 | # Copyright 2023 The Chromium Authors | 
 | # Use of this source code is governed by a BSD-style license that can be | 
 | # found in the LICENSE file. | 
 |  | 
 | import os | 
 | import pathlib | 
 | import shutil | 
 | import sys | 
 | import tempfile | 
 | import textwrap | 
 | import unittest | 
 | from unittest import mock | 
 |  | 
 | import clobber | 
 |  | 
 |  | 
 | class TestExtractBuildCommand(unittest.TestCase): | 
 |   def setUp(self): | 
 |     self.build_ninja_file, self.build_ninja_path = tempfile.mkstemp(text=True) | 
 |  | 
 |   def tearDown(self): | 
 |     os.close(self.build_ninja_file) | 
 |     os.remove(self.build_ninja_path) | 
 |  | 
 |   def test_normal_extraction(self): | 
 |     build_ninja_file_contents = textwrap.dedent(""" | 
 |         ninja_required_version = 1.7.2 | 
 |  | 
 |         rule gn | 
 |           command = ../../buildtools/gn --root=../.. -q --regeneration gen . | 
 |           pool = console | 
 |           description = Regenerating ninja files | 
 |  | 
 |         build build.ninja.stamp: gn | 
 |           generator = 1 | 
 |           depfile = build.ninja.d | 
 |  | 
 |         build build.ninja: phony build.ninja.stamp | 
 |           generator = 1 | 
 |  | 
 |         pool build_toolchain_action_pool | 
 |           depth = 72 | 
 |  | 
 |         pool build_toolchain_link_pool | 
 |           depth = 23 | 
 |  | 
 |         subninja toolchain.ninja | 
 |         subninja clang_newlib_x64/toolchain.ninja | 
 |         subninja glibc_x64/toolchain.ninja | 
 |         subninja irt_x64/toolchain.ninja | 
 |         subninja nacl_bootstrap_x64/toolchain.ninja | 
 |         subninja newlib_pnacl/toolchain.ninja | 
 |  | 
 |         build blink_python_tests: phony obj/blink_python_tests.stamp | 
 |         build blink_tests: phony obj/blink_tests.stamp | 
 |  | 
 |         default all | 
 |     """)  # Based off of a standard linux build dir. | 
 |     with open(self.build_ninja_path, 'w') as f: | 
 |       f.write(build_ninja_file_contents) | 
 |  | 
 |     expected_build_ninja_file_contents = textwrap.dedent(""" | 
 |         ninja_required_version = 1.7.2 | 
 |  | 
 |         rule gn | 
 |           command = ../../buildtools/gn --root=../.. -q --regeneration gen . | 
 |           pool = console | 
 |           description = Regenerating ninja files | 
 |  | 
 |         build build.ninja.stamp: gn | 
 |           generator = 1 | 
 |           depfile = build.ninja.d | 
 |  | 
 |         build build.ninja: phony build.ninja.stamp | 
 |           generator = 1 | 
 |  | 
 |     """) | 
 |  | 
 |     self.assertEqual(clobber.extract_gn_build_commands(self.build_ninja_path), | 
 |                      expected_build_ninja_file_contents) | 
 |  | 
 |   def test_unexpected_format(self): | 
 |     # No "build build.ninja:" line should make it return an empty string. | 
 |     build_ninja_file_contents = textwrap.dedent(""" | 
 |         ninja_required_version = 1.7.2 | 
 |  | 
 |         rule gn | 
 |           command = ../../buildtools/gn --root=../.. -q --regeneration gen . | 
 |           pool = console | 
 |           description = Regenerating ninja files | 
 |  | 
 |         subninja toolchain.ninja | 
 |  | 
 |         build blink_python_tests: phony obj/blink_python_tests.stamp | 
 |         build blink_tests: phony obj/blink_tests.stamp | 
 |  | 
 |     """) | 
 |     with open(self.build_ninja_path, 'w') as f: | 
 |       f.write(build_ninja_file_contents) | 
 |  | 
 |     self.assertEqual(clobber.extract_gn_build_commands(self.build_ninja_path), | 
 |                      '') | 
 |  | 
 |  | 
 | class TestDelete(unittest.TestCase): | 
 |   def setUp(self): | 
 |     self.build_dir = tempfile.mkdtemp() | 
 |  | 
 |     pathlib.Path(os.path.join(self.build_dir, 'build.ninja')).touch() | 
 |     pathlib.Path(os.path.join(self.build_dir, 'build.ninja.d')).touch() | 
 |  | 
 |   def tearDown(self): | 
 |     shutil.rmtree(self.build_dir) | 
 |  | 
 |   def test_delete_build_dir_full(self): | 
 |     # Create a dummy file in the build dir and ensure it gets removed. | 
 |     dummy_file = os.path.join(self.build_dir, 'dummy') | 
 |     pathlib.Path(dummy_file).touch() | 
 |  | 
 |     clobber.delete_build_dir(self.build_dir) | 
 |  | 
 |     self.assertFalse(os.path.exists(dummy_file)) | 
 |  | 
 |   def test_delete_build_dir_fail(self): | 
 |     # Make delete_dir() throw to ensure it's handled gracefully. | 
 |  | 
 |     with mock.patch('clobber._clean_dir', side_effect=OSError): | 
 |       with self.assertRaises(OSError): | 
 |         clobber.delete_build_dir(self.build_dir) | 
 |  | 
 |   @unittest.skipIf(sys.platform == 'win32', 'Symlinks are not allowed on Windows by default') | 
 |   def test_delete_build_dir_link(self): | 
 |     with tempfile.TemporaryDirectory() as tmpdir: | 
 |       # create a symlink. | 
 |       build_dir = os.path.join(tmpdir, 'link') | 
 |       os.symlink(self.build_dir, build_dir) | 
 |  | 
 |       # create a dummy file. | 
 |       dummy_file = os.path.join(build_dir, 'dummy') | 
 |       pathlib.Path(dummy_file).touch() | 
 |       clobber.delete_build_dir(build_dir) | 
 |  | 
 |       self.assertFalse(os.path.exists(dummy_file)) | 
 |  | 
 |  | 
 | if __name__ == '__main__': | 
 |   unittest.main() |