spin 0.7.0 → 0.7.1
Sign up to get free protection for your applications and to get access to all the features.
- data/lib/spin.rb +76 -64
- data/lib/spin/version.rb +1 -1
- metadata +3 -3
- data/lib/spin/test_process.rb +0 -21
data/lib/spin.rb
CHANGED
@@ -1,6 +1,5 @@
|
|
1
1
|
require 'spin/version'
|
2
2
|
require 'spin/hooks'
|
3
|
-
require 'spin/test_process'
|
4
3
|
require 'spin/logger'
|
5
4
|
require 'socket'
|
6
5
|
require 'tempfile' # Dir.tmpdir
|
@@ -17,8 +16,9 @@ module Spin
|
|
17
16
|
|
18
17
|
PUSH_FILE_SEPARATOR = '|'
|
19
18
|
ARGS_SEPARATOR = ' -- '
|
20
|
-
#
|
21
|
-
|
19
|
+
# Messages written to/read from the self-pipe queue.
|
20
|
+
SIGQUIT_MESSAGE = 'SIGQUIT'
|
21
|
+
SIGINT_MESSAGE = 'SIGINT'
|
22
22
|
|
23
23
|
class << self
|
24
24
|
def serve(options)
|
@@ -35,15 +35,66 @@ module Spin
|
|
35
35
|
|
36
36
|
open_socket do |socket|
|
37
37
|
preload(options) if root_path
|
38
|
+
self_read, self_write = IO.pipe
|
38
39
|
|
39
|
-
|
40
|
+
if options[:push_results]
|
41
|
+
logger.info "Pushing test results back to push processes"
|
42
|
+
else
|
43
|
+
trap('SIGQUIT') { sigquit_handler(self_write) }
|
44
|
+
end
|
45
|
+
trap('SIGINT') { sigint_handler(self_write) }
|
40
46
|
|
41
47
|
loop do
|
42
|
-
|
48
|
+
readable_io = ready_while do
|
49
|
+
IO.select([socket, self_read])[0][0]
|
50
|
+
end
|
51
|
+
|
52
|
+
if readable_io == self_read
|
53
|
+
# One of our signal handlers has fired
|
54
|
+
case readable_io.gets.strip
|
55
|
+
when SIGQUIT_MESSAGE
|
56
|
+
rerun_last_tests(options)
|
57
|
+
when SIGINT_MESSAGE
|
58
|
+
exit_server(socket)
|
59
|
+
end
|
60
|
+
else
|
61
|
+
# The socket must have had a new test written to it
|
62
|
+
run_pushed_tests(socket, options)
|
63
|
+
end
|
43
64
|
end
|
44
65
|
end
|
45
66
|
end
|
46
67
|
|
68
|
+
# This method is called when a SIGQUIT ought to be handled.
|
69
|
+
#
|
70
|
+
# Given the self-pipe +queue+, adds a SIGQUIT message to it. Message is
|
71
|
+
# *not* queued if the current process is not the Spin server process (i.e.
|
72
|
+
# it's a test process). Otherwise, more than one message would be added to
|
73
|
+
# the queue when Ctrl+\ is pressed.
|
74
|
+
#
|
75
|
+
def sigquit_handler(queue)
|
76
|
+
return unless server_process?
|
77
|
+
|
78
|
+
queue.puts(SIGQUIT_MESSAGE)
|
79
|
+
end
|
80
|
+
|
81
|
+
# This method is called when a SIGINT ought to be handled.
|
82
|
+
#
|
83
|
+
# Given the self-pipe +queue+, adds a SIGINT message to it. Message is
|
84
|
+
# *not* queued if either of these are true:
|
85
|
+
#
|
86
|
+
# 1. The current process is not the Spin server process (i.e. it's a test
|
87
|
+
# process). Instead, the signal is "bubbled up" by exiting.
|
88
|
+
#
|
89
|
+
# 2. The Spin server is not ready for a new command.
|
90
|
+
#
|
91
|
+
def sigint_handler(queue)
|
92
|
+
exit unless server_process?
|
93
|
+
return unless ready?
|
94
|
+
|
95
|
+
queue.puts(SIGINT_MESSAGE)
|
96
|
+
end
|
97
|
+
|
47
98
|
def logger
|
48
99
|
@logger ||= Spin::Logger.new
|
49
100
|
end
|
@@ -136,10 +187,6 @@ module Spin
|
|
136
187
|
end
|
137
188
|
|
138
189
|
def run_pushed_tests(socket, options)
|
139
|
-
rerun_last_tests_on_quit(options) unless options[:push_results]
|
140
|
-
|
141
|
-
notify_ready
|
142
|
-
|
143
190
|
# Since `spin push` reconnects each time it has new files for us we just
|
144
191
|
# need to accept(2) connections from it.
|
145
192
|
conn = socket.accept
|
@@ -172,36 +219,28 @@ module Spin
|
|
172
219
|
end
|
173
220
|
end
|
174
221
|
|
175
|
-
#
|
176
|
-
|
177
|
-
def rerun_last_tests_on_quit(options)
|
178
|
-
trap('QUIT') { sigquit_handler(options) }
|
179
|
-
end
|
180
|
-
|
181
|
-
# This method is called when a SIGQUIT ought to be handled.
|
182
|
-
def sigquit_handler(options)
|
183
|
-
# If the current process is not the Spin server process, ignore the
|
184
|
-
# signal by doing nothing.
|
185
|
-
return unless server_process?
|
186
|
-
|
222
|
+
# Reruns the last tests that were pushed.
|
223
|
+
def rerun_last_tests(options)
|
187
224
|
unless @last_files_ran
|
188
225
|
logger.fatal "Cannot rerun last tests, please push a file to Spin server first"
|
189
226
|
return
|
190
227
|
end
|
191
228
|
|
192
|
-
if test_process.alive?
|
193
|
-
logger.fatal "Cannot rerun last tests, test process #{test_process} still alive"
|
194
|
-
return
|
195
|
-
end
|
196
|
-
|
197
229
|
fork_and_run(@last_files_ran, nil, options.merge(:trailing_args => @last_trailing_args_used))
|
230
|
+
end
|
198
231
|
|
199
|
-
|
232
|
+
# Changes Spin server's "ready" state to +true+ while the given +block+
|
233
|
+
# executes. Returns the result of the +block+.
|
234
|
+
def ready_while(&block)
|
235
|
+
@ready = true
|
236
|
+
logger.info('Ready')
|
237
|
+
yield.tap { @ready = false }
|
200
238
|
end
|
201
239
|
|
202
|
-
#
|
203
|
-
|
204
|
-
|
240
|
+
# Returns Spin server's "ready" state. If +true+, this indicates that the
|
241
|
+
# server is available for new tests or commands.
|
242
|
+
def ready?
|
243
|
+
@ready
|
205
244
|
end
|
206
245
|
|
207
246
|
def preload(options)
|
@@ -252,38 +291,16 @@ module Spin
|
|
252
291
|
File.delete(file) if File.exist?(file)
|
253
292
|
socket = UNIXServer.open(file)
|
254
293
|
|
255
|
-
trap('SIGINT') { sigint_handler(socket) }
|
256
|
-
|
257
294
|
yield socket
|
258
295
|
ensure
|
259
296
|
File.delete(file) if file && File.exist?(file)
|
260
297
|
end
|
261
298
|
|
262
|
-
#
|
263
|
-
def
|
264
|
-
|
265
|
-
|
266
|
-
exit
|
267
|
-
|
268
|
-
if sigint_recently_sent?
|
269
|
-
socket.close
|
270
|
-
exit
|
271
|
-
else
|
272
|
-
set_last_sigint_sent
|
273
|
-
logger.info "Press Ctrl+C again (within #{SIGINT_TIME_WINDOW}s) to exit"
|
274
|
-
end
|
275
|
-
end
|
276
|
-
|
277
|
-
# Updates the timestamp when the last SIGINT was sent.
|
278
|
-
def set_last_sigint_sent
|
279
|
-
@last_sigint_sent = Time.now
|
280
|
-
end
|
281
|
-
|
282
|
-
# Returns +true+ if a SIGINT has been sent within the time window.
|
283
|
-
def sigint_recently_sent?
|
284
|
-
return if @last_sigint_sent.nil?
|
285
|
-
|
286
|
-
(Time.now - SIGINT_TIME_WINDOW) < @last_sigint_sent
|
299
|
+
# Exits the server process.
|
300
|
+
def exit_server(socket)
|
301
|
+
logger.info "Exiting"
|
302
|
+
socket.close
|
303
|
+
exit
|
287
304
|
end
|
288
305
|
|
289
306
|
def determine_test_framework
|
@@ -308,17 +325,12 @@ module Spin
|
|
308
325
|
path
|
309
326
|
end
|
310
327
|
|
311
|
-
# Returns (and caches) a TestProcess instance.
|
312
|
-
def test_process
|
313
|
-
@test_process ||= Spin::TestProcess.new
|
314
|
-
end
|
315
|
-
|
316
328
|
def fork_and_run(files, conn, options)
|
317
329
|
execute_hook(:before_fork)
|
318
330
|
# We fork(2) before loading the file so that our pristine preloaded
|
319
331
|
# environment is untouched. The child process will load whatever code it
|
320
332
|
# needs to, then it exits and we're back to the baseline preloaded app.
|
321
|
-
|
333
|
+
fork do
|
322
334
|
# To push the test results to the push process instead of having them
|
323
335
|
# displayed by the server, we reopen $stdout/$stderr to the open
|
324
336
|
# connection.
|
@@ -361,7 +373,7 @@ module Spin
|
|
361
373
|
# WAIT: We don't want the parent process handling multiple test runs at the same
|
362
374
|
# time because then we'd need to deal with multiple test databases, and
|
363
375
|
# that destroys the idea of being simple to use.
|
364
|
-
|
376
|
+
Process.wait
|
365
377
|
end
|
366
378
|
|
367
379
|
def socket_file
|
data/lib/spin/version.rb
CHANGED
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: spin
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.7.
|
4
|
+
version: 0.7.1
|
5
5
|
prerelease:
|
6
6
|
platform: ruby
|
7
7
|
authors:
|
@@ -9,7 +9,7 @@ authors:
|
|
9
9
|
autorequire:
|
10
10
|
bindir: bin
|
11
11
|
cert_chain: []
|
12
|
-
date: 2013-
|
12
|
+
date: 2013-08-18 00:00:00.000000000 Z
|
13
13
|
dependencies:
|
14
14
|
- !ruby/object:Gem::Dependency
|
15
15
|
name: rake
|
@@ -60,7 +60,6 @@ files:
|
|
60
60
|
- lib/spin/cli.rb
|
61
61
|
- lib/spin/hooks.rb
|
62
62
|
- lib/spin/logger.rb
|
63
|
-
- lib/spin/test_process.rb
|
64
63
|
- lib/spin/version.rb
|
65
64
|
- lib/spin.rb
|
66
65
|
- spec/integration_spec.rb
|
@@ -91,3 +90,4 @@ specification_version: 3
|
|
91
90
|
summary: Spin preloads your Rails environment to speed up your autotest(ish) workflow.
|
92
91
|
test_files:
|
93
92
|
- spec/integration_spec.rb
|
93
|
+
has_rdoc:
|
data/lib/spin/test_process.rb
DELETED
@@ -1,21 +0,0 @@
|
|
1
|
-
module Spin
|
2
|
-
class TestProcess
|
3
|
-
attr_accessor :pid
|
4
|
-
|
5
|
-
# Use wait(2) to block execution until the test process has finished. When
|
6
|
-
# finished, reset the assigned pid.
|
7
|
-
def wait
|
8
|
-
Process.wait
|
9
|
-
@pid = nil
|
10
|
-
end
|
11
|
-
|
12
|
-
# Returns +true+ if the test process is alive.
|
13
|
-
def alive?
|
14
|
-
!@pid.nil?
|
15
|
-
end
|
16
|
-
|
17
|
-
def to_s
|
18
|
-
@pid.to_s
|
19
|
-
end
|
20
|
-
end
|
21
|
-
end
|