spring 2.0.2 → 2.1.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -1,229 +0,0 @@
1
- require "spring/env"
2
-
3
- module Spring
4
- module Test
5
- class Application
6
- DEFAULT_TIMEOUT = ENV['CI'] ? 30 : 10
7
-
8
- attr_reader :root, :spring_env
9
-
10
- def initialize(root)
11
- @root = Pathname.new(root)
12
- @spring_env = Spring::Env.new(root: root)
13
- @times = nil
14
- end
15
-
16
- def exists?
17
- root.exist?
18
- end
19
-
20
- def stdout
21
- @stdout ||= IO.pipe
22
- end
23
-
24
- def stderr
25
- @stderr ||= IO.pipe
26
- end
27
-
28
- def log_file
29
- @log_file ||= path("tmp/spring.log").open("w+")
30
- end
31
-
32
- def env
33
- @env ||= {
34
- "GEM_HOME" => gem_home.to_s,
35
- "GEM_PATH" => gem_home.to_s,
36
- "HOME" => user_home.to_s,
37
- "RAILS_ENV" => nil,
38
- "RACK_ENV" => nil,
39
- "SPRING_LOG" => log_file.path
40
- }
41
- end
42
-
43
- def path(addition)
44
- root.join addition
45
- end
46
-
47
- def gemfile
48
- path "Gemfile"
49
- end
50
-
51
- def gem_home
52
- path "../gems/#{RUBY_VERSION}"
53
- end
54
-
55
- def user_home
56
- path "user_home"
57
- end
58
-
59
- def spring
60
- gem_home.join "bin/spring"
61
- end
62
-
63
- def rails_version
64
- @rails_version ||= RailsVersion.new(gemfile.read.match(/gem 'rails', '(.*)'/)[1])
65
- end
66
-
67
- def spring_test_command
68
- "bin/rake test #{test}"
69
- end
70
-
71
- def stop_spring
72
- run "#{spring} stop"
73
- rescue Errno::ENOENT
74
- end
75
-
76
- def test
77
- path "test/controllers/posts_controller_test.rb"
78
- end
79
-
80
- def controller
81
- path "app/controllers/posts_controller.rb"
82
- end
83
-
84
- def application_config
85
- path "config/application.rb"
86
- end
87
-
88
- def spring_config
89
- path "config/spring.rb"
90
- end
91
-
92
- def spring_client_config
93
- path "config/spring_client.rb"
94
- end
95
-
96
- def run(command, opts = {})
97
- start_time = Time.now
98
-
99
- Bundler.with_clean_env do
100
- Process.spawn(
101
- env,
102
- command.to_s,
103
- out: stdout.last,
104
- err: stderr.last,
105
- in: :close,
106
- chdir: root.to_s,
107
- )
108
- end
109
-
110
- _, status = Timeout.timeout(opts.fetch(:timeout, DEFAULT_TIMEOUT)) { Process.wait2 }
111
-
112
- if pid = spring_env.pid
113
- @server_pid = pid
114
- lines = `ps -A -o ppid= -o pid= | egrep '^\\s*#{@server_pid}'`.lines
115
- @application_pids = lines.map { |l| l.split.last.to_i }
116
- end
117
-
118
- output = read_streams
119
- puts dump_streams(command, output) if ENV["SPRING_DEBUG"]
120
-
121
- @times << (Time.now - start_time) if @times
122
-
123
- output.merge(status: status, command: command)
124
- rescue Timeout::Error
125
- raise Timeout::Error, "While running command:\n\n#{dump_streams(command, read_streams)}"
126
- end
127
-
128
- def with_timing
129
- @times = []
130
- yield
131
- ensure
132
- @times = nil
133
- end
134
-
135
- def last_time
136
- @times.last
137
- end
138
-
139
- def first_time
140
- @times.first
141
- end
142
-
143
- def timing_ratio
144
- last_time / first_time
145
- end
146
-
147
- def read_streams
148
- {
149
- stdout: read_stream(stdout.first),
150
- stderr: read_stream(stderr.first),
151
- log: read_stream(log_file)
152
- }
153
- end
154
-
155
- def read_stream(stream)
156
- output = ""
157
- while IO.select([stream], [], [], 0.5) && !stream.eof?
158
- output << stream.readpartial(10240)
159
- end
160
- output
161
- end
162
-
163
- def dump_streams(command, streams)
164
- output = "$ #{command}\n"
165
-
166
- streams.each do |name, stream|
167
- unless stream.chomp.empty?
168
- output << "--- #{name} ---\n"
169
- output << "#{stream.chomp}\n"
170
- end
171
- end
172
-
173
- output << "\n"
174
- output
175
- end
176
-
177
- def debug(artifacts)
178
- artifacts = artifacts.dup
179
- artifacts.delete :status
180
- dump_streams(artifacts.delete(:command), artifacts)
181
- end
182
-
183
- def await_reload
184
- raise "no pid" if @application_pids.nil? || @application_pids.empty?
185
-
186
- Timeout.timeout(DEFAULT_TIMEOUT) do
187
- sleep 0.1 while @application_pids.any? { |p| process_alive?(p) }
188
- end
189
- end
190
-
191
- def run!(command, options = {})
192
- attempts = (options.delete(:retry) || 0) + 1
193
- artifacts = nil
194
-
195
- until attempts == 0 || artifacts && artifacts[:status].success?
196
- artifacts = run(command, options)
197
- attempts -= 1
198
- end
199
-
200
- if artifacts[:status].success?
201
- artifacts
202
- else
203
- raise "command failed\n\n#{debug(artifacts)}"
204
- end
205
- end
206
-
207
- def bundle
208
- # Version restriction is a workaround for https://github.com/bundler/bundler/pull/4981
209
- # The problem breaks our tests on Ruby 2.2
210
- # We can remove once it's fixed
211
- run! "(gem list bundler | grep bundler) || gem install bundler --version '~> 1.12.0'", timeout: nil, retry: 2
212
- run! "bundle check || bundle update --retry=2", timeout: nil
213
- end
214
-
215
- def insert_into_test(code)
216
- File.write(test, test.read.sub(/^\s*get .+$/, code))
217
- end
218
-
219
- private
220
-
221
- def process_alive?(pid)
222
- Process.kill 0, pid
223
- true
224
- rescue Errno::ESRCH
225
- false
226
- end
227
- end
228
- end
229
- end
@@ -1,144 +0,0 @@
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
- @installed = false
12
- end
13
-
14
- def test_root
15
- Pathname.new Spring::Test.root
16
- end
17
-
18
- def root
19
- test_root.join("apps/rails-#{version.major}-#{version.minor}-spring-#{Spring::VERSION}")
20
- end
21
-
22
- def system(command)
23
- if ENV["SPRING_DEBUG"]
24
- puts "$ #{command}\n"
25
- else
26
- command = "(#{command}) > /dev/null"
27
- end
28
-
29
- Kernel.system(command) or raise "command failed: #{command}"
30
- puts if ENV["SPRING_DEBUG"]
31
- end
32
-
33
- def generate
34
- Bundler.with_clean_env { generate_files }
35
- install_spring
36
- generate_scaffold
37
- end
38
-
39
- # Sporadic SSL errors keep causing test failures so there are anti-SSL workarounds here
40
- def generate_files
41
- if RUBY_VERSION == "1.9.3"
42
- system("gem list '^mime-types$' --installed --version '~> 2' || " \
43
- "gem install mime-types --clear-sources --source http://rubygems.org --version '~> 2'")
44
- end
45
-
46
- system("gem list '^rails$' --installed --version '#{version_constraint}' || " \
47
- "gem install rails --clear-sources --source http://rubygems.org --version '#{version_constraint}'")
48
-
49
- @version = RailsVersion.new(`ruby -e 'puts Gem::Specification.find_by_name("rails", "#{version_constraint}").version'`.chomp)
50
-
51
- skips = %w(--skip-bundle --skip-javascript --skip-sprockets --skip-spring)
52
-
53
- system("rails _#{version}_ new #{application.root} #{skips.join(' ')}")
54
- raise "application generation failed" unless application.exists?
55
-
56
- FileUtils.mkdir_p(application.gem_home)
57
- FileUtils.mkdir_p(application.user_home)
58
- FileUtils.rm_rf(application.path("test/performance"))
59
-
60
- append_to_file(application.gemfile, "gem 'spring', '#{Spring::VERSION}'")
61
-
62
- rewrite_file(application.gemfile) do |c|
63
- c.sub!("https://rubygems.org", "http://rubygems.org")
64
- c.gsub!(/(gem '(byebug|web-console|sdoc|jbuilder)')/, "# \\1")
65
- c
66
- end
67
-
68
-
69
- if application.path("bin").exist?
70
- FileUtils.cp_r(application.path("bin"), application.path("bin_original"))
71
- end
72
- end
73
-
74
- def rewrite_file(file)
75
- File.write(file, yield(file.read))
76
- end
77
-
78
- def append_to_file(file, add)
79
- rewrite_file(file) { |c| c << "#{add}\n" }
80
- end
81
-
82
- def generate_if_missing
83
- generate unless application.exists?
84
- end
85
-
86
- def install_spring
87
- return if @installed
88
-
89
- if RUBY_VERSION < "2.2.2"
90
- application.run! "gem install activesupport --version '#{version}'"
91
- end
92
-
93
- build_and_install_gems
94
-
95
- # TO prevent nokogiri install error in application.bundle.
96
- if RUBY_VERSION < "2.1.0"
97
- append_to_file(application.gemfile, "gem 'nokogiri', '~> 1.6.8'")
98
- end
99
-
100
- application.bundle
101
-
102
- FileUtils.rm_rf application.path("bin")
103
-
104
- if application.path("bin_original").exist?
105
- FileUtils.cp_r application.path("bin_original"), application.path("bin")
106
- end
107
-
108
- application.run! "#{application.spring} binstub --all"
109
- @installed = true
110
- end
111
-
112
- def manually_built_gems
113
- %w(spring)
114
- end
115
-
116
- def build_and_install_gems
117
- manually_built_gems.each do |name|
118
- spec = Gem::Specification.find_by_name(name)
119
-
120
- FileUtils.cd(spec.gem_dir) do
121
- FileUtils.rm(Dir.glob("#{name}-*.gem"))
122
- system("gem build #{name}.gemspec 2>&1")
123
- end
124
-
125
- application.run! "gem install #{spec.gem_dir}/#{name}-*.gem --no-ri --no-rdoc", timeout: nil
126
- end
127
- end
128
-
129
- def copy_to(path)
130
- system("rm -rf #{path}")
131
- system("cp -r #{application.root} #{path}")
132
- end
133
-
134
- def generate_scaffold
135
- application.run! "bundle exec rails g scaffold post title:string"
136
- application.run! "bundle exec rake db:migrate db:test:clone"
137
- end
138
-
139
- def gemspec(name)
140
- "#{Gem::Specification.find_by_name(name).gem_dir}/#{name}.gemspec"
141
- end
142
- end
143
- end
144
- end
@@ -1,23 +0,0 @@
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 major
11
- version.segments[0]
12
- end
13
-
14
- def minor
15
- version.segments[1]
16
- end
17
-
18
- def to_s
19
- version.to_s
20
- end
21
- end
22
- end
23
- end
@@ -1,194 +0,0 @@
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
-
166
- test "add symlink" do
167
- File.write("#{dir}/bar", "bar")
168
- File.symlink("#{dir}/bar", "#{dir}/foo")
169
- watcher.add './foo'
170
- assert_equal ["#{dir}/bar"], watcher.files.to_a
171
- end
172
-
173
- test "add dangling symlink" do
174
- File.symlink("#{dir}/bar", "#{dir}/foo")
175
- watcher.add './foo'
176
- assert watcher.files.empty?
177
- end
178
-
179
- test "add directory with dangling symlink" do
180
- subdir = "#{@dir}/subdir"
181
- FileUtils.mkdir(subdir)
182
- File.symlink("dangling", "#{subdir}/foo")
183
-
184
- watcher.add subdir
185
- assert_not_stale
186
-
187
- # Adding a new file should mark as stale despite the dangling symlink.
188
- File.write("#{subdir}/new-file", "new")
189
- watcher.check_stale
190
- assert_stale
191
- end
192
- end
193
- end
194
- end