vdirsyncer/tests/utils/test_main.py
Markus Unterwaditzer 8ab9c429cc Rewrite safe_write
2015-01-12 00:32:49 +01:00

243 lines
7.1 KiB
Python

# -*- coding: utf-8 -*-
'''
tests.utils.test_main
~~~~~~~~~~~~~~~~~~~~~
:copyright: (c) 2014 Markus Unterwaditzer & contributors
:license: MIT, see LICENSE for more details.
'''
import os
import stat
import click
from click.testing import CliRunner
import pytest
import requests
import vdirsyncer.doubleclick as doubleclick
import vdirsyncer.utils as utils
from .. import blow_up
class EmptyNetrc(object):
def __init__(self, file=None):
self._file = file
def authenticators(self, hostname):
return None
class EmptyKeyring(object):
def get_password(self, *a, **kw):
return None
@pytest.fixture(autouse=True)
def empty_password_storages(monkeypatch):
monkeypatch.setattr('netrc.netrc', EmptyNetrc)
monkeypatch.setattr(utils, 'keyring', EmptyKeyring())
def test_get_password_from_netrc(monkeypatch):
username = 'foouser'
password = 'foopass'
resource = 'http://example.com/path/to/whatever/'
hostname = 'example.com'
calls = []
class Netrc(object):
def authenticators(self, hostname):
calls.append(hostname)
return username, 'bogus', password
monkeypatch.setattr('netrc.netrc', Netrc)
monkeypatch.setattr('getpass.getpass', blow_up)
_password = utils.get_password(username, resource)
assert _password == password
assert calls == [hostname]
def test_get_password_from_system_keyring(monkeypatch):
username = 'foouser'
password = 'foopass'
resource = 'http://example.com/path/to/whatever/'
hostname = 'example.com'
class KeyringMock(object):
def get_password(self, resource, _username):
assert _username == username
assert resource == utils.password_key_prefix + hostname
return password
monkeypatch.setattr(utils, 'keyring', KeyringMock())
monkeypatch.setattr('getpass.getpass', blow_up)
_password = utils.get_password(username, resource)
assert _password == password
def test_get_password_from_command(tmpdir):
username = 'my_username'
resource = 'http://example.com'
password = 'testpassword'
filename = 'command.sh'
filepath = str(tmpdir) + '/' + filename
f = open(filepath, 'w')
f.write('#!/bin/sh\n'
'[ "$1" != "my_username" ] && exit 1\n'
'[ "$2" != "example.com" ] && exit 1\n'
'echo "{}"'.format(password))
f.close()
st = os.stat(filepath)
os.chmod(filepath, st.st_mode | stat.S_IEXEC)
@doubleclick.click.command()
@doubleclick.click.pass_context
def fake_app(ctx):
ctx.obj = {'config': ({'password_command': filepath}, {}, {})}
_password = utils.get_password(username, resource)
assert _password == password
runner = CliRunner()
result = runner.invoke(fake_app)
assert not result.exception
def test_get_password_from_prompt():
user = 'my_user'
resource = 'http://example.com'
@click.command()
def fake_app():
x = utils.get_password(user, resource)
click.echo('Password is {}'.format(x))
runner = CliRunner()
result = runner.invoke(fake_app, input='my_password\n\n')
assert not result.exception
assert result.output.splitlines() == [
'Server password for {} at host {}: '.format(user, 'example.com'),
'Password is my_password'
]
def test_set_keyring_password(monkeypatch):
class KeyringMock(object):
def get_password(self, resource, username):
assert resource == utils.password_key_prefix + 'example.com'
assert username == 'foouser'
return None
def set_password(self, resource, username, password):
assert resource == utils.password_key_prefix + 'example.com'
assert username == 'foouser'
assert password == 'hunter2'
monkeypatch.setattr(utils, 'keyring', KeyringMock())
@doubleclick.click.command()
@doubleclick.click.pass_context
def fake_app(ctx):
ctx.obj = {}
x = utils.get_password('foouser', 'http://example.com/a/b')
click.echo('password is ' + x)
runner = CliRunner()
result = runner.invoke(fake_app, input='hunter2\ny\n')
assert not result.exception
assert result.output == (
'Server password for foouser at host example.com: \n'
'Save this password in the keyring? [y/N]: y\n'
'password is hunter2\n'
)
def test_get_password_from_cache(monkeypatch):
user = 'my_user'
resource = 'http://example.com'
@doubleclick.click.command()
@doubleclick.click.pass_context
def fake_app(ctx):
ctx.obj = {}
x = utils.get_password(user, resource)
click.echo('Password is {}'.format(x))
monkeypatch.setattr(doubleclick.click, 'prompt', blow_up)
assert (user, 'example.com') in ctx.obj['passwords']
x = utils.get_password(user, resource)
click.echo('Password is {}'.format(x))
runner = CliRunner()
result = runner.invoke(fake_app, input='my_password\n')
assert not result.exception
assert result.output.splitlines() == [
'Server password for {} at host {}: '.format(user, 'example.com'),
'Save this password in the keyring? [y/N]: ',
'Password is my_password',
'debug: Got password for my_user from internal cache',
'Password is my_password'
]
def test_get_class_init_args():
class Foobar(object):
def __init__(self, foo, bar, baz=None):
pass
all, required = utils.get_class_init_args(Foobar)
assert all == {'foo', 'bar', 'baz'}
assert required == {'foo', 'bar'}
def test_get_class_init_args_on_storage():
from vdirsyncer.storage.memory import MemoryStorage
all, required = utils.get_class_init_args(MemoryStorage)
assert all == set(['fileext', 'collection', 'read_only', 'instance_name',
'collection_human'])
assert not required
@pytest.mark.skipif(not utils.compat.PY2,
reason='https://github.com/shazow/urllib3/issues/529')
def test_request_ssl(httpsserver):
sha1 = '94:FD:7A:CB:50:75:A4:69:82:0A:F8:23:DF:07:FC:69:3E:CD:90:CA'
md5 = '19:90:F7:23:94:F2:EF:AB:2B:64:2D:57:3D:25:95:2D'
httpsserver.serve_content('') # we need to serve something
with pytest.raises(requests.exceptions.SSLError) as excinfo:
utils.request('GET', httpsserver.url)
assert 'certificate verify failed' in str(excinfo.value)
utils.request('GET', httpsserver.url, verify=False)
utils.request('GET', httpsserver.url,
verify_fingerprint=sha1)
utils.request('GET', httpsserver.url, verify_fingerprint=md5)
with pytest.raises(requests.exceptions.SSLError) as excinfo:
utils.request('GET', httpsserver.url,
verify_fingerprint=''.join(reversed(sha1)))
assert 'Fingerprints did not match' in str(excinfo.value)
def test_atomic_write(tmpdir):
x = utils.atomic_write
fname = tmpdir.join('ha')
for i in range(2):
with x(str(fname), binary=False, overwrite=True) as f:
f.write('hoho')
with pytest.raises(OSError):
with x(str(fname), binary=False, overwrite=False) as f:
f.write('haha')
assert fname.read() == 'hoho'