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 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162
|
# -*- coding: utf-8 -*-
import os
import pytest
import subprocess
import sys
import time
from yarsync import YARsync
from .settings import TEST_DIR_EMPTY, YSDIR
def test_commit(mocker):
"""Test commit creation and logging."""
os.chdir(TEST_DIR_EMPTY)
# important that it goes before patches, we need normal initialization
commit_msg = "initial commit"
args = ["yarsync", "commit", "-m", commit_msg]
ys = YARsync(args)
# time.localtime uses time.time
time_3 = time.localtime(3)
def loctime(sec=None):
return time_3
mocker.patch("time.localtime", loctime)
# hope this will work in another time zone.
mocker.patch("time.tzname", "MSK")
# time.time is called a slight instant after time.localtime
# their order is not important though.
commit_time = 2
mocker.patch("time.time", lambda: commit_time)
rename = mocker.patch("os.rename")
mkdir = mocker.patch("os.mkdir")
mocker.patch("socket.gethostname", lambda: "host")
mocker.patch("getpass.getuser", lambda: "user")
# we only read repofile. Otherwise must be changed!
m = mocker.mock_open(read_data="myhost")
if sys.version[0] == "2":
mocker.patch("__builtin__.open", m)
else:
mocker.patch("builtins.open", m)
popen = mocker.patch("subprocess.Popen")
subprocess_mock = mocker.Mock()
attrs = {'communicate.return_value': ('output', 'error')}
subprocess_mock.configure_mock(**attrs)
subprocess_mock.configure_mock(**{"returncode": 0})
popen.return_value = subprocess_mock
commit_name = str(int(commit_time))
commit_dir = os.path.join(ys.COMMITDIR, commit_name)
commit_dir_tmp = commit_dir + "_tmp"
commit_log_path = os.path.join(ys.LOGDIR, commit_name + ".txt")
commit_time_str = time.strftime(ys.DATEFMT, time.localtime())
# call _commit
res = ys()
filter_ = ys._get_filter(include_commits=False)[0]
call = mocker.call
assert res == 0
assert mkdir.mock_calls == [
call(ys.COMMITDIR),
call(ys.LOGDIR),
]
assert rename.mock_calls == [
call(commit_dir_tmp, commit_dir),
]
assert popen.mock_calls == [
call(["rsync", "-a", "--link-dest=../../..", "--exclude=/.ys"]
+ filter_ +
[ys.root_dir + '/', os.path.join(ys.COMMITDIR, "2_tmp")],
stdout=-3),
call().communicate(),
]
# this seems patched, but the date on Python 3.6 is still different
assert time.tzname == "MSK"
# will be UTC
time_str = time.strftime(ys.DATEFMT, time_3)
assert m.mock_calls == [
call(ys.REPOFILE),
call().__enter__(),
call().read(),
call().__exit__(None, None, None),
call(commit_log_path, "w"), call().__enter__(),
call().write(commit_msg + "\n\n"
"When: {}\n".format(time_str) +
"Where: user@myhost"),
call().write('\n'),
call().__exit__(None, None, None),
]
def test_commit_rsync_error(mocker):
os.chdir(TEST_DIR_EMPTY)
popen = mocker.patch("subprocess.Popen")
subprocess_mock = mocker.Mock()
attrs = {'communicate.return_value': ('output', 'error')}
subprocess_mock.configure_mock(**attrs)
# some error occurred in rsync
subprocess_mock.configure_mock(returncode=1)
popen.return_value = subprocess_mock
# just in case. Now it won't be called, but to make code more stable.
mocker.patch("os.mkdir")
args = ["yarsync", "commit"]
ys = YARsync(args)
res = ys()
assert res == 1
def test_existent_commit_exception(mocker):
os.chdir(TEST_DIR_EMPTY)
mocker.patch("time.time", lambda: 2)
def _os_path_exists(filepath):
if YSDIR in filepath and not filepath.endswith("MERGE.txt"):
return True
return False
mocker.patch("os.path.exists", _os_path_exists)
args = "yarsync commit".split()
ys = YARsync(args)
with pytest.raises(RuntimeError) as err:
res = ys()
# can't compare them directly
assert repr(err.value) == repr(RuntimeError(
"commit {} exists".format(os.path.join(ys.COMMITDIR, "2"))
))
def test_existent_tmp_commit_exception(mocker):
os.chdir(TEST_DIR_EMPTY)
mocker.patch("time.time", lambda: 2)
def _os_path_exists(filepath):
if YSDIR in filepath:
# print("path = ", filepath)
return "_tmp" in filepath
return False
# initialization is fine, because the config file is present
args = "yarsync commit".split()
ys = YARsync(args)
mocker.patch("os.path.exists", _os_path_exists)
mocker.patch("os.mkdir")
with pytest.raises(RuntimeError) as err:
res = ys()
assert repr(err.value) == repr(RuntimeError(
"temporary commit {} exists".format(os.path.join(ys.COMMITDIR, "2_tmp"))
))
|