blob: 3b33d0ec73c7384632aa39b063db0d7cd75d6dcb [file]
#!/usr/bin/env vpython3
# Copyright 2026 The Chromium Authors
# Use of this source code is governed by a BSD-style license that can be
# found in the LICENSE file.
"""Unit tests for find_chromium_root.py."""
import contextlib
import io
import os
import tempfile
import textwrap
import unittest
import find_chromium_root
CHROMIUM_GCLIENT = """
solutions = [
{
"name": "src",
"url": "https://chromium.googlesource.com/chromium/src.git",
"managed": False,
"custom_deps": {},
"custom_vars": {
"checkout_pgo_profiles": True,
},
},
]
target_os = ["android"]
"""
STANDALONE_GCLIENT = """
solutions = [
{
"name": "devtools-frontend",
"url": "https://chromium.googlesource.com/devtools/devtools-frontend.git",
"deps_file": "DEPS",
"managed": False,
"custom_deps": {},
},
]
"""
class FindChromiumRootTest(unittest.TestCase):
def setUp(self):
tmpdir = tempfile.TemporaryDirectory()
self.addCleanup(tmpdir.cleanup)
# Resolve symlinks (e.g. /tmp on macOS), so we can compare paths.
self.tmp = os.path.realpath(tmpdir.name)
def mkdir(self, *parts):
directory = os.path.join(self.tmp, *parts)
os.makedirs(directory, exist_ok=True)
return directory
def write_gclient(self, directory, content):
gclient_file = os.path.join(directory, '.gclient')
with open(gclient_file, 'w', encoding='utf-8') as f:
f.write(textwrap.dedent(content))
return gclient_file
def test_standalone_checkout(self):
devtools = self.mkdir('devtools', 'devtools-frontend')
self.write_gclient(self.mkdir('devtools'), STANDALONE_GCLIENT)
self.assertIsNone(find_chromium_root.find_chromium_root(devtools))
def test_no_gclient_file_is_standalone(self):
devtools = self.mkdir('devtools-frontend')
self.assertIsNone(find_chromium_root.find_chromium_root(devtools))
def test_current_location_in_chromium(self):
src = self.mkdir('chromium', 'src')
devtools = self.mkdir('chromium', 'src', 'third_party',
'devtools-frontend', 'src')
self.write_gclient(self.mkdir('chromium'), CHROMIUM_GCLIENT)
self.assertEqual(find_chromium_root.find_chromium_root(devtools), src)
def test_new_location_in_chromium(self):
src = self.mkdir('chromium', 'src')
devtools = self.mkdir('chromium', 'src', 'third_party', 'devtools')
self.write_gclient(self.mkdir('chromium'), CHROMIUM_GCLIENT)
self.assertEqual(find_chromium_root.find_chromium_root(devtools), src)
def test_trailing_separator_and_relative_segments(self):
src = self.mkdir('chromium', 'src')
devtools = self.mkdir('chromium', 'src', 'third_party', 'devtools')
self.write_gclient(self.mkdir('chromium'), CHROMIUM_GCLIENT)
self.assertEqual(
find_chromium_root.find_chromium_root(
os.path.join(devtools, 'scripts', '..') + os.sep), src)
def test_closest_gclient_file_wins(self):
# A standalone checkout that happens to be nested in a Chromium
# checkout.
self.mkdir('chromium', 'src')
self.write_gclient(self.mkdir('chromium'), CHROMIUM_GCLIENT)
nested = self.mkdir('chromium', 'src', 'nested')
devtools = self.mkdir('chromium', 'src', 'nested', 'devtools-frontend')
self.write_gclient(nested, STANDALONE_GCLIENT)
self.assertIsNone(find_chromium_root.find_chromium_root(devtools))
def test_not_covered_by_any_solution_is_standalone(self):
self.mkdir('chromium', 'src')
devtools = self.mkdir('chromium', 'elsewhere', 'devtools-frontend')
self.write_gclient(self.mkdir('chromium'), CHROMIUM_GCLIENT)
self.assertIsNone(find_chromium_root.find_chromium_root(devtools))
def test_solution_with_common_name_prefix_does_not_match(self):
self.mkdir('chromium', 'src')
devtools = self.mkdir('chromium', 'src-internal', 'devtools')
self.write_gclient(self.mkdir('chromium'), CHROMIUM_GCLIENT)
self.assertIsNone(find_chromium_root.find_chromium_root(devtools))
def test_multiple_solutions(self):
src = self.mkdir('chromium', 'src')
devtools = self.mkdir('chromium', 'src', 'third_party', 'devtools')
self.write_gclient(
self.mkdir('chromium'), """
solutions = [
{"name": "src-internal", "url": None},
{"name": "src", "url": None},
]
""")
self.assertEqual(find_chromium_root.find_chromium_root(devtools), src)
@unittest.skipUnless(hasattr(os, 'symlink'), 'requires symlinks')
def test_symlinked_standalone_checkout(self):
standalone = self.mkdir('devtools', 'devtools-frontend')
self.write_gclient(self.mkdir('devtools'), STANDALONE_GCLIENT)
src = self.mkdir('chromium', 'src')
self.write_gclient(self.mkdir('chromium'), CHROMIUM_GCLIENT)
link = os.path.join(self.mkdir('chromium', 'src', 'third_party'),
'devtools')
try:
os.symlink(standalone, link, True)
except OSError:
self.skipTest('unable to create symlinks')
# Via the symlink we are part of Chromium, via the real path we are
# a standalone checkout.
self.assertEqual(find_chromium_root.find_chromium_root(link), src)
self.assertIsNone(find_chromium_root.find_chromium_root(standalone))
def test_default_devtools_root_is_the_checkout_of_this_file(self):
expected = os.path.dirname(
os.path.dirname(os.path.abspath(find_chromium_root.__file__)))
self.assertEqual(find_chromium_root._default_devtools_root(), expected)
def test_gclient_file_is_executed_like_gclient_does(self):
src = self.mkdir('chromium', 'src')
devtools = self.mkdir('chromium', 'src', 'third_party', 'devtools')
self.write_gclient(
self.mkdir('chromium'), """
name = "s" + "rc"
solutions = [{"name": name}]
""")
self.assertEqual(find_chromium_root.find_chromium_root(devtools), src)
def test_version_file_fallback_without_gclient_file(self):
src = self.mkdir('chromium-1.2.3.4')
self.mkdir('chromium-1.2.3.4', 'chrome')
with open(os.path.join(src, 'chrome', 'VERSION'), 'w') as f:
f.write('MAJOR=1\n')
devtools = self.mkdir('chromium-1.2.3.4', 'third_party', 'devtools')
self.assertEqual(find_chromium_root.find_chromium_root(devtools), src)
def test_version_file_is_ignored_with_gclient_file(self):
# The `.gclient` file is the source of truth if it exists.
self.mkdir('chromium', 'src', 'chrome')
with open(
os.path.join(self.tmp, 'chromium', 'src', 'chrome', 'VERSION'),
'w') as f:
f.write('MAJOR=1\n')
nested = self.mkdir('chromium', 'src', 'nested')
devtools = self.mkdir('chromium', 'src', 'nested', 'devtools-frontend')
self.write_gclient(nested, STANDALONE_GCLIENT)
self.assertIsNone(find_chromium_root.find_chromium_root(devtools))
def test_invalid_gclient_file_raises(self):
devtools = self.mkdir('devtools', 'devtools-frontend')
for content in [
'solutions = [',
'solutions = get_solutions()',
'solutions = "src"',
'solutions = [{"url": None}]',
]:
with self.subTest(content=content):
self.write_gclient(self.mkdir('devtools'), content)
with self.assertRaises(find_chromium_root.GclientParseError):
find_chromium_root.find_chromium_root(devtools)
def test_gclient_file_without_solutions_is_standalone(self):
devtools = self.mkdir('devtools', 'devtools-frontend')
self.write_gclient(self.mkdir('devtools'), 'target_os = ["android"]')
self.assertIsNone(find_chromium_root.find_chromium_root(devtools))
class MainTest(unittest.TestCase):
def setUp(self):
tmpdir = tempfile.TemporaryDirectory()
self.addCleanup(tmpdir.cleanup)
self.tmp = os.path.realpath(tmpdir.name)
def run_main(self, devtools_root):
stdout, stderr = io.StringIO(), io.StringIO()
with contextlib.redirect_stdout(stdout), contextlib.redirect_stderr(
stderr):
status = find_chromium_root.main(
['--devtools-root', devtools_root])
return status, stdout.getvalue(), stderr.getvalue()
def write_gclient(self, content):
with open(os.path.join(self.tmp, '.gclient'), 'w',
encoding='utf-8') as f:
f.write(textwrap.dedent(content))
def test_prints_chromium_root(self):
src = os.path.join(self.tmp, 'src')
devtools = os.path.join(src, 'third_party', 'devtools')
os.makedirs(devtools)
self.write_gclient(CHROMIUM_GCLIENT)
self.assertEqual(self.run_main(devtools), (0, src + '\n', ''))
def test_prints_nothing_for_standalone(self):
devtools = os.path.join(self.tmp, 'devtools-frontend')
os.makedirs(devtools)
self.write_gclient(STANDALONE_GCLIENT)
self.assertEqual(self.run_main(devtools), (0, '', ''))
def test_fails_for_invalid_gclient_file(self):
devtools = os.path.join(self.tmp, 'devtools-frontend')
os.makedirs(devtools)
self.write_gclient('solutions = [')
status, stdout, stderr = self.run_main(devtools)
self.assertEqual(status, 1)
self.assertEqual(stdout, '')
self.assertIn('.gclient', stderr)
if __name__ == '__main__':
unittest.main()