Пример #1
0
def test_close_error():
    class Connection(sqlite3.Connection):
        pass

    def execute(*args):
        raise sqlite3.ProgrammingError('unexpected error')

    storage = Storage(':memory:', factory=Connection)
    storage.db.execute = execute

    # should not be StorageError, because it's likely a bug
    with pytest.raises(sqlite3.ProgrammingError):
        storage.close()
Пример #2
0
def test_get_entries_for_update_param_limit(entry_count):
    """get_entries_for_update() should work even if the number of query
    parameters goes over the variable_number SQLite run-time limit.

    https://github.com/lemon24/reader/issues/109

    """
    storage = Storage(':memory:')

    # shouldn't raise an exception
    list(
        storage.get_entries_for_update(
            ('feed', 'entry-{}'.format(i)) for i in range(entry_count)))
    list(
        storage.get_entries_for_update(
            ('feed', 'entry-{}'.format(i)) for i in range(entry_count)))
Пример #3
0
 def target():
     storage = Storage(db_path, wal_enabled=False)
     storage.db.isolation_level = None
     storage.db.execute("BEGIN EXCLUSIVE;")
     in_transaction.set()
     can_return_from_transaction.wait()
     storage.db.execute("ROLLBACK;")
Пример #4
0
def test_minimum_sqlite_version(db_path, monkeypatch):
    mock = MagicMock(wraps=require_version, side_effect=DBError)
    monkeypatch.setattr('reader._sqlite_utils.require_version', mock)

    with pytest.raises(StorageError):
        Storage(db_path)

    mock.assert_called_with(ANY, (3, 15))
Пример #5
0
def test_close():
    storage = Storage(':memory:')

    storage.db.execute('values (1)')

    storage.close()
    # no-op a second time
    storage.close()

    with pytest.raises(sqlite3.ProgrammingError):
        storage.db.execute('values (1)')
Пример #6
0
def check_errors_locked(db_path, pre_stuff, do_stuff, exc_type):
    """Actual implementation of test_errors_locked, so it can be reused."""

    # WAL provides more concurrency; some things won't to block with it enabled.
    storage = Storage(db_path, wal_enabled=False)
    storage.db.execute("PRAGMA busy_timeout = 0;")

    feed = FeedData('one')
    entry = EntryData('one', 'entry', datetime(2010, 1, 2))
    storage.add_feed(feed.url, datetime(2010, 1, 1))
    storage.add_or_update_entry(
        EntryUpdateIntent(entry, entry.updated, datetime(2010, 1, 1), 0, 0))

    in_transaction = threading.Event()
    can_return_from_transaction = threading.Event()

    def target():
        storage = Storage(db_path, wal_enabled=False)
        storage.db.isolation_level = None
        storage.db.execute("BEGIN EXCLUSIVE;")
        in_transaction.set()
        can_return_from_transaction.wait()
        storage.db.execute("ROLLBACK;")

    if pre_stuff:
        pre_stuff(storage, feed, entry)

    thread = threading.Thread(target=target)
    thread.start()

    in_transaction.wait()

    try:
        with pytest.raises(exc_type) as excinfo:
            do_stuff(storage, feed, entry)
        assert 'locked' in str(excinfo.value.__cause__)
    finally:
        can_return_from_transaction.set()
        thread.join()
Пример #7
0
def init(storage, _, __):
    Storage(storage.path, timeout=0)
Пример #8
0
def test_path(db_path):
    storage = Storage(db_path)
    assert storage.path == db_path
Пример #9
0
def storage():
    return Storage(':memory:')
Пример #10
0
def test_update_feed_last_updated_not_found(db_path):
    storage = Storage(db_path)
    with pytest.raises(FeedNotFoundError):
        storage.update_feed(
            FeedUpdateIntent('inexistent-feed', datetime(2010, 1, 2)))
Пример #11
0
def check_iter_locked(db_path, pre_stuff, iter_stuff):
    """Actual implementation of test_errors_locked, so it can be reused."""

    # WAL provides more concurrency; some things won't to block with it enabled.
    storage = Storage(db_path, wal_enabled=False)

    feed = FeedData('one')
    entry = EntryData('one', 'entry', datetime(2010, 1, 1), title='entry')
    storage.add_feed(feed.url, datetime(2010, 1, 2))
    storage.add_or_update_entry(
        EntryUpdateIntent(entry, entry.updated, datetime(2010, 1, 1), 0, 0))
    storage.add_feed('two', datetime(2010, 1, 1))
    storage.add_or_update_entry(
        EntryUpdateIntent(entry._replace(feed_url='two'), entry.updated,
                          datetime(2010, 1, 1), 0, 0))
    storage.set_feed_metadata('two', '1', 1)
    storage.set_feed_metadata('two', '2', 2)
    storage.add_feed_tag('two', '1')
    storage.add_feed_tag('two', '2')

    if pre_stuff:
        pre_stuff(storage)

    rv = iter_stuff(storage)
    next(rv)

    # shouldn't raise an exception
    storage = Storage(db_path, timeout=0, wal_enabled=False)
    storage.mark_as_read_unread(feed.url, entry.id, 1)
    storage = Storage(db_path, timeout=0)
    storage.mark_as_read_unread(feed.url, entry.id, 0)
Пример #12
0
def test_storage_errors_connect(tmpdir):
    # try to open a directory
    with pytest.raises(StorageError) as excinfo:
        Storage(str(tmpdir))
    assert isinstance(excinfo.value.__cause__, sqlite3.OperationalError)
    assert 'while opening' in excinfo.value.message
Пример #13
0
def test_make_reader_storage():
    storage = Storage(':memory:')
    reader = make_reader('', _storage=storage)
    assert reader._storage is storage
Пример #14
0
def storage():
    with closing(Storage(':memory:')) as storage:
        yield storage