On Thu, May 31, 2007 at 12:27:24PM +0100, Brian Candler wrote:
> I've noticed what appears to be an inconsistency in the behaviour of
> Net::Telnet's waitfor() method.
> 
> If a timeout occurs while waiting for a match, a TimeoutError is raised (and
> any data received so far is lost).
> 
> However, if the remote end disconnects while waiting for a match, no error
> is generated, and the data received so far is returned. It explicitly
> rescues EOFError to do this.
> 
> This leads to difficult usage, because if you do
> 
>     @telnet.waitfor(/prompt/)
> 
> and it returns, it could mean one of two things: either the string you were
> waiting for was matched, or it wasn't matched and the far end disconnected.
> The first is what you expect, and the second is likely to be an error
> condition.
> 
> So I find that every waitfor call has to be wrapped, e.g.
> 
>     res = @telnet.waitfor(/prompt/)
>     unless /prompt/ =~ res
>       raise EOFError  # or handle this situation some other way
>     end

And for that matter, IO#expect isn't much better behaved, in that it raises
a NoMethodError.

Here's a program which demonstrates both:

----- 8< -------------------------------------------------------------
require 'socket'

server = TCPServer.new("127.0.0.1", nil)
port = server.addr[1]

st = Thread.new do
  while socket = server.accept
    Thread.new(socket) do |s|
      s.puts "abcde"
      s.close
    end
  end
end

# Version using Net::Telnet
require 'net/telnet'
client = Net::Telnet.new("Host"=>"127.0.0.1", "Port"=>port)
res = client.waitfor(/f/)
puts res  # returns successfully, even though no match

# Version using IO#expect
require 'expect'
client = TCPSocket.new("127.0.0.1", port)
client.expect(/f/) # undefined method `chr' for nil:NilClass (NoMethodError)

----- 8< -------------------------------------------------------------

This was tested with 1.8.4 under Ubuntu 6.06, but IO#expect appears to be
identical in trunk:
http://svn.ruby-lang.org/cgi-bin/viewvc.cgi/trunk/ext/pty/lib/expect.rb?view=markup
and Net::Telnet has only one minor change, to remove #{NULL} from the
stream.

Regards,

Brian.