Home > Software engineering >  Trouble using 'expect' for automatic testing of interative dotnet program
Trouble using 'expect' for automatic testing of interative dotnet program

Time:08-06

I'm working on an automated testing of an interactive script in fsharp, and I'm using brew's version of expect on a osx system. It works with mono's fsharpi, but not with dotnet fsi, and I don't understand the difference. I want to automatize dialogues as

% fsharpi                                            

Microsoft (R) F# Interactive version 11.0.0.0 for F# 5.0
Copyright (c) Microsoft Corporation. All Rights Reserved.

For help type #help;;

> let a = 3;;
val a : int = 3

> let b = 3*a;;
val b : int = 9

> #quit;;

In dotnet fsi, it looks similar

% dotnet fsi

Microsoft (R) F# Interactive version 12.0.0.0 for F# 6.0
Copyright (c) Microsoft Corporation. All Rights Reserved.

For help type #help;;

> let a = 3;;
val a: int = 3

> let b = 3*a;;
val b: int = 9

> #quit;;

except colors are added by default, which can be turned off, and does not seem to be the cause of the problem. The fsharp versions are different, but again, I don't think this is the cause of the problem.

A simplified version of my problem is as follows: My expect script for fsharpi is

#!/usr/bin/expect -df

set timeout -1

# Start fsharp - for some reason, this does not work with dotnet fsi
spawn fsharpi
expect "> "
send -- "let a = 3;;\n"
expect "> "
send -- "let b = 3*a;;\n"
expect "> "
send -- "#quit;;\n"
expect eof

and for dotnet I spawn dotnet fsi instead of fsharpi. I call them testFsharpi.exp and testDotnet.exp. When run as

./testFsharpi.exp > testFsharpi.out >& testFsharpi.dbg  

The content of testFsharpi.out is

spawn fsharpi

Microsoft (R) F# Interactive version 11.0.0.0 for F# 5.0
Copyright (c) Microsoft Corporation. All Rights Reserved.

For help type #help;;

> let a = 3;;
[?1h=[6n[H[2J[1;1H- [1;3H[1;3H[1;3H[1;3H[1;3H[1;3Hlet a = 3;;
val a : int = 3

> [4;3H[4;3H[4;3H[4;3Hlet b = 3*a;;
val b : int = 9

> [7;3H[7;3H[7;3H[7;3H#quit;;
[?1l>[39;49m

and the content of testFsharpi.dbg is

expect version 5.45
argv[0] = /usr/bin/expect  argv[1] = -df  argv[2] = ./testFsharpi.exp  
set argc 0
set argv0 "./testFsharpi.exp"
set argv ""
executing commands from command file ./testFsharpi.exp
spawn fsharpi
parent: waiting for sync byte
parent: telling child to go ahead
parent: now unsynchronized from child
spawn: returns {72534}

expect: does "" (spawn_id exp6) match glob pattern "> "? no

expect: does "
\r\n" (spawn_id exp6) match glob pattern "> "? no

expect: does "\r\nMicrosoft (R) F# Interactive version 11.0.0.0 for F# 5.0" (spawn_id exp6) match glob pattern "> "? Microsoft (R) F# Interactive version 11.0.0.0 for F# 5.0no

expect: does "\r\nMicrosoft (R) F# Interactive version 11.0.0.0 for F# 5.0\r\n" (spawn_id exp6) match glob pattern "> "? no


expect: does "\r\nMicrosoft (R) F# Interactive version 11.0.0.0 for F# 5.0\r\nCopyright (c) Microsoft Corporation. All Rights Reserved." (spawn_id exp6) match glob pattern "> "? no
Copyright (c) Microsoft Corporation. All Rights Reserved.
expect: does "\r\nMicrosoft (R) F# Interactive version 11.0.0.0 for F# 5.0\r\nCopyright (c) Microsoft Corporation. All Rights Reserved.\r\n\r\n" (spawn_id exp6) match glob pattern "> "? no



expect: does "\r\nMicrosoft (R) F# Interactive version 11.0.0.0 for F# 5.0\r\nCopyright (c) Microsoft Corporation. All Rights Reserved.\r\n\r\nFor help type #help;;\r\n" (spawn_id exp6) match glob pattern "> "? no
For help type #help;;

expect: does "\r\nMicrosoft (R) F# Interactive version 11.0.0.0 for F# 5.0\r\nCopyright (c) Microsoft Corporation. All Rights Reserved.\r\n\r\nFor help type #help;;\r\n\r\n" (spawn_id exp6) match glob pattern "> "? no


expect: does "\r\nMicrosoft (R) F# Interactive version 11.0.0.0 for F# 5.0\r\nCopyright (c) Microsoft Corporation. All Rights Reserved.\r\n\r\nFor help type #help;;\r\n\r\n> " (spawn_id exp6) match glob pattern "> "? yes
expect: set expect_out(0,string) "> "
> expect: set expect_out(spawn_id) "exp6"
expect: set expect_out(buffer) "\r\nMicrosoft (R) F# Interactive version 11.0.0.0 for F# 5.0\r\nCopyright (c) Microsoft Corporation. All Rights Reserved.\r\n\r\nFor help type #help;;\r\n\r\n> "
send: sending "let a = 3;;\n" to { exp6 }

expect: does "" (spawn_id exp6) match glob pattern "> "? no

expect: does "let a = 3;;\r\n" (spawn_id exp6) match glob pattern "> "? no
let a = 3;;

expect: does "let a = 3;;\r\n\u001b[?1h\u001b=" (spawn_id exp6) match glob pattern "> "? no
[?1h=
expect: does "let a = 3;;\r\n\u001b[?1h\u001b=\u001b[6n" (spawn_id exp6) match glob pattern [6n"> "? no

expect: does "[H[2Jlet a = 3;;\r\n\u001b[?1h\u001b=\u001b[6n\u001b[H\u001b[2J" (spawn_id exp6) match glob pattern "> "? no

expect: does "[1;1Hlet a = 3;;\r\n\u001b[?1h\u001b=\u001b[6n\u001b[H\u001b[2J\u001b[1;1H" (spawn_id exp6) match glob pattern "> "? no

expect: does "let a = 3;;\r\n\u001b[?1h\u001b=\u001b[6n\u001b[H\u001b[2J\u001b[1;1H- " (spawn_id exp6) match glob pattern "> "? no
- 
expect: does "[1;3Hlet a = 3;;\r\n\u001b[?1h\u001b=\u001b[6n\u001b[H\u001b[2J\u001b[1;1H- \u001b[1;3H" (spawn_id exp6) match glob pattern "> "? no

expect: does "[1;3Hlet a = 3;;\r\n\u001b[?1h\u001b=\u001b[6n\u001b[H\u001b[2J\u001b[1;1H- \u001b[1;3H\u001b[1;3H" (spawn_id exp6) match glob pattern "> "? no

expect: does "let a = 3;;\r\n\u001b[?1h\u001b=\u001b[6n\u001b[H\u001b[2J\u001b[1;1H- \u001b[1;3H\u001b[1;3H\u001b[1;3H" (spawn_id exp6) match glob pattern "> "? no
[1;3H
expect: does "let a = 3;;\r\n\u001b[?1h\u001b=\u001b[6n\u001b[H\u001b[2J\u001b[1;1H- \u001b[1;3H\u001b[1;3H\u001b[1;3H\u001b[1;3H" (spawn_id exp6) match glob pattern "> "? no
[1;3H
expect: does "let a = 3;;\r\n\u001b[?1h\u001b=\u001b[6n\u001b[H\u001b[2J\u001b[1;1H- \u001b[1;3H\u001b[1;3H\u001b[1;3H\u001b[1;3H\u001b[1;3H\u001b[1;3H" (spawn_id exp6) match glob pattern "> "? no
[1;3H[1;3H
expect: does "let a = 3;;\r\n\u001b[?1h\u001b=\u001b[6n\u001b[H\u001b[2J\u001b[1;1H- \u001b[1;3H\u001b[1;3H\u001b[1;3H\u001b[1;3H\u001b[1;3H\u001b[1;3Hl" (spawn_id exp6) match glob pattern "> "? no
l
expect: does "let a = 3;;\r\n\u001b[?1h\u001b=\u001b[6n\u001b[H\u001b[2J\u001b[1;1H- \u001b[1;3H\u001b[1;3H\u001b[1;3H\u001b[1;3H\u001b[1;3H\u001b[1;3Hle" (spawn_id exp6) match glob pattern "e> "? no

expect: does "let a = 3;;\r\n\u001b[?1h\u001b=\u001b[6n\u001b[H\u001b[2J\u001b[1;1H- \u001b[1;3H\u001b[1;3H\u001b[1;3H\u001b[1;3H\u001b[1;3H\u001b[1;3Hlet a = 3;;" (spawn_id exp6) match glob pattern "> "? no
t a = 3;;
expect: does "let a = 3;;\r\n\u001b[?1h\u001b=\u001b[6n\u001b[H\u001b[2J\u001b[1;1H- \u001b[1;3H\u001b[1;3H\u001b[1;3H\u001b[1;3H\u001b[1;3H\u001b[1;3Hlet a = 3;;\r\n" (spawn_id exp6) match glob pattern "> "? 
no

expect: does "let a = 3;;\r\n\u001b[?1h\u001b=\u001b[6n\u001b[H\u001b[2J\u001b[1;1H- \u001b[1;3H\u001b[1;3H\u001b[1;3H\u001b[1;3H\u001b[1;3H\u001b[1;3Hlet a = 3;;\r\nval" (spawn_id exp6) match glob pattern "> "? no
val
expect: does "let a = 3;;\r\n\u001b[?1h\u001b=\u001b[6n\u001b[H\u001b[2J\u001b[1;1H- \u001b[1;3H\u001b[1;3H\u001b[1;3H\u001b[1;3H\u001b[1;3H\u001b[1;3Hlet a = 3;;\r\nval " (spawn_id exp6) match glob pattern "> "? no
 
expect: does "let a = 3;;\r\n\u001b[?1h\u001b=\u001b[6n\u001b[H\u001b[2J\u001b[1;1H- \u001b[1;3H\u001b[1;3H\u001b[1;3H\u001b[1;3H\u001b[1;3H\u001b[1;3Hlet a = 3;;\r\nval a" (spawn_id exp6) match glob pattern "> "? no
a
expect: does " : int = let a = 3;;\r\n\u001b[?1h\u001b=\u001b[6n\u001b[H\u001b[2J\u001b[1;1H- \u001b[1;3H\u001b[1;3H\u001b[1;3H\u001b[1;3H\u001b[1;3H\u001b[1;3Hlet a = 3;;\r\nval a : int = " (spawn_id exp6) match glob pattern "> "? no

expect: does "3let a = 3;;\r\n\u001b[?1h\u001b=\u001b[6n\u001b[H\u001b[2J\u001b[1;1H- \u001b[1;3H\u001b[1;3H\u001b[1;3H\u001b[1;3H\u001b[1;3H\u001b[1;3Hlet a = 3;;\r\nval a : int = 3" (spawn_id exp6) match glob pattern "> "? no

expect: does "let a = 3;;\r\n\u001b[?1h\u001b=\u001b[6n\u001b[H\u001b[2J\u001b[1;1H- \u001b[1;3H\u001b[1;3H\u001b[1;3H\u001b[1;3H\u001b[1;3H\u001b[1;3Hlet a = 3;;\r\nval a : int = 3\r\n" (spawn_id exp6) match glob pattern "> "? no


expect: does "let a = 3;;\r\n\u001b[?1h\u001b=\u001b[6n\u001b[H\u001b[2J\u001b[1;1H- \u001b[1;3H\u001b[1;3H\u001b[1;3H\u001b[1;3H\u001b[1;3H\u001b[1;3Hlet a = 3;;\r\nval a : int = 3\r\n\r\n" (spawn_id exp6) match glob pattern "> "? no


expect: does "> let a = 3;;\r\n\u001b[?1h\u001b=\u001b[6n\u001b[H\u001b[2J\u001b[1;1H- \u001b[1;3H\u001b[1;3H\u001b[1;3H\u001b[1;3H\u001b[1;3H\u001b[1;3Hlet a = 3;;\r\nval a : int = 3\r\n\r\n> " (spawn_id exp6) match glob pattern "> "? yes
expect: set expect_out(0,string) "> "
expect: set expect_out(spawn_id) "exp6"
expect: set expect_out(buffer) "let a = 3;;\r\n\u001b[?1h\u001b=\u001b[6n\u001b[H\u001b[2J\u001b[1;1H- \u001b[1;3H\u001b[1;3H\u001b[1;3H\u001b[1;3H\u001b[1;3H\u001b[1;3Hlet a = 3;;\r\nval a : int = 3\r\n\r\n> "
send: sending "let b = 3*a;;\n" to { exp6 }

expect: does "" (spawn_id exp6) match glob pattern "> "? no

expect: does "\u001b[4;3H\u001b[4;3H\u001b[4;3H\u001b[4;3H" (spawn_id exp6) match glob pattern "> "? no
[4;3H[4;3H[4;3H[4;3H
expect: does "\u001b[4;3H\u001b[4;3H\u001b[4;3H\u001b[4;3Hl" (spawn_id exp6) match glob pattern "> "? no
l
expect: does "\u001b[4;3H\u001b[4;3H\u001b[4;3H\u001b[4;3Hlet b = 3*a;;" (spawn_id exp6) match glob pattern "> "? no
et b = 3*a;;
expect: does "\u001b[4;3H\u001b[4;3H\u001b[4;3H\u001b[4;3Hlet b = 3*a;;\r\n" (spawn_id exp6) match glob pattern "> "? no


expect: does "val \u001b[4;3H\u001b[4;3H\u001b[4;3H\u001b[4;3Hlet b = 3*a;;\r\nval " (spawn_id exp6) match glob pattern "> "? no

expect: does "\u001b[4;3H\u001b[4;3H\u001b[4;3H\u001b[4;3Hlet b = 3*a;;\r\nval b : int = 9" (spawn_id exp6) match glob pattern "> "? no
b : int = 9
expect: does "\u001b[4;3H\u001b[4;3H\u001b[4;3H\u001b[4;3Hlet b = 3*a;;\r\nval b : int = 9\r\n\r\n" (spawn_id exp6) match glob pattern "> "? no



expect: does "\u001b[4;3H\u001b[4;3H\u001b[4;3H\u001b[4;3Hlet b = 3*a;;\r\nval b : int = 9\r\n\r\n> " (spawn_id exp6) match glob pattern "> "? yes
expect: set expect_out(0,string) "> "
> expect: set expect_out(spawn_id) "exp6"
expect: set expect_out(buffer) "\u001b[4;3H\u001b[4;3H\u001b[4;3H\u001b[4;3Hlet b = 3*a;;\r\nval b : int = 9\r\n\r\n> "
send: sending "#quit;;\n" to { exp6 }
[7;3H[7;3H[7;3H[7;3H#quit;;
[?1l>[39;49mexpect: read eof
expect: set expect_out(spawn_id) "exp6"
expect: set expect_out(buffer) "\u001b[7;3H\u001b[7;3H\u001b[7;3H\u001b[7;3H#quit;;\r\n\u001b[?1l\u001b>\u001b[39;49m"

However, when I run testDotnet.exp it enters into an infinite loop. The first part of the output of the debug file is

expect version 5.45
argv[0] = /usr/bin/expect  argv[1] = -df  argv[2] = ./testDotnet.exp  
set argc 0
set argv0 "./testDotnet.exp"
set argv ""
executing commands from command file ./testDotnet.exp
parent: waiting for sync byte
parent: telling child to go ahead
parent: now unsynchronized from child
spawn: returns {72656}

expect: does "" (spawn_id exp6) match glob pattern "> "? no

expect: does "\u001b[?1h\u001b=" (spawn_id exp6) match glob pattern "> "? no

expect: does "\u001b[?1h\u001b=\u001b[?1h\u001b=" (spawn_id exp6) match glob pattern "> "? no

expect: does "\u001b[?1h\u001b=\u001b[?1h\u001b=\r\n" (spawn_id exp6) match glob pattern "> "? no

expect: does "\u001b[?1h\u001b=\u001b[?1h\u001b=\r\nMicrosoft (R) F# Interactive version 12.0.0.0 for F# 6.0\r\n" (spawn_id exp6) match glob pattern "> "? no

expect: does "\u001b[?1h\u001b=\u001b[?1h\u001b=\r\nMicrosoft (R) F# Interactive version 12.0.0.0 for F# 6.0\r\nCopyright (c) Microsoft Corporation. All Rights Reserved.\r\n\r\n" (spawn_id exp6) match glob pattern "> "? no

expect: does "\u001b[?1h\u001b=\u001b[?1h\u001b=\r\nMicrosoft (R) F# Interactive version 12.0.0.0 for F# 6.0\r\nCopyright (c) Microsoft Corporation. All Rights Reserved.\r\n\r\nFor help type #help;;\r\n\r\n" (spawn_id exp6) match glob pattern "> "? no

expect: does "\u001b[?1h\u001b=\u001b[?1h\u001b=\r\nMicrosoft (R) F# Interactive version 12.0.0.0 for F# 6.0\r\nCopyright (c) Microsoft Corporation. All Rights Reserved.\r\n\r\nFor help type #help;;\r\n\r\n> " (spawn_id exp6) match glob pattern "> "? yes
expect: set expect_out(0,string) "> "
expect: set expect_out(spawn_id) "exp6"
expect: set expect_out(buffer) "\u001b[?1h\u001b=\u001b[?1h\u001b=\r\nMicrosoft (R) F# Interactive version 12.0.0.0 for F# 6.0\r\nCopyright (c) Microsoft Corporation. All Rights Reserved.\r\n\r\nFor help type #help;;\r\n\r\n> "
send: sending "let a = 3;;\n" to { exp6 }

expect: does "" (spawn_id exp6) match glob pattern "> "? no

expect: does "let a = 3;;\r\n" (spawn_id exp6) match glob pattern "> "? no

expect: does "let a = 3;;\r\n\u001b[6n" (spawn_id exp6) match glob pattern "> "? no

expect: does "let a = 3;;\r\n\u001b[6n\u001b[6n" (spawn_id exp6) match glob pattern "> "? no

expect: does "let a = 3;;\r\n\u001b[6n\u001b[6n\u001b[1;1H" (spawn_id exp6) match glob pattern "> "? no

expect: does "let a = 3;;\r\n\u001b[6n\u001b[6n\u001b[1;1H- " (spawn_id exp6) match glob pattern "> "? no

expect: does "let a = 3;;\r\n\u001b[6n\u001b[6n\u001b[1;1H- l" (spawn_id exp6) match glob pattern "> "? no

expect: does "let a = 3;;\r\n\u001b[6n\u001b[6n\u001b[1;1H- let " (spawn_id exp6) match glob pattern "> "? no

expect: does "let a = 3;;\r\n\u001b[6n\u001b[6n\u001b[1;1H- let a = 3;;" (spawn_id exp6) match glob pattern "> "? no

expect: does "let a = 3;;\r\n\u001b[6n\u001b[6n\u001b[1;1H- let a = 3;;\r\n" (spawn_id exp6) match glob pattern "> "? no

expect: does "let a = 3;;\r\n\u001b[6n\u001b[6n\u001b[1;1H- let a = 3;;\r\n\u001b[39;49m" (spawn_id exp6) match glob pattern "> "? no

expect: does "let a = 3;;\r\n\u001b[6n\u001b[6n\u001b[1;1H- let a = 3;;\r\n\u001b[39;49m\u001b[97m" (spawn_id exp6) match glob pattern "> "? no

expect: does "let a = 3;;\r\n\u001b[6n\u001b[6n\u001b[1;1H- let a = 3;;\r\n\u001b[39;49m\u001b[97mval\u001b[39;49m" (spawn_id exp6) match glob pattern "> "? no

expect: does "let a = 3;;\r\n\u001b[6n\u001b[6n\u001b[1;1H- let a = 3;;\r\n\u001b[39;49m\u001b[97mval\u001b[39;49m\u001b[39;49m \u001b[39;49m\u001b[39;49ma\u001b[39;49m\u001b[39;49m:\u001b[39;49m\u001b[39;49m \u001b[39;49m\u001b[39;49m\u001b[96mint\u001b[39;49m\u001b[39;49m \u001b[39;49m\u001b[39;49m=\u001b[39;49m\u001b[39;49m \u001b[39;49m\u001b[39;49m\u001b[92m3\u001b[39;49m" (spawn_id exp6) match glob pattern "> "? no

expect: does "let a = 3;;\r\n\u001b[6n\u001b[6n\u001b[1;1H- let a = 3;;\r\n\u001b[39;49m\u001b[97mval\u001b[39;49m\u001b[39;49m \u001b[39;49m\u001b[39;49ma\u001b[39;49m\u001b[39;49m:\u001b[39;49m\u001b[39;49m \u001b[39;49m\u001b[39;49m\u001b[96mint\u001b[39;49m\u001b[39;49m \u001b[39;49m\u001b[39;49m=\u001b[39;49m\u001b[39;49m \u001b[39;49m\u001b[39;49m\u001b[92m3\u001b[39;49m\r\n" (spawn_id exp6) match glob pattern "> "? no

expect: does "let a = 3;;\r\n\u001b[6n\u001b[6n\u001b[1;1H- let a = 3;;\r\n\u001b[39;49m\u001b[97mval\u001b[39;49m\u001b[39;49m \u001b[39;49m\u001b[39;49ma\u001b[39;49m\u001b[39;49m:\u001b[39;49m\u001b[39;49m \u001b[39;49m\u001b[39;49m\u001b[96mint\u001b[39;49m\u001b[39;49m \u001b[39;49m\u001b[39;49m=\u001b[39;49m\u001b[39;49m \u001b[39;49m\u001b[39;49m\u001b[92m3\u001b[39;49m\r\n\r\n" (spawn_id exp6) match glob pattern "> "? no

expect: does "let a = 3;;\r\n\u001b[6n\u001b[6n\u001b[1;1H- let a = 3;;\r\n\u001b[39;49m\u001b[97mval\u001b[39;49m\u001b[39;49m \u001b[39;49m\u001b[39;49ma\u001b[39;49m\u001b[39;49m:\u001b[39;49m\u001b[39;49m \u001b[39;49m\u001b[39;49m\u001b[96mint\u001b[39;49m\u001b[39;49m \u001b[39;49m\u001b[39;49m=\u001b[39;49m\u001b[39;49m \u001b[39;49m\u001b[39;49m\u001b[92m3\u001b[39;49m\r\n\r\n> " (spawn_id exp6) match glob pattern "> "? yes
expect: set expect_out(0,string) "> "
expect: set expect_out(spawn_id) "exp6"
expect: set expect_out(buffer) "let a = 3;;\r\n\u001b[6n\u001b[6n\u001b[1;1H- let a = 3;;\r\n\u001b[39;49m\u001b[97mval\u001b[39;49m\u001b[39;49m \u001b[39;49m\u001b[39;49ma\u001b[39;49m\u001b[39;49m:\u001b[39;49m\u001b[39;49m \u001b[39;49m\u001b[39;49m\u001b[96mint\u001b[39;49m\u001b[39;49m \u001b[39;49m\u001b[39;49m=\u001b[39;49m\u001b[39;49m \u001b[39;49m\u001b[39;49m\u001b[92m3\u001b[39;49m\r\n\r\n> "
send: sending "let b = 3*a;;\n" to { exp6 }

expect: does "" (spawn_id exp6) match glob pattern "> "? no

expect: does "\u001b[6n" (spawn_id exp6) match glob pattern "> "? no

expect: does "\u001b[6n- \u001b[6n" (spawn_id exp6) match glob pattern "> "? no

expect: does "\u001b[6n- \u001b[6n\u001b[6n" (spawn_id exp6) match glob pattern "> "? no

expect: does "\u001b[6n- \u001b[6n\u001b[6n\u001b[1;1H\u001b[1;3H" (spawn_id exp6) match glob pattern "> "? no

expect: does "\u001b[6n- \u001b[6n\u001b[6n\u001b[1;1H\u001b[1;3H\ufffd\u001b[6n" (spawn_id exp6) match glob pattern "> "? no

expect: does "\u001b[6n- \u001b[6n\u001b[6n\u001b[1;1H\u001b[1;3H\ufffd\u001b[6n- \u001b[6n" (spawn_id exp6) match glob pattern "> "? no

expect: does "\u001b[6n- \u001b[6n\u001b[6n\u001b[1;1H\u001b[1;3H\ufffd\u001b[6n- \u001b[6n\u001b[6n" (spawn_id exp6) match glob pattern "> "? no

expect: does "\u001b[6n- \u001b[6n\u001b[6n\u001b[1;1H\u001b[1;3H\ufffd\u001b[6n- \u001b[6n\u001b[6n\u001b[1;1H\u001b[1;3H" (spawn_id exp6) match glob pattern "> "? no

expect: does "\u001b[6n- \u001b[6n\u001b[6n\u001b[1;1H\u001b[1;3H\ufffd\u001b[6n- \u001b[6n\u001b[6n\u001b[1;1H\u001b[1;3H?\ufffd\u001b[6n" (spawn_id exp6) match glob pattern "> "? no

expect: does "\u001b[6n- \u001b[6n\u001b[6n\u001b[1;1H\u001b[1;3H\ufffd\u001b[6n- \u001b[6n\u001b[6n\u001b[1;1H\u001b[1;3H?\ufffd\u001b[6n- \u001b[6n" (spawn_id exp6) match glob pattern "> "? no

expect: does "\u001b[6n- \u001b[6n\u001b[6n\u001b[1;1H\u001b[1;3H\ufffd\u001b[6n- \u001b[6n\u001b[6n\u001b[1;1H\u001b[1;3H?\ufffd\u001b[6n- \u001b[6n\u001b[6n" (spawn_id exp6) match glob pattern "> "? no

expect: does "\u001b[6n- \u001b[6n\u001b[6n\u001b[1;1H\u001b[1;3H\ufffd\u001b[6n- \u001b[6n\u001b[6n\u001b[1;1H\u001b[1;3H?\ufffd\u001b[6n- \u001b[6n\u001b[6n\u001b[1;1H\u001b[1;3H" (spawn_id exp6) match glob pattern "> "? no

expect: does "\u001b[6n- \u001b[6n\u001b[6n\u001b[1;1H\u001b[1;3H\ufffd\u001b[6n- \u001b[6n\u001b[6n\u001b[1;1H\u001b[1;3H?\ufffd\u001b[6n- \u001b[6n\u001b[6n\u001b[1;1H\u001b[1;3H\ufffd\u001b[6n" (spawn_id exp6) match glob pattern "> "? no

expect: does "\u001b[6n- \u001b[6n\u001b[6n\u001b[1;1H\u001b[1;3H\ufffd\u001b[6n- \u001b[6n\u001b[6n\u001b[1;1H\u001b[1;3H?\ufffd\u001b[6n- \u001b[6n\u001b[6n\u001b[1;1H\u001b[1;3H\ufffd\u001b[6n- \u001b[6n" (spawn_id exp6) match glob pattern "> "? no

expect: does "\u001b[6n- \u001b[6n\u001b[6n\u001b[1;1H\u001b[1;3H\ufffd\u001b[6n- \u001b[6n\u001b[6n\u001b[1;1H\u001b[1;3H?\ufffd\u001b[6n- \u001b[6n\u001b[6n\u001b[1;1H\u001b[1;3H\ufffd\u001b[6n- \u001b[6n\u001b[6n" (spawn_id exp6) match glob pattern "> "? no

expect: does "\u001b[6n- \u001b[6n\u001b[6n\u001b[1;1H\u001b[1;3H\ufffd\u001b[6n- \u001b[6n\u001b[6n\u001b[1;1H\u001b[1;3H?\ufffd\u001b[6n- \u001b[6n\u001b[6n\u001b[1;1H\u001b[1;3H\ufffd\u001b[6n- \u001b[6n\u001b[6n\u001b[1;1H\u001b[1;3H" (spawn_id exp6) match glob pattern "> "? no

expect: does "\u001b[6n- \u001b[6n\u001b[6n\u001b[1;1H\u001b[1;3H\ufffd\u001b[6n- \u001b[6n\u001b[6n\u001b[1;1H\u001b[1;3H?\ufffd\u001b[6n- \u001b[6n\u001b[6n\u001b[1;1H\u001b[1;3H\ufffd\u001b[6n- \u001b[6n\u001b[6n\u001b[1;1H\u001b[1;3H\u001b[1;2H" (spawn_id exp6) match glob pattern "> "? no

expect: does "\u001b[6n- \u001b[6n\u001b[6n\u001b[1;1H\u001b[1;3H\ufffd\u001b[6n- \u001b[6n\u001b[6n\u001b[1;1H\u001b[1;3H?\ufffd\u001b[6n- \u001b[6n\u001b[6n\u001b[1;1H\u001b[1;3H\ufffd\u001b[6n- \u001b[6n\u001b[6n\u001b[1;1H\u001b[1;3H\u001b[1;2H\u001b[1;3H\ufffd" (spawn_id exp6) match glob pattern "> "? no

expect: does "\u001b[6n- \u001b[6n\u001b[6n\u001b[1;1H\u001b[1;3H\ufffd\u001b[6n- \u001b[6n\u001b[6n\u001b[1;1H\u001b[1;3H?\ufffd\u001b[6n- \u001b[6n\u001b[6n\u001b[1;1H\u001b[1;3H\ufffd\u001b[6n- \u001b[6n\u001b[6n\u001b[1;1H\u001b[1;3H\u001b[1;2H\u001b[1;3H\ufffd\u001b[6n" (spawn_id exp6) match glob pattern "> "? no

expect: does "\u001b[6n- \u001b[6n\u001b[6n\u001b[1;1H\u001b[1;3H\ufffd\u001b[6n- \u001b[6n\u001b[6n\u001b[1;1H\u001b[1;3H?\ufffd\u001b[6n- \u001b[6n\u001b[6n\u001b[1;1H\u001b[1;3H\ufffd\u001b[6n- \u001b[6n\u001b[6n\u001b[1;1H\u001b[1;3H\u001b[1;2H\u001b[1;3H\ufffd\u001b[6n- \u001b[6n" (spawn_id exp6) match glob pattern "> "? no

expect: does "\u001b[6n- \u001b[6n\u001b[6n\u001b[1;1H\u001b[1;3H\ufffd\u001b[6n- \u001b[6n\u001b[6n\u001b[1;1H\u001b[1;3H?\ufffd\u001b[6n- \u001b[6n\u001b[6n\u001b[1;1H\u001b[1;3H\ufffd\u001b[6n- \u001b[6n\u001b[6n\u001b[1;1H\u001b[1;3H\u001b[1;2H\u001b[1;3H\ufffd\u001b[6n- \u001b[6n\u001b[6n" (spawn_id exp6) match glob pattern "> "? no

expect: does "\u001b[6n- \u001b[6n\u001b[6n\u001b[1;1H\u001b[1;3H\ufffd\u001b[6n- \u001b[6n\u001b[6n\u001b[1;1H\u001b[1;3H?\ufffd\u001b[6n- \u001b[6n\u001b[6n\u001b[1;1H\u001b[1;3H\ufffd\u001b[6n- \u001b[6n\u001b[6n\u001b[1;1H\u001b[1;3H\u001b[1;2H\u001b[1;3H\ufffd\u001b[6n- \u001b[6n\u001b[6n\u001b[1;1H\u001b[1;3H?\ufffd\u001b[6n" (spawn_id exp6) match glob pattern "> "? no
^C

I don't understand why it works in one but not the other program. I have tried inserting sleeps and send_slow with no effects. Any ideas?

Thanks, Jon

CodePudding user response:

A friend of mine came up with the solution. For dotnet fsi, I must spawn with

spawn dotnet fsi --readline-

For completeness sake, my expect script in the end is

#!/usr/bin/expect -df

set timeout -1

# Start the fsharp interpreter
spawn dotnet fsi --readline- --consolecolors-
expect "> "
# enter commands and exit
send -- "let a = 3;;\n"
expect "> "
send -- "let b = 3*a;;\n"
expect "> "
send -- "#quit;;\n"
expect eof

Thanks, everybody

CodePudding user response:

(Not a direct answer. Just FYI.)

The sequence \u001b[6n (ESC [ 6 n) in the debug output indicates dotnet fsi is requesting the tty's current cursor position. The ESC [ 6 n sequence is called CPR (cursor position report).

This is what happens when you manually interact with dotnet fsi:

  1. After dotnet fsi prints the prompt > it requests the cursor position by printing ESC [ 6 n to the tty. And then it'll wait for the CPR result.
  2. When the tty receives the CPR request, it'll send the CPR result (ESC [ row ; col R) back to the tty's input buffer.
  3. Then dotnet fsi gets the CPR result and continue reading user's input.

When Expect is involved, the CPR result is actually got by Expect so Expect should read the CPR result and "forward" it to dotnet fsi, otherwise dotnet fsi will keep waiting (not sure if it has a timeout mechanism).


I'll use my sexpect to demo how to make it work --

The script automate-dotnet-fsi.sh:

wait_prompt()
{
    local rep

    sexpect expect -re $'[\r\n]> \033\\[6n'
    #                            ^^^^^^^^^

    # ESC [ row ; col R
    read -r -d R rep
    # forward CPR to the spawned process
    sexpect send "${rep}R"
}

trap 'stty echo' EXIT
stty -echo

export SEXPECT_SOCKFILE=/tmp/dotnet-fsi-$$.sock
sexpect spawn dotnet fsi
wait_prompt

sexpect send -cr 'let a = 3;;'
wait_prompt

sexpect send -cr '#quit;;'
sexpect wait

Result (tested on macos):

$ bash automate-dotnet-fsi.sh

Microsoft (R) F# Interactive version 12.0.4.0 for F# 6.0
Copyright (c) Microsoft Corporation. All Rights Reserved.

For help type #help;;

> let a = 3;;
val a: int = 3

> #quit;;
  • Related