| #!/usr/bin/env vpython3 |
| # Copyright (c) 2024 The Chromium Authors. All rights reserved. |
| # Use of this source code is governed by a BSD-style license that can be |
| # found in the LICENSE file. |
| """Unit tests for presubmit_diff.py.""" |
| |
| import os |
| import sys |
| import tempfile |
| import unittest |
| from unittest import mock |
| |
| sys.path.insert(0, os.path.dirname(os.path.dirname(os.path.abspath(__file__)))) |
| |
| import gclient_utils |
| import presubmit_diff |
| |
| |
| class PresubmitDiffTest(unittest.TestCase): |
| |
| def setUp(self): |
| # State of the local directory. |
| self.root = tempfile.mkdtemp() |
| os.makedirs(os.path.join(self.root, "nested")) |
| with open(os.path.join(self.root, "unchanged.txt"), "w") as f: |
| f.write("unchanged\n") |
| with open(os.path.join(self.root, "added.txt"), "w") as f: |
| f.write("added\n") |
| with open(os.path.join(self.root, "modified.txt"), "w") as f: |
| f.write("modified... foo\n") |
| with open(os.path.join(self.root, "nested/modified.txt"), "w") as f: |
| f.write("goodbye\n") |
| |
| # State of the remote repository. |
| fetch_data = { |
| "unchanged.txt": "unchanged\n", |
| "deleted.txt": "deleted\n", |
| "modified.txt": "modified... bar\n", |
| "nested/modified.txt": "hello\n", |
| } |
| |
| def fetch_side_effect(host, repo, ref, file): |
| return fetch_data.get(file, "") |
| |
| fetch_content_mock = mock.patch("presubmit_diff.fetch_content", |
| side_effect=fetch_side_effect) |
| fetch_content_mock.start() |
| |
| self.addCleanup(mock.patch.stopall) |
| |
| def tearDown(self): |
| gclient_utils.rmtree(self.root) |
| |
| def _test_create_diffs(self, files: list[str], expected: dict[str, str]): |
| actual = presubmit_diff.create_diffs("host", "repo", "ref", self.root, |
| files) |
| self.assertEqual(actual.keys(), expected.keys()) |
| |
| # Manually check each line in the diffs except the "index" line because |
| # hashes can differ in length. |
| for file, diff in actual.items(): |
| expected_lines = expected[file].splitlines() |
| for idx, line in enumerate(diff.splitlines()): |
| if line.startswith("index "): |
| continue |
| self.assertEqual(line, expected_lines[idx]) |
| |
| def test_create_diffs_with_nonexistent_file_raises_error(self): |
| self.assertRaises( |
| RuntimeError, |
| presubmit_diff.create_diffs, |
| "host", |
| "repo", |
| "ref", |
| self.root, |
| ["doesnotexist.txt"], |
| ) |
| |
| def test_create_diffs_with_unchanged_file(self): |
| self._test_create_diffs( |
| ["unchanged.txt"], |
| {"unchanged.txt": ""}, |
| ) |
| |
| def test_create_diffs_with_added_file(self): |
| expected_diff = """diff --git a/added.txt b/added.txt |
| new file mode 100644 |
| index 00000000..d5f7fc3f |
| --- /dev/null |
| +++ b/added.txt |
| @@ -0,0 +1 @@ |
| +added |
| """ |
| self._test_create_diffs( |
| ["added.txt"], |
| {"added.txt": expected_diff}, |
| ) |
| |
| def test_create_diffs_with_deleted_file(self): |
| expected_diff = """diff --git a/deleted.txt b/deleted.txt |
| deleted file mode 100644 |
| index 71779d2c..00000000 |
| --- a/deleted.txt |
| +++ /dev/null |
| @@ -1 +0,0 @@ |
| -deleted |
| """ |
| self._test_create_diffs( |
| ["deleted.txt"], |
| {"deleted.txt": expected_diff}, |
| ) |
| |
| # pylint: disable=line-too-long |
| |
| def test_create_diffs_with_modified_files(self): |
| expected_diff = """diff --git a/modified.txt b/modified.txt |
| index a7dd0b00..12d68703 100644 |
| --- a/modified.txt |
| +++ b/modified.txt |
| @@ -1 +1 @@ |
| -modified... bar |
| +modified... foo |
| """ |
| expected_nested_diff = """diff --git a/nested/modified.txt b/nested/modified.txt |
| index ce013625..dd7e1c6f 100644 |
| --- a/nested/modified.txt |
| +++ b/nested/modified.txt |
| @@ -1 +1 @@ |
| -hello |
| +goodbye |
| """ |
| self._test_create_diffs( |
| ["modified.txt", "nested/modified.txt"], |
| { |
| "modified.txt": expected_diff, |
| "nested/modified.txt": expected_nested_diff, |
| }, |
| ) |
| |
| # Test cases for _process_diff. |
| def test_process_diff_with_no_changes(self): |
| self.assertEqual( |
| presubmit_diff._process_diff( |
| "", |
| "/path/to/src", |
| "/path/to/dst", |
| ), |
| "", |
| ) |
| |
| @mock.patch("platform.system", return_value="Linux") |
| @mock.patch("os.sep", new="/") |
| def test_process_diff_handles_unix_paths(self, sys_mock): |
| diff = """diff --git a/path/to/src/file.txt b/path/to/dst/file.txt |
| index ce013625..dd7e1c6f 100644 |
| --- a/path/to/file.txt |
| +++ b/path/to/file.txt |
| @@ -1 +1 @@ |
| -random |
| +content |
| """ |
| expected = """diff --git a/file.txt b/file.txt |
| index ce013625..dd7e1c6f 100644 |
| --- a/path/to/file.txt |
| +++ b/path/to/file.txt |
| @@ -1 +1 @@ |
| -random |
| +content |
| """ |
| self.assertEqual( |
| presubmit_diff._process_diff( |
| diff, |
| "/path/to/src", |
| "/path/to/dst", |
| ), |
| expected, |
| ) |
| |
| # Trailing slashes are handled. |
| self.assertEqual( |
| presubmit_diff._process_diff( |
| diff, |
| "/path/to/src/", |
| "/path/to/dst/", |
| ), |
| expected, |
| ) |
| |
| @mock.patch("platform.system", return_value="Windows") |
| @mock.patch("os.sep", new="\\") |
| def test_process_diff_handles_windows_paths(self, sys_mock): |
| diff = """diff --git "a/C:\\\\path\\\\to\\\\src\\\\file.txt" "b/C:\\\\path\\\\to\\\\dst\\\\file.txt" |
| index ce013625..dd7e1c6f 100644 |
| --- "a/C:\\\\path\\\\to\\\\src\\\\file.txt |
| +++ "b/C:\\\\path\\\\to\\\\dst\\\\file.txt" |
| @@ -1 +1 @@ |
| -random |
| +content |
| """ |
| expected = """diff --git a/file.txt b/file.txt |
| index ce013625..dd7e1c6f 100644 |
| --- a/file.txt |
| +++ b/file.txt |
| @@ -1 +1 @@ |
| -random |
| +content |
| """ |
| self.assertEqual( |
| expected, |
| presubmit_diff._process_diff(diff, "C:\\path\\to\\src", |
| "C:\\path\\to\\dst"), |
| ) |
| |
| # Trailing slashes are handled. |
| self.assertEqual( |
| expected, |
| presubmit_diff._process_diff(diff, "C:\\path\\to\\src\\", |
| "C:\\path\\to\\dst\\"), |
| ) |
| |
| @mock.patch("platform.system", return_value="Linux") |
| def test_process_diff_without_chunk_header(self, sys_mock): |
| diff = """diff --git a/path/to/src/file.txt b/path/to/dst/file.txt |
| old mode 100644 |
| new mode 100755 |
| """ |
| expected = """diff --git a/file.txt b/file.txt |
| old mode 100644 |
| new mode 100755 |
| """ |
| self.assertEqual( |
| presubmit_diff._process_diff( |
| diff, |
| "/path/to/src", |
| "/path/to/dst", |
| ), |
| expected, |
| ) |
| |
| |
| if __name__ == "__main__": |
| unittest.main() |