Example #1
0
def test_kill_descendents():
    with ProcessGroup() as pg:
        pin = Pipe()
        pout = Pipe()
        pg.add(
            Process(
                runpy("""import subprocess
import sys
child = subprocess.Popen([sys.executable, '-c', '''
print("spam")
input()
print("eggs")
'''])
child.wait()
"""),
                stdin=pin.side_out,
                stdout=pout.side_in,
            ))
    pg.start()
    pin.side_out.close()
    pout.side_in.close()
    assert pout.side_out.read(4) == b'spam'
    pg.terminate()
    pg.join()
    try:
        pin.side_in.write(b'\n')
        pin.side_in.close()
    except (BrokenPipeError, OSError):
        # BrokenPipeError on Linux, nothing on Mac, OSError on Windows
        pass
    assert pout.side_out.read() in b'\r\n'
Example #2
0
def test_tee_basics():
    pin = Pipe()
    pout = Pipe()
    buf = io.BytesIO()

    closed = False

    def _closeit():
        nonlocal closed
        closed = True

    t = Tee(  # noqa
        side_in=pin.side_out,
        side_out=pout.side_in,
        callback=buf.write,
        eof=_closeit,
    )
    pin.side_in.write(b'foobar')
    pin.side_in.close()

    roundtrip = pout.side_out.read()
    assert roundtrip == b'foobar'
    # This is only guarenteed _after_ it appears on the pipe
    assert buf.getvalue() == b'foobar'
    assert closed
Example #3
0
def test_valve_stop():
    pin = Pipe()
    pout = Pipe()
    v = Valve(
        side_in=pin.side_out,
        side_out=pout.side_in,
    )

    pin.side_in.write(b'spameggs')
    pin.side_in.close()

    buf = None
    timediff = None

    def clockread():
        nonlocal buf, timediff
        s = time.perf_counter()
        buf = pout.side_out.read()
        e = time.perf_counter()
        timediff = e - s

    v.turn_off()
    t = threading.Thread(target=clockread, daemon=True)
    t.start()
    time.sleep(1.0)
    v.turn_on()
    t.join()

    assert buf == b'spameggs'
    assert timediff > 0.9
Example #4
0
def test_through():
    pin = Pipe()
    pout = Pipe()
    qc = QuickConnect(  # noqa
        side_in=pin.side_out, side_out=pout.side_in, keepopen=False)

    pin.side_in.write(b'spameggs')
    pin.side_in.close()

    roundtrip = pout.side_out.read()
    assert roundtrip == b'spameggs'
Example #5
0
def test_valve_through():
    pin = Pipe()
    pout = Pipe()
    v = Valve(
        side_in=pin.side_out,
        side_out=pout.side_in,
    )
    v.turn_on()

    pin.side_in.write(b'spameggs')
    pin.side_in.close()

    roundtrip = pout.side_out.read()
    assert roundtrip == b'spameggs'
Example #6
0
def test_goesthrough():
    p = Pipe()
    p.side_in.write(b"Hello")
    p.side_in.close()

    data = p.side_out.read()
    assert data == b'Hello'
    data = p.side_out.read()
    assert data == b''
Example #7
0
def test_large_chunk_interactivish():
    p = Pipe()
    p.side_in.write(b"Hello")

    data = p.side_out.read(4000)
    assert data == b'Hello'
    p.side_in.close()
    data = p.side_out.read(4000)
    assert data == b''
Example #8
0
def test_group():
    with ProcessGroup() as pg:
        p1 = Pipe()
        pg.add(Process(runpy("print('spam')"), stdout=p1.side_in))
        p2 = Pipe()
        pg.add(Process(runpy("print('eggs')"), stdout=p2.side_in))
        p3 = Pipe()
        pg.add(Process(runpy("print('vikings')"), stdout=p3.side_in))

    pg.start()
    p1.side_in.close()
    p2.side_in.close()
    p3.side_in.close()
    pg.join()

    assert p1.side_out.read().rstrip() == b'spam'
    assert p2.side_out.read().rstrip() == b'eggs'
    assert p3.side_out.read().rstrip() == b'vikings'
Example #9
0
def test_valve_stop_midway():
    pin = Pipe()
    pout = Pipe()
    v = Valve(
        side_in=pin.side_out,
        side_out=pout.side_in,
    )

    v.turn_on()
    pin.side_in.write(b'spam')
    time.sleep(1.0)
    v.turn_off()
    pin.side_in.write(b'eggs')
    time.sleep(1.0)

    buf = pout.side_out.read(4000)

    assert buf == b'spam'
Example #10
0
def test_pipe_output():
    pi = Pipe()
    proc = Process(runpy(r'print("hello")'), stdout=pi.side_in)
    proc.start()
    data = pi.side_out.readline()
    # Pipe is closed but process might still be live
    proc.join()  # Commenting this out causes data to be None?
    assert proc.return_code == 0
    assert data in (b'hello\n', b'hello\r\n')
Example #11
0
def test_eof():
    p = Pipe()
    p.side_in.write(b"spam")

    data = p.side_out.read(4)  # read() or read(-1) read until EOF
    assert data == b'spam'

    p.side_in.close()
    data = p.side_out.read()
    assert data == b''
Example #12
0
def test_pipe_input():
    pi = Pipe()
    proc = Process(runpy(r'import sys; sys.exit(input() == "spam")'),
                   stdin=pi.side_out)
    proc.start()
    pi.side_in.write(b"spam\n")
    pi.side_in.close()
    # Pipe is closed but process might still be live
    proc.join()
    assert proc.return_code == 1
Example #13
0
def test_change_output():
    pin = Pipe()
    p1 = Pipe()
    p2 = Pipe()
    qc = QuickConnect(
        side_in=pin.side_out,
        side_out=p1.side_in,
    )

    pin.side_in.write(b'spam')

    time.sleep(1.0)
    qc.side_out = p2.side_in

    pin.side_in.write(b'eggs')

    out1 = p1.side_out.read(4000)
    out2 = p2.side_out.read(4000)
    assert out1 == b'spam'
    assert out2 == b'eggs'
Example #14
0
def test_chunk_eof():
    p = Pipe()
    p.side_in.write(b"Hello")

    data = p.side_out.read(3)
    assert data == b'Hel'
    data = p.side_out.read(2)
    assert data == b'lo'
    p.side_in.close()
    data = p.side_out.read(5)
    assert data == b''
Example #15
0
def test_partial_output():
    pi = Pipe()
    proc = Process(
        runpy(r'print("foo", flush=True); input(); print("bar", flush=True)'),
        stdout=pi.side_in,
    )
    proc.start()
    data = pi.side_out.readline()
    proc.terminate()
    proc.join()
    assert data in (b'foo\n', b'foo\r\n')
Example #16
0
def test_inner_pipe_reversed_order():
    pi = Pipe()
    prod = Process(runpy(r'print("eggs")'), stdout=pi.side_in)
    cons = Process(runpy(r'import sys; sys.exit(input() == "eggs")'),
                   stdin=pi.side_out)
    cons.start()
    prod.start()
    cons.join()
    prod.join()
    assert prod.return_code == 0
    assert cons.return_code == 1
Example #17
0
def test_iter():
    p = Pipe()
    p.side_in.write(b"Hello")
    p.side_in.close()

    riter = iter(p.side_out)

    data = next(riter)
    assert data == b'Hello'

    with pytest.raises(StopIteration):
        next(riter)
Example #18
0
def test_argv_roundtrip(st):
    # This is for the benefit of Windows and other platforms that don't actually
    # pass processes a paramaterized argv
    pi = Pipe()
    proc = Process(runpy(r'import sys; print(sys.argv[1])') + [st],
                   stdout=pi.side_in)
    proc.start()
    data = pi.side_out.readline()
    # Pipe is closed but process might still be live
    proc.join()  # Commenting this out causes data to be None?
    assert proc.return_code == 0
    assert data.rstrip(b'\r\n') == st.encode('ascii')
Example #19
0
def test_change_input():
    p1 = Pipe()
    p2 = Pipe()
    pout = Pipe()
    qc = QuickConnect(side_in=p1.side_out,
                      side_out=pout.side_in,
                      keepopen=False)

    p1.side_in.write(b'spam')
    p2.side_in.write(b'foo')

    time.sleep(1.0)
    qc.side_in = p2.side_out

    p1.side_in.write(b'eggs')
    p2.side_in.write(b'bar')

    p1.side_in.close()
    p2.side_in.close()

    roundtrip = pout.side_out.read()
    assert roundtrip == b'spamfoobar'
Example #20
0
def test_error_output():
    # NOTE: POSIX clears the pipe when a process has non-zero return
    pi = Pipe()
    proc = Process(
        runpy(r'import sys; print("bar", flush=True); sys.exit(42)'),
        stdout=pi.side_in,
    )
    proc.start()
    pi.side_in.close(
    )  # Remove our reference on this end of the pipe, now that the child has one
    proc.join()
    data = pi.side_out.read()
    assert data in (b'bar\n', b'bar\r\n')
Example #21
0
def test_terminated_output():
    # NOTE: POSIX clears the pipe when a process has non-zero return
    pi = Pipe()
    proc = Process(
        runpy(r'print("foo", flush=True); input(); print("bar", flush=True)'),
        stdout=pi.side_in,
    )
    proc.start()
    pi.side_in.close(
    )  # Remove our reference on this end of the pipe, now that the child has one
    proc.terminate()
    proc.join()
    data = pi.side_out.read()
    assert data == b''
Example #22
0
def test_lswc_gh10():
    """
    Tests ls|wc
    """

    # From https://github.com/xonsh/slug/issues/10

    with ProcessGroup() as pg:
        pipe = Pipe()
        pg.add(Process(['ls'], stdout=pipe.side_in))
        pg.add(Process(['wc'], stdin=pipe.side_out))
    pg.start()
    pipe.side_in.close()
    pipe.side_out.close()
    pg.join()
Example #23
0
def test_pause_unpause():
    import time
    pi = Pipe()
    proc = Process(
        runpy('import time\nwhile True: print(time.time(), flush=True)'),
        stdout=pi.side_in,
    )
    proc.start()
    pi.side_in.close(
    )  # Remove our reference on this end of the pipe, now that the child has one

    below = [
        float(ts.decode('utf-8').rstrip('\r\n'))
        for ts in iter_for_time(1, pi.side_out) if ts
    ]
    proc.pause()
    time.sleep(1)
    proc.unpause()
    above = [
        float(ts.decode('utf-8').rstrip('\r\n'))
        for ts in iter_for_time(1, pi.side_out) if ts
    ]
    proc.terminate()

    # We don't have a non-blocking way to flush, so we're just hoping that 1s is
    # enough time to get what was stashed.
    timestamps = below + above

    # Calculate the mean, assume its in the paused area, and calculate the gap
    # in the timestamps from that pause.
    mean = sum(timestamps) / len(timestamps)
    below = [ts for ts in timestamps if ts < mean]
    above = [ts for ts in timestamps if ts > mean]
    pause_begin = max(below)
    pause_end = min(above)
    gap = pause_end - pause_begin
    assert gap > 0.9  # 0.9 for leeway