spring 2.0.0 → 3.0.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -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