mirror of
https://github.com/samschott/maestral.git
synced 2024-09-21 02:47:59 +03:00
269 lines
7.9 KiB
Python
269 lines
7.9 KiB
Python
import pytest
|
|
from watchdog.events import (
|
|
DirCreatedEvent,
|
|
DirDeletedEvent,
|
|
DirMovedEvent,
|
|
FileCreatedEvent,
|
|
FileDeletedEvent,
|
|
FileModifiedEvent,
|
|
FileMovedEvent,
|
|
)
|
|
|
|
from maestral.client import DropboxClient
|
|
from maestral.config import remove_configuration
|
|
from maestral.keyring import CredentialStorage
|
|
from maestral.sync import SyncEngine
|
|
|
|
|
|
@pytest.fixture
|
|
def sync():
|
|
sync = SyncEngine(DropboxClient("test-config", CredentialStorage("test-config")))
|
|
sync.dropbox_path = "/"
|
|
|
|
yield sync
|
|
|
|
remove_configuration("test-config")
|
|
|
|
|
|
def ipath(i):
|
|
"""Returns path names '/test 1', '/test 2', ..."""
|
|
return f"/test {i}"
|
|
|
|
|
|
def test_single_file_events(sync: SyncEngine) -> None:
|
|
# only a single event for every path -> no consolidation
|
|
|
|
file_events = [
|
|
FileModifiedEvent(ipath(1)),
|
|
FileCreatedEvent(ipath(2)),
|
|
FileDeletedEvent(ipath(3)),
|
|
FileMovedEvent(ipath(4), ipath(5)),
|
|
]
|
|
|
|
res = [
|
|
FileModifiedEvent(ipath(1)),
|
|
FileCreatedEvent(ipath(2)),
|
|
FileDeletedEvent(ipath(3)),
|
|
FileMovedEvent(ipath(4), ipath(5)),
|
|
]
|
|
|
|
cleaned_events = sync._clean_local_events(file_events)
|
|
assert cleaned_events == res
|
|
|
|
|
|
def test_single_path_cases(sync: SyncEngine) -> None:
|
|
file_events = [
|
|
# created + deleted -> None
|
|
FileCreatedEvent(ipath(1)),
|
|
FileDeletedEvent(ipath(1)),
|
|
# deleted + created -> modified
|
|
FileDeletedEvent(ipath(2)),
|
|
FileCreatedEvent(ipath(2)),
|
|
# created + modified -> created
|
|
FileCreatedEvent(ipath(3)),
|
|
FileModifiedEvent(ipath(3)),
|
|
]
|
|
|
|
res = [
|
|
# created + deleted -> None
|
|
# deleted + created -> modified
|
|
FileModifiedEvent(ipath(2)),
|
|
# created + modified -> created
|
|
FileCreatedEvent(ipath(3)),
|
|
]
|
|
|
|
cleaned_events = sync._clean_local_events(file_events)
|
|
assert cleaned_events == res
|
|
|
|
|
|
def test_move_events(sync: SyncEngine) -> None:
|
|
file_events = [
|
|
# created + moved -> created
|
|
FileCreatedEvent(ipath(1)),
|
|
FileMovedEvent(ipath(1), ipath(2)),
|
|
# moved + deleted -> deleted
|
|
FileMovedEvent(ipath(3), ipath(4)),
|
|
FileDeletedEvent(ipath(4)),
|
|
# moved + moved back -> modified
|
|
FileMovedEvent(ipath(5), ipath(6)),
|
|
FileMovedEvent(ipath(6), ipath(5)),
|
|
# moved + moved -> deleted + created
|
|
# (this is currently not handled as a single moved)
|
|
FileMovedEvent(ipath(7), ipath(8)),
|
|
FileMovedEvent(ipath(8), ipath(9)),
|
|
]
|
|
|
|
res = [
|
|
# created + moved -> created
|
|
FileCreatedEvent(ipath(2)),
|
|
# moved + deleted -> deleted
|
|
FileDeletedEvent(ipath(3)),
|
|
# moved + moved back -> modified
|
|
FileModifiedEvent(ipath(5)),
|
|
# moved + moved -> deleted + created
|
|
# (this is currently not handled as a single moved)
|
|
FileDeletedEvent(ipath(7)),
|
|
FileCreatedEvent(ipath(9)),
|
|
]
|
|
|
|
cleaned_events = sync._clean_local_events(file_events)
|
|
assert cleaned_events == res
|
|
|
|
|
|
def test_gedit_save(sync: SyncEngine) -> None:
|
|
file_events = [
|
|
FileCreatedEvent("/.gedit-save-UR4EC0"), # save new version to tmp file
|
|
FileModifiedEvent("/.gedit-save-UR4EC0"), # modify tmp file
|
|
FileMovedEvent(ipath(1), ipath(1) + "~"), # move old version to backup
|
|
FileMovedEvent("/.gedit-save-UR4EC0", ipath(1)), # replace old version with tmp
|
|
]
|
|
|
|
res = [
|
|
FileModifiedEvent(ipath(1)), # modified file
|
|
FileCreatedEvent(ipath(1) + "~"), # backup
|
|
]
|
|
|
|
cleaned_events = sync._clean_local_events(file_events)
|
|
assert cleaned_events == res
|
|
|
|
|
|
def test_macos_safe_save(sync: SyncEngine) -> None:
|
|
file_events = [
|
|
FileMovedEvent(ipath(1), ipath(1) + ".sb-b78ef837-dLht38"), # move to backup
|
|
FileCreatedEvent(ipath(1)), # create new version
|
|
FileDeletedEvent(ipath(1) + ".sb-b78ef837-dLht38"), # delete backup
|
|
]
|
|
|
|
res = [
|
|
FileModifiedEvent(ipath(1)), # modified file
|
|
]
|
|
|
|
cleaned_events = sync._clean_local_events(file_events)
|
|
assert cleaned_events == res
|
|
|
|
|
|
def test_msoffice_created(sync: SyncEngine) -> None:
|
|
file_events = [
|
|
FileCreatedEvent(ipath(1)),
|
|
FileDeletedEvent(ipath(1)),
|
|
FileCreatedEvent(ipath(1)),
|
|
FileCreatedEvent("/~$" + ipath(1)),
|
|
]
|
|
|
|
res = [
|
|
FileCreatedEvent(ipath(1)), # created file
|
|
FileCreatedEvent("/~$" + ipath(1)), # backup
|
|
]
|
|
|
|
cleaned_events = sync._clean_local_events(file_events)
|
|
assert cleaned_events == res
|
|
|
|
|
|
def test_type_changes(sync: SyncEngine) -> None:
|
|
file_events = [
|
|
# keep as is
|
|
FileDeletedEvent(ipath(1)),
|
|
DirCreatedEvent(ipath(1)),
|
|
# keep as is
|
|
DirDeletedEvent(ipath(2)),
|
|
FileCreatedEvent(ipath(2)),
|
|
]
|
|
|
|
res = [
|
|
# keep as is
|
|
FileDeletedEvent(ipath(1)),
|
|
DirCreatedEvent(ipath(1)),
|
|
# keep as is
|
|
DirDeletedEvent(ipath(2)),
|
|
FileCreatedEvent(ipath(2)),
|
|
]
|
|
|
|
cleaned_events = sync._clean_local_events(file_events)
|
|
assert cleaned_events == res
|
|
|
|
|
|
def test_type_changes_difficult(sync: SyncEngine) -> None:
|
|
file_events = [
|
|
# convert to FileDeleted -> DirCreated
|
|
FileModifiedEvent(ipath(1)),
|
|
FileDeletedEvent(ipath(1)),
|
|
FileCreatedEvent(ipath(1)),
|
|
FileDeletedEvent(ipath(1)),
|
|
DirCreatedEvent(ipath(1)),
|
|
# convert to FileDeleted(path1) -> DirCreated(path2)
|
|
FileModifiedEvent(ipath(2)),
|
|
FileDeletedEvent(ipath(2)),
|
|
FileCreatedEvent(ipath(2)),
|
|
FileDeletedEvent(ipath(2)),
|
|
DirCreatedEvent(ipath(2)),
|
|
DirMovedEvent(ipath(2), ipath(3)),
|
|
]
|
|
|
|
res = [
|
|
FileDeletedEvent(ipath(1)),
|
|
DirCreatedEvent(ipath(1)),
|
|
FileDeletedEvent(ipath(2)),
|
|
DirCreatedEvent(ipath(3)),
|
|
]
|
|
|
|
cleaned_events = sync._clean_local_events(file_events)
|
|
assert cleaned_events == res
|
|
|
|
|
|
def test_nested_events(sync: SyncEngine) -> None:
|
|
file_events = [
|
|
# convert to a single DirDeleted
|
|
DirDeletedEvent(ipath(1)),
|
|
FileDeletedEvent(ipath(1) + "/file1.txt"),
|
|
FileDeletedEvent(ipath(1) + "/file2.txt"),
|
|
DirDeletedEvent(ipath(1) + "/sub"),
|
|
FileDeletedEvent(ipath(1) + "/sub/file3.txt"),
|
|
# convert to a single DirMoved
|
|
DirMovedEvent(ipath(2), ipath(3)),
|
|
FileMovedEvent(ipath(2) + "/file1.txt", ipath(3) + "/file1.txt"),
|
|
FileMovedEvent(ipath(2) + "/file2.txt", ipath(3) + "/file2.txt"),
|
|
DirMovedEvent(ipath(2) + "/sub", ipath(3) + "/sub"),
|
|
FileMovedEvent(ipath(2) + "/sub/file3.txt", ipath(3) + "/sub/file3.txt"),
|
|
]
|
|
|
|
res = [
|
|
DirDeletedEvent(ipath(1)),
|
|
DirMovedEvent(ipath(2), ipath(3)),
|
|
]
|
|
|
|
cleaned_events = sync._clean_local_events(file_events)
|
|
assert cleaned_events == res
|
|
|
|
|
|
@pytest.mark.benchmark(
|
|
group="local-event-processing",
|
|
min_time=0.1,
|
|
max_time=5,
|
|
)
|
|
def test_performance(sync: SyncEngine, benchmark) -> None:
|
|
# 10,000 nested deleted events (5,000 folders, 5,000 files)
|
|
file_events = [DirDeletedEvent(n * ipath(1)) for n in range(1, 5001)]
|
|
file_events += [FileDeletedEvent(n * ipath(1) + ".txt") for n in range(1, 5001)]
|
|
|
|
# 10,000 nested moved events (5,000 folders, 5,000 files)
|
|
file_events += [DirMovedEvent(n * ipath(2), n * ipath(3)) for n in range(1, 5001)]
|
|
file_events += [
|
|
FileMovedEvent(n * ipath(2) + ".txt", n * ipath(3) + ".txt")
|
|
for n in range(1, 5001)
|
|
]
|
|
|
|
# 4,995 unrelated created events
|
|
file_events += [FileCreatedEvent(ipath(n)) for n in range(5, 5001)]
|
|
|
|
res = [
|
|
DirDeletedEvent(ipath(1)),
|
|
FileDeletedEvent(ipath(1) + ".txt"),
|
|
DirMovedEvent(ipath(2), ipath(3)),
|
|
FileMovedEvent(ipath(2) + ".txt", ipath(3) + ".txt"),
|
|
]
|
|
res += [FileCreatedEvent(ipath(n)) for n in range(5, 5001)]
|
|
|
|
cleaned_events = benchmark(sync._clean_local_events, file_events)
|
|
|
|
assert cleaned_events == res
|