summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--ChangeLog8
-rw-r--r--lib/net/imap.rb24
-rw-r--r--test/net/imap/test_imap.rb94
3 files changed, 116 insertions, 10 deletions
diff --git a/ChangeLog b/ChangeLog
index 2a5d02a08c..2acb49c09b 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,11 @@
+Fri Jul 24 18:03:01 2009 Shugo Maeda <shugo@ruby-lang.org>
+
+ * lib/net/imap.rb (idle): leaves IDLE in a ensure clause. a patch
+ from Eric Hodel.
+
+ * test/net/imap/test_imap.rb (setup, teardown): turn on
+ Socket.do_not_reverse_lookup in tests.
+
Fri Jul 24 00:13:41 2009 Shugo Maeda <shugo@ruby-lang.org>
* lib/net/imap.rb (resp_text_code): accepts response codes without
diff --git a/lib/net/imap.rb b/lib/net/imap.rb
index 5741568034..8b7529d79d 100644
--- a/lib/net/imap.rb
+++ b/lib/net/imap.rb
@@ -851,13 +851,16 @@ module Net
tag = Thread.current[:net_imap_tag] = generate_tag
put_string("#{tag} IDLE#{CRLF}")
- add_response_handler(response_handler)
- @idle_done_cond = new_cond
- @idle_done_cond.wait
- @idle_done_cond = nil
- remove_response_handler(response_handler)
- put_string("DONE#{CRLF}")
- response = get_tagged_response(tag, "IDLE")
+ begin
+ add_response_handler(response_handler)
+ @idle_done_cond = new_cond
+ @idle_done_cond.wait
+ @idle_done_cond = nil
+ ensure
+ remove_response_handler(response_handler)
+ put_string("DONE#{CRLF}")
+ response = get_tagged_response(tag, "IDLE")
+ end
end
return response
@@ -865,10 +868,10 @@ module Net
# Leaves IDLE.
def idle_done
- if @idle_done_cond.nil?
- raise Net::IMAP::Error, "not during IDLE"
- end
synchronize do
+ if @idle_done_cond.nil?
+ raise Net::IMAP::Error, "not during IDLE"
+ end
@idle_done_cond.signal
end
end
@@ -985,6 +988,7 @@ module Net
@response_handlers = []
@tagged_response_arrival = new_cond
@continuation_request_arrival = new_cond
+ @idle_done_cond = nil
@logout_command_tag = nil
@debug_output_bol = true
@exception = nil
diff --git a/test/net/imap/test_imap.rb b/test/net/imap/test_imap.rb
index e4e1c25ca0..882487881d 100644
--- a/test/net/imap/test_imap.rb
+++ b/test/net/imap/test_imap.rb
@@ -6,6 +6,15 @@ class IMAPTest < Test::Unit::TestCase
SERVER_KEY = File.expand_path("server.key", File.dirname(__FILE__))
SERVER_CERT = File.expand_path("server.crt", File.dirname(__FILE__))
+ def setup
+ @do_not_reverse_lookup = Socket.do_not_reverse_lookup
+ Socket.do_not_reverse_lookup = true
+ end
+
+ def teardown
+ Socket.do_not_reverse_lookup = @do_not_reverse_lookup
+ end
+
def test_encode_utf7
utf8 = "\357\274\241\357\274\242\357\274\243".force_encoding("UTF-8")
s = Net::IMAP.encode_utf7(utf8)
@@ -176,6 +185,91 @@ class IMAPTest < Test::Unit::TestCase
end
end
+ def test_exception_during_idle
+ server = TCPServer.new(0)
+ port = server.addr[1]
+ requests = []
+ Thread.start do
+ begin
+ sock = server.accept
+ begin
+ sock.print("* OK test server\r\n")
+ requests.push(sock.gets)
+ sock.print("+ idling\r\n")
+ sock.print("* 3 EXISTS\r\n")
+ sock.print("* 2 EXPUNGE\r\n")
+ requests.push(sock.gets)
+ sock.print("RUBY0001 OK IDLE terminated\r\n")
+ sock.gets
+ sock.print("* BYE terminating connection\r\n")
+ sock.print("RUBY0002 OK LOGOUT completed\r\n")
+ ensure
+ sock.close
+ end
+ rescue
+ end
+ end
+ begin
+ begin
+ imap = Net::IMAP.new("localhost", :port => port)
+ begin
+ th = Thread.current
+ m = Monitor.new
+ c = m.new_cond
+ Thread.start do
+ m.synchronize do
+ c.wait
+ end
+ th.raise(Interrupt)
+ end
+ imap.idle do |res|
+ m.synchronize do
+ c.signal
+ end
+ end
+ rescue Interrupt
+ end
+ assert_equal(2, requests.length)
+ assert_equal("RUBY0001 IDLE\r\n", requests[0])
+ assert_equal("DONE\r\n", requests[1])
+ imap.logout
+ ensure
+ imap.disconnect if imap
+ end
+ ensure
+ server.close
+ end
+ end
+
+ def test_idle_done_not_during_idle
+ server = TCPServer.new(0)
+ port = server.addr[1]
+ requests = []
+ Thread.start do
+ begin
+ sock = server.accept
+ begin
+ sock.print("* OK test server\r\n")
+ ensure
+ sock.close
+ end
+ rescue
+ end
+ end
+ begin
+ begin
+ imap = Net::IMAP.new("localhost", :port => port)
+ assert_raise(Net::IMAP::Error) do
+ imap.idle_done
+ end
+ ensure
+ imap.disconnect if imap
+ end
+ ensure
+ server.close
+ end
+ end
+
private
def imaps_test