deep_test 1.1.2 → 1.1.3
Sign up to get free protection for your applications and to get access to all the features.
- data/CHANGELOG +6 -0
- data/README +39 -2
- data/Rakefile +17 -12
- data/lib/deep_test.rb +27 -18
- data/lib/deep_test/deadlock_detector.rb +7 -0
- data/lib/deep_test/logger.rb +9 -0
- data/lib/deep_test/null_worker_listener.rb +12 -0
- data/lib/deep_test/options.rb +72 -0
- data/lib/deep_test/process_orchestrator.rb +85 -0
- data/lib/deep_test/rake_tasks.rb +7 -0
- data/lib/deep_test/rinda_blackboard.rb +8 -7
- data/lib/deep_test/rspec_detector.rb +17 -0
- data/lib/deep_test/server.rb +3 -9
- data/lib/deep_test/spec.rb +9 -0
- data/lib/deep_test/spec/extensions/options.rb +11 -0
- data/lib/deep_test/spec/extensions/reporter.rb +17 -0
- data/lib/deep_test/spec/extensions/spec_task.rb +13 -0
- data/lib/deep_test/spec/runner.rb +48 -0
- data/lib/deep_test/spec/work_result.rb +26 -0
- data/lib/deep_test/spec/work_unit.rb +53 -0
- data/lib/deep_test/test.rb +9 -0
- data/lib/deep_test/{extensions → test/extensions}/error.rb +0 -0
- data/lib/deep_test/{extensions/testresult.rb → test/extensions/test_result.rb} +1 -1
- data/lib/deep_test/test/runner.rb +29 -0
- data/lib/deep_test/test/supervised_test_suite.rb +46 -0
- data/lib/deep_test/test/work_unit.rb +36 -0
- data/lib/deep_test/test_task.rb +36 -9
- data/lib/deep_test/tuple_space_factory.rb +3 -2
- data/lib/deep_test/warlock.rb +2 -2
- data/lib/deep_test/worker.rb +10 -20
- data/script/run_test_suite.rb +5 -34
- data/test/deep_test/rinda_blackboard_test.rb +5 -5
- data/test/{testresult_test.rb → deep_test/test/extensions/test_result_test.rb} +2 -2
- data/test/deep_test/test/runner_test.rb +7 -0
- data/test/deep_test/test/supervised_test_suite_test.rb +89 -0
- data/test/deep_test/test/work_unit_test.rb +50 -0
- data/test/deep_test/test_task_test.rb +23 -0
- data/test/deep_test/worker_test.rb +62 -0
- data/test/failing.rake +11 -0
- data/test/fake_deadlock_error.rb +12 -0
- data/test/logger_test.rb +11 -0
- data/test/simple_test_blackboard.rb +44 -0
- data/test/simple_test_blackboard_test.rb +5 -5
- data/test/test_factory.rb +74 -0
- data/test/test_helper.rb +5 -71
- metadata +32 -13
- data/lib/deep_test/loader.rb +0 -18
- data/lib/deep_test/simple_test_blackboard.rb +0 -24
- data/lib/deep_test/supervised_test_suite.rb +0 -19
- data/lib/deep_test/supervisor.rb +0 -27
- data/test/deep_test/loader_test.rb +0 -8
- data/test/supervised_test_suite_test.rb +0 -63
- data/test/supervisor_test.rb +0 -80
- data/test/worker_test.rb +0 -64
@@ -0,0 +1,9 @@
|
|
1
|
+
require 'spec/runner/example_group_runner'
|
2
|
+
require 'spec/rake/spectask'
|
3
|
+
|
4
|
+
require File.dirname(__FILE__) + "/spec/extensions/spec_task"
|
5
|
+
require File.dirname(__FILE__) + "/spec/extensions/options"
|
6
|
+
require File.dirname(__FILE__) + "/spec/extensions/reporter"
|
7
|
+
require File.dirname(__FILE__) + "/spec/runner"
|
8
|
+
require File.dirname(__FILE__) + "/spec/work_unit"
|
9
|
+
require File.dirname(__FILE__) + "/spec/work_result"
|
@@ -0,0 +1,17 @@
|
|
1
|
+
require 'spec/runner/reporter'
|
2
|
+
module Spec
|
3
|
+
module Runner
|
4
|
+
class Reporter
|
5
|
+
def failure(example, error)
|
6
|
+
backtrace_tweaker.tweak_backtrace(error)
|
7
|
+
example_name = "#{example.class.description} #{example.description}"
|
8
|
+
failure = Failure.new(example_name, error)
|
9
|
+
@failures << failure
|
10
|
+
formatters.each do |f|
|
11
|
+
f.example_failed(example, @failures.length, failure)
|
12
|
+
end
|
13
|
+
end
|
14
|
+
alias_method :example_failed, :failure
|
15
|
+
end
|
16
|
+
end
|
17
|
+
end
|
@@ -0,0 +1,13 @@
|
|
1
|
+
module Spec
|
2
|
+
module Rake
|
3
|
+
class SpecTask
|
4
|
+
def deep_test(options)
|
5
|
+
deep_test_options = DeepTest::Options.new(options)
|
6
|
+
deep_test_path = File.expand_path(File.dirname(__FILE__) +
|
7
|
+
"/../../../deep_test")
|
8
|
+
spec_opts << "--require #{deep_test_path}"
|
9
|
+
spec_opts << "--runner 'DeepTest::Spec::Runner:#{deep_test_options.to_command_line}'"
|
10
|
+
end
|
11
|
+
end
|
12
|
+
end
|
13
|
+
end
|
@@ -0,0 +1,48 @@
|
|
1
|
+
module DeepTest
|
2
|
+
module Spec
|
3
|
+
class Runner < ::Spec::Runner::ExampleGroupRunner
|
4
|
+
def initialize(options, deep_test_options, blackboard = nil)
|
5
|
+
super(options)
|
6
|
+
@deep_test_options = DeepTest::Options.from_command_line(deep_test_options)
|
7
|
+
@blackboard = blackboard
|
8
|
+
end
|
9
|
+
|
10
|
+
def blackboard
|
11
|
+
# Can't create blackboard as default argument to initialize
|
12
|
+
# because ProcessOrchestrator hasn't been invoked at
|
13
|
+
# instantiation time
|
14
|
+
@blackboard ||= RindaBlackboard.new(@deep_test_options)
|
15
|
+
end
|
16
|
+
|
17
|
+
def run
|
18
|
+
ProcessOrchestrator.run(@deep_test_options, self)
|
19
|
+
end
|
20
|
+
|
21
|
+
def process_work_units
|
22
|
+
prepare
|
23
|
+
|
24
|
+
examples = example_groups.map {|g| g.send(:examples_to_run)}.flatten
|
25
|
+
examples_by_location = {}
|
26
|
+
examples.each do |example|
|
27
|
+
file, line, *rest = example.implementation_backtrace.first.split(/:/)
|
28
|
+
examples_by_location["#{file}:#{line}"] = example
|
29
|
+
blackboard.write_work Spec::WorkUnit.new(file, line.to_i)
|
30
|
+
end
|
31
|
+
|
32
|
+
success = true
|
33
|
+
until examples_by_location.empty?
|
34
|
+
result = blackboard.take_result
|
35
|
+
next unless result
|
36
|
+
print result.output if result.output
|
37
|
+
example = examples_by_location.delete("#{result.file}:#{result.line}")
|
38
|
+
@options.reporter.example_finished(example, result.error)
|
39
|
+
success &= result.error.nil?
|
40
|
+
end
|
41
|
+
|
42
|
+
success
|
43
|
+
ensure
|
44
|
+
finish
|
45
|
+
end
|
46
|
+
end
|
47
|
+
end
|
48
|
+
end
|
@@ -0,0 +1,26 @@
|
|
1
|
+
module DeepTest
|
2
|
+
module Spec
|
3
|
+
class WorkResult
|
4
|
+
attr_reader :file, :line, :example_description, :error, :output
|
5
|
+
def initialize(file, line, example_description, error, output)
|
6
|
+
@file, @line, @example_description, @error, @output =
|
7
|
+
file, line, example_description, error, output
|
8
|
+
end
|
9
|
+
|
10
|
+
def ==(other)
|
11
|
+
file == other.file &&
|
12
|
+
line == other.line &&
|
13
|
+
example_description == other.example_description &&
|
14
|
+
error == other.error
|
15
|
+
end
|
16
|
+
|
17
|
+
def failed_due_to_deadlock?
|
18
|
+
DeadlockDetector.due_to_deadlock?(@error)
|
19
|
+
end
|
20
|
+
|
21
|
+
def deadlock_result
|
22
|
+
WorkResult.new(file, line, example_description, nil, '-deadlock-')
|
23
|
+
end
|
24
|
+
end
|
25
|
+
end
|
26
|
+
end
|
@@ -0,0 +1,53 @@
|
|
1
|
+
module DeepTest
|
2
|
+
module Spec
|
3
|
+
class WorkUnit
|
4
|
+
def initialize(file, line)
|
5
|
+
@file, @line = file, line
|
6
|
+
end
|
7
|
+
|
8
|
+
def run
|
9
|
+
# Dup options here to avoid clobbering the reporter on someone
|
10
|
+
# elses options reference (Such as ExampleGroupRunner)
|
11
|
+
original_options, $rspec_options = $rspec_options, $rspec_options.dup
|
12
|
+
rspec_options.reporter = ResultReporter.new(@file, @line)
|
13
|
+
result = run_without_deadlock_protection
|
14
|
+
result = run_without_deadlock_protection if result.failed_due_to_deadlock?
|
15
|
+
result = result.deadlock_result if result.failed_due_to_deadlock?
|
16
|
+
result
|
17
|
+
ensure
|
18
|
+
$rspec_options = original_options
|
19
|
+
end
|
20
|
+
|
21
|
+
protected
|
22
|
+
|
23
|
+
def run_without_deadlock_protection
|
24
|
+
output = capture_stdout do
|
25
|
+
rspec_options.run_one_example(@file, @line)
|
26
|
+
end
|
27
|
+
rspec_options.reporter.result(output)
|
28
|
+
end
|
29
|
+
|
30
|
+
class ResultReporter
|
31
|
+
attr_reader :result
|
32
|
+
def initialize(file,line)
|
33
|
+
@file, @line = file, line
|
34
|
+
end
|
35
|
+
|
36
|
+
def add_example_group(example_group); end
|
37
|
+
def dump; end
|
38
|
+
def end; end
|
39
|
+
def example_started(name); end
|
40
|
+
|
41
|
+
def example_finished(example, error)
|
42
|
+
@example, @error = example, error
|
43
|
+
end
|
44
|
+
|
45
|
+
def result(output)
|
46
|
+
Spec::WorkResult.new(@file, @line, @example.description, @error, output)
|
47
|
+
end
|
48
|
+
|
49
|
+
def start(example); end
|
50
|
+
end
|
51
|
+
end
|
52
|
+
end
|
53
|
+
end
|
@@ -0,0 +1,9 @@
|
|
1
|
+
require "test/unit/testresult"
|
2
|
+
require "test/unit/error"
|
3
|
+
require 'test/unit/failure'
|
4
|
+
|
5
|
+
require File.dirname(__FILE__) + "/test/extensions/test_result"
|
6
|
+
require File.dirname(__FILE__) + "/test/extensions/error"
|
7
|
+
require File.dirname(__FILE__) + "/test/runner"
|
8
|
+
require File.dirname(__FILE__) + "/test/supervised_test_suite"
|
9
|
+
require File.dirname(__FILE__) + "/test/work_unit"
|
File without changes
|
@@ -0,0 +1,29 @@
|
|
1
|
+
module DeepTest
|
2
|
+
module Test
|
3
|
+
class Runner
|
4
|
+
unless defined?(NO_FILTERS)
|
5
|
+
NO_FILTERS = Object.new.instance_eval do
|
6
|
+
def filters; []; end;
|
7
|
+
self
|
8
|
+
end
|
9
|
+
end
|
10
|
+
|
11
|
+
def initialize(options)
|
12
|
+
@options = options
|
13
|
+
end
|
14
|
+
|
15
|
+
def load_files
|
16
|
+
Dir.glob(@options.pattern).each { |file| load file }
|
17
|
+
::Test::Unit.run = true
|
18
|
+
end
|
19
|
+
|
20
|
+
def process_work_units
|
21
|
+
suite = ::Test::Unit::AutoRunner::COLLECTORS[:objectspace].call NO_FILTERS
|
22
|
+
supervised_suite = DeepTest::Test::SupervisedTestSuite.new(suite, RindaBlackboard.new(@options))
|
23
|
+
require 'test/unit/ui/console/testrunner'
|
24
|
+
result = ::Test::Unit::UI::Console::TestRunner.run(supervised_suite, ::Test::Unit::UI::NORMAL)
|
25
|
+
result.passed?
|
26
|
+
end
|
27
|
+
end
|
28
|
+
end
|
29
|
+
end
|
@@ -0,0 +1,46 @@
|
|
1
|
+
module DeepTest
|
2
|
+
module Test
|
3
|
+
class SupervisedTestSuite
|
4
|
+
def initialize(suite, blackboard)
|
5
|
+
@suite = suite
|
6
|
+
@blackboard = blackboard
|
7
|
+
end
|
8
|
+
|
9
|
+
def run(result, &progress_block)
|
10
|
+
yield ::Test::Unit::TestSuite::STARTED, @suite.name
|
11
|
+
count = add_tests @suite
|
12
|
+
read_results result, count, &progress_block
|
13
|
+
yield ::Test::Unit::TestSuite::FINISHED, @suite.name
|
14
|
+
end
|
15
|
+
|
16
|
+
def size
|
17
|
+
@suite.size
|
18
|
+
end
|
19
|
+
|
20
|
+
def add_tests(test_suite)
|
21
|
+
count = 0
|
22
|
+
if test_suite.respond_to? :tests
|
23
|
+
test_suite.tests.each do |test|
|
24
|
+
count += add_tests(test)
|
25
|
+
end
|
26
|
+
else
|
27
|
+
count += 1
|
28
|
+
@blackboard.write_work Test::WorkUnit.new(test_suite)
|
29
|
+
end
|
30
|
+
count
|
31
|
+
end
|
32
|
+
|
33
|
+
def read_results(result, count)
|
34
|
+
while count > 0
|
35
|
+
remote_result = @blackboard.take_result
|
36
|
+
next unless remote_result
|
37
|
+
count -= 1
|
38
|
+
remote_result.add_to result
|
39
|
+
# TODO: is this the right place for this next line? -Dan
|
40
|
+
print remote_result.output if remote_result.output
|
41
|
+
yield ::Test::Unit::TestCase::FINISHED, nil if block_given?
|
42
|
+
end
|
43
|
+
end
|
44
|
+
end
|
45
|
+
end
|
46
|
+
end
|
@@ -0,0 +1,36 @@
|
|
1
|
+
module DeepTest
|
2
|
+
module Test
|
3
|
+
class WorkUnit
|
4
|
+
def initialize(test_case)
|
5
|
+
@test_case = test_case
|
6
|
+
end
|
7
|
+
|
8
|
+
def run
|
9
|
+
result = run_without_deadlock_protection
|
10
|
+
result = run_without_deadlock_protection if result.failed_due_to_deadlock?
|
11
|
+
if result.failed_due_to_deadlock?
|
12
|
+
result = ::Test::Unit::TestResult.new
|
13
|
+
result.add_run
|
14
|
+
result.output = "-deadlock-"
|
15
|
+
end
|
16
|
+
result
|
17
|
+
end
|
18
|
+
|
19
|
+
def ==(other)
|
20
|
+
return false unless other.class == self.class
|
21
|
+
@test_case == other.instance_variable_get(:@test_case)
|
22
|
+
end
|
23
|
+
|
24
|
+
protected
|
25
|
+
|
26
|
+
def run_without_deadlock_protection
|
27
|
+
result = ::Test::Unit::TestResult.new
|
28
|
+
output = capture_stdout do
|
29
|
+
@test_case.run(result) {|channel,event|}
|
30
|
+
end
|
31
|
+
result.output = output
|
32
|
+
result
|
33
|
+
end
|
34
|
+
end
|
35
|
+
end
|
36
|
+
end
|
data/lib/deep_test/test_task.rb
CHANGED
@@ -1,10 +1,9 @@
|
|
1
1
|
module DeepTest
|
2
2
|
class TestTask
|
3
|
-
DEFAULT_NUMBER_OF_WORKERS = 2
|
4
|
-
attr_writer :number_of_workers, :pattern
|
5
|
-
|
6
3
|
def initialize(name = :deep_test)
|
7
4
|
@name = name
|
5
|
+
@options = Options.new({})
|
6
|
+
self.pattern = "test/**/*_test.rb"
|
8
7
|
yield self if block_given?
|
9
8
|
define
|
10
9
|
end
|
@@ -12,18 +11,46 @@ module DeepTest
|
|
12
11
|
def define
|
13
12
|
desc "Run '#{@name}' suite using DeepTest"
|
14
13
|
task @name do
|
15
|
-
|
16
|
-
runner = File.expand_path(File.dirname(__FILE__) + "/../../script/run_test_suite.rb")
|
17
|
-
ruby "-I#{deep_test_lib} #{runner} '#{number_of_workers}' '#{pattern}'"
|
14
|
+
ruby "#{runner} '#{@options.to_command_line}'"
|
18
15
|
end
|
19
16
|
end
|
20
|
-
|
17
|
+
|
21
18
|
def number_of_workers
|
22
|
-
@number_of_workers
|
19
|
+
@options.number_of_workers
|
20
|
+
end
|
21
|
+
|
22
|
+
def number_of_workers=(num)
|
23
|
+
@options.number_of_workers = num
|
23
24
|
end
|
24
25
|
|
25
26
|
def pattern
|
26
|
-
|
27
|
+
@options.pattern
|
28
|
+
end
|
29
|
+
|
30
|
+
def pattern=(pattern)
|
31
|
+
@options.pattern = Dir.pwd + "/" + pattern
|
32
|
+
end
|
33
|
+
|
34
|
+
def timeout_in_seconds=(seconds)
|
35
|
+
@options.timeout_in_seconds = seconds
|
27
36
|
end
|
37
|
+
|
38
|
+
def timeout_in_seconds
|
39
|
+
@options.timeout_in_seconds
|
40
|
+
end
|
41
|
+
|
42
|
+
def worker_listener=(listener)
|
43
|
+
@options.worker_listener = listener
|
44
|
+
end
|
45
|
+
|
46
|
+
def worker_listener
|
47
|
+
@options.worker_listener
|
48
|
+
end
|
49
|
+
|
50
|
+
private
|
51
|
+
|
52
|
+
def runner
|
53
|
+
File.expand_path(File.dirname(__FILE__) + "/../../script/run_test_suite.rb")
|
54
|
+
end
|
28
55
|
end
|
29
56
|
end
|
@@ -2,9 +2,10 @@ module DeepTest
|
|
2
2
|
class TupleSpaceFactory
|
3
3
|
def self.tuple_space
|
4
4
|
require "rinda/ring"
|
5
|
+
require "socket"
|
5
6
|
DRb.start_service
|
6
|
-
ts = Rinda::RingFinger.new([
|
7
|
-
|
7
|
+
ts = Rinda::RingFinger.new([Socket.gethostname],DeepTest::Server::PORT).lookup_ring_any
|
8
|
+
DeepTest.logger.debug "Connected to DeepTest server at #{ts.__drburi}"
|
8
9
|
Rinda::TupleSpaceProxy.new ts
|
9
10
|
end
|
10
11
|
end
|
data/lib/deep_test/warlock.rb
CHANGED
@@ -13,7 +13,7 @@ module DeepTest
|
|
13
13
|
end
|
14
14
|
raise "fatal: fork returned nil" if pid.nil?
|
15
15
|
@demons << [name, pid]
|
16
|
-
|
16
|
+
DeepTest.logger.debug "Started #{name} (#{pid})"
|
17
17
|
rescue => e
|
18
18
|
puts "exception starting #{name}: #{e}"
|
19
19
|
puts "\t" + e.backtrace.join("\n\t")
|
@@ -34,7 +34,7 @@ module DeepTest
|
|
34
34
|
rescue Errno::ECHILD => e
|
35
35
|
puts e
|
36
36
|
end
|
37
|
-
|
37
|
+
DeepTest.logger.debug "Stopped #{name} (#{pid})"
|
38
38
|
end
|
39
39
|
end
|
40
40
|
|
data/lib/deep_test/worker.rb
CHANGED
@@ -1,31 +1,21 @@
|
|
1
1
|
module DeepTest
|
2
2
|
class Worker
|
3
|
-
|
3
|
+
attr_reader :number
|
4
|
+
|
5
|
+
def initialize(number, blackboard, worker_listener)
|
6
|
+
@number = number
|
4
7
|
@blackboard = blackboard
|
8
|
+
@listener = worker_listener
|
5
9
|
end
|
6
10
|
|
7
11
|
def run
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
result.add_run
|
14
|
-
result.output = "-deadlock-"
|
15
|
-
end
|
12
|
+
@listener.starting(self)
|
13
|
+
while work_unit = @blackboard.take_work
|
14
|
+
@listener.starting_work(self, work_unit)
|
15
|
+
result = work_unit.run
|
16
|
+
@listener.finished_work(self, work_unit, result)
|
16
17
|
@blackboard.write_result result
|
17
18
|
end
|
18
19
|
end
|
19
|
-
|
20
|
-
protected
|
21
|
-
|
22
|
-
def run_test_case(test_case)
|
23
|
-
result = Test::Unit::TestResult.new
|
24
|
-
output = capture_stdout do
|
25
|
-
test_case.run(result) {|channel,event|}
|
26
|
-
end
|
27
|
-
result.output = output
|
28
|
-
result
|
29
|
-
end
|
30
20
|
end
|
31
21
|
end
|