Beispiel #1
0
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
Beispiel #2
0
def test_remove_context_error(cfg):
    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"]), cfg)
    ctx = FailingContext()
    ticket.add_context(1, ctx)

    # If closing a context fails, fail. The ticket cannot be removed
    # until this context is closed successfully.
    with pytest.raises(RuntimeError):
        ticket.cancel(timeout=0)

    assert not ctx.closed

    # Calling again will close context successfully, and the ticket can
    # be removed.
    ticket.cancel(timeout=0)

    assert ctx.closed
Beispiel #3
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()
Beispiel #4
0
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
Beispiel #5
0
def test_canceled_fail_add_context():
    ticket = Ticket(testutil.create_ticket(ops=["read"]))
    ticket.cancel()

    ctx = Context()

    # Adding new context must fail.
    with pytest.raises(errors.AuthorizationError):
        ticket.add_context(2, ctx)
Beispiel #6
0
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
Beispiel #7
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
Beispiel #8
0
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
Beispiel #9
0
def test_canceled_fail_run_before():
    ticket = Ticket(testutil.create_ticket(ops=["read"]))
    ticket.cancel()

    op = Operation()

    # Running operations must fail.
    with pytest.raises(errors.AuthorizationError):
        ticket.run(op)

    # Operation was not run.
    assert op.done == 0
Beispiel #10
0
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
Beispiel #11
0
def test_cancel_ongoing_operations():
    ticket = Ticket(testutil.create_ticket(ops=["read"]))

    # Few connections are using this ticket. Each running an operation.
    ops = []
    for i in range(4):
        ctx = Context()
        op = Operation()
        ticket.add_context(i, ctx)
        ticket._add_operation(op)
        ops.append(op)

    ticket.cancel(timeout=0)

    # All ongoing operations are canceled.
    assert all(op.canceled for op in ops)
Beispiel #12
0
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
Beispiel #13
0
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
Beispiel #14
0
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