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()
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)))
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;")
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))
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)')
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()
def init(storage, _, __): Storage(storage.path, timeout=0)
def test_path(db_path): storage = Storage(db_path) assert storage.path == db_path
def storage(): return Storage(':memory:')
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)))
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)
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
def test_make_reader_storage(): storage = Storage(':memory:') reader = make_reader('', _storage=storage) assert reader._storage is storage
def storage(): with closing(Storage(':memory:')) as storage: yield storage