test_diffs_context.py
382 lines
| 10.9 KiB
| text/x-python
|
PythonLexer
r5608 | # Copyright (C) 2010-2024 RhodeCode GmbH | |||
r1 | # | |||
# This program is free software: you can redistribute it and/or modify | ||||
# it under the terms of the GNU Affero General Public License, version 3 | ||||
# (only), as published by the Free Software Foundation. | ||||
# | ||||
# This program is distributed in the hope that it will be useful, | ||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of | ||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||||
# GNU General Public License for more details. | ||||
# | ||||
# You should have received a copy of the GNU Affero General Public License | ||||
# along with this program. If not, see <http://www.gnu.org/licenses/>. | ||||
# | ||||
# This program is dual-licensed. If you wish to learn more about the | ||||
# RhodeCode Enterprise Edition, including its added features, Support services, | ||||
# and proprietary license terms, please see https://rhodecode.com/licenses/ | ||||
""" | ||||
Tests of :mod:`rhodecode.lib.diffs` around the context of a specific line. | ||||
""" | ||||
import textwrap | ||||
import pytest | ||||
from rhodecode.lib import diffs | ||||
r5087 | from rhodecode.lib.str_utils import safe_bytes | |||
r1 | from rhodecode.lib.vcs.backends.git.diff import GitDiff | |||
def test_context_of_new_and_old_line_number_raises(diff_processor): | ||||
with pytest.raises(ValueError): | ||||
diff_processor.get_context_of_line( | ||||
path='file.txt', diff_line=diffs.DiffLineNumber(old=7, new=7)) | ||||
def test_context_of_an_old_line_number(diff_processor): | ||||
context = diff_processor.get_context_of_line( | ||||
path='file.txt', diff_line=diffs.DiffLineNumber(old=7, new=None)) | ||||
expected_context = [ | ||||
r5087 | ('unmod', b'line04\n'), | |||
('unmod', b'line05\n'), | ||||
('unmod', b'line06\n'), | ||||
('unmod', b'line07\n'), | ||||
('add', b'line07a Add after line07\n'), | ||||
('unmod', b'line08\n'), | ||||
('unmod', b'line09\n'), | ||||
r1 | ] | |||
assert context == expected_context | ||||
def test_context_of_a_new_line_number(diff_processor): | ||||
context = diff_processor.get_context_of_line( | ||||
path='file.txt', diff_line=diffs.DiffLineNumber(old=None, new=8)) | ||||
expected_context = [ | ||||
r5087 | ('unmod', b'line05\n'), | |||
('unmod', b'line06\n'), | ||||
('unmod', b'line07\n'), | ||||
('add', b'line07a Add after line07\n'), | ||||
('unmod', b'line08\n'), | ||||
('unmod', b'line09\n'), | ||||
('unmod', b'line10\n'), | ||||
r1 | ] | |||
assert context == expected_context | ||||
def test_context_of_an_invisible_line_beginning_of_hunk(diff_processor): | ||||
# Note: The caller has to pass in a diff which is suitable to satisfy | ||||
# its requirements. This test just ensures that we see a sane behavior. | ||||
context = diff_processor.get_context_of_line( | ||||
path='file.txt', diff_line=diffs.DiffLineNumber(old=None, new=3)) | ||||
expected_context = [ | ||||
r5087 | ('unmod', b'line02\n'), | |||
('unmod', b'line03\n'), | ||||
('unmod', b'line04\n'), | ||||
('unmod', b'line05\n'), | ||||
('unmod', b'line06\n'), | ||||
r1 | ] | |||
assert context == expected_context | ||||
def test_context_of_an_invisible_line_end_of_hunk(diff_processor): | ||||
# Note: The caller has to pass in a diff which is suitable to satisfy | ||||
# its requirements. This test just ensures that we see a sane behavior. | ||||
context = diff_processor.get_context_of_line( | ||||
path='file.txt', diff_line=diffs.DiffLineNumber(old=12, new=None)) | ||||
expected_context = [ | ||||
r5087 | ('unmod', b'line09\n'), | |||
('unmod', b'line10\n'), | ||||
('unmod', b'line11\n'), | ||||
('unmod', b'line12\n'), | ||||
('unmod', b'line13\n'), | ||||
r1 | ] | |||
assert context == expected_context | ||||
@pytest.mark.parametrize('diff_fixture', ['change-in-beginning.diff']) | ||||
def test_context_of_an_incomplete_hunk_in_the_beginning(diff_processor): | ||||
context = diff_processor.get_context_of_line( | ||||
path='file.txt', diff_line=diffs.DiffLineNumber(old=None, new=2)) | ||||
expected_context = [ | ||||
r5087 | ('unmod', b'line01\n'), | |||
('add', b'line01a Add line after line01\n'), | ||||
('unmod', b'line02\n'), | ||||
('unmod', b'line03\n'), | ||||
('unmod', b'line04\n'), | ||||
r1 | ] | |||
assert context == expected_context | ||||
@pytest.mark.parametrize('diff_fixture', ['change-in-end.diff']) | ||||
def test_context_of_an_incomplete_hunk_in_the_end(diff_processor): | ||||
context = diff_processor.get_context_of_line( | ||||
path='file.txt', diff_line=diffs.DiffLineNumber(old=None, new=80)) | ||||
expected_context = [ | ||||
r5087 | ('unmod', b'line36\n'), | |||
('unmod', b'line37\n'), | ||||
('unmod', b'line38\n'), | ||||
('add', b'line38a Add line after line38\n'), | ||||
('unmod', b'line39\n'), | ||||
r1 | ] | |||
assert context == expected_context | ||||
@pytest.mark.parametrize('diff_fixture', [ | ||||
'single-line.diff', | ||||
'single-line-two-files.diff', | ||||
]) | ||||
def test_appends_newline_for_each_context_line(diff_processor): | ||||
context = diff_processor.get_context_of_line( | ||||
path='file_b', diff_line=diffs.DiffLineNumber(old=None, new=1)) | ||||
r5087 | assert context == [('add', b'test_content\n')] | |||
r1 | ||||
def test_context_of_a_missing_line_raises(diff_processor): | ||||
missing_line = 20 | ||||
with pytest.raises(diffs.LineNotInDiffException): | ||||
diff_processor.get_context_of_line( | ||||
path='file.txt', | ||||
diff_line=diffs.DiffLineNumber(old=None, new=missing_line)) | ||||
def test_context_of_a_missing_file_raises(diff_processor): | ||||
with pytest.raises(diffs.FileNotInDiffException): | ||||
diff_processor.get_context_of_line( | ||||
path='not_existing_file.txt', | ||||
diff_line=diffs.DiffLineNumber(old=None, new=8)) | ||||
def test_find_context_with_full_context(diff_processor): | ||||
context_of_line_7 = [ | ||||
r5087 | ('unmod', b'line05\n'), | |||
('unmod', b'line06\n'), | ||||
('unmod', b'line07\n'), | ||||
('add', b'line07a Add after line07\n'), | ||||
('unmod', b'line08\n'), | ||||
('unmod', b'line09\n'), | ||||
('unmod', b'line10\n'), | ||||
r1 | ] | |||
found_line = diff_processor.find_context( | ||||
'file.txt', context_of_line_7, offset=3) | ||||
assert found_line == [diffs.DiffLineNumber(old=None, new=8)] | ||||
@pytest.mark.parametrize('diff_fixture', ['change-duplicated.diff']) | ||||
def test_find_context_multiple_times(diff_processor): | ||||
context = [ | ||||
r5087 | ('unmod', b'line04\n'), | |||
('unmod', b'line05\n'), | ||||
('unmod', b'line06\n'), | ||||
('add', b'line06a add line\n'), | ||||
('unmod', b'line07\n'), | ||||
('unmod', b'line08\n'), | ||||
('unmod', b'line09\n'), | ||||
r1 | ] | |||
found_line = diff_processor.find_context('file.txt', context, offset=3) | ||||
assert found_line == [ | ||||
diffs.DiffLineNumber(old=None, new=7), | ||||
diffs.DiffLineNumber(old=None, new=49), | ||||
] | ||||
@pytest.mark.parametrize('offset', [20, -20, -1, 7]) | ||||
def test_find_context_offset_param_raises(diff_processor, offset): | ||||
context_of_line_7 = [ | ||||
r5087 | ('unmod', b'line04\n'), | |||
('unmod', b'line05\n'), | ||||
('unmod', b'line06\n'), | ||||
('unmod', b'line07\n'), | ||||
('add', b'line07a Add after line07\n'), | ||||
('unmod', b'line08\n'), | ||||
('unmod', b'line09\n'), | ||||
r1 | ] | |||
with pytest.raises(ValueError): | ||||
diff_processor.find_context( | ||||
'file.txt', context_of_line_7, offset=offset) | ||||
def test_find_context_beginning_of_chunk(diff_processor): | ||||
context_of_first_line = [ | ||||
r5087 | ('unmod', b'line02\n'), | |||
('unmod', b'line03\n'), | ||||
('unmod', b'line04\n'), | ||||
('unmod', b'line05\n'), | ||||
r1 | ] | |||
found_line = diff_processor.find_context( | ||||
'file.txt', context_of_first_line, offset=0) | ||||
assert found_line == [diffs.DiffLineNumber(old=2, new=2)] | ||||
@pytest.mark.parametrize('diff_fixture', ['change-in-beginning.diff']) | ||||
def test_find_context_beginning_of_file(diff_processor): | ||||
context_of_first_line = [ | ||||
r5087 | ('add', b'line01a Add line after line01\n'), | |||
('unmod', b'line02\n'), | ||||
('unmod', b'line03\n'), | ||||
('unmod', b'line04\n'), | ||||
('unmod', b'line05\n'), | ||||
('unmod', b'line06\n'), | ||||
('unmod', b'line07\n'), | ||||
r1 | ] | |||
found_line = diff_processor.find_context( | ||||
'file.txt', context_of_first_line, offset=3) | ||||
assert found_line == [diffs.DiffLineNumber(old=4, new=5)] | ||||
def test_find_context_end_of_chunk(diff_processor): | ||||
context_of_last_line = [ | ||||
r5087 | ('unmod', b'line10\n'), | |||
('unmod', b'line11\n'), | ||||
('unmod', b'line12\n'), | ||||
('unmod', b'line13\n'), | ||||
r1 | ] | |||
found_line = diff_processor.find_context( | ||||
'file.txt', context_of_last_line, offset=3) | ||||
assert found_line == [diffs.DiffLineNumber(old=13, new=14)] | ||||
r3946 | @pytest.fixture() | |||
r1 | def diff_processor(request, diff_fixture): | |||
raw_diff = diffs_store[diff_fixture] | ||||
diff = GitDiff(raw_diff) | ||||
r5087 | processor = diffs.DiffProcessor(diff, diff_format='newdiff') | |||
r1 | processor.prepare() | |||
return processor | ||||
r3946 | @pytest.fixture() | |||
r1 | def diff_fixture(): | |||
return 'default.diff' | ||||
r5087 | diff_default: bytes = safe_bytes(textwrap.dedent(""" | |||
r1 | diff --git a/file.txt b/file.txt | |||
index 76e4f2e..6f8738f 100644 | ||||
--- a/file.txt | ||||
+++ b/file.txt | ||||
@@ -2,12 +2,13 @@ line01 | ||||
line02 | ||||
line03 | ||||
line04 | ||||
line05 | ||||
line06 | ||||
line07 | ||||
+line07a Add after line07 | ||||
line08 | ||||
line09 | ||||
line10 | ||||
line11 | ||||
line12 | ||||
line13 | ||||
r5087 | """)) | |||
r1 | ||||
r5087 | diff_beginning: bytes = safe_bytes(textwrap.dedent(""" | |||
r1 | diff --git a/file.txt b/file.txt | |||
index 76e4f2e..47d39f4 100644 | ||||
--- a/file.txt | ||||
+++ b/file.txt | ||||
@@ -1,7 +1,8 @@ | ||||
line01 | ||||
+line01a Add line after line01 | ||||
line02 | ||||
line03 | ||||
line04 | ||||
line05 | ||||
line06 | ||||
line07 | ||||
r5087 | """)) | |||
r1 | ||||
r5087 | diff_end: bytes = safe_bytes(textwrap.dedent(""" | |||
r1 | diff --git a/file.txt b/file.txt | |||
index 76e4f2e..b1304db 100644 | ||||
--- a/file.txt | ||||
+++ b/file.txt | ||||
@@ -74,7 +74,8 @@ line32 | ||||
line33 | ||||
line34 | ||||
line35 | ||||
line36 | ||||
line37 | ||||
line38 | ||||
+line38a Add line after line38 | ||||
line39 | ||||
r5087 | """)) | |||
r1 | ||||
r5087 | diff_duplicated_change: bytes = safe_bytes(textwrap.dedent(""" | |||
r1 | diff --git a/file.txt b/file.txt | |||
index 76e4f2e..55c2781 100644 | ||||
--- a/file.txt | ||||
+++ b/file.txt | ||||
@@ -1,12 +1,13 @@ | ||||
line01 | ||||
line02 | ||||
line03 | ||||
line04 | ||||
line05 | ||||
line06 | ||||
+line06a add line | ||||
line07 | ||||
line08 | ||||
line09 | ||||
line10 | ||||
line11 | ||||
line12 | ||||
@@ -42,12 +43,13 @@ line39 | ||||
line01 | ||||
line02 | ||||
line03 | ||||
line04 | ||||
line05 | ||||
line06 | ||||
+line06a add line | ||||
line07 | ||||
line08 | ||||
line09 | ||||
line10 | ||||
line11 | ||||
line12 | ||||
r5087 | """)) | |||
r1 | ||||
r5087 | diff_single_line: bytes = safe_bytes(textwrap.dedent(""" | |||
r1 | diff --git a/file_b b/file_b | |||
new file mode 100644 | ||||
index 00000000..915e94ff | ||||
--- /dev/null | ||||
+++ b/file_b | ||||
@@ -0,0 +1 @@ | ||||
+test_content | ||||
r5087 | """)) | |||
r1 | ||||
r5087 | diff_single_line_two_files: bytes = safe_bytes(textwrap.dedent(""" | |||
r1 | diff --git a/file_b b/file_b | |||
new file mode 100644 | ||||
index 00000000..915e94ff | ||||
--- /dev/null | ||||
+++ b/file_b | ||||
@@ -0,0 +1 @@ | ||||
+test_content | ||||
diff --git a/file_c b/file_c | ||||
new file mode 100644 | ||||
index 00000000..915e94ff | ||||
--- /dev/null | ||||
+++ b/file_c | ||||
@@ -0,0 +1 @@ | ||||
+test_content | ||||
r5087 | """)) | |||
r1 | ||||
diffs_store = { | ||||
'default.diff': diff_default, | ||||
'change-in-beginning.diff': diff_beginning, | ||||
'change-in-end.diff': diff_end, | ||||
'change-duplicated.diff': diff_duplicated_change, | ||||
'single-line.diff': diff_single_line, | ||||
'single-line-two-files.diff': diff_single_line_two_files, | ||||
} | ||||