Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

test failure on FreeBSD #12

Closed
emaste opened this issue Mar 23, 2015 · 5 comments
Closed

test failure on FreeBSD #12

emaste opened this issue Mar 23, 2015 · 5 comments
Assignees

Comments

@emaste
Copy link

emaste commented Mar 23, 2015

Running the tests on FreeBSD 11 I see:

% py.test  
============================= test session starts ==============================
platform freebsd11 -- Python 2.7.9 -- py-1.4.26 -- pytest-2.6.4
collected 5 items 

tests/test_invalid_binary.py .
tests/test_preexec_fn.py ..
tests/test_spawn.py FF


=================================== FAILURES ===================================
__________________________ PtyTestCase.test_spawn_sh ___________________________

self = <tests.test_spawn.PtyTestCase testMethod=test_spawn_sh>

    def test_spawn_sh(self):
        env = os.environ.copy()
        env['FOO'] = 'rebar'
        p = PtyProcess.spawn(['sh'], env=env)
        p.read()
        p.write(b'echo $FOO\n')
        time.sleep(0.1)
        response = p.read()
>       assert b'rebar' in response
E       AssertionError: assert 'rebar' in 'echo $FOO\r\n'

tests/test_spawn.py:15: AssertionError
______________________ PtyTestCase.test_spawn_unicode_sh _______________________

self = <tests.test_spawn.PtyTestCase testMethod=test_spawn_unicode_sh>

    def test_spawn_unicode_sh(self):
        env = os.environ.copy()
        env['FOO'] = 'rebar'
        p = PtyProcessUnicode.spawn(['sh'], env=env)
        p.read()
        p.write(u'echo $FOO\n')
        time.sleep(0.1)
        response = p.read()
>       assert u'rebar' in response
\n'     AssertionError: assert 'rebar' in 'echo $FOO

tests/test_spawn.py:31: AssertionError
====================== 2 failed, 3 passed in 0.80 seconds ======================

The expected output is produced, it is just not returned by the second p.read() in the test. Inserting a dummy p.read() before response = p.read() gets the tests passing.

@jquast jquast added the bug label Apr 14, 2015
jquast added a commit to pexpect/pexpect that referenced this issue Apr 26, 2015
This is to support testing for FreeBSD in particular,
for issue pexpect/ptyprocess#12
@jquast
Copy link
Member

jquast commented Apr 26, 2015

I was not running tests on FreeBSD (10-Release) for ptyprocess (even though we do for pexpect). Addressing this now and we'll see how the tests do -- thanks for noticing!

@jquast
Copy link
Member

jquast commented Apr 26, 2015

Awesome find: it reproduces. I will address it, thanks @emaste !

@jquast jquast self-assigned this Apr 26, 2015
@jquast
Copy link
Member

jquast commented Apr 26, 2015

Strange enough, output is seen three times with /bin/sh through ptyprocess.

We would expect it once for input (echo=True by default), and a second time for output. I'm not sure yet what is happening.

/bin/sh

In [8]: p = ptyprocess.PtyProcess.spawn(['sh'])

In [9]: p.write('echo HELLO; exit 0\n')
Out[9]: 19L

In [10]: p.read()
Out[10]: '(ptyprocess)[\\u@freebsd /home/freebsd/Code/ptyprocess]$ echo HELLO; exit 0\r\n'

In [11]: p.read()
Out[11]: 'echo HELLO; exit 0\r\n'

In [12]: p.read()
Out[12]: 'HELLO\r\n'

In [13]: p.read()
---------------------------------------------------------------------------
EOFError                                  Traceback (most recent call last)
<ipython-input-13-3cef27ad5fc2> in <module>()
----> 1 p.read()

/usr/home/freebsd/Code/ptyprocess/ptyprocess/ptyprocess.pyc in read(self, size)
    520             # BSD-style EOF (also appears to work on recent Solaris (OpenIndiana))
    521             self.flag_eof = True
--> 522             raise EOFError('End Of File (EOF). Empty string style platform.')
    523
    524         return s

EOFError: End Of File (EOF). Empty string style platform.

bash

In [2]: p = ptyprocess.PtyProcess.spawn(['bash'])

In [3]: p.write('echo HELLO; exit 0\n')
Out[3]: 19L

In [4]: p.read()
Out[4]: '(ptyprocess)[freebsd@freebsd ~/Code/ptyprocess]$ echo HELLO; exit 0\r\n'

In [5]: p.read()
Out[5]: 'HELLO\r\nexit\r\n'

In [6]: p.read()
---------------------------------------------------------------------------
EOFError                                  Traceback (most recent call last)
<ipython-input-6-3cef27ad5fc2> in <module>()
----> 1 p.read()

/usr/home/freebsd/Code/ptyprocess/ptyprocess/ptyprocess.pyc in read(self, size)
    520             # BSD-style EOF (also appears to work on recent Solaris (OpenIndiana))
    521             self.flag_eof = True
--> 522             raise EOFError('End Of File (EOF). Empty string style platform.')
    523
    524         return s

EOFError: End Of File (EOF). Empty string style platform.

@jquast
Copy link
Member

jquast commented Apr 26, 2015

This is very strange. It is some form of a race condition that is particular with the AT&T shell supplied by FreeBSD. I'm going to just write some kind of workaround for the test case: I don't believe it exposes any actual bug with ptyprocess.

Triggered on 2nd call:

$ while [ 0 ]; do python /tmp/test_freebsd.py | grep '^-stty' && break || echo -n '.'; done
.-stty -a; TEST=1; echo $TEST; echo $FOO; exit 0

Triggered on 81st call:

$ while [ 0 ]; do python /tmp/test_freebsd.py | grep '^-stty' && break || echo -n '.'; done
.................................................................................-stty -a; TEST=1; echo $TEST; echo $FOO; exit 0

test_freebsd.py is:

    from __future__ import print_function
    import difflib
    from ptyprocess.ptyprocess import PtyProcess

    cmd = 'stty -a; TEST=1; echo $TEST; echo $FOO; exit 0\n'
    env = {'PS1': '\$ ', 'FOO': 'bar'}
    def get_out(proc):
        out = ''
        while True:
            try:
               out += proc.read()
            except EOFError:
               return out

    bash = PtyProcess.spawn(['bash'], env=env, cwd='/')
    bash.write(cmd)
    out_bash = get_out(bash)

    attsh = PtyProcess.spawn(['sh'], env=env, cwd='/')
    attsh.write(cmd)
    out_attsh = get_out(attsh)

    map(print, difflib.unified_diff(
        out_attsh.splitlines(),
        out_bash.splitlines(),
        fromfile='AT&T compatible shell',
        tofile='bourne-again shell'))

There is something I am not able to understand about /bin/sh on freebsd: This is actually some kind of "second output of input echo" that occurs only with the AT&T-compatible /bin/sh on FreeBSD, and intermittently (a modified version of the test runs forever on OSX and Linux).

@jquast jquast removed the bug label Apr 26, 2015
jquast added a commit that referenced this issue Apr 26, 2015
There is something I am not able to understand about /bin/sh
on freebsd: This is actually some kind of "second output of
input echo" that occurs only with the AT&T-compatible /bin/sh
on FreeBSD, and intermittently (a modified version of the test
runs forever on OSX and Linux).

Complete analysis is in issue #12,
#12 (comment)
@jquast
Copy link
Member

jquast commented Apr 27, 2015

Closed by #20, new ptyprocess should come shortly.

@jquast jquast closed this as completed Apr 27, 2015
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants