Skip to content

Commit

Permalink
Add unit tests for all new functions
Browse files Browse the repository at this point in the history
  • Loading branch information
akaihola committed Mar 13, 2022
1 parent 51e68dd commit 0257656
Show file tree
Hide file tree
Showing 3 changed files with 216 additions and 6 deletions.
52 changes: 46 additions & 6 deletions src/darker/tests/test_diff.py
Original file line number Diff line number Diff line change
Expand Up @@ -180,6 +180,7 @@ def test_opcodes_to_chunks():


EXAMPLE_OPCODES = [
# 0-based, end-exclusive
("replace", 0, 4, 0, 1),
("equal", 4, 6, 1, 3),
("replace", 6, 8, 3, 5),
Expand All @@ -194,20 +195,59 @@ def test_opcodes_to_chunks():
("equal", 20, 23, 23, 26),
("insert", 23, 23, 26, 27),
("equal", 23, 24, 27, 28),
("replace", 24, 34, 28, 38),
("equal", 34, 35, 38, 39),
]


@pytest.mark.kwparametrize(
dict(context_lines=0, expect=[1, 4, 5, 13, 14, 17, 20, 22, 23, 27]),
dict(context_lines=1, expect=[[1, 6], [12, 24], [26, 28]]),
dict(context_lines=2, expect=[[1, 7], [11, 28]]),
dict(
context_lines=0,
multiline_string_ranges=[],
expect=[0, 3, 4, 12, 13, 16, 19, 21, 22, 26, [28, 37]], # 0-based
),
dict(
context_lines=1,
multiline_string_ranges=[],
expect=[[0, 5], [11, 23], [25, 38]], # 0-based, end-inclusive
),
dict(
context_lines=2,
multiline_string_ranges=[],
expect=[[0, 6], [10, 38]], # 0-based, end-inclusive
),
dict(
context_lines=0,
multiline_string_ranges=[ # 0-based, end exclusive
(2, 4), # partial left overlap with (3, 5)
(13, 15), # partial right overlap with (12, 14)
(16, 17), # exact overlap with (16, 17)
(18, 21), # overextending overlap with (19, 20)
(22, 27), # inner overlap with (21, 23) and full overlap with (26, 27)
(28, 30), # full overlap with (28, 38)...
(36, 46), # ...partial left overlap with (28, 38)
],
expect=[0, [2, 4], [12, 14], 16, [18, 26], [28, 45]], # 0-based, end-inclusive
),
)
def test_opcodes_to_edit_linenums(context_lines, expect):
edit_linenums = list(opcodes_to_edit_linenums(EXAMPLE_OPCODES, context_lines, []))
def test_opcodes_to_edit_linenums(context_lines, multiline_string_ranges, expect):
"""`opcodes_to_edit_linenums()` gives correct results"""
edit_linenums = list(
opcodes_to_edit_linenums(
EXAMPLE_OPCODES,
context_lines,
# Convert ranges from 0 to 1 based. The test case is defined using 0-based
# ranges so it's easier to reason about the relation between multi-line
# string ranges and opcode ranges.
[(start + 1, end + 1) for start, end in multiline_string_ranges],
)
)
# Normalize expected lines/ranges to 0-based, end-exclusive.
expect_ranges = [[n, n] if isinstance(n, int) else n for n in expect]
expect_linenums = list(chain(*(range(n[0], n[1] + 1) for n in expect_ranges)))

assert edit_linenums == expect_linenums
# Normalize result to 0-based, end-exclusive before comparison
assert [linenum - 1 for linenum in edit_linenums] == expect_linenums


def test_opcodes_to_edit_linenums_empty_opcodes():
Expand Down
46 changes: 46 additions & 0 deletions src/darker/tests/test_git.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
from datetime import datetime, timedelta
from pathlib import Path
from subprocess import DEVNULL, PIPE, CalledProcessError, check_call # nosec
from textwrap import dedent # nosec
from typing import List, Union
from unittest.mock import call, patch

Expand Down Expand Up @@ -803,6 +804,51 @@ def test_edited_linenums_differ_revision_vs_lines(git_repo, context_lines, expec
assert linenums == expect


@pytest.mark.kwparametrize(
dict(context_lines=0, expect=[1, 3, 4, 5, 6, 8]),
dict(context_lines=1, expect=[1, 2, 3, 4, 5, 6, 7, 8]),
)
def test_edited_linenums_differ_revision_vs_lines_multiline_strings(
git_repo, context_lines, expect
):
"""Tests for EditedLinenumsDiffer.revision_vs_lines() with multi-line strings"""
git_repo.add(
{
"a.py": dedent(
"""\
change\n
keep\n
'''change first,\n
keep second\n
and third,\n
change fourth line of multiline'''\n
keep\n
change\n
"""
)
},
commit="Initial commit",
)
content = TextDocument.from_lines(
[
"CHANGED",
"keep",
"'''CHANGED FIRST,",
"keep second",
"and third,",
"CHANGED FOURTH LINE OF MULTILINE'''",
"keep",
"CHANGED",
]
)
revrange = git.RevisionRange("HEAD", ":WORKTREE:")
differ = git.EditedLinenumsDiffer(git_repo.root, revrange)

linenums = differ.revision_vs_lines(Path("a.py"), content, context_lines)

assert linenums == expect


def test_local_gitconfig_ignored_by_gitrepofixture(tmp_path):
"""Tests that ~/.gitconfig is ignored when running darker's git tests"""
(tmp_path / "HEAD").write_text("ref: refs/heads/main")
Expand Down
124 changes: 124 additions & 0 deletions src/darker/tests/test_multiline_strings.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,124 @@
"""Tests for `darker.multiline_strings`"""

import pytest

from darker import multiline_strings
from darker.utils import TextDocument


def test_get_multiline_string_ranges():
"""`get_multiline_string_ranges()` identifies multi-line strings correctly"""
content = TextDocument.from_lines(
[
"'single-quoted string'", # (line 1)
"f'single-quoted f-string'",
"r'single-quoted raw string'",
"rf'single-quoted raw f-string'",
"b'single-quoted bytestring'", # (line 5)
"rb'single-quoted raw bytestring'",
"'''triple-single-quoted one-line string'''",
"f'''triple-single-quoted one-line f-string'''",
"r'''triple-single-quoted one-line raw string'''",
"rf'''triple-single-quoted one-line raw f-string'''", # (line 10)
"b'''triple-single-quoted one-line bytestring'''",
"rb'''triple-single-quoted one-line raw bytestring'''",
"'''triple-single-quoted", # line 13
" two-line string'''",
"f'''triple-single-quoted", # line 15
" two-line f-string'''",
"r'''triple-single-quoted", # line 17
" two-line raw string'''",
"rf'''triple-single-quoted", # line 19
" two-line raw f-string'''",
"b'''triple-single-quoted", # line 21
" two-line bytestring'''",
"rb'''triple-single-quoted", # line 23
" two-line raw bytestring'''",
'"double-quoted string"', # (line 25)
'f"double-quoted f-string"',
'r"double-quoted raw string"',
'rf"double-quoted raw f-string"',
'b"double-quoted bytestring"',
'rb"double-quoted raw bytestring"', # (line 30)
'"""triple-double-quoted one-line string"""',
'f"""triple-double-quoted one-line f-string"""',
'r"""triple-double-quoted one-line raw string"""',
'rf"""triple-double-quoted one-line raw f-string"""',
'b"""triple-double-quoted one-line bytestring"""', # (line 35)
'rb"""triple-double-quoted one-line raw bytestring"""',
'"""triple-double-quoted', # line 37
' two-line string"""',
'f"""triple-double-quoted', # line 39
' two-line f-string"""',
'r"""triple-double-quoted', # line 41
' two-line raw string"""',
'rf"""triple-double-quoted', # line 43
' two-line raw f-string"""',
'b"""triple-double-quoted', # line 45
' two-line bytestring"""',
'rb"""triple-double-quoted', # line 47
' two-line raw bytestring"""',
'"""triple-', # line 49
" double-",
" quoted",
" six-",
" line",
' string"""', # line 54
]
)

result = multiline_strings.get_multiline_string_ranges(content)

assert result == [
# 1-based, end-exclusive
(13, 15),
(15, 17),
(17, 19),
(19, 21),
(21, 23),
(23, 25),
(37, 39),
(39, 41),
(41, 43),
(43, 45),
(45, 47),
(47, 49),
(49, 55),
]


# End-exclusive
TEST_RANGES = [(2, 2), (5, 6), (9, 11), (14, 17)]


@pytest.mark.kwparametrize(
# `(start, end)` and `ranges` are end-exclusive
dict(start=0, end=0, ranges=[], expect=None),
dict(start=0, end=42, ranges=[], expect=None),
dict(start=0, end=0, ranges=TEST_RANGES, expect=None),
dict(start=1, end=2, ranges=TEST_RANGES, expect=None),
dict(start=2, end=2, ranges=TEST_RANGES, expect=None),
dict(start=1, end=3, ranges=TEST_RANGES, expect=(2, 2)),
dict(start=2, end=3, ranges=TEST_RANGES, expect=None),
dict(start=3, end=3, ranges=TEST_RANGES, expect=None),
dict(start=4, end=5, ranges=TEST_RANGES, expect=None),
dict(start=5, end=5, ranges=TEST_RANGES, expect=None),
dict(start=4, end=6, ranges=TEST_RANGES, expect=(5, 6)),
dict(start=5, end=6, ranges=TEST_RANGES, expect=(5, 6)),
dict(start=6, end=6, ranges=TEST_RANGES, expect=None),
dict(start=4, end=7, ranges=TEST_RANGES, expect=(5, 6)),
dict(start=5, end=7, ranges=TEST_RANGES, expect=(5, 6)),
dict(start=6, end=7, ranges=TEST_RANGES, expect=None),
dict(start=10, end=10, ranges=TEST_RANGES, expect=(9, 11)),
dict(start=10, end=11, ranges=TEST_RANGES, expect=(9, 11)),
dict(start=10, end=12, ranges=TEST_RANGES, expect=(9, 11)),
dict(start=11, end=11, ranges=TEST_RANGES, expect=None),
dict(start=11, end=12, ranges=TEST_RANGES, expect=None),
dict(start=12, end=12, ranges=TEST_RANGES, expect=None),
dict(start=10, end=19, ranges=TEST_RANGES, expect=(9, 17)),
)
def test_find_overlap(start, end, ranges, expect):
"""`find_overlap()` finds the enclosing range for overlapping ranges"""
result = multiline_strings.find_overlap(start, end, ranges)

assert result == expect

0 comments on commit 0257656

Please sign in to comment.