示例#1
0
def test_rwmutex():
    mu = sync.RWMutex()

    # Unlock  without lock -> panic
    # RUnlock without lock -> panic
    with panics("sync: Unlock of unlocked RWMutex"):
        mu.Unlock()
    with panics("sync: RUnlock of unlocked RWMutex"):
        mu.RUnlock()

    # Lock vs Lock; was also tested in test_rwmutex_basic
    mu.Lock()
    l = []
    done = chan()

    def _():
        mu.Lock()
        l.append('b')
        mu.Unlock()
        done.close()

    go(_)
    time.sleep(1 * dt)
    l.append('a')
    mu.Unlock()
    done.recv()
    assert l == ['a', 'b']
示例#2
0
def test_waitgroup():
    wg = sync.WaitGroup()
    wg.add(2)

    ch = chan(3)

    def _():
        wg.wait()
        ch.send('a')

    for i in range(3):
        go(_)

    wg.done()
    assert len(ch) == 0
    time.sleep(0.1)
    assert len(ch) == 0
    wg.done()

    for i in range(3):
        assert ch.recv() == 'a'

    wg.add(1)
    go(_)
    time.sleep(0.1)
    assert len(ch) == 0
    wg.done()
    assert ch.recv() == 'a'

    with panics("sync: negative WaitGroup counter"):
        wg.done()
示例#3
0
def _test_mutex(mu, lock, unlock):
    # verify that g2 mu.lock() blocks until g1 does mu.unlock()
    getattr(mu, lock)()
    l = []
    done = chan()

    def _():
        getattr(mu, lock)()
        l.append('b')
        getattr(mu, unlock)()
        done.close()

    go(_)
    time.sleep(1 * dt)
    l.append('a')
    getattr(mu, unlock)()
    done.recv()
    assert l == ['a', 'b']

    # the same via with
    with mu:
        l = []
        done = chan()

        def _():
            with mu:
                l.append('d')
            done.close()

        go(_)
        time.sleep(1 * dt)
        l.append('c')
    done.recv()
    assert l == ['c', 'd']
示例#4
0
def waitfor(cond):
    tstart = time.now()
    while 1:
        if cond():
            return
        t = time.now()
        if (t - tstart) > 1*time.second:
            raise AssertionError("timeout waiting")
        time.sleep(1E-6) # NOTE sleep(0) consumes lot of CPU under gevent
示例#5
0
    def leaktask():
        gstarted.send(1)
        mainexit.recv()

        # normally when main thread exits, the whole process is terminated.
        # however if go spawns a thread with daemon=0, we are left here to continue.
        # make sure it is not the case
        time.sleep(3)
        print("leaked goroutine: process did not terminate", file=sys.stderr)
        sys.stderr.flush()
        time.sleep(1)
        os._exit(1)  # not sys.exit - that can be used only from main thread
示例#6
0
def test_timer_stop_drain():
    t = time.Timer(1 * dt)
    tx = time.Ticker(1 * dt)

    time.sleep(2 * dt)
    assert len(t.c) == 1
    assert len(tx.c) == 1

    assert t.stop() == False
    assert len(t.c) == 0

    tx.stop()
    assert len(tx.c) == 0
示例#7
0
 def W(): # 1 writer
     mu.Lock()
     time.sleep(Nr2*dt)  # give R2 readers more chance to call mu.RLock and run first
     locked.send('W')
     l.append('a')
     if not unlock_via_downgrade:
         locked.send('_WUnlock')
         mu.Unlock()
     else:
         locked.send('_WUnlockToRLock')
         mu.UnlockToRLock()
         time.sleep(Nr2*dt)
         locked.send('_WRUnlock')
         mu.RUnlock()
示例#8
0
def test_notify_reinstall():
    ch = chan(10, dtype=gos.Signal)
    def _():
        signal.Stop(ch)
    defer(_)

    for i in range(N):
        signal.Stop(ch)
        signal.Notify(ch, syscall.SIGUSR1)

    time.sleep(0.1*time.second)
    assert len(ch) == 0
    killme(syscall.SIGUSR1)
    time.sleep(0.1*time.second)
    assert len(ch) == 1
示例#9
0
def main():
    # build "all signals" list
    allsigv = []
    for attr in dir(syscall):
        if attr.startswith("SIG") and "_" not in attr:
            sig = getattr(syscall, attr)
            if sig not in allsigv: # avoid e.g. SIGCHLD/SIGCLD dups
                allsigv.append(sig)
    allsigv.sort(key=lambda sig: sig.signo)
    allsigv.remove(syscall.SIGKILL) # SIGKILL/SIGSTOP cannot be caught
    allsigv.remove(syscall.SIGSTOP)
    allsigv.remove(syscall.SIGBUS)  # AddressSanitizer crashes on SIGBUS/SIGFPE/SIGSEGV
    allsigv.remove(syscall.SIGFPE)
    allsigv.remove(syscall.SIGSEGV)

    # Notify() -> kill * -> should be notified
    ch = chan(10, dtype=gos.Signal)
    signal.Notify(ch) # all signals
    for sig in allsigv:
        emit("-> %d %s" % (sig.signo, sig))
        killme(sig)
        xsig = ch.recv()
        emit("<- %d %s" % (xsig.signo, xsig))
        if xsig != sig:
            raise AssertionError("got %s, expected %s" % (xsig, sig))
    emit("ok (notify)")

    # Ignore() -> kill * -> should not be notified
    emit()
    signal.Ignore() # all signals
    assert len(ch) == 0
    for sig in allsigv:
        emit("-> %d %s" % (sig.signo, sig))
        killme(sig)
        assert len(ch) == 0
    time.sleep(0.3)
    assert len(ch) == 0
    emit("ok (ignore)")

    # Reset() -> kill * should be handled by OS by default
    emit()
    signal.Reset() # all signals
    emit("terminating ...")
    killme(syscall.SIGTERM)
    raise AssertionError("not terminated")
示例#10
0
 def _():
     time.sleep(1 * dt)
     l.append('a')
     sema.release()
     done.close()
示例#11
0
def test_rwmutex_lock_vs_rlock(unlock_via_downgrade):
    mu = sync.RWMutex()

    # Lock vs RLock
    l = []  # accessed as R R R ... R  W  R R R ... R
    Nr1 = 10  # Nreaders queued before W
    Nr2 = 15  # Nreaders queued after  W
    mu.RLock()
    locked = chan(Nr1 + 1 * 3 + Nr2)  # main <- R|W: mu locked
    rcont = chan()  # main -> R: continue

    def R():  # readers
        mu.RLock()
        locked.send(('R', len(l)))
        rcont.recv()
        mu.RUnlock()

    for i in range(Nr1):
        go(R)

    # make sure all Nr1 readers entered mu.RLock
    for i in range(Nr1):
        assert locked.recv() == ('R', 0)

    # spawn W
    def W():  # 1 writer
        mu.Lock()
        time.sleep(
            Nr2 *
            dt)  # give R2 readers more chance to call mu.RLock and run first
        locked.send('W')
        l.append('a')
        if not unlock_via_downgrade:
            locked.send('_WUnlock')
            mu.Unlock()
        else:
            locked.send('_WUnlockToRLock')
            mu.UnlockToRLock()
            time.sleep(Nr2 * dt)
            locked.send('_WRUnlock')
            mu.RUnlock()

    go(W)

    # spawn more readers to verify that Lock has priority over RLock
    time.sleep(1 * dt)  # give W more chance to call mu.Lock first
    for i in range(Nr2):
        go(R)

    # release main rlock, make sure nor W nor more R are yet ready, and let all readers continue
    time.sleep((1 + 1) * dt)
    mu.RUnlock()
    time.sleep(1 * dt)
    for i in range(100):
        _, _rx = select(
            default,  # 0
            locked.recv,  # 1
        )
        assert _ == 0
    rcont.close()

    # W must get the lock first and all R2 readers only after it
    assert locked.recv() == 'W'
    if not unlock_via_downgrade:
        assert locked.recv() == '_WUnlock'
    else:
        assert locked.recv() == '_WUnlockToRLock'
    for i in range(Nr2):
        assert locked.recv() == ('R', 1)
    if unlock_via_downgrade:
        assert locked.recv() == '_WRUnlock'
示例#12
0
def test_signal():
    # Notify/Stop with wrong chan dtype -> panic
    _ = panics("pychan: channel type mismatch")
    with _:  signal.Notify(chan(2), syscall.SIGUSR1)
    with _:  signal.Stop  (chan(2))
    with _:  signal.Notify(chan(2, dtype='C.int'), syscall.SIGUSR1)
    with _:  signal.Stop  (chan(2, dtype='C.int'))

    # Notify/Ignore/Reset with wrong signal type
    _ = raises(TypeError)
    with _:  signal.Notify(chan(dtype=gos.Signal), None)
    with _:  signal.Ignore(None)
    with _:  signal.Reset(None)

    # subscribe ch1(USR1), ch12(USR1,USR2) and ch2(USR2)
    ch1  = chan(2, dtype=gos.Signal)
    ch12 = chan(2, dtype=gos.Signal)
    ch2  = chan(2, dtype=gos.Signal)
    signal.Notify(ch1,  syscall.SIGUSR1)
    signal.Notify(ch12, syscall.SIGUSR1, syscall.SIGUSR2)
    signal.Notify(ch2,                   syscall.SIGUSR2)
    def _():
        signal.Reset()
    defer(_)

    for i in range(N):
        # raise SIGUSR1 -> should be delivered to ch1 and ch12
        assert len(ch1)  == 0
        assert len(ch12) == 0
        assert len(ch2)  == 0
        killme(syscall.SIGUSR1)
        waitfor(lambda: len(ch1) == 1 and len(ch12) == 1)
        sig1  = ch1.recv()
        sig12 = ch12.recv()
        assert sig1  == syscall.SIGUSR1
        assert sig12 == syscall.SIGUSR1

        # raise SIGUSR2 -> should be delivered to         ch12 and ch2
        assert len(ch1)  == 0
        assert len(ch12) == 0
        assert len(ch2)  == 0
        killme(syscall.SIGUSR2)
        waitfor(lambda: len(ch12) == 1 and len(ch2) == 1)
        sig12 = ch12.recv()
        sig2  = ch2.recv()
        assert sig12 == syscall.SIGUSR2
        assert sig2  == syscall.SIGUSR2
        # if SIGUSR2 will be eventually delivered to ch1 - it will break
        # in SIGUSR1 check on next iteration.

    # Stop(ch2) -> signals should not be delivered to ch2 anymore
    signal.Stop(ch2)
    for i in range(N):
        # USR1 -> ch1, ch12
        assert len(ch1)  == 0
        assert len(ch12) == 0
        assert len(ch2)  == 0
        killme(syscall.SIGUSR1)
        waitfor(lambda: len(ch1) == 1 and len(ch12) == 1)
        sig1  = ch1.recv()
        sig12 = ch12.recv()
        assert sig1  == syscall.SIGUSR1
        assert sig12 == syscall.SIGUSR1

        # USR2 -> ch12, !ch2
        assert len(ch1)  == 0
        assert len(ch12) == 0
        assert len(ch2)  == 0
        killme(syscall.SIGUSR2)
        waitfor(lambda: len(ch12) == 1)
        sig12 = ch12.recv()
        assert sig12 == syscall.SIGUSR2
        # if SIGUSR2 will be eventually delivered to ch2 - it will break on
        # next iteration.

    # Ignore(USR1) -> ch1 should not be delivered to anymore, ch12 should be delivered only USR2
    signal.Ignore(syscall.SIGUSR1)
    for i in range(N):
        # USR1 -> ø
        assert len(ch1)  == 0
        assert len(ch12) == 0
        assert len(ch2)  == 0
        killme(syscall.SIGUSR1)
        time.sleep(1E-6)

        # USR2 -> ch12
        assert len(ch1)  == 0
        assert len(ch12) == 0
        assert len(ch2)  == 0
        killme(syscall.SIGUSR2)
        waitfor(lambda: len(ch12) == 1)
        sig12 = ch12.recv()
        assert sig12 == syscall.SIGUSR2
        # if SIGUSR1 or SIGUSR2 will be eventually delivered to ch1 or ch2 - it
        # will break on next iteration.

    # Notify after Ignore
    signal.Notify(ch1, syscall.SIGUSR1)
    for i in range(N):
        # USR1 -> ch1
        assert len(ch1)  == 0
        assert len(ch12) == 0
        assert len(ch2)  == 0
        killme(syscall.SIGUSR1)
        waitfor(lambda: len(ch1) == 1)
        sig1 = ch1.recv()
        assert sig1 == syscall.SIGUSR1

        # USR2 -> ch12
        assert len(ch1)  == 0
        assert len(ch12) == 0
        assert len(ch2)  == 0
        killme(syscall.SIGUSR2)
        waitfor(lambda: len(ch12) == 1)
        sig12 = ch12.recv()
        assert sig12 == syscall.SIGUSR2
示例#13
0
def test_stdlib_interop_KeyboardInterrupt():
    # KeyboardInterrupt is raised by default
    with raises(KeyboardInterrupt):
        killme(syscall.SIGINT)
        time.sleep(1)

    ch1 = chan(2, dtype=gos.Signal)
    ch2 = chan(2, dtype=gos.Signal)
    def _():
        signal.Reset(syscall.SIGINT)
    defer(_)

    # Notify disables raising KeyboardInterrupt by default on SIGINT
    signal.Notify(ch1, syscall.SIGINT)
    try:
        killme(syscall.SIGINT)
        waitfor(lambda: len(ch1) == 1)
        obj1 = ch1.recv()
        assert obj1 == syscall.SIGINT
        time.sleep(0.1) # just in case
    except KeyboardInterrupt:
        raise AssertionError("KeyboardInterrupt raised after signal.Notify +ch1")

    signal.Notify(ch2, syscall.SIGINT)
    try:
        killme(syscall.SIGINT)
        waitfor(lambda: len(ch1) == 1 and len(ch2) == 1)
        obj1 = ch1.recv()
        obj2 = ch2.recv()
        assert obj1 == syscall.SIGINT
        assert obj2 == syscall.SIGINT
        time.sleep(0.1) # just in case
    except KeyboardInterrupt:
        raise AssertionError("KeyboardInterrupt raised after signal.Notify +ch1 +ch2")

    # last Stop should reenable raising KeyboardInterrupt by default on SIGINT
    signal.Stop(ch1)
    try:
        killme(syscall.SIGINT)
        waitfor(lambda: len(ch2) == 1)
        obj2 = ch2.recv()
        assert obj2 == syscall.SIGINT
        time.sleep(0.1) # just in case
        assert len(ch1) == 0
    except KeyboardInterrupt:
        raise AssertionError("KeyboardInterrupt raised after signal.Notify +ch1 +ch2 -ch1")

    signal.Stop(ch2)
    with raises(KeyboardInterrupt):
        killme(syscall.SIGINT)
        time.sleep(1)
    time.sleep(0.1) # just in case
    assert len(ch1) == 0
    assert len(ch2) == 0

    # Ignore disables raising KeyboardInterrupt by default on SIGINT
    signal.Ignore(syscall.SIGINT)
    try:
        killme(syscall.SIGINT)
        time.sleep(0.1)
        assert len(ch1) == 0
        assert len(ch2) == 0
    except KeyboardInterrupt:
        raise AssertionError("KeyboardInterrupt raised after signal.Ignore")

    # Reset restores original behaviour
    signal.Reset(syscall.SIGINT)
    with raises(KeyboardInterrupt):
        killme(syscall.SIGINT)
        time.sleep(1)
    time.sleep(0.1) # just in case
    assert len(ch1) == 0
    assert len(ch2) == 0
示例#14
0
def test_stdlib_interop():
    import signal as pysig

    ch1 = chan(2, dtype=object) # NOTE not gos.Signal nor 'C.os::Signal'
    def _(signo, frame):
        ch1.send("USR1")
    pysig.signal(pysig.SIGUSR1, _)
    def _():
        pysig.signal(pysig.SIGUSR1, pysig.SIG_IGN)
    defer(_)

    # verify that plain pysig delivery works
    for i in range(N):
        assert len(ch1) == 0
        killme(syscall.SIGUSR1)
        waitfor(lambda: len(ch1) == 1)
        obj1 = ch1.recv()
        assert obj1 == "USR1"

    # verify that combined pysig + golang.os.signal delivery works
    ch2 = chan(2, dtype=gos.Signal)
    signal.Notify(ch2, syscall.SIGUSR1)
    def _():
        signal.Stop(ch2)
    defer(_)

    for i in range(N):
        assert len(ch1) == 0
        assert len(ch2) == 0
        killme(syscall.SIGUSR1)
        waitfor(lambda: len(ch1) == 1 and len(ch2) == 1)
        obj1 = ch1.recv()
        sig2 = ch2.recv()
        assert obj1 == "USR1"
        assert sig2 == syscall.SIGUSR1

    # Ignore stops delivery to both pysig and golang.os.signal
    signal.Ignore(syscall.SIGUSR1)
    for i in range(N):
        assert len(ch1) == 0
        assert len(ch2) == 0
        killme(syscall.SIGUSR1)
        time.sleep(1E-6)
    time.sleep(0.1) # just in case
    assert len(ch1) == 0
    assert len(ch2) == 0

    # after Reset pysig delivery is restored even after Ignore
    signal.Reset(syscall.SIGUSR1)
    for i in range(N):
        assert len(ch1) == 0
        assert len(ch2) == 0
        killme(syscall.SIGUSR1)
        waitfor(lambda: len(ch1) == 1)
        assert len(ch2) == 0
        obj1 = ch1.recv()
        assert obj1 == "USR1"

    # Reset stops delivery to golang.os.signal and restores pysig delivery
    signal.Notify(ch2, syscall.SIGUSR1)
    signal.Reset(syscall.SIGUSR1)
    for i in range(N):
        assert len(ch1) == 0
        assert len(ch2) == 0
        killme(syscall.SIGUSR1)
        waitfor(lambda: len(ch1) == 1)
        assert len(ch2) == 0
        obj1 = ch1.recv()
        assert obj1 == "USR1"
示例#15
0
 def tick():  # cpython 2.7 time.time uses max microsecond precision
     time.sleep(1 * time.microsecond)
示例#16
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)