summaryrefslogtreecommitdiff
path: root/test/net/imap/test_imap.rb
diff options
context:
space:
mode:
Diffstat (limited to 'test/net/imap/test_imap.rb')
-rw-r--r--test/net/imap/test_imap.rb844
1 files changed, 0 insertions, 844 deletions
diff --git a/test/net/imap/test_imap.rb b/test/net/imap/test_imap.rb
deleted file mode 100644
index 8b924b524e..0000000000
--- a/test/net/imap/test_imap.rb
+++ /dev/null
@@ -1,844 +0,0 @@
-# frozen_string_literal: true
-
-require "net/imap"
-require "test/unit"
-
-class IMAPTest < Test::Unit::TestCase
- CA_FILE = File.expand_path("../fixtures/cacert.pem", __dir__)
- SERVER_KEY = File.expand_path("../fixtures/server.key", __dir__)
- SERVER_CERT = File.expand_path("../fixtures/server.crt", __dir__)
-
- def setup
- @do_not_reverse_lookup = Socket.do_not_reverse_lookup
- Socket.do_not_reverse_lookup = true
- @threads = []
- end
-
- def teardown
- if !@threads.empty?
- assert_join_threads(@threads)
- end
- ensure
- Socket.do_not_reverse_lookup = @do_not_reverse_lookup
- end
-
- def test_encode_utf7
- assert_equal("foo", Net::IMAP.encode_utf7("foo"))
- assert_equal("&-", Net::IMAP.encode_utf7("&"))
-
- utf8 = "\357\274\241\357\274\242\357\274\243".dup.force_encoding("UTF-8")
- s = Net::IMAP.encode_utf7(utf8)
- assert_equal("&,yH,Iv8j-", s)
- s = Net::IMAP.encode_utf7("foo&#{utf8}-bar".encode("EUC-JP"))
- assert_equal("foo&-&,yH,Iv8j--bar", s)
-
- utf8 = "\343\201\202&".dup.force_encoding("UTF-8")
- s = Net::IMAP.encode_utf7(utf8)
- assert_equal("&MEI-&-", s)
- s = Net::IMAP.encode_utf7(utf8.encode("EUC-JP"))
- assert_equal("&MEI-&-", s)
- end
-
- def test_decode_utf7
- assert_equal("&", Net::IMAP.decode_utf7("&-"))
- assert_equal("&-", Net::IMAP.decode_utf7("&--"))
-
- s = Net::IMAP.decode_utf7("&,yH,Iv8j-")
- utf8 = "\357\274\241\357\274\242\357\274\243".dup.force_encoding("UTF-8")
- assert_equal(utf8, s)
- end
-
- def test_format_date
- time = Time.mktime(2009, 7, 24)
- s = Net::IMAP.format_date(time)
- assert_equal("24-Jul-2009", s)
- end
-
- def test_format_datetime
- time = Time.mktime(2009, 7, 24, 1, 23, 45)
- s = Net::IMAP.format_datetime(time)
- assert_match(/\A24-Jul-2009 01:23 [+\-]\d{4}\z/, s)
- end
-
- if defined?(OpenSSL::SSL::SSLError)
- def test_imaps_unknown_ca
- assert_raise(OpenSSL::SSL::SSLError) do
- imaps_test do |port|
- begin
- Net::IMAP.new("localhost",
- :port => port,
- :ssl => true)
- rescue SystemCallError
- skip $!
- end
- end
- end
- end
-
- def test_imaps_with_ca_file
- assert_nothing_raised do
- imaps_test do |port|
- begin
- Net::IMAP.new("localhost",
- :port => port,
- :ssl => { :ca_file => CA_FILE })
- rescue SystemCallError
- skip $!
- end
- end
- end
- end
-
- def test_imaps_verify_none
- assert_nothing_raised do
- imaps_test do |port|
- Net::IMAP.new(server_addr,
- :port => port,
- :ssl => { :verify_mode => OpenSSL::SSL::VERIFY_NONE })
- end
- end
- end
-
- def test_imaps_post_connection_check
- assert_raise(OpenSSL::SSL::SSLError) do
- imaps_test do |port|
- # server_addr is different from the hostname in the certificate,
- # so the following code should raise a SSLError.
- Net::IMAP.new(server_addr,
- :port => port,
- :ssl => { :ca_file => CA_FILE })
- end
- end
- end
- end
-
- if defined?(OpenSSL::SSL)
- def test_starttls
- imap = nil
- starttls_test do |port|
- imap = Net::IMAP.new("localhost", :port => port)
- imap.starttls(:ca_file => CA_FILE)
- imap
- end
- rescue SystemCallError
- skip $!
- ensure
- if imap && !imap.disconnected?
- imap.disconnect
- end
- end
- end
-
- def start_server
- th = Thread.new do
- yield
- end
- @threads << th
- sleep 0.1 until th.stop?
- end
-
- def test_unexpected_eof
- server = create_tcp_server
- port = server.addr[1]
- start_server do
- sock = server.accept
- begin
- sock.print("* OK test server\r\n")
- sock.gets
-# sock.print("* BYE terminating connection\r\n")
-# sock.print("RUBY0001 OK LOGOUT completed\r\n")
- ensure
- sock.close
- server.close
- end
- end
- begin
- imap = Net::IMAP.new(server_addr, :port => port)
- assert_raise(EOFError) do
- imap.logout
- end
- ensure
- imap.disconnect if imap
- end
- end
-
- def test_idle
- server = create_tcp_server
- port = server.addr[1]
- requests = []
- start_server do
- 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
- server.close
- end
- end
-
- begin
- imap = Net::IMAP.new(server_addr, :port => port)
- responses = []
- imap.idle do |res|
- responses.push(res)
- if res.name == "EXPUNGE"
- imap.idle_done
- end
- end
- assert_equal(3, responses.length)
- assert_instance_of(Net::IMAP::ContinuationRequest, responses[0])
- assert_equal("EXISTS", responses[1].name)
- assert_equal(3, responses[1].data)
- assert_equal("EXPUNGE", responses[2].name)
- assert_equal(2, responses[2].data)
- 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
- end
-
- def test_exception_during_idle
- server = create_tcp_server
- port = server.addr[1]
- requests = []
- start_server do
- 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
- server.close
- end
- end
- begin
- imap = Net::IMAP.new(server_addr, :port => port)
- begin
- th = Thread.current
- m = Monitor.new
- in_idle = false
- exception_raised = false
- c = m.new_cond
- raiser = Thread.start do
- m.synchronize do
- until in_idle
- c.wait(0.1)
- end
- end
- th.raise(Interrupt)
- m.synchronize do
- exception_raised = true
- c.signal
- end
- end
- @threads << raiser
- imap.idle do |res|
- m.synchronize do
- in_idle = true
- c.signal
- until exception_raised
- c.wait(0.1)
- end
- 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
- raiser.kill unless in_idle
- end
- end
-
- def test_idle_done_not_during_idle
- server = create_tcp_server
- port = server.addr[1]
- start_server do
- sock = server.accept
- begin
- sock.print("* OK test server\r\n")
- ensure
- sock.close
- server.close
- end
- end
- begin
- imap = Net::IMAP.new(server_addr, :port => port)
- assert_raise(Net::IMAP::Error) do
- imap.idle_done
- end
- ensure
- imap.disconnect if imap
- end
- end
-
- def test_idle_timeout
- server = create_tcp_server
- port = server.addr[1]
- requests = []
- start_server do
- 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
- server.close
- end
- end
-
- begin
- imap = Net::IMAP.new(server_addr, :port => port)
- responses = []
- Thread.pass
- imap.idle(0.2) do |res|
- responses.push(res)
- end
- # There is no guarantee that this thread has received all the responses,
- # so check the response length.
- if responses.length > 0
- assert_instance_of(Net::IMAP::ContinuationRequest, responses[0])
- if responses.length > 1
- assert_equal("EXISTS", responses[1].name)
- assert_equal(3, responses[1].data)
- if responses.length > 2
- assert_equal("EXPUNGE", responses[2].name)
- assert_equal(2, responses[2].data)
- end
- end
- end
- # Also, there is no guarantee that the server thread has stored
- # all the requests into the array, so check the length.
- if requests.length > 0
- assert_equal("RUBY0001 IDLE\r\n", requests[0])
- if requests.length > 1
- assert_equal("DONE\r\n", requests[1])
- end
- end
- imap.logout
- ensure
- imap.disconnect if imap
- end
- end
-
- def test_unexpected_bye
- server = create_tcp_server
- port = server.addr[1]
- start_server do
- sock = server.accept
- begin
- sock.print("* OK Gimap ready for requests from 75.101.246.151 33if2752585qyk.26\r\n")
- sock.gets
- sock.print("* BYE System Error 33if2752585qyk.26\r\n")
- ensure
- sock.close
- server.close
- end
- end
- begin
- imap = Net::IMAP.new(server_addr, :port => port)
- assert_raise(Net::IMAP::ByeResponseError) do
- imap.login("user", "password")
- end
- end
- end
-
- def test_exception_during_shutdown
- server = create_tcp_server
- port = server.addr[1]
- start_server do
- sock = server.accept
- begin
- sock.print("* OK test server\r\n")
- sock.gets
- sock.print("* BYE terminating connection\r\n")
- sock.print("RUBY0001 OK LOGOUT completed\r\n")
- ensure
- sock.close
- server.close
- end
- end
- begin
- imap = Net::IMAP.new(server_addr, :port => port)
- imap.instance_eval do
- def @sock.shutdown(*args)
- super
- ensure
- raise "error"
- end
- end
- imap.logout
- ensure
- assert_raise(RuntimeError) do
- imap.disconnect
- end
- end
- end
-
- def test_connection_closed_during_idle
- server = create_tcp_server
- port = server.addr[1]
- requests = []
- sock = nil
- threads = []
- started = false
- threads << Thread.start do
- started = true
- begin
- sock = server.accept
- sock.print("* OK test server\r\n")
- requests.push(sock.gets)
- sock.print("+ idling\r\n")
- rescue IOError # sock is closed by another thread
- ensure
- server.close
- end
- end
- sleep 0.1 until started
- threads << Thread.start do
- imap = Net::IMAP.new(server_addr, :port => port)
- begin
- m = Monitor.new
- in_idle = false
- closed = false
- c = m.new_cond
- threads << Thread.start do
- m.synchronize do
- until in_idle
- c.wait(0.1)
- end
- end
- sock.close
- m.synchronize do
- closed = true
- c.signal
- end
- end
- assert_raise(EOFError) do
- imap.idle do |res|
- m.synchronize do
- in_idle = true
- c.signal
- until closed
- c.wait(0.1)
- end
- end
- end
- end
- assert_equal(1, requests.length)
- assert_equal("RUBY0001 IDLE\r\n", requests[0])
- ensure
- imap.disconnect if imap
- end
- end
- assert_join_threads(threads)
- ensure
- if sock && !sock.closed?
- sock.close
- end
- end
-
- def test_connection_closed_without_greeting
- server = create_tcp_server
- port = server.addr[1]
- h = {
- server: server,
- port: port,
- server_created: {
- server: server.inspect,
- t: Process.clock_gettime(Process::CLOCK_MONOTONIC),
- }
- }
- net_imap = Class.new(Net::IMAP) do
- @@h = h
- def tcp_socket(host, port)
- @@h[:in_tcp_socket] = {
- host: host,
- port: port,
- server: @@h[:server].inspect,
- t: Process.clock_gettime(Process::CLOCK_MONOTONIC),
- }
- #super
- s = Socket.tcp(host, port, :connect_timeout => @open_timeout)
- @@h[:in_tcp_socket_2] = {
- s: s.inspect,
- local_address: s.local_address,
- remote_address: s.remote_address,
- t: Process.clock_gettime(Process::CLOCK_MONOTONIC),
- }
- s.setsockopt(:SOL_SOCKET, :SO_KEEPALIVE, true)
- s
- end
- end
- start_server do
- begin
- h[:in_start_server_before_accept] = {
- t: Process.clock_gettime(Process::CLOCK_MONOTONIC),
- }
- sock = server.accept
- h[:in_start_server] = {
- sock_addr: sock.addr,
- sock_peeraddr: sock.peeraddr,
- t: Process.clock_gettime(Process::CLOCK_MONOTONIC),
- sockets: ObjectSpace.each_object(BasicSocket).map{|s| [s.inspect, connect_address: (s.connect_address rescue nil).inspect, local_address: (s.local_address rescue nil).inspect, remote_address: (s.remote_address rescue nil).inspect] },
- }
- sock.close
- h[:in_start_server_sock_closed] = {
- t: Process.clock_gettime(Process::CLOCK_MONOTONIC),
- }
- ensure
- server.close
- end
- end
- assert_raise(Net::IMAP::Error) do
- #Net::IMAP.new(server_addr, :port => port)
- if true
- net_imap.new(server_addr, :port => port)
- else
- # for testing debug print
- begin
- net_imap.new(server_addr, :port => port)
- rescue Net::IMAP::Error
- raise Errno::EINVAL
- end
- end
- rescue SystemCallError => e # for debug on OpenCSW
- h[:in_rescue] = {
- e: e,
- server_addr: server_addr,
- t: Process.clock_gettime(Process::CLOCK_MONOTONIC),
- }
- require 'pp'
- raise(PP.pp(h, +''))
- end
- end
-
- def test_default_port
- assert_equal(143, Net::IMAP.default_port)
- assert_equal(143, Net::IMAP.default_imap_port)
- assert_equal(993, Net::IMAP.default_tls_port)
- assert_equal(993, Net::IMAP.default_ssl_port)
- assert_equal(993, Net::IMAP.default_imaps_port)
- end
-
- def test_send_invalid_number
- server = create_tcp_server
- port = server.addr[1]
- start_server do
- sock = server.accept
- begin
- sock.print("* OK test server\r\n")
- sock.gets
- sock.print("RUBY0001 OK TEST completed\r\n")
- sock.gets
- sock.print("RUBY0002 OK TEST completed\r\n")
- sock.gets
- sock.print("RUBY0003 OK TEST completed\r\n")
- sock.gets
- sock.print("RUBY0004 OK TEST completed\r\n")
- sock.gets
- sock.print("* BYE terminating connection\r\n")
- sock.print("RUBY0005 OK LOGOUT completed\r\n")
- ensure
- sock.close
- server.close
- end
- end
- begin
- imap = Net::IMAP.new(server_addr, :port => port)
- assert_raise(Net::IMAP::DataFormatError) do
- imap.send(:send_command, "TEST", -1)
- end
- imap.send(:send_command, "TEST", 0)
- imap.send(:send_command, "TEST", 4294967295)
- assert_raise(Net::IMAP::DataFormatError) do
- imap.send(:send_command, "TEST", 4294967296)
- end
- assert_raise(Net::IMAP::DataFormatError) do
- imap.send(:send_command, "TEST", Net::IMAP::MessageSet.new(-1))
- end
- assert_raise(Net::IMAP::DataFormatError) do
- imap.send(:send_command, "TEST", Net::IMAP::MessageSet.new(0))
- end
- imap.send(:send_command, "TEST", Net::IMAP::MessageSet.new(1))
- imap.send(:send_command, "TEST", Net::IMAP::MessageSet.new(4294967295))
- assert_raise(Net::IMAP::DataFormatError) do
- imap.send(:send_command, "TEST", Net::IMAP::MessageSet.new(4294967296))
- end
- imap.logout
- ensure
- imap.disconnect
- end
- end
-
- def test_send_literal
- server = create_tcp_server
- port = server.addr[1]
- requests = []
- literal = nil
- start_server do
- sock = server.accept
- begin
- sock.print("* OK test server\r\n")
- line = sock.gets
- requests.push(line)
- size = line.slice(/{(\d+)}\r\n/, 1).to_i
- sock.print("+ Ready for literal data\r\n")
- literal = sock.read(size)
- requests.push(sock.gets)
- sock.print("RUBY0001 OK TEST completed\r\n")
- sock.gets
- sock.print("* BYE terminating connection\r\n")
- sock.print("RUBY0002 OK LOGOUT completed\r\n")
- ensure
- sock.close
- server.close
- end
- end
- begin
- imap = Net::IMAP.new(server_addr, :port => port)
- imap.send(:send_command, "TEST", ["\xDE\xAD\xBE\xEF".b])
- assert_equal(2, requests.length)
- assert_equal("RUBY0001 TEST ({4}\r\n", requests[0])
- assert_equal("\xDE\xAD\xBE\xEF".b, literal)
- assert_equal(")\r\n", requests[1])
- imap.logout
- ensure
- imap.disconnect
- end
- end
-
- def test_disconnect
- server = create_tcp_server
- port = server.addr[1]
- start_server do
- sock = server.accept
- begin
- sock.print("* OK test server\r\n")
- sock.gets
- sock.print("* BYE terminating connection\r\n")
- sock.print("RUBY0001 OK LOGOUT completed\r\n")
- ensure
- sock.close
- server.close
- end
- end
- begin
- imap = Net::IMAP.new(server_addr, :port => port)
- imap.logout
- imap.disconnect
- assert_equal(true, imap.disconnected?)
- imap.disconnect
- assert_equal(true, imap.disconnected?)
- ensure
- imap.disconnect if imap && !imap.disconnected?
- end
- end
-
- def test_append
- server = create_tcp_server
- port = server.addr[1]
- mail = <<EOF.gsub(/\n/, "\r\n")
-From: shugo@example.com
-To: matz@example.com
-Subject: hello
-
-hello world
-EOF
- requests = []
- received_mail = nil
- start_server do
- sock = server.accept
- begin
- sock.print("* OK test server\r\n")
- line = sock.gets
- requests.push(line)
- size = line.slice(/{(\d+)}\r\n/, 1).to_i
- sock.print("+ Ready for literal data\r\n")
- received_mail = sock.read(size)
- sock.gets
- sock.print("RUBY0001 OK APPEND completed\r\n")
- requests.push(sock.gets)
- sock.print("* BYE terminating connection\r\n")
- sock.print("RUBY0002 OK LOGOUT completed\r\n")
- ensure
- sock.close
- server.close
- end
- end
-
- begin
- imap = Net::IMAP.new(server_addr, :port => port)
- imap.append("INBOX", mail)
- assert_equal(1, requests.length)
- assert_equal("RUBY0001 APPEND INBOX {#{mail.size}}\r\n", requests[0])
- assert_equal(mail, received_mail)
- imap.logout
- assert_equal(2, requests.length)
- assert_equal("RUBY0002 LOGOUT\r\n", requests[1])
- ensure
- imap.disconnect if imap
- end
- end
-
- def test_append_fail
- server = create_tcp_server
- port = server.addr[1]
- mail = <<EOF.gsub(/\n/, "\r\n")
-From: shugo@example.com
-To: matz@example.com
-Subject: hello
-
-hello world
-EOF
- requests = []
- start_server do
- sock = server.accept
- begin
- sock.print("* OK test server\r\n")
- requests.push(sock.gets)
- sock.print("RUBY0001 NO Mailbox doesn't exist\r\n")
- requests.push(sock.gets)
- sock.print("* BYE terminating connection\r\n")
- sock.print("RUBY0002 OK LOGOUT completed\r\n")
- ensure
- sock.close
- server.close
- end
- end
-
- begin
- imap = Net::IMAP.new(server_addr, :port => port)
- assert_raise(Net::IMAP::NoResponseError) do
- imap.append("INBOX", mail)
- end
- assert_equal(1, requests.length)
- assert_equal("RUBY0001 APPEND INBOX {#{mail.size}}\r\n", requests[0])
- imap.logout
- assert_equal(2, requests.length)
- assert_equal("RUBY0002 LOGOUT\r\n", requests[1])
- ensure
- imap.disconnect if imap
- end
- end
-
- private
-
- def imaps_test
- server = create_tcp_server
- port = server.addr[1]
- ctx = OpenSSL::SSL::SSLContext.new
- ctx.ca_file = CA_FILE
- ctx.key = File.open(SERVER_KEY) { |f|
- OpenSSL::PKey::RSA.new(f)
- }
- ctx.cert = File.open(SERVER_CERT) { |f|
- OpenSSL::X509::Certificate.new(f)
- }
- ssl_server = OpenSSL::SSL::SSLServer.new(server, ctx)
- started = false
- ths = Thread.start do
- Thread.current.report_on_exception = false # always join-ed
- begin
- started = true
- sock = ssl_server.accept
- begin
- sock.print("* OK test server\r\n")
- sock.gets
- sock.print("* BYE terminating connection\r\n")
- sock.print("RUBY0001 OK LOGOUT completed\r\n")
- ensure
- sock.close
- end
- rescue Errno::EPIPE, Errno::ECONNRESET, Errno::ECONNABORTED
- end
- end
- sleep 0.1 until started
- begin
- begin
- imap = yield(port)
- imap.logout
- ensure
- imap.disconnect if imap
- end
- ensure
- ssl_server.close
- ths.join
- end
- end
-
- def starttls_test
- server = create_tcp_server
- port = server.addr[1]
- start_server do
- sock = server.accept
- begin
- sock.print("* OK test server\r\n")
- sock.gets
- sock.print("RUBY0001 OK completed\r\n")
- ctx = OpenSSL::SSL::SSLContext.new
- ctx.ca_file = CA_FILE
- ctx.key = File.open(SERVER_KEY) { |f|
- OpenSSL::PKey::RSA.new(f)
- }
- ctx.cert = File.open(SERVER_CERT) { |f|
- OpenSSL::X509::Certificate.new(f)
- }
- sock = OpenSSL::SSL::SSLSocket.new(sock, ctx)
- sock.sync_close = true
- sock.accept
- sock.gets
- sock.print("* BYE terminating connection\r\n")
- sock.print("RUBY0002 OK LOGOUT completed\r\n")
- ensure
- sock.close
- server.close
- end
- end
- begin
- imap = yield(port)
- imap.logout if !imap.disconnected?
- ensure
- imap.disconnect if imap && !imap.disconnected?
- end
- end
-
- def create_tcp_server
- return TCPServer.new(server_addr, 0)
- end
-
- def server_addr
- Addrinfo.tcp("localhost", 0).ip_address
- end
-end