deep_test_pre 2.0

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 (98) hide show
  1. data/CHANGELOG +47 -0
  2. data/README.rdoc +199 -0
  3. data/Rakefile +137 -0
  4. data/lib/deep_test.rb +78 -0
  5. data/lib/deep_test/agent.rb +108 -0
  6. data/lib/deep_test/central_command.rb +165 -0
  7. data/lib/deep_test/cpu_info.rb +22 -0
  8. data/lib/deep_test/database/mysql_setup_listener.rb +112 -0
  9. data/lib/deep_test/database/setup_listener.rb +116 -0
  10. data/lib/deep_test/deadlock_detector.rb +7 -0
  11. data/lib/deep_test/demon.rb +25 -0
  12. data/lib/deep_test/distributed/beachhead.rb +104 -0
  13. data/lib/deep_test/distributed/dispatch_controller.rb +60 -0
  14. data/lib/deep_test/distributed/establish_beachhead.rb +19 -0
  15. data/lib/deep_test/distributed/filename_resolver.rb +40 -0
  16. data/lib/deep_test/distributed/landing_fleet.rb +30 -0
  17. data/lib/deep_test/distributed/landing_ship.rb +60 -0
  18. data/lib/deep_test/distributed/remote_deployment.rb +56 -0
  19. data/lib/deep_test/distributed/rsync.rb +50 -0
  20. data/lib/deep_test/distributed/shell_environment.rb +50 -0
  21. data/lib/deep_test/distributed/ssh_client_connection_info.rb +14 -0
  22. data/lib/deep_test/extensions/object_extension.rb +40 -0
  23. data/lib/deep_test/failure_message.rb +19 -0
  24. data/lib/deep_test/lib_root.rb +4 -0
  25. data/lib/deep_test/listener_list.rb +17 -0
  26. data/lib/deep_test/local_deployment.rb +46 -0
  27. data/lib/deep_test/logger.rb +32 -0
  28. data/lib/deep_test/main.rb +41 -0
  29. data/lib/deep_test/marshallable_exception_wrapper.rb +44 -0
  30. data/lib/deep_test/metrics/data.rb +34 -0
  31. data/lib/deep_test/metrics/measurement.rb +39 -0
  32. data/lib/deep_test/null_listener.rb +62 -0
  33. data/lib/deep_test/options.rb +113 -0
  34. data/lib/deep_test/proxy_io.rb +77 -0
  35. data/lib/deep_test/rake_tasks.rb +13 -0
  36. data/lib/deep_test/result_reader.rb +40 -0
  37. data/lib/deep_test/rspec_detector.rb +21 -0
  38. data/lib/deep_test/spec.rb +17 -0
  39. data/lib/deep_test/spec/extensions/example_group_methods.rb +64 -0
  40. data/lib/deep_test/spec/extensions/example_methods.rb +52 -0
  41. data/lib/deep_test/spec/extensions/options.rb +43 -0
  42. data/lib/deep_test/spec/extensions/spec_task.rb +21 -0
  43. data/lib/deep_test/spec/runner.rb +72 -0
  44. data/lib/deep_test/spec/work_result.rb +35 -0
  45. data/lib/deep_test/spec/work_unit.rb +59 -0
  46. data/lib/deep_test/test.rb +10 -0
  47. data/lib/deep_test/test/extensions/error.rb +14 -0
  48. data/lib/deep_test/test/run_test_suite.rb +5 -0
  49. data/lib/deep_test/test/runner.rb +24 -0
  50. data/lib/deep_test/test/supervised_test_suite.rb +48 -0
  51. data/lib/deep_test/test/work_result.rb +35 -0
  52. data/lib/deep_test/test/work_unit.rb +40 -0
  53. data/lib/deep_test/test_task.rb +47 -0
  54. data/lib/deep_test/ui/console.rb +74 -0
  55. data/lib/deep_test/ui/null.rb +17 -0
  56. data/lib/deep_test/warlock.rb +146 -0
  57. data/lib/telegraph.rb +29 -0
  58. data/lib/telegraph/ack_sequence.rb +14 -0
  59. data/lib/telegraph/logging.rb +20 -0
  60. data/lib/telegraph/message.rb +39 -0
  61. data/lib/telegraph/operator.rb +47 -0
  62. data/lib/telegraph/switchboard.rb +57 -0
  63. data/lib/telegraph/wire.rb +73 -0
  64. data/test/deep_test/agent_test.rb +175 -0
  65. data/test/deep_test/central_command_test.rb +147 -0
  66. data/test/deep_test/cpu_info_test.rb +33 -0
  67. data/test/deep_test/database/mysql_setup_listener_test.rb +18 -0
  68. data/test/deep_test/demon_test.rb +23 -0
  69. data/test/deep_test/distributed/beachhead_test.rb +67 -0
  70. data/test/deep_test/distributed/dispatch_controller_test.rb +162 -0
  71. data/test/deep_test/distributed/filename_resolver_test.rb +56 -0
  72. data/test/deep_test/distributed/landing_fleet_test.rb +55 -0
  73. data/test/deep_test/distributed/landing_ship_test.rb +48 -0
  74. data/test/deep_test/distributed/remote_deployment_test.rb +134 -0
  75. data/test/deep_test/distributed/rsync_test.rb +47 -0
  76. data/test/deep_test/distributed/shell_environment_test.rb +108 -0
  77. data/test/deep_test/distributed/ssh_client_connection_info_test.rb +34 -0
  78. data/test/deep_test/extensions/object_extension_test.rb +37 -0
  79. data/test/deep_test/listener_list_test.rb +22 -0
  80. data/test/deep_test/local_deployment_test.rb +19 -0
  81. data/test/deep_test/logger_test.rb +38 -0
  82. data/test/deep_test/main_test.rb +12 -0
  83. data/test/deep_test/marshallable_exception_wrapper_test.rb +46 -0
  84. data/test/deep_test/metrics/data_test.rb +22 -0
  85. data/test/deep_test/metrics/measurement_test.rb +18 -0
  86. data/test/deep_test/proxy_io_test.rb +104 -0
  87. data/test/deep_test/result_reader_test.rb +128 -0
  88. data/test/deep_test/test/extensions/error_test.rb +42 -0
  89. data/test/deep_test/test/runner_test.rb +11 -0
  90. data/test/deep_test/test/supervised_test_suite_test.rb +107 -0
  91. data/test/deep_test/test/work_result_test.rb +85 -0
  92. data/test/deep_test/test/work_unit_test.rb +63 -0
  93. data/test/deep_test/test_task_test.rb +15 -0
  94. data/test/deep_test/ui/console_test.rb +13 -0
  95. data/test/deep_test/warlock_test.rb +40 -0
  96. data/test/test_helper.rb +30 -0
  97. data/test/test_task_test.rb +75 -0
  98. metadata +156 -0
@@ -0,0 +1,113 @@
1
+ module DeepTest
2
+ Option = Struct.new :name, :default unless defined?(Option)
3
+
4
+ class Options
5
+ unless defined?(VALID_OPTIONS)
6
+ VALID_OPTIONS = [
7
+ Option.new(:distributed_hosts, nil),
8
+ Option.new(:number_of_agents, nil),
9
+ Option.new(:metrics_file, nil),
10
+ Option.new(:pattern, nil),
11
+ Option.new(:server_port, nil),
12
+ Option.new(:sync_options, {}),
13
+ Option.new(:ui, "DeepTest::UI::Console"),
14
+ Option.new(:listener, "DeepTest::NullListener"),
15
+ ]
16
+ end
17
+
18
+ attr_accessor *VALID_OPTIONS.map {|o| o.name}
19
+ attr_accessor :ssh_client_connection_info, :environment_log_level
20
+
21
+ def number_of_agents
22
+ return CpuInfo.new.count unless @number_of_agents
23
+ @number_of_agents
24
+ end
25
+
26
+ def ui=(value)
27
+ @ui = value.to_s
28
+ end
29
+
30
+ def listener=(value)
31
+ @listener = value.to_s
32
+ end
33
+
34
+ def self.from_command_line(command_line)
35
+ return new({}) if command_line.nil? || command_line.empty?
36
+ Marshal.load Base64.decode64(command_line)
37
+ end
38
+
39
+ def initialize(hash)
40
+ @origin_hostname = Socket.gethostname
41
+ check_option_keys(hash)
42
+ VALID_OPTIONS.each do |option|
43
+ send("#{option.name}=", hash[option.name] || hash[option.name.to_s] || option.default)
44
+ end
45
+ self.environment_log_level = ENV['DEEP_TEST_LOG_LEVEL']
46
+ end
47
+
48
+ def gathering_metrics?
49
+ !@metrics_file.nil?
50
+ end
51
+
52
+ def new_listener_list
53
+ listeners = listener.split(',').map do |listener|
54
+ eval(listener).new
55
+ end
56
+ ListenerList.new(listeners)
57
+ end
58
+
59
+ def origin_hostname
60
+ (Socket.gethostname == @origin_hostname) ? 'localhost' : @origin_hostname
61
+ end
62
+
63
+ def connect_to_central_command
64
+ address = ssh_client_connection_info ? ssh_client_connection_info.address : "localhost"
65
+ Telegraph::Wire.connect(address, server_port) do |wire|
66
+ yield wire
67
+ end
68
+ end
69
+
70
+ # Don't store UI instances in the options instance, which will
71
+ # need to be dumped over Telegraph since UI instances may not be dumpable.
72
+ #
73
+ UI_INSTANCES = {} unless defined?(UI_INSTANCES)
74
+ def ui_instance
75
+ UI_INSTANCES[self] ||= eval(ui).new(self)
76
+ end
77
+
78
+ def to_command_line
79
+ Base64.encode64(Marshal.dump(self)).gsub("\n","")
80
+ end
81
+
82
+ def mirror_path
83
+ raise "No source directory specified in sync_options" unless sync_options[:source]
84
+ relative_mirror_path = @origin_hostname + sync_options[:source].gsub('/','_')
85
+ "#{sync_options[:remote_base_dir] || '/tmp'}/#{relative_mirror_path}"
86
+ end
87
+
88
+ def new_deployment
89
+ if distributed_hosts.nil?
90
+ LocalDeployment.new self
91
+ else
92
+ Distributed::RemoteDeployment.new self, new_landing_fleet, LocalDeployment.new(self)
93
+ end
94
+ end
95
+
96
+ def new_landing_fleet
97
+ landing_ships = distributed_hosts.map do |host|
98
+ Distributed::LandingShip.new :address => host
99
+ end
100
+ Distributed::LandingFleet.new self, landing_ships
101
+ end
102
+
103
+ protected
104
+
105
+ def check_option_keys(hash)
106
+ hash.keys.each do |key|
107
+ raise InvalidOptionError.new("#{key} is not a valid option") unless VALID_OPTIONS.any? {|o| o.name == key.to_sym}
108
+ end
109
+ end
110
+
111
+ class InvalidOptionError < StandardError; end
112
+ end
113
+ end
@@ -0,0 +1,77 @@
1
+ module DeepTest
2
+ class ProxyIO < StringIO
3
+ def initialize(output_module, wire)
4
+ @output_module = output_module
5
+ @wire = wire
6
+ super("")
7
+ end
8
+
9
+ def write(*args)
10
+ super
11
+ @wire.send_message @output_module::Output.new(string)
12
+ self.string = ""
13
+ end
14
+
15
+ def flush
16
+ @wire.send_message @output_module::Flush.new
17
+ end
18
+
19
+ def self.replace_stdout_stderr!(wire)
20
+ old_stdout_const, old_stdout_global = STDOUT, $stdout
21
+ old_stderr_const, old_stderr_global = STDERR, $stderr
22
+
23
+ supress_warnings { Object.const_set :STDOUT, ProxyIO.new(Stdout, wire) }
24
+ $stdout = STDOUT
25
+
26
+ supress_warnings { Object.const_set :STDERR, ProxyIO.new(Stderr, wire) }
27
+ $stderr = STDERR
28
+
29
+ DeepTest.logger = nil
30
+
31
+ yield
32
+ ensure
33
+ $stdout = old_stdout_global
34
+ supress_warnings { Object.const_set :STDOUT, old_stdout_const }
35
+
36
+ $stderr = old_stderr_global
37
+ supress_warnings { Object.const_set :STDERR, old_stderr_const }
38
+ end
39
+
40
+ def self.supress_warnings
41
+ old_verbose, $VERBOSE = $VERBOSE, nil
42
+ yield
43
+ ensure
44
+ $VERBOSE = old_verbose
45
+ end
46
+
47
+ class AbstractOutput
48
+ include CentralCommand::Operation
49
+ attr_reader :s
50
+ def initialize(s); @s = s; end
51
+ def execute; stream.write s; end
52
+ def ==(other); self.class == other.class && s == other.s; end
53
+ end
54
+
55
+ module Stdout
56
+ class Output < AbstractOutput
57
+ def stream; $stdout; end
58
+ end
59
+
60
+ class Flush
61
+ include CentralCommand::Operation
62
+ def execute; $stdout.flush; end
63
+ end
64
+ end
65
+
66
+ module Stderr
67
+ class Output < AbstractOutput
68
+ def stream; $stderr; end
69
+ end
70
+
71
+ class Flush
72
+ include CentralCommand::Operation
73
+ def execute; $stderr.flush; end
74
+ end
75
+ end
76
+ end
77
+ end
@@ -0,0 +1,13 @@
1
+ require "socket"
2
+ require "base64"
3
+
4
+ require File.dirname(__FILE__) + "/options"
5
+ require File.dirname(__FILE__) + "/cpu_info"
6
+ require File.dirname(__FILE__) + "/test_task"
7
+ require File.dirname(__FILE__) + "/rspec_detector"
8
+
9
+ DeepTest::RSpecDetector.if_rspec_available do
10
+ require 'spec/rake/spectask'
11
+ require File.dirname(__FILE__) + "/spec/extensions/spec_task"
12
+ end
13
+
@@ -0,0 +1,40 @@
1
+ module DeepTest
2
+ class ResultReader
3
+ def initialize(central_command)
4
+ @central_command = central_command
5
+ end
6
+
7
+ def read(original_work_units_by_id)
8
+ work_units_by_id = original_work_units_by_id.dup
9
+ errors = 0
10
+
11
+ begin
12
+ until errors == work_units_by_id.size
13
+ Thread.pass
14
+ result = @central_command.take_result
15
+ next if result.nil?
16
+
17
+ if Agent::Error === result
18
+ puts result
19
+ errors += 1
20
+ else
21
+ if result.respond_to?(:output) && (output = result.output)
22
+ print output
23
+ end
24
+
25
+ work_unit = work_units_by_id.delete(result.identifier)
26
+ yield [work_unit, result]
27
+ end
28
+ end
29
+ rescue CentralCommand::NoAgentsRunningError
30
+ FailureMessage.show "DeepTest Agents Are Not Running", <<-end_msg
31
+ DeepTest's test running agents have not contacted the
32
+ server to indicate they are still running.
33
+ Shutting down the test run on the assumption that they have died.
34
+ end_msg
35
+ end
36
+
37
+ work_units_by_id
38
+ end
39
+ end
40
+ end
@@ -0,0 +1,21 @@
1
+ module DeepTest
2
+ class RSpecDetector
3
+ def self.if_rspec_available
4
+ if defined?(::Spec)
5
+ require 'spec/version'
6
+ if ::Spec::VERSION::MAJOR == 1 &&
7
+ ::Spec::VERSION::MINOR == 1 &&
8
+ ::Spec::VERSION::TINY >= 8
9
+ yield
10
+ else
11
+ require 'spec/rake/spectask'
12
+ ::Spec::Rake::SpecTask.class_eval do
13
+ def deep_test(options)
14
+ raise "* DeepTest RSpec support requires RSpec 1.1.8"
15
+ end
16
+ end
17
+ end
18
+ end
19
+ end
20
+ end
21
+ end
@@ -0,0 +1,17 @@
1
+ require 'rubygems'
2
+ require 'spec/runner/example_group_runner'
3
+ if ::Spec::VERSION::MAJOR == 1 &&
4
+ ::Spec::VERSION::MINOR == 1 &&
5
+ ::Spec::VERSION::TINY >= 12
6
+ require 'spec/example/before_and_after_hooks'
7
+ end
8
+ require 'spec/example/example_group_methods'
9
+ require 'spec/rake/spectask'
10
+
11
+ require File.dirname(__FILE__) + "/spec/extensions/example_group_methods"
12
+ require File.dirname(__FILE__) + "/spec/extensions/example_methods"
13
+ require File.dirname(__FILE__) + "/spec/extensions/spec_task"
14
+ require File.dirname(__FILE__) + "/spec/extensions/options"
15
+ require File.dirname(__FILE__) + "/spec/runner"
16
+ require File.dirname(__FILE__) + "/spec/work_unit"
17
+ require File.dirname(__FILE__) + "/spec/work_result"
@@ -0,0 +1,64 @@
1
+ module Spec
2
+ module Example
3
+ module ExampleGroupMethods
4
+ class << self
5
+ def assign_instance_method_to_constant(proposed_constant)
6
+ method_sym = proposed_constant.to_s.downcase
7
+
8
+ unless const_defined?(proposed_constant)
9
+ const_set(proposed_constant, instance_method(method_sym))
10
+ end
11
+ end
12
+
13
+ private :assign_instance_method_to_constant
14
+ end
15
+
16
+ assign_instance_method_to_constant :PREPEND_BEFORE
17
+ assign_instance_method_to_constant :APPEND_BEFORE
18
+ assign_instance_method_to_constant :PREPEND_AFTER
19
+ assign_instance_method_to_constant :APPEND_AFTER
20
+
21
+ def prepend_before(*args, &block)
22
+ check_filter_args(args)
23
+ call_regular_instance_method :prepend_before, *args, &block
24
+ end
25
+
26
+ def append_before(*args, &block)
27
+ check_filter_args(args)
28
+ call_regular_instance_method :append_before, *args, &block
29
+ end
30
+
31
+ alias_method :before, :append_before
32
+
33
+ def prepend_after(*args, &block)
34
+ check_filter_args(args)
35
+ call_regular_instance_method :prepend_after, *args, &block
36
+ end
37
+
38
+ def append_after(*args, &block)
39
+ check_filter_args(args)
40
+ call_regular_instance_method :append_after, *args, &block
41
+ end
42
+
43
+ alias_method :after, :append_after
44
+
45
+ private
46
+
47
+ DeepTestAllBlockWarning =
48
+ "Warning: DeepTest will run before(:all) and after(:all) blocks for *every* test that is run. To remove this warning either convert all before/after blocks to each blocks or set $show_deep_test_all_block_warning to false" unless defined?(DeepTestAllBlockWarning)
49
+
50
+ $show_deep_test_all_block_warning = true
51
+
52
+ def check_filter_args(args)
53
+ if args.first == :all && $show_deep_test_all_block_warning
54
+ $show_deep_test_all_block_warning = false
55
+ $stderr.puts DeepTestAllBlockWarning
56
+ end
57
+ end
58
+
59
+ def call_regular_instance_method(sym, *args, &block)
60
+ ExampleGroupMethods.const_get(sym.to_s.upcase).bind(self).call(*args, &block)
61
+ end
62
+ end
63
+ end
64
+ end
@@ -0,0 +1,52 @@
1
+ module Spec
2
+ module Example
3
+ module ExampleMethods
4
+ def identifier
5
+ if ::Spec::VERSION::MAJOR == 1 &&
6
+ ::Spec::VERSION::MINOR == 1 &&
7
+ ::Spec::VERSION::TINY >= 12
8
+ file, line = eval("caller", @_implementation).first.split(/:/)
9
+ else
10
+ file, line = implementation_backtrace.first.split(/:/)
11
+ end
12
+ Identifier.new(file, line.to_i, self.class.description, description)
13
+ end
14
+
15
+ class Identifier
16
+ attr_reader :file, :line, :group_description, :description
17
+ def initialize(file, line, group_description, description)
18
+ @file, @line, @group_description, @description =
19
+ file, line, group_description, description
20
+ end
21
+
22
+ def ==(other)
23
+ eql?(other)
24
+ end
25
+
26
+ def eql?(other)
27
+ File.basename(file) == File.basename(other.file) &&
28
+ line == other.line &&
29
+ group_description == other.group_description &&
30
+ description == other.description
31
+ end
32
+
33
+ def hash
34
+ description.hash
35
+ end
36
+
37
+ def locate(groups)
38
+ groups.each do |group|
39
+ group.examples.each do |example|
40
+ return example if example.identifier == self
41
+ end
42
+ end
43
+ raise "Unable to locate example #{self}"
44
+ end
45
+
46
+ def to_s
47
+ "#{group_description} #{description}"
48
+ end
49
+ end
50
+ end
51
+ end
52
+ end
@@ -0,0 +1,43 @@
1
+ module Spec
2
+ module Runner
3
+ class Options
4
+ def run_one_example(identifier)
5
+ example = identifier.locate(example_groups)
6
+ SingleExampleRunner.new(self, example).run
7
+ end
8
+
9
+ class SingleExampleRunner < ExampleGroupRunner
10
+ def initialize(options, example)
11
+ super(options)
12
+ @example = example
13
+ example_group.extend ExampleGroupHelper
14
+ end
15
+
16
+ def example_group
17
+ @example.class
18
+ end
19
+
20
+ def example_groups
21
+ [example_group]
22
+ end
23
+
24
+ def run
25
+ example_group.with_example_objects([@example]) do
26
+ super
27
+ end
28
+ end
29
+
30
+ module ExampleGroupHelper
31
+ def with_example_objects(example_objects)
32
+ original_example_objects = @example_objects
33
+ @example_objects = example_objects
34
+ yield
35
+ ensure
36
+ @example_objects = original_example_objects
37
+ end
38
+ end
39
+ end
40
+ end
41
+ end
42
+ end
43
+