1#!/usr/bin/env python3 2# Copyright 2023 The Chromium Authors 3# Use of this source code is governed by a BSD-style license that can be 4# found in the LICENSE file. 5 6import os 7import pathlib 8import shutil 9import sys 10import tempfile 11import textwrap 12import unittest 13from unittest import mock 14 15import clobber 16 17 18class TestExtractBuildCommand(unittest.TestCase): 19 def setUp(self): 20 self.build_ninja_file, self.build_ninja_path = tempfile.mkstemp(text=True) 21 22 def tearDown(self): 23 os.close(self.build_ninja_file) 24 os.remove(self.build_ninja_path) 25 26 def test_normal_extraction(self): 27 build_ninja_file_contents = textwrap.dedent(""" 28 ninja_required_version = 1.7.2 29 30 rule gn 31 command = ../../buildtools/gn --root=../.. -q --regeneration gen . 32 pool = console 33 description = Regenerating ninja files 34 35 build build.ninja.stamp: gn 36 generator = 1 37 depfile = build.ninja.d 38 39 build build.ninja: phony build.ninja.stamp 40 generator = 1 41 42 pool build_toolchain_action_pool 43 depth = 72 44 45 pool build_toolchain_link_pool 46 depth = 23 47 48 subninja toolchain.ninja 49 subninja clang_newlib_x64/toolchain.ninja 50 subninja glibc_x64/toolchain.ninja 51 subninja irt_x64/toolchain.ninja 52 subninja nacl_bootstrap_x64/toolchain.ninja 53 subninja newlib_pnacl/toolchain.ninja 54 55 build blink_python_tests: phony obj/blink_python_tests.stamp 56 build blink_tests: phony obj/blink_tests.stamp 57 58 default all 59 """) # Based off of a standard linux build dir. 60 with open(self.build_ninja_path, 'w') as f: 61 f.write(build_ninja_file_contents) 62 63 expected_build_ninja_file_contents = textwrap.dedent(""" 64 ninja_required_version = 1.7.2 65 66 rule gn 67 command = ../../buildtools/gn --root=../.. -q --regeneration gen . 68 pool = console 69 description = Regenerating ninja files 70 71 build build.ninja.stamp: gn 72 generator = 1 73 depfile = build.ninja.d 74 75 build build.ninja: phony build.ninja.stamp 76 generator = 1 77 78 """) 79 80 self.assertEqual(clobber.extract_gn_build_commands(self.build_ninja_path), 81 expected_build_ninja_file_contents) 82 83 def test_unexpected_format(self): 84 # No "build build.ninja:" line should make it return an empty string. 85 build_ninja_file_contents = textwrap.dedent(""" 86 ninja_required_version = 1.7.2 87 88 rule gn 89 command = ../../buildtools/gn --root=../.. -q --regeneration gen . 90 pool = console 91 description = Regenerating ninja files 92 93 subninja toolchain.ninja 94 95 build blink_python_tests: phony obj/blink_python_tests.stamp 96 build blink_tests: phony obj/blink_tests.stamp 97 98 """) 99 with open(self.build_ninja_path, 'w') as f: 100 f.write(build_ninja_file_contents) 101 102 self.assertEqual(clobber.extract_gn_build_commands(self.build_ninja_path), 103 '') 104 105 106class TestDelete(unittest.TestCase): 107 def setUp(self): 108 self.build_dir = tempfile.mkdtemp() 109 110 pathlib.Path(os.path.join(self.build_dir, 'build.ninja')).touch() 111 pathlib.Path(os.path.join(self.build_dir, 'build.ninja.d')).touch() 112 113 def tearDown(self): 114 shutil.rmtree(self.build_dir) 115 116 def test_delete_build_dir_full(self): 117 # Create a dummy file in the build dir and ensure it gets removed. 118 dummy_file = os.path.join(self.build_dir, 'dummy') 119 pathlib.Path(dummy_file).touch() 120 121 clobber.delete_build_dir(self.build_dir) 122 123 self.assertFalse(os.path.exists(dummy_file)) 124 125 def test_delete_build_dir_fail(self): 126 # Make delete_dir() throw to ensure it's handled gracefully. 127 128 with mock.patch('clobber._clean_dir', side_effect=OSError): 129 with self.assertRaises(OSError): 130 clobber.delete_build_dir(self.build_dir) 131 132 @unittest.skipIf(sys.platform == 'win32', 'Symlinks are not allowed on Windows by default') 133 def test_delete_build_dir_link(self): 134 with tempfile.TemporaryDirectory() as tmpdir: 135 # create a symlink. 136 build_dir = os.path.join(tmpdir, 'link') 137 os.symlink(self.build_dir, build_dir) 138 139 # create a dummy file. 140 dummy_file = os.path.join(build_dir, 'dummy') 141 pathlib.Path(dummy_file).touch() 142 clobber.delete_build_dir(build_dir) 143 144 self.assertFalse(os.path.exists(dummy_file)) 145 146 147if __name__ == '__main__': 148 unittest.main() 149