specjour 0.7.0 → 2.0.0.rc1

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 (49) hide show
  1. checksums.yaml +7 -0
  2. data/History.markdown +12 -0
  3. data/README.markdown +24 -1
  4. data/Rakefile +12 -12
  5. data/bin/specjour +3 -1
  6. data/lib/specjour/cli.rb +86 -110
  7. data/lib/specjour/colors.rb +23 -0
  8. data/lib/specjour/configuration.rb +47 -91
  9. data/lib/specjour/connection.rb +69 -20
  10. data/lib/specjour/cpu.rb +4 -0
  11. data/lib/specjour/fork.rb +1 -1
  12. data/lib/specjour/formatter.rb +153 -0
  13. data/lib/specjour/listener.rb +181 -0
  14. data/lib/specjour/loader.rb +55 -119
  15. data/lib/specjour/logger.rb +34 -0
  16. data/lib/specjour/plugin/base.rb +61 -0
  17. data/lib/specjour/plugin/manager.rb +28 -0
  18. data/lib/specjour/plugin/rails.rb +47 -0
  19. data/lib/specjour/plugin/rails_v3.rb +23 -0
  20. data/lib/specjour/plugin/rails_v4.rb +25 -0
  21. data/lib/specjour/plugin/rspec.rb +160 -0
  22. data/lib/specjour/plugin/rspec_v2.rb +53 -0
  23. data/lib/specjour/plugin/rspec_v3.rb +59 -0
  24. data/lib/specjour/plugin/ssh.rb +24 -0
  25. data/lib/specjour/plugin.rb +4 -0
  26. data/lib/specjour/printer.rb +235 -67
  27. data/lib/specjour/protocol.rb +13 -6
  28. data/lib/specjour/rspec_formatter.rb +17 -0
  29. data/lib/specjour/rsync_daemon.rb +6 -3
  30. data/lib/specjour/socket_helper.rb +26 -10
  31. data/lib/specjour/worker.rb +36 -62
  32. data/lib/specjour.rb +50 -24
  33. data/lib/specjour_plugin.rb +5 -0
  34. metadata +52 -84
  35. data/lib/specjour/cucumber/distributed_formatter.rb +0 -82
  36. data/lib/specjour/cucumber/final_report.rb +0 -83
  37. data/lib/specjour/cucumber/preloader.rb +0 -22
  38. data/lib/specjour/cucumber/runner.rb +0 -15
  39. data/lib/specjour/cucumber.rb +0 -16
  40. data/lib/specjour/db_scrub.rb +0 -56
  41. data/lib/specjour/dispatcher.rb +0 -170
  42. data/lib/specjour/manager.rb +0 -174
  43. data/lib/specjour/rspec/distributed_formatter.rb +0 -50
  44. data/lib/specjour/rspec/final_report.rb +0 -73
  45. data/lib/specjour/rspec/marshalable_exception.rb +0 -19
  46. data/lib/specjour/rspec/preloader.rb +0 -15
  47. data/lib/specjour/rspec/runner.rb +0 -14
  48. data/lib/specjour/rspec/shared_example_group_ext.rb +0 -9
  49. data/lib/specjour/rspec.rb +0 -17
checksums.yaml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: 2b2e786f14b5e926503fdadd4a4504fc188ded2c
4
+ data.tar.gz: e2de43dfdccc720d0befdad67fd51ffc239cc63a
5
+ SHA512:
6
+ metadata.gz: 0228128342542bf82575bcbd36a1a00e42852dec83735dbdb1b46186647eec849b11cb7fae53294b6087250af505ac28a60b7406f38926133e4eb1b6ffe8f195
7
+ data.tar.gz: 1db0922eac8c9552bade26f9669bc9149393e780741ffb4d359d70a598d83c322ba250ad2fb61de783926a24c628436ff76e6f241d39e6f18561f2d59027b2bc
data/History.markdown CHANGED
@@ -1,6 +1,18 @@
1
1
  History
2
2
  =======
3
3
 
4
+ 0.7.1 / (master)
5
+ ---------------------------
6
+ * [fixed] printer exit\_status returns false if there are no reporters
7
+ * [fixed] regression when running a subdirectory. Specjour was loading all
8
+ specs, even those outside of the default spec directory, i.e. a fast\_specs/
9
+ directory.
10
+ * [fixed] "file has vanished" bug. The specjour listener can now transition
11
+ between networks without restarts.
12
+ * [fixed] before(:all). Specjour now distributes before(:all) as a group.
13
+ Previously, each example would be distributed alone, effectively turning
14
+ before(:all) into before(:each).
15
+
4
16
  0.7.0 / 2012-11-21
5
17
  ---------------------------
6
18
  * [added] Cucumber now distributes individual scenarios instead of files
data/README.markdown CHANGED
@@ -1,6 +1,23 @@
1
1
  # Specjour
2
2
 
3
- ## FUCK SETI. Run specs with your spare CPU cycles.
3
+ ## Notes
4
+ Listener daemonized or foregrounded
5
+ forks a loader
6
+ loader should load, setsid, then exit
7
+ all workers then have the same sid and gid with no parent pid
8
+ worker pgid = 100 sid = 100
9
+ webkit_server
10
+ worker pgid = 100 sid = 100
11
+ webkit_server
12
+
13
+ performance.txt
14
+ printing informational messages
15
+ single specjour command starts daemon
16
+ interrupts
17
+ handle no careful_test database
18
+ bonjour announce project names
19
+ printer#project_name aliases
20
+
4
21
 
5
22
  ## Instructions
6
23
 
@@ -20,6 +37,12 @@ by [parallel\_tests](http://github.com/grosser/parallel_tests)):
20
37
  database: project_name_test<%=ENV['TEST_ENV_NUMBER']%>
21
38
 
22
39
  ## Give it a try
40
+
41
+ source .dev
42
+ bin/specjour listen -f -l
43
+ bin/specjour spec/
44
+
45
+
23
46
  Run `specjour` to start a dispatcher, manager, and multiple workers in the same
24
47
  terminal window.
25
48
 
data/Rakefile CHANGED
@@ -1,21 +1,21 @@
1
1
  require 'bundler/gem_tasks'
2
2
  require "bundler/setup"
3
3
 
4
- require 'rspec/core/rake_task'
5
- RSpec::Core::RakeTask.new(:spec)
4
+ # require 'rspec/core/rake_task'
5
+ # RSpec::Core::RakeTask.new(:spec)
6
6
 
7
- RSpec::Core::RakeTask.new(:rcov)
7
+ # RSpec::Core::RakeTask.new(:rcov)
8
8
 
9
- task :default => :spec
9
+ # task :default => :spec
10
10
 
11
- begin
12
- require 'yard'
13
- YARD::Rake::YardocTask.new
14
- rescue LoadError
15
- task :yardoc do
16
- abort "YARD is not available. In order to run yardoc, you must: sudo gem install yard"
17
- end
18
- end
11
+ # begin
12
+ # require 'yard'
13
+ # YARD::Rake::YardocTask.new
14
+ # rescue LoadError
15
+ # task :yardoc do
16
+ # abort "YARD is not available. In order to run yardoc, you must: sudo gem install yard"
17
+ # end
18
+ # end
19
19
 
20
20
  desc "tag, push gem, push to github"
21
21
  task :prerelease do
data/bin/specjour CHANGED
@@ -2,4 +2,6 @@
2
2
  require 'specjour'
3
3
 
4
4
  $PROGRAM_NAME = File.basename(__FILE__)
5
- Specjour::CLI.start
5
+ Specjour.load_plugins
6
+ Specjour.load_custom_hooks
7
+ Specjour::CLI.new.start
data/lib/specjour/cli.rb CHANGED
@@ -1,135 +1,111 @@
1
1
  module Specjour
2
- require 'thor'
3
- class CLI < Thor
2
+ require 'optparse'
3
+ class CLI
4
+ include Logger
4
5
 
5
- def self.worker_option
6
- method_option :workers, :aliases => "-w", :type => :numeric, :desc => "Number of concurent processes to run. Defaults to your system's available cores."
7
- end
6
+ COMMANDS = %w(listen ls stop)
8
7
 
9
- def self.dispatcher_option
10
- method_option :alias, :aliases => "-a", :desc => "Project name advertised to listeners"
11
- end
8
+ attr_accessor :options
12
9
 
13
- def self.rsync_port_option
14
- method_option :rsync_port, :type => :numeric, :default => 23456, :desc => "Port to use for rsync daemon"
10
+ def initialize
11
+ self.options = {}
15
12
  end
16
13
 
17
- # allow specjour to be called with path arguments
18
- def self.start(original_args=ARGV, config={})
19
- Specjour.trap_interrupt
20
- real_tasks = all_tasks.keys | @map.keys
21
- unless real_tasks.include? original_args.first
22
- original_args.unshift default_task
14
+ def stop_running_listener
15
+ listener = Listener.new
16
+ if listener.started?
17
+ listener.stop
23
18
  end
24
- super(original_args)
19
+ listener
25
20
  end
26
21
 
27
- default_task :dispatch
28
-
29
- class_option :log, :aliases => "-l", :type => :boolean, :desc => "Print debug messages to $stderr"
30
-
31
- desc "listen", "Listen for incoming tests to run"
32
- long_desc <<-DESC
33
- Advertise availability to run tests for the current directory.
34
- DESC
35
- worker_option
36
- rsync_port_option
37
- method_option :projects, :aliases => "-p", :type => :array, :desc => "Projects supported by this listener"
38
- def listen
39
- handle_logging
40
- handle_workers
41
- params[:registered_projects] = params.delete(:projects) || [File.basename(Dir.pwd)]
42
- append_to_program_name "listen"
43
- Specjour::Manager.new(params).start
22
+ def start
23
+ Specjour.trap_interrupt_with_exit
24
+ parser.parse!
25
+ append_to_program_name(ARGV[0])
26
+ ensure_alias
27
+ case ARGV[0]
28
+ when "listen"
29
+ listener = stop_running_listener
30
+ listener.daemonize unless options[:foreground]
31
+ listener.start
32
+ when "ls"
33
+ puts "Plugins:"
34
+ puts Specjour.plugin_manager.plugins
35
+ when "stop"
36
+ listener = Listener.new
37
+ if listener.started?
38
+ puts "Stopping listener with pid #{listener.pid}"
39
+ listener.stop
40
+ else
41
+ abort("No listener found")
42
+ end
43
+ when "help"
44
+ abort("Commands are: #{COMMANDS.join(" ")}")
45
+ else
46
+ test_paths = ARGV[0..-1]
47
+ if options[:workers]
48
+ stop_running_listener
49
+ if options[:workers] > 0
50
+ Listener.ensure_started
51
+ end
52
+ else
53
+ Listener.ensure_started
54
+ end
55
+ printer = Printer.new test_paths: Array(test_paths)
56
+ printer.announce
57
+ printer.start_rsync
58
+ printer.start
59
+ end
44
60
  end
45
61
 
46
- desc "load", "load the app, then fork workers", :hide => true
47
- worker_option
48
- method_option :printer_uri, :required => true
49
- method_option :project_path, :required => true
50
- method_option :task, :required => true
51
- method_option :test_paths, :type => :array, :default => []
52
- method_option :quiet, :type => :boolean, :default => false
53
- def load
54
- handle_logging
55
- handle_workers
56
- append_to_program_name "load"
57
- Specjour::Loader.new(params).start
62
+ def ensure_alias
63
+ if Specjour.configuration.project_aliases.empty?
64
+ Specjour.configuration.project_aliases = [File.basename(Dir.pwd)]
65
+ end
58
66
  end
59
67
 
60
- desc "dispatch [test_paths]", "Send tests to a listener"
61
- worker_option
62
- dispatcher_option
63
- rsync_port_option
64
- long_desc <<-DESC
65
- This is run when you simply type `specjour`.
66
- By default, it will run the specs and features found in the current directory.
67
- If you like, you can run a subset of tests by specifying the folder containing the tests.\n
68
- Examples\n
69
- `specjour dispatch spec`\n
70
- `specjour dispatch features`\n
71
- `specjour dispatch spec/models features/sign_up.feature`\n
72
- DESC
73
- def dispatch(*paths)
74
- handle_logging
75
- handle_workers
76
- handle_dispatcher(paths)
77
- append_to_program_name "dispatch"
78
- Specjour::Dispatcher.new(params).start
79
- end
68
+ def parser
69
+ @parser ||= OptionParser.new do |parser|
70
+ parser.banner = "Usage: specjour [command] [options] [files or directories]\n\nCommands are #{COMMANDS.join(",")}\n\n"
80
71
 
81
- desc "prepare [PROJECT_PATH]", "Run the prepare task on all listening workers"
82
- long_desc <<-DESC
83
- Run the Specjour::Configuration.prepare block on all listening workers.
84
- Defaults to dropping the database, then loading the schema.
85
- DESC
86
- worker_option
87
- dispatcher_option
88
- rsync_port_option
89
- def prepare(path = Dir.pwd)
90
- handle_logging
91
- handle_workers
92
- params[:project_path] = File.expand_path(path)
93
- params[:project_alias] = params.delete(:alias)
94
- params[:test_paths] = []
95
- params[:worker_task] = 'prepare'
96
- append_to_program_name "prepare"
97
- Specjour::Dispatcher.new(params).start
98
- end
72
+ parser.on('-b', '--backtrace', 'Include specjour in the backtrace (do not scrub backtrace)') do |o|
73
+ options[:full_backtrace] = true
74
+ Specjour.configuration.full_backtrace = true
75
+ end
99
76
 
100
- map %w(-v --version) => :version
101
- desc "version", "Show the current version"
102
- def version
103
- puts Specjour::VERSION
104
- end
77
+ parser.on("-l", "--log", "Enable informational logging") do
78
+ Specjour.new_logger ::Logger::INFO
79
+ end
105
80
 
106
- protected
81
+ parser.on("-d", "--debug", "Enable debug logging") do
82
+ Specjour.new_logger ::Logger::DEBUG
83
+ end
107
84
 
108
- def append_to_program_name(command)
109
- $PROGRAM_NAME = "#{$PROGRAM_NAME} #{command}"
110
- end
85
+ parser.on("-f", "--foreground", "Foreground the listener") do |option|
86
+ options[:foreground] = option
87
+ end
111
88
 
112
- def params
113
- @params ||= options.dup
114
- end
89
+ parser.on("-w", "--workers NUM", Numeric, "Number of workers") do |option|
90
+ options[:workers] = option.to_i
91
+ Specjour.configuration.worker_size = options[:workers]
92
+ end
115
93
 
116
- def handle_logging
117
- Specjour.new_logger(Logger::DEBUG) if options['log']
118
- end
94
+ parser.on("-a", "--alias NAME", Array, "Project name alias") do |option|
95
+ Specjour.configuration.project_aliases = option
96
+ end
119
97
 
120
- def handle_workers
121
- params[:worker_size] = options["workers"] || CPU.cores
98
+ parser.on("-v", "--version", "Version number") do |option|
99
+ puts Specjour::VERSION
100
+ exit
101
+ end
102
+ end
122
103
  end
123
104
 
124
- def handle_dispatcher(paths)
125
- if paths.empty?
126
- params[:project_path] = Dir.pwd
127
- else
128
- params[:project_path] = File.expand_path(paths.first.sub(/(spec|features).*$/, ''))
129
- end
130
- params[:test_paths] = paths
131
- params[:project_alias] = params.delete(:alias)
132
- raise ArgumentError, "Cannot dispatch line numbers" if paths.any? {|p| p =~ /:\d+/}
105
+ private
106
+
107
+ def append_to_program_name(command)
108
+ $PROGRAM_NAME = "#{$PROGRAM_NAME} #{command}"
133
109
  end
134
110
  end
135
111
  end
@@ -0,0 +1,23 @@
1
+ module Specjour
2
+ module Colors
3
+
4
+ VT100_COLORS = {
5
+ :black => 30,
6
+ :red => 31,
7
+ :green => 32,
8
+ :yellow => 33,
9
+ :blue => 34,
10
+ :magenta => 35,
11
+ :cyan => 36,
12
+ :white => 37
13
+ }
14
+
15
+ def colorize(text, color)
16
+ if output.tty?
17
+ "\e[#{VT100_COLORS[color]}m#{text}\e[0m"
18
+ else
19
+ text
20
+ end
21
+ end
22
+ end
23
+ end
@@ -1,105 +1,61 @@
1
1
  module Specjour
2
- module Configuration
3
- extend self
4
-
5
- attr_writer :before_fork, :after_fork, :after_load, :prepare, :rspec_formatter, :rsync_options
6
-
7
- # This block is run by each worker before they begin running tests.
8
- # The default action is to migrate the database, and clear it of any old
9
- # data.
10
- def after_fork
11
- @after_fork ||= default_after_fork
12
- end
13
-
14
- # This block is run after the manager loads the app into memory, but before
15
- # forking new worker processes. The default action is to disconnect from
16
- # the ActiveRecord database.
17
- def after_load
18
- @after_load ||= default_after_load
19
- end
20
-
21
- # This block is run by the manager before forking workers. The default
22
- # action is to run bundle install.
23
- def before_fork
24
- @before_fork ||= default_before_fork
25
- end
26
-
27
- # This block is run on all workers when invoking `specjour prepare`
28
- # Defaults to dropping the worker's database and recreating it. This
29
- # is especially useful when two teams are sharing workers and writing
30
- # migrations at around the same time causing databases to get out of sync.
31
- def prepare
32
- @prepare ||= default_prepare
33
- end
34
-
35
- def reset
36
- @before_fork = nil
37
- @after_fork = nil
38
- @after_load = nil
39
- @prepare = nil
40
- @rsync_options = nil
41
- @rspec_formatter = nil
42
- end
43
-
44
- def rspec_formatter
45
- @rspec_formatter ||= default_rspec_formatter
46
- end
47
-
48
- def rsync_options
49
- @rsync_options ||= default_rsync_options
50
- end
51
-
52
- def bundle_install
53
- if system('which bundle')
54
- system('bundle check') || system('bundle install')
55
- end
56
- end
57
-
58
- def default_before_fork
59
- lambda do
60
- bundle_install
61
- end
62
- end
63
-
64
- def default_after_fork
65
- lambda do
66
- DbScrub.scrub if rails_with_ar?
67
- end
68
- end
69
-
70
- def default_after_load
71
- lambda do
72
- ActiveRecord::Base.remove_connection if rails_with_ar?
73
- end
74
- end
75
-
76
- def default_prepare
77
- lambda do
78
- if rails_with_ar?
79
- DbScrub.drop
80
- DbScrub.scrub
2
+ class Configuration
3
+ attr_accessor :options
4
+
5
+ DEFAULT_BACKTRACE_EXCLUSION = Regexp.union([
6
+ "/lib/specjour/",
7
+ /lib\/rspec\/(core|expectations|matchers|mocks)/,
8
+ "/gems/",
9
+ "spec/spec_helper.rb",
10
+ "spec/rails_helper.rb",
11
+ "bin/"
12
+ ]).freeze
13
+
14
+ DEFAULT_OPTIONS = {
15
+ backtrace_exclusion_pattern: DEFAULT_BACKTRACE_EXCLUSION,
16
+ formatter: Formatter.new,
17
+ full_backtrace: false,
18
+ printer_port: nil,
19
+ printer_uri: nil,
20
+ project_aliases: [],
21
+ project_name: nil,
22
+ project_path: nil,
23
+ remote_job: nil,
24
+ rsync_options: "-aL --delete --ignore-errors",
25
+ rsync_port: 23456,
26
+ test_paths: nil,
27
+ tmp_path: "/tmp",
28
+ worker_size: lambda { Specjour.configuration.remote_job ? CPU.half_cores : CPU.cores },
29
+ worker_number: 0
30
+ }.freeze
31
+
32
+ def self.make_option(name)
33
+ define_method(name) do
34
+ option = @options[name]
35
+ if option.respond_to?(:call)
36
+ option.call()
37
+ else
38
+ option
81
39
  end
82
40
  end
83
- end
84
41
 
85
- def default_rspec_formatter
86
- lambda do
87
- ::RSpec::Core::Formatters::ProgressFormatter
42
+ define_method("#{name}=") do |value|
43
+ @options[name] = value
88
44
  end
89
45
  end
90
46
 
91
- def default_rsync_options
92
- "-aL --delete --ignore-errors"
47
+ DEFAULT_OPTIONS.each do |k,v|
48
+ make_option(k)
93
49
  end
94
50
 
95
- protected
96
-
97
- def rails_with_ar?
98
- defined?(Rails) && defined?(ActiveRecord::Base)
51
+ def initialize(options={})
52
+ @original_options = options
53
+ set_options
99
54
  end
100
55
 
101
- def system(cmd)
102
- Kernel.system("#{cmd} > /dev/null")
56
+ def set_options
57
+ @options = DEFAULT_OPTIONS.merge @original_options
103
58
  end
59
+
104
60
  end
105
61
  end
@@ -1,12 +1,13 @@
1
1
  module Specjour
2
2
  class Connection
3
+ include Logger
3
4
  include Protocol
4
5
  extend Forwardable
5
6
 
6
7
  attr_reader :uri, :retries
7
8
  attr_writer :socket
8
9
 
9
- def_delegators :socket, :flush, :close, :closed?, :gets, :each
10
+ def_delegators :socket, :flush, :close, :closed?, :gets, :puts, :each, :eof?, :tty?
10
11
 
11
12
  def self.wrap(established_connection)
12
13
  host, port = established_connection.peeraddr.values_at(3,1)
@@ -23,58 +24,106 @@ module Specjour
23
24
  alias to_str to_s
24
25
 
25
26
  def connect
27
+ debug "connecting to socket #{host}:#{port}"
26
28
  timeout { connect_socket }
27
29
  end
28
30
 
29
31
  def disconnect
30
- socket.close if socket && !socket.closed?
32
+ if socket && !socket.closed?
33
+ debug "closing socket"
34
+ socket.close
35
+ end
36
+ end
37
+
38
+ def host
39
+ uri.host
40
+ end
41
+
42
+ def port
43
+ uri.port
31
44
  end
32
45
 
33
46
  def socket
34
47
  @socket ||= connect
35
48
  end
36
49
 
50
+ def add_to_profiler(test, time, host)
51
+ send_command("add_to_profiler", test, time, host)
52
+ end
53
+
54
+ def done
55
+ send_command("done")
56
+ end
57
+
58
+ def error(exception)
59
+ prefix = if n = ENV["TEST_ENV_NUMBER"]
60
+ "[#{n}]"
61
+ else
62
+ ""
63
+ end
64
+ send_command("error", "#{prefix}#{exception.inspect}\n#{exception.backtrace.join("\n")}")
65
+ rescue => error
66
+ $stderr.puts "Error sending error to server: #{error.inspect}"
67
+ $stderr.puts error.backtrace
68
+ end
69
+
70
+ def report_test(test)
71
+ send_command("report_test", test)
72
+ end
73
+
37
74
  def next_test
38
- will_reconnect do
39
- send_message(:ready)
40
- load_object socket.gets(TERMINATOR)
41
- end
75
+ send_recv_command("next_test")
42
76
  end
43
77
 
44
- def print(arg)
78
+ def ready(info)
79
+ send_recv_command("ready", info)
80
+ end
81
+
82
+ def reconnect
83
+ socket.close unless socket.closed?
84
+ connect
85
+ end
86
+
87
+ def register_tests(tests)
88
+ send_command("register_tests", tests)
89
+ end
90
+
91
+ def send_server_done(signal)
92
+ send_command("server_done", signal)
93
+ end
94
+
95
+ def get_server_done
45
96
  will_reconnect do
46
- socket.print dump_object(arg)
97
+ data = recv_data
98
+ if data[:command] == "server_done"
99
+ data[:args].first
100
+ end
47
101
  end
48
102
  end
49
103
 
50
- def puts(arg='')
104
+ def send_command(method_name, *args)
51
105
  will_reconnect do
52
- print(arg << "\n")
106
+ send_data command: method_name, args: args
53
107
  end
54
108
  end
55
109
 
56
- def send_message(method_name, *args)
110
+ def send_recv_command(method_name, *args)
111
+ send_command(method_name, *args)
57
112
  will_reconnect do
58
- print([method_name, *args])
59
- flush
113
+ recv_data
60
114
  end
61
115
  end
62
116
 
63
117
  protected
64
118
 
65
119
  def connect_socket
66
- @socket = TCPSocket.open(uri.host, uri.port)
120
+ @socket = TCPSocket.open(host, port)
67
121
  rescue Errno::ECONNREFUSED => error
68
122
  retry
69
123
  end
70
124
 
71
- def reconnect
72
- socket.close unless socket.closed?
73
- connect
74
- end
75
-
76
125
  def timeout(&block)
77
- Timeout.timeout(1.0, &block)
126
+ Timeout.timeout(0.2, &block)
78
127
  rescue Timeout::Error
79
128
  end
80
129
 
data/lib/specjour/cpu.rb CHANGED
@@ -10,6 +10,10 @@ module Specjour
10
10
  end
11
11
  end
12
12
 
13
+ def self.half_cores
14
+ cores / 2
15
+ end
16
+
13
17
  protected
14
18
 
15
19
  def self.command(cmd)
data/lib/specjour/fork.rb CHANGED
@@ -10,7 +10,7 @@ module Specjour::Fork
10
10
  at_exit { exit! }
11
11
  begin
12
12
  yield
13
- rescue StandardError => e
13
+ rescue Exception => e
14
14
  $stderr.puts "#{e.class} #{e.message}", e.backtrace
15
15
  end
16
16
  end