[tests] create and assert sync states declaratively

This commit is contained in:
samschott 2022-04-05 00:23:32 +02:00
parent 94184ba1c3
commit 0555f851e2
11 changed files with 418 additions and 463 deletions

View File

@ -5,16 +5,8 @@ import time
import pytest
from maestral.main import Maestral
from maestral.core import FileMetadata
from maestral.config import remove_configuration
from maestral.utils.path import (
generate_cc_name,
delete,
to_existing_unnormalized_path,
is_child,
walk,
get_symlink_target,
)
from maestral.utils.path import generate_cc_name, delete
from maestral.utils.appdirs import get_home_dir
from maestral.keyring import TokenType
from maestral.exceptions import NotFoundError
@ -116,65 +108,3 @@ def wait_for_idle(m: Maestral, cycles: int = 4) -> None:
else:
time.sleep(1)
count += 1
def assert_synced(m: Maestral) -> None:
"""Asserts that the ``local_folder`` and ``remote_folder`` are synced."""
listing = m.client.list_folder("/", recursive=True)
# Assert that all items from server are present locally with the same content hash.
for md in listing.entries:
if m.sync.is_excluded_by_user(md.path_lower):
continue
local_path = m.to_local_path(md.path_display)
remote_hash = md.content_hash if isinstance(md, FileMetadata) else "folder"
local_hash = m.sync.get_local_hash(local_path)
local_symlink_target = get_symlink_target(local_path)
assert local_hash, f"'{md.path_display}' not found locally"
assert local_hash == remote_hash, f'different content for "{md.path_display}"'
if isinstance(md, FileMetadata):
assert (
md.symlink_target == local_symlink_target
), f'different symlink targets for "{md.path_display}"'
# Assert that all local items are present on server.
for path, _ in walk(m.dropbox_path, m.sync._scandir_with_ignore):
dbx_path = m.sync.to_dbx_path_lower(path)
has_match = any(md for md in listing.entries if md.path_lower == dbx_path)
assert has_match, f'local item "{path}" does not exist on dbx'
# Check that our index is correct.
for index_entry in m.sync.get_index():
if is_child(index_entry.dbx_path_lower, "/"):
# Check that there is a match on the server.
matching_items = [
e for e in listing.entries if e.path_lower == index_entry.dbx_path_lower
]
assert (
len(matching_items) == 1
), f'indexed item "{index_entry.dbx_path_lower}" does not exist on dbx'
e = matching_items[0]
remote_rev = e.rev if isinstance(e, FileMetadata) else "folder"
# Check if revs are equal on server and locally.
assert (
index_entry.rev == remote_rev
), f'different revs for "{index_entry.dbx_path_lower}"'
# Check if casing on drive is the same as in index.
local_path_expected_casing = m.dropbox_path + index_entry.dbx_path_cased
local_path_actual_casing = to_existing_unnormalized_path(
local_path_expected_casing
)
assert (
local_path_expected_casing == local_path_actual_casing
), "casing on drive does not match index"

View File

@ -1,13 +1,15 @@
import pathlib
from __future__ import annotations
import sys
import os
import os.path as osp
import subprocess
import pytest
from dropbox import files
from maestral.main import Maestral
from maestral.core import FileMetadata, WriteMode
from maestral.core import FileMetadata
from maestral.exceptions import (
NotFoundError,
UnsupportedFileTypeForDiff,
@ -18,7 +20,7 @@ from maestral.constants import FileStatus, IDLE
from maestral.utils.path import delete
from maestral.utils.integration import get_inotify_limits
from .conftest import wait_for_idle, resources
from .conftest import wait_for_idle
if not ("DROPBOX_ACCESS_TOKEN" in os.environ or "DROPBOX_REFRESH_TOKEN" in os.environ):
@ -26,14 +28,13 @@ if not ("DROPBOX_ACCESS_TOKEN" in os.environ or "DROPBOX_REFRESH_TOKEN" in os.en
def _create_file_with_content(
m: Maestral, tmp_path: pathlib.Path, dbx_path: str, content: str, mode: str = "w"
m: Maestral, dbx_path: str, content: str | bytes
) -> FileMetadata:
local_path = str(tmp_path / dbx_path.lstrip("/"))
with open(local_path, mode) as f:
f.write(content)
if isinstance(content, str):
content = content.encode()
return m.client.upload(local_path, dbx_path, write_mode=WriteMode.Overwrite)
return m.client.dbx.files_upload(content, dbx_path, mode=files.WriteMode.overwrite)
def test_status_properties(m: Maestral) -> None:
@ -268,11 +269,11 @@ def test_selective_sync_nested(m: Maestral) -> None:
assert not m.fatal_errors
def test_get_file_diff(m: Maestral, tmp_path) -> None:
def test_get_file_diff(m: Maestral) -> None:
dbx_path = "/test.txt"
md_old = _create_file_with_content(m, tmp_path, dbx_path, "old")
md_new = _create_file_with_content(m, tmp_path, dbx_path, "new")
md_old = _create_file_with_content(m, dbx_path, "old")
md_new = _create_file_with_content(m, dbx_path, "new")
diff = m.get_file_diff(md_old.rev, md_new.rev)
assert diff[2] == "@@ -1 +1 @@\n"
@ -280,14 +281,14 @@ def test_get_file_diff(m: Maestral, tmp_path) -> None:
assert diff[4] == "+new"
def test_get_file_diff_local(m: Maestral, tmp_path) -> None:
def test_get_file_diff_local(m: Maestral) -> None:
dbx_path = "/test.txt"
local_path = m.to_local_path(dbx_path)
m.stop_sync()
wait_for_idle(m)
md_old = _create_file_with_content(m, tmp_path, dbx_path, "old")
md_old = _create_file_with_content(m, dbx_path, "old")
with open(local_path, "w") as f:
f.write("new")
@ -299,46 +300,46 @@ def test_get_file_diff_local(m: Maestral, tmp_path) -> None:
assert diff[4] == "+new"
def test_get_file_diff_not_found(m: Maestral, tmp_path) -> None:
def test_get_file_diff_not_found(m: Maestral) -> None:
dbx_path = "/test.txt"
md_new = _create_file_with_content(m, tmp_path, dbx_path, "new")
md_new = _create_file_with_content(m, dbx_path, "new")
with pytest.raises(NotFoundError):
m.get_file_diff("015db1e6dec9da000000001f7709020", md_new.rev)
def test_get_file_diff_unsupported_ext(m: Maestral, tmp_path) -> None:
def test_get_file_diff_unsupported_ext(m: Maestral) -> None:
"""Tests file diffs for unsupported file types."""
dbx_path = "/test.pdf"
md_old = _create_file_with_content(m, tmp_path, dbx_path, "old")
md_new = _create_file_with_content(m, tmp_path, dbx_path, "new")
md_old = _create_file_with_content(m, dbx_path, "old")
md_new = _create_file_with_content(m, dbx_path, "new")
with pytest.raises(UnsupportedFileTypeForDiff):
m.get_file_diff(md_old.rev, md_new.rev)
def test_get_file_diff_unsupported_content(m: Maestral, tmp_path) -> None:
def test_get_file_diff_unsupported_content(m: Maestral) -> None:
"""Tests file diffs for unsupported file types."""
dbx_path = "/test.txt"
# Upload a compiled c file with .txt extension
md_old = m.client.upload(resources + "/bin.txt", dbx_path)
md_new = _create_file_with_content(m, tmp_path, dbx_path, "new")
md_old = _create_file_with_content(m, dbx_path, b"\xcf\xfa\xed\xfe\x07")
md_new = _create_file_with_content(m, dbx_path, "new")
with pytest.raises(UnsupportedFileTypeForDiff):
m.get_file_diff(md_old.rev, md_new.rev)
def test_get_file_diff_unsupported_content_local(m: Maestral, tmp_path) -> None:
def test_get_file_diff_unsupported_content_local(m: Maestral) -> None:
dbx_path = "/test.txt"
local_path = m.to_local_path(dbx_path)
m.stop_sync()
wait_for_idle(m)
md_old = _create_file_with_content(m, tmp_path, dbx_path, "old")
md_old = _create_file_with_content(m, dbx_path, "old")
with open(local_path, "wb") as f:
f.write("möglich".encode("cp273"))

File diff suppressed because it is too large Load Diff

Binary file not shown.

Binary file not shown.

Before

Width:  |  Height:  |  Size: 314 KiB

View File

@ -1 +0,0 @@
content 1

View File

@ -1 +0,0 @@
content 2

View File

@ -1 +0,0 @@
content

View File

@ -1 +0,0 @@
content

View File

@ -78,15 +78,15 @@ def test_upload_session(client: DropboxClient) -> None:
def test_upload_hash_mismatch(client: DropboxClient, monkeypatch) -> None:
"""Test that DataCorruptionError is raised after four failed attempts."""
file = resources + "/file2.txt"
file = resources + "/file.txt"
hasher = failing_content_hasher()
monkeypatch.setattr(maestral.client, "DropboxContentHasher", hasher)
with pytest.raises(DataCorruptionError):
client.upload(file, "/file2.txt")
client.upload(file, "/file.txt")
assert not client.get_metadata("/file2.txt")
assert not client.get_metadata("/file.txt")
def test_upload_session_start_hash_mismatch(client: DropboxClient, monkeypatch) -> None:
@ -196,14 +196,14 @@ def test_upload_session_finish_hash_mismatch_retry(
def test_download_hash_mismatch(client: DropboxClient, monkeypatch, tmp_path) -> None:
# not tested during integration tests
file = resources + "/file2.txt"
client.upload(file, "/file2.txt")
file = resources + "/file.txt"
client.upload(file, "/file.txt")
hasher = failing_content_hasher(0, 4)
monkeypatch.setattr(maestral.client, "DropboxContentHasher", hasher)
with pytest.raises(DataCorruptionError):
client.download("/file2.txt", str(tmp_path / "file2.txt"))
client.download("/file.txt", str(tmp_path / "file.txt"))
@pytest.mark.parametrize("batch_size", [10, 30])