spring 1.1.3 → 1.2.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.gitignore +1 -0
- data/CHANGELOG.md +9 -0
- data/CONTRIBUTING.md +5 -0
- data/Gemfile +0 -2
- data/README.md +19 -11
- data/Rakefile +1 -1
- data/lib/spring/application.rb +4 -0
- data/lib/spring/client/binstub.rb +1 -1
- data/lib/spring/commands.rb +11 -2
- data/lib/spring/commands/rails.rb +13 -1
- data/lib/spring/env.rb +2 -2
- data/lib/spring/sid.rb +1 -1
- data/lib/spring/test.rb +15 -0
- data/lib/spring/test/acceptance_test.rb +333 -0
- data/{test/acceptance/helper.rb → lib/spring/test/application.rb} +1 -128
- data/lib/spring/test/application_generator.rb +121 -0
- data/lib/spring/test/rails_version.rb +40 -0
- data/lib/spring/test/watcher_test.rb +167 -0
- data/lib/spring/version.rb +1 -1
- data/lib/spring/watcher.rb +4 -8
- data/lib/spring/watcher/polling.rb +2 -0
- data/test/acceptance_test.rb +4 -0
- data/test/helper.rb +2 -2
- data/test/unit/commands_test.rb +11 -1
- data/test/unit/watcher_test.rb +2 -188
- metadata +10 -7
- data/lib/spring/watcher/listen.rb +0 -52
- data/test/acceptance/app_test.rb +0 -334
@@ -2,43 +2,6 @@ require "spring/env"
|
|
2
2
|
|
3
3
|
module Spring
|
4
4
|
module Test
|
5
|
-
class RailsVersion
|
6
|
-
attr_reader :version
|
7
|
-
|
8
|
-
def initialize(string)
|
9
|
-
@version = Gem::Version.new(string)
|
10
|
-
end
|
11
|
-
|
12
|
-
def rails_3?
|
13
|
-
version < Gem::Version.new("4.0.0")
|
14
|
-
end
|
15
|
-
alias needs_testunit? rails_3?
|
16
|
-
|
17
|
-
def test_command
|
18
|
-
needs_testunit? ? 'bin/testunit' : 'bin/rake test'
|
19
|
-
end
|
20
|
-
|
21
|
-
def controller_tests_dir
|
22
|
-
rails_3? ? 'functional' : 'controllers'
|
23
|
-
end
|
24
|
-
|
25
|
-
def bundles_spring?
|
26
|
-
version.segments.take(2) == [4, 1] || version > Gem::Version.new("4.1")
|
27
|
-
end
|
28
|
-
|
29
|
-
def major
|
30
|
-
version.segments[0]
|
31
|
-
end
|
32
|
-
|
33
|
-
def minor
|
34
|
-
version.segments[1]
|
35
|
-
end
|
36
|
-
|
37
|
-
def to_s
|
38
|
-
version.to_s
|
39
|
-
end
|
40
|
-
end
|
41
|
-
|
42
5
|
class Application
|
43
6
|
DEFAULT_TIMEOUT = ENV['CI'] ? 30 : 10
|
44
7
|
|
@@ -238,7 +201,7 @@ module Spring
|
|
238
201
|
|
239
202
|
def bundle
|
240
203
|
run! "(gem list bundler | grep bundler) || gem install bundler", timeout: nil, retry: 2
|
241
|
-
run! "bundle update --retry=2", timeout: nil
|
204
|
+
run! "bundle check || bundle update --retry=2", timeout: nil
|
242
205
|
end
|
243
206
|
|
244
207
|
private
|
@@ -250,95 +213,5 @@ module Spring
|
|
250
213
|
false
|
251
214
|
end
|
252
215
|
end
|
253
|
-
|
254
|
-
class ApplicationGenerator
|
255
|
-
attr_reader :version_constraint, :version, :application
|
256
|
-
|
257
|
-
def initialize(version_constraint)
|
258
|
-
@version_constraint = version_constraint
|
259
|
-
@version = RailsVersion.new(version_constraint.split(' ').last)
|
260
|
-
@application = Application.new(root)
|
261
|
-
@bundled = false
|
262
|
-
end
|
263
|
-
|
264
|
-
def root
|
265
|
-
"#{TEST_ROOT}/apps/rails-#{version.major}-#{version.minor}-spring-#{Spring::VERSION}"
|
266
|
-
end
|
267
|
-
|
268
|
-
def system(command)
|
269
|
-
if ENV["SPRING_DEBUG"]
|
270
|
-
puts "$ #{command}\n"
|
271
|
-
else
|
272
|
-
command = "(#{command}) > /dev/null"
|
273
|
-
end
|
274
|
-
|
275
|
-
Kernel.system(command) or raise "command failed: #{command}"
|
276
|
-
puts if ENV["SPRING_DEBUG"]
|
277
|
-
end
|
278
|
-
|
279
|
-
# Sporadic SSL errors keep causing test failures so there are anti-SSL workarounds here
|
280
|
-
def generate
|
281
|
-
Bundler.with_clean_env do
|
282
|
-
system("gem list rails --installed --version '#{version_constraint}' || " \
|
283
|
-
"gem install rails --clear-sources --source http://rubygems.org --version '#{version_constraint}'")
|
284
|
-
|
285
|
-
@version = RailsVersion.new(`ruby -e 'puts Gem::Specification.find_by_name("rails", "#{version_constraint}").version'`.chomp)
|
286
|
-
|
287
|
-
skips = %w(--skip-bundle --skip-javascript --skip-sprockets)
|
288
|
-
skips << "--skip-spring" if version.bundles_spring?
|
289
|
-
|
290
|
-
system("rails _#{version}_ new #{application.root} #{skips.join(' ')}")
|
291
|
-
raise "application generation failed" unless application.exists?
|
292
|
-
|
293
|
-
FileUtils.mkdir_p(application.gem_home)
|
294
|
-
FileUtils.mkdir_p(application.user_home)
|
295
|
-
FileUtils.rm_rf(application.path("test/performance"))
|
296
|
-
|
297
|
-
File.write(application.gemfile, "#{application.gemfile.read}gem 'spring', '#{Spring::VERSION}'\n")
|
298
|
-
|
299
|
-
if version.needs_testunit?
|
300
|
-
File.write(application.gemfile, "#{application.gemfile.read}gem 'spring-commands-testunit'\n")
|
301
|
-
end
|
302
|
-
|
303
|
-
File.write(application.gemfile, application.gemfile.read.sub("https://rubygems.org", "http://rubygems.org"))
|
304
|
-
|
305
|
-
if application.path("bin").exist?
|
306
|
-
FileUtils.cp_r(application.path("bin"), application.path("bin_original"))
|
307
|
-
end
|
308
|
-
end
|
309
|
-
|
310
|
-
install_spring
|
311
|
-
|
312
|
-
application.run! "bundle exec rails g scaffold post title:string"
|
313
|
-
application.run! "bundle exec rake db:migrate db:test:clone"
|
314
|
-
end
|
315
|
-
|
316
|
-
def generate_if_missing
|
317
|
-
generate unless application.exists?
|
318
|
-
end
|
319
|
-
|
320
|
-
def install_spring
|
321
|
-
return if @installed
|
322
|
-
|
323
|
-
system("gem build spring.gemspec 2>&1")
|
324
|
-
application.run! "gem install ../../../spring-#{Spring::VERSION}.gem", timeout: nil
|
325
|
-
|
326
|
-
application.bundle
|
327
|
-
|
328
|
-
FileUtils.rm_rf application.path("bin")
|
329
|
-
|
330
|
-
if application.path("bin_original").exist?
|
331
|
-
FileUtils.cp_r application.path("bin_original"), application.path("bin")
|
332
|
-
end
|
333
|
-
|
334
|
-
application.run! "#{application.spring} binstub --all"
|
335
|
-
@installed = true
|
336
|
-
end
|
337
|
-
|
338
|
-
def copy_to(path)
|
339
|
-
system("rm -rf #{path}")
|
340
|
-
system("cp -r #{application.root} #{path}")
|
341
|
-
end
|
342
|
-
end
|
343
216
|
end
|
344
217
|
end
|
@@ -0,0 +1,121 @@
|
|
1
|
+
module Spring
|
2
|
+
module Test
|
3
|
+
class ApplicationGenerator
|
4
|
+
attr_reader :version_constraint, :version, :application
|
5
|
+
|
6
|
+
def initialize(version_constraint)
|
7
|
+
@version_constraint = version_constraint
|
8
|
+
@version = RailsVersion.new(version_constraint.split(' ').last)
|
9
|
+
@application = Application.new(root)
|
10
|
+
@bundled = false
|
11
|
+
end
|
12
|
+
|
13
|
+
def test_root
|
14
|
+
Pathname.new Spring::Test.root
|
15
|
+
end
|
16
|
+
|
17
|
+
def root
|
18
|
+
test_root.join("apps/rails-#{version.major}-#{version.minor}-spring-#{Spring::VERSION}")
|
19
|
+
end
|
20
|
+
|
21
|
+
def system(command)
|
22
|
+
if ENV["SPRING_DEBUG"]
|
23
|
+
puts "$ #{command}\n"
|
24
|
+
else
|
25
|
+
command = "(#{command}) > /dev/null"
|
26
|
+
end
|
27
|
+
|
28
|
+
Kernel.system(command) or raise "command failed: #{command}"
|
29
|
+
puts if ENV["SPRING_DEBUG"]
|
30
|
+
end
|
31
|
+
|
32
|
+
def generate
|
33
|
+
Bundler.with_clean_env { generate_files }
|
34
|
+
install_spring
|
35
|
+
generate_scaffold
|
36
|
+
end
|
37
|
+
|
38
|
+
# Sporadic SSL errors keep causing test failures so there are anti-SSL workarounds here
|
39
|
+
def generate_files
|
40
|
+
system("gem list rails --installed --version '#{version_constraint}' || " \
|
41
|
+
"gem install rails --clear-sources --source http://rubygems.org --version '#{version_constraint}'")
|
42
|
+
|
43
|
+
@version = RailsVersion.new(`ruby -e 'puts Gem::Specification.find_by_name("rails", "#{version_constraint}").version'`.chomp)
|
44
|
+
|
45
|
+
skips = %w(--skip-bundle --skip-javascript --skip-sprockets)
|
46
|
+
skips << "--skip-spring" if version.bundles_spring?
|
47
|
+
|
48
|
+
system("rails _#{version}_ new #{application.root} #{skips.join(' ')}")
|
49
|
+
raise "application generation failed" unless application.exists?
|
50
|
+
|
51
|
+
FileUtils.mkdir_p(application.gem_home)
|
52
|
+
FileUtils.mkdir_p(application.user_home)
|
53
|
+
FileUtils.rm_rf(application.path("test/performance"))
|
54
|
+
|
55
|
+
File.write(application.gemfile, "#{application.gemfile.read}gem 'spring', '#{Spring::VERSION}'\n")
|
56
|
+
|
57
|
+
if version.needs_testunit?
|
58
|
+
File.write(application.gemfile, "#{application.gemfile.read}gem 'spring-commands-testunit'\n")
|
59
|
+
end
|
60
|
+
|
61
|
+
File.write(application.gemfile, application.gemfile.read.sub("https://rubygems.org", "http://rubygems.org"))
|
62
|
+
|
63
|
+
if application.path("bin").exist?
|
64
|
+
FileUtils.cp_r(application.path("bin"), application.path("bin_original"))
|
65
|
+
end
|
66
|
+
end
|
67
|
+
|
68
|
+
def generate_if_missing
|
69
|
+
generate unless application.exists?
|
70
|
+
end
|
71
|
+
|
72
|
+
def install_spring
|
73
|
+
return if @installed
|
74
|
+
|
75
|
+
build_and_install_gems
|
76
|
+
|
77
|
+
application.bundle
|
78
|
+
|
79
|
+
FileUtils.rm_rf application.path("bin")
|
80
|
+
|
81
|
+
if application.path("bin_original").exist?
|
82
|
+
FileUtils.cp_r application.path("bin_original"), application.path("bin")
|
83
|
+
end
|
84
|
+
|
85
|
+
application.run! "#{application.spring} binstub --all"
|
86
|
+
@installed = true
|
87
|
+
end
|
88
|
+
|
89
|
+
def manually_built_gems
|
90
|
+
%w(spring)
|
91
|
+
end
|
92
|
+
|
93
|
+
def build_and_install_gems
|
94
|
+
manually_built_gems.each do |name|
|
95
|
+
spec = Gem::Specification.find_by_name(name)
|
96
|
+
|
97
|
+
FileUtils.cd(spec.gem_dir) do
|
98
|
+
FileUtils.rm(Dir.glob("#{name}-*.gem"))
|
99
|
+
system("gem build #{name}.gemspec 2>&1")
|
100
|
+
end
|
101
|
+
|
102
|
+
application.run! "gem install #{spec.gem_dir}/#{name}-*.gem", timeout: nil
|
103
|
+
end
|
104
|
+
end
|
105
|
+
|
106
|
+
def copy_to(path)
|
107
|
+
system("rm -rf #{path}")
|
108
|
+
system("cp -r #{application.root} #{path}")
|
109
|
+
end
|
110
|
+
|
111
|
+
def generate_scaffold
|
112
|
+
application.run! "bundle exec rails g scaffold post title:string"
|
113
|
+
application.run! "bundle exec rake db:migrate db:test:clone"
|
114
|
+
end
|
115
|
+
|
116
|
+
def gemspec(name)
|
117
|
+
"#{Gem::Specification.find_by_name(name).gem_dir}/#{name}.gemspec"
|
118
|
+
end
|
119
|
+
end
|
120
|
+
end
|
121
|
+
end
|
@@ -0,0 +1,40 @@
|
|
1
|
+
module Spring
|
2
|
+
module Test
|
3
|
+
class RailsVersion
|
4
|
+
attr_reader :version
|
5
|
+
|
6
|
+
def initialize(string)
|
7
|
+
@version = Gem::Version.new(string)
|
8
|
+
end
|
9
|
+
|
10
|
+
def rails_3?
|
11
|
+
version < Gem::Version.new("4.0.0")
|
12
|
+
end
|
13
|
+
alias needs_testunit? rails_3?
|
14
|
+
|
15
|
+
def test_command
|
16
|
+
needs_testunit? ? 'bin/testunit' : 'bin/rake test'
|
17
|
+
end
|
18
|
+
|
19
|
+
def controller_tests_dir
|
20
|
+
rails_3? ? 'functional' : 'controllers'
|
21
|
+
end
|
22
|
+
|
23
|
+
def bundles_spring?
|
24
|
+
version.segments.take(2) == [4, 1] || version > Gem::Version.new("4.1")
|
25
|
+
end
|
26
|
+
|
27
|
+
def major
|
28
|
+
version.segments[0]
|
29
|
+
end
|
30
|
+
|
31
|
+
def minor
|
32
|
+
version.segments[1]
|
33
|
+
end
|
34
|
+
|
35
|
+
def to_s
|
36
|
+
version.to_s
|
37
|
+
end
|
38
|
+
end
|
39
|
+
end
|
40
|
+
end
|
@@ -0,0 +1,167 @@
|
|
1
|
+
require "tmpdir"
|
2
|
+
require "fileutils"
|
3
|
+
require "timeout"
|
4
|
+
require "active_support/core_ext/numeric/time"
|
5
|
+
|
6
|
+
module Spring
|
7
|
+
module Test
|
8
|
+
class WatcherTest < ActiveSupport::TestCase
|
9
|
+
runnables.delete self # prevent Minitest running this class
|
10
|
+
|
11
|
+
LATENCY = 0.001
|
12
|
+
TIMEOUT = 1
|
13
|
+
|
14
|
+
attr_accessor :dir
|
15
|
+
|
16
|
+
def watcher_class
|
17
|
+
raise NotImplementedError
|
18
|
+
end
|
19
|
+
|
20
|
+
def watcher
|
21
|
+
@watcher ||= watcher_class.new(dir, LATENCY)
|
22
|
+
end
|
23
|
+
|
24
|
+
def setup
|
25
|
+
@dir = File.realpath(Dir.mktmpdir)
|
26
|
+
end
|
27
|
+
|
28
|
+
def teardown
|
29
|
+
FileUtils.remove_entry_secure @dir
|
30
|
+
watcher.stop
|
31
|
+
end
|
32
|
+
|
33
|
+
def touch(file, mtime = nil)
|
34
|
+
options = {}
|
35
|
+
options[:mtime] = mtime if mtime
|
36
|
+
FileUtils.touch(file, options)
|
37
|
+
end
|
38
|
+
|
39
|
+
def assert_stale
|
40
|
+
timeout = Time.now + TIMEOUT
|
41
|
+
sleep LATENCY until watcher.stale? || Time.now > timeout
|
42
|
+
assert watcher.stale?
|
43
|
+
end
|
44
|
+
|
45
|
+
def assert_not_stale
|
46
|
+
sleep LATENCY * 10
|
47
|
+
assert !watcher.stale?
|
48
|
+
end
|
49
|
+
|
50
|
+
test "starting with no file" do
|
51
|
+
file = "#{@dir}/omg"
|
52
|
+
touch file, Time.now - 2.seconds
|
53
|
+
|
54
|
+
watcher.start
|
55
|
+
watcher.add file
|
56
|
+
|
57
|
+
assert_not_stale
|
58
|
+
touch file, Time.now
|
59
|
+
assert_stale
|
60
|
+
end
|
61
|
+
|
62
|
+
test "is stale when a watched file is updated" do
|
63
|
+
file = "#{@dir}/omg"
|
64
|
+
touch file, Time.now - 2.seconds
|
65
|
+
|
66
|
+
watcher.add file
|
67
|
+
watcher.start
|
68
|
+
|
69
|
+
assert_not_stale
|
70
|
+
touch file, Time.now
|
71
|
+
assert_stale
|
72
|
+
end
|
73
|
+
|
74
|
+
test "is stale when removing files" do
|
75
|
+
file = "#{@dir}/omg"
|
76
|
+
touch file, Time.now
|
77
|
+
|
78
|
+
watcher.add file
|
79
|
+
watcher.start
|
80
|
+
|
81
|
+
assert_not_stale
|
82
|
+
FileUtils.rm(file)
|
83
|
+
assert_stale
|
84
|
+
end
|
85
|
+
|
86
|
+
test "is stale when files are added to a watched directory" do
|
87
|
+
subdir = "#{@dir}/subdir"
|
88
|
+
FileUtils.mkdir(subdir)
|
89
|
+
|
90
|
+
watcher.add subdir
|
91
|
+
watcher.start
|
92
|
+
|
93
|
+
assert_not_stale
|
94
|
+
touch "#{subdir}/foo", Time.now - 1.minute
|
95
|
+
assert_stale
|
96
|
+
end
|
97
|
+
|
98
|
+
test "is stale when a file is changed in a watched directory" do
|
99
|
+
subdir = "#{@dir}/subdir"
|
100
|
+
FileUtils.mkdir(subdir)
|
101
|
+
touch "#{subdir}/foo", Time.now - 1.minute
|
102
|
+
|
103
|
+
watcher.add subdir
|
104
|
+
watcher.start
|
105
|
+
|
106
|
+
assert_not_stale
|
107
|
+
touch "#{subdir}/foo", Time.now
|
108
|
+
assert_stale
|
109
|
+
end
|
110
|
+
|
111
|
+
test "adding doesn't wipe stale state" do
|
112
|
+
file = "#{@dir}/omg"
|
113
|
+
file2 = "#{@dir}/foo"
|
114
|
+
touch file, Time.now - 2.seconds
|
115
|
+
touch file2, Time.now - 2.seconds
|
116
|
+
|
117
|
+
watcher.add file
|
118
|
+
watcher.start
|
119
|
+
|
120
|
+
assert_not_stale
|
121
|
+
|
122
|
+
touch file, Time.now
|
123
|
+
watcher.add file2
|
124
|
+
|
125
|
+
assert_stale
|
126
|
+
end
|
127
|
+
|
128
|
+
test "on stale" do
|
129
|
+
file = "#{@dir}/omg"
|
130
|
+
touch file, Time.now - 2.seconds
|
131
|
+
|
132
|
+
stale = false
|
133
|
+
watcher.on_stale { stale = true }
|
134
|
+
|
135
|
+
watcher.add file
|
136
|
+
watcher.start
|
137
|
+
|
138
|
+
touch file, Time.now
|
139
|
+
|
140
|
+
Timeout.timeout(1) { sleep 0.01 until stale }
|
141
|
+
assert stale
|
142
|
+
|
143
|
+
# Check that we only get notified once
|
144
|
+
stale = false
|
145
|
+
sleep LATENCY * 3
|
146
|
+
assert !stale
|
147
|
+
end
|
148
|
+
|
149
|
+
test "add relative path" do
|
150
|
+
File.write("#{dir}/foo", "foo")
|
151
|
+
watcher.add "foo"
|
152
|
+
assert_equal ["#{dir}/foo"], watcher.files.to_a
|
153
|
+
end
|
154
|
+
|
155
|
+
test "add dot relative path" do
|
156
|
+
File.write("#{dir}/foo", "foo")
|
157
|
+
watcher.add "./foo"
|
158
|
+
assert_equal ["#{dir}/foo"], watcher.files.to_a
|
159
|
+
end
|
160
|
+
|
161
|
+
test "add non existent file" do
|
162
|
+
watcher.add './foobar'
|
163
|
+
assert watcher.files.empty?
|
164
|
+
end
|
165
|
+
end
|
166
|
+
end
|
167
|
+
end
|