spring 2.0.2 → 3.1.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -1,558 +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 gets reloaded even with abort_on_exception=true" do
176
- assert_success app.spring_test_command
177
- File.write(app.path("config/initializers/thread_config.rb"), "Thread.abort_on_exception = true")
178
-
179
- app.await_reload
180
- assert_success app.spring_test_command
181
- end
182
-
183
- test "app recovers when a boot-level error is introduced" do
184
- config = app.application_config.read
185
-
186
- assert_success app.spring_test_command
187
-
188
- File.write(app.application_config, "#{config}\nomg")
189
- app.await_reload
190
-
191
- assert_failure app.spring_test_command
192
-
193
- File.write(app.application_config, config)
194
- assert_success app.spring_test_command
195
- end
196
-
197
- test "stop command kills server" do
198
- app.run app.spring_test_command
199
- assert spring_env.server_running?, "The server should be running but it isn't"
200
-
201
- assert_success "bin/spring stop"
202
- assert !spring_env.server_running?, "The server should not be running but it is"
203
- end
204
-
205
- test "custom commands" do
206
- # Start spring before setting up the command, to test that it gracefully upgrades itself
207
- assert_success "bin/rails runner ''"
208
-
209
- File.write(app.spring_config, <<-RUBY.strip_heredoc)
210
- class CustomCommand
211
- def call
212
- puts "omg"
213
- end
214
-
215
- def exec_name
216
- "rake"
217
- end
218
- end
219
-
220
- Spring.register_command "custom", CustomCommand.new
221
- RUBY
222
-
223
- assert_success "bin/spring custom", stdout: "omg"
224
-
225
- assert_success "bin/spring binstub custom"
226
- assert_success "bin/custom", stdout: "omg"
227
-
228
- app.env["DISABLE_SPRING"] = "1"
229
- assert_success %{bin/custom -e 'puts "foo"'}, stdout: "foo"
230
- end
231
-
232
- test "binstub" do
233
- assert_success "bin/rails server --help", stdout: "Usage: rails server" # rails command fallback
234
-
235
- assert_success "#{app.spring} binstub rake", stdout: "bin/rake: spring already present"
236
-
237
- assert_success "#{app.spring} binstub --remove rake", stdout: "bin/rake: spring removed"
238
- assert !app.path("bin/rake").read.include?(Spring::Client::Binstub::LOADER)
239
- assert_success "bin/rake -T", stdout: "rake db:migrate"
240
- end
241
-
242
- test "binstub remove all" do
243
- assert_success "bin/spring binstub --remove --all"
244
- refute File.exist?(app.path("bin/spring"))
245
- end
246
-
247
- test "binstub when spring gem is missing" do
248
- without_gem "spring-#{Spring::VERSION}" do
249
- File.write(app.gemfile, app.gemfile.read.gsub(/gem 'spring.*/, ""))
250
- assert_success "bin/rake -T", stdout: "rake db:migrate"
251
- end
252
- end
253
-
254
- test "binstub when spring binary is missing" do
255
- begin
256
- File.rename(app.path("bin/spring"), app.path("bin/spring.bak"))
257
- assert_success "bin/rake -T", stdout: "rake db:migrate"
258
- ensure
259
- File.rename(app.path("bin/spring.bak"), app.path("bin/spring"))
260
- end
261
- end
262
-
263
- test "binstub upgrade with old binstub" do
264
- File.write(app.path("bin/rake"), <<-RUBY.strip_heredoc)
265
- #!/usr/bin/env ruby
266
-
267
- if !Process.respond_to?(:fork) || Gem::Specification.find_all_by_name("spring").empty?
268
- exec "bundle", "exec", "rake", *ARGV
269
- else
270
- ARGV.unshift "rake"
271
- load Gem.bin_path("spring", "spring")
272
- end
273
- RUBY
274
-
275
- File.write(app.path("bin/rails"), <<-RUBY.strip_heredoc)
276
- #!/usr/bin/env ruby
277
-
278
- if !Process.respond_to?(:fork) || Gem::Specification.find_all_by_name("spring").empty?
279
- APP_PATH = File.expand_path('../../config/application', __FILE__)
280
- require_relative '../config/boot'
281
- require 'rails/commands'
282
- else
283
- ARGV.unshift "rails"
284
- load Gem.bin_path("spring", "spring")
285
- end
286
- RUBY
287
-
288
- assert_success "bin/spring binstub --all", stdout: "upgraded"
289
-
290
- expected = <<-RUBY.gsub(/^ /, "")
291
- #!/usr/bin/env ruby
292
- #{Spring::Client::Binstub::LOADER.strip}
293
- require 'bundler/setup'
294
- load Gem.bin_path('rake', 'rake')
295
- RUBY
296
- assert_equal expected, app.path("bin/rake").read
297
-
298
- expected = <<-RUBY.gsub(/^ /, "")
299
- #!/usr/bin/env ruby
300
- #{Spring::Client::Binstub::LOADER.strip}
301
- APP_PATH = File.expand_path('../../config/application', __FILE__)
302
- require_relative '../config/boot'
303
- require 'rails/commands'
304
- RUBY
305
- assert_equal expected, app.path("bin/rails").read
306
- end
307
-
308
- test "binstub upgrade with new binstub variations" do
309
- expected = <<-RUBY.gsub(/^ /, "")
310
- #!/usr/bin/env ruby
311
- #{Spring::Client::Binstub::LOADER.strip}
312
- require 'bundler/setup'
313
- load Gem.bin_path('rake', 'rake')
314
- RUBY
315
-
316
- # older variation with double quotes
317
- File.write(app.path("bin/rake"), <<-RUBY.strip_heredoc)
318
- #!/usr/bin/env ruby
319
- begin
320
- load File.expand_path("../spring", __FILE__)
321
- rescue LoadError
322
- end
323
- require 'bundler/setup'
324
- load Gem.bin_path('rake', 'rake')
325
- RUBY
326
-
327
- assert_success "bin/spring binstub rake", stdout: "bin/rake: upgraded"
328
- assert_equal expected, app.path("bin/rake").read
329
-
330
- # newer variation with single quotes
331
- File.write(app.path("bin/rake"), <<-RUBY.strip_heredoc)
332
- #!/usr/bin/env ruby
333
- begin
334
- load File.expand_path('../spring', __FILE__)
335
- rescue LoadError
336
- end
337
- require 'bundler/setup'
338
- load Gem.bin_path('rake', 'rake')
339
- RUBY
340
-
341
- assert_success "bin/spring binstub rake", stdout: "bin/rake: upgraded"
342
- assert_equal expected, app.path("bin/rake").read
343
-
344
- # newer variation which checks end of exception message
345
- File.write(app.path("bin/rake"), <<-RUBY.strip_heredoc)
346
- #!/usr/bin/env ruby
347
- begin
348
- spring_bin_path = File.expand_path('../spring', __FILE__)
349
- load spring_bin_path
350
- rescue LoadError => e
351
- raise unless e.message.end_with? spring_bin_path, 'spring/binstub'
352
- end
353
- require 'bundler/setup'
354
- load Gem.bin_path('rake', 'rake')
355
- RUBY
356
-
357
- assert_success "bin/spring binstub rake", stdout: "bin/rake: upgraded"
358
- assert_equal expected, app.path("bin/rake").read
359
- end
360
-
361
- test "binstub remove with new binstub variations" do
362
- # older variation with double quotes
363
- File.write(app.path("bin/rake"), <<-RUBY.strip_heredoc)
364
- #!/usr/bin/env ruby
365
- begin
366
- load File.expand_path("../spring", __FILE__)
367
- rescue LoadError
368
- end
369
- require 'bundler/setup'
370
- load Gem.bin_path('rake', 'rake')
371
- RUBY
372
-
373
- # newer variation with single quotes
374
- File.write(app.path("bin/rails"), <<-RUBY.strip_heredoc)
375
- #!/usr/bin/env ruby
376
- begin
377
- load File.expand_path('../spring', __FILE__)
378
- rescue LoadError
379
- end
380
- APP_PATH = File.expand_path('../../config/application', __FILE__)
381
- require_relative '../config/boot'
382
- require 'rails/commands'
383
- RUBY
384
-
385
- assert_success "bin/spring binstub --remove rake", stdout: "bin/rake: spring removed"
386
- assert_success "bin/spring binstub --remove rails", stdout: "bin/rails: spring removed"
387
-
388
- expected = <<-RUBY.strip_heredoc
389
- #!/usr/bin/env ruby
390
- require 'bundler/setup'
391
- load Gem.bin_path('rake', 'rake')
392
- RUBY
393
- assert_equal expected, app.path("bin/rake").read
394
-
395
- expected = <<-RUBY.strip_heredoc
396
- #!/usr/bin/env ruby
397
- APP_PATH = File.expand_path('../../config/application', __FILE__)
398
- require_relative '../config/boot'
399
- require 'rails/commands'
400
- RUBY
401
- assert_equal expected, app.path("bin/rails").read
402
- end
403
-
404
- test "after fork callback" do
405
- File.write(app.spring_config, "Spring.after_fork { puts '!callback!' }")
406
- assert_success "bin/rails runner 'puts 2'", stdout: "!callback!\n2"
407
- end
408
-
409
- test "global config file evaluated" do
410
- File.write("#{app.user_home}/.spring.rb", "Spring.after_fork { puts '!callback!' }")
411
- assert_success "bin/rails runner 'puts 2'", stdout: "!callback!\n2"
412
- end
413
-
414
- test "can define client tasks" do
415
- File.write("#{app.spring_client_config}", <<-RUBY)
416
- Spring::Client::COMMANDS["foo"] = lambda { |args| puts "bar -- \#{args.inspect}" }
417
- RUBY
418
- assert_success "bin/spring foo --baz", stdout: "bar -- [\"foo\", \"--baz\"]\n"
419
- end
420
-
421
- test "missing config/application.rb" do
422
- app.application_config.delete
423
- assert_failure "bin/rake -T", stderr: "unable to find your config/application.rb"
424
- end
425
-
426
- test "piping with boot-level error" do
427
- config = app.application_config.read
428
- File.write(app.application_config, "#{config}\nomg")
429
- assert_success "bin/rake -T | cat"
430
- end
431
-
432
- test "piping" do
433
- assert_success "bin/rake -T | grep db", stdout: "rake db:migrate"
434
- end
435
-
436
- test "status" do
437
- assert_success "bin/spring status", stdout: "Spring is not running"
438
- assert_success "bin/rails runner ''"
439
- assert_success "bin/spring status", stdout: "Spring is running"
440
- end
441
-
442
- test "runner command sets Rails environment from command-line options" do
443
- assert_success "bin/rails runner -e test 'puts Rails.env'", stdout: "test"
444
- assert_success "bin/rails runner --environment=test 'puts Rails.env'", stdout: "test"
445
- end
446
-
447
- test "forcing rails env via environment variable" do
448
- app.env['RAILS_ENV'] = 'test'
449
- assert_success "bin/rake -p 'Rails.env'", stdout: "test"
450
- end
451
-
452
- test "setting env vars with rake" do
453
- File.write(app.path("lib/tasks/env.rake"), <<-RUBY.strip_heredoc)
454
- task :print_rails_env => :environment do
455
- puts Rails.env
456
- end
457
-
458
- task :print_env do
459
- ENV.each { |k, v| puts "\#{k}=\#{v}" }
460
- end
461
-
462
- task(:default).clear.enhance [:print_rails_env]
463
- RUBY
464
-
465
- assert_success "bin/rake RAILS_ENV=test print_rails_env", stdout: "test"
466
- assert_success "bin/rake FOO=bar print_env", stdout: "FOO=bar"
467
- assert_success "bin/rake", stdout: "test"
468
- end
469
-
470
- test "changing the Gemfile works" do
471
- assert_success %(bin/rails runner 'require "sqlite3"')
472
-
473
- File.write(app.gemfile, app.gemfile.read.sub(%{gem 'sqlite3'}, %{# gem 'sqlite3'}))
474
- app.await_reload
475
-
476
- assert_failure %(bin/rails runner 'require "sqlite3"'), stderr: "sqlite3"
477
- end
478
-
479
- test "changing the Gemfile works when spring calls into itself" do
480
- File.write(app.path("script.rb"), <<-RUBY.strip_heredoc)
481
- gemfile = Rails.root.join("Gemfile")
482
- File.write(gemfile, "\#{gemfile.read}gem 'text'\\n")
483
- Bundler.with_clean_env do
484
- system(#{app.env.inspect}, "bundle install")
485
- end
486
- output = `\#{Rails.root.join('bin/rails')} runner 'require "text"; puts "done";'`
487
- exit output.include? "done\n"
488
- RUBY
489
-
490
- assert_success [%(bin/rails runner 'load Rails.root.join("script.rb")'), timeout: 60]
491
- end
492
-
493
- test "changing the environment between runs" do
494
- File.write(app.application_config, "#{app.application_config.read}\nENV['BAR'] = 'bar'")
495
-
496
- app.env["OMG"] = "1"
497
- app.env["FOO"] = "1"
498
- app.env["RUBYOPT"] = "-rubygems"
499
-
500
- assert_success %(bin/rails runner 'p ENV["OMG"]'), stdout: "1"
501
- assert_success %(bin/rails runner 'p ENV["BAR"]'), stdout: "bar"
502
- assert_success %(bin/rails runner 'p ENV.key?("BUNDLE_GEMFILE")'), stdout: "true"
503
- assert_success %(bin/rails runner 'p ENV["RUBYOPT"]'), stdout: "bundler"
504
-
505
- app.env["OMG"] = "2"
506
- app.env.delete "FOO"
507
-
508
- assert_success %(bin/rails runner 'p ENV["OMG"]'), stdout: "2"
509
- assert_success %(bin/rails runner 'p ENV.key?("FOO")'), stdout: "false"
510
- end
511
-
512
- test "Kernel.raise remains private" do
513
- expr = "p Kernel.private_instance_methods.include?(:raise)"
514
- assert_success %(bin/rails runner '#{expr}'), stdout: "true"
515
- end
516
-
517
- test "custom bundle path" do
518
- bundle_path = app.path(".bundle/#{Bundler.ruby_scope}")
519
- bundle_path.dirname.mkpath
520
-
521
- FileUtils.cp_r "#{app.gem_home}/", bundle_path.to_s
522
-
523
- app.run! "bundle install --path .bundle --clean --local"
524
-
525
- assert_speedup do
526
- 2.times { assert_success "bundle exec rails runner ''" }
527
- end
528
- end
529
-
530
- test "booting a foreground server" do
531
- FileUtils.cd(app.root) do
532
- assert !spring_env.server_running?
533
- assert_success "bin/spring server &"
534
-
535
- Timeout.timeout(10) do
536
- sleep 0.1 until spring_env.server_running? && spring_env.socket_path.exist?
537
- end
538
-
539
- assert_success app.spring_test_command
540
- end
541
- end
542
-
543
- test "server boot timeout" do
544
- app.env["SPRING_SERVER_COMMAND"] = "sleep 1"
545
- File.write("#{app.spring_client_config}", %(
546
- Spring::Client::Run.const_set(:BOOT_TIMEOUT, 0.1)
547
- ))
548
-
549
- assert_failure "bin/rails runner ''", stderr: "timed out"
550
- end
551
-
552
- test "no warnings are shown for unsprung commands" do
553
- app.env["DISABLE_SPRING"] = "1"
554
- refute_output_includes "bin/rails runner ''", stderr: "WARN"
555
- end
556
- end
557
- end
558
- end