コード例 #1
0
    def test_delegates_to_agent_for_location(self, agent):
        """
        When a request is made using the agent, the added agents are delegated
        to based on the URI location/authority.
        """
        agent.add_agent(b'foo:8080', DummyAgent())
        agent.add_agent(b'bar:8080', FailingAgent(RuntimeError('bar')))
        agent.add_agent(b'foo:9090', FailingAgent(RuntimeError('9090')))

        d = agent.request(b'GET', b'http://foo:8080')
        assert_that(d, succeeded(MatchesListwise([
            MatchesListwise([Equals(b'GET'), Equals(b'http://foo:8080')]),
            MatchesDict({'headers': Is(None), 'bodyProducer': Is(None)})
        ])))

        # Scheme doesn't matter
        d = agent.request(b'GET', b'https://foo:8080')
        assert_that(d, succeeded(MatchesListwise([
            MatchesListwise([Equals(b'GET'), Equals(b'https://foo:8080')]),
            MatchesDict({'headers': Is(None), 'bodyProducer': Is(None)})
        ])))

        # Path doesn't matter
        d = agent.request(b'GET', b'http://foo:8080/bar/baz')
        assert_that(d, succeeded(MatchesListwise([
            MatchesListwise([
                Equals(b'GET'), Equals(b'http://foo:8080/bar/baz')]),
            MatchesDict({'headers': Is(None), 'bodyProducer': Is(None)})
        ])))

        # Hostname *does* matter
        d = agent.request(b'GET', b'http://bar:8080')
        assert_that(d, failed(MatchesStructure(value=MatchesAll(
            IsInstance(RuntimeError),
            MatchesPredicate(str, Equals('bar'))
        ))))

        # Port *does* matter
        d = agent.request(b'GET', b'http://foo:9090')
        assert_that(d, failed(MatchesStructure(value=MatchesAll(
            IsInstance(RuntimeError),
            MatchesPredicate(str, Equals('9090'))
        ))))

        # Other args passed through
        d = agent.request(b'GET', b'http://foo:8080', 'bar', 'baz')
        assert_that(d, succeeded(MatchesListwise([
            MatchesListwise([Equals(b'GET'), Equals(b'http://foo:8080')]),
            MatchesDict(
                {'headers': Equals('bar'), 'bodyProducer': Equals('baz')})
        ])))
コード例 #2
0
    def test_no_folder_arg(self):
        """
        An error is printed if we don't specify --folder
        """
        stdout = StringIO()
        stderr = StringIO()

        self.assertThat(
            dispatch_magic_folder_api_command(
                ["add-snapshot", "--file", "foo"],
                stdout=stdout,
                stderr=stderr,
                client=None,
            ),
            failed(
                AfterPreprocessing(
                    lambda f: isinstance(f.value, SystemExit) and f.value.code,
                    Equals(1)
                )
            )
        )
        self.assertThat(
            stdout.getvalue().strip(),
            Equals("Error: --folder / -n is required")
        )
コード例 #3
0
ファイル: test_common.py プロジェクト: sajith/tahoe-lafs
    def test_disconnected(self):
        """
        If the transport is disconnected before the response is available, no
        ``RuntimeError`` is logged for finishing a disconnected request.
        """
        result = Deferred()
        resource = StaticResource(result)
        d = render(resource, {})

        resource._request.connectionLost(Failure(ConnectionDone()))
        result.callback(b"Some result")

        self.assertThat(
            d,
            failed(
                AfterPreprocessing(
                    lambda reason: reason.type,
                    Equals(ConnectionDone),
                ),
            ),
        )

        # Since we're not a trial TestCase we don't have flushLoggedErrors.
        # The next best thing is to make sure any dangling Deferreds have been
        # garbage collected and then let the generic trial logic for failing
        # tests with logged errors kick in.
        gc.collect()
コード例 #4
0
    def test_get_events_non_200(self):
        """
        When a request is made to Marathon's event stream, and a non-200
        response code is returned, an error should be raised.
        """
        data = []
        d = self.cleanup_d(self.client.get_events({'test': data.append}))

        request = yield self.requests.get()
        self.assertThat(request, HasRequestProperties(
            method='GET', url=self.uri('/v2/events'),
            query={'event_type': ['test']}))
        self.assertThat(request.requestHeaders,
                        HasHeader('accept', ['text/event-stream']))

        request.setResponseCode(202)
        request.setHeader('Content-Type', 'text/event-stream')

        json_data = {'hello': 'world'}
        write_json_event(request, 'test', json_data)

        yield wait0()
        self.assertThat(d, failed(WithErrorTypeAndMessage(
            HTTPError, 'Non-200 response code (202) for url: '
                       'http://localhost:8080/v2/events?event_type=test')))

        self.assertThat(data, Equals([]))

        request.finish()
        yield d
コード例 #5
0
    def test_get_events_incorrect_content_type(self):
        """
        When a request is made to Marathon's event stream, and the content-type
        header value returned is not "text/event-stream", an error should be
        raised.
        """
        data = []
        d = self.cleanup_d(self.client.get_events({'test': data.append}))

        request = yield self.requests.get()
        self.assertThat(request, HasRequestProperties(
            method='GET', url=self.uri('/v2/events'),
            query={'event_type': ['test']}))
        self.assertThat(request.requestHeaders,
                        HasHeader('accept', ['text/event-stream']))

        request.setResponseCode(200)
        request.setHeader('Content-Type', 'application/json')

        json_data = {'hello': 'world'}
        write_json_event(request, 'test', json_data)

        yield wait0()
        self.assertThat(d, failed(WithErrorTypeAndMessage(
            HTTPError,
            'Expected header "Content-Type" to be "text/event-stream" but '
            'found "application/json" instead')))

        self.assertThat(data, Equals([]))

        request.finish()
        yield d
コード例 #6
0
    def test_get_json_field_missing_content_type(self):
        """
        When get_json_field is used to make a request and the content-type
        header is not set in the response headers then an error should be
        raised.
        """
        d = self.cleanup_d(
            self.client.get_json_field('field-key', path='/my-path'))

        request = yield self.requests.get()
        self.assertThat(request, HasRequestProperties(
            method='GET', url=self.uri('/my-path')))

        request.setResponseCode(200)
        # Twisted will set the content type to "text/html" by default but this
        # can be disabled by setting the default content type to None:
        # https://twistedmatrix.com/documents/current/api/twisted.web.server.Request.html#defaultContentType
        request.defaultContentType = None
        request.write(json.dumps({}).encode('utf-8'))
        request.finish()

        yield wait0()
        self.assertThat(d, failed(WithErrorTypeAndMessage(
            HTTPError, 'Expected header "Content-Type" to be '
                       '"application/json" but header not found in response')))
コード例 #7
0
    def test_should_not_redeem(self, get_config, now, voucher, public_key):
        """
        ``PaymentController.redeem`` raises ``ValueError`` if passed a voucher in
        a state when redemption should not be started.
        """
        store = self.useFixture(TemporaryVoucherStore(get_config,
                                                      lambda: now)).store
        controller = PaymentController(
            store,
            DummyRedeemer(public_key),
            default_token_count=100,
            clock=Clock(),
        )

        self.assertThat(
            controller.redeem(voucher),
            succeeded(Always()),
        )

        # Sanity check.  It should be redeemed now.
        voucher_obj = controller.get_voucher(voucher)
        self.assertThat(
            voucher_obj.state.should_start_redemption(),
            Equals(False),
        )

        self.assertThat(
            controller.redeem(voucher),
            failed(AfterPreprocessing(
                lambda f: f.type,
                Equals(ValueError),
            ), ),
        )
コード例 #8
0
    def test_non_json_response(self, voucher, counter, num_tokens):
        """
        If the issuer responds with something that isn't JSON then the response is
        logged and the ``Deferred`` fires with a ``Failure`` wrapping
        ``UnexpectedResponse``.
        """
        issuer = UnexpectedResponseRedemption()
        treq = treq_for_loopback_ristretto(issuer)
        redeemer = RistrettoRedeemer(treq, NOWHERE)
        random_tokens = redeemer.random_tokens_for_voucher(
            voucher, counter, num_tokens)

        d = redeemer.redeemWithCounter(
            voucher,
            counter,
            random_tokens,
        )

        self.assertThat(
            d,
            failed(
                AfterPreprocessing(
                    lambda f: f.value,
                    Equals(
                        UnexpectedResponse(
                            INTERNAL_SERVER_ERROR,
                            b"Sorry, this server does not behave well.",
                        ), ),
                ), ),
        )
コード例 #9
0
 def test_redemption_denied_unpaid(self, voucher, counter, extra_tokens):
     """
     If the issuer declines to allow the voucher to be redeemed and gives a
     reason that the voucher has not been paid for, ``RistrettoRedeem``
     returns a ``Deferred`` that fires with a ``Failure`` wrapping
     ``Unpaid``.
     """
     num_tokens = counter + extra_tokens
     issuer = UnpaidRedemption()
     treq = treq_for_loopback_ristretto(issuer)
     redeemer = RistrettoRedeemer(treq, NOWHERE)
     random_tokens = redeemer.random_tokens_for_voucher(
         voucher, counter, num_tokens)
     d = redeemer.redeemWithCounter(
         voucher,
         counter,
         random_tokens,
     )
     self.assertThat(
         d,
         failed(AfterPreprocessing(
             lambda f: f.value,
             IsInstance(Unpaid),
         ), ),
     )
コード例 #10
0
    def test_bad_ristretto_redemption(self, voucher, counter, extra_tokens):
        """
        If the issuer returns a successful result with an invalid proof then
        ``RistrettoRedeemer.redeem`` returns a ``Deferred`` that fires with a
        ``Failure`` wrapping ``SecurityException``.
        """
        num_tokens = counter + extra_tokens
        signing_key = random_signing_key()
        issuer = RistrettoRedemption(signing_key)

        # Make it lie about the public key it is using.  This causes the proof
        # to be invalid since it proves the signature was made with a
        # different key than reported in the response.
        issuer.public_key = PublicKey.from_signing_key(random_signing_key())

        treq = treq_for_loopback_ristretto(issuer)
        redeemer = RistrettoRedeemer(treq, NOWHERE)
        random_tokens = redeemer.random_tokens_for_voucher(
            voucher, counter, num_tokens)
        d = redeemer.redeemWithCounter(
            voucher,
            counter,
            random_tokens,
        )
        self.addDetail(u"redeem Deferred", text_content(str(d)))
        self.assertThat(
            d,
            failed(
                AfterPreprocessing(
                    lambda f: f.value,
                    IsInstance(SecurityException),
                ), ),
        )
コード例 #11
0
ファイル: test_service.py プロジェクト: LuckySB/marathon-acme
    def test_sync_other_issue_failure(self):
        """
        When a sync is run and we try to issue a certificate for a domain but
        some non-ACME server error occurs, the sync should fail.
        """
        self.fake_marathon.add_app({
            'id':
            '/my-app_1',
            'labels': {
                'HAPROXY_GROUP': 'external',
                'MARATHON_ACME_0_DOMAIN': 'example.com'
            },
            'portDefinitions': [{
                'port': 9000,
                'protocol': 'tcp',
                'labels': {}
            }]
        })
        self.txacme_client.issuance_error = RuntimeError('Something bad')

        d = self.marathon_acme.sync()

        assert_that(
            d,
            failed(
                MatchesStructure(value=MatchesStructure(
                    subFailure=MatchesStructure(value=MatchesAll(
                        IsInstance(RuntimeError),
                        MatchesPredicate(str, 'Something bad')))))))
        # Nothing stored, nothing notified
        assert_that(self.cert_store.as_dict(), succeeded(Equals({})))
        assert_that(self.fake_marathon_lb.check_signalled_usr1(),
                    Equals(False))
コード例 #12
0
    def test_single_fail(self):
        """
        A single incoming message with a single file path.
        """
        sut = MetadataExtractor('exiftool', ('-some', '-arg'))

        error = RuntimeError('boom!')

        sut.peer = Mock(spec=ExiftoolProtocol)
        sut.peer.execute.return_value = defer.fail(error)

        insert = {
            'inserts': ['a'],
            'deletes': [],
            'data': {
                'a': {
                    'path': '/path/to/file.jpg',
                }
            }
        }
        send = Mock(spec=Scheduler.send)
        result = sut(insert, send)
        self.assertEquals(send.call_count, 0)
        sut.peer.execute.assert_called_once_with(
            b'-some', b'-arg', b'-j', b'-charset', b'exiftool=UTF-8',
            b'-charset', b'filename=UTF-8', b'/path/to/file.jpg')

        failure_matcher = matchers.AfterPreprocessing(
            lambda f: f.value, matchers.IsInstance(MetadataExtractorError))
        assert_that(result, twistedsupport.failed(failure_matcher))
コード例 #13
0
    def test_cap_not_okay(self, folder_name, collective_dircap, upload_dircap,
                          token):
        """
        If the response to a request for metadata about a capability for the magic
        folder does not receive an HTTP OK response, ``status`` fails with
        ``BadResponseCode``.
        """
        tempdir = FilePath(self.mktemp())
        node_directory = tempdir.child(u"node")
        node = self.useFixture(NodeDirectory(node_directory, token))

        node.create_magic_folder(
            folder_name,
            collective_dircap,
            upload_dircap,
            tempdir.child(u"folder"),
            60,
        )

        # A bare resource will result in 404s for all requests made.  That'll
        # do.
        treq = StubTreq(Resource())

        self.assertThat(
            status(folder_name, node_directory, treq),
            failed(
                AfterPreprocessing(
                    lambda f: f.value,
                    IsInstance(BadResponseCode),
                ), ),
        )
コード例 #14
0
    def test_timer_errors(self):
        """
        If the timed check fails (for example, because registration fails), the
        error should be caught and logged.
        """
        with AcmeFixture(client=FailingClient()) as fixture:
            # Registration is triggered with service starts.
            fixture.service.startService()
            latest_logs = flush_logged_errors()
            self.assertThat(latest_logs, HasLength(1))
            self.assertThat(
                str(latest_logs[0]), Contains('Failing at "register".'))

            # Forcing a check will trigger again the registration.
            self.assertThat(
                fixture.service._check_certs(),
                succeeded(Always()))

            latest_logs = flush_logged_errors()
            self.assertThat(latest_logs, HasLength(1))
            self.assertThat(
                str(latest_logs[0]), Contains('Failing at "register".'))

            # Manually stop the service to not stop it from the fixture
            # and trigger another failure.
            self.assertThat(
                fixture.service.stopService(),
                failed(AfterPreprocessing(
                    lambda f: f.value.args[0], Equals('Failing at "stop".'))))
            latest_logs = flush_logged_errors()
コード例 #15
0
    def test_add_writable_dmd(self, author, rw_collective_dircap,
                              rw_upload_dircap, personal_dmd):
        """
        Calling ``IParticipants.add`` with a read-write Personal DMD
        reports an error.
        """
        assume(rw_collective_dircap != rw_upload_dircap)
        assume(rw_collective_dircap != personal_dmd)
        assume(rw_upload_dircap != personal_dmd)
        # we are testing error-cases, so don't need a real client
        participants = participants_from_collective(
            rw_collective_dircap,
            rw_upload_dircap,
            tahoe_client=None,
        )

        self.assertThat(
            participants.add(
                create_local_author(author).to_remote_author(),
                personal_dmd,
            ),
            failed(
                AfterPreprocessing(
                    lambda f: str(f.value),
                    Equals(
                        "New participant Personal DMD must be read-only dircap"
                    ))))
コード例 #16
0
    def test_failed_node_connection(self, folder_name, collective_dircap,
                                    upload_dircap):
        """
        If an HTTP request to the Tahoe-LAFS node fails, ``status`` returns a
        ``Deferred`` that fails with that failure.
        """
        assume(collective_dircap != upload_dircap)

        tempdir = FilePath(self.mktemp())
        node_directory = tempdir.child(u"node")
        node = self.useFixture(NodeDirectory(node_directory))

        node.create_magic_folder(
            folder_name,
            collective_dircap,
            upload_dircap,
            tempdir.child(u"folder"),
            60,
        )

        exception = Exception("Made up failure")
        treq = HTTPClient(FailingAgent(Failure(exception)))
        self.assertThat(
            status(folder_name, node_directory, treq),
            failed(AfterPreprocessing(
                lambda f: f.value,
                Equals(exception),
            ), ),
        )
コード例 #17
0
    def test_fail_job(self):
        """
        Tests that scheduler is stopped whenever a port is failing.
        """
        port_out = object()
        port_in = Mock(spec=_port_callback, side_effect=RuntimeError('failed!'))
        self.flowmap[port_out] = port_in

        run_deferred = self.scheduler.run(self.clock)
        self.scheduler.send('some item', port_out)

        expected_message = 'Job failed on {:s} while processing {:s}'.format(
            str(port_in), 'some item')

        from testtools.twistedsupport._runtest import _NoTwistedLogObservers
        with _NoTwistedLogObservers():
            with twistedsupport.CaptureTwistedLogs() as twisted_logs:
                # Trigger queue run.
                self.clock.advance(self.epsilon)
                assert_that(twisted_logs.getDetails(), matchers.MatchesDict({
                    'twisted-log': matchers.AfterPreprocessing(
                        lambda log: log.as_text(), matchers.Contains(expected_message))
                }))

        port_in.assert_called_once_with('some item', self.scheduler.send)

        matcher = matchers.AfterPreprocessing(lambda f: f.value, matchers.IsInstance(RuntimeError))
        assert_that(run_deferred, twistedsupport.failed(matcher))
コード例 #18
0
    def test_single_fail(self):
        """
        A single incoming message with a single file path.
        """
        sut = MetadataExtractor('exiftool', ('-some', '-arg'))

        error = RuntimeError('boom!')

        sut.peer = Mock(spec=ExiftoolProtocol)
        sut.peer.execute.return_value = defer.fail(error)

        insert = {
            'inserts': ['a'],
            'deletes': [],
            'data': {
                'a': {
                    'path': '/path/to/file.jpg',
                }
            }
        }
        send = Mock(spec=Scheduler.send)
        result = sut(insert, send)
        self.assertEquals(send.call_count, 0)
        sut.peer.execute.assert_called_once_with(
            b'-some', b'-arg', b'-j', b'-charset', b'exiftool=UTF-8',
            b'-charset', b'filename=UTF-8', b'/path/to/file.jpg')

        failure_matcher = matchers.AfterPreprocessing(
            lambda f: f.value, matchers.IsInstance(MetadataExtractorError))
        assert_that(result, twistedsupport.failed(failure_matcher))
コード例 #19
0
    def test_json_content_incorrect_content_type(self):
        """
        When a request is made with the json_content callback and the
        content-type header is set to a value other than 'application/json' in
        the response headers then an error should be raised.
        """
        d = self.cleanup_d(self.client.request('GET', path='/hello'))
        d.addCallback(json_content)

        request = yield self.requests.get()
        self.assertThat(request, HasRequestProperties(
            method='GET', url=self.uri('/hello')))
        self.assertThat(request.requestHeaders,
                        HasHeader('accept', ['application/json']))

        request.setResponseCode(200)
        request.setHeader('Content-Type', 'application/octet-stream')
        request.write(json.dumps({}).encode('utf-8'))
        request.finish()

        yield wait0()
        self.assertThat(d, failed(WithErrorTypeAndMessage(
            HTTPError,
            'Expected header "Content-Type" to be "application/json" but '
            'found "application/octet-stream" instead')))
コード例 #20
0
    def test_sync_other_issue_failure(self):
        """
        When a sync is run and we try to issue a certificate for a domain but
        some non-ACME server error occurs, the sync should fail.
        """
        self.fake_marathon.add_app({
            'id': '/my-app_1',
            'labels': {
                'HAPROXY_GROUP': 'external',
                'MARATHON_ACME_0_DOMAIN': 'example.com'
            },
            'portDefinitions': [
                {'port': 9000, 'protocol': 'tcp', 'labels': {}}
            ]
        })
        self.txacme_client.issuance_error = RuntimeError('Something bad')

        marathon_acme = self.mk_marathon_acme()
        d = marathon_acme.sync()

        assert_that(d, failed(MatchesStructure(
            value=MatchesStructure(subFailure=MatchesStructure(
                value=MatchesAll(
                    IsInstance(RuntimeError),
                    MatchesPredicate(str, 'Something bad')
                )
            ))
        )))
        # Nothing stored, nothing notified
        assert_that(self.cert_store.as_dict(), succeeded(Equals({})))
        assert_that(self.fake_marathon_lb.check_signalled_usr1(),
                    Equals(False))
コード例 #21
0
    def test_get_events_non_200(self):
        """
        When a request is made to Marathon's event stream, and a non-200
        response code is returned, an error should be raised.
        """
        data = []
        d = self.cleanup_d(self.client.get_events({'test': data.append}))

        request = yield self.requests.get()
        self.assertThat(request, HasRequestProperties(
            method='GET', url=self.uri('/v2/events')))
        self.assertThat(request.requestHeaders,
                        HasHeader('accept', ['text/event-stream']))

        request.setResponseCode(202)
        request.setHeader('Content-Type', 'text/event-stream')

        json_data = {'hello': 'world'}
        request.write(b'event: test\n')
        request.write(b'data: %s\n' % (json.dumps(json_data).encode('utf-8'),))
        request.write(b'\n')

        yield wait0()
        self.assertThat(d, failed(WithErrorTypeAndMessage(
            HTTPError, 'Non-200 response code (202) for url: '
                       'http://localhost:8080/v2/events')))

        self.assertThat(data, Equals([]))

        request.finish()
        yield d
コード例 #22
0
    def test_json_content_missing_content_type(self):
        """
        When a request is made with the json_content callback and the
        content-type header is not set in the response headers then an error
        should be raised.
        """
        d = self.cleanup_d(self.client.request('GET', path='/hello'))
        d.addCallback(json_content)

        request = yield self.requests.get()
        self.assertThat(request, HasRequestProperties(
            method='GET', url=self.uri('/hello')))
        self.assertThat(request.requestHeaders,
                        HasHeader('accept', ['application/json']))

        request.setResponseCode(200)
        # Twisted will set the content type to "text/html" by default but this
        # can be disabled by setting the default content type to None:
        # https://twistedmatrix.com/documents/current/api/twisted.web.server.Request.html#defaultContentType
        request.defaultContentType = None
        request.write(json.dumps({}).encode('utf-8'))
        request.finish()

        yield wait0()
        self.assertThat(d, failed(WithErrorTypeAndMessage(
            HTTPError, 'Expected header "Content-Type" to be '
                       '"application/json" but header not found in response')))
コード例 #23
0
    def test_get_events_incorrect_content_type(self):
        """
        When a request is made to Marathon's event stream, and the content-type
        header value returned is not "text/event-stream", an error should be
        raised.
        """
        data = []
        d = self.cleanup_d(self.client.get_events({'test': data.append}))

        request = yield self.requests.get()
        self.assertThat(request, HasRequestProperties(
            method='GET', url=self.uri('/v2/events')))
        self.assertThat(request.requestHeaders,
                        HasHeader('accept', ['text/event-stream']))

        request.setResponseCode(200)
        request.setHeader('Content-Type', 'application/json')

        json_data = {'hello': 'world'}
        request.write(b'event: test\n')
        request.write(b'data: %s\n' % (json.dumps(json_data).encode('utf-8'),))
        request.write(b'\n')

        yield wait0()
        self.assertThat(d, failed(WithErrorTypeAndMessage(
            HTTPError,
            'Expected header "Content-Type" to be "text/event-stream" but '
            'found "application/json" instead')))

        self.assertThat(data, Equals([]))

        request.finish()
        yield d
コード例 #24
0
    def test_not_enough_tokens_for_retry(self, num_passes, extras):
        """
        When there are not enough tokens to successfully complete a retry with the
        required number of passes, ``call_with_passes`` marks all passes
        reported as invalid during its efforts as such and resets all other
        passes it acquired.
        """
        passes = pass_factory(integer_passes(num_passes + extras))
        rejected = []
        accepted = []

        def reject_half_passes(group):
            num = len(group.passes)
            # Floor division will always short-change valid here, even for a
            # group size of 1.  Therefore there will always be some passes
            # marked as invalid.
            accept_indexes = range(num // 2)
            reject_indexes = range(num // 2, num)
            # Only keep this iteration's accepted passes.  We'll want to see
            # that the final iteration's passes are all returned.  Passes from
            # earlier iterations don't matter.
            accepted[:] = list(group.passes[i] for i in accept_indexes)
            # On the other hand, keep *all* rejected passes.  They should all
            # be marked as invalid and we want to make sure that's the case,
            # no matter which iteration rejected them.
            rejected.extend(group.passes[i] for i in reject_indexes)
            _ValidationResult(
                valid=accept_indexes,
                signature_check_failed=reject_indexes,
            ).raise_for(num)

        self.assertThat(
            call_with_passes(
                # Since half of every group is rejected, we'll eventually run
                # out of passes no matter how many we start with.
                reject_half_passes,
                num_passes,
                partial(passes.get, u"message"),
            ),
            failed(
                AfterPreprocessing(
                    lambda f: f.value,
                    IsInstance(NotEnoughTokens),
                ), ),
        )
        self.assertThat(
            passes,
            MatchesStructure(
                # Whatever is left in the group when we run out of tokens must
                # be returned.
                returned=Equals(accepted),
                in_use=HasLength(0),
                invalid=AfterPreprocessing(
                    lambda invalid: invalid.keys(),
                    Equals(rejected),
                ),
                spent=HasLength(0),
                issued=Equals(set(accepted + rejected)),
            ),
        )
コード例 #25
0
    def test_version(self):
        """
        Version is displayed with --version
        """
        stdout = StringIO()
        stderr = StringIO()

        self.assertThat(
            dispatch_magic_folder_api_command(
                ["--version"],
                stdout=stdout,
                stderr=stderr,
                client=None,
            ),
            failed(
                AfterPreprocessing(
                    lambda f: isinstance(f.value, SystemExit) and f.value.code,
                    Equals(0)
                )
            )
        )
        from .. import __version__
        self.assertThat(
            stdout.getvalue().strip(),
            Equals("magic-folder-api version {}".format(__version__))
        )
コード例 #26
0
    def test_pass_through_too_few_passes(self, num_passes):
        """
        ``call_with_passes`` lets ``MorePassesRequired`` propagate through it if
        no passes have been marked as invalid.  This happens if all passes
        given were valid but too fewer were given.
        """
        passes = pass_factory()

        def reject_passes(passes):
            _ValidationResult(
                valid=range(len(passes)),
                signature_check_failed=[],
            ).raise_for(len(passes) + 1)

        self.assertThat(
            call_with_passes(
                reject_passes,
                num_passes,
                passes.get,
            ),
            failed(
                AfterPreprocessing(
                    lambda f: f.value,
                    Equals(
                        MorePassesRequired(
                            valid_count=num_passes,
                            required_count=num_passes + 1,
                            signature_check_failed=[],
                        ), ),
                ), ),
        )
コード例 #27
0
 def test_async_error_propagates(self):
     """
     If an unhandled asynchronous error occurs in an interceptor it
     propogates along the execution.
     """
     interceptors = [tracer('a'), tracer('b'), thrower('c'), tracer('d')]
     self.assertThat(execute(empty_context, interceptors),
                     failed(After(lambda f: f.type, Is(TracingError))))
コード例 #28
0
 def test_argument_serialization_failure(self):
     """
     ``LocalRemote.callRemote`` returns a ``Deferred`` that fires with a
     failure if an argument cannot be serialized.
     """
     ref = LocalRemote(DummyReferenceable(IHasSchema))
     self.assertThat(
         ref.callRemote("whatever_method", BrokenCopyable()),
         failed(Always()),
     )
コード例 #29
0
ファイル: test_service.py プロジェクト: LuckySB/marathon-acme
    def test_sync_failure(self):
        """
        When a sync is run and something fails, the failure is propagated to
        the sync's deferred.
        """
        self.marathon_acme.marathon_client = MarathonClient(
            'http://localhost:8080', client=failing_client)

        d = self.marathon_acme.sync()
        assert_that(d,
                    failed(MatchesStructure(value=IsInstance(RuntimeError))))
コード例 #30
0
 def test_cancel_while_waiting_for_uptime(self):
     """
     If the 'ready' deferred gets cancelled while still waiting for the
     minumum uptime, a proper message is emitted.
     """
     self.protocol.makeConnection(self.process)
     self.protocol.ready.cancel()
     self.assertIn("minimum uptime not yet elapsed", self.logger.output)
     self.assertThat(
         self.protocol.ready,
         failed(MatchesStructure(value=IsInstance(CancelledError))))
コード例 #31
0
ファイル: test_service.py プロジェクト: zhoukunpeng504/txacme
 def test_starting_stopping_cancellation(self):
     """
     Test the starting and stopping behaviour.
     """
     with AcmeFixture(client=HangingClient()) as fixture:
         d = fixture.service.when_certs_valid()
         self.assertThat(d, has_no_result())
         fixture.service.startService()
         self.assertThat(d, has_no_result())
         fixture.service.stopService()
         self.assertThat(d, failed(Always()))
コード例 #32
0
 def test_download_immutable_wrong_kind(self, cap):
     """
     ``download_capability`` returns a ``Deferred`` that fails when a
     directory-capability is downloaded
     """
     self.assertThat(
         self.tahoe_client.download_file(cap),
         failed(
             AfterPreprocessing(
                 lambda failure: str(failure.value),
                 Equals("{} is not a file capability".format(cap)))))
コード例 #33
0
ファイル: test_service.py プロジェクト: habnabit/txacme
 def test_starting_stopping_cancellation(self):
     """
     Test the starting and stopping behaviour.
     """
     with AcmeFixture(client=HangingClient()) as fixture:
         d = fixture.service.when_certs_valid()
         self.assertThat(d, has_no_result())
         fixture.service.startService()
         self.assertThat(d, has_no_result())
         fixture.service.stopService()
         self.assertThat(d, failed(Always()))
コード例 #34
0
 def test_cancel_ready(self):
     """
     If the `ready` deferred gets cancelled, the protocol will stop doing
     anything related to waiting for the service to be ready.
     """
     self.protocol.makeConnection(self.process)
     self.protocol.ready.cancel()
     self.assertThat(
         self.protocol.ready,
         failed(MatchesStructure(value=IsInstance(CancelledError))))
     self.assertEqual(0, len(self.reactor.getDelayedCalls()))
コード例 #35
0
    def test_sync_failure(self):
        """
        When a sync is run and something fails, the failure is propagated to
        the sync's deferred.
        """
        marathon_acme = self.mk_marathon_acme()
        marathon_acme.marathon_client = MarathonClient(
            'http://localhost:8080', client=failing_client)

        d = marathon_acme.sync()
        assert_that(d, failed(MatchesStructure(
            value=IsInstance(RuntimeError))))
コード例 #36
0
    def test_failure_during_request(self):
        """
        When a failure occurs during a request, the exception is propagated
        to the request's deferred.
        """
        client = self.get_client(failing_client)

        d = client.request('GET', path='/hello')
        self.assertThat(d, failed(MatchesStructure(
            value=IsInstance(RuntimeError))))

        flush_logged_errors(RuntimeError)
コード例 #37
0
    def test_failure_during_request(self):
        """
        When a failure occurs during a request, the exception is propagated
        to the request's deferred.
        """
        client = self.get_client(failing_client)

        d = client.request('GET', path='/hello')
        self.assertThat(d, failed(MatchesStructure(
            value=IsInstance(RuntimeError))))

        flush_logged_errors(RuntimeError)
コード例 #38
0
 def _api_error_test(self, operation):
     """
     Assert that ``operation`` fails with ``TahoeAPIError``.
     """
     self.assertThat(
         operation(),
         failed(
             AfterPreprocessing(
                 lambda failure: failure.value,
                 IsInstance(TahoeAPIError),
             ), ),
     )
コード例 #39
0
    def test_process_dies_shortly_after_fork(self):
        """
        If the service process exists right after having been spawned (for
        example the executable was not found), the 'ready' Deferred fires
        with an errback.
        """
        self.protocol.makeConnection(self.process)

        error = ProcessTerminated(exitCode=1, signal=None)
        self.protocol.processExited(Failure(error))
        self.assertThat(self.protocol.ready,
                        failed(MatchesStructure(value=Is(error))))
コード例 #40
0
    def test_snapshot_bad_metadata(self, raw_metadata):
        """
        Test error-handling cases when de-serializing a snapshot. If the
        snapshot version is missing or wrong we should error.
        """

        # arbitrary (but valid) content-cap
        contents = []
        content_cap_d = self.tahoe_client.create_immutable(b"0" * 256)
        content_cap_d.addCallback(contents.append)
        self.assertThat(content_cap_d, succeeded(Always()))
        content_cap = contents[0]

        # invalid metadata cap (we use Hypothesis to give us two
        # definitely-invalid versions)
        metadata_caps = []

        d = self.tahoe_client.create_immutable(
            json.dumps(raw_metadata).encode("utf8"))
        d.addCallback(metadata_caps.append)
        self.assertThat(d, succeeded(Always()))

        # create a Snapshot using the wrong metadata
        raw_snapshot_data = {
            u"content":
            format_filenode(content_cap),
            u"metadata":
            format_filenode(
                metadata_caps[0],
                {
                    u"magic_folder": {
                        u"author_signature": u"not valid",
                    },
                },
            ),
        }

        snapshot_cap = []
        d = self.tahoe_client.create_immutable_directory(raw_snapshot_data)
        d.addCallback(snapshot_cap.append)
        self.assertThat(d, succeeded(Always()))

        # now when we read back the snapshot with incorrect metadata,
        # it should fail
        snapshot_d = create_snapshot_from_capability(snapshot_cap[0],
                                                     self.tahoe_client)

        self.assertThat(
            snapshot_d,
            failed(
                MatchesStructure(value=AfterPreprocessing(
                    str, Contains("snapshot_version")), )))
コード例 #41
0
    def test_dispatch_with_fails(self):
        dispatcher = EventDispatcher()

        test_callback_prio_0_cb_0 = Mock()
        test_callback_prio_0_cb_1 = Mock(side_effect=RuntimeError('boom!'))
        test_callback_prio_1_cb_0 = Mock()

        dispatcher.add_listener(TestEvent, 0, test_callback_prio_0_cb_0)
        dispatcher.add_listener(TestEvent, 0, test_callback_prio_0_cb_1)
        dispatcher.add_listener(TestEvent, 1, test_callback_prio_1_cb_0)

        event = TestEvent()
        d = dispatcher.dispatch(event)

        matcher = matchers.AfterPreprocessing(lambda f: f.value, matchers.IsInstance(HandlerError))
        assert_that(d, twistedsupport.failed(matcher))
コード例 #42
0
 def test_raise_exception(self, logger):
     """
     An exception raised by the decorated function is passed through.
     """
     class Result(Exception):
         pass
     @log_call_deferred(action_type=u"the-action")
     def f():
         raise Result()
     self.assertThat(
         f(),
         failed(
             AfterPreprocessing(
                 lambda f: f.value,
                 IsInstance(Result),
             ),
         ),
     )
コード例 #43
0
ファイル: test_client.py プロジェクト: fusionapp/txdocumint
 def test_malformed_error(self):
     """
     Documint errors that do not have a JSON content type raise
     `MalformedDocumintError`.
     """
     def _response_for(method, url, params, headers, data):
         return 400, {}, b'an error'
     resource = StringStubbingResource(_response_for)
     treq = StubTreq(resource)
     request = documint_request_factory(treq.request)
     self.assertThat(
         request(b'GET', b'http://example.com/malformed_error'),
         failed(
             AfterPreprocessing(
                 lambda f: f.value,
                 MatchesAll(
                     IsInstance(MalformedDocumintError),
                     MatchesStructure(data=Equals(b'an error'))))))
コード例 #44
0
    def test_store_unexpected_response(self):
        """
        When the wrapped certificate store returns something other than None,
        an error should be raised as this is unexpected.
        """
        class BrokenCertificateStore(object):
            def store(self, server_name, pem_objects):
                # Return something other than None
                return succeed('foo')

        mlb_store = MlbCertificateStore(BrokenCertificateStore(), self.client)

        d = mlb_store.store('example.com', EXAMPLE_PEM_OBJECTS)

        assert_that(d, failed(WithErrorTypeAndMessage(
            RuntimeError,
            "Wrapped certificate store returned something non-None. Don't "
            "know what to do with 'foo'.")))
コード例 #45
0
    def test_get_json_field_error(self):
        """
        When get_json_field is used to make a request but the response code
        indicates an error, an HTTPError should be raised.
        """
        d = self.cleanup_d(
            self.client.get_json_field('field-key', path='/my-path'))

        request = yield self.requests.get()
        self.assertThat(request, HasRequestProperties(
            method='GET', url=self.uri('/my-path')))

        request.setResponseCode(404)
        request.write(b'Not found\n')
        request.finish()

        yield wait0()
        self.assertThat(d, failed(WithErrorTypeAndMessage(
            HTTPError, '404 Client Error for url: %s' % self.uri('/my-path'))))
コード例 #46
0
    def test_sync_acme_server_failure_unacceptable(self):
        """
        When a sync is run and we try to issue a certificate for a domain but
        the ACME server returns an error, if that error is of an unacceptable
        type then a failure should be returned.
        """
        self.fake_marathon.add_app({
            'id': '/my-app_1',
            'labels': {
                'HAPROXY_GROUP': 'external',
                'MARATHON_ACME_0_DOMAIN': 'example.com'
            },
            'portDefinitions': [
                {'port': 9000, 'protocol': 'tcp', 'labels': {}}
            ]
        })
        acme_error = acme_Error(typ='urn:acme:error:badCSR', detail='bar')
        # Server error takes an ACME error and a treq response...but we don't
        # have a response
        self.txacme_client.issuance_error = txacme_ServerError(
            acme_error, None)

        marathon_acme = self.mk_marathon_acme()
        d = marathon_acme.sync()

        # Oh god
        assert_that(d, failed(MatchesStructure(
            value=MatchesStructure(subFailure=MatchesStructure(
                value=MatchesAll(IsInstance(txacme_ServerError),
                    MatchesStructure(message=MatchesAll(
                        IsInstance(acme_Error),
                        MatchesStructure(
                            typ=Equals('urn:acme:error:badCSR'),
                            detail=Equals('bar')
                        )
                    ))
                )
            ))
        )))
        # Nothing stored, nothing notified
        assert_that(self.cert_store.as_dict(), succeeded(Equals({})))
        assert_that(self.fake_marathon_lb.check_signalled_usr1(),
                    Equals(False))
コード例 #47
0
    def test_server_error_response(self):
        """
        When a request is made and the raise_for_status callback is added and a
        5xx response code is returned, a HTTPError should be raised to indicate
        a server error.
        """
        d = self.cleanup_d(self.client.request('GET', path='/hello'))
        d.addCallback(raise_for_status)

        request = yield self.requests.get()
        self.assertThat(request, HasRequestProperties(
            method='GET', url=self.uri('/hello')))

        request.setResponseCode(502)
        request.write(b'Bad gateway\n')
        request.finish()

        yield wait0()
        self.assertThat(d, failed(WithErrorTypeAndMessage(
            HTTPError, '502 Server Error for url: %s' % self.uri('/hello'))))
コード例 #48
0
    def test_request_fallback_all_failed(self):
        """
        When we make a request and there are multiple Marathon endpoints
        specified, and all the endpoints fail, the last failure should be
        returned.
        """
        agent = PerLocationAgent()
        agent.add_agent(b'localhost:8080', FailingAgent(RuntimeError('8080')))
        agent.add_agent(b'localhost:9090', FailingAgent(RuntimeError('9090')))
        client = MarathonClient(
            ['http://localhost:8080', 'http://localhost:9090'],
            client=treq_HTTPClient(agent))

        d = self.cleanup_d(client.request('GET', path='/my-path'))

        yield wait0()
        self.assertThat(d, failed(WithErrorTypeAndMessage(
            RuntimeError, '9090')))

        flush_logged_errors(RuntimeError)
コード例 #49
0
ファイル: test_client.py プロジェクト: fusionapp/txdocumint
 def test_not_json_error(self):
     """
     Documint errors that have a JSON content type but do not contain valid
     JSON raise `MalformedDocumintError`.
     """
     def _response_for(method, url, params, headers, data):
         return (400,
                 {b'Content-Type': b'application/json'},
                 b'hello world')
     resource = StringStubbingResource(_response_for)
     treq = StubTreq(resource)
     request = documint_request_factory(treq.request)
     self.assertThat(
         request(b'GET', b'http://example.com/not_json_error'),
         failed(
             AfterPreprocessing(
                 lambda f: f.value,
                 MatchesAll(
                     IsInstance(MalformedDocumintError),
                     MatchesStructure(data=Equals(b'hello world'))))))
コード例 #50
0
    def test_get_json_field_missing(self):
        """
        When get_json_field is used to make a request, the response is
        deserialized from JSON and if the specified field is missing, an error
        is raised.
        """
        d = self.cleanup_d(
            self.client.get_json_field('field-key', path='/my-path'))

        request = yield self.requests.get()
        self.assertThat(request, HasRequestProperties(
            method='GET', url=self.uri('/my-path')))

        json_response(request, {'other-field-key': 'do-not-care'})

        yield wait0()
        self.assertThat(d, failed(WithErrorTypeAndMessage(
            KeyError,
            '\'Unable to get value for "field-key" from Marathon response: '
            '"{"other-field-key": "do-not-care"}"\''
        )))
コード例 #51
0
    def test_get_json_field_incorrect_content_type(self):
        """
        When get_json_field is used to make a request and the content-type
        header is set to a value other than 'application/json' in the response
        headers then an error should be raised.
        """
        d = self.cleanup_d(
            self.client.get_json_field('field-key', path='/my-path'))

        request = yield self.requests.get()
        self.assertThat(request, HasRequestProperties(
            method='GET', url=self.uri('/my-path')))

        request.setResponseCode(200)
        request.setHeader('Content-Type', 'application/octet-stream')
        request.write(json.dumps({}).encode('utf-8'))
        request.finish()

        yield wait0()
        self.assertThat(d, failed(WithErrorTypeAndMessage(
            HTTPError,
            'Expected header "Content-Type" to be "application/json" but '
            'found "application/octet-stream" instead')))
コード例 #52
0
ファイル: test_client.py プロジェクト: fusionapp/txdocumint
    def test_error(self):
        """
        Documint errors are parsed into a structured exception.
        """
        def _response_for(method, url, params, headers, data):
            return (400,
                    {b'Content-Type': b'application/json'},
                    json.dumps({u'causes': [
                        {u'type': u'foo',
                         u'reason': 42,
                         u'description': u'nope'},
                        {u'type': u'bar',
                         u'reason': 42,
                         u'description': None},
                        {u'type': u'baz',
                         u'reason': None,
                         u'description': None}]}))
        resource = StringStubbingResource(_response_for)
        treq = StubTreq(resource)
        request = documint_request_factory(treq.request)

        def cause(t, r=None, d=None):
            return MatchesStructure(type=Equals(t),
                                    reason=Equals(r),
                                    description=Equals(d))
        self.assertThat(
            request(b'GET', b'http://example.com/error'),
            failed(
                AfterPreprocessing(
                    lambda f: f.value,
                    MatchesAll(
                        IsInstance(DocumintError),
                        MatchesStructure(
                            causes=MatchesListwise([
                                cause(u'foo', 42, u'nope'),
                                cause(u'bar', 42),
                                cause(u'baz')]))))))
コード例 #53
0
    def test_request_failure(self):
        """
        When the requests to all the marathon-lb instances have a bad status
        code then an error should be raised.
        """
        d = self.cleanup_d(self.client.request('GET', path='/my-path'))

        for lb in ['lb1', 'lb2']:
            request = yield self.requests.get()
            self.assertThat(request, HasRequestProperties(
                method='GET', url='http://%s:9090/my-path' % (lb,)))

            request.setResponseCode(500)
            request.setHeader('content-type', 'text/plain')
            request.write(b'Internal Server Error')
            request.finish()

        yield wait0()
        self.assertThat(d, failed(WithErrorTypeAndMessage(
            RuntimeError,
            'Failed to make a request to all marathon-lb instances'
        )))

        flush_logged_errors(HTTPError)
コード例 #54
0
def fires_with_timeout():
    """Assert that a notification request fails with a Timeout"""
    return failed(
         AfterPreprocessing(lambda f: f.value, IsInstance(Timeout)))
コード例 #55
0
def fires_with_not_found():
    """Assert that a notification request fails with a NotFound"""
    return failed(
         AfterPreprocessing(lambda f: f.value, IsInstance(NotFound)))
コード例 #56
0
def fires_with_connection_closed():
    """Assert that a notification request fails with a NotFound"""
    return failed(
         AfterPreprocessing(lambda f: f.value, IsInstance(ConnectionClosed)))