From 7f802515273ce5396fe6794baedf296a38d753c0 Mon Sep 17 00:00:00 2001 From: Markus Unterwaditzer Date: Tue, 30 May 2017 09:12:00 +0200 Subject: [PATCH] Test development Radicale again (#428) * Revert "Don't test development Radicale" This reverts commit 7a5241101e811a02ab14f4f79fb2f35b4ee8590c. * Fix Radicale test setup * Radicale is very tolerant * Simplify test such that output is more predictable * Runtime version check for Radicale * Don't create user explicitly * stylefix * Shorter tracebacks Travis logs are very hard to read --- Makefile | 1 - setup.cfg | 1 + tests/storage/__init__.py | 10 +- tests/storage/dav/__init__.py | 6 +- tests/storage/servers/radicale/__init__.py | 124 +++++---------------- tests/storage/servers/radicale/install.sh | 15 ++- vdirsyncer/http.py | 2 +- 7 files changed, 46 insertions(+), 113 deletions(-) diff --git a/Makefile b/Makefile index c45de07..8301baa 100644 --- a/Makefile +++ b/Makefile @@ -2,7 +2,6 @@ export DAV_SERVER := skip export REMOTESTORAGE_SERVER := skip -export RADICALE_BACKEND := filesystem export REQUIREMENTS := release export TESTSERVER_BASE := ./tests/storage/servers/ export CI := false diff --git a/setup.cfg b/setup.cfg index 2830aa8..1909b8d 100644 --- a/setup.cfg +++ b/setup.cfg @@ -3,6 +3,7 @@ universal = 1 [tool:pytest] norecursedirs = tests/storage/servers/* +addopts = --tb=short [flake8] # E731: Use a def instead of lambda expr diff --git a/tests/storage/__init__.py b/tests/storage/__init__.py index 697b4ce..db953b9 100644 --- a/tests/storage/__init__.py +++ b/tests/storage/__init__.py @@ -322,11 +322,11 @@ class StorageTests(object): BEGIN:VCALENDAR VERSION:2.0 BEGIN:VEVENT - DTSTART;TZID=Australia/Sydney:20140325T084000 - DTEND;TZID=Australia/Sydney:20140325T101000 + DTSTART;TZID=UTC:20140325T084000Z + DTEND;TZID=UTC:20140325T101000Z DTSTAMP:20140327T060506Z UID:{uid} - RECURRENCE-ID;TZID=Australia/Sydney:20140325T083000 + RECURRENCE-ID;TZID=UTC:20140325T083000Z CREATED:20131216T033331Z DESCRIPTION: LAST-MODIFIED:20140327T060215Z @@ -337,8 +337,8 @@ class StorageTests(object): TRANSP:OPAQUE END:VEVENT BEGIN:VEVENT - DTSTART;TZID=Australia/Sydney:20140128T083000 - DTEND;TZID=Australia/Sydney:20140128T100000 + DTSTART;TZID=UTC:20140128T083000Z + DTEND;TZID=UTC:20140128T100000Z RRULE:FREQ=WEEKLY;UNTIL=20141208T213000Z;BYDAY=TU DTSTAMP:20140327T060506Z UID:{uid} diff --git a/tests/storage/dav/__init__.py b/tests/storage/dav/__init__.py index edcd2a4..2da3d8b 100644 --- a/tests/storage/dav/__init__.py +++ b/tests/storage/dav/__init__.py @@ -24,12 +24,12 @@ ServerMixin = get_server_mixin(dav_server) class DAVStorageTests(ServerMixin, StorageTests): dav_server = dav_server + @pytest.mark.skipif(dav_server == 'radicale', + reason='Radicale is very tolerant.') def test_dav_broken_item(self, s): item = Item(u'HAHA:YES') - try: + with pytest.raises((exceptions.Error, requests.exceptions.HTTPError)): s.upload(item) - except (exceptions.Error, requests.exceptions.HTTPError): - pass assert not list(s.list()) def test_dav_empty_get_multi_performance(self, s, monkeypatch): diff --git a/tests/storage/servers/radicale/__init__.py b/tests/storage/servers/radicale/__init__.py index ae0f2f7..66b1407 100644 --- a/tests/storage/servers/radicale/__init__.py +++ b/tests/storage/servers/radicale/__init__.py @@ -1,105 +1,42 @@ # -*- coding: utf-8 -*- -import os -import sys - -from urllib.parse import quote as urlquote - +import logging import pytest +import radicale +import radicale.config + +from pkg_resources import parse_version as ver + import wsgi_intercept import wsgi_intercept.requests_intercept - -RADICALE_SCHEMA = ''' -create table collection ( - path varchar(200) not null, - parent_path varchar(200) references collection (path), - primary key (path)); - -create table item ( - name varchar(200) not null, - tag text not null, - collection_path varchar(200) references collection (path), - primary key (name)); - -create table header ( - name varchar(200) not null, - value text not null, - collection_path varchar(200) references collection (path), - primary key (name, collection_path)); - -create table line ( - name text not null, - value text not null, - item_name varchar(200) references item (name), - timestamp bigint not null, - primary key (timestamp)); - -create table property ( - name varchar(200) not null, - value text not null, - collection_path varchar(200) references collection (path), - primary key (name, collection_path)); -'''.split(';') - -storage_backend = os.environ.get('RADICALE_BACKEND', '') or 'filesystem' - - -def do_the_radicale_dance(tmpdir): - # All of radicale is already global state, the cleanliness of the code and - # all hope is already lost. This function runs before every test. - - # This wipes out the radicale modules, to reset all of its state. - for module in list(sys.modules): - if module.startswith('radicale'): - del sys.modules[module] - - # radicale.config looks for this envvar. We have to delete it before it - # tries to load a config file. - os.environ['RADICALE_CONFIG'] = '' - import radicale.config - - # Now we can set some basic configuration. - # Radicale <=0.7 doesn't work with this, therefore we just catch the - # exception and assume Radicale is open for everyone. - try: - radicale.config.set('rights', 'type', 'owner_only') - radicale.config.set('auth', 'type', 'http') - - import radicale.auth.http - - def is_authenticated(user, password): - return user == 'bob' and password == 'bob' - radicale.auth.http.is_authenticated = is_authenticated - except Exception as e: - print(e) - - if storage_backend in ('filesystem', 'multifilesystem'): - radicale.config.set('storage', 'type', storage_backend) - radicale.config.set('storage', 'filesystem_folder', tmpdir) - elif storage_backend == 'database': - radicale.config.set('storage', 'type', 'database') - radicale.config.set('storage', 'database_url', 'sqlite://') - from radicale.storage import database - - s = database.Session() - for line in RADICALE_SCHEMA: - s.execute(line) - s.commit() - else: - raise RuntimeError(storage_backend) +logger = logging.getLogger(__name__) class ServerMixin(object): @pytest.fixture(autouse=True) def setup(self, request, tmpdir): - do_the_radicale_dance(str(tmpdir)) - from radicale import Application + if ver(radicale.VERSION) < ver('2.0.0-pre'): + raise RuntimeError('Testing against Radicale only works with ' + 'Radicale >= 2.0.0') + + def get_app(): + config = radicale.config.load(()) + config.set('storage', 'filesystem_folder', str(tmpdir)) + config.set('rights', 'type', 'owner_only') + + app = radicale.Application(config, logger) + + def is_authenticated(user, password): + return user == 'bob' and password == 'bob' + + app.is_authenticated = is_authenticated + return app wsgi_intercept.requests_intercept.install() - wsgi_intercept.add_wsgi_intercept('127.0.0.1', 80, Application) + wsgi_intercept.add_wsgi_intercept('127.0.0.1', 80, get_app) def teardown(): wsgi_intercept.remove_wsgi_intercept('127.0.0.1', 80) @@ -109,17 +46,14 @@ class ServerMixin(object): @pytest.fixture def get_storage_args(self, get_item): def inner(collection='test'): - url = 'http://127.0.0.1/bob/' - if collection is not None: - collection += self.storage_class.fileext - url = url.rstrip('/') + '/' + urlquote(collection) - - rv = {'url': url, 'username': 'bob', 'password': 'bob', - 'collection': collection} + url = 'http://127.0.0.1/' + rv = {'url': url, 'username': 'bob', 'password': 'bob'} if collection is not None: + collection = collection + self.storage_class.fileext + rv = self.storage_class.create_collection(collection, **rv) s = self.storage_class(**rv) - s.delete(*s.upload(get_item())) + assert not list(s.list()) return rv return inner diff --git a/tests/storage/servers/radicale/install.sh b/tests/storage/servers/radicale/install.sh index 308f044..16ecd01 100644 --- a/tests/storage/servers/radicale/install.sh +++ b/tests/storage/servers/radicale/install.sh @@ -1,13 +1,12 @@ #!/bin/sh set -e -if [ -z "$RADICALE_BACKEND" ]; then - echo "Missing RADICALE_BACKEND" +if [ "$REQUIREMENTS" = "release" ] || [ "$REQUIREMENTS" = "minimal" ]; then + radicale_pkg="radicale" +elif [ "$REQUIREMENTS" = "devel" ]; then + radicale_pkg="git+https://github.com/Kozea/Radicale.git" +else + echo "Invalid requirements envvar" false fi - -pip install wsgi_intercept radicale - -if [ "$RADICALE_BACKEND" = "database" ]; then - pip install sqlalchemy -fi +pip install wsgi_intercept $radicale_pkg diff --git a/vdirsyncer/http.py b/vdirsyncer/http.py index 77f13dc..915d7aa 100644 --- a/vdirsyncer/http.py +++ b/vdirsyncer/http.py @@ -177,7 +177,7 @@ def request(method, url, session=None, latin1_fallback=True, if r.status_code == 412: raise exceptions.PreconditionFailed(r.reason) - if r.status_code == 404: + if r.status_code in (404, 410): raise exceptions.NotFoundError(r.reason) r.raise_for_status()