spring 2.0.0 → 3.0.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.
@@ -1,550 +0,0 @@
1
- require "io/wait"
2
- require "timeout"
3
- require "spring/sid"
4
- require "spring/client"
5
- require "active_support/core_ext/string/strip"
6
-
7
- module Spring
8
- module Test
9
- class AcceptanceTest < ActiveSupport::TestCase
10
- runnables.delete self # prevent Minitest running this class
11
-
12
- DEFAULT_SPEEDUP = 0.8
13
-
14
- def rails_version
15
- ENV['RAILS_VERSION'] || '~> 5.0.0'
16
- end
17
-
18
- # Extension point for spring-watchers-listen
19
- def generator_klass
20
- Spring::Test::ApplicationGenerator
21
- end
22
-
23
- def generator
24
- @@generator ||= generator_klass.new(rails_version)
25
- end
26
-
27
- def app
28
- @app ||= Spring::Test::Application.new("#{Spring::Test.root}/apps/tmp")
29
- end
30
-
31
- def spring_env
32
- app.spring_env
33
- end
34
-
35
- def assert_output(artifacts, expected)
36
- expected.each do |stream, output|
37
- assert artifacts[stream].include?(output),
38
- "expected #{stream} to include '#{output}'.\n\n#{app.debug(artifacts)}"
39
- end
40
- end
41
-
42
- def assert_success(command, expected_output = nil)
43
- artifacts = app.run(*Array(command))
44
- assert artifacts[:status].success?, "expected successful exit status\n\n#{app.debug(artifacts)}"
45
- assert_output artifacts, expected_output if expected_output
46
- end
47
-
48
- def assert_failure(command, expected_output = nil)
49
- artifacts = app.run(*Array(command))
50
- assert !artifacts[:status].success?, "expected unsuccessful exit status\n\n#{app.debug(artifacts)}"
51
- assert_output artifacts, expected_output if expected_output
52
- end
53
-
54
- def refute_output_includes(command, not_expected)
55
- artifacts = app.run(*Array(command))
56
- not_expected.each do |stream, output|
57
- assert !artifacts[stream].include?(output),
58
- "expected #{stream} to not include '#{output}'.\n\n#{app.debug(artifacts)}"
59
- end
60
- end
61
-
62
- def assert_speedup(ratio = DEFAULT_SPEEDUP)
63
- if ENV['CI']
64
- yield
65
- else
66
- app.with_timing do
67
- yield
68
- assert app.timing_ratio < ratio, "#{app.last_time} was not less than #{ratio} of #{app.first_time}"
69
- end
70
- end
71
- end
72
-
73
- def without_gem(name)
74
- gem_home = app.gem_home.join('gems')
75
- FileUtils.mv(gem_home.join(name), app.root)
76
- yield
77
- ensure
78
- FileUtils.mv(app.root.join(name), gem_home)
79
- end
80
-
81
- setup do
82
- generator.generate_if_missing
83
- generator.install_spring
84
- generator.copy_to(app.root)
85
- end
86
-
87
- teardown do
88
- app.stop_spring
89
- end
90
-
91
- test "basic" do
92
- assert_speedup do
93
- 2.times { app.run app.spring_test_command }
94
- end
95
- end
96
-
97
- test "help message when called without arguments" do
98
- assert_success "bin/spring", stdout: 'Usage: spring COMMAND [ARGS]'
99
- assert spring_env.server_running?
100
- end
101
-
102
- test "shows help" do
103
- assert_success "bin/spring help", stdout: 'Usage: spring COMMAND [ARGS]'
104
- assert_success "bin/spring -h", stdout: 'Usage: spring COMMAND [ARGS]'
105
- assert_success "bin/spring --help", stdout: 'Usage: spring COMMAND [ARGS]'
106
- refute spring_env.server_running?
107
- end
108
-
109
- test "tells the user that spring is being used when used automatically via binstubs" do
110
- assert_success "bin/rails runner ''", stderr: "Running via Spring preloader in process"
111
- assert_success app.spring_test_command, stderr: "Running via Spring preloader in process"
112
- end
113
-
114
- test "does not tell the user that spring is being used when used automatically via binstubs but quiet is enabled" do
115
- File.write("#{app.user_home}/.spring.rb", "Spring.quiet = true")
116
- assert_success "bin/rails runner ''"
117
- refute_output_includes "bin/rails runner ''", stderr: 'Running via Spring preloader in process'
118
- end
119
-
120
- test "test changes are picked up" do
121
- assert_speedup do
122
- assert_success app.spring_test_command, stdout: "0 failures"
123
-
124
- app.insert_into_test "raise 'omg'"
125
- assert_failure app.spring_test_command, stdout: "RuntimeError: omg"
126
- end
127
- end
128
-
129
- test "code changes are picked up" do
130
- assert_speedup do
131
- assert_success app.spring_test_command, stdout: "0 failures"
132
-
133
- File.write(app.controller, app.controller.read.sub("@posts = Post.all", "raise 'omg'"))
134
- assert_failure app.spring_test_command, stdout: "RuntimeError: omg"
135
- end
136
- end
137
-
138
- test "code changes in pre-referenced app files are picked up" do
139
- File.write(app.path("config/initializers/load_posts_controller.rb"), "PostsController\n")
140
-
141
- assert_speedup do
142
- assert_success app.spring_test_command, stdout: "0 failures"
143
-
144
- File.write(app.controller, app.controller.read.sub("@posts = Post.all", "raise 'omg'"))
145
- assert_failure app.spring_test_command, stdout: "RuntimeError: omg"
146
- end
147
- end
148
-
149
- test "app gets reloaded when preloaded files change" do
150
- assert_success app.spring_test_command
151
-
152
- File.write(app.application_config, app.application_config.read + <<-RUBY.strip_heredoc)
153
- class Foo
154
- def self.omg
155
- raise "omg"
156
- end
157
- end
158
- RUBY
159
- app.insert_into_test "Foo.omg"
160
-
161
- app.await_reload
162
- assert_failure app.spring_test_command, stdout: "RuntimeError: omg"
163
- end
164
-
165
- test "app gets reloaded even with a ton of boot output" do
166
- limit = UNIXSocket.pair.first.getsockopt(:SOCKET, :SNDBUF).int
167
-
168
- assert_success app.spring_test_command
169
- File.write(app.path("config/initializers/verbose.rb"), "#{limit}.times { puts 'x' }")
170
-
171
- app.await_reload
172
- assert_success app.spring_test_command
173
- end
174
-
175
- test "app recovers when a boot-level error is introduced" do
176
- config = app.application_config.read
177
-
178
- assert_success app.spring_test_command
179
-
180
- File.write(app.application_config, "#{config}\nomg")
181
- app.await_reload
182
-
183
- assert_failure app.spring_test_command
184
-
185
- File.write(app.application_config, config)
186
- assert_success app.spring_test_command
187
- end
188
-
189
- test "stop command kills server" do
190
- app.run app.spring_test_command
191
- assert spring_env.server_running?, "The server should be running but it isn't"
192
-
193
- assert_success "bin/spring stop"
194
- assert !spring_env.server_running?, "The server should not be running but it is"
195
- end
196
-
197
- test "custom commands" do
198
- # Start spring before setting up the command, to test that it gracefully upgrades itself
199
- assert_success "bin/rails runner ''"
200
-
201
- File.write(app.spring_config, <<-RUBY.strip_heredoc)
202
- class CustomCommand
203
- def call
204
- puts "omg"
205
- end
206
-
207
- def exec_name
208
- "rake"
209
- end
210
- end
211
-
212
- Spring.register_command "custom", CustomCommand.new
213
- RUBY
214
-
215
- assert_success "bin/spring custom", stdout: "omg"
216
-
217
- assert_success "bin/spring binstub custom"
218
- assert_success "bin/custom", stdout: "omg"
219
-
220
- app.env["DISABLE_SPRING"] = "1"
221
- assert_success %{bin/custom -e 'puts "foo"'}, stdout: "foo"
222
- end
223
-
224
- test "binstub" do
225
- assert_success "bin/rails server --help", stdout: "Usage: rails server" # rails command fallback
226
-
227
- assert_success "#{app.spring} binstub rake", stdout: "bin/rake: spring already present"
228
-
229
- assert_success "#{app.spring} binstub --remove rake", stdout: "bin/rake: spring removed"
230
- assert !app.path("bin/rake").read.include?(Spring::Client::Binstub::LOADER)
231
- assert_success "bin/rake -T", stdout: "rake db:migrate"
232
- end
233
-
234
- test "binstub remove all" do
235
- assert_success "bin/spring binstub --remove --all"
236
- refute File.exist?(app.path("bin/spring"))
237
- end
238
-
239
- test "binstub when spring gem is missing" do
240
- without_gem "spring-#{Spring::VERSION}" do
241
- File.write(app.gemfile, app.gemfile.read.gsub(/gem 'spring.*/, ""))
242
- assert_success "bin/rake -T", stdout: "rake db:migrate"
243
- end
244
- end
245
-
246
- test "binstub when spring binary is missing" do
247
- begin
248
- File.rename(app.path("bin/spring"), app.path("bin/spring.bak"))
249
- assert_success "bin/rake -T", stdout: "rake db:migrate"
250
- ensure
251
- File.rename(app.path("bin/spring.bak"), app.path("bin/spring"))
252
- end
253
- end
254
-
255
- test "binstub upgrade with old binstub" do
256
- File.write(app.path("bin/rake"), <<-RUBY.strip_heredoc)
257
- #!/usr/bin/env ruby
258
-
259
- if !Process.respond_to?(:fork) || Gem::Specification.find_all_by_name("spring").empty?
260
- exec "bundle", "exec", "rake", *ARGV
261
- else
262
- ARGV.unshift "rake"
263
- load Gem.bin_path("spring", "spring")
264
- end
265
- RUBY
266
-
267
- File.write(app.path("bin/rails"), <<-RUBY.strip_heredoc)
268
- #!/usr/bin/env ruby
269
-
270
- if !Process.respond_to?(:fork) || Gem::Specification.find_all_by_name("spring").empty?
271
- APP_PATH = File.expand_path('../../config/application', __FILE__)
272
- require_relative '../config/boot'
273
- require 'rails/commands'
274
- else
275
- ARGV.unshift "rails"
276
- load Gem.bin_path("spring", "spring")
277
- end
278
- RUBY
279
-
280
- assert_success "bin/spring binstub --all", stdout: "upgraded"
281
-
282
- expected = <<-RUBY.gsub(/^ /, "")
283
- #!/usr/bin/env ruby
284
- #{Spring::Client::Binstub::LOADER.strip}
285
- require 'bundler/setup'
286
- load Gem.bin_path('rake', 'rake')
287
- RUBY
288
- assert_equal expected, app.path("bin/rake").read
289
-
290
- expected = <<-RUBY.gsub(/^ /, "")
291
- #!/usr/bin/env ruby
292
- #{Spring::Client::Binstub::LOADER.strip}
293
- APP_PATH = File.expand_path('../../config/application', __FILE__)
294
- require_relative '../config/boot'
295
- require 'rails/commands'
296
- RUBY
297
- assert_equal expected, app.path("bin/rails").read
298
- end
299
-
300
- test "binstub upgrade with new binstub variations" do
301
- expected = <<-RUBY.gsub(/^ /, "")
302
- #!/usr/bin/env ruby
303
- #{Spring::Client::Binstub::LOADER.strip}
304
- require 'bundler/setup'
305
- load Gem.bin_path('rake', 'rake')
306
- RUBY
307
-
308
- # older variation with double quotes
309
- File.write(app.path("bin/rake"), <<-RUBY.strip_heredoc)
310
- #!/usr/bin/env ruby
311
- begin
312
- load File.expand_path("../spring", __FILE__)
313
- rescue LoadError
314
- end
315
- require 'bundler/setup'
316
- load Gem.bin_path('rake', 'rake')
317
- RUBY
318
-
319
- assert_success "bin/spring binstub rake", stdout: "bin/rake: upgraded"
320
- assert_equal expected, app.path("bin/rake").read
321
-
322
- # newer variation with single quotes
323
- File.write(app.path("bin/rake"), <<-RUBY.strip_heredoc)
324
- #!/usr/bin/env ruby
325
- begin
326
- load File.expand_path('../spring', __FILE__)
327
- rescue LoadError
328
- end
329
- require 'bundler/setup'
330
- load Gem.bin_path('rake', 'rake')
331
- RUBY
332
-
333
- assert_success "bin/spring binstub rake", stdout: "bin/rake: upgraded"
334
- assert_equal expected, app.path("bin/rake").read
335
-
336
- # newer variation which checks end of exception message
337
- File.write(app.path("bin/rake"), <<-RUBY.strip_heredoc)
338
- #!/usr/bin/env ruby
339
- begin
340
- spring_bin_path = File.expand_path('../spring', __FILE__)
341
- load spring_bin_path
342
- rescue LoadError => e
343
- raise unless e.message.end_with? spring_bin_path, 'spring/binstub'
344
- end
345
- require 'bundler/setup'
346
- load Gem.bin_path('rake', 'rake')
347
- RUBY
348
-
349
- assert_success "bin/spring binstub rake", stdout: "bin/rake: upgraded"
350
- assert_equal expected, app.path("bin/rake").read
351
- end
352
-
353
- test "binstub remove with new binstub variations" do
354
- # older variation with double quotes
355
- File.write(app.path("bin/rake"), <<-RUBY.strip_heredoc)
356
- #!/usr/bin/env ruby
357
- begin
358
- load File.expand_path("../spring", __FILE__)
359
- rescue LoadError
360
- end
361
- require 'bundler/setup'
362
- load Gem.bin_path('rake', 'rake')
363
- RUBY
364
-
365
- # newer variation with single quotes
366
- File.write(app.path("bin/rails"), <<-RUBY.strip_heredoc)
367
- #!/usr/bin/env ruby
368
- begin
369
- load File.expand_path('../spring', __FILE__)
370
- rescue LoadError
371
- end
372
- APP_PATH = File.expand_path('../../config/application', __FILE__)
373
- require_relative '../config/boot'
374
- require 'rails/commands'
375
- RUBY
376
-
377
- assert_success "bin/spring binstub --remove rake", stdout: "bin/rake: spring removed"
378
- assert_success "bin/spring binstub --remove rails", stdout: "bin/rails: spring removed"
379
-
380
- expected = <<-RUBY.strip_heredoc
381
- #!/usr/bin/env ruby
382
- require 'bundler/setup'
383
- load Gem.bin_path('rake', 'rake')
384
- RUBY
385
- assert_equal expected, app.path("bin/rake").read
386
-
387
- expected = <<-RUBY.strip_heredoc
388
- #!/usr/bin/env ruby
389
- APP_PATH = File.expand_path('../../config/application', __FILE__)
390
- require_relative '../config/boot'
391
- require 'rails/commands'
392
- RUBY
393
- assert_equal expected, app.path("bin/rails").read
394
- end
395
-
396
- test "after fork callback" do
397
- File.write(app.spring_config, "Spring.after_fork { puts '!callback!' }")
398
- assert_success "bin/rails runner 'puts 2'", stdout: "!callback!\n2"
399
- end
400
-
401
- test "global config file evaluated" do
402
- File.write("#{app.user_home}/.spring.rb", "Spring.after_fork { puts '!callback!' }")
403
- assert_success "bin/rails runner 'puts 2'", stdout: "!callback!\n2"
404
- end
405
-
406
- test "can define client tasks" do
407
- File.write("#{app.spring_client_config}", <<-RUBY)
408
- Spring::Client::COMMANDS["foo"] = lambda { |args| puts "bar -- \#{args.inspect}" }
409
- RUBY
410
- assert_success "bin/spring foo --baz", stdout: "bar -- [\"foo\", \"--baz\"]\n"
411
- end
412
-
413
- test "missing config/application.rb" do
414
- app.application_config.delete
415
- assert_failure "bin/rake -T", stderr: "unable to find your config/application.rb"
416
- end
417
-
418
- test "piping with boot-level error" do
419
- config = app.application_config.read
420
- File.write(app.application_config, "#{config}\nomg")
421
- assert_success "bin/rake -T | cat"
422
- end
423
-
424
- test "piping" do
425
- assert_success "bin/rake -T | grep db", stdout: "rake db:migrate"
426
- end
427
-
428
- test "status" do
429
- assert_success "bin/spring status", stdout: "Spring is not running"
430
- assert_success "bin/rails runner ''"
431
- assert_success "bin/spring status", stdout: "Spring is running"
432
- end
433
-
434
- test "runner command sets Rails environment from command-line options" do
435
- assert_success "bin/rails runner -e test 'puts Rails.env'", stdout: "test"
436
- assert_success "bin/rails runner --environment=test 'puts Rails.env'", stdout: "test"
437
- end
438
-
439
- test "forcing rails env via environment variable" do
440
- app.env['RAILS_ENV'] = 'test'
441
- assert_success "bin/rake -p 'Rails.env'", stdout: "test"
442
- end
443
-
444
- test "setting env vars with rake" do
445
- File.write(app.path("lib/tasks/env.rake"), <<-RUBY.strip_heredoc)
446
- task :print_rails_env => :environment do
447
- puts Rails.env
448
- end
449
-
450
- task :print_env do
451
- ENV.each { |k, v| puts "\#{k}=\#{v}" }
452
- end
453
-
454
- task(:default).clear.enhance [:print_rails_env]
455
- RUBY
456
-
457
- assert_success "bin/rake RAILS_ENV=test print_rails_env", stdout: "test"
458
- assert_success "bin/rake FOO=bar print_env", stdout: "FOO=bar"
459
- assert_success "bin/rake", stdout: "test"
460
- end
461
-
462
- test "changing the Gemfile works" do
463
- assert_success %(bin/rails runner 'require "sqlite3"')
464
-
465
- File.write(app.gemfile, app.gemfile.read.sub(%{gem 'sqlite3'}, %{# gem 'sqlite3'}))
466
- app.await_reload
467
-
468
- assert_failure %(bin/rails runner 'require "sqlite3"'), stderr: "sqlite3"
469
- end
470
-
471
- test "changing the Gemfile works when spring calls into itself" do
472
- File.write(app.path("script.rb"), <<-RUBY.strip_heredoc)
473
- gemfile = Rails.root.join("Gemfile")
474
- File.write(gemfile, "\#{gemfile.read}gem 'text'\\n")
475
- Bundler.with_clean_env do
476
- system(#{app.env.inspect}, "bundle install")
477
- end
478
- output = `\#{Rails.root.join('bin/rails')} runner 'require "text"; puts "done";'`
479
- exit output.include? "done\n"
480
- RUBY
481
-
482
- assert_success [%(bin/rails runner 'load Rails.root.join("script.rb")'), timeout: 60]
483
- end
484
-
485
- test "changing the environment between runs" do
486
- File.write(app.application_config, "#{app.application_config.read}\nENV['BAR'] = 'bar'")
487
-
488
- app.env["OMG"] = "1"
489
- app.env["FOO"] = "1"
490
- app.env["RUBYOPT"] = "-rubygems"
491
-
492
- assert_success %(bin/rails runner 'p ENV["OMG"]'), stdout: "1"
493
- assert_success %(bin/rails runner 'p ENV["BAR"]'), stdout: "bar"
494
- assert_success %(bin/rails runner 'p ENV.key?("BUNDLE_GEMFILE")'), stdout: "true"
495
- assert_success %(bin/rails runner 'p ENV["RUBYOPT"]'), stdout: "bundler"
496
-
497
- app.env["OMG"] = "2"
498
- app.env.delete "FOO"
499
-
500
- assert_success %(bin/rails runner 'p ENV["OMG"]'), stdout: "2"
501
- assert_success %(bin/rails runner 'p ENV.key?("FOO")'), stdout: "false"
502
- end
503
-
504
- test "Kernel.raise remains private" do
505
- expr = "p Kernel.private_instance_methods.include?(:raise)"
506
- assert_success %(bin/rails runner '#{expr}'), stdout: "true"
507
- end
508
-
509
- test "custom bundle path" do
510
- bundle_path = app.path(".bundle/#{Bundler.ruby_scope}")
511
- bundle_path.dirname.mkpath
512
-
513
- FileUtils.cp_r "#{app.gem_home}/", bundle_path.to_s
514
-
515
- app.run! "bundle install --path .bundle --clean --local"
516
-
517
- assert_speedup do
518
- 2.times { assert_success "bundle exec rails runner ''" }
519
- end
520
- end
521
-
522
- test "booting a foreground server" do
523
- FileUtils.cd(app.root) do
524
- assert !spring_env.server_running?
525
- assert_success "bin/spring server &"
526
-
527
- Timeout.timeout(10) do
528
- sleep 0.1 until spring_env.server_running? && spring_env.socket_path.exist?
529
- end
530
-
531
- assert_success app.spring_test_command
532
- end
533
- end
534
-
535
- test "server boot timeout" do
536
- app.env["SPRING_SERVER_COMMAND"] = "sleep 1"
537
- File.write("#{app.spring_client_config}", %(
538
- Spring::Client::Run.const_set(:BOOT_TIMEOUT, 0.1)
539
- ))
540
-
541
- assert_failure "bin/rails runner ''", stderr: "timed out"
542
- end
543
-
544
- test "no warnings are shown for unsprung commands" do
545
- app.env["DISABLE_SPRING"] = "1"
546
- refute_output_includes "bin/rails runner ''", stderr: "WARN"
547
- end
548
- end
549
- end
550
- end