def test_cancellation(self, server_name): """ Cancelling the deferred returned by ``issue_cert`` cancels the actual issuing process. """ with AcmeFixture() as fixture: fixture.service.startService() self.assertThat( fixture.cert_store.as_dict(), succeeded( Not(Contains(server_name)))) fixture.controller.pause() d1 = fixture.service.issue_cert(server_name) self.assertThat(d1, has_no_result()) d2 = fixture.service.issue_cert(server_name) self.assertThat(d2, has_no_result()) self.assertThat(fixture.controller.count(), Equals(1)) d2.cancel() fixture.controller.resume() self.assertThat(d1, failed_with(IsInstance(CancelledError))) self.assertThat(d2, failed_with(IsInstance(CancelledError))) self.assertThat( fixture.cert_store.as_dict(), succeeded( Not(Contains(server_name))))
def test_issue_concurrently(self, server_name): """ Invoking ``issue_cert`` multiple times concurrently for the same name will not start multiple issuing processes, only wait for the first process to complete. """ with AcmeFixture() as fixture: fixture.service.startService() self.assertThat(fixture.cert_store.as_dict(), succeeded(Not(Contains(server_name)))) fixture.controller.pause() d1 = fixture.service.issue_cert(server_name) self.assertThat(d1, has_no_result()) d2 = fixture.service.issue_cert(server_name) self.assertThat(d2, has_no_result()) self.assertThat(fixture.controller.count(), Equals(1)) fixture.controller.resume() self.assertThat(d1, succeeded(Always())) self.assertThat(d2, succeeded(Always())) self.assertThat( fixture.cert_store.as_dict(), succeeded(MatchesDict({server_name: Not(Equals([]))})))
def test_issue_concurrently(self, server_name): """ Invoking ``issue_cert`` multiple times concurrently for the same name will not start multiple issuing processes, only wait for the first process to complete. """ with AcmeFixture() as fixture: fixture.service.startService() self.assertThat( fixture.cert_store.as_dict(), succeeded( Not(Contains(server_name)))) fixture.controller.pause() d1 = fixture.service.issue_cert(server_name) self.assertThat(d1, has_no_result()) d2 = fixture.service.issue_cert(server_name) self.assertThat(d2, has_no_result()) self.assertThat(fixture.controller.count(), Equals(1)) fixture.controller.resume() self.assertThat(d1, succeeded(Always())) self.assertThat(d2, succeeded(Always())) self.assertThat( fixture.cert_store.as_dict(), succeeded( MatchesDict({server_name: Not(Equals([]))})))
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()))
def test_not_done_yet(self): """ If the decorated method returns ``NOT_DONE_YET`` then the resource is responsible for finishing the request itself. """ the_request = [] class R(Resource): @render_exception def render(self, request): the_request.append(request) return NOT_DONE_YET d = render(R(), {}) self.assertThat( d, has_no_result(), ) the_request[0].write(b"some content") the_request[0].finish() self.assertThat( d, succeeded( Equals(b"some content"), ), )
def test_run_job(self): """ Tests send() and ensure that the job-event is fired. """ job_handler = Mock() self.dispatcher.add_listener(JobEvent, 0, job_handler) port_out = object() port_in = Mock(spec=_port_callback) self.flowmap[port_out] = port_in self.scheduler.run(self.clock) self.scheduler.send('some item', port_out) expected_job = Job(port_in, 'some item', self.scheduler.send, port_out) self.assertEquals(job_handler.call_count, 1) assert_that(job_handler.call_args, MatchesInvocation( MatchesEvent(JobEvent, scheduler=matchers.Equals(self.scheduler), job=matchers.Equals(expected_job), completed=twistedsupport.has_no_result()) )) self.assertEquals(port_in.call_count, 0) self.assertEquals(len(list(self.scheduler.pending)), 1) # Trigger queue run. self.clock.advance(self.epsilon) port_in.assert_called_once_with('some item', self.scheduler.send) self.assertEquals(len(list(self.scheduler.pending)), 0)
def test_expected_output(self): """ If some expected output is required, the 'ready' deferred fires only when such output has been received. """ self.protocol.expectedOutput = "hello" self.protocol.makeConnection(self.process) self.reactor.advance(self.protocol.minUptime) self.assertThat(self.protocol.ready, has_no_result()) self.protocol.outReceived(b"hello world!\n") self.assertThat(self.protocol.ready, succeeded(Is(None))) self.assertIn("Service process emitted 'hello'", self.logger.output)
def first_try(): controller = PaymentController( store, # It will let `before_restart` attempts succeed before hanging. IndexedRedeemer([DummyRedeemer(public_key)] * before_restart + [NonRedeemer()] * after_restart, ), default_token_count=num_tokens, num_redemption_groups=num_redemption_groups, clock=Clock(), ) self.assertThat( controller.redeem(voucher), has_no_result(), )
def test_expected_port(self): """ If some expected port is required, the 'ready' deferred fires only when such port has been opened. """ self.protocol.expectedPort = 1234 self.protocol.makeConnection(self.process) self.reactor.advance(self.protocol.minUptime) self.assertThat(self.protocol.ready, has_no_result()) factory = self.reactor.tcpClients[0][2] factory.buildProtocol(None).connectionMade() self.assertThat(self.protocol.ready, succeeded(Is(None))) self.assertIn("Service opened port 1234", self.logger.output)
def test_deferred(self): """ Any interceptor stage can return a `Deferred` and the execution will wait for it to resolve (or fail) before continuing. """ clock = Clock() interceptors = [tracer('a'), deferrer('b', clock, 1), tracer('c')] d = execute(empty_context, interceptors) self.assertThat(d, has_no_result()) clock.advance(1) self.assertThat( d, succeeded( Equals({ TRACE: v(('enter', 'a'), ('enter', 'b'), ('enter', 'c'), ('leave', 'c'), ('leave', 'b'), ('leave', 'a')) })))
def test_wait_for_completion(self, author, folder_name, path_in_folder, some_content): """ A **POST** request to **/v1/magic-folder/:folder-name/snapshot** does not receive a response before the snapshot has been created in the local database. """ local_path = FilePath(self.mktemp()) local_path.makedirs() some_file = local_path.preauthChild(path_in_folder).asBytesMode( "utf-8") some_file.parent().makedirs(ignoreExistingDirectory=True) some_file.setContent(some_content) treq = treq_for_folders( object(), FilePath(self.mktemp()), AUTH_TOKEN, { folder_name: magic_folder_config(author, FilePath(self.mktemp()), local_path) }, # The interesting behavior of this test hinges on this flag. We # decline to start the folder services here. Therefore, no local # snapshots will ever be created. This lets us observe the # request in a state where it is waiting to receive its response. # This demonstrates that the response is not delivered before the # local snapshot is created. See test_create_snapshot for the # alternative case. start_folder_services=False, ) self.assertThat( authorized_request( treq, AUTH_TOKEN, b"POST", self.url.child(folder_name, "snapshot").set(u"path", path_in_folder), ), has_no_result(), )
def test_expected_port_probe_failed(self): """ If probing for the expected port fails, the probe will be retried. """ self.protocol.expectedPort = 1234 self.protocol.makeConnection(self.process) self.reactor.advance(self.protocol.minUptime) self.assertThat(self.protocol.ready, has_no_result()) factory = self.reactor.tcpClients[0][2] factory.clientConnectionFailed(None, ConnectionRefusedError()) self.assertIn("Service port probe failed", self.logger.output) self.reactor.advance(0.1) factory = self.reactor.tcpClients[1][2] factory.buildProtocol(None).connectionMade() self.assertThat(self.protocol.ready, succeeded(Is(None))) self.assertIn("Service opened port 1234", self.logger.output)
def test_process_dies_while_waiting_expected_output(self): """ If the service process exists while waiting for the expected output, the 'ready' Deferred fires with an errback. """ self.protocol.expectedOutput = "hello" self.protocol.makeConnection(self.process) self.reactor.advance(self.protocol.minUptime) error = ProcessTerminated(exitCode=1, signal=None) self.protocol.processExited(Failure(error)) self.assertThat(self.protocol.ready, failed(MatchesStructure(value=Is(error)))) # Further input received on the file descriptor will be discarded self.protocol.ready = Deferred() # pretend that we didn't get fired self.protocol.outReceived(b"hello world!\n") self.assertThat(self.protocol.ready, has_no_result())
def test_when_certs_valid_certs_expired(self, fixture): """ The deferred returned by ``when_certs_valid`` only fires once all panicing and expired certs have been renewed. """ with fixture: service = fixture.service d = service.when_certs_valid() self.assertThat(d, has_no_result()) service.startService() self.assertThat(d, succeeded(Is(None))) max_expiry = fixture.now + service.panic_interval self.assertThat( fixture.cert_store.as_dict(), succeeded(AfterPreprocessing( methodcaller('values'), AllMatch(AllMatch( _match_certificate( MatchesStructure( not_valid_after=GreaterThan(max_expiry)))))))) self.assertThat(fixture.responder.challenges, HasLength(0))
def test_not_redeemed_while_redeeming(self, get_config, now, voucher): """ A ``Voucher`` is not marked redeemed before ``IRedeemer.redeem`` completes. """ store = self.useFixture(TemporaryVoucherStore(get_config, lambda: now)).store controller = PaymentController( store, NonRedeemer(), default_token_count=100, ) self.assertThat( controller.redeem(voucher), has_no_result(), ) persisted_voucher = store.get(voucher) self.assertThat( persisted_voucher.state, Equals(model_Pending(counter=0)), )
def test_redeeming(self, get_config, now, voucher, num_successes, public_key): """ A ``Voucher`` is marked redeeming while ``IRedeemer.redeem`` is actively working on redeeming it with a counter value that reflects the number of successful partial redemptions so far completed. """ # The voucher counter can be zero (no tries yet succeeded). We want # at least *one* run through so we'll bump this up to be sure we get # that. counter = num_successes + 1 redeemer = IndexedRedeemer( [DummyRedeemer(public_key)] * num_successes + [NonRedeemer()], ) store = self.useFixture(TemporaryVoucherStore(get_config, lambda: now)).store controller = PaymentController( store, redeemer, # This will give us one ZKAP per attempt. default_token_count=counter, # Require more success than we're going to get so it doesn't # finish. num_redemption_groups=counter, clock=Clock(), ) self.assertThat( controller.redeem(voucher), has_no_result(), ) controller_voucher = controller.get_voucher(voucher) self.assertThat( controller_voucher.state, Equals(model_Redeeming( started=now, counter=num_successes, )), )
def test_yield_unfired_deferred(self, logger): waiting = Deferred() @inline_callbacks def g(): Message.log(message_type=u"a") yield waiting Message.log(message_type=u"b") with start_action(action_type=u"the-action"): d = g() self.assertThat(waiting, has_no_result()) waiting.callback(None) self.assertThat(d, succeeded(Is(None))) assert_expected_action_tree( self, logger, u"the-action", [ u"a", u"yielded", u"b", ], )
def test_run_scheduler(self): """ Tests run(), stop() and join() and ensures that appropriate events are fired. """ job_handler = Mock() attach_handler = Mock() start_handler = Mock() join_handler = Mock() detach_handler = Mock() self.dispatcher.add_listener(JobEvent, 0, job_handler) self.dispatcher.add_listener(AttachEvent, 0, attach_handler) self.dispatcher.add_listener(DetachEvent, 0, detach_handler) # Start the scheduler. run_deferred = self.scheduler.run(self.clock) assert_that(run_deferred, twistedsupport.has_no_result()) self.assertEquals(job_handler.call_count, 0) attach_handler.assert_called_once_with(AttachEvent(scheduler=self.scheduler, reactor=self.clock)) self.assertEquals(join_handler.call_count, 0) self.assertEquals(detach_handler.call_count, 0) job_handler.reset_mock() attach_handler.reset_mock() start_handler.reset_mock() join_handler.reset_mock() detach_handler.reset_mock() # Turn a bit on the clock. self.clock.advance(self.epsilon) assert_that(run_deferred, twistedsupport.has_no_result()) self.assertEquals(job_handler.call_count, 0) self.assertEquals(attach_handler.call_count, 0) self.assertEquals(start_handler.call_count, 0) self.assertEquals(join_handler.call_count, 0) self.assertEquals(detach_handler.call_count, 0) job_handler.reset_mock() attach_handler.reset_mock() start_handler.reset_mock() join_handler.reset_mock() detach_handler.reset_mock() # Stop the scheduler. self.scheduler.stop('some reason') assert_that(run_deferred, twistedsupport.succeeded(matchers.Equals('some reason'))) self.assertEquals(job_handler.call_count, 0) self.assertEquals(attach_handler.call_count, 0) self.assertEquals(start_handler.call_count, 0) self.assertEquals(join_handler.call_count, 0) self.assertEquals(detach_handler.call_count, 0) job_handler.reset_mock() attach_handler.reset_mock() start_handler.reset_mock() join_handler.reset_mock() detach_handler.reset_mock() # Stop the queue and join processes. join_deferred = self.scheduler.join() self.clock.advance(self.epsilon) assert_that(join_deferred, twistedsupport.succeeded(matchers.Always())) self.assertEquals(job_handler.call_count, 0) self.assertEquals(attach_handler.call_count, 0) self.assertEquals(start_handler.call_count, 0) detach_handler.assert_called_once_with(DetachEvent(scheduler=self.scheduler))