def test_remove_context_error(): class FailingContext: def __init__(self): self.count = 1 self.closed = False def close(self): if self.count > 0: self.count -= 1 raise RuntimeError("Cannot close yet") self.closed = True ticket = Ticket(testutil.create_ticket(ops=["read"])) ticket.add_context(1, FailingContext()) ticket.cancel(timeout=0) # If closing a context fails, keep it. The ticket cannot be removed until # this context is removed successfully. with pytest.raises(RuntimeError): ticket.remove_context(1) info = ticket.info() assert info["connections"] == 1 # Calling again will close and remove the context successfully. ticket.remove_context(1) info = ticket.info() assert info["connections"] == 0
def test_cancel_wait(): ticket = Ticket(testutil.create_ticket(ops=["read"])) # Add connections using this ticket. connections = [] for i in range(4): ctx = Context() ticket.add_context(i, ctx) connections.append(ctx) def close_connections(): time.sleep(0.1) for i in range(4): ticket.remove_context(i) info = ticket.info() assert not info["canceled"] assert info["connections"] == 4 t = util.start_thread(close_connections) try: ticket.cancel(timeout=10) # After the ticket was canceled, number of connections must be zero. info = ticket.info() assert info["connections"] == 0 # And all contexts must be closed. assert all(ctx.closed for ctx in connections) finally: t.join()
def test_remove_context_missing(): ticket = Ticket(testutil.create_ticket(ops=["read"])) ticket.add_context(1, Context()) assert ticket.info()["connections"] == 1 ticket.remove_context(2) assert ticket.info()["connections"] == 1
def test_cancel_timeout(cfg): ticket = Ticket(testutil.create_ticket(ops=["read"]), cfg) # Add conection - having connections does not block cancelation, but we # cannot have ongoing operations without a connection. ctx = Context() ticket.add_context(1, ctx) # Ongoing operation blocks cancel. ticket._add_operation(Operation(0, 100)) # Canceling will time out. with pytest.raises(errors.TransferCancelTimeout): ticket.cancel(timeout=0.001) # Ticket is marked as canceled, but the context was not closed. assert ticket.canceled assert not ctx.closed # Caller can poll ticket "active" property and remove the ticket when the # ticket is inactive. info = ticket.info() assert info["canceled"] assert info["active"] assert info["connections"] == 1
def test_cancel_wait(cfg): ticket = Ticket(testutil.create_ticket(ops=["read"]), cfg) # Add connections using this ticket. users = [] for cid in range(4): ctx = Context() op = Operation(cid * 1024**2, 1024**2) ticket.add_context(cid, ctx) ticket._add_operation(op) users.append((cid, ctx, op)) # Add idle connection. idle_ctx = Context() ticket.add_context(4, idle_ctx) def finish_operations(): time.sleep(0.1) for cid, ctx, op in users: # Removing operation from a canceled ticket raises, send and error # and close the connection. try: ticket._remove_operation(op) except errors.AuthorizationError: ticket.remove_context(cid) info = ticket.info() assert not info["canceled"] assert info["connections"] == 5 assert info["active"] t = util.start_thread(finish_operations) try: ticket.cancel(timeout=10) finally: t.join() info = ticket.info() # After the ticket was canceled, ticket is inactive, and all ongoging # connnections removed from ticket. The idle connection is left, but its # context is closed. assert not info["active"] assert info["connections"] == 1 assert all(ctx.closed for cid, ctx, op in users) assert idle_ctx.closed
def test_cancel_unused(): ticket = Ticket(testutil.create_ticket(ops=["read"])) ticket.cancel() # Ticket is canceled and can be removed immediately. assert ticket.canceled info = ticket.info() assert info["canceled"] assert info["connections"] == 0
def test_cancel_async(): ticket = Ticket(testutil.create_ticket(ops=["read"])) ticket.add_context(1, None) ticket.cancel(timeout=0) # Ticket is canceled, but it cannot be removed. assert ticket.canceled info = ticket.info() assert info["canceled"] assert info["connections"] == 1
def test_cancel_no_connection(cfg): ticket = Ticket(testutil.create_ticket(ops=["read"]), cfg) ticket.cancel() # Ticket is canceled and can be removed immediately. assert ticket.canceled info = ticket.info() assert info["canceled"] assert not info["active"] assert info["connections"] == 0
def test_repr(): ticket = Ticket(testutil.create_ticket( ops=["read"], filename="tmp_file")) ticket_repr = repr(ticket) info = ticket.info() del info["timeout"] for key, value in info.items(): pair = "%s=%r" % (key, value) assert pair in ticket_repr
def test_cancel_async(cfg): ticket = Ticket(testutil.create_ticket(ops=["read"]), cfg) ctx = Context() ticket.add_context(1, ctx) ticket._add_operation(Operation(0, 100)) ticket.cancel(timeout=0) # Ticket is marked as canceled, but the context was not closed. assert ticket.canceled assert not ctx.closed info = ticket.info() assert info["canceled"] assert info["active"] assert info["connections"] == 1
def test_cancel_timeout(): ticket = Ticket(testutil.create_ticket(ops=["read"])) ticket.add_context(1, None) # Canceling will time out. with pytest.raises(errors.TicketCancelTimeout): ticket.cancel(timeout=0.001) # But ticket is marked as canceled. assert ticket.canceled # Caller can poll ticket status and remove the ticket when number of # connections is zero. info = ticket.info() assert info["canceled"] assert info["connections"] == 1
def test_cancel_idle_connection(cfg): ticket = Ticket(testutil.create_ticket(ops=["read"]), cfg) ctx = Context() ticket.add_context(1, ctx) ticket.cancel() # Ticket is canceled and can be removed immediately. assert ticket.canceled assert ctx.closed info = ticket.info() assert info["canceled"] assert not info["active"] # The conection context was closed. The connection will be closed when it # times out or when a user send the next request. assert info["connections"] == 1