summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorntalbott <ntalbott@b2dd03c8-39d4-4d8f-98ff-823fe69b080e>2003-10-08 13:21:28 +0000
committerntalbott <ntalbott@b2dd03c8-39d4-4d8f-98ff-823fe69b080e>2003-10-08 13:21:28 +0000
commit09d2946061379d18407d4de2002a01f3a82c8c84 (patch)
treeeaefbd65eb42404ac9230f108bed0576943269ca
parent777681bda1fe3fbc33bd2c3d4ce132e6b8c0042e (diff)
* lib/test/unit.rb: removed installation instructions.
* lib/test/unit/ui/testrunnermediator.rb: moved the run flag to a more central location. * lib/test/unit.rb: ditto. * lib/test/unit.rb: extracted the running code in to AutoRunner. * lib/test/unit/autorunner.rb: added. * lib/test/unit/collector/objectspace.rb: extracted common test collection functionality in to a module. * lib/test/unit/collector.rb: ditto; added. * test/testunit/collector/test_objectspace.rb: ditto. * lib/test/unit/collector/dir.rb: added. Supports collecting tests out of a directory structure. * test/testunit/collector/test_dir.rb: added. * test/runner.rb: simplified to use the new capabilities. git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@4720 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
-rw-r--r--ChangeLog27
-rw-r--r--lib/test/unit.rb130
-rw-r--r--lib/test/unit/autorunner.rb178
-rw-r--r--lib/test/unit/collector.rb43
-rw-r--r--lib/test/unit/collector/dir.rb80
-rw-r--r--lib/test/unit/collector/objectspace.rb30
-rw-r--r--lib/test/unit/ui/testrunnermediator.rb10
-rw-r--r--test/runner.rb60
-rw-r--r--test/testunit/collector/test_dir.rb389
-rw-r--r--test/testunit/collector/test_objectspace.rb61
10 files changed, 775 insertions, 233 deletions
diff --git a/ChangeLog b/ChangeLog
index dd8b2789b9..57e7becdf6 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,30 @@
+Wed Oct 8 22:19:00 2003 Nathaniel Talbott <ntalbott@ruby-lang.org>
+
+ * lib/test/unit.rb: removed installation instructions.
+
+ * lib/test/unit/ui/testrunnermediator.rb: moved the run flag to a more
+ central location.
+
+ * lib/test/unit.rb: ditto.
+
+ * lib/test/unit.rb: extracted the running code in to AutoRunner.
+
+ * lib/test/unit/autorunner.rb: added.
+
+ * lib/test/unit/collector/objectspace.rb: extracted common test
+ collection functionality in to a module.
+
+ * lib/test/unit/collector.rb: ditto; added.
+
+ * test/testunit/collector/test_objectspace.rb: ditto.
+
+ * lib/test/unit/collector/dir.rb: added. Supports collecting tests out
+ of a directory structure.
+
+ * test/testunit/collector/test_dir.rb: added.
+
+ * test/runner.rb: simplified to use the new capabilities.
+
Tue Oct 7 15:23:09 2003 NAKAMURA, Hiroshi <nahi@ruby-lang.org>
* test/ruby/test_beginendblock.rb: add tests for nested BEGIN/END.
diff --git a/lib/test/unit.rb b/lib/test/unit.rb
index 08e57f2f17..6fab874f23 100644
--- a/lib/test/unit.rb
+++ b/lib/test/unit.rb
@@ -19,20 +19,6 @@
# have tests for it.
#
#
-# == Installation
-#
-# Run:
-# * ruby setup.rb config
-# * ruby setup.rb setup
-# * ruby setup.rb install
-#
-# Note that the runit compatibility layer will *not* be installed if you
-# already have RubyUnit installed.
-#
-# Mac OS X users should also note that setup.rb will fail unless they
-# execute 'unlimit stacksize' before running it.
-#
-#
# == Notes
#
# Test::Unit has grown out of and superceded Lapidary.
@@ -272,114 +258,18 @@
require 'test/unit/testcase'
-require 'test/unit/ui/testrunnermediator'
-require 'test/unit/collector/objectspace'
-
-at_exit {
- require 'optparse'
- if (!Test::Unit::UI::TestRunnerMediator.run?)
- output_level = nil
- runners = {
- :console => proc do |suite|
- require 'test/unit/ui/console/testrunner'
- output_level ||= Test::Unit::UI::Console::TestRunner::NORMAL
- passed = Test::Unit::UI::Console::TestRunner.run(suite, output_level).passed?
- exit(passed ? 0 : 1)
- end,
- :gtk => proc do |suite|
- require 'test/unit/ui/gtk/testrunner'
- Test::Unit::UI::GTK::TestRunner.run(suite)
- end,
- :fox => proc do |suite|
- require 'test/unit/ui/fox/testrunner'
- Test::Unit::UI::Fox::TestRunner.run(suite)
- end,
- }
-
- runner = runners[:console]
- filters = []
- catch(:stop_processing) do
- ARGV.options do |o|
- o.program_name = "test/unit.rb"
- o.banner = "Test::Unit automatic runner."
- o.banner = "#{$0} [options] [-- untouched arguments]"
+require 'test/unit/autorunner'
- o.on
- runner_display = runners.keys.collect{|r| r.to_s.sub(/^(.)/, '[\\1]')}.join(", ")
- o.on('-r', '--runner=RUNNER', runners.keys,
- "Use the given runner.",
- "(" + runner_display + ")"){|r| runner = runners[r]}
- o.on('-n', '--name=NAME', String,
- "Runs tests matching NAME",
- "(patterns may be used).") do |n|
- n = (%r{\A/(.*)/\Z} =~ n ? Regexp.new($1) : n)
- case n
- when Regexp
- filters << proc{|t| n =~ t.method_name}
- else
- filters << proc{|t| n == t.method_name}
- end
- end
- o.on('-t', '--testcase=TESTCASE', String,
- "Runs tests in TestCases matching TESTCASE",
- "(patterns may be used).") do |n|
- n = (%r{\A/(.*)/\Z} =~ n ? Regexp.new($1) : n)
- case n
- when Regexp
- filters << proc{|t| n =~ t.class.name}
- else
- filters << proc{|t| n == t.class.name}
- end
- end
- o.on('-v', '--verbose=[LEVEL]', (0..3).to_a.collect{|i| i.to_s},
- "Set output level.",
- "Levels are:",
- " 0 = SILENT",
- " 1 = PROGRESS_ONLY",
- " 2 = NORMAL",
- " 3 = VERBOSE (default)",
- " Only valid for the console runner."){|l| output_level = (l ? l.to_i : 3)}
- o.on('--',
- "Stop processing options so that",
- "remaining options will be passed",
- "to the test."){throw :stop_processing}
- o.on('-h', '--help', 'Display this help.'){puts o; exit(0)}
-
- o.on_tail
- o.on_tail('Deprecated options:')
- o.on_tail('--console', 'Console runner (use --runner).') do
- warn("Deprecated option (--console).")
- runner = runners[:console]
- end
- o.on_tail('--gtk', 'GTK runner (use --runner).') do
- warn("Deprecated option (--gtk).")
- runner = runners[:gtk]
- end
- o.on_tail('--fox', 'Fox runner (use --runner).') do
- warn("Deprecated option (--fox).")
- runner = runners[:fox]
- end
- o.on_tail
-
- begin
- o.parse!
- rescue OptionParser::ParseError => e
- puts e
- puts o
- exit(1)
- end
- end
+module Test
+ module Unit
+ def self.run=(flag)
+ @run = flag
end
- if(output_level && !(runner == runners[:console]))
- puts "Invalid arguments: You can only specify an output level with the console runner."
- exit(1)
+ def self.run?
+ @run ||= false
end
-
- collector = Test::Unit::Collector::ObjectSpace::new
- collector.filter = filters
-
- suite_name = $0.sub(/\.rb$/, '')
- runner.call(collector.collect(suite_name))
end
-}
+end
+
+at_exit{Test::Unit::AutoRunner.run($0) unless(Test::Unit.run?)}
diff --git a/lib/test/unit/autorunner.rb b/lib/test/unit/autorunner.rb
new file mode 100644
index 0000000000..be32e47f6e
--- /dev/null
+++ b/lib/test/unit/autorunner.rb
@@ -0,0 +1,178 @@
+require 'optparse'
+
+require 'test/unit/ui/console/testrunner'
+
+module Test
+ module Unit
+ class AutoRunner
+ def self.run(current_file=nil, default_dir=nil, &block)
+ if(!current_file || current_file == $0)
+ r = new(!current_file, &block)
+ if(default_dir && r.to_run.empty?)
+ r.to_run = default_dir
+ end
+ r.run
+ end
+ end
+
+ RUNNERS = {
+ :console => proc do |r|
+ output_level = r.output_level || Test::Unit::UI::Console::TestRunner::NORMAL
+ passed = Test::Unit::UI::Console::TestRunner.run(r.suite, output_level).passed?
+ exit(passed ? 0 : 1)
+ end,
+ :gtk => proc do |r|
+ require 'test/unit/ui/gtk/testrunner'
+ Test::Unit::UI::GTK::TestRunner.run(r.suite)
+ end,
+ :fox => proc do |suite|
+ require 'test/unit/ui/fox/testrunner'
+ Test::Unit::UI::Fox::TestRunner.run(r.suite)
+ end,
+ }
+
+ OUTPUT_LEVELS = {
+ :silent => UI::Console::TestRunner::SILENT,
+ :progress => UI::Console::TestRunner::PROGRESS_ONLY,
+ :normal => UI::Console::TestRunner::NORMAL,
+ :verbose => UI::Console::TestRunner::VERBOSE,
+ }
+
+ COLLECTORS = {
+ :objectspace => proc do |r|
+ require 'test/unit/collector/objectspace'
+ c = Collector::ObjectSpace.new
+ c.filter = r.filters
+ c.collect($0.sub(/\.rb\Z/, ''))
+ end,
+ :dir => proc do |r|
+ require 'test/unit/collector/dir'
+ c = Collector::Dir.new
+ c.filter = r.filters
+ c.pattern = r.pattern if(r.pattern)
+ c.collect(*(r.to_run.empty? ? ['.'] : r.to_run))
+ end,
+ }
+
+ attr_reader :suite
+ attr_accessor :output_level, :filters, :to_run, :pattern
+ attr_writer :runner, :collector
+
+ def initialize(standalone)
+ Unit.run = true
+ @standalone = standalone
+ @runner = RUNNERS[:console]
+ @collector = COLLECTORS[(standalone ? :dir : :objectspace)]
+ @filters = []
+ @to_run = []
+ process_args
+ yield(self) if(block_given?)
+ end
+
+ def process_args
+ catch(:stop_processing) do
+ ARGV.options do |o|
+ o.program_name = "test/unit.rb"
+ o.banner = "Test::Unit automatic runner."
+ o.banner = "#{$0} [options] [-- untouched arguments]"
+
+ o.on
+ o.on('-r', '--runner=RUNNER', RUNNERS.keys,
+ "Use the given RUNNER.",
+ "(" + keyword_display(RUNNERS.keys) + ")") do |r|
+ @runner = runners[r]
+ end
+
+ if(@standalone)
+ o.on('-a', '--add=TORUN', Array,
+ "Add TORUN to the list of things to run;",
+ "can be a file or a directory.") do |a|
+ @to_run.concat(a)
+ end
+
+ o.on('-p', '--pattern=PATTERN', String,
+ "Match files to collect against PATTERN.") do |e|
+ @pattern = Regexp.new(e.sub(%r{\A/(.*)/\Z}m, '\\1'))
+ end
+ end
+
+ o.on('-n', '--name=NAME', String,
+ "Runs tests matching NAME.",
+ "(patterns may be used).") do |n|
+ n = (%r{\A/(.*)/\Z} =~ n ? Regexp.new($1) : n)
+ case n
+ when Regexp
+ @filters << proc{|t| n =~ t.method_name ? true : nil}
+ else
+ @filters << proc{|t| n == t.method_name ? true : nil}
+ end
+ end
+
+ o.on('-t', '--testcase=TESTCASE', String,
+ "Runs tests in TestCases matching TESTCASE.",
+ "(patterns may be used).") do |n|
+ n = (%r{\A/(.*)/\Z} =~ n ? Regexp.new($1) : n)
+ case n
+ when Regexp
+ @filters << proc{|t| n =~ t.class.name ? true : nil}
+ else
+ @filters << proc{|t| n == t.class.name ? true : nil}
+ end
+ end
+
+ o.on('-v', '--verbose=[LEVEL]', OUTPUT_LEVELS.keys,
+ "Set the output level (default is verbose).",
+ "(" + keyword_display(OUTPUT_LEVELS.keys) + ")") do |l|
+ @output_level = (l ? OUTPUT_LEVELS[l] : OUTPUT_LEVELS[:verbose])
+ end
+
+ o.on('--',
+ "Stop processing options so that the",
+ "remaining options will be passed to the",
+ "test."){throw :stop_processing}
+
+ o.on('-h', '--help', 'Display this help.'){puts o; exit(0)}
+
+ o.on_tail
+ o.on_tail('Deprecated options:')
+
+ o.on_tail('--console', 'Console runner (use --runner).') do
+ warn("Deprecated option (--console).")
+ @runner = RUNNERS[:console]
+ end
+
+ o.on_tail('--gtk', 'GTK runner (use --runner).') do
+ warn("Deprecated option (--gtk).")
+ @runner = RUNNERS[:gtk]
+ end
+
+ o.on_tail('--fox', 'Fox runner (use --runner).') do
+ warn("Deprecated option (--fox).")
+ @runner = RUNNERS[:fox]
+ end
+
+ o.on_tail
+
+ begin
+ o.parse!
+ rescue OptionParser::ParseError => e
+ puts e
+ puts o
+ exit(1)
+ end
+ end
+ end
+ @filters << proc{false} unless(@filters.empty?)
+ end
+
+ def keyword_display(array)
+ array.collect{|e| e.to_s.sub(/^(.)(.+)$/, '\\1[\\2]')}.join(", ")
+ end
+
+ def run
+ @suite = @collector[self]
+ @runner[self]
+ end
+ end
+ end
+end
diff --git a/lib/test/unit/collector.rb b/lib/test/unit/collector.rb
new file mode 100644
index 0000000000..9e9e654147
--- /dev/null
+++ b/lib/test/unit/collector.rb
@@ -0,0 +1,43 @@
+module Test
+ module Unit
+ module Collector
+ def initialize
+ @filters = []
+ end
+
+ def filter=(filters)
+ @filters = case(filters)
+ when Proc
+ [filters]
+ when Array
+ filters
+ end
+ end
+
+ def add_suite(destination, suite)
+ to_delete = suite.tests.find_all{|t| !include?(t)}
+ to_delete.each{|t| suite.delete(t)}
+ destination << suite unless(suite.size == 0)
+ end
+
+ def include?(test)
+ return true if(@filters.empty?)
+ @filters.each do |filter|
+ result = filter[test]
+ if(result.nil?)
+ next
+ elsif(!result)
+ return false
+ else
+ return true
+ end
+ end
+ true
+ end
+
+ def sort(suites)
+ suites.sort_by{|s| s.name}
+ end
+ end
+ end
+end
diff --git a/lib/test/unit/collector/dir.rb b/lib/test/unit/collector/dir.rb
new file mode 100644
index 0000000000..b5c935519e
--- /dev/null
+++ b/lib/test/unit/collector/dir.rb
@@ -0,0 +1,80 @@
+require 'test/unit/testsuite'
+require 'test/unit/collector'
+
+module Test
+ module Unit
+ module Collector
+ class Dir
+ include Collector
+
+ attr_writer :pattern
+
+ def initialize(dir=::Dir, file=::File, object_space=::ObjectSpace, req=nil)
+ super()
+ @dir = dir
+ @file = file
+ @object_space = object_space
+ @req = req
+ @pattern = /\Atest_.*\.rb\Z/m
+ end
+
+ def collect(*from)
+ if(from.empty?)
+ recursive_collect('.', find_test_cases)
+ elsif(from.size == 1)
+ recursive_collect(from.first, find_test_cases)
+ else
+ suites = []
+ from.each do |f|
+ suite = recursive_collect(f, find_test_cases)
+ suites << suite unless(suite.tests.empty?)
+ end
+ suite = TestSuite.new("[#{from.join(', ')}]")
+ sort(suites).each{|s| suite << s}
+ suite
+ end
+ end
+
+ def find_test_cases(ignore=[])
+ cases = []
+ @object_space.each_object(Class) do |c|
+ cases << c if(c < TestCase && !ignore.include?(c))
+ end
+ ignore.concat(cases)
+ cases
+ end
+
+ def recursive_collect(name, already_gathered)
+ sub_suites = []
+ if(@file.directory?(name))
+ @dir.entries(name).each do |e|
+ next if(e == '.' || e == '..')
+ e_name = @file.join(name, e)
+ if(@file.directory?(e_name))
+ sub_suite = recursive_collect(e_name, already_gathered)
+ sub_suites << sub_suite unless(sub_suite.empty?)
+ else
+ (next unless(@pattern =~ e)) if(@pattern)
+ collect_file(e_name, sub_suites, already_gathered)
+ end
+ end
+ else
+ collect_file(name, sub_suites, already_gathered)
+ end
+ suite = TestSuite.new(@file.basename(name))
+ sort(sub_suites).each{|s| suite << s}
+ suite
+ end
+
+ def collect_file(name, suites, already_gathered)
+ if(@req)
+ @req.require(name)
+ else
+ require(name)
+ end
+ find_test_cases(already_gathered).each{|t| add_suite(suites, t.suite)}
+ end
+ end
+ end
+ end
+end
diff --git a/lib/test/unit/collector/objectspace.rb b/lib/test/unit/collector/objectspace.rb
index 5a1d29cc1a..d1127a981f 100644
--- a/lib/test/unit/collector/objectspace.rb
+++ b/lib/test/unit/collector/objectspace.rb
@@ -2,15 +2,19 @@
# Copyright:: Copyright (c) 2000-2003 Nathaniel Talbott. All rights reserved.
# License:: Ruby license.
+require 'test/unit/collector'
+
module Test
module Unit
module Collector
class ObjectSpace
+ include Collector
+
NAME = 'collected from the ObjectSpace'
def initialize(source=::ObjectSpace)
+ super()
@source = source
- @filters = []
end
def collect(name=NAME)
@@ -18,32 +22,12 @@ module Test
sub_suites = []
@source.each_object(Class) do |klass|
if(Test::Unit::TestCase > klass)
- sub_suite = klass.suite
- to_delete = sub_suite.tests.find_all{|t| !include(t)}
- to_delete.each{|t| sub_suite.delete(t)}
- sub_suites << sub_suite unless(sub_suite.size == 0)
+ add_suite(sub_suites, klass.suite)
end
end
- sub_suites.sort_by{|s| s.name}.each{|s| suite << s}
+ sort(sub_suites).each{|s| suite << s}
suite
end
-
- def include(test)
- return true if(@filters.empty?)
- @filters.each do |filter|
- return true if(filter.call(test))
- end
- false
- end
-
- def filter=(filters)
- @filters = case(filters)
- when Proc
- [filters]
- when Array
- filters
- end
- end
end
end
end
diff --git a/lib/test/unit/ui/testrunnermediator.rb b/lib/test/unit/ui/testrunnermediator.rb
index 41c77dc7a9..bd051e2a51 100644
--- a/lib/test/unit/ui/testrunnermediator.rb
+++ b/lib/test/unit/ui/testrunnermediator.rb
@@ -20,14 +20,6 @@ module Test
include Util::Observable
- @@run = false
-
- # Returns true if any TestRunnerMediator instances
- # have been run.
- def self.run?
- return @@run
- end
-
# Creates a new TestRunnerMediator initialized to run
# the passed suite.
def initialize(suite)
@@ -37,7 +29,7 @@ module Test
# Runs the suite the TestRunnerMediator was created
# with.
def run_suite
- @@run = true
+ Unit.run = true
begin_time = Time.now
notify_listeners(RESET, @suite.size)
result = create_result
diff --git a/test/runner.rb b/test/runner.rb
index b0a63a31ce..b2841b012a 100644
--- a/test/runner.rb
+++ b/test/runner.rb
@@ -1,63 +1,7 @@
-require 'test/unit/testsuite'
-require 'test/unit/testcase'
-require 'optparse'
+require 'test/unit'
rcsid = %w$Id$
Version = rcsid[2].scan(/\d+/).collect!(&method(:Integer)).freeze
Release = rcsid[3].freeze
-class BulkTestSuite < Test::Unit::TestSuite
- def self.suite
- suite = Test::Unit::TestSuite.new(self.name)
- ObjectSpace.each_object(Class) do |klass|
- suite << klass.suite if (Test::Unit::TestCase > klass)
- end
- suite
- end
-end
-
-runners_map = {
- 'console' => proc do |suite|
- require 'test/unit/ui/console/testrunner'
- passed = Test::Unit::UI::Console::TestRunner.run(suite).passed?
- exit(passed ? 0 : 1)
- end,
- 'gtk' => proc do |suite|
- require 'test/unit/ui/gtk/testrunner'
- Test::Unit::UI::GTK::TestRunner.run(suite)
- end,
- 'fox' => proc do |suite|
- require 'test/unit/ui/fox/testrunner'
- Test::Unit::UI::Fox::TestRunner.run(suite)
- end,
-}
-
-runner = 'console'
-opt = OptionParser.new
-opt.program_name = $0
-opt.banner << " [tests...]"
-opt.on("--runner=mode", runners_map.keys, "UI mode (console, gtk,fox)") do |arg|
- runner = arg
-end
-begin
- argv = opt.parse(*ARGV)
-rescue OptionParser::ParseError
- opt.abort($!)
-end
-
-if argv.empty?
- argv = [File.dirname(__FILE__)]
-end
-argv.collect! do |arg|
- if File.directory?(arg)
- Dir.glob(File.join(arg, "**", "test_*.rb")).sort
- else
- arg
- end
-end.flatten!
-
-argv.each do |tc_name|
- require tc_name
-end
-
-runners_map[runner].call(BulkTestSuite.suite)
+Test::Unit::AutoRunner.run(false, File.dirname(__FILE__))
diff --git a/test/testunit/collector/test_dir.rb b/test/testunit/collector/test_dir.rb
new file mode 100644
index 0000000000..e9b42d7966
--- /dev/null
+++ b/test/testunit/collector/test_dir.rb
@@ -0,0 +1,389 @@
+require 'test/unit'
+require 'test/unit/collector/dir'
+require 'pp'
+
+module Test
+ module Unit
+ module Collector
+ class TestDir < TestCase
+ class FileSystem
+ class Directory
+ def initialize(name, fs, parent=self, &block)
+ @name = name
+ @fs = fs
+ @parent = parent
+ @contents = {'.' => self, '..' => parent}
+ instance_eval(&block) if(block)
+ end
+
+ def file(name, contents)
+ @contents[name] = contents
+ end
+
+ def dir(name, &block)
+ @contents[name] = self.class.new(name, @fs, self, &block)
+ end
+
+ def entries
+ @contents.keys
+ end
+
+ def directory?(name)
+ return true if(name.nil? || name.empty?)
+ return false unless(@contents.include?(name))
+ @contents[name].kind_of?(self.class)
+ end
+
+ def file?(name)
+ return false unless(@contents.include?(name))
+ !directory?(name)
+ end
+
+ def exist?(name)
+ @contents.include?(name)
+ end
+
+ def [](name)
+ raise Errno::ENOENT, name unless(@contents.include?(name))
+ @contents[name]
+ end
+
+ def path_to(name=nil)
+ if(!name)
+ @parent.path_to(@name)
+ elsif(@parent == self)
+ @fs.join('/', name)
+ else
+ @fs.join(@parent.path_to(@name), name)
+ end
+ end
+ end
+
+ class ObjectSpace
+ def initialize
+ @objects = []
+ end
+
+ def each_object(klass, &block)
+ @objects.find_all{|o| o.kind_of?(klass)}.each(&block)
+ end
+
+ def <<(object)
+ @objects << object
+ end
+ end
+
+ attr_reader :object_space
+
+ def initialize(&block)
+ @root = Directory.new('/', self, &block)
+ @pwd = @root
+ @object_space = ObjectSpace.new
+ @required = []
+ end
+
+ def entries(dir)
+ e = find(dir)
+ require_directory(dir)
+ e.entries
+ end
+
+ def directory?(name)
+ e = find(dirname(name))
+ return false unless(e)
+ e.directory?(basename(name))
+ end
+
+ def find(path)
+ if(/\A\// =~ path)
+ path = path.sub(/\A\//, '')
+ thing = @root
+ else
+ thing = @pwd
+ end
+ split(path).each do |e|
+ break thing = false unless(thing.kind_of?(Directory))
+ thing = thing[e]
+ end
+ thing
+ end
+
+ def dirname(name)
+ join(*split(name)[0..-2])
+ end
+
+ def basename(name)
+ split(name)[-1]
+ end
+
+ def split(name)
+ name.split('/')
+ end
+
+ def join(*parts)
+ parts.join('/').gsub(%r{/+}, '/')
+ end
+
+ def file?(name)
+ e = find(dirname(name))
+ return false unless(e)
+ e.file?(basename(name))
+ end
+
+ def pwd
+ @pwd.path_to
+ end
+
+ def chdir(to)
+ e = find(to)
+ require_directory(to)
+ @pwd = e
+ end
+
+ def require_directory(path)
+ raise Errno::ENOTDIR, path unless(directory?(path))
+ end
+
+ def require(file)
+ return false if(@required.include?(file))
+ begin
+ e = find(file)
+ rescue Errno::ENOENT => e
+ if(/\.rb\Z/ =~ file)
+ raise LoadError, file
+ end
+ e = find(file + '.rb')
+ end
+ @required << file
+ @object_space << e
+ true
+ rescue Errno::ENOENT
+ raise LoadError, file
+ end
+ end
+
+ def test_dir
+ inner_dir = nil
+ dir = FileSystem::Directory.new('/', nil) do
+ file 'a', nil
+ inner_dir = dir 'b'
+ end
+ assert_equal(inner_dir, dir['b'])
+ end
+
+ def test_fs
+ fs = FileSystem.new do
+ file 'a', nil
+ dir 'b'
+ end
+ assert_equal(['.', '..', 'a', 'b'].sort, fs.entries('/').sort)
+ assert(fs.directory?('/'))
+ assert(!fs.directory?('/a'))
+ assert(!fs.directory?('/bogus'))
+ assert(fs.file?('/a'))
+ assert(!fs.file?('/'))
+ assert(!fs.file?('/bogus'))
+ assert(fs.directory?('/b'))
+ assert(fs.file?('a'))
+ assert(fs.directory?('b'))
+ end
+
+ def test_fs_sub
+ fs = FileSystem.new do
+ dir 'a' do
+ file 'b', nil
+ dir 'c' do
+ file 'd', nil
+ end
+ end
+ end
+ assert(fs.file?('/a/b'))
+ assert(!fs.file?('/a/b/c/d'))
+ assert(fs.file?('/a/c/d'))
+ end
+
+ def test_fs_pwd
+ fs = FileSystem.new do
+ file 'a', nil
+ dir 'b' do
+ file 'c', nil
+ dir 'd' do
+ file 'e', nil
+ end
+ end
+ end
+ assert_equal('/', fs.pwd)
+ assert_raises(Errno::ENOENT) do
+ fs.chdir('bogus')
+ end
+ assert_raises(Errno::ENOTDIR) do
+ fs.chdir('a')
+ end
+ fs.chdir('b')
+ assert_equal('/b', fs.pwd)
+ fs.chdir('d')
+ assert_equal('/b/d', fs.pwd)
+ fs.chdir('..')
+ assert_equal('/b', fs.pwd)
+ fs.chdir('..')
+ assert_equal('/', fs.pwd)
+ end
+
+ def test_fs_entries
+ fs = FileSystem.new do
+ file 'a', nil
+ dir 'b' do
+ file 'c', nil
+ file 'd', nil
+ end
+ file 'e', nil
+ dir 'f' do
+ file 'g', nil
+ dir 'h' do
+ file 'i', nil
+ end
+ end
+ end
+ assert_equal(['.', '..', 'a', 'b', 'e', 'f'], fs.entries('/').sort)
+ assert_equal(['.', '..', 'a', 'b', 'e', 'f'], fs.entries('.').sort)
+ assert_equal(['.', '..', 'a', 'b', 'e', 'f'], fs.entries('b/..').sort)
+ assert_equal(['.', '..', 'c', 'd'], fs.entries('b').sort)
+ assert_raises(Errno::ENOENT) do
+ fs.entries('z')
+ end
+ assert_raises(Errno::ENOTDIR) do
+ fs.entries('a')
+ end
+ fs.chdir('f')
+ assert_equal(['.', '..', 'i'], fs.entries('h').sort)
+ end
+
+ class TestClass1
+ end
+ class TestClass2
+ end
+ def test_fs_require
+ fs = FileSystem.new do
+ file 'test_class1.rb', TestClass1
+ dir 'dir' do
+ file 'test_class2.rb', TestClass2
+ end
+ end
+ c = []
+ fs.object_space.each_object(Class) do |o|
+ c << o
+ end
+ assert_equal([], c)
+
+ assert_raises(LoadError) do
+ fs.require('bogus')
+ end
+
+ assert(fs.require('test_class1.rb'))
+ assert(!fs.require('test_class1.rb'))
+ c = []
+ fs.object_space.each_object(Class) do |o|
+ c << o
+ end
+ assert_equal([TestClass1], c)
+
+ fs.require('dir/test_class2')
+ c = []
+ fs.object_space.each_object(Class) do |o|
+ c << o
+ end
+ assert_equal([TestClass1, TestClass2], c)
+
+ c = []
+ fs.object_space.each_object(Time) do |o|
+ c << o
+ end
+ assert_equal([], c)
+ end
+
+ def setup
+ @t1 = t1 = create_test(1)
+ @t2 = t2 = create_test(2)
+ @t3 = t3 = create_test(3)
+ @t4 = t4 = create_test(4)
+ @t5 = t5 = create_test(5)
+ @t6 = t6 = create_test(6)
+ fs = FileSystem.new do
+ file 'test_1.rb', t1
+ file 'test_2.rb', t2
+ dir 'd1' do
+ file 'test_3.rb', t3
+ end
+ file 't4.rb', t4
+ dir 'd2' do
+ file 'test_5', t5
+ file 'test_6.rb', Time
+ end
+ file 't6.rb', t6
+ end
+ fs.require('t6')
+ @c = Dir.new(fs, fs, fs.object_space, fs)
+ end
+
+ def create_test(name)
+ t = Class.new(TestCase)
+ t.class_eval <<-EOC
+ def self.name
+ "T\#{#{name}}"
+ end
+ def test_#{name}a
+ end
+ def test_#{name}b
+ end
+ EOC
+ t
+ end
+
+ def test_simple_collect
+ expected = TestSuite.new('d1')
+ expected << (@t3.suite)
+ assert_equal(expected, @c.collect('d1'))
+ end
+
+ def test_multilevel_collect
+ expected = TestSuite.new('.')
+ expected << @t1.suite << @t2.suite
+ expected << (TestSuite.new('d1') << @t3.suite)
+ assert_equal(expected, @c.collect)
+ end
+
+ def test_collect_file
+ expected = TestSuite.new('test_1.rb')
+ expected << @t1.suite
+ assert_equal(expected, @c.collect('test_1.rb'))
+
+ expected = TestSuite.new('t4.rb')
+ expected << @t4.suite
+ assert_equal(expected, @c.collect('t4.rb'))
+ end
+
+ def test_nil_pattern
+ expected = TestSuite.new('d2')
+ expected << @t5.suite
+ @c.pattern = nil
+ assert_equal(expected, @c.collect('d2'))
+ end
+
+ def test_filtering
+ expected = TestSuite.new('.')
+ expected << @t1.suite
+ @c.filter = proc{|t| t.method_name == 'test_1a' || t.method_name == 'test_1b'}
+ assert_equal(expected, @c.collect)
+ end
+
+ def test_collect_multi
+ expected = TestSuite.new('[d1, d2]')
+ expected << (TestSuite.new('d1') << @t3.suite)
+ expected << (TestSuite.new('d2') << @t5.suite)
+ @c.pattern = /^test_/
+ assert_equal(expected, @c.collect('d1', 'd2'))
+ end
+ end
+ end
+ end
+end
diff --git a/test/testunit/collector/test_objectspace.rb b/test/testunit/collector/test_objectspace.rb
index 488f2e394c..a1532ff3e6 100644
--- a/test/testunit/collector/test_objectspace.rb
+++ b/test/testunit/collector/test_objectspace.rb
@@ -37,45 +37,60 @@ module Test
def @object_space.each_object(type)
self[type].each{|item| yield(item) }
end
+
+ @c = ObjectSpace.new(@object_space)
end
-
- def test_basic_collection
- expected = TestSuite.new("name")
+
+ def full_suite(name=ObjectSpace::NAME)
+ expected = TestSuite.new(name)
expected << (TestSuite.new(@tc1.name) << @tc1.new('test_1') << @tc1.new('test_2'))
expected << (TestSuite.new(@tc2.name) << @tc2.new('test_0'))
- assert_equal(expected, ObjectSpace.new(@object_space).collect("name"))
+ end
+
+ def empty_suite
+ TestSuite.new(ObjectSpace::NAME)
+ end
+
+ def test_basic_collection
+ assert_equal(full_suite("name"), @c.collect("name"))
- c = ObjectSpace.new(@object_space)
- c.filter = []
- assert_equal(expected, c.collect("name"))
+ @c.filter = []
+ assert_equal(full_suite("name"), @c.collect("name"))
end
def test_filtered_collection
- expected = TestSuite.new(ObjectSpace::NAME)
- collector = ObjectSpace.new(@object_space)
- collector.filter = proc{|test| false}
- assert_equal(expected, collector.collect)
+ @c.filter = proc{false}
+ assert_equal(empty_suite, @c.collect)
- expected = TestSuite.new(ObjectSpace::NAME)
- expected << (TestSuite.new(@tc1.name) << @tc1.new('test_1') << @tc1.new('test_2'))
- expected << (TestSuite.new(@tc2.name) << @tc2.new('test_0'))
- collector = ObjectSpace.new(@object_space)
- collector.filter = proc{|test| true}
- assert_equal(expected, collector.collect)
+ @c.filter = proc{true}
+ assert_equal(full_suite, @c.collect)
+
+ @c.filter = proc{nil}
+ assert_equal(full_suite, @c.collect)
+
+ @c.filter = [proc{false}, proc{true}]
+ assert_equal(empty_suite, @c.collect)
+
+ @c.filter = [proc{true}, proc{false}]
+ assert_equal(full_suite, @c.collect)
+ @c.filter = [proc{nil}, proc{false}]
+ assert_equal(empty_suite, @c.collect)
+
+ @c.filter = [proc{nil}, proc{true}]
+ assert_equal(full_suite, @c.collect)
+
expected = TestSuite.new(ObjectSpace::NAME)
expected << (TestSuite.new(@tc1.name) << @tc1.new('test_1'))
expected << (TestSuite.new(@tc2.name) << @tc2.new('test_0'))
- collector = ObjectSpace.new(@object_space)
- collector.filter = proc{|test| ['test_1', 'test_0'].include?(test.method_name)}
- assert_equal(expected, collector.collect)
+ @c.filter = proc{|test| ['test_1', 'test_0'].include?(test.method_name)}
+ assert_equal(expected, @c.collect)
expected = TestSuite.new(ObjectSpace::NAME)
expected << (TestSuite.new(@tc1.name) << @tc1.new('test_1'))
expected << (TestSuite.new(@tc2.name) << @tc2.new('test_0'))
- collector = ObjectSpace.new(@object_space)
- collector.filter = [proc{|test| test.method_name == 'test_1'}, proc{|test| test.method_name == 'test_0'}]
- assert_equal(expected, collector.collect)
+ @c.filter = [proc{|t| t.method_name == 'test_1' ? true : nil}, proc{|t| t.method_name == 'test_0' ? true : nil}, proc{false}]
+ assert_equal(expected, @c.collect)
end
end
end