Class: Spring::Test::Application

Inherits:
Object
  • Object
show all
Defined in:
lib/spring/test/application.rb

Constant Summary collapse

DEFAULT_TIMEOUT =
ENV['CI'] ? 30 : 10

Instance Attribute Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(root) ⇒ Application

Returns a new instance of Application.



10
11
12
13
# File 'lib/spring/test/application.rb', line 10

def initialize(root)
  @root       = Pathname.new(root)
  @spring_env = Spring::Env.new(root: root)
end

Instance Attribute Details

#rootObject (readonly)

Returns the value of attribute root.



8
9
10
# File 'lib/spring/test/application.rb', line 8

def root
  @root
end

#spring_envObject (readonly)

Returns the value of attribute spring_env.



8
9
10
# File 'lib/spring/test/application.rb', line 8

def spring_env
  @spring_env
end

Instance Method Details

#application_configObject



83
84
85
# File 'lib/spring/test/application.rb', line 83

def application_config
  path "config/application.rb"
end

#await_reloadObject



182
183
184
185
186
187
188
# File 'lib/spring/test/application.rb', line 182

def await_reload
  raise "no pid" if @application_pids.nil? || @application_pids.empty?

  Timeout.timeout(DEFAULT_TIMEOUT) do
    sleep 0.1 while @application_pids.any? { |p| process_alive?(p) }
  end
end

#bundleObject



206
207
208
209
# File 'lib/spring/test/application.rb', line 206

def bundle
  run! "(gem list bundler | grep bundler) || gem install bundler", timeout: nil, retry: 2
  run! "bundle check || bundle update --retry=2", timeout: nil
end

#controllerObject



79
80
81
# File 'lib/spring/test/application.rb', line 79

def controller
  path "app/controllers/posts_controller.rb"
end

#debug(artifacts) ⇒ Object



176
177
178
179
180
# File 'lib/spring/test/application.rb', line 176

def debug(artifacts)
  artifacts = artifacts.dup
  artifacts.delete :status
  dump_streams(artifacts.delete(:command), artifacts)
end

#dump_streams(command, streams) ⇒ Object



162
163
164
165
166
167
168
169
170
171
172
173
174
# File 'lib/spring/test/application.rb', line 162

def dump_streams(command, streams)
  output = "$ #{command}\n"

  streams.each do |name, stream|
    unless stream.chomp.empty?
      output << "--- #{name} ---\n"
      output << "#{stream.chomp}\n"
    end
  end

  output << "\n"
  output
end

#envObject



31
32
33
34
35
36
37
38
39
40
# File 'lib/spring/test/application.rb', line 31

def env
  @env ||= {
    "GEM_HOME"   => gem_home.to_s,
    "GEM_PATH"   => gem_home.to_s,
    "HOME"       => user_home.to_s,
    "RAILS_ENV"  => nil,
    "RACK_ENV"   => nil,
    "SPRING_LOG" => log_file.path
  }
end

#exists?Boolean

Returns:

  • (Boolean)


15
16
17
# File 'lib/spring/test/application.rb', line 15

def exists?
  root.exist?
end

#first_timeObject



138
139
140
# File 'lib/spring/test/application.rb', line 138

def first_time
  @times.first
end

#gem_homeObject



50
51
52
# File 'lib/spring/test/application.rb', line 50

def gem_home
  path "../gems/#{RUBY_VERSION}"
end

#gemfileObject



46
47
48
# File 'lib/spring/test/application.rb', line 46

def gemfile
  path "Gemfile"
end

#last_timeObject



134
135
136
# File 'lib/spring/test/application.rb', line 134

def last_time
  @times.last
end

#log_fileObject



27
28
29
# File 'lib/spring/test/application.rb', line 27

def log_file
  @log_file ||= path("tmp/spring.log").open("w+")
end

#path(addition) ⇒ Object



42
43
44
# File 'lib/spring/test/application.rb', line 42

def path(addition)
  root.join addition
end

#rails_versionObject



62
63
64
# File 'lib/spring/test/application.rb', line 62

def rails_version
  @rails_version ||= RailsVersion.new(gemfile.read.match(/gem 'rails', '(.*)'/)[1])
end

#read_stream(stream) ⇒ Object



154
155
156
157
158
159
160
# File 'lib/spring/test/application.rb', line 154

def read_stream(stream)
  output = ""
  while IO.select([stream], [], [], 0.5) && !stream.eof?
    output << stream.readpartial(10240)
  end
  output
end

#read_streamsObject



146
147
148
149
150
151
152
# File 'lib/spring/test/application.rb', line 146

def read_streams
  {
    stdout: read_stream(stdout.first),
    stderr: read_stream(stderr.first),
    log:    read_stream(log_file)
  }
end

#run(command, opts = {}) ⇒ Object



95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
# File 'lib/spring/test/application.rb', line 95

def run(command, opts = {})
  start_time = Time.now

  Bundler.with_clean_env do
    Process.spawn(
      env,
      command.to_s,
      out:   stdout.last,
      err:   stderr.last,
      in:    :close,
      chdir: root.to_s,
    )
  end

  _, status = Timeout.timeout(opts.fetch(:timeout, DEFAULT_TIMEOUT)) { Process.wait2 }

  if pid = spring_env.pid
    @server_pid = pid
    lines = `ps -A -o ppid= -o pid= | egrep '^\\s*#{@server_pid}'`.lines
    @application_pids = lines.map { |l| l.split.last.to_i }
  end

  output = read_streams
  puts dump_streams(command, output) if ENV["SPRING_DEBUG"]

  @times << (Time.now - start_time) if @times

  output.merge(status: status, command: command)
rescue Timeout::Error => e
  raise Timeout::Error, "While running command:\n\n#{dump_streams(command, read_streams)}"
end

#run!(command, options = {}) ⇒ Object



190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
# File 'lib/spring/test/application.rb', line 190

def run!(command, options = {})
  attempts  = (options.delete(:retry) || 0) + 1
  artifacts = nil

  until attempts == 0 || artifacts && artifacts[:status].success?
    artifacts = run(command, options)
    attempts -= 1
  end

  if artifacts[:status].success?
    artifacts
  else
    raise "command failed\n\n#{debug(artifacts)}"
  end
end

#springObject



58
59
60
# File 'lib/spring/test/application.rb', line 58

def spring
  gem_home.join "bin/spring"
end

#spring_client_configObject



91
92
93
# File 'lib/spring/test/application.rb', line 91

def spring_client_config
  path "config/spring_client.rb"
end

#spring_configObject



87
88
89
# File 'lib/spring/test/application.rb', line 87

def spring_config
  path "config/spring.rb"
end

#spring_test_commandObject



66
67
68
# File 'lib/spring/test/application.rb', line 66

def spring_test_command
  "#{rails_version.test_command} #{test}"
end

#stderrObject



23
24
25
# File 'lib/spring/test/application.rb', line 23

def stderr
  @stderr ||= IO.pipe
end

#stdoutObject



19
20
21
# File 'lib/spring/test/application.rb', line 19

def stdout
  @stdout ||= IO.pipe
end

#stop_springObject



70
71
72
73
# File 'lib/spring/test/application.rb', line 70

def stop_spring
  run "#{spring} stop"
rescue Errno::ENOENT
end

#testObject



75
76
77
# File 'lib/spring/test/application.rb', line 75

def test
  path "test/#{rails_version.controller_tests_dir}/posts_controller_test.rb"
end

#timing_ratioObject



142
143
144
# File 'lib/spring/test/application.rb', line 142

def timing_ratio
  last_time / first_time
end

#user_homeObject



54
55
56
# File 'lib/spring/test/application.rb', line 54

def user_home
  path "user_home"
end

#with_timingObject



127
128
129
130
131
132
# File 'lib/spring/test/application.rb', line 127

def with_timing
  @times = []
  yield
ensure
  @times = nil
end