diff --git a/src/_secureaccesstokenauthorizer/model.py b/src/_secureaccesstokenauthorizer/model.py index f6da6946b47ea83945d174d18c52b9a9b6bc2d90..fb259f1e4e4377a43a70c740ff87909ebb3d977d 100644 --- a/src/_secureaccesstokenauthorizer/model.py +++ b/src/_secureaccesstokenauthorizer/model.py @@ -26,6 +26,7 @@ from json import ( ) from sqlite3 import ( + OperationalError, connect as _connect, ) @@ -36,12 +37,10 @@ from twisted.python.filepath import ( ) -class StoreAddError(Exception): - def __init__(self, reason): - self.reason = reason - - -class StoreDirectoryError(Exception): +class StoreOpenError(Exception): + """ + There was a problem opening the underlying data store. + """ def __init__(self, reason): self.reason = reason @@ -75,12 +74,17 @@ def open_and_initialize(path, required_schema_version, connect=None): try: path.parent().makedirs(ignoreExistingDirectory=True) except OSError as e: - raise StoreDirectoryError(e) + raise StoreOpenError(e) + + dbfile = path.asBytesMode().path + try: + conn = connect( + dbfile, + isolation_level="IMMEDIATE", + ) + except OperationalError as e: + raise StoreOpenError(e) - conn = connect( - path.asBytesMode().path, - isolation_level="IMMEDIATE", - ) with conn: cursor = conn.cursor() cursor.execute( diff --git a/src/_secureaccesstokenauthorizer/tests/test_model.py b/src/_secureaccesstokenauthorizer/tests/test_model.py index 2e7ba782120c41acc861705a74ffc238058435bd..3ef54d46d16e960fc2728f2abf46309bf1c49fc9 100644 --- a/src/_secureaccesstokenauthorizer/tests/test_model.py +++ b/src/_secureaccesstokenauthorizer/tests/test_model.py @@ -1,3 +1,4 @@ +# coding: utf-8 # Copyright 2019 PrivateStorage.io, LLC # # Licensed under the Apache License, Version 2.0 (the "License"); @@ -53,8 +54,9 @@ from twisted.python.filepath import ( from ..model import ( SchemaError, - StoreDirectoryError, + StoreOpenError, PaymentReferenceStore, + PaymentReference, open_and_initialize, memory_connect, ) @@ -174,12 +176,12 @@ class PaymentReferenceStoreTests(TestCase): ) - @given(tahoe_configs(), payment_reference_numbers()) - def test_uncreateable_store_directory(self, get_config, prn): + @given(tahoe_configs()) + def test_uncreateable_store_directory(self, get_config): """ If the underlying directory in the node configuration cannot be created then ``PaymentReferenceStore.from_node_config`` raises - ``StoreDirectoryError``. + ``StoreOpenError``. """ tempdir = self.useFixture(TempDir()) nodedir = tempdir.join(b"node") @@ -199,7 +201,7 @@ class PaymentReferenceStoreTests(TestCase): AfterPreprocessing( lambda (type, exc, tb): exc, MatchesAll( - IsInstance(StoreDirectoryError), + IsInstance(StoreOpenError), MatchesStructure( reason=MatchesAll( IsInstance(OSError), @@ -212,3 +214,44 @@ class PaymentReferenceStoreTests(TestCase): ), ), ) + + + @given(tahoe_configs()) + def test_unopenable_store(self, get_config): + """ + If the underlying database file cannot be opened then + ``PaymentReferenceStore.from_node_config`` raises ``StoreOpenError``. + """ + tempdir = self.useFixture(TempDir()) + nodedir = tempdir.join(b"node") + + config = get_config(nodedir, b"tub.port") + + # Create the underlying database file. + store = PaymentReferenceStore.from_node_config(config) + + # Prevent further access to it. + store.database_path.chmod(0o000) + + self.assertThat( + lambda: PaymentReferenceStore.from_node_config( + config, + ), + raises(StoreOpenError), + ) + + +class PaymentReferenceTests(TestCase): + """ + Tests for ``PaymentReference``. + """ + @given(payment_reference_numbers()) + def test_json_roundtrip(self, prn): + """ + ``PaymentReference.to_json . PaymentReference.from_json → id`` + """ + ref = PaymentReference(prn) + self.assertThat( + PaymentReference.from_json(ref.to_json()), + Equals(ref), + )