summaryrefslogtreecommitdiff
path: root/test/lib/minitest
diff options
context:
space:
mode:
authorakr <akr@b2dd03c8-39d4-4d8f-98ff-823fe69b080e>2014-05-27 03:24:52 +0000
committerakr <akr@b2dd03c8-39d4-4d8f-98ff-823fe69b080e>2014-05-27 03:24:52 +0000
commitdbd239a7aafd2c19fad795b5c453c79eefa1ec87 (patch)
tree407df54ddd855b486fa3cb4c48dd14db4a5fbc2c /test/lib/minitest
parent2e5d698538ea132a4dcd46d924c071227b5f4956 (diff)
* test/lib/minitest/unit.rb: Show leaked file descriptors.
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@46156 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
Diffstat (limited to 'test/lib/minitest')
-rw-r--r--test/lib/minitest/unit.rb57
1 files changed, 57 insertions, 0 deletions
diff --git a/test/lib/minitest/unit.rb b/test/lib/minitest/unit.rb
index 54f34d5..2516034 100644
--- a/test/lib/minitest/unit.rb
+++ b/test/lib/minitest/unit.rb
@@ -932,6 +932,7 @@ module MiniTest
}
threads = find_threads
+ fds = find_fds
tempfiles = find_tempfiles
assertions = filtered_test_methods.map { |method|
@@ -949,6 +950,8 @@ module MiniTest
threads = check_thread_leak inst, threads, find_threads
+ fds = check_fd_leak inst, fds, find_fds
+
# find_tempfiles is too slow to run for each test method.
#tempfiles = check_tempfile_leak inst, tempfiles, find_tempfiles
@@ -984,6 +987,60 @@ module MiniTest
live2
end
+ def find_fds
+ fd_dir = "/proc/#{$$}/fd"
+ if File.directory?(fd_dir)
+ Dir.entries(fd_dir).grep(/\A\d+\z/).map(&:to_i).sort
+ else
+ []
+ end
+ end
+
+ def check_fd_leak(inst, live1, live2)
+ name = "#{inst.class}\##{inst.__name__}"
+ fd_closed = live1 - live2
+ if !fd_closed.empty?
+ fd_closed.each {|fd|
+ puts "Closed file descriptor: #{name}: #{fd}"
+ }
+ end
+ fd_leaked = live2 - live1
+ if !fd_leaked.empty?
+ h = {}
+ ObjectSpace.each_object(IO) {|io|
+ begin
+ fd = io.fileno
+ rescue IOError # closed IO object
+ next
+ end
+ (h[fd] ||= []) << io
+ }
+ fd_leaked.each {|fd|
+ str = ''
+ if h[fd]
+ str << ' :'
+ h[fd].map {|io|
+ s = ' ' + io.inspect
+ s << "(not-autoclose)" if !io.autoclose?
+ s
+ }.each {|s|
+ str << s
+ }
+ end
+ puts "Leaked file descriptor: #{name}: #{fd}#{str}"
+ }
+ h.each {|fd, ios|
+ next if ios.length <= 1
+ list = ios.map {|io| [io, io.autoclose?] }
+ if 1 < list.count {|io, autoclose| autoclose }
+ str = list.map {|io, autoclose| " #{io.inspect}" + (autoclose ? "(autoclose)" : "") }.sort.join
+ puts "Multiple autoclose IO object for a file descriptor:#{str}"
+ end
+ }
+ end
+ live2
+ end
+
def find_tempfiles
if defined? Tempfile
ObjectSpace.each_object(Tempfile).find_all {|t|