class Spring::Test::Application

Constants

DEFAULT_TIMEOUT

Attributes

root[R]
spring_env[R]

Public Class Methods

new(root) click to toggle source
# File lib/spring/test/application.rb, line 10
def initialize(root)
  @root       = Pathname.new(root)
  @spring_env = Spring::Env.new(root: root)
  @times      = nil
end

Public Instance Methods

application_config() click to toggle source
# File lib/spring/test/application.rb, line 84
def application_config
  path "config/application.rb"
end
await_reload() click to toggle source
# File lib/spring/test/application.rb, line 183
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
bundle() click to toggle source
# File lib/spring/test/application.rb, line 207
def bundle
  # Version restriction is a workaround for https://github.com/bundler/bundler/pull/4981
  # The problem breaks our tests on Ruby 2.2
  # We can remove once it's fixed
  run! "(gem list bundler | grep bundler) || gem install bundler --version '~> 1.12.0'", timeout: nil, retry: 2
  run! "bundle check || bundle update --retry=2", timeout: nil
end
controller() click to toggle source
# File lib/spring/test/application.rb, line 80
def controller
  path "app/controllers/posts_controller.rb"
end
debug(artifacts) click to toggle source
# File lib/spring/test/application.rb, line 177
def debug(artifacts)
  artifacts = artifacts.dup
  artifacts.delete :status
  dump_streams(artifacts.delete(:command), artifacts)
end
dump_streams(command, streams) click to toggle source
# File lib/spring/test/application.rb, line 163
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
env() click to toggle source
# File lib/spring/test/application.rb, line 32
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?() click to toggle source
# File lib/spring/test/application.rb, line 16
def exists?
  root.exist?
end
first_time() click to toggle source
# File lib/spring/test/application.rb, line 139
def first_time
  @times.first
end
gem_home() click to toggle source
# File lib/spring/test/application.rb, line 51
def gem_home
  path "../gems/#{RUBY_VERSION}"
end
gemfile() click to toggle source
# File lib/spring/test/application.rb, line 47
def gemfile
  path "Gemfile"
end
insert_into_test(code) click to toggle source
# File lib/spring/test/application.rb, line 215
def insert_into_test(code)
  File.write(test, test.read.sub(/^\s*get .+$/, code))
end
last_time() click to toggle source
# File lib/spring/test/application.rb, line 135
def last_time
  @times.last
end
log_file() click to toggle source
# File lib/spring/test/application.rb, line 28
def log_file
  @log_file ||= path("tmp/spring.log").open("w+")
end
path(addition) click to toggle source
# File lib/spring/test/application.rb, line 43
def path(addition)
  root.join addition
end
rails_version() click to toggle source
# File lib/spring/test/application.rb, line 63
def rails_version
  @rails_version ||= RailsVersion.new(gemfile.read.match(/gem 'rails', '(.*)'/)[1])
end
read_stream(stream) click to toggle source
# File lib/spring/test/application.rb, line 155
def read_stream(stream)
  output = ""
  while IO.select([stream], [], [], 0.5) && !stream.eof?
    output << stream.readpartial(10240)
  end
  output
end
read_streams() click to toggle source
# File lib/spring/test/application.rb, line 147
def read_streams
  {
    stdout: read_stream(stdout.first),
    stderr: read_stream(stderr.first),
    log:    read_stream(log_file)
  }
end
run(command, opts = {}) click to toggle source
# File lib/spring/test/application.rb, line 96
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 = %x`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
  raise Timeout::Error, "While running command:\n\n#{dump_streams(command, read_streams)}"
end
run!(command, options = {}) click to toggle source
# File lib/spring/test/application.rb, line 191
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
spring() click to toggle source
# File lib/spring/test/application.rb, line 59
def spring
  gem_home.join "bin/spring"
end
spring_client_config() click to toggle source
# File lib/spring/test/application.rb, line 92
def spring_client_config
  path "config/spring_client.rb"
end
spring_config() click to toggle source
# File lib/spring/test/application.rb, line 88
def spring_config
  path "config/spring.rb"
end
spring_test_command() click to toggle source
# File lib/spring/test/application.rb, line 67
def spring_test_command
  "bin/rake test #{test}"
end
stderr() click to toggle source
# File lib/spring/test/application.rb, line 24
def stderr
  @stderr ||= IO.pipe
end
stdout() click to toggle source
# File lib/spring/test/application.rb, line 20
def stdout
  @stdout ||= IO.pipe
end
stop_spring() click to toggle source
# File lib/spring/test/application.rb, line 71
def stop_spring
  run "#{spring} stop"
rescue Errno::ENOENT
end
test() click to toggle source
# File lib/spring/test/application.rb, line 76
def test
  path "test/controllers/posts_controller_test.rb"
end
timing_ratio() click to toggle source
# File lib/spring/test/application.rb, line 143
def timing_ratio
  last_time / first_time
end
user_home() click to toggle source
# File lib/spring/test/application.rb, line 55
def user_home
  path "user_home"
end
with_timing() { || ... } click to toggle source
# File lib/spring/test/application.rb, line 128
def with_timing
  @times = []
  yield
ensure
  @times = nil
end

Private Instance Methods

process_alive?(pid) click to toggle source
# File lib/spring/test/application.rb, line 221
def process_alive?(pid)
  Process.kill 0, pid
  true
rescue Errno::ESRCH
  false
end