Example #1
0
def test_already_canceled():
    parent, pcancel = context.with_cancel(bg)
    assertCtx(parent, Z)
    pcancel()
    assertCtx(parent, Z, err=C, done=Y)

    ctxC, _ = context.with_cancel(parent)
    assert ctxC.done() != parent.done()
    assertCtx(parent, Z, err=C, done=Y)  # no ctxC in children
    assertCtx(ctxC, Z, err=C, done=Y)

    ctxT, _ = context.with_timeout(parent, 10 * dt)
    d = ctxT.deadline()
    assert ctxT.done() != parent.done()
    assertCtx(parent, Z, err=C, done=Y)  # no ctxT in children
    assertCtx(ctxT, Z, deadline=d, err=C, done=Y)

    d = time.now() + 10 * dt
    ctxD, _ = context.with_deadline(parent, d)
    assert ctxD.done() != parent.done()
    assertCtx(parent, Z, err=C, done=Y)  # no ctxD in children
    assertCtx(ctxD, Z, deadline=d, err=C, done=Y)

    ctxM, _ = context.merge(parent, bg)
    assert ctxM.done() != parent.done()
    assertCtx(parent, Z, err=C, done=Y)  # no ctxM in children
    assertCtx(ctxM, Z, err=C, done=Y)

    ctxV = context.with_value(parent, kHello, "world")
    assert ctxV.done() == parent.done()
    assert ctxV.value(kHello) == "world"
    assertCtx(parent, Z, err=C, done=Y)  # no ctxV in children
    assertCtx(ctxV, Z, err=C, done=Y)
Example #2
0
def test_workgroup():
    ctx, cancel = context.with_cancel(context.background())
    mu = sync.Mutex()

    # t1=ok, t2=ok
    wg = sync.WorkGroup(ctx)
    l = [0, 0]
    for i in range(2):

        def _(ctx, i):
            with mu:
                l[i] = i + 1

        wg.go(_, i)
    wg.wait()
    assert l == [1, 2]

    # WorkGroup must catch/propagate all exception classes.
    # Python2 allows to raise old-style classes not derived from BaseException.
    # Python3 allows to raise only BaseException derivatives.
    if six.PY2:

        class MyError:
            def __init__(self, *args):
                self.args = args
    else:

        class MyError(BaseException):
            pass

    # t1=fail, t2=ok, does not look at ctx
    wg = sync.WorkGroup(ctx)
    l = [0, 0]
    for i in range(2):

        def _(ctx, i):
            Iam__ = 0
            with mu:
                l[i] = i + 1
                if i == 0:
                    raise MyError('aaa')

        def f(ctx, i):
            Iam_f = 0
            _(ctx, i)

        wg.go(f, i)
    with raises(MyError) as exc:
        wg.wait()
    assert exc.type is MyError
    assert exc.value.args == ('aaa', )
    if PyErr_Restore_traceback_ok:
        assert 'Iam__' in exc.traceback[-1].locals
        assert 'Iam_f' in exc.traceback[-2].locals
    assert l == [1, 2]

    # t1=fail, t2=wait cancel, fail
    wg = sync.WorkGroup(ctx)
    l = [0, 0]
    for i in range(2):

        def _(ctx, i):
            Iam__ = 0
            with mu:
                l[i] = i + 1
                if i == 0:
                    raise MyError('bbb')
            if i == 1:
                ctx.done().recv()
                raise ValueError('ccc')  # != MyError

        def f(ctx, i):
            Iam_f = 0
            _(ctx, i)

        wg.go(f, i)
    with raises(MyError) as exc:
        wg.wait()
    assert exc.type is MyError
    assert exc.value.args == ('bbb', )
    if PyErr_Restore_traceback_ok:
        assert 'Iam__' in exc.traceback[-1].locals
        assert 'Iam_f' in exc.traceback[-2].locals
    assert l == [1, 2]

    # t1=ok,wait cancel  t2=ok,wait cancel
    # cancel parent
    wg = sync.WorkGroup(ctx)
    l = [0, 0]
    for i in range(2):

        def _(ctx, i):
            with mu:
                l[i] = i + 1
            ctx.done().recv()

        wg.go(_, i)
    cancel()  # parent cancel - must be propagated into workgroup
    wg.wait()
    assert l == [1, 2]
Example #3
0
def test_context():
    assert bg.err() is None
    assert bg.done() == nilchan
    assert bg.deadline() is None
    assert not ready(bg.done())
    assert bg.value(kHello) is None

    ctx1, cancel1 = context.with_cancel(bg)
    assert ctx1.done() != bg.done()
    assertCtx(ctx1, Z)

    ctx11, cancel11 = context.with_cancel(ctx1)
    assert ctx11.done() != ctx1.done()
    assertCtx(ctx1, {ctx11})
    assertCtx(ctx11, Z)

    vAlpha = Key("alpha")  # value object; Key is just reused as placeholder
    ctx111 = context.with_value(ctx11, kHello, vAlpha)
    assert ctx111.done() == ctx11.done()
    assert ctx111.value(kHello) is vAlpha  # original value object is returned
    assert ctx111.value(
        kHello2) is None  # _not_ vAlpha: keys are compared by identity
    assert ctx111.value(kAbc) is None
    assertCtx(ctx1, {ctx11})
    assertCtx(ctx11, {ctx111})
    assertCtx(ctx111, Z)

    ctx1111 = context.with_value(ctx111, kBeta, "gamma")
    assert ctx1111.done() == ctx11.done()
    assert ctx1111.value(kHello) is vAlpha
    assert ctx1111.value(kBeta) == "gamma"
    assert ctx1111.value(kAbc) is None
    assertCtx(ctx1, {ctx11})
    assertCtx(ctx11, {ctx111})
    assertCtx(ctx111, {ctx1111})
    assertCtx(ctx1111, Z)

    ctx12 = context.with_value(ctx1, kHello, "world")
    assert ctx12.done() == ctx1.done()
    assert ctx12.value(kHello) == "world"
    assert ctx12.value(kAbc) is None
    assertCtx(ctx1, {ctx11, ctx12})
    assertCtx(ctx11, {ctx111})
    assertCtx(ctx111, {ctx1111})
    assertCtx(ctx1111, Z)
    assertCtx(ctx12, Z)

    ctx121, cancel121 = context.with_cancel(ctx12)
    assert ctx121.done() != ctx12.done()
    assert ctx121.value(kHello) == "world"
    assert ctx121.value(kAbc) is None
    assertCtx(ctx1, {ctx11, ctx12})
    assertCtx(ctx11, {ctx111})
    assertCtx(ctx111, {ctx1111})
    assertCtx(ctx1111, Z)
    assertCtx(ctx12, {ctx121})
    assertCtx(ctx121, Z)

    ctx1211 = context.with_value(ctx121, kMir, "май")
    assert ctx1211.done() == ctx121.done()
    assert ctx1211.value(kHello) == "world"
    assert ctx1211.value(kMir) == "май"
    assert ctx1211.value(kAbc) is None
    assertCtx(ctx1, {ctx11, ctx12})
    assertCtx(ctx11, {ctx111})
    assertCtx(ctx111, {ctx1111})
    assertCtx(ctx1111, Z)
    assertCtx(ctx12, {ctx121})
    assertCtx(ctx121, {ctx1211})
    assertCtx(ctx1211, Z)

    ctxM, cancelM = context.merge(ctx1111, ctx1211)
    assert ctxM.done() != ctx1111.done()
    assert ctxM.done() != ctx1211.done()
    assert ctxM.value(kHello) is vAlpha
    assert ctxM.value(kMir) == "май"
    assert ctxM.value(kBeta) == "gamma"
    assert ctxM.value(kAbc) is None
    assertCtx(ctx1, {ctx11, ctx12})
    assertCtx(ctx11, {ctx111})
    assertCtx(ctx111, {ctx1111})
    assertCtx(ctx1111, {ctxM})
    assertCtx(ctx12, {ctx121})
    assertCtx(ctx121, {ctx1211})
    assertCtx(ctx1211, {ctxM})
    assertCtx(ctxM, Z)

    for _ in range(2):
        cancel11()
        assertCtx(ctx1, {ctx12})
        assertCtx(ctx11, Z, err=C, done=Y)
        assertCtx(ctx111, Z, err=C, done=Y)
        assertCtx(ctx1111, Z, err=C, done=Y)
        assertCtx(ctx12, {ctx121})
        assertCtx(ctx121, {ctx1211})
        assertCtx(ctx1211, Z)
        assertCtx(ctxM, Z, err=C, done=Y)

    for _ in range(2):
        cancel1()
        assertCtx(ctx1, Z, err=C, done=Y)
        assertCtx(ctx11, Z, err=C, done=Y)
        assertCtx(ctx111, Z, err=C, done=Y)
        assertCtx(ctx1111, Z, err=C, done=Y)
        assertCtx(ctx12, Z, err=C, done=Y)
        assertCtx(ctx121, Z, err=C, done=Y)
        assertCtx(ctx1211, Z, err=C, done=Y)
        assertCtx(ctxM, Z, err=C, done=Y)
Example #4
0
def test_deadline():
    t0 = time.now()
    d1 = t0 + 10 * dt
    d2 = t0 + 20 * dt
    d3 = t0 + 30 * dt

    ctx1, cancel1 = context.with_deadline(bg, d2)
    assert ctx1.done() != bg.done()
    assertCtx(ctx1, Z, deadline=d2)

    ctx11 = context.with_value(ctx1, kA, "b")
    assert ctx11.done() == ctx1.done()
    assert ctx11.value(kA) == "b"
    assertCtx(ctx1, {ctx11}, deadline=d2)
    assertCtx(ctx11, Z, deadline=d2)

    ctx111, cancel111 = context.with_cancel(ctx11)
    assert ctx111.done() != ctx11.done
    assertCtx(ctx1, {ctx11}, deadline=d2)
    assertCtx(ctx11, {ctx111}, deadline=d2)
    assertCtx(ctx111, Z, deadline=d2)

    ctx1111, cancel1111 = context.with_deadline(ctx111,
                                                d3)  # NOTE deadline > parent
    assert ctx1111.done() != ctx111.done()
    assertCtx(ctx1, {ctx11}, deadline=d2)
    assertCtx(ctx11, {ctx111}, deadline=d2)
    assertCtx(ctx111, {ctx1111}, deadline=d2)
    assertCtx(ctx1111, Z, deadline=d2)  # NOTE not d3

    ctx12, cancel12 = context.with_deadline(ctx1, d1)
    assert ctx12.done() != ctx1.done()
    assertCtx(ctx1, {ctx11, ctx12}, deadline=d2)
    assertCtx(ctx11, {ctx111}, deadline=d2)
    assertCtx(ctx111, {ctx1111}, deadline=d2)
    assertCtx(ctx1111, Z, deadline=d2)
    assertCtx(ctx12, Z, deadline=d1)

    ctxM, cancelM = context.merge(ctx1111, ctx12)
    assert ctxM.done() != ctx1111.done()
    assert ctxM.done() != ctx12.done()
    assert ctxM.value(kA) == "b"
    assertCtx(ctx1, {ctx11, ctx12}, deadline=d2)
    assertCtx(ctx11, {ctx111}, deadline=d2)
    assertCtx(ctx111, {ctx1111}, deadline=d2)
    assertCtx(ctx1111, {ctxM}, deadline=d2)
    assertCtx(ctx12, {ctxM}, deadline=d1)
    assertCtx(ctxM, Z, deadline=d1)

    time.sleep(11 * dt)

    assertCtx(ctx1, {ctx11}, deadline=d2)
    assertCtx(ctx11, {ctx111}, deadline=d2)
    assertCtx(ctx111, {ctx1111}, deadline=d2)
    assertCtx(ctx1111, Z, deadline=d2)
    assertCtx(ctx12, Z, deadline=d1, err=D, done=Y)
    assertCtx(ctxM, Z, deadline=d1, err=D, done=Y)

    # explicit cancel first -> err=canceled instead of deadlineExceeded
    for i in range(2):
        cancel1()
        assertCtx(ctx1, Z, deadline=d2, err=C, done=Y)
        assertCtx(ctx11, Z, deadline=d2, err=C, done=Y)
        assertCtx(ctx111, Z, deadline=d2, err=C, done=Y)
        assertCtx(ctx1111, Z, deadline=d2, err=C, done=Y)
        assertCtx(ctx12, Z, deadline=d1, err=D, done=Y)
        assertCtx(ctxM, Z, deadline=d1, err=D, done=Y)

    # with_timeout
    ctx, cancel = context.with_timeout(bg, 10 * dt)
    assert ctx.done() != bg.done()
    d = ctx.deadline()
    assert abs(d - (time.now() + 10 * dt)) < 1 * dt
    assertCtx(ctx, Z, deadline=d)

    time.sleep(11 * dt)
    assertCtx(ctx, Z, deadline=d, err=D, done=Y)
Example #5
0
def test_workgroup_with():
    # verify with support for sync.WorkGroup
    ctx, cancel = context.with_cancel(context.background())
    defer(cancel)
    mu = sync.Mutex()

    # t1=ok, t2=ok
    l = [0, 0]
    with sync.WorkGroup(ctx) as wg:
        for i in range(2):
            def _(ctx, i):
                with mu:
                    l[i] = i+1
            wg.go(_, i)
    assert l == [1, 2]

    # t1=fail, t2=wait cancel, fail
    with raises(MyError) as exci:
        with sync.WorkGroup(ctx) as wg:
            def _(ctx):
                Iam_t1 = 0
                raise MyError('hello (fail)')
            wg.go(_)

            def _(ctx):
                ctx.done().recv()
                raise MyError('world (after zzz)')
            wg.go(_)

    e = exci.value
    assert e.__class__      is MyError
    assert e.args           == ('hello (fail)',)
    assert e.__cause__      is None
    assert e.__context__    is None
    assert e.__suppress_context__ == False
    if PyErr_Restore_traceback_ok:
        assert 'Iam_t1' in exci.traceback[-1].locals

    # t=ok, but code from under with raises
    l = [0]
    with raises(MyError) as exci:
        with sync.WorkGroup(ctx) as wg:
            def _(ctx):
                l[0] = 1
            wg.go(_)
            def bad():
                raise MyError('wow')
            bad()

    e = exci.value
    assert e.__class__      is MyError
    assert e.args           == ('wow',)
    assert e.__cause__      is None
    assert e.__context__    is None
    assert e.__suppress_context__ == False
    assert exci.traceback[-1].name == 'bad'
    assert l[0] == 1

    # t=fail, code from under with also raises
    with raises(MyError) as exci:
        with sync.WorkGroup(ctx) as wg:
            def f(ctx):
                raise MyError('fail from go')
            wg.go(f)
            def g():
                raise MyError('just raise')
            g()

    e = exci.value
    assert e.__class__      is MyError
    assert e.args           == ('fail from go',)
    assert e.__cause__      is None
    assert e.__context__    is not None
    assert e.__suppress_context__ == False
    assert exci.traceback[-1].name == 'f'
    e2 = e.__context__
    assert e2.__class__     is MyError
    assert e2.args          == ('just raise',)
    assert e2.__cause__     is None
    assert e2.__context__   is None
    assert e2.__suppress_context__ == False
    assert e2.__traceback__ is not None
    t2 = Traceback(e2.__traceback__)
    assert t2[-1].name == 'g'
Example #6
0
def test_workgroup():
    ctx, cancel = context.with_cancel(context.background())
    mu = sync.Mutex()

    # t1=ok, t2=ok
    wg = sync.WorkGroup(ctx)
    l = [0, 0]
    for i in range(2):
        def _(ctx, i):
            with mu:
                l[i] = i+1
        wg.go(_, i)
    wg.wait()
    assert l == [1, 2]


    # t1=fail, t2=ok, does not look at ctx
    wg = sync.WorkGroup(ctx)
    l = [0, 0]
    for i in range(2):
        def _(ctx, i):
            Iam__ = 0
            with mu:
                l[i] = i+1
                if i == 0:
                    raise MyError('aaa')
        def f(ctx, i):
            Iam_f = 0
            _(ctx, i)

        wg.go(f, i)
    with raises(MyError) as exc:
        wg.wait()
    assert exc.type       is MyError
    assert exc.value.args == ('aaa',)
    if PyErr_Restore_traceback_ok:
        assert 'Iam__' in exc.traceback[-1].locals
        assert 'Iam_f' in exc.traceback[-2].locals
    assert l == [1, 2]

    # t1=fail, t2=wait cancel, fail
    wg = sync.WorkGroup(ctx)
    l = [0, 0]
    for i in range(2):
        def _(ctx, i):
            Iam__ = 0
            with mu:
                l[i] = i+1
                if i == 0:
                    raise MyError('bbb')
            if i == 1:
                ctx.done().recv()
                raise ValueError('ccc') # != MyError
        def f(ctx, i):
            Iam_f = 0
            _(ctx, i)

        wg.go(f, i)
    with raises(MyError) as exc:
        wg.wait()
    assert exc.type       is MyError
    assert exc.value.args == ('bbb',)
    if PyErr_Restore_traceback_ok:
        assert 'Iam__' in exc.traceback[-1].locals
        assert 'Iam_f' in exc.traceback[-2].locals
    assert l == [1, 2]


    # t1=ok,wait cancel  t2=ok,wait cancel
    # cancel parent
    wg = sync.WorkGroup(ctx)
    l = [0, 0]
    for i in range(2):
        def _(ctx, i):
            with mu:
                l[i] = i+1
            ctx.done().recv()
        wg.go(_, i)
    cancel()    # parent cancel - must be propagated into workgroup
    wg.wait()
    assert l == [1, 2]