• does tcltest have smth like exec's -ignorestderr?

    From Petro Kazmirchuk@21:1/5 to All on Wed Nov 23 03:24:07 2022
    I have a number of tests that spawn a child process - it is a binary outside my control. I'm using processman::spawn, but it could easily be just 'exec'.
    This process prints something to stderr.
    While I was using -singleproc 1, this wasn't a problem. However, later I realized that in this mode, global variables created by one .test script will be inherited by other .test scripts. So, I decided to switch to -singleproc 0 (that is the default
    anyway). And suddenly I end up with test reports like this:

    Test file error: <stderr output from my child process>
    ...
    Tests ended at Wed Nov 23 11:30:44 CET 2022
    all.tcl: Total 9 Passed 9 Skipped 0 Failed 0 Sourced 1 Test Files.
    Test files exiting with errors:
    pubsub.test
    also $? is 1.
    So, tcltest believes that some tests failed just because they happen to print something to stderr!
    I looked in the source code, and it doesn't look like I can configure this behaviour, because in essence it is:
    if {!$singleProcess} {
    catch { open shell } error

    So, apparently 'open' throws an error and then catch's handler counts the test as failed.

    could somebody point me to how I can avoid this?
    thanks in advance

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Ralf Fassel@21:1/5 to All on Wed Nov 23 12:29:25 2022
    * Petro Kazmirchuk <petro.kazmirchuk@gmail.com>
    | So, tcltest believes that some tests failed just because they happen to print something to stderr!
    | I looked in the source code, and it doesn't look like I can configure this behaviour, because in essence it is:
    | if {!$singleProcess} {
    | catch { open shell } error

    | So, apparently 'open' throws an error and then catch's handler counts the test as failed.

    I expect rather the 'close' call for the pipe to fail if there is output
    on stderr.

    | could somebody point me to how I can avoid this?

    Redirect stderr to some file, and inspect that file if the process
    really fails (i.e. errorCode = childStatus)? Clumsy, I know...

    R'

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Petro Kazmirchuk@21:1/5 to All on Wed Nov 23 05:49:00 2022
    sorry, ofc you're right, it's 'close' that throws the error
    well, I don't *really* need to see stderr (it would be nice to have though), so I'll just redirect it to /dev/null

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Emiliano =?ISO-8859-1?Q?Gavil=E1n?=@21:1/5 to Petro Kazmirchuk on Thu Nov 24 20:04:23 2022
    On Wed, 23 Nov 2022 03:24:07 -0800 (PST)
    Petro Kazmirchuk <petro.kazmirchuk@gmail.com> wrote:

    I have a number of tests that spawn a child process - it is a binary outside my control. I'm using processman::spawn, but it could easily be just 'exec'.
    This process prints something to stderr.
    While I was using -singleproc 1, this wasn't a problem. However, later I realized that in this mode, global variables created by one .test script will be inherited by other .test scripts. So, I decided to switch to -singleproc 0 (that is the default
    anyway). And suddenly I end up with test reports like this:

    Test file error: <stderr output from my child process>
    ...
    Tests ended at Wed Nov 23 11:30:44 CET 2022
    all.tcl: Total 9 Passed 9 Skipped 0 Failed 0 Sourced 1 Test Files.
    Test files exiting with errors:
    pubsub.test
    also $? is 1.
    So, tcltest believes that some tests failed just because they happen to print something to stderr!
    I looked in the source code, and it doesn't look like I can configure this behaviour, because in essence it is:
    if {!$singleProcess} {
    catch { open shell } error

    So, apparently 'open' throws an error and then catch's handler counts the test as failed.

    could somebody point me to how I can avoid this?
    thanks in advance

    You can get stdout and stderr from the child process using [chan pipe].
    The magic incantation is

    lassign [chan pipe] ir iw
    lassign [chan pipe] er ew
    exec {*}[list $progname $param1 $param2 ...] >@ $iw 2>@ $ew
    chan close $iw
    chan close $ew

    Now you can use either [chan read] or [chan gets] to get the child process
    data from $ir and $er handlers.

    Regards

    --
    Emiliano Gavilán

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Ralf Fassel@21:1/5 to All on Fri Nov 25 11:30:22 2022
    * Emiliano Gavilán <emilianogavilan@gmail.com>
    | You can get stdout and stderr from the child process using [chan pipe].
    | The magic incantation is

    | lassign [chan pipe] ir iw
    | lassign [chan pipe] er ew
    | exec {*}[list $progname $param1 $param2 ...] >@ $iw 2>@ $ew
    | chan close $iw
    | chan close $ew

    | Now you can use either [chan read] or [chan gets] to get the child process
    | data from $ir and $er handlers.

    Cool trick, thanks for pointing that out!

    However, if large amount of data is produced (notably more than the OS
    pipes buffer) there is a chance of deadlock here, since TCL waits for
    the 'exec' to finish, while the exec'd process might be blocked waiting
    for the pipe to be read, no? (I think this could be avoided by using
    [open |$cmd 2>@...] with only the pipe for stderr.)

    R'

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Emiliano Gavilan@21:1/5 to Ralf Fassel on Mon Nov 28 10:51:46 2022
    On Fri, 25 Nov 2022 11:30:22 +0100
    Ralf Fassel <ralfixx@gmx.de> wrote:

    * Emiliano Gavilán
    | You can get stdout and stderr from the child process using [chan pipe].
    | The magic incantation is

    | lassign [chan pipe] ir iw
    | lassign [chan pipe] er ew
    | exec {*}[list $progname $param1 $param2 ...] >@ $iw 2>@ $ew
    | chan close $iw
    | chan close $ew

    | Now you can use either [chan read] or [chan gets] to get the child process | data from $ir and $er handlers.

    Cool trick, thanks for pointing that out!

    However, if large amount of data is produced (notably more than the OS
    pipes buffer) there is a chance of deadlock here, since TCL waits for
    the 'exec' to finish, while the exec'd process might be blocked waiting
    for the pipe to be read, no? (I think this could be avoided by using
    [open |$cmd 2>@...] with only the pipe for stderr.)

    You can launch the child process in the background adding a trailing "&"
    to the [exec] line.

    - exec {*}[list $progname $param1 $param2 ...] >@ $iw 2>@ $ew
    + exec {*}[list $progname $param1 $param2 ...] >@ $iw 2>@ $ew &

    This also allows for [chan event] to be used for both $ir and $er.

    You can find more details on using [chan pipe] in the tip itself

    https://core.tcl-lang.org/tips/doc/trunk/tip/304.md

    and in the wiki

    https://wiki.tcl-lang.org/page/chan+pipe

    Regards

    --
    Emiliano Gavilan

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)