wycats-merb-core 0.9.8 → 0.9.9
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 +136 -2
- data/CONTRIBUTORS +6 -0
- data/PUBLIC_CHANGELOG +15 -0
- data/Rakefile +12 -14
- data/lib/merb-core.rb +82 -43
- data/lib/merb-core/bootloader.rb +268 -60
- data/lib/merb-core/config.rb +119 -34
- data/lib/merb-core/controller/abstract_controller.rb +58 -18
- data/lib/merb-core/controller/exceptions.rb +2 -15
- data/lib/merb-core/controller/merb_controller.rb +28 -1
- data/lib/merb-core/controller/mime.rb +4 -0
- data/lib/merb-core/controller/mixins/controller.rb +14 -17
- data/lib/merb-core/controller/mixins/render.rb +23 -28
- data/lib/merb-core/controller/mixins/responder.rb +0 -1
- data/lib/merb-core/controller/template.rb +44 -20
- data/lib/merb-core/core_ext/kernel.rb +8 -3
- data/lib/merb-core/dispatch/default_exception/default_exception.rb +1 -1
- data/lib/merb-core/dispatch/default_exception/views/_css.html.erb +3 -1
- data/lib/merb-core/dispatch/default_exception/views/_javascript.html.erb +71 -67
- data/lib/merb-core/dispatch/default_exception/views/index.html.erb +6 -2
- data/lib/merb-core/dispatch/dispatcher.rb +5 -9
- data/lib/merb-core/dispatch/request.rb +46 -57
- data/lib/merb-core/dispatch/router.rb +83 -6
- data/lib/merb-core/dispatch/router/behavior.rb +87 -27
- data/lib/merb-core/dispatch/router/resources.rb +281 -167
- data/lib/merb-core/dispatch/router/route.rb +141 -27
- data/lib/merb-core/logger.rb +213 -202
- data/lib/merb-core/rack.rb +3 -1
- data/lib/merb-core/rack/adapter.rb +7 -4
- data/lib/merb-core/rack/adapter/ebb.rb +12 -13
- data/lib/merb-core/rack/adapter/evented_mongrel.rb +2 -15
- data/lib/merb-core/rack/adapter/irb.rb +3 -2
- data/lib/merb-core/rack/adapter/mongrel.rb +22 -15
- data/lib/merb-core/rack/adapter/swiftiplied_mongrel.rb +4 -16
- data/lib/merb-core/rack/adapter/thin.rb +21 -22
- data/lib/merb-core/rack/adapter/thin_turbo.rb +4 -11
- data/lib/merb-core/rack/adapter/webrick.rb +54 -18
- data/lib/merb-core/rack/handler/mongrel.rb +12 -13
- data/lib/merb-core/rack/middleware/csrf.rb +1 -1
- data/lib/merb-core/server.rb +135 -98
- data/lib/merb-core/tasks/gem_management.rb +50 -12
- data/lib/merb-core/tasks/merb.rb +1 -0
- data/lib/merb-core/tasks/merb_rake_helper.rb +9 -38
- data/lib/merb-core/tasks/stats.rake +2 -2
- data/lib/merb-core/test.rb +9 -3
- data/lib/merb-core/test/helpers.rb +1 -0
- data/lib/merb-core/test/helpers/multipart_request_helper.rb +3 -2
- data/lib/merb-core/test/helpers/request_helper.rb +40 -372
- data/lib/merb-core/test/helpers/route_helper.rb +15 -7
- data/lib/merb-core/test/matchers.rb +1 -0
- data/lib/merb-core/test/matchers/controller_matchers.rb +4 -247
- data/lib/merb-core/test/matchers/view_matchers.rb +22 -4
- data/lib/merb-core/test/run_specs.rb +117 -25
- data/lib/merb-core/version.rb +1 -1
- metadata +1 -1
- data/lib/merb-core/vendor/facets.rb +0 -2
- data/lib/merb-core/vendor/facets/dictionary.rb +0 -433
- data/lib/merb-core/vendor/facets/inflect.rb +0 -342
@@ -12,13 +12,21 @@ module Merb
|
|
12
12
|
# ==== Returns
|
13
13
|
# String:: The generated URL.
|
14
14
|
def url(*args)
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
15
|
+
args << (@request_params || {})
|
16
|
+
Merb::Router.url(*args)
|
17
|
+
end
|
18
|
+
|
19
|
+
# Mimics the resource method available to controllers
|
20
|
+
#
|
21
|
+
# ==== Paramaters
|
22
|
+
# resources<Object>:: The resources to generate URLs from
|
23
|
+
# params<Hash>:: Any extra parameters that are required.
|
24
|
+
#
|
25
|
+
# ==== Returns
|
26
|
+
# String:: The generated URL.
|
27
|
+
def resource(*args)
|
28
|
+
args << @request_params || {}
|
29
|
+
Merb::Router.resource(*args)
|
22
30
|
end
|
23
31
|
|
24
32
|
# ==== Parameters
|
@@ -3,6 +3,7 @@ module Merb::Test::Rspec; end
|
|
3
3
|
require "merb-core/test/matchers/controller_matchers"
|
4
4
|
require "merb-core/test/matchers/route_matchers"
|
5
5
|
require "merb-core/test/matchers/view_matchers"
|
6
|
+
require "merb-core/test/matchers/request_matchers"
|
6
7
|
|
7
8
|
Merb::Test::ControllerHelper.send(:include, Merb::Test::Rspec::ControllerMatchers)
|
8
9
|
Merb::Test::RouteHelper.send(:include, Merb::Test::Rspec::RouteMatchers)
|
@@ -31,140 +31,6 @@ module Merb::Test::Rspec::ControllerMatchers
|
|
31
31
|
end
|
32
32
|
end
|
33
33
|
|
34
|
-
class RedirectTo
|
35
|
-
|
36
|
-
# === Parameters
|
37
|
-
# String:: The expected location
|
38
|
-
# Hash:: Optional hash of options (currently only :message)
|
39
|
-
def initialize(expected, options = {})
|
40
|
-
@expected = expected
|
41
|
-
@options = options
|
42
|
-
end
|
43
|
-
|
44
|
-
# ==== Parameters
|
45
|
-
# target<Merb::Controller>:: The controller to match
|
46
|
-
#
|
47
|
-
# ==== Returns
|
48
|
-
# Boolean::
|
49
|
-
# True if the controller status is redirect and the locations match.
|
50
|
-
def matches?(target)
|
51
|
-
@target, @location = target, target.headers['Location']
|
52
|
-
@redirected = BeRedirect.new.matches?(target.status)
|
53
|
-
|
54
|
-
if @options[:message]
|
55
|
-
msg = Merb::Request.escape([Marshal.dump(@options[:message])].pack("m"))
|
56
|
-
@expected << "?_message=#{msg}"
|
57
|
-
end
|
58
|
-
|
59
|
-
@location == @expected && @redirected
|
60
|
-
end
|
61
|
-
|
62
|
-
# ==== Returns
|
63
|
-
# String:: The failure message.
|
64
|
-
def failure_message
|
65
|
-
msg = "expected #{inspect_target} to redirect to <#{@expected}>, but "
|
66
|
-
if @redirected
|
67
|
-
msg << "was <#{target_location}>"
|
68
|
-
else
|
69
|
-
msg << "there was no redirection"
|
70
|
-
end
|
71
|
-
end
|
72
|
-
|
73
|
-
# ==== Returns
|
74
|
-
# String:: The failure message to be displayed in negative matches.
|
75
|
-
def negative_failure_message
|
76
|
-
"expected #{inspect_target} not to redirect to <#{@expected}>, but did anyway"
|
77
|
-
end
|
78
|
-
|
79
|
-
# ==== Returns
|
80
|
-
# String:: The controller and action name.
|
81
|
-
def inspect_target
|
82
|
-
"#{@target.controller_name}##{@target.action_name}"
|
83
|
-
end
|
84
|
-
|
85
|
-
# ==== Returns
|
86
|
-
# String:: Either the target's location header or the target itself.
|
87
|
-
def target_location
|
88
|
-
@target.respond_to?(:headers) ? @target.headers['Location'] : @target
|
89
|
-
end
|
90
|
-
end
|
91
|
-
|
92
|
-
class BeSuccess
|
93
|
-
|
94
|
-
# ==== Parameters
|
95
|
-
# target<Fixnum, ~status>::
|
96
|
-
# Either the status code or a controller with a status code.
|
97
|
-
#
|
98
|
-
# ==== Returns
|
99
|
-
# Boolean:: True if the status code is in the range 200..207.
|
100
|
-
def matches?(target)
|
101
|
-
@target = target
|
102
|
-
(200..207).include?(status_code)
|
103
|
-
end
|
104
|
-
|
105
|
-
# ==== Returns
|
106
|
-
# String:: The failure message.
|
107
|
-
def failure_message
|
108
|
-
"expected#{inspect_target} to be successful but was #{status_code}"
|
109
|
-
end
|
110
|
-
|
111
|
-
# ==== Returns
|
112
|
-
# String:: The failure message to be displayed in negative matches.
|
113
|
-
def negative_failure_message
|
114
|
-
"expected#{inspect_target} not to be successful but it was #{status_code}"
|
115
|
-
end
|
116
|
-
|
117
|
-
# ==== Returns
|
118
|
-
# String:: The controller and action name.
|
119
|
-
def inspect_target
|
120
|
-
" #{@target.controller_name}##{@target.action_name}" if @target.respond_to?(:controller_name) && @target.respond_to?(:action_name)
|
121
|
-
end
|
122
|
-
|
123
|
-
# ==== Returns
|
124
|
-
# Fixnum:: Either the target's status or the target itself.
|
125
|
-
def status_code
|
126
|
-
@target.respond_to?(:status) ? @target.status : @target
|
127
|
-
end
|
128
|
-
end
|
129
|
-
|
130
|
-
class BeMissing
|
131
|
-
|
132
|
-
# ==== Parameters
|
133
|
-
# target<Fixnum, ~status>::
|
134
|
-
# Either the status code or a controller with a status code.
|
135
|
-
#
|
136
|
-
# ==== Returns
|
137
|
-
# Boolean:: True if the status code is in the range 400..417.
|
138
|
-
def matches?(target)
|
139
|
-
@target = target
|
140
|
-
(400..417).include?(status_code)
|
141
|
-
end
|
142
|
-
|
143
|
-
# ==== Returns
|
144
|
-
# String:: The failure message.
|
145
|
-
def failure_message
|
146
|
-
"expected#{inspect_target} to be missing but was #{status_code}"
|
147
|
-
end
|
148
|
-
|
149
|
-
# ==== Returns
|
150
|
-
# String:: The failure message to be displayed in negative matches.
|
151
|
-
def negative_failure_message
|
152
|
-
"expected#{inspect_target} not to be missing but it was #{status_code}"
|
153
|
-
end
|
154
|
-
|
155
|
-
# ==== Returns
|
156
|
-
# String:: The controller and action name.
|
157
|
-
def inspect_target
|
158
|
-
" #{@target.controller_name}##{@target.action_name}" if @target.respond_to?(:controller_name) && @target.respond_to?(:action_name)
|
159
|
-
end
|
160
|
-
|
161
|
-
# ==== Returns
|
162
|
-
# Fixnum:: Either the target's status or the target itself.
|
163
|
-
def status_code
|
164
|
-
@target.respond_to?(:status) ? @target.status : @target
|
165
|
-
end
|
166
|
-
end
|
167
|
-
|
168
34
|
class BeError
|
169
35
|
def initialize(expected)
|
170
36
|
@expected = expected
|
@@ -185,6 +51,10 @@ module Merb::Test::Rspec::ControllerMatchers
|
|
185
51
|
"expected #{@target} not to be a #{@expected} error, but it was"
|
186
52
|
end
|
187
53
|
end
|
54
|
+
|
55
|
+
def be_error(expected)
|
56
|
+
BeError.new(expected)
|
57
|
+
end
|
188
58
|
|
189
59
|
class Provide
|
190
60
|
|
@@ -223,120 +93,7 @@ module Merb::Test::Rspec::ControllerMatchers
|
|
223
93
|
@target.class_provided_formats
|
224
94
|
end
|
225
95
|
end
|
226
|
-
|
227
|
-
# Passes if the target was redirected, or the target is a redirection (300
|
228
|
-
# level) response code.
|
229
|
-
#
|
230
|
-
# ==== Examples
|
231
|
-
# # Passes if the controller was redirected
|
232
|
-
# controller.should redirect
|
233
|
-
#
|
234
|
-
# # Also works if the target is the response code
|
235
|
-
# controller.status.should redirect
|
236
|
-
#
|
237
|
-
# ==== Notes
|
238
|
-
# valid HTTP Redirection codes:
|
239
|
-
# * 300: Multiple Choices
|
240
|
-
# * 301: Moved Permanently
|
241
|
-
# * 302: Moved Temporarily (HTTP/1.0)
|
242
|
-
# * 302: Found (HTTP/1.1)
|
243
|
-
# * 303: See Other (HTTP/1.1)
|
244
|
-
# * 304: Not Modified
|
245
|
-
# * 305: Use Proxy
|
246
|
-
# * 307: Temporary Redirect
|
247
|
-
#--
|
248
|
-
# status codes based on: http://cheat.errtheblog.com/s/http_status_codes/
|
249
|
-
def redirect
|
250
|
-
BeRedirect.new
|
251
|
-
end
|
252
|
-
|
253
|
-
alias_method :be_redirection, :redirect
|
254
|
-
|
255
|
-
# Passes if the target was redirected to the expected location.
|
256
|
-
#
|
257
|
-
# ==== Paramters
|
258
|
-
# expected<String>:: A relative or absolute url.
|
259
|
-
#
|
260
|
-
# ==== Examples
|
261
|
-
# # Passes if the controller was redirected to http://example.com/
|
262
|
-
# controller.should redirect_to('http://example.com/')
|
263
|
-
def redirect_to(expected, options = {})
|
264
|
-
RedirectTo.new(expected, options)
|
265
|
-
end
|
266
|
-
|
267
|
-
alias_method :be_redirection_to, :redirect_to
|
268
|
-
|
269
|
-
# Passes if the request that generated the target was successful, or the
|
270
|
-
# target is a success (200 level) response code.
|
271
|
-
#
|
272
|
-
# ==== Examples
|
273
|
-
# # Passes if the controller call was successful
|
274
|
-
# controller.should respond_successfully
|
275
|
-
#
|
276
|
-
# # Also works if the target is the response code
|
277
|
-
# controller.status.should respond_successfully
|
278
|
-
#
|
279
|
-
# ==== Notes
|
280
|
-
# valid HTTP Success codes:
|
281
|
-
# * 200: OK
|
282
|
-
# * 201: Created
|
283
|
-
# * 202: Accepted
|
284
|
-
# * 203: Non-Authoritative Information
|
285
|
-
# * 204: No Content
|
286
|
-
# * 205: Reset Content
|
287
|
-
# * 206: Partial Content
|
288
|
-
# * 207: Multi-Status
|
289
|
-
#--
|
290
|
-
# status codes based on: http://cheat.errtheblog.com/s/http_status_codes/
|
291
|
-
def respond_successfully
|
292
|
-
BeSuccess.new
|
293
|
-
end
|
294
|
-
|
295
|
-
alias_method :be_successful, :respond_successfully
|
296
|
-
|
297
|
-
# Passes if the request that generated the target was missing, or the target
|
298
|
-
# is a client-side error (400 level) response code.
|
299
|
-
#
|
300
|
-
# ==== Examples
|
301
|
-
# # Passes if the controller call was unknown or not understood
|
302
|
-
# controller.should be_missing
|
303
|
-
#
|
304
|
-
# # Also passes if the target is a response code
|
305
|
-
# controller.status.should be_missing
|
306
|
-
#
|
307
|
-
# ==== Notes
|
308
|
-
# valid HTTP Client Error codes:
|
309
|
-
# * 400: Bad Request
|
310
|
-
# * 401: Unauthorized
|
311
|
-
# * 402: Payment Required
|
312
|
-
# * 403: Forbidden
|
313
|
-
# * 404: Not Found
|
314
|
-
# * 405: Method Not Allowed
|
315
|
-
# * 406: Not Acceptable
|
316
|
-
# * 407: Proxy Authentication Required
|
317
|
-
# * 408: Request Timeout
|
318
|
-
# * 409: Conflict
|
319
|
-
# * 410: Gone
|
320
|
-
# * 411: Length Required
|
321
|
-
# * 412: Precondition Failed
|
322
|
-
# * 413: Request Entity Too Large
|
323
|
-
# * 414: Request-URI Too Long
|
324
|
-
# * 415: Unsupported Media Type
|
325
|
-
# * 416: Requested Range Not Satisfiable
|
326
|
-
# * 417: Expectation Failed
|
327
|
-
# * 422: Unprocessable Entity
|
328
|
-
#--
|
329
|
-
# status codes based on: http://cheat.errtheblog.com/s/http_status_codes/
|
330
|
-
def be_missing
|
331
|
-
BeMissing.new
|
332
|
-
end
|
333
96
|
|
334
|
-
def be_error(expected)
|
335
|
-
BeError.new(expected)
|
336
|
-
end
|
337
|
-
|
338
|
-
alias_method :be_client_error, :be_missing
|
339
|
-
|
340
97
|
# Passes if the controller actually provides the target format
|
341
98
|
#
|
342
99
|
# === Parameters
|
@@ -1,10 +1,26 @@
|
|
1
1
|
module Merb::Test::Rspec::ViewMatchers
|
2
2
|
class HaveXpath
|
3
|
-
def initialize(expected)
|
4
|
-
@expected = expected
|
3
|
+
def initialize(expected, type)
|
4
|
+
@expected, @type = expected, type
|
5
5
|
end
|
6
6
|
|
7
7
|
def matches?(stringlike)
|
8
|
+
send("matches_#{@type}?", stringlike)
|
9
|
+
end
|
10
|
+
|
11
|
+
def matches_rexml?(stringlike)
|
12
|
+
@document = case stringlike
|
13
|
+
when REXML::Document
|
14
|
+
stringlike.root
|
15
|
+
when REXML::Node
|
16
|
+
stringlike
|
17
|
+
when StringIO, String
|
18
|
+
REXML::Document.new(stringlike).root
|
19
|
+
end
|
20
|
+
!REXML::XPath.match(@document, @expected).empty?
|
21
|
+
end
|
22
|
+
|
23
|
+
def matches_libxml?(stringlike)
|
8
24
|
@document = case stringlike
|
9
25
|
when LibXML::XML::Document, LibXML::XML::Node
|
10
26
|
stringlike
|
@@ -335,10 +351,12 @@ module Merb::Test::Rspec::ViewMatchers
|
|
335
351
|
def have_xpath(expected)
|
336
352
|
begin
|
337
353
|
require "libxml"
|
354
|
+
type = "libxml"
|
338
355
|
rescue LoadError => e
|
339
|
-
|
356
|
+
require "rexml/document"
|
357
|
+
type = "rexml"
|
340
358
|
end
|
341
|
-
HaveXpath.new(expected)
|
359
|
+
HaveXpath.new(expected, type)
|
342
360
|
end
|
343
361
|
alias_method :match_xpath, :have_xpath
|
344
362
|
|
@@ -1,6 +1,94 @@
|
|
1
1
|
require 'rubygems'
|
2
|
-
require 'open3'
|
3
2
|
require 'benchmark'
|
3
|
+
require 'drb'
|
4
|
+
require 'spec'
|
5
|
+
require 'spec/runner/formatter/base_text_formatter'
|
6
|
+
require 'spec/spec_helper.rb'
|
7
|
+
|
8
|
+
# Load this stuff so it only has to be loaded once for the entire suite
|
9
|
+
require 'spec/mocks'
|
10
|
+
require 'spec/mocks/extensions'
|
11
|
+
require 'spec/runner/formatter/specdoc_formatter'
|
12
|
+
require 'base64'
|
13
|
+
require 'nkf'
|
14
|
+
require 'kconv'
|
15
|
+
require 'rack'
|
16
|
+
|
17
|
+
begin
|
18
|
+
require 'json'
|
19
|
+
rescue
|
20
|
+
require 'json/pure'
|
21
|
+
end
|
22
|
+
|
23
|
+
Merb::Dispatcher
|
24
|
+
|
25
|
+
module Spec
|
26
|
+
module Runner
|
27
|
+
module Formatter
|
28
|
+
class BaseTextFormatter
|
29
|
+
def dump_failure(counter, failure)
|
30
|
+
output = @options.error_stream
|
31
|
+
output.puts
|
32
|
+
output.puts "#{counter.to_s})"
|
33
|
+
output.puts colourise("#{failure.header}\n#{failure.exception.message}", failure)
|
34
|
+
output.puts format_backtrace(failure.exception.backtrace)
|
35
|
+
output.flush
|
36
|
+
end
|
37
|
+
end
|
38
|
+
end
|
39
|
+
end
|
40
|
+
end
|
41
|
+
|
42
|
+
module Merb
|
43
|
+
class Counter
|
44
|
+
include DRb::DRbUndumped
|
45
|
+
|
46
|
+
attr_accessor :time
|
47
|
+
def initialize
|
48
|
+
@examples, @failures, @errors, @pending, @total_time = 0, 0, 0, 0, 0
|
49
|
+
@err = ""
|
50
|
+
@mutex = Mutex.new
|
51
|
+
end
|
52
|
+
|
53
|
+
def add(spec, out, err)
|
54
|
+
@mutex.synchronize do
|
55
|
+
puts
|
56
|
+
puts "Running #{spec}."
|
57
|
+
STDOUT.puts out
|
58
|
+
STDOUT.flush
|
59
|
+
match = out.match(/(\d+) examples?, (\d+) failures?(?:, (\d+) errors?)?(?:, (\d+) pending?)?/m)
|
60
|
+
time = out.match(/Finished in (\d+\.\d+) seconds/)
|
61
|
+
@total_time += time[1].to_f if time
|
62
|
+
if match
|
63
|
+
e, f, errors, pending = match[1..-1]
|
64
|
+
@examples += e.to_i
|
65
|
+
@failures += f.to_i
|
66
|
+
@errors += errors.to_i
|
67
|
+
@pending += pending.to_i
|
68
|
+
end
|
69
|
+
unless err.chomp.empty?
|
70
|
+
@err << err.chomp << "\n"
|
71
|
+
end
|
72
|
+
end
|
73
|
+
end
|
74
|
+
|
75
|
+
def report
|
76
|
+
puts @err
|
77
|
+
puts
|
78
|
+
if @failures != 0 || @errors != 0
|
79
|
+
print "\e[31m" # Red
|
80
|
+
elsif @pending != 0
|
81
|
+
print "\e[33m" # Yellow
|
82
|
+
else
|
83
|
+
print "\e[32m" # Green
|
84
|
+
end
|
85
|
+
puts "Total actual time: #{@total_time}"
|
86
|
+
puts "#{@examples} examples, #{@failures} failures, #{@errors} errors, #{@pending} pending, #{sprintf("suite run in %3.3f seconds", @time.real)}"
|
87
|
+
# TODO: we need to report pending examples all together
|
88
|
+
puts "\e[0m"
|
89
|
+
end
|
90
|
+
end
|
91
|
+
end
|
4
92
|
|
5
93
|
# Runs specs in all files matching the file pattern.
|
6
94
|
#
|
@@ -14,36 +102,40 @@ def run_specs(globs, spec_cmd='spec', run_opts = "-c", except = [])
|
|
14
102
|
require "optparse"
|
15
103
|
require "spec"
|
16
104
|
globs = globs.is_a?(Array) ? globs : [globs]
|
17
|
-
|
105
|
+
|
106
|
+
counter = Merb::Counter.new
|
107
|
+
forks = 0
|
18
108
|
|
19
109
|
time = Benchmark.measure do
|
110
|
+
pid = nil
|
20
111
|
globs.each do |glob|
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
112
|
+
Dir[glob].each do |spec|
|
113
|
+
drb_uri = DRb.start_service(nil, counter).uri
|
114
|
+
Kernel.fork do
|
115
|
+
$VERBOSE = nil
|
116
|
+
DRb.stop_service
|
117
|
+
DRb.start_service
|
118
|
+
counter_client = DRbObject.new_with_uri(drb_uri)
|
119
|
+
err, out = StringIO.new, StringIO.new
|
120
|
+
def out.tty?() true end
|
121
|
+
options = Spec::Runner::OptionParser.parse(%W(#{spec} -fs --color), err, out)
|
122
|
+
options.filename_pattern = File.expand_path(spec)
|
123
|
+
Spec::Runner::CommandLine.run(options)
|
124
|
+
begin
|
125
|
+
counter_client.add(spec, out.string, err.string)
|
126
|
+
rescue DRb::DRbConnError => e
|
127
|
+
puts "#{Process.pid}: Exception caught"
|
128
|
+
puts "#{e.class}: #{e.message}"
|
129
|
+
retry
|
31
130
|
end
|
32
|
-
|
33
|
-
STDOUT.puts e.read if e.is_a?(IO)
|
131
|
+
exit
|
34
132
|
end
|
35
133
|
end
|
134
|
+
Process.waitall
|
36
135
|
end
|
37
136
|
end
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
print "\e[32m"
|
43
|
-
else
|
44
|
-
print "\e[31m"
|
45
|
-
end
|
46
|
-
puts "#{examples} examples, #{failures} failures, #{errors} errors, #{pending} pending, #{sprintf("suite run in %3.3f seconds", time.real)}"
|
47
|
-
# TODO: we need to report pending examples all together
|
48
|
-
print "\e[0m"
|
137
|
+
|
138
|
+
counter.time = time
|
139
|
+
counter.report
|
140
|
+
exit!
|
49
141
|
end
|