jperkins-deep_test 1.2.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- data/CHANGELOG +47 -0
- data/README.rdoc +228 -0
- data/Rakefile +247 -0
- data/bin/deep_test +15 -0
- data/lib/deep_test.rb +91 -0
- data/lib/deep_test/database/mysql_setup_listener.rb +112 -0
- data/lib/deep_test/database/postgresql_setup_listener.rb +116 -0
- data/lib/deep_test/database/setup_listener.rb +125 -0
- data/lib/deep_test/deadlock_detector.rb +7 -0
- data/lib/deep_test/distributed/dispatch_controller.rb +53 -0
- data/lib/deep_test/distributed/drb_client_connection_info.rb +15 -0
- data/lib/deep_test/distributed/filename_resolver.rb +40 -0
- data/lib/deep_test/distributed/master_test_server.rb +52 -0
- data/lib/deep_test/distributed/multi_test_server_proxy.rb +44 -0
- data/lib/deep_test/distributed/null_work_unit.rb +12 -0
- data/lib/deep_test/distributed/remote_worker_client.rb +54 -0
- data/lib/deep_test/distributed/remote_worker_server.rb +82 -0
- data/lib/deep_test/distributed/rsync.rb +37 -0
- data/lib/deep_test/distributed/show_status.rhtml +41 -0
- data/lib/deep_test/distributed/test_server.rb +78 -0
- data/lib/deep_test/distributed/test_server_status.rb +9 -0
- data/lib/deep_test/distributed/test_server_workers.rb +24 -0
- data/lib/deep_test/distributed/throughput_runner.rb +42 -0
- data/lib/deep_test/distributed/throughput_statistics.rb +26 -0
- data/lib/deep_test/distributed/throughput_worker_client.rb +19 -0
- data/lib/deep_test/extensions/drb_extension.rb +34 -0
- data/lib/deep_test/extensions/object_extension.rb +40 -0
- data/lib/deep_test/listener_list.rb +17 -0
- data/lib/deep_test/local_workers.rb +55 -0
- data/lib/deep_test/logger.rb +17 -0
- data/lib/deep_test/marshallable_exception_wrapper.rb +44 -0
- data/lib/deep_test/metrics/gatherer.rb +67 -0
- data/lib/deep_test/metrics/queue_lock_wait_time_measurement.rb +133 -0
- data/lib/deep_test/null_worker_listener.rb +62 -0
- data/lib/deep_test/option.rb +60 -0
- data/lib/deep_test/options.rb +110 -0
- data/lib/deep_test/process_orchestrator.rb +49 -0
- data/lib/deep_test/rake_tasks.rb +11 -0
- data/lib/deep_test/result_reader.rb +36 -0
- data/lib/deep_test/rspec_detector.rb +21 -0
- data/lib/deep_test/server.rb +75 -0
- data/lib/deep_test/spec.rb +13 -0
- data/lib/deep_test/spec/extensions/example_group_methods.rb +64 -0
- data/lib/deep_test/spec/extensions/example_methods.rb +46 -0
- data/lib/deep_test/spec/extensions/options.rb +43 -0
- data/lib/deep_test/spec/extensions/reporter.rb +29 -0
- data/lib/deep_test/spec/extensions/spec_task.rb +20 -0
- data/lib/deep_test/spec/runner.rb +57 -0
- data/lib/deep_test/spec/work_result.rb +33 -0
- data/lib/deep_test/spec/work_unit.rb +59 -0
- data/lib/deep_test/test.rb +10 -0
- data/lib/deep_test/test/extensions/error.rb +14 -0
- data/lib/deep_test/test/runner.rb +24 -0
- data/lib/deep_test/test/supervised_test_suite.rb +49 -0
- data/lib/deep_test/test/work_result.rb +34 -0
- data/lib/deep_test/test/work_unit.rb +40 -0
- data/lib/deep_test/test_task.rb +47 -0
- data/lib/deep_test/ui/console.rb +76 -0
- data/lib/deep_test/ui/null.rb +17 -0
- data/lib/deep_test/warlock.rb +134 -0
- data/lib/deep_test/worker.rb +57 -0
- data/script/internal/run_test_suite.rb +7 -0
- data/script/public/master_test_server.rb +24 -0
- data/script/public/test_server.rb +18 -0
- data/script/public/test_throughput.rb +29 -0
- data/spec/deep_test/option_spec.rb +33 -0
- data/spec/deep_test/options_spec.rb +183 -0
- data/spec/deep_test/spec/extensions/example_group_methods_spec.rb +48 -0
- data/spec/deep_test/spec/extensions/example_methods_spec.rb +61 -0
- data/spec/deep_test/spec/extensions/options_spec.rb +23 -0
- data/spec/deep_test/spec/extensions/reporter_spec.rb +28 -0
- data/spec/deep_test/spec/extensions/spec_task_spec.rb +36 -0
- data/spec/deep_test/spec/runner_spec.rb +106 -0
- data/spec/deep_test/spec/work_result_spec.rb +14 -0
- data/spec/deep_test/spec/work_unit_spec.rb +78 -0
- data/spec/spec_helper.rb +59 -0
- data/spec/thread_worker.rb +25 -0
- data/test/deep_test/database/mysql_setup_listener_test.rb +14 -0
- data/test/deep_test/distributed/dispatch_controller_test.rb +209 -0
- data/test/deep_test/distributed/drb_client_connection_info_test.rb +42 -0
- data/test/deep_test/distributed/filename_resolver_test.rb +52 -0
- data/test/deep_test/distributed/master_test_server_test.rb +32 -0
- data/test/deep_test/distributed/multi_test_server_proxy_test.rb +96 -0
- data/test/deep_test/distributed/remote_worker_client_test.rb +180 -0
- data/test/deep_test/distributed/remote_worker_server_test.rb +99 -0
- data/test/deep_test/distributed/rsync_test.rb +67 -0
- data/test/deep_test/distributed/test_server_test.rb +94 -0
- data/test/deep_test/distributed/test_server_workers_test.rb +26 -0
- data/test/deep_test/distributed/throughput_runner_test.rb +68 -0
- data/test/deep_test/distributed/throughput_worker_client_test.rb +28 -0
- data/test/deep_test/extensions/object_extension_test.rb +37 -0
- data/test/deep_test/listener_list_test.rb +20 -0
- data/test/deep_test/local_workers_test.rb +22 -0
- data/test/deep_test/logger_test.rb +11 -0
- data/test/deep_test/marshallable_exception_wrapper_test.rb +44 -0
- data/test/deep_test/metrics/gatherer_test.rb +66 -0
- data/test/deep_test/process_orchestrator_test.rb +11 -0
- data/test/deep_test/result_reader_test.rb +128 -0
- data/test/deep_test/server_test.rb +58 -0
- data/test/deep_test/test/extensions/error_test.rb +40 -0
- data/test/deep_test/test/runner_test.rb +7 -0
- data/test/deep_test/test/supervised_test_suite_test.rb +79 -0
- data/test/deep_test/test/work_result_test.rb +81 -0
- data/test/deep_test/test/work_unit_test.rb +61 -0
- data/test/deep_test/test_task_test.rb +43 -0
- data/test/deep_test/ui/console_test.rb +9 -0
- data/test/deep_test/warlock_test.rb +38 -0
- data/test/deep_test/worker_test.rb +94 -0
- data/test/failing.rake +11 -0
- data/test/failing.rb +7 -0
- data/test/fake_deadlock_error.rb +12 -0
- data/test/simple_test_blackboard.rb +45 -0
- data/test/simple_test_blackboard_test.rb +33 -0
- data/test/test_factory.rb +74 -0
- data/test/test_helper.rb +15 -0
- data/test/test_task_test.rb +72 -0
- metadata +214 -0
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
require File.dirname(__FILE__) + "/../../../spec_helper"
|
|
2
|
+
|
|
3
|
+
describe Spec::Runner::Options do
|
|
4
|
+
it_should_behave_like "sandboxed rspec_options"
|
|
5
|
+
|
|
6
|
+
it "should be able to run a single passing example" do
|
|
7
|
+
example_group = describe("test") do
|
|
8
|
+
it("passes") {1.should == 1}
|
|
9
|
+
it("fails") {1.should == 2}
|
|
10
|
+
end
|
|
11
|
+
options.run_one_example(example_group.examples.first.identifier)
|
|
12
|
+
options.reporter.passed?.should == true
|
|
13
|
+
end
|
|
14
|
+
|
|
15
|
+
it "should be able to run a single failing example" do
|
|
16
|
+
example_group = describe("test") do
|
|
17
|
+
it("passes") {1.should == 1}
|
|
18
|
+
it("fails") {1.should == 2}
|
|
19
|
+
end
|
|
20
|
+
options.run_one_example(example_group.examples.last.identifier)
|
|
21
|
+
options.reporter.passed?.should == false
|
|
22
|
+
end
|
|
23
|
+
end
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
require File.dirname(__FILE__) + "/../../../spec_helper"
|
|
2
|
+
|
|
3
|
+
describe Spec::Runner::Reporter do
|
|
4
|
+
it_should_behave_like "sandboxed rspec_options"
|
|
5
|
+
|
|
6
|
+
it "should be able to handle a failure without having any example groups" do
|
|
7
|
+
example_group = describe("test") do
|
|
8
|
+
it("example") {}
|
|
9
|
+
end
|
|
10
|
+
example = example_group.examples.first
|
|
11
|
+
reporter = Spec::Runner::Reporter.new(options)
|
|
12
|
+
lambda {
|
|
13
|
+
reporter.failure(example,RuntimeError.new)
|
|
14
|
+
}.should_not raise_error
|
|
15
|
+
end
|
|
16
|
+
|
|
17
|
+
it "should be able to handle a pending example without having any example groups" do
|
|
18
|
+
example_group = describe("test") do
|
|
19
|
+
it("example") {pending}
|
|
20
|
+
end
|
|
21
|
+
example = example_group.examples.first
|
|
22
|
+
reporter = Spec::Runner::Reporter.new(options)
|
|
23
|
+
lambda {
|
|
24
|
+
reporter.example_finished(example,::Spec::Example::ExamplePendingError.new)
|
|
25
|
+
}.should_not raise_error
|
|
26
|
+
end
|
|
27
|
+
end
|
|
28
|
+
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
require File.dirname(__FILE__) + "/../../../spec_helper"
|
|
2
|
+
|
|
3
|
+
describe Spec::Rake::SpecTask do
|
|
4
|
+
it "should allow deep_test configuration" do
|
|
5
|
+
t = Spec::Rake::SpecTask.new do |t|
|
|
6
|
+
t.deep_test :number_of_workers => 2
|
|
7
|
+
end
|
|
8
|
+
|
|
9
|
+
deep_test_path = File.expand_path(File.dirname(__FILE__) +
|
|
10
|
+
'/../../../../lib/deep_test')
|
|
11
|
+
options = DeepTest::Options.new(:number_of_workers => 2)
|
|
12
|
+
t.spec_opts.should == ["--require #{deep_test_path}",
|
|
13
|
+
"--runner 'DeepTest::Spec::Runner:#{options.to_command_line}'"]
|
|
14
|
+
end
|
|
15
|
+
|
|
16
|
+
it "should maintain deep_test options if spec_opts is set directly" do
|
|
17
|
+
t = Spec::Rake::SpecTask.new do |t|
|
|
18
|
+
t.deep_test({})
|
|
19
|
+
t.spec_opts = ["anoption"]
|
|
20
|
+
end
|
|
21
|
+
|
|
22
|
+
deep_test_path = File.expand_path(File.dirname(__FILE__) +
|
|
23
|
+
'/../../../../lib/deep_test')
|
|
24
|
+
options = DeepTest::Options.new({})
|
|
25
|
+
t.spec_opts.should == ["--require #{deep_test_path}",
|
|
26
|
+
"--runner 'DeepTest::Spec::Runner:#{options.to_command_line}'",
|
|
27
|
+
"anoption"]
|
|
28
|
+
end
|
|
29
|
+
|
|
30
|
+
it "should allow spec_opts to be set without deep_test" do
|
|
31
|
+
t = Spec::Rake::SpecTask.new do |t|
|
|
32
|
+
t.spec_opts = ["anoption"]
|
|
33
|
+
end
|
|
34
|
+
t.spec_opts.should == ["anoption"]
|
|
35
|
+
end
|
|
36
|
+
end
|
|
@@ -0,0 +1,106 @@
|
|
|
1
|
+
require File.dirname(__FILE__) + "/../../spec_helper"
|
|
2
|
+
|
|
3
|
+
module DeepTest
|
|
4
|
+
module Spec
|
|
5
|
+
describe Runner do
|
|
6
|
+
it_should_behave_like 'sandboxed rspec_options'
|
|
7
|
+
|
|
8
|
+
it "should run each test using blackboard" do
|
|
9
|
+
blackboard = SimpleTestBlackboard.new
|
|
10
|
+
runner = Runner.new(options, Options.new({}), blackboard)
|
|
11
|
+
|
|
12
|
+
describe("test") do
|
|
13
|
+
it("passes1") {}
|
|
14
|
+
it("passes2") {}
|
|
15
|
+
end
|
|
16
|
+
|
|
17
|
+
worker = ThreadWorker.new(blackboard, 2)
|
|
18
|
+
Timeout.timeout(5) do
|
|
19
|
+
runner.process_work_units.should == true
|
|
20
|
+
end
|
|
21
|
+
worker.wait_until_done
|
|
22
|
+
|
|
23
|
+
worker.work_done.should == 2
|
|
24
|
+
options.reporter.number_of_examples.should == 2
|
|
25
|
+
blackboard.take_result.should be_nil
|
|
26
|
+
options.reporter.examples_finished.should == ['passes1','passes2']
|
|
27
|
+
options.reporter.should be_ended
|
|
28
|
+
end
|
|
29
|
+
|
|
30
|
+
it "should return failure when a spec fails" do
|
|
31
|
+
blackboard = SimpleTestBlackboard.new
|
|
32
|
+
runner = Runner.new(options, Options.new({}), blackboard)
|
|
33
|
+
|
|
34
|
+
describe("test") do
|
|
35
|
+
it("passes") {};
|
|
36
|
+
it("fails") {1.should == 2};
|
|
37
|
+
end
|
|
38
|
+
|
|
39
|
+
worker = ThreadWorker.new(blackboard, 2)
|
|
40
|
+
Timeout.timeout(5) do
|
|
41
|
+
runner.process_work_units.should == false
|
|
42
|
+
end
|
|
43
|
+
worker.wait_until_done
|
|
44
|
+
end
|
|
45
|
+
|
|
46
|
+
it "should return success when there are pending examples" do
|
|
47
|
+
blackboard = SimpleTestBlackboard.new
|
|
48
|
+
runner = Runner.new(options, Options.new({}), blackboard)
|
|
49
|
+
|
|
50
|
+
describe("test") do
|
|
51
|
+
it("pending") {pending {1.should == 2}};
|
|
52
|
+
end
|
|
53
|
+
|
|
54
|
+
worker = ThreadWorker.new(blackboard, 1)
|
|
55
|
+
Timeout.timeout(5) do
|
|
56
|
+
runner.process_work_units.should == true
|
|
57
|
+
end
|
|
58
|
+
worker.wait_until_done
|
|
59
|
+
end
|
|
60
|
+
|
|
61
|
+
it "should return failure when a pending example passes" do
|
|
62
|
+
blackboard = SimpleTestBlackboard.new
|
|
63
|
+
runner = Runner.new(options, Options.new({}), blackboard)
|
|
64
|
+
|
|
65
|
+
describe("test") do
|
|
66
|
+
it("pending") {pending {1.should == 1}};
|
|
67
|
+
end
|
|
68
|
+
|
|
69
|
+
worker = ThreadWorker.new(blackboard, 1)
|
|
70
|
+
Timeout.timeout(5) do
|
|
71
|
+
runner.process_work_units.should == false
|
|
72
|
+
end
|
|
73
|
+
worker.wait_until_done
|
|
74
|
+
end
|
|
75
|
+
|
|
76
|
+
it "should return failure when a worker error occurs" do
|
|
77
|
+
blackboard = SimpleTestBlackboard.new
|
|
78
|
+
runner = Runner.new(options, Options.new({}), blackboard)
|
|
79
|
+
|
|
80
|
+
describe("test") do
|
|
81
|
+
it("pending") {pending {1.should == 1}};
|
|
82
|
+
end
|
|
83
|
+
|
|
84
|
+
blackboard.write_result Worker::Error.new("example", RuntimeError.new)
|
|
85
|
+
capture_stdout do
|
|
86
|
+
runner.process_work_units.should == false
|
|
87
|
+
end
|
|
88
|
+
|
|
89
|
+
options.reporter.number_of_errors.should == 1
|
|
90
|
+
end
|
|
91
|
+
|
|
92
|
+
it "should raise error if duplicate spec is found" do
|
|
93
|
+
blackboard = SimpleTestBlackboard.new
|
|
94
|
+
runner = Runner.new(options, Options.new({}), blackboard)
|
|
95
|
+
|
|
96
|
+
describe("test") do
|
|
97
|
+
2.times {it("example") {}};
|
|
98
|
+
end
|
|
99
|
+
|
|
100
|
+
lambda {
|
|
101
|
+
runner.process_work_units
|
|
102
|
+
}.should raise_error
|
|
103
|
+
end
|
|
104
|
+
end
|
|
105
|
+
end
|
|
106
|
+
end
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
require File.dirname(__FILE__) + "/../../spec_helper"
|
|
2
|
+
|
|
3
|
+
describe DeepTest::Spec::WorkResult do
|
|
4
|
+
it "should make errors marshallable" do
|
|
5
|
+
result = DeepTest::Spec::WorkResult.new("id", Exception.new, nil)
|
|
6
|
+
result.instance_variable_get(:@error).should be_instance_of(DeepTest::MarshallableExceptionWrapper)
|
|
7
|
+
result.error.should be_instance_of(Exception)
|
|
8
|
+
end
|
|
9
|
+
|
|
10
|
+
it "should preserve nil errors" do
|
|
11
|
+
result = DeepTest::Spec::WorkResult.new("id", nil, nil)
|
|
12
|
+
result.error.should be_nil
|
|
13
|
+
end
|
|
14
|
+
end
|
|
@@ -0,0 +1,78 @@
|
|
|
1
|
+
require File.dirname(__FILE__) + "/../../spec_helper"
|
|
2
|
+
|
|
3
|
+
describe DeepTest::Spec::WorkUnit do
|
|
4
|
+
it_should_behave_like "sandboxed rspec_options"
|
|
5
|
+
|
|
6
|
+
it "should run the example specified by location" do
|
|
7
|
+
spec_was_run = false
|
|
8
|
+
group = describe("test") do
|
|
9
|
+
it("passes") {spec_was_run = true}
|
|
10
|
+
end
|
|
11
|
+
work_unit = DeepTest::Spec::WorkUnit.new(group.examples.first.identifier)
|
|
12
|
+
work_unit.run
|
|
13
|
+
spec_was_run.should == true
|
|
14
|
+
end
|
|
15
|
+
|
|
16
|
+
it "should return a Spec::WorkResult with the location and errors" do
|
|
17
|
+
error = RuntimeError.new
|
|
18
|
+
group = describe("test") do
|
|
19
|
+
it("fails") {raise error}
|
|
20
|
+
end
|
|
21
|
+
id = group.examples.first.identifier
|
|
22
|
+
work_unit = DeepTest::Spec::WorkUnit.new(id)
|
|
23
|
+
work_unit.run.should == DeepTest::Spec::WorkResult.new(id, error, nil)
|
|
24
|
+
end
|
|
25
|
+
|
|
26
|
+
it "should preserve the original rspec_options reporter" do
|
|
27
|
+
group = describe("test") do
|
|
28
|
+
it("passes") {}
|
|
29
|
+
end
|
|
30
|
+
original_reporter = options.reporter
|
|
31
|
+
work_unit = DeepTest::Spec::WorkUnit.new(group.examples.first.identifier)
|
|
32
|
+
work_unit.run
|
|
33
|
+
options.reporter.should == original_reporter
|
|
34
|
+
end
|
|
35
|
+
|
|
36
|
+
it "should retry examples that fail due to deadlock once" do
|
|
37
|
+
example_run_count = 0
|
|
38
|
+
group = describe("test") do
|
|
39
|
+
it("passes") {example_run_count += 1; raise FakeDeadlockError.new if example_run_count == 1};
|
|
40
|
+
end
|
|
41
|
+
work_unit = DeepTest::Spec::WorkUnit.new(group.examples.first.identifier)
|
|
42
|
+
result = work_unit.run
|
|
43
|
+
example_run_count.should == 2
|
|
44
|
+
result.error.should == nil
|
|
45
|
+
end
|
|
46
|
+
|
|
47
|
+
it "should move on without failing test if example fails do to deadlock more than once" do
|
|
48
|
+
example_run_count = 0
|
|
49
|
+
group = describe("test") do
|
|
50
|
+
it("passes") {example_run_count += 1; raise FakeDeadlockError.new};
|
|
51
|
+
end
|
|
52
|
+
work_unit = DeepTest::Spec::WorkUnit.new(group.examples.first.identifier)
|
|
53
|
+
result = work_unit.run
|
|
54
|
+
example_run_count.should == 2
|
|
55
|
+
result.error.should == nil
|
|
56
|
+
result.output.should == '-deadlock-'
|
|
57
|
+
end
|
|
58
|
+
|
|
59
|
+
it "should only run examples that don't fail due to deadlock once" do
|
|
60
|
+
example_run_count = 0
|
|
61
|
+
group = describe("test") do
|
|
62
|
+
it("passes") {example_run_count += 1; raise "Error"}
|
|
63
|
+
end
|
|
64
|
+
work_unit = DeepTest::Spec::WorkUnit.new(group.examples.first.identifier)
|
|
65
|
+
result = work_unit.run
|
|
66
|
+
example_run_count.should == 1
|
|
67
|
+
result.error.message.should == "Error"
|
|
68
|
+
end
|
|
69
|
+
|
|
70
|
+
it "should provide useful description as string" do
|
|
71
|
+
group = describe("my example") do
|
|
72
|
+
it("passes") {}
|
|
73
|
+
end
|
|
74
|
+
work_unit = DeepTest::Spec::WorkUnit.new(group.examples.first.identifier)
|
|
75
|
+
|
|
76
|
+
work_unit.to_s.should == "my example: passes"
|
|
77
|
+
end
|
|
78
|
+
end
|
data/spec/spec_helper.rb
ADDED
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
require 'rubygems'
|
|
2
|
+
gem 'rspec', '=1.1.8'
|
|
3
|
+
require 'spec'
|
|
4
|
+
|
|
5
|
+
require File.dirname(__FILE__) + "/../lib/deep_test"
|
|
6
|
+
require File.dirname(__FILE__) + "/../test/fake_deadlock_error"
|
|
7
|
+
require File.dirname(__FILE__) + "/../test/simple_test_blackboard"
|
|
8
|
+
require File.dirname(__FILE__) + "/thread_worker"
|
|
9
|
+
|
|
10
|
+
describe "sandboxed rspec_options", :shared => true do
|
|
11
|
+
attr_reader :options
|
|
12
|
+
|
|
13
|
+
before(:each) do
|
|
14
|
+
@original_rspec_options = ::Spec::Runner.options
|
|
15
|
+
@options = ::Spec::Runner::Options.new(StringIO.new, StringIO.new)
|
|
16
|
+
@options.reporter = FakeReporter.new
|
|
17
|
+
::Spec::Runner.use @options
|
|
18
|
+
end
|
|
19
|
+
|
|
20
|
+
after(:each) do
|
|
21
|
+
::Spec::Runner.use @original_rspec_options
|
|
22
|
+
end
|
|
23
|
+
|
|
24
|
+
class FakeReporter
|
|
25
|
+
attr_reader :number_of_examples, :examples_finished, :number_of_errors
|
|
26
|
+
|
|
27
|
+
def initialize
|
|
28
|
+
@examples_finished = []
|
|
29
|
+
@number_of_errors = 0
|
|
30
|
+
end
|
|
31
|
+
|
|
32
|
+
def example_started(example) end
|
|
33
|
+
def add_example_group(example_group) end
|
|
34
|
+
|
|
35
|
+
def end
|
|
36
|
+
@ended = true
|
|
37
|
+
end
|
|
38
|
+
|
|
39
|
+
def ended?
|
|
40
|
+
@ended == true
|
|
41
|
+
end
|
|
42
|
+
|
|
43
|
+
def dump; end
|
|
44
|
+
|
|
45
|
+
def start(number_of_examples)
|
|
46
|
+
@number_of_examples = number_of_examples
|
|
47
|
+
end
|
|
48
|
+
|
|
49
|
+
def example_finished(example, error)
|
|
50
|
+
@examples_finished << example.description
|
|
51
|
+
@number_of_errors += 1 if error
|
|
52
|
+
@error = error
|
|
53
|
+
end
|
|
54
|
+
|
|
55
|
+
def passed?
|
|
56
|
+
@error == nil
|
|
57
|
+
end
|
|
58
|
+
end
|
|
59
|
+
end
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
class ThreadWorker
|
|
2
|
+
attr_reader :work_done
|
|
3
|
+
|
|
4
|
+
def initialize(blackboard, expected_work)
|
|
5
|
+
@blackboard, @expected_work = blackboard, expected_work
|
|
6
|
+
@thread = Thread.new {run}
|
|
7
|
+
end
|
|
8
|
+
|
|
9
|
+
def wait_until_done
|
|
10
|
+
Timeout.timeout(5) {@thread.join}
|
|
11
|
+
@thread.kill if @thread.alive?
|
|
12
|
+
end
|
|
13
|
+
|
|
14
|
+
def run
|
|
15
|
+
@work_done = 0
|
|
16
|
+
until @work_done >= @expected_work
|
|
17
|
+
Thread.pass
|
|
18
|
+
work = @blackboard.take_work
|
|
19
|
+
if work
|
|
20
|
+
@blackboard.write_result work.run
|
|
21
|
+
@work_done += 1
|
|
22
|
+
end
|
|
23
|
+
end
|
|
24
|
+
end
|
|
25
|
+
end
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
require File.dirname(__FILE__) + "/../../test_helper"
|
|
2
|
+
|
|
3
|
+
unit_tests do
|
|
4
|
+
test "dump_schema includes procedures" do
|
|
5
|
+
listener = DeepTest::Database::MysqlSetupListener.new
|
|
6
|
+
listener.expects(:system).with do |command|
|
|
7
|
+
command =~ / -R /
|
|
8
|
+
end
|
|
9
|
+
listener.expects(:master_database_config).returns({})
|
|
10
|
+
listener.expects(:dump_file_name).returns("")
|
|
11
|
+
$?.expects(:success?).returns(true)
|
|
12
|
+
listener.dump_schema
|
|
13
|
+
end
|
|
14
|
+
end
|
|
@@ -0,0 +1,209 @@
|
|
|
1
|
+
require File.dirname(__FILE__) + "/../../test_helper"
|
|
2
|
+
|
|
3
|
+
unit_tests do
|
|
4
|
+
test "dispatch invokes each receiver once" do
|
|
5
|
+
receiver_1, receiver_2 = mock, mock
|
|
6
|
+
|
|
7
|
+
controller = DeepTest::Distributed::DispatchController.new(
|
|
8
|
+
DeepTest::Options.new({:ui => "DeepTest::UI::Null"}),
|
|
9
|
+
[receiver_1, receiver_2]
|
|
10
|
+
)
|
|
11
|
+
|
|
12
|
+
receiver_1.expects(:a_method).with(:args)
|
|
13
|
+
receiver_2.expects(:a_method).with(:args)
|
|
14
|
+
|
|
15
|
+
controller.dispatch(:a_method, :args)
|
|
16
|
+
end
|
|
17
|
+
|
|
18
|
+
test "dispatch returns array of all results" do
|
|
19
|
+
receiver_1, receiver_2 = mock, mock
|
|
20
|
+
|
|
21
|
+
controller = DeepTest::Distributed::DispatchController.new(
|
|
22
|
+
DeepTest::Options.new({:ui => "DeepTest::UI::Null"}),
|
|
23
|
+
[receiver_1, receiver_2]
|
|
24
|
+
)
|
|
25
|
+
|
|
26
|
+
receiver_1.expects(:a_method).returns(:result_1)
|
|
27
|
+
receiver_2.expects(:a_method).returns(:result_2)
|
|
28
|
+
|
|
29
|
+
results = controller.dispatch(:a_method)
|
|
30
|
+
assert_equal 2, results.size
|
|
31
|
+
assert_equal [:result_1, :result_2].to_set, results.to_set
|
|
32
|
+
end
|
|
33
|
+
|
|
34
|
+
test "dispatch calls all receivers in parallel" do
|
|
35
|
+
options = DeepTest::Options.new({:ui => "DeepTest::UI::Null"})
|
|
36
|
+
waiter = Waiter.new(tracker = Tracker.new)
|
|
37
|
+
|
|
38
|
+
Timeout.timeout(1) do
|
|
39
|
+
DeepTest::Distributed::DispatchController.new(options,[tracker, waiter]).
|
|
40
|
+
dispatch(:tracked_method)
|
|
41
|
+
end
|
|
42
|
+
|
|
43
|
+
waiter = Waiter.new(tracker = Tracker.new)
|
|
44
|
+
|
|
45
|
+
Timeout.timeout(1) do
|
|
46
|
+
DeepTest::Distributed::DispatchController.new(options,[waiter, tracker]).
|
|
47
|
+
dispatch(:tracked_method)
|
|
48
|
+
end
|
|
49
|
+
end
|
|
50
|
+
|
|
51
|
+
test "dispatch omits results that are taking too long" do
|
|
52
|
+
receiver = Object.new
|
|
53
|
+
def receiver.__drburi; ""; end
|
|
54
|
+
def receiver.sleep_100_millis
|
|
55
|
+
sleep 0.1
|
|
56
|
+
end
|
|
57
|
+
|
|
58
|
+
controller = DeepTest::Distributed::DispatchController.new(
|
|
59
|
+
DeepTest::Options.new({:ui => "DeepTest::UI::Null", :timeout_in_seconds => 0.05}),
|
|
60
|
+
[receiver]
|
|
61
|
+
)
|
|
62
|
+
|
|
63
|
+
DeepTest.logger.expects(:error)
|
|
64
|
+
|
|
65
|
+
assert_equal [], controller.dispatch(:sleep_100_millis)
|
|
66
|
+
end
|
|
67
|
+
|
|
68
|
+
test "after timeout, no further calls are sent to that receiver" do
|
|
69
|
+
receiver_1, receiver_2 = mock(:__drburi => ""), mock
|
|
70
|
+
receiver_1.expects(:method_call_1).raises(Timeout::Error.new("message"))
|
|
71
|
+
receiver_1.expects(:method_call_2).never
|
|
72
|
+
|
|
73
|
+
receiver_2.expects(:method_call_1)
|
|
74
|
+
receiver_2.expects(:method_call_2)
|
|
75
|
+
|
|
76
|
+
controller = DeepTest::Distributed::DispatchController.new(
|
|
77
|
+
DeepTest::Options.new({:ui => "DeepTest::UI::Null", :timeout_in_seconds => 0.05}),
|
|
78
|
+
[receiver_1, receiver_2]
|
|
79
|
+
)
|
|
80
|
+
|
|
81
|
+
DeepTest.logger.expects(:error)
|
|
82
|
+
|
|
83
|
+
controller.dispatch(:method_call_1)
|
|
84
|
+
controller.dispatch(:method_call_2)
|
|
85
|
+
end
|
|
86
|
+
|
|
87
|
+
test "receiver is dropped when connection is refused" do
|
|
88
|
+
receiver_1, receiver_2 = mock(:__drburi => ""), mock
|
|
89
|
+
receiver_1.expects(:method_call_1).raises(DRb::DRbConnError)
|
|
90
|
+
receiver_1.expects(:method_call_2).never
|
|
91
|
+
|
|
92
|
+
receiver_2.expects(:method_call_1).returns(:value)
|
|
93
|
+
receiver_2.expects(:method_call_2)
|
|
94
|
+
|
|
95
|
+
controller = DeepTest::Distributed::DispatchController.new(
|
|
96
|
+
DeepTest::Options.new({:ui => "DeepTest::UI::Null", :timeout_in_seconds => 0.05}),
|
|
97
|
+
[receiver_1, receiver_2]
|
|
98
|
+
)
|
|
99
|
+
|
|
100
|
+
DeepTest.logger.expects(:error)
|
|
101
|
+
|
|
102
|
+
assert_equal [:value], controller.dispatch(:method_call_1)
|
|
103
|
+
|
|
104
|
+
controller.dispatch(:method_call_2)
|
|
105
|
+
end
|
|
106
|
+
|
|
107
|
+
test "receiver is dropped when any exception occurs" do
|
|
108
|
+
receiver = mock(:__drburi => "")
|
|
109
|
+
receiver.expects(:method_call).raises(Exception)
|
|
110
|
+
|
|
111
|
+
controller = DeepTest::Distributed::DispatchController.new(
|
|
112
|
+
DeepTest::Options.new({:ui => "DeepTest::UI::Null", :timeout_in_seconds => 0.05}),
|
|
113
|
+
[receiver]
|
|
114
|
+
)
|
|
115
|
+
|
|
116
|
+
DeepTest.logger.expects(:error)
|
|
117
|
+
|
|
118
|
+
controller.dispatch(:method_call)
|
|
119
|
+
assert_raises(DeepTest::Distributed::NoDispatchReceiversError) {controller.dispatch(:another_call)}
|
|
120
|
+
end
|
|
121
|
+
|
|
122
|
+
test "no error is printed if dispatching without error" do
|
|
123
|
+
receiver_1 = mock
|
|
124
|
+
receiver_1.expects(:method_call_1).raises(DRb::DRbConnError)
|
|
125
|
+
|
|
126
|
+
controller = DeepTest::Distributed::DispatchController.new(
|
|
127
|
+
DeepTest::Options.new({:ui => "DeepTest::UI::Null", :timeout_in_seconds => 0.05}),
|
|
128
|
+
[receiver_1]
|
|
129
|
+
)
|
|
130
|
+
|
|
131
|
+
DeepTest.logger.expects(:error).never
|
|
132
|
+
|
|
133
|
+
controller.dispatch_with_options(:method_call_1, :ignore_connection_error => true)
|
|
134
|
+
end
|
|
135
|
+
|
|
136
|
+
test "dispatch calls notifies ui of start and stop of dispatch" do
|
|
137
|
+
options = DeepTest::Options.new({:ui => "DeepTest::UI::Null"})
|
|
138
|
+
controller = DeepTest::Distributed::DispatchController.new(
|
|
139
|
+
options, [stub_everything]
|
|
140
|
+
)
|
|
141
|
+
|
|
142
|
+
options.ui_instance.expects(:dispatch_starting).with(:method_name)
|
|
143
|
+
options.ui_instance.expects(:dispatch_finished).with(:method_name)
|
|
144
|
+
|
|
145
|
+
controller.dispatch(:method_name)
|
|
146
|
+
end
|
|
147
|
+
|
|
148
|
+
test "dispatch calls notifies ui dispatch end in case of an error" do
|
|
149
|
+
options = DeepTest::Options.new({:ui => "DeepTest::UI::Null"})
|
|
150
|
+
controller = DeepTest::Distributed::DispatchController.new(
|
|
151
|
+
options, [receiver = mock(:__drburi => '')]
|
|
152
|
+
)
|
|
153
|
+
receiver.expects(:method_name).raises("An Error")
|
|
154
|
+
DeepTest.logger.expects(:error)
|
|
155
|
+
|
|
156
|
+
options.ui_instance.expects(:dispatch_starting).with(:method_name)
|
|
157
|
+
options.ui_instance.expects(:dispatch_finished).with(:method_name)
|
|
158
|
+
|
|
159
|
+
begin
|
|
160
|
+
controller.dispatch(:method_name)
|
|
161
|
+
rescue RuntimeError => e
|
|
162
|
+
raise unless e.message == "An Error"
|
|
163
|
+
end
|
|
164
|
+
end
|
|
165
|
+
|
|
166
|
+
test "error is raised if dispatch to no receivers in attempted" do
|
|
167
|
+
options = DeepTest::Options.new({:ui => "DeepTest::UI::Null"})
|
|
168
|
+
controller = DeepTest::Distributed::DispatchController.new(
|
|
169
|
+
options, []
|
|
170
|
+
)
|
|
171
|
+
|
|
172
|
+
assert_raises(DeepTest::Distributed::NoDispatchReceiversError) do
|
|
173
|
+
controller.dispatch(:any_method)
|
|
174
|
+
end
|
|
175
|
+
end
|
|
176
|
+
|
|
177
|
+
class Tracker
|
|
178
|
+
def initialize
|
|
179
|
+
@mutex = Mutex.new
|
|
180
|
+
@condvar = ConditionVariable.new
|
|
181
|
+
end
|
|
182
|
+
|
|
183
|
+
def tracked_method
|
|
184
|
+
@mutex.synchronize do
|
|
185
|
+
@tracked_method_called = true
|
|
186
|
+
@condvar.broadcast
|
|
187
|
+
end
|
|
188
|
+
end
|
|
189
|
+
|
|
190
|
+
def wait_for_tracked_method
|
|
191
|
+
@mutex.synchronize do
|
|
192
|
+
loop do
|
|
193
|
+
return if @tracked_method_called
|
|
194
|
+
@condvar.wait(@mutex)
|
|
195
|
+
end
|
|
196
|
+
end
|
|
197
|
+
end
|
|
198
|
+
end
|
|
199
|
+
|
|
200
|
+
class Waiter
|
|
201
|
+
def initialize(tracker)
|
|
202
|
+
@tracker = tracker
|
|
203
|
+
end
|
|
204
|
+
|
|
205
|
+
def tracked_method
|
|
206
|
+
@tracker.wait_for_tracked_method
|
|
207
|
+
end
|
|
208
|
+
end
|
|
209
|
+
end
|