mongo/buildscripts/bazel_rules_mongo/tests/test_changed_files.py

170 lines
6.3 KiB
Python

import os
import platform
import shutil
import sys
import tempfile
import unittest
from git import Repo
from mock import MagicMock
from buildscripts.bazel_rules_mongo.utils import evergreen_git
changed_file_name = "changed_file.txt"
new_file_name = "new_file.txt"
def write_file(repo: Repo, file_name: str) -> None:
# just adding more text to the file so git thinks it has changed or is created
with open(os.path.join(repo.working_tree_dir, file_name), "a+") as file:
file.write("change\n")
@unittest.skipIf(
sys.platform == "win32" or platform.machine().lower() in {"ppc64le", "s390x"},
reason="This test breaks on windows and only needs to work on linux",
)
class TestChangedFiles(unittest.TestCase):
@classmethod
def setUpClass(cls):
cls.tmp_dir = tempfile.mkdtemp()
root_repo = Repo()
# commit of HEAD
commit = root_repo.head.commit.hexsha
files_to_copy = set()
# copy the current repo into a temp dir to do testing on
root_repo.git.execute(["git", "worktree", "add", cls.tmp_dir, commit])
# get tracked files that have been changed that are tracked by git
diff_output = root_repo.git.execute(
["git", "diff", "--name-only", "--diff-filter=d", commit]
)
files_to_copy.update(diff_output.split("\n"))
# gets all the untracked changes in the current repo
untracked_changes = root_repo.git.execute(["git", "add", ".", "-n"])
for line in untracked_changes.split("\n"):
if not line:
continue
files_to_copy.add(line.strip()[5:-1])
# copy all changed files from the current repo to the new worktree for testing.
for file in files_to_copy:
if not file:
continue
if not os.path.exists(file):
raise RuntimeError(f"Changed file was found and does not exist: {file}")
# This means the file is an embeded git repo, this happens when other evergreen modules
# are present, we can just ignore them
if os.path.isdir(file):
continue
new_dest = os.path.join(cls.tmp_dir, file)
os.makedirs(os.path.dirname(new_dest), exist_ok=True)
shutil.copy(file, new_dest)
cls.repo = Repo(cls.tmp_dir)
# add a testing file to this original commit so we can treat it as a preexisting file that
# is going to be modified
write_file(cls.repo, changed_file_name)
cls.repo.git.execute(["git", "add", "."])
cls.repo.git.execute(["git", "commit", "-m", "Commit changed files"])
# this new commit is out base revision to compare changes against
cls.base_revision = cls.repo.head.commit.hexsha
cls.original_dir = os.path.abspath(os.curdir)
os.chdir(cls.tmp_dir)
@classmethod
def tearDownClass(cls):
os.chdir(cls.original_dir)
shutil.rmtree(cls.tmp_dir)
def setUp(self):
# change the file already commited to the repo
write_file(self.repo, changed_file_name)
# make a new file that has not been commited yet
write_file(self.repo, new_file_name)
with tempfile.NamedTemporaryFile(mode="w", encoding="utf-8", delete=False) as tmp:
tmp.write("fake_expansion: true\n")
self.expansions_file = tmp.name
def tearDown(self):
# reset to the original state between tests
self.repo.git.execute(["git", "reset", "--hard", self.base_revision])
os.unlink(self.expansions_file)
def test_local_unchanged_files(self):
evergreen_git.get_remote_branch_ref = MagicMock(return_value=self.base_revision)
new_files = evergreen_git.get_new_files()
self.assertEqual(
new_files, [], msg="New files list was not empty when no new files were added to git."
)
changed_files = evergreen_git.get_changed_files()
self.assertEqual(
changed_files, [changed_file_name], msg="Changed file list was not as expected."
)
self.repo.git.execute(["git", "add", "."])
# random file not tracked by git
write_file(self.repo, "random_other_untracked_file.txt")
new_files = evergreen_git.get_new_files()
self.assertEqual(
new_files,
[new_file_name],
msg="New file list did not contain the new file added to git.",
)
changed_files = evergreen_git.get_changed_files()
self.assertEqual(
changed_files,
[changed_file_name, new_file_name],
msg="Changed file list was not as expected.",
)
def test_evergreen_patch(self):
# the files in evergreen patches live as uncommited files added to the index
with open(self.expansions_file, "a") as tmp:
tmp.write("is_patch: true\n")
tmp.write(f"revision: {self.base_revision}\n")
self.repo.git.execute(["git", "add", "."])
new_files = evergreen_git.get_new_files(expansions_file=self.expansions_file)
self.assertEqual(
new_files, [new_file_name], msg="New file list did not contain the new file."
)
changed_files = evergreen_git.get_changed_files(expansions_file=self.expansions_file)
self.assertEqual(
changed_files,
[changed_file_name, new_file_name],
msg="Changed file list was not as expected.",
)
def test_evergreen_waterfall(self):
# Evergreen waterfall runs just check against the last commit so we need to commit the changes
self.repo.git.execute(["git", "add", "."])
self.repo.git.execute(["git", "commit", "-m", "Fake waterfall changes"])
new_files = evergreen_git.get_new_files(expansions_file=self.expansions_file)
self.assertEqual(
new_files, [new_file_name], msg="New file list did not contain the new file."
)
changed_files = evergreen_git.get_changed_files(expansions_file=self.expansions_file)
self.assertEqual(
changed_files,
[changed_file_name, new_file_name],
msg="Changed file list was not as expected.",
)
def test_remote_picker(self):
remote = evergreen_git.get_mongodb_remote(self.repo)
self.assertIn("10gen/mongo", remote.url, msg="The wrong remote was found.")