From 09d2946061379d18407d4de2002a01f3a82c8c84 Mon Sep 17 00:00:00 2001 From: ntalbott Date: Wed, 8 Oct 2003 13:21:28 +0000 Subject: [PATCH] * 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 --- ChangeLog | 27 ++ lib/test/unit.rb | 130 +------ lib/test/unit/autorunner.rb | 178 +++++++++ lib/test/unit/collector.rb | 43 +++ lib/test/unit/collector/dir.rb | 80 ++++ lib/test/unit/collector/objectspace.rb | 30 +- lib/test/unit/ui/testrunnermediator.rb | 10 +- test/runner.rb | 60 +-- test/testunit/collector/test_dir.rb | 389 ++++++++++++++++++++ test/testunit/collector/test_objectspace.rb | 65 ++-- 10 files changed, 777 insertions(+), 235 deletions(-) create mode 100644 lib/test/unit/autorunner.rb create mode 100644 lib/test/unit/collector.rb create mode 100644 lib/test/unit/collector/dir.rb create mode 100644 test/testunit/collector/test_dir.rb 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 + + * 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 * 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' +require 'test/unit/autorunner' -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]" - - 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 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')) + end + + def empty_suite + TestSuite.new(ObjectSpace::NAME) end def test_basic_collection - 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")) + 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) + @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') << @tc1.new('test_2')) + 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| true} - 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_1', 'test_0'].include?(test.method_name)} - assert_equal(expected, collector.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