File: test_status.py

package info (click to toggle)
yarsync 0.1.1%2Bdeb-2
  • links: PTS, VCS
  • area: main
  • in suites: bookworm
  • size: 624 kB
  • sloc: python: 1,905; makefile: 13
file content (127 lines) | stat: -rw-r--r-- 4,411 bytes parent folder | download
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
# -*- coding: utf-8 -*-
import os
import pytest
import subprocess
import sys
import time

from yarsync import YARsync
from .settings import (
    TEST_DIR, TEST_DIR_EMPTY, YSDIR, TEST_DIR_YS_BAD_PERMISSIONS,
    TEST_DIR_CONFIG_DIR, TEST_DIR_WORK_DIR, TEST_DIR_FILTER
)


def test_status_error(mocker, test_dir_read_only):
    ## test directory without .ys configuration
    os.chdir(test_dir_read_only)
    mocker_stdout = mocker.patch("sys.stdout")
    mocker_stderr = mocker.patch("sys.stderr")
    call = mocker.call

    args = ["yarsync", "status"]
    # issues a mocker warning
    # with mocker.patch("sys.stderr") as mocker_stderr:
    with pytest.raises(OSError) as err:
        ys = YARsync(args)
    assert ".ys not found" in repr(err.value)

    # adapted from https://stackoverflow.com/a/59398826/952234
    write_calls = mocker_stderr.write.call_args_list
    # [0] is call args, [1] is kwargs
    written_strs = "".join(call[0][0] for call in write_calls)
    # error message is correct
    assert written_strs.startswith(
        "! fatal: no yarsync configuration directory .ys found\n"
    )
    # no stdout output
    assert mocker_stdout.mock_calls == []

    # don't test for exact messages,
    # because we might improve them in the future.
    # assert mocker_print.mock_calls == [
    #     call.write('!'),
    #     call.write(' '),
    #     call.write("fatal: no yarsync configuration "
    #                ".ys found"),
    #     call.write('\n')
    # ]


@pytest.mark.skipif(os.geteuid() == 0, reason="This test is meant to be run for normal user")
def test_status_error_bad_permissions(capfd, test_dir_ys_bad_permissions):
    os.chdir(test_dir_ys_bad_permissions)
    ys = YARsync(["yarsync", "status"])
    returncode = ys()
    # rsync returns 23 in case of permission errors
    assert returncode == 23
    # mock will not work with non-Python stderr,
    # https://github.com/pytest-dev/pytest-mock/issues/295#issuecomment-1155105804
    # so we use capfd
    # https://docs.pytest.org/en/stable/how-to/capture-stdout-stderr.html#accessing-captured-output-from-a-test-function
    # https://docs.pytest.org/en/stable/reference/reference.html#capfd
    captured = capfd.readouterr()
    assert 'test_dir_ys_bad_permissions/forbidden" failed: Permission denied '\
           in captured.err
    assert "No synchronization information found." in captured.out


def test_status_no_commits(mocker):
    os.chdir(TEST_DIR_EMPTY)
    # io.StringIO uses only utf-8
    mocker_print = mocker.patch("sys.stdout")  #, new_callable=StringIO)

    args = ["yarsync", "status"]
    ys = YARsync(args)
    res = ys()
    call = mocker.call
    assert res == 0
    assert mocker_print.mock_calls == [
        call.write('No commits found'), call.write('\n')
    ]


@pytest.mark.parametrize(
    "command,test_dir",
    [
        (["yarsync"], TEST_DIR_FILTER),
        (["yarsync", "--config-dir="+TEST_DIR_CONFIG_DIR], TEST_DIR_WORK_DIR),
    ]
)
def test_status_existing_commits(capfd, command, test_dir):
    """Status works same for a normal and a detached configuration."""
    os.chdir(test_dir)
    # mocker_print = mocker.patch("sys.stdout")

    command.append("status")
    ys = YARsync(command)
    res = ys()
    # we don't check for the exact rsync message here, only for results.
    # # filter is needed, because not only .ys can be excluded
    # filter_str = ys._get_filter(include_commits=False)[1]
    assert res == 0

    ## stdout is correct
    # we don't test for exact lines, because they can change
    # when we e.g. add and remove a file to a subdirectory
    # (thus changing its timestamps)
    captured = capfd.readouterr()
    assert not captured.err
    assert captured.out.endswith(
        'Nothing to commit, working directory clean.\n'
        'No synchronization information found.\n'
    )
    # assert mocker_print.mock_calls == [
    #     # this is written only with -v
    #     # call.write('# '),
    #     # call.write(''),
    #     # call.write(
    #     #     "rsync -aun --delete -i --exclude=/.ys {} --outbuf=L {}/ {}/commits/2"\
    #     #     .format(filter_str, ys.root_dir, ys.config_dir)
    #     # ),
    #     # call.write('\n'),
    #     call.write('Nothing to commit, working directory clean.'),
    #     call.write('\n'),
    #     call.write('No synchronization information found.'),
    #     call.write('\n'),
    # ]