spring 0.0.6 → 0.0.7

Sign up to get free protection for your applications and to get access to all the features.
@@ -1,5 +1,3 @@
1
- require 'active_support/core_ext/class/attribute'
2
-
3
1
  module Spring
4
2
  @commands = {}
5
3
 
@@ -25,8 +23,19 @@ module Spring
25
23
 
26
24
  module Commands
27
25
  class Command
28
- class_attribute :preloads
29
- self.preloads = []
26
+ @preloads = []
27
+
28
+ def self.preloads
29
+ @preloads ||= superclass.preloads.dup
30
+ end
31
+
32
+ def self.preloads=(val)
33
+ @preloads = val
34
+ end
35
+
36
+ def preloads
37
+ self.class.preloads
38
+ end
30
39
 
31
40
  def setup
32
41
  preload_files
@@ -50,7 +59,7 @@ MESSAGE
50
59
  end
51
60
 
52
61
  class Test < Command
53
- self.preloads += %w(test_helper)
62
+ preloads << "test_helper"
54
63
 
55
64
  def env
56
65
  "test"
@@ -75,11 +84,15 @@ MESSAGE
75
84
  $stderr.puts "you need to specify what test to run: spring test TEST_NAME"
76
85
  end
77
86
  end
87
+
88
+ def description
89
+ "Execute a Test::Unit test."
90
+ end
78
91
  end
79
92
  Spring.register_command "test", Test.new
80
93
 
81
94
  class RSpec < Command
82
- self.preloads += %w(spec_helper)
95
+ preloads << "spec_helper"
83
96
 
84
97
  def env
85
98
  "test"
@@ -95,6 +108,10 @@ MESSAGE
95
108
  $0 = "rspec"
96
109
  ::RSpec::Core::Runner.run(args)
97
110
  end
111
+
112
+ def description
113
+ "Execute an RSpec spec."
114
+ end
98
115
  end
99
116
  Spring.register_command "rspec", RSpec.new
100
117
 
@@ -111,6 +128,10 @@ MESSAGE
111
128
  def call(args)
112
129
  ::Cucumber::Cli::Main.execute(args)
113
130
  end
131
+
132
+ def description
133
+ "Execute a Cucumber feature."
134
+ end
114
135
  end
115
136
  Spring.register_command "cucumber", Cucumber.new
116
137
 
@@ -124,19 +145,27 @@ MESSAGE
124
145
  ARGV.replace args
125
146
  ::Rake.application.run
126
147
  end
148
+
149
+ def description
150
+ "Run a rake task."
151
+ end
127
152
  end
128
153
  Spring.register_command "rake", Rake.new
129
154
 
130
155
 
131
156
  class Console < Command
132
- def call(args)
133
- # This cannot be preloaded as it messes up the IRB prompt on OS X
134
- # for unknown reasons. See discussion in issue #34.
157
+ def setup
135
158
  require "rails/commands/console"
159
+ end
136
160
 
161
+ def call(args)
137
162
  ARGV.replace args
138
163
  ::Rails::Console.start(::Rails.application)
139
164
  end
165
+
166
+ def description
167
+ "Start the Rails console."
168
+ end
140
169
  end
141
170
  Spring.register_command "console", Console.new, alias: "c"
142
171
 
@@ -150,6 +179,10 @@ MESSAGE
150
179
  ARGV.replace args
151
180
  require "rails/commands/generate"
152
181
  end
182
+
183
+ def description
184
+ "Trigger a Rails generator."
185
+ end
153
186
  end
154
187
  Spring.register_command "generate", Generate.new, alias: "g"
155
188
 
@@ -159,6 +192,10 @@ MESSAGE
159
192
  ARGV.replace args
160
193
  require "rails/commands/runner"
161
194
  end
195
+
196
+ def description
197
+ "Execute a command with the Rails runner."
198
+ end
162
199
  end
163
200
  Spring.register_command "runner", Runner.new, alias: "r"
164
201
  end
@@ -167,5 +204,4 @@ MESSAGE
167
204
  # needs to be at the end to allow modification of existing commands.
168
205
  config = File.expand_path("./config/spring.rb")
169
206
  require config if File.exist?(config)
170
-
171
207
  end
@@ -4,6 +4,14 @@ module Spring
4
4
  class << self
5
5
  attr_accessor :application_root
6
6
 
7
+ def after_fork_callbacks
8
+ @after_fork_callbacks ||= []
9
+ end
10
+
11
+ def after_fork(&block)
12
+ after_fork_callbacks << block
13
+ end
14
+
7
15
  def verify_environment!
8
16
  application_root_path
9
17
  end
data/lib/spring/env.rb CHANGED
@@ -25,7 +25,7 @@ module Spring
25
25
  end
26
26
 
27
27
  def socket_path
28
- tmp_path.join(SID.sid.to_s)
28
+ tmp_path.join("spring")
29
29
  end
30
30
 
31
31
  def socket_name
@@ -33,11 +33,14 @@ module Spring
33
33
  end
34
34
 
35
35
  def pidfile_path
36
- tmp_path.join("#{SID.sid}.pid")
36
+ tmp_path.join("spring.pid")
37
37
  end
38
38
 
39
39
  def pid
40
40
  pidfile_path.exist? ? pidfile_path.read.to_i : nil
41
+ rescue Errno::ENOENT
42
+ # This can happen if the pidfile is removed after we check it
43
+ # exists
41
44
  end
42
45
 
43
46
  def app_name
@@ -0,0 +1,65 @@
1
+ module Spring
2
+ # Yes, I know this reimplements a bunch of stuff in Active Support, but
3
+ # I don't want the spring client to depend on AS, in order to keep its
4
+ # load time down.
5
+ class ProcessTitleUpdater
6
+ SECOND = 1
7
+ MINUTE = 60
8
+ HOUR = 60*60
9
+
10
+ def self.run(&block)
11
+ updater = new(&block)
12
+
13
+ Thread.new {
14
+ $0 = updater.value
15
+ loop { $0 = updater.next }
16
+ }
17
+ end
18
+
19
+ attr_reader :block
20
+
21
+ def initialize(start = Time.now, &block)
22
+ @start = start
23
+ @block = block
24
+ end
25
+
26
+ def interval
27
+ distance = Time.now - @start
28
+
29
+ if distance < MINUTE
30
+ SECOND
31
+ elsif distance < HOUR
32
+ MINUTE
33
+ else
34
+ HOUR
35
+ end
36
+ end
37
+
38
+ def next
39
+ sleep interval
40
+ value
41
+ end
42
+
43
+ def value
44
+ block.call(distance_in_words)
45
+ end
46
+
47
+ def distance_in_words(now = Time.now)
48
+ distance = now - @start
49
+
50
+ if distance < MINUTE
51
+ pluralize(distance, "sec")
52
+ elsif distance < HOUR
53
+ pluralize(distance / MINUTE, "min")
54
+ else
55
+ pluralize(distance / HOUR, "hour")
56
+ end
57
+ end
58
+
59
+ private
60
+
61
+ def pluralize(amount, unit)
62
+ "#{amount.to_i} #{amount.to_i == 1 ? unit : "#{unit}s"}"
63
+ end
64
+ end
65
+ end
data/lib/spring/server.rb CHANGED
@@ -2,6 +2,11 @@ require "socket"
2
2
 
3
3
  require "spring/env"
4
4
  require "spring/application_manager"
5
+ require "spring/process_title_updater"
6
+
7
+ # readline must be required before we setpgid, otherwise the require may hang,
8
+ # if readline has been built against libedit. See issue #70.
9
+ require "readline"
5
10
 
6
11
  module Spring
7
12
  class Server
@@ -18,14 +23,19 @@ module Spring
18
23
  end
19
24
 
20
25
  def boot
26
+ # Boot the server into the process group of the current session.
27
+ # This will cause it to be automatically killed once the session
28
+ # ends (i.e. when the user closes their terminal).
29
+ Process.setpgid(0, SID.pgid)
30
+
21
31
  # Ignore SIGINT and SIGQUIT otherwise the user typing ^C or ^\ on the command line
22
32
  # will kill the server/application.
23
33
  IGNORE_SIGNALS.each { |sig| trap(sig, "IGNORE") }
24
34
 
25
35
  set_exit_hook
26
36
  write_pidfile
27
-
28
- $0 = "spring server | #{env.app_name} | started #{Time.now}"
37
+ redirect_output
38
+ set_process_title
29
39
 
30
40
  server = UNIXServer.open(env.socket_name)
31
41
  loop { serve server.accept }
@@ -62,9 +72,30 @@ module Spring
62
72
  @pidfile.write("#{Process.pid}\n")
63
73
  @pidfile.fsync
64
74
  else
65
- STDERR.puts "#{file.path} is locked; it looks like a server is already running"
75
+ $stderr.puts "#{@pidfile.path} is locked; it looks like a server is already running"
66
76
  exit 1
67
77
  end
68
78
  end
79
+
80
+ # We can't leave STDOUT, STDERR as they as because then they will
81
+ # never get closed for the lifetime of the server. This means that
82
+ # piping, e.g. "spring rake -T | grep db" won't work correctly
83
+ # because grep will hang while waiting for its stdin to reach EOF.
84
+ #
85
+ # However we do want server output to go to the terminal in case
86
+ # there are exceptions etc, so we just open the current terminal
87
+ # device directly.
88
+ def redirect_output
89
+ # ruby doesn't expose ttyname()
90
+ file = open(STDIN.tty? ? `tty`.chomp : "/dev/null", "a")
91
+ STDOUT.reopen(file)
92
+ STDERR.reopen(file)
93
+ end
94
+
95
+ def set_process_title
96
+ ProcessTitleUpdater.run { |distance|
97
+ "spring server | #{env.app_name} | started #{distance} ago"
98
+ }
99
+ end
69
100
  end
70
101
  end
data/lib/spring/sid.rb CHANGED
@@ -1,15 +1,38 @@
1
- require 'fiddle'
1
+ begin
2
+ # If rubygems is present, keep it out of the way when loading fiddle,
3
+ # otherwise if fiddle is not installed then rubygems will load all
4
+ # gemspecs in its (futile) search for fiddle, which is slow.
5
+ if respond_to?(:gem_original_require, true)
6
+ gem_original_require 'fiddle'
7
+ else
8
+ require 'fiddle'
9
+ end
10
+ rescue LoadError
11
+ end
2
12
 
3
13
  module Spring
4
14
  module SID
5
- FUNC = Fiddle::Function.new(
6
- DL::Handle::DEFAULT['getsid'],
7
- [Fiddle::TYPE_INT],
8
- Fiddle::TYPE_INT
9
- )
15
+ def self.fiddle_func
16
+ @fiddle_func ||= Fiddle::Function.new(
17
+ DL::Handle::DEFAULT['getsid'],
18
+ [Fiddle::TYPE_INT],
19
+ Fiddle::TYPE_INT
20
+ )
21
+ end
10
22
 
11
- def self.sid(pid = 0)
12
- FUNC.call(pid)
23
+ def self.sid
24
+ @sid ||= begin
25
+ if Process.respond_to?(:getsid)
26
+ # Ruby 2
27
+ Process.getsid
28
+ elsif defined?(Fiddle)
29
+ # Ruby 1.9.3 compiled with libffi support
30
+ fiddle_func.call(0)
31
+ else
32
+ # last resort: shell out
33
+ `ps -p #{Process.pid} -o sess=`.to_i
34
+ end
35
+ end
13
36
  end
14
37
 
15
38
  def self.pgid
@@ -1,3 +1,3 @@
1
1
  module Spring
2
- VERSION = "0.0.6"
2
+ VERSION = "0.0.7"
3
3
  end
@@ -3,26 +3,23 @@ require 'io/wait'
3
3
  require "timeout"
4
4
  require "spring/sid"
5
5
  require "spring/env"
6
+ require "pty"
6
7
 
7
8
  class AppTest < ActiveSupport::TestCase
8
9
  def app_root
9
10
  Pathname.new("#{TEST_ROOT}/apps/rails-3-2")
10
11
  end
11
12
 
12
- def server_pidfile
13
- "#{app_root}/tmp/spring/#{Spring::SID.sid}.pid"
13
+ def gem_home
14
+ app_root.join "vendor/gems/#{RUBY_VERSION}"
14
15
  end
15
16
 
16
- def spring_env
17
- @spring_env ||= Spring::Env.new(app_root)
18
- end
19
-
20
- def server_pid
21
- spring_env.pid
17
+ def spring
18
+ gem_home.join "bin/spring"
22
19
  end
23
20
 
24
- def server_running?
25
- spring_env.server_running?
21
+ def spring_env
22
+ @spring_env ||= Spring::Env.new(app_root)
26
23
  end
27
24
 
28
25
  def stdout
@@ -38,90 +35,83 @@ class AppTest < ActiveSupport::TestCase
38
35
 
39
36
  Bundler.with_clean_env do
40
37
  Process.spawn(
41
- {
42
- "GEM_HOME" => "#{app_root}/vendor/gems",
43
- "GEM_PATH" => "",
44
- "PATH" => "#{app_root}/vendor/gems/bin:#{ENV["PATH"]}"
45
- },
46
- command,
38
+ { "GEM_HOME" => gem_home.to_s, "GEM_PATH" => "" },
39
+ command.to_s,
47
40
  out: stdout.last,
48
41
  err: stderr.last,
42
+ in: :close,
49
43
  chdir: app_root.to_s,
50
44
  )
51
45
  end
52
46
 
53
47
  _, status = Timeout.timeout(opts.fetch(:timeout, 5)) { Process.wait2 }
54
48
 
55
- out, err = read_streams
49
+ stdout, stderr = read_streams
50
+ puts dump_streams(stdout, stderr) if ENV["SPRING_DEBUG"]
56
51
 
57
52
  @times << (Time.now - start_time) if @times
58
53
 
59
- print_streams(out, err) if ENV["SPRING_DEBUG"]
60
-
61
- [status, out, err]
62
- rescue Timeout::Error
63
- print_streams *read_streams
64
- raise
54
+ {
55
+ status: status,
56
+ stdout: stdout,
57
+ stderr: stderr,
58
+ }
59
+ rescue Timeout::Error => e
60
+ raise e, "Output:\n\n#{dump_streams(*read_streams)}"
65
61
  end
66
62
 
67
- def print_streams(out, err)
68
- puts "---"
69
- puts out
70
- puts "***"
71
- puts err
72
- puts "---"
63
+ def read_streams
64
+ [stdout, stderr].map(&:first).map do |stream|
65
+ output = ""
66
+ output << stream.readpartial(10240) while IO.select([stream], [], [], 0.1)
67
+ output
68
+ end
73
69
  end
74
70
 
75
- def read_streams
76
- [stdout, stderr].map(&:first).map { |s| s.ready? ? s.readpartial(10240) : "" }
71
+ def dump_streams(stdout, stderr)
72
+ output = "--- stdout ---\n"
73
+ output << "#{stdout.chomp}\n"
74
+ output << "--- stderr ---\n"
75
+ output << "#{stderr.chomp}\n"
76
+ output << "\n"
77
+ output
77
78
  end
78
79
 
79
80
  def await_reload
80
81
  sleep 0.4
81
82
  end
82
83
 
83
- def assert_successful_run(*args)
84
- status, _, _ = app_run(*args)
85
- assert status.success?, "The run should be successful but it wasn't"
86
- end
87
-
88
- def assert_unsuccessful_run(*args)
89
- status, _, _ = app_run(*args)
90
- assert !status.success?, "The run should not be successful but it was"
91
- end
92
-
93
- def assert_stdout(command, expected)
94
- _, stdout, _ = app_run(command)
95
- assert stdout.include?(expected), "expected '#{expected}' to be printed to stdout. But it wasn't, the stdout is:\n#{stdout}"
84
+ def assert_output(artifacts, expected)
85
+ expected.each do |stream, output|
86
+ assert artifacts[stream].include?(output),
87
+ "expected #{stream} to include '#{output}', but it was:\n\n#{artifacts[stream]}"
88
+ end
96
89
  end
97
90
 
98
- def assert_stderr(command, expected)
99
- _, _, stderr = app_run(command)
100
- assert stderr.include?(expected), "expected '#{expected}' to be printed to stderr. But it wasn't, the stderr is:\n#{stderr}"
91
+ def assert_success(command, expected_output = nil)
92
+ artifacts = app_run(command)
93
+ assert artifacts[:status].success?, "expected successful exit status"
94
+ assert_output artifacts, expected_output if expected_output
101
95
  end
102
96
 
103
- def assert_speedup(opts = {})
104
- ratio = opts.fetch(:ratio, 0.5)
105
- from = opts.fetch(:from, 0)
106
- first = @times[from]
107
- second = @times[from + 1]
108
-
109
- assert (second / first) < ratio, "#{second} was not less than #{ratio} of #{first}"
97
+ def assert_failure(command, expected_output = nil)
98
+ artifacts = app_run(command)
99
+ assert !artifacts[:status].success?, "expected unsuccessful exit status"
100
+ assert_output artifacts, expected_output if expected_output
110
101
  end
111
102
 
112
- def assert_server_running(*args)
113
- assert server_running?, "The server should be running but it isn't"
114
- end
115
-
116
- def assert_server_not_running(*args)
117
- assert !server_running?, "The server should not be running but it is"
103
+ def assert_speedup(ratio = 0.6)
104
+ @times = []
105
+ yield
106
+ assert (@times.last / @times.first) < ratio, "#{@times.last} was not less than #{ratio} of #{@times.first}"
107
+ @times = nil
118
108
  end
119
109
 
120
- def test_command
121
- "spring test #{@test}"
110
+ def spring_test_command
111
+ "#{spring} test #{@test}"
122
112
  end
123
113
 
124
- @@installed_spring = false
114
+ @@installed = false
125
115
 
126
116
  setup do
127
117
  @test = "#{app_root}/test/functional/posts_controller_test.rb"
@@ -129,59 +119,51 @@ class AppTest < ActiveSupport::TestCase
129
119
  @controller = "#{app_root}/app/controllers/posts_controller.rb"
130
120
  @controller_contents = File.read(@controller)
131
121
 
132
- @spring_env = Spring::Env.new(app_root)
133
-
134
- unless @@installed_spring
122
+ unless @@installed
123
+ FileUtils.mkdir_p(gem_home)
135
124
  system "gem build spring.gemspec 2>/dev/null 1>/dev/null"
136
- app_run "gem install ../../../spring-*.gem"
137
- @@installed_spring = true
125
+ app_run "gem install ../../../spring-#{Spring::VERSION}.gem"
126
+ app_run "(gem list bundler | grep bundler) || gem install bundler #{'--pre' if RUBY_VERSION >= "2.0"}", timeout: nil
127
+ app_run "bundle check || bundle update", timeout: nil
128
+ app_run "bundle exec rake db:migrate db:test:clone"
129
+ @@installed = true
138
130
  end
139
131
 
140
132
  FileUtils.rm_rf "#{app_root}/bin"
141
- app_run "(gem list bundler | grep bundler) || gem install bundler", timeout: nil
142
- app_run "bundle check || bundle update", timeout: nil
143
- app_run "bundle exec rake db:migrate"
144
-
145
- @times = []
146
133
  end
147
134
 
148
135
  teardown do
149
- if pid = server_pid
150
- Process.kill('TERM', pid)
151
- end
152
-
136
+ app_run "#{spring} stop"
153
137
  File.write(@test, @test_contents)
154
138
  File.write(@controller, @controller_contents)
155
139
  end
156
140
 
157
141
  test "basic" do
158
- assert_successful_run test_command
159
- assert File.exist?(server_pidfile)
160
-
161
- assert_successful_run test_command
162
- assert_speedup
142
+ assert_speedup do
143
+ 2.times { app_run spring_test_command }
144
+ end
163
145
  end
164
146
 
165
147
  test "help message when called without arguments" do
166
- assert_stdout "spring", 'Usage: spring COMMAND [ARGS]'
148
+ assert_success spring, stdout: 'Usage: spring COMMAND [ARGS]'
167
149
  end
168
150
 
169
151
  test "test changes are picked up" do
170
- assert_successful_run test_command
171
-
172
- File.write(@test, @test_contents.sub("get :index", "raise 'omg'"))
173
- assert_stdout test_command, "RuntimeError: omg"
152
+ assert_speedup do
153
+ assert_success spring_test_command, stdout: "0 failures"
174
154
 
175
- assert_speedup
155
+ File.write(@test, @test_contents.sub("get :index", "raise 'omg'"))
156
+ assert_failure spring_test_command, stdout: "RuntimeError: omg"
157
+ end
176
158
  end
177
159
 
178
160
  test "code changes are picked up" do
179
- assert_successful_run test_command
161
+ assert_speedup do
162
+ assert_success spring_test_command, stdout: "0 failures"
180
163
 
181
- File.write(@controller, @controller_contents.sub("@posts = Post.all", "raise 'omg'"))
182
- assert_stdout test_command, "RuntimeError: omg"
183
-
184
- assert_speedup
164
+ File.write(@controller, @controller_contents.sub("@posts = Post.all", "raise 'omg'"))
165
+ assert_failure spring_test_command, stdout: "RuntimeError: omg"
166
+ end
185
167
  end
186
168
 
187
169
  test "code changes in pre-referenced app files are picked up" do
@@ -189,12 +171,12 @@ class AppTest < ActiveSupport::TestCase
189
171
  initializer = "#{app_root}/config/initializers/load_posts_controller.rb"
190
172
  File.write(initializer, "PostsController\n")
191
173
 
192
- assert_successful_run test_command
193
-
194
- File.write(@controller, @controller_contents.sub("@posts = Post.all", "raise 'omg'"))
195
- assert_stdout test_command, "RuntimeError: omg"
174
+ assert_speedup do
175
+ assert_success spring_test_command, stdout: "0 failures"
196
176
 
197
- assert_speedup
177
+ File.write(@controller, @controller_contents.sub("@posts = Post.all", "raise 'omg'"))
178
+ assert_failure spring_test_command, stdout: "RuntimeError: omg"
179
+ end
198
180
  ensure
199
181
  FileUtils.rm_f(initializer)
200
182
  end
@@ -205,7 +187,7 @@ class AppTest < ActiveSupport::TestCase
205
187
  application = "#{app_root}/config/application.rb"
206
188
  application_contents = File.read(application)
207
189
 
208
- assert_successful_run test_command
190
+ assert_success spring_test_command
209
191
 
210
192
  File.write(application, application_contents + <<-CODE)
211
193
  class Foo
@@ -218,10 +200,9 @@ class AppTest < ActiveSupport::TestCase
218
200
 
219
201
  await_reload
220
202
 
221
- assert_stdout test_command, "RuntimeError: omg"
222
- assert_stdout test_command, "RuntimeError: omg"
223
-
224
- assert_speedup from: 1
203
+ assert_speedup do
204
+ 2.times { assert_failure spring_test_command, stdout: "RuntimeError: omg" }
205
+ end
225
206
  ensure
226
207
  File.write(application, application_contents)
227
208
  end
@@ -232,50 +213,72 @@ class AppTest < ActiveSupport::TestCase
232
213
  application = "#{app_root}/config/application.rb"
233
214
  application_contents = File.read(application)
234
215
 
235
- assert_successful_run test_command
216
+ assert_success spring_test_command
236
217
 
237
218
  File.write(application, application_contents + "\nomg")
238
219
  await_reload
239
220
 
240
- assert_unsuccessful_run test_command
221
+ assert_failure spring_test_command
241
222
 
242
223
  File.write(application, application_contents)
243
224
  await_reload
244
225
 
245
- assert_successful_run test_command
226
+ assert_success spring_test_command
246
227
  ensure
247
228
  File.write(application, application_contents)
248
229
  end
249
230
  end
250
231
 
251
232
  test "stop command kills server" do
252
- assert_successful_run test_command
253
- assert_server_running
233
+ app_run spring_test_command
234
+ assert spring_env.server_running?, "The server should be running but it isn't"
254
235
 
255
- assert_successful_run 'spring stop'
256
- assert_server_not_running
236
+ assert_success "#{spring} stop"
237
+ assert !spring_env.server_running?, "The server should not be running but it is"
257
238
  end
258
239
 
259
240
  test "custom commands" do
260
- assert_stdout "spring custom", "omg"
241
+ assert_success "#{spring} custom", stdout: "omg"
261
242
  end
262
243
 
263
244
  test "runner alias" do
264
- assert_stdout "spring r 'puts 1'", "1"
245
+ assert_success "#{spring} r 'puts 1'", stdout: "1"
265
246
  end
266
247
 
267
248
  test "binstubs" do
268
- app_run "spring binstub rake"
269
- assert_successful_run "bin/spring help"
270
- assert_stdout "bin/rake -T", "rake db:migrate"
249
+ app_run "#{spring} binstub rake"
250
+ assert_success "bin/spring help"
251
+ assert_success "bin/rake -T", stdout: "rake db:migrate"
252
+ end
253
+
254
+ test "after fork callback" do
255
+ begin
256
+ config_path = "#{app_root}/config/spring.rb"
257
+ config_contents = File.read(config_path)
258
+
259
+ File.write(config_path, config_contents + "\nSpring.after_fork { puts '!callback!' }")
260
+ assert_success "#{spring} r 'puts 2'", stdout: "!callback!\n2"
261
+ ensure
262
+ File.write(config_path, config_contents)
263
+ end
271
264
  end
272
265
 
273
266
  test "missing config/application.rb" do
274
267
  begin
275
268
  FileUtils.mv app_root.join("config/application.rb"), app_root.join("config/application.rb.bak")
276
- assert_stderr "spring rake -T", "unable to find your config/application.rb"
269
+ assert_failure "#{spring} rake -T", stderr: "unable to find your config/application.rb"
277
270
  ensure
278
271
  FileUtils.mv app_root.join("config/application.rb.bak"), app_root.join("config/application.rb")
279
272
  end
280
273
  end
274
+
275
+ test "piping" do
276
+ assert_success "#{spring} rake -T | grep db", stdout: "rake db:migrate"
277
+ end
278
+
279
+ test "status" do
280
+ assert_success "#{spring} status", stdout: "Spring is not running"
281
+ app_run "#{spring} runner ''"
282
+ assert_success "#{spring} status", stdout: "Spring is running"
283
+ end
281
284
  end