Пример #1
0
class TestIdentifierResolutionCoverageProvider(DatabaseTest):

    def setup(self):
        super(TestIdentifierResolutionCoverageProvider, self).setup()
        self.identifier = self._identifier(Identifier.OVERDRIVE_ID)
        self.source = DataSource.license_source_for(self._db, self.identifier)
        uploader = DummyS3Uploader()
        self.coverage_provider = IdentifierResolutionCoverageProvider(
            self._db, uploader=uploader, providers=([], [])
        )

        self.always_successful = AlwaysSuccessfulCoverageProvider(
            "Always", [self.identifier.type], self.source
        )
        self.never_successful = NeverSuccessfulCoverageProvider(
            "Never", [self.identifier.type], self.source
        )
        self.broken = BrokenCoverageProvider(
            "Broken", [self.identifier.type], self.source
        )

    def test_items_that_need_coverage(self):
        # Only items with an existing transient failure status require coverage.
        self._coverage_record(
            self.identifier, self.coverage_provider.output_source,
            operation=CoverageRecord.RESOLVE_IDENTIFIER_OPERATION,
            status=CoverageRecord.TRANSIENT_FAILURE
        )
        # Identifiers without coverage will be ignored.
        no_coverage = self._identifier(identifier_type=Identifier.ISBN)

        items = self.coverage_provider.items_that_need_coverage().all()
        eq_([self.identifier], items)

    def test_process_item_creates_license_pool(self):
        self.coverage_provider.required_coverage_providers = [
            self.always_successful
        ]

        self.coverage_provider.process_item(self.identifier)
        lp = self.identifier.licensed_through
        eq_(True, isinstance(lp, LicensePool))
        eq_(lp.data_source, self.coverage_provider.output_source)

    def test_process_item_succeeds_if_all_required_coverage_providers_succeed(self):
        self.coverage_provider.required_coverage_providers = [
            self.always_successful, self.always_successful
        ]

        # The coverage provider succeeded and returned an identifier.
        result = self.coverage_provider.process_item(self.identifier)
        eq_(result, self.identifier)

    def test_process_item_fails_if_any_required_coverage_providers_fail(self):
        self.coverage_provider.required_coverage_providers = [
            self.always_successful, self.never_successful
        ]

        result = self.coverage_provider.process_item(self.identifier)

        eq_(True, isinstance(result, CoverageFailure))
        eq_("500: What did you expect?", result.exception)
        eq_(False, result.transient)

        # The failure type of the IdentifierResolutionCoverageProvider
        # coverage record matches the failure type of the required provider's
        # coverage record.
        self.never_successful.transient = True
        result = self.coverage_provider.process_item(self.identifier)
        eq_(True, isinstance(result, CoverageFailure))
        eq_(True, result.transient)

    def test_process_item_fails_when_required_provider_raises_exception(self):
        self.coverage_provider.required_coverage_providers = [self.broken]
        result = self.coverage_provider.process_item(self.identifier)

        eq_(True, isinstance(result, CoverageFailure))
        eq_(True, result.transient)

    def test_process_item_fails_when_finalize_raises_exception(self):
        class FinalizeAlwaysFails(IdentifierResolutionCoverageProvider):
            def finalize(self, unresolved_identifier):
                raise Exception("Oh no!")

        provider = FinalizeAlwaysFails(
            self._db, uploader=DummyS3Uploader(), providers=([], [])
        )
        result = provider.process_item(self.identifier)

        eq_(True, isinstance(result, CoverageFailure))
        assert "Oh no!" in result.exception
        eq_(True, result.transient)

    def test_process_item_succeeds_when_optional_provider_fails(self):
        self.coverage_provider.required_coverage_providers = [
            self.always_successful, self.always_successful
        ]

        self.coverage_provider.optional_coverage_providers = [
            self.always_successful, self.never_successful
        ]

        result = self.coverage_provider.process_item(self.identifier)

        # A successful result is achieved, even though the optional
        # coverage provider failed.
        eq_(result, self.identifier)

        # An appropriate coverage record was created to mark the failure.
        presentation_edition = DataSource.lookup(
            self._db, DataSource.PRESENTATION_EDITION
        )
        r = self._db.query(CoverageRecord).filter(
            CoverageRecord.identifier==self.identifier,
            CoverageRecord.data_source!=presentation_edition).one()
        eq_("What did you expect?", r.exception)