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.
Files changed (117) hide show
  1. data/CHANGELOG +47 -0
  2. data/README.rdoc +228 -0
  3. data/Rakefile +247 -0
  4. data/bin/deep_test +15 -0
  5. data/lib/deep_test.rb +91 -0
  6. data/lib/deep_test/database/mysql_setup_listener.rb +112 -0
  7. data/lib/deep_test/database/postgresql_setup_listener.rb +116 -0
  8. data/lib/deep_test/database/setup_listener.rb +125 -0
  9. data/lib/deep_test/deadlock_detector.rb +7 -0
  10. data/lib/deep_test/distributed/dispatch_controller.rb +53 -0
  11. data/lib/deep_test/distributed/drb_client_connection_info.rb +15 -0
  12. data/lib/deep_test/distributed/filename_resolver.rb +40 -0
  13. data/lib/deep_test/distributed/master_test_server.rb +52 -0
  14. data/lib/deep_test/distributed/multi_test_server_proxy.rb +44 -0
  15. data/lib/deep_test/distributed/null_work_unit.rb +12 -0
  16. data/lib/deep_test/distributed/remote_worker_client.rb +54 -0
  17. data/lib/deep_test/distributed/remote_worker_server.rb +82 -0
  18. data/lib/deep_test/distributed/rsync.rb +37 -0
  19. data/lib/deep_test/distributed/show_status.rhtml +41 -0
  20. data/lib/deep_test/distributed/test_server.rb +78 -0
  21. data/lib/deep_test/distributed/test_server_status.rb +9 -0
  22. data/lib/deep_test/distributed/test_server_workers.rb +24 -0
  23. data/lib/deep_test/distributed/throughput_runner.rb +42 -0
  24. data/lib/deep_test/distributed/throughput_statistics.rb +26 -0
  25. data/lib/deep_test/distributed/throughput_worker_client.rb +19 -0
  26. data/lib/deep_test/extensions/drb_extension.rb +34 -0
  27. data/lib/deep_test/extensions/object_extension.rb +40 -0
  28. data/lib/deep_test/listener_list.rb +17 -0
  29. data/lib/deep_test/local_workers.rb +55 -0
  30. data/lib/deep_test/logger.rb +17 -0
  31. data/lib/deep_test/marshallable_exception_wrapper.rb +44 -0
  32. data/lib/deep_test/metrics/gatherer.rb +67 -0
  33. data/lib/deep_test/metrics/queue_lock_wait_time_measurement.rb +133 -0
  34. data/lib/deep_test/null_worker_listener.rb +62 -0
  35. data/lib/deep_test/option.rb +60 -0
  36. data/lib/deep_test/options.rb +110 -0
  37. data/lib/deep_test/process_orchestrator.rb +49 -0
  38. data/lib/deep_test/rake_tasks.rb +11 -0
  39. data/lib/deep_test/result_reader.rb +36 -0
  40. data/lib/deep_test/rspec_detector.rb +21 -0
  41. data/lib/deep_test/server.rb +75 -0
  42. data/lib/deep_test/spec.rb +13 -0
  43. data/lib/deep_test/spec/extensions/example_group_methods.rb +64 -0
  44. data/lib/deep_test/spec/extensions/example_methods.rb +46 -0
  45. data/lib/deep_test/spec/extensions/options.rb +43 -0
  46. data/lib/deep_test/spec/extensions/reporter.rb +29 -0
  47. data/lib/deep_test/spec/extensions/spec_task.rb +20 -0
  48. data/lib/deep_test/spec/runner.rb +57 -0
  49. data/lib/deep_test/spec/work_result.rb +33 -0
  50. data/lib/deep_test/spec/work_unit.rb +59 -0
  51. data/lib/deep_test/test.rb +10 -0
  52. data/lib/deep_test/test/extensions/error.rb +14 -0
  53. data/lib/deep_test/test/runner.rb +24 -0
  54. data/lib/deep_test/test/supervised_test_suite.rb +49 -0
  55. data/lib/deep_test/test/work_result.rb +34 -0
  56. data/lib/deep_test/test/work_unit.rb +40 -0
  57. data/lib/deep_test/test_task.rb +47 -0
  58. data/lib/deep_test/ui/console.rb +76 -0
  59. data/lib/deep_test/ui/null.rb +17 -0
  60. data/lib/deep_test/warlock.rb +134 -0
  61. data/lib/deep_test/worker.rb +57 -0
  62. data/script/internal/run_test_suite.rb +7 -0
  63. data/script/public/master_test_server.rb +24 -0
  64. data/script/public/test_server.rb +18 -0
  65. data/script/public/test_throughput.rb +29 -0
  66. data/spec/deep_test/option_spec.rb +33 -0
  67. data/spec/deep_test/options_spec.rb +183 -0
  68. data/spec/deep_test/spec/extensions/example_group_methods_spec.rb +48 -0
  69. data/spec/deep_test/spec/extensions/example_methods_spec.rb +61 -0
  70. data/spec/deep_test/spec/extensions/options_spec.rb +23 -0
  71. data/spec/deep_test/spec/extensions/reporter_spec.rb +28 -0
  72. data/spec/deep_test/spec/extensions/spec_task_spec.rb +36 -0
  73. data/spec/deep_test/spec/runner_spec.rb +106 -0
  74. data/spec/deep_test/spec/work_result_spec.rb +14 -0
  75. data/spec/deep_test/spec/work_unit_spec.rb +78 -0
  76. data/spec/spec_helper.rb +59 -0
  77. data/spec/thread_worker.rb +25 -0
  78. data/test/deep_test/database/mysql_setup_listener_test.rb +14 -0
  79. data/test/deep_test/distributed/dispatch_controller_test.rb +209 -0
  80. data/test/deep_test/distributed/drb_client_connection_info_test.rb +42 -0
  81. data/test/deep_test/distributed/filename_resolver_test.rb +52 -0
  82. data/test/deep_test/distributed/master_test_server_test.rb +32 -0
  83. data/test/deep_test/distributed/multi_test_server_proxy_test.rb +96 -0
  84. data/test/deep_test/distributed/remote_worker_client_test.rb +180 -0
  85. data/test/deep_test/distributed/remote_worker_server_test.rb +99 -0
  86. data/test/deep_test/distributed/rsync_test.rb +67 -0
  87. data/test/deep_test/distributed/test_server_test.rb +94 -0
  88. data/test/deep_test/distributed/test_server_workers_test.rb +26 -0
  89. data/test/deep_test/distributed/throughput_runner_test.rb +68 -0
  90. data/test/deep_test/distributed/throughput_worker_client_test.rb +28 -0
  91. data/test/deep_test/extensions/object_extension_test.rb +37 -0
  92. data/test/deep_test/listener_list_test.rb +20 -0
  93. data/test/deep_test/local_workers_test.rb +22 -0
  94. data/test/deep_test/logger_test.rb +11 -0
  95. data/test/deep_test/marshallable_exception_wrapper_test.rb +44 -0
  96. data/test/deep_test/metrics/gatherer_test.rb +66 -0
  97. data/test/deep_test/process_orchestrator_test.rb +11 -0
  98. data/test/deep_test/result_reader_test.rb +128 -0
  99. data/test/deep_test/server_test.rb +58 -0
  100. data/test/deep_test/test/extensions/error_test.rb +40 -0
  101. data/test/deep_test/test/runner_test.rb +7 -0
  102. data/test/deep_test/test/supervised_test_suite_test.rb +79 -0
  103. data/test/deep_test/test/work_result_test.rb +81 -0
  104. data/test/deep_test/test/work_unit_test.rb +61 -0
  105. data/test/deep_test/test_task_test.rb +43 -0
  106. data/test/deep_test/ui/console_test.rb +9 -0
  107. data/test/deep_test/warlock_test.rb +38 -0
  108. data/test/deep_test/worker_test.rb +94 -0
  109. data/test/failing.rake +11 -0
  110. data/test/failing.rb +7 -0
  111. data/test/fake_deadlock_error.rb +12 -0
  112. data/test/simple_test_blackboard.rb +45 -0
  113. data/test/simple_test_blackboard_test.rb +33 -0
  114. data/test/test_factory.rb +74 -0
  115. data/test/test_helper.rb +15 -0
  116. data/test/test_task_test.rb +72 -0
  117. 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
@@ -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