[canary] Adding GitStatus tests (#28625)
These change adds coverage to `GitStatus`. It also adds some extra tests for `Patchfile` completing the coverage for that type. Resolves https://github.com/brave/brave-browser/issues/45234
This commit is contained in:
+1
-32
@@ -179,6 +179,7 @@ import sys
|
||||
from typing import Optional, List, Dict
|
||||
|
||||
from incendiary_error_handler import IncendiaryErrorHandler
|
||||
from git_status import GitStatus
|
||||
from patchfile import Patchfile
|
||||
import repository
|
||||
from repository import Repository, CHROMIUM_SRC_PATH
|
||||
@@ -305,38 +306,6 @@ def _get_apply_patches_list():
|
||||
return None
|
||||
|
||||
|
||||
class GitStatus:
|
||||
"""Runs `git status` and provides a summary.
|
||||
"""
|
||||
|
||||
def __init__(self):
|
||||
self.git_status = repository.brave.run_git('status', '--short')
|
||||
|
||||
# a list of all deleted files, regardless of their staged status.
|
||||
self.deleted = []
|
||||
|
||||
# a list of all modified files, regardless of their staged status.
|
||||
self.modified = []
|
||||
|
||||
# a list of all untracked files.
|
||||
self.untracked = []
|
||||
|
||||
for line in self.git_status.splitlines():
|
||||
[status, path] = line.lstrip().split(' ', 1)
|
||||
if status == 'D':
|
||||
self.deleted.append(path)
|
||||
elif status == 'M':
|
||||
self.modified.append(path)
|
||||
elif status == '??':
|
||||
self.untracked.append(path)
|
||||
|
||||
def has_deleted_patch_files(self):
|
||||
return any(path.endswith('.patch') for path in self.deleted)
|
||||
|
||||
def has_untracked_patch_files(self):
|
||||
return any(path.endswith('.patch') for path in self.untracked)
|
||||
|
||||
|
||||
@dataclass(frozen=True)
|
||||
class ApplyPatchesRecord:
|
||||
"""A class to hold the continuation data for patches.
|
||||
|
||||
@@ -0,0 +1,38 @@
|
||||
# Copyright (c) 2025 The Brave Authors. All rights reserved.
|
||||
# This Source Code Form is subject to the terms of the Mozilla Public
|
||||
# License, v. 2.0. If a copy of the MPL was not distributed with this file,
|
||||
# You can obtain one at https://mozilla.org/MPL/2.0/.
|
||||
|
||||
import repository
|
||||
|
||||
|
||||
class GitStatus:
|
||||
"""Runs `git status` and provides a summary.
|
||||
"""
|
||||
|
||||
def __init__(self):
|
||||
self.git_status = repository.brave.run_git('status', '--short')
|
||||
|
||||
# a list of all deleted files, regardless of their staged status.
|
||||
self.deleted = []
|
||||
|
||||
# a list of all modified files, regardless of their staged status.
|
||||
self.modified = []
|
||||
|
||||
# a list of all untracked files.
|
||||
self.untracked = []
|
||||
|
||||
for line in self.git_status.splitlines():
|
||||
[status, path] = line.lstrip().split(' ', 1)
|
||||
if status == 'D':
|
||||
self.deleted.append(path)
|
||||
elif status == 'M':
|
||||
self.modified.append(path)
|
||||
elif status == '??':
|
||||
self.untracked.append(path)
|
||||
|
||||
def has_deleted_patch_files(self):
|
||||
return any(path.endswith('.patch') for path in self.deleted)
|
||||
|
||||
def has_untracked_patch_files(self):
|
||||
return any(path.endswith('.patch') for path in self.untracked)
|
||||
Executable
+53
@@ -0,0 +1,53 @@
|
||||
#!/usr/bin/env vpython3
|
||||
# Copyright (c) 2025 The Brave Authors. All rights reserved.
|
||||
# This Source Code Form is subject to the terms of the Mozilla Public
|
||||
# License, v. 2.0. If a copy of the MPL was not distributed with this file,
|
||||
# You can obtain one at https://mozilla.org/MPL/2.0/.
|
||||
|
||||
import unittest
|
||||
from pathlib import Path
|
||||
|
||||
from test.fake_chromium_src import FakeChromiumSrc
|
||||
from git_status import GitStatus
|
||||
|
||||
|
||||
class GitStatusTest(unittest.TestCase):
|
||||
|
||||
def setUp(self):
|
||||
"""Set up a fake Chromium repository for testing."""
|
||||
self.fake_chromium_src = FakeChromiumSrc()
|
||||
self.fake_chromium_src.setup()
|
||||
self.addCleanup(self.fake_chromium_src.cleanup)
|
||||
|
||||
def test_has_deleted_patch_files(self):
|
||||
"""Test has_deleted_patch_files method."""
|
||||
self.assertFalse(GitStatus().has_deleted_patch_files())
|
||||
|
||||
# Create a patch file and commit it
|
||||
patch_file = 'patches/test.patch'
|
||||
self.fake_chromium_src.write_and_stage_file(
|
||||
patch_file, 'Patch content', self.fake_chromium_src.brave)
|
||||
self.fake_chromium_src.commit('Add test.patch',
|
||||
self.fake_chromium_src.brave)
|
||||
|
||||
# Delete the patch file
|
||||
self.fake_chromium_src.delete_file(patch_file,
|
||||
self.fake_chromium_src.brave)
|
||||
|
||||
# Run GitStatus and verify the deleted patch file is detected
|
||||
self.assertTrue(GitStatus().has_deleted_patch_files())
|
||||
|
||||
def test_has_untracked_patch_files(self):
|
||||
"""Test has_untracked_patch_files method."""
|
||||
self.assertFalse(GitStatus().has_untracked_patch_files())
|
||||
|
||||
# Create a patch file but do not stage it
|
||||
Path(self.fake_chromium_src.brave /
|
||||
'test_untracked.patch').write_text('Untracked patch content')
|
||||
|
||||
# Run GitStatus and verify the untracked patch file is detected
|
||||
self.assertTrue(GitStatus().has_untracked_patch_files())
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
unittest.main()
|
||||
@@ -6,7 +6,7 @@
|
||||
from dataclasses import dataclass, field, replace
|
||||
from enum import Enum, auto
|
||||
import logging
|
||||
from pathlib import PurePath
|
||||
from pathlib import PurePath, Path
|
||||
import re
|
||||
import subprocess
|
||||
from typing import Optional, NamedTuple
|
||||
|
||||
@@ -311,6 +311,220 @@ class PatchfileTest(unittest.TestCase):
|
||||
'patches/build-android-gyp-dex.py.patch')).path_from_repo(),
|
||||
'brave/patches/build-android-gyp-dex.py.patch')
|
||||
|
||||
def test_fetch_source_from_git(self):
|
||||
"""Test fetch_source_from_git with renamed patch file."""
|
||||
test_idl = Path('chrome/common/extensions/api/developer_private.idl')
|
||||
self.fake_chromium_src.write_and_stage_file(
|
||||
test_idl, """
|
||||
enum ExtensionType {
|
||||
HOSTED_APP,
|
||||
PLATFORM_APP,
|
||||
LEGACY_PACKAGED_APP,
|
||||
EXTENSION,
|
||||
THEME,
|
||||
SHARED_MODULE
|
||||
};
|
||||
""", self.fake_chromium_src.chromium)
|
||||
|
||||
self.fake_chromium_src.commit('Add developer_private.idl',
|
||||
self.fake_chromium_src.chromium)
|
||||
|
||||
# Create a patch for the file
|
||||
target_file = self.fake_chromium_src.chromium / test_idl
|
||||
target_file.write_text(target_file.read_text().replace(
|
||||
'HOSTED_APP', 'HOSTED_APP,\n NEW_TYPE'))
|
||||
self.fake_chromium_src.run_update_patches()
|
||||
|
||||
# Rename the patch file
|
||||
original_patch_path = (
|
||||
self.fake_chromium_src.get_patchfile_path_for_source(
|
||||
self.fake_chromium_src.chromium, test_idl))
|
||||
renamed_patch_path = original_patch_path.with_name(
|
||||
'renamed_developer_private.idl.patch')
|
||||
(self.fake_chromium_src.brave / original_patch_path).rename(
|
||||
self.fake_chromium_src.brave / renamed_patch_path)
|
||||
|
||||
# Fetch the source from the renamed patch file
|
||||
patchfile = Patchfile(path=renamed_patch_path)
|
||||
|
||||
# Verify the source file path matches the original file
|
||||
self.assertEqual(
|
||||
str(patchfile.fetch_source_from_git().source_from_git),
|
||||
str(test_idl))
|
||||
|
||||
def test_get_last_commit_for_source(self):
|
||||
"""Test get_last_commit_for_source method."""
|
||||
test_file = Path('chrome/common/extensions/api/developer_private.idl')
|
||||
self.fake_chromium_src.write_and_stage_file(
|
||||
test_file, """
|
||||
enum ExtensionType {
|
||||
HOSTED_APP,
|
||||
PLATFORM_APP,
|
||||
LEGACY_PACKAGED_APP,
|
||||
EXTENSION,
|
||||
THEME,
|
||||
SHARED_MODULE
|
||||
};
|
||||
""", self.fake_chromium_src.chromium)
|
||||
|
||||
# Commit the file and get the short commit hash
|
||||
initial_commit_hash = self.fake_chromium_src.commit(
|
||||
'Add developer_private.idl', self.fake_chromium_src.chromium)[:7]
|
||||
|
||||
# Create a patch for the file
|
||||
target_file = self.fake_chromium_src.chromium / test_file
|
||||
target_file.write_text(target_file.read_text().replace(
|
||||
'HOSTED_APP', 'HOSTED_APP,\n NEW_TYPE'))
|
||||
self.fake_chromium_src.run_update_patches()
|
||||
|
||||
# Add a few empty commits
|
||||
self.fake_chromium_src.commit_empty('Empty commit 1',
|
||||
self.fake_chromium_src.chromium)
|
||||
self.fake_chromium_src.commit_empty('Empty commit 2',
|
||||
self.fake_chromium_src.chromium)
|
||||
|
||||
# Verify the last commit for the source matches the initial commit hash
|
||||
patchfile_path = self.fake_chromium_src.get_patchfile_path_for_source(
|
||||
self.fake_chromium_src.chromium, test_file)
|
||||
patchfile = Patchfile(path=patchfile_path)
|
||||
self.assertEqual(patchfile.get_last_commit_for_source(),
|
||||
initial_commit_hash)
|
||||
|
||||
# Delete the file and commit
|
||||
self.fake_chromium_src.delete_file(test_file,
|
||||
self.fake_chromium_src.chromium)
|
||||
delete_commit_hash = self.fake_chromium_src.commit(
|
||||
'Delete developer_private.idl',
|
||||
self.fake_chromium_src.chromium)[:7]
|
||||
|
||||
# Add a few more empty commits
|
||||
self.fake_chromium_src.commit_empty('Empty commit 3',
|
||||
self.fake_chromium_src.chromium)
|
||||
self.fake_chromium_src.commit_empty('Empty commit 4',
|
||||
self.fake_chromium_src.chromium)
|
||||
|
||||
# Get the patch file path
|
||||
patchfile = Patchfile(path=patchfile_path)
|
||||
|
||||
# Verify the last commit for the source matches the delete commit hash
|
||||
self.assertEqual(patchfile.get_last_commit_for_source(),
|
||||
delete_commit_hash)
|
||||
|
||||
def test_get_source_removal_status(self):
|
||||
"""Test get_source_removal_status for a deleted source file."""
|
||||
test_file = Path('chrome/common/extensions/api/developer_private.idl')
|
||||
self.fake_chromium_src.write_and_stage_file(
|
||||
test_file, """
|
||||
enum ExtensionType {
|
||||
HOSTED_APP,
|
||||
PLATFORM_APP,
|
||||
LEGACY_PACKAGED_APP,
|
||||
EXTENSION,
|
||||
THEME,
|
||||
SHARED_MODULE
|
||||
};
|
||||
""", self.fake_chromium_src.chromium)
|
||||
|
||||
# Commit the file
|
||||
self.fake_chromium_src.commit('Add developer_private.idl',
|
||||
self.fake_chromium_src.chromium)
|
||||
|
||||
# Add a few empty commits
|
||||
self.fake_chromium_src.commit_empty('Empty commit 1',
|
||||
self.fake_chromium_src.chromium)
|
||||
self.fake_chromium_src.commit_empty('Empty commit 2',
|
||||
self.fake_chromium_src.chromium)
|
||||
|
||||
# Create a patch for the file
|
||||
target_file = self.fake_chromium_src.chromium / test_file
|
||||
target_file.write_text(target_file.read_text().replace(
|
||||
'HOSTED_APP', 'HOSTED_APP,\n NEW_TYPE'))
|
||||
self.fake_chromium_src.run_update_patches()
|
||||
|
||||
# Delete the file and commit
|
||||
self.fake_chromium_src.delete_file(test_file,
|
||||
self.fake_chromium_src.chromium)
|
||||
delete_commit_hash = self.fake_chromium_src.commit(
|
||||
'Delete developer_private.idl', self.fake_chromium_src.chromium)
|
||||
|
||||
# Get the patch file path
|
||||
patchfile_path = self.fake_chromium_src.get_patchfile_path_for_source(
|
||||
self.fake_chromium_src.chromium, test_file)
|
||||
patchfile = Patchfile(path=patchfile_path)
|
||||
|
||||
# Add a few more empty commits
|
||||
self.fake_chromium_src.commit_empty('Empty commit 3',
|
||||
self.fake_chromium_src.chromium)
|
||||
self.fake_chromium_src.commit_empty('Empty commit 4',
|
||||
self.fake_chromium_src.chromium)
|
||||
|
||||
# Verify the source removal status
|
||||
removal_status = patchfile.get_source_removal_status(
|
||||
delete_commit_hash)
|
||||
self.assertEqual(removal_status.status, 'D') # 'D' indicates deletion
|
||||
self.assertIn('Delete developer_private.idl',
|
||||
removal_status.commit_details)
|
||||
self.assertIsNone(removal_status.renamed_to)
|
||||
|
||||
def test_get_source_rename_status(self):
|
||||
"""Test get_source_removal_status for a renamed source file."""
|
||||
test_file = Path('chrome/common/extensions/api/developer_private.idl')
|
||||
renamed_file = Path('chrome/common/extensions/api/renamed_private.idl')
|
||||
|
||||
# Write and commit the original file
|
||||
self.fake_chromium_src.write_and_stage_file(
|
||||
test_file, """
|
||||
enum ExtensionType {
|
||||
HOSTED_APP,
|
||||
PLATFORM_APP,
|
||||
LEGACY_PACKAGED_APP,
|
||||
EXTENSION,
|
||||
THEME,
|
||||
SHARED_MODULE
|
||||
};
|
||||
""", self.fake_chromium_src.chromium)
|
||||
self.fake_chromium_src.commit('Add developer_private.idl',
|
||||
self.fake_chromium_src.chromium)
|
||||
|
||||
# Add a few empty commits
|
||||
self.fake_chromium_src.commit_empty('Empty commit 1',
|
||||
self.fake_chromium_src.chromium)
|
||||
self.fake_chromium_src.commit_empty('Empty commit 2',
|
||||
self.fake_chromium_src.chromium)
|
||||
|
||||
# Create a patch for the file
|
||||
target_file = self.fake_chromium_src.chromium / test_file
|
||||
target_file.write_text(target_file.read_text().replace(
|
||||
'HOSTED_APP', 'HOSTED_APP,\n NEW_TYPE'))
|
||||
self.fake_chromium_src.run_update_patches()
|
||||
|
||||
# Rename the file and commit
|
||||
(self.fake_chromium_src.chromium / test_file).rename(
|
||||
self.fake_chromium_src.chromium / renamed_file)
|
||||
self.fake_chromium_src._run_git_command(
|
||||
['add', '-A'], self.fake_chromium_src.chromium)
|
||||
rename_commit_hash = self.fake_chromium_src.commit(
|
||||
'Rename developer_private.idl to renamed_private.idl',
|
||||
self.fake_chromium_src.chromium)
|
||||
|
||||
# Get the patch file path
|
||||
patchfile_path = self.fake_chromium_src.get_patchfile_path_for_source(
|
||||
self.fake_chromium_src.chromium, test_file)
|
||||
patchfile = Patchfile(path=patchfile_path)
|
||||
|
||||
# Add a few more empty commits
|
||||
self.fake_chromium_src.commit_empty('Empty commit 3',
|
||||
self.fake_chromium_src.chromium)
|
||||
self.fake_chromium_src.commit_empty('Empty commit 4',
|
||||
self.fake_chromium_src.chromium)
|
||||
|
||||
# Verify the source rename status
|
||||
rename_status = patchfile.get_source_removal_status(rename_commit_hash)
|
||||
self.assertEqual(rename_status.status, 'R') # 'R' indicates rename
|
||||
self.assertIn('Rename developer_private.idl to renamed_private.idl',
|
||||
rename_status.commit_details)
|
||||
self.assertEqual(rename_status.renamed_to, str(renamed_file))
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
unittest.main()
|
||||
|
||||
Reference in New Issue
Block a user