76 lines
2.4 KiB
Python
Executable File
76 lines
2.4 KiB
Python
Executable File
from pathlib import Path
|
|
import random
|
|
import unittest
|
|
|
|
from govoplan_campaign.backend.services.filenames import FilenameAllocator
|
|
from govoplan_campaign.backend.services.zip_service import _normalized_members
|
|
|
|
|
|
def legacy_names(names):
|
|
used = set()
|
|
result = []
|
|
for name in names:
|
|
path = Path(name)
|
|
candidate = name
|
|
counter = 2
|
|
while candidate.casefold() in used:
|
|
candidate = f"{path.stem} ({counter}){path.suffix}"
|
|
counter += 1
|
|
used.add(candidate.casefold())
|
|
result.append(candidate)
|
|
return result
|
|
|
|
|
|
class FilenameAllocatorTests(unittest.TestCase):
|
|
def test_exact_equivalence_with_colliding_suffixes_case_unicode_and_multiple_dots(
|
|
self,
|
|
):
|
|
choices = [
|
|
"report.pdf",
|
|
"REPORT.PDF",
|
|
"report (2).pdf",
|
|
"report (3).pdf",
|
|
"report (2) (2).pdf",
|
|
".hidden",
|
|
"a.tar.gz",
|
|
"A.TAR.GZ",
|
|
"Straße.txt",
|
|
"STRASSE.txt",
|
|
"readme",
|
|
]
|
|
rng = random.Random(42)
|
|
for _ in range(30):
|
|
names = [rng.choice(choices) for _ in range(200)]
|
|
allocator = FilenameAllocator()
|
|
self.assertEqual(
|
|
legacy_names(names), [allocator.allocate(name) for name in names]
|
|
)
|
|
|
|
def test_zip_and_message_names_preserve_every_input_and_sequence(self):
|
|
names = ["a.pdf", "A.pdf", "a (2).pdf", "a.pdf"]
|
|
paths = [Path(f"/synthetic/{index}/source") for index in range(len(names))]
|
|
members = _normalized_members(list(zip(paths, names)))
|
|
self.assertEqual(paths, [path for path, _ in members])
|
|
self.assertEqual(legacy_names(names), [name for _, name in members])
|
|
self.assertEqual("a.pdf", FilenameAllocator().allocate("a.pdf"))
|
|
|
|
def test_many_collisions_have_linear_membership_work(self):
|
|
class CountingSet(set):
|
|
probes = 0
|
|
|
|
def __contains__(self, item):
|
|
self.probes += 1
|
|
return super().__contains__(item)
|
|
|
|
allocator = FilenameAllocator()
|
|
allocator.used = CountingSet()
|
|
for _ in range(10000):
|
|
last = allocator.allocate("report.pdf")
|
|
self.assertEqual("report (10000).pdf", last)
|
|
self.assertEqual(10000, len(allocator.used))
|
|
self.assertEqual(19999, allocator.used.probes)
|
|
|
|
|
|
if __name__ == "__main__":
|
|
unittest.main()
|