<commit_before># encoding: utf-8
require 'helper'
require 'io/wait'
require "timeout"
require "spring/sid"
require "spring/env"

class AppTest < ActiveSupport::TestCase
  DEFAULT_SPEEDUP = 0.8
  DEFAULT_TIMEOUT = ENV['CI'] ? 30 : 10

  def rails_version
    ENV['RAILS_VERSION'] || '~> 4.0.0'
  end

  def rails_3?
    rails_version.split(" ").last =~ /^3/
  end

  def app_root
    Pathname.new("#{TEST_ROOT}/apps/rails-#{rails_version.scan(/\d/)[0..1].join("-")}")
  end

  def gem_home
    app_root.join "vendor/gems/#{RUBY_VERSION}"
  end

  def user_home
    app_root.join "user_home"
  end

  def spring
    gem_home.join "bin/spring"
  end

  def spring_env
    @spring_env ||= Spring::Env.new(app_root)
  end

  def stdout
    @stdout ||= IO.pipe
  end

  def stderr
    @stderr ||= IO.pipe
  end

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

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

  def app_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: app_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 e, "Output:\n\n#{dump_streams(command, read_streams)}"
  end

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

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

  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

  def alive?(pid)
    Process.kill 0, pid
    true
  rescue Errno::ESRCH
    false
  end

  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| alive?(p) }
    end
  end

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

  def assert_output(artifacts, expected)
    expected.each do |stream, output|
      assert artifacts[stream].include?(output),
             "expected #{stream} to include '#{output}'.\n\n#{debug(artifacts)}"
    end
  end

  def assert_success(command, expected_output = nil)
    artifacts = app_run(*Array(command))
    assert artifacts[:status].success?, "expected successful exit status\n\n#{debug(artifacts)}"
    assert_output artifacts, expected_output if expected_output
  end

  def assert_failure(command, expected_output = nil)
    artifacts = app_run(*Array(command))
    assert !artifacts[:status].success?, "expected unsuccessful exit status\n\n#{debug(artifacts)}"
    assert_output artifacts, expected_output if expected_output
  end

  def assert_speedup(ratio = DEFAULT_SPEEDUP)
    if ENV['CI']
      yield
    else
      @times = []
      yield
      assert (@times.last / @times.first) < ratio, "#{@times.last} was not less than #{ratio} of #{@times.first}"
      @times = nil
    end
  end

  def spring_test_command
    "#{spring} testunit #{@test}"
  end

  def generate_app
    Bundler.with_clean_env do
      system "(gem list rails --installed --version '#{rails_version}' || " \
             "gem install rails --version '#{rails_version}') > /dev/null"

      # Have to shell out otherwise bundler prevents us finding the gem
      version = `ruby -e 'puts Gem::Specification.find_by_name("rails", "#{rails_version}").version'`.chomp

      system "rails _#{version}_ new #{app_root} --skip-bundle --skip-javascript --skip-sprockets > /dev/null"

      FileUtils.mkdir_p(gem_home)
      FileUtils.mkdir_p(user_home)
      FileUtils.rm_rf("#{app_root}/test/performance/")
    end
  end

  def install
    generate_app unless app_root.exist?

    system "gem build spring.gemspec 2>/dev/null 1>/dev/null"

    assert_success "gem install ../../../spring-#{Spring::VERSION}.gem"
    assert_success ["(gem list bundler | grep bundler) || gem install bundler", timeout: nil]
    assert_success ["bundle check || bundle update", timeout: nil]

    unless File.exist?(@controller)
      assert_success "bundle exec rails g scaffold post title:string"
    end

    assert_success "bundle exec rake db:migrate db:test:clone"
    @@installed = true
  end

  @@installed = false<commit_msg>Assert that Kernel#system calls work<commit_after># encoding: utf-8
require 'helper'
require 'io/wait'
require "timeout"
require "spring/sid"
require "spring/env"

class AppTest < ActiveSupport::TestCase
  DEFAULT_SPEEDUP = 0.8
  DEFAULT_TIMEOUT = ENV['CI'] ? 30 : 10

  def rails_version
    ENV['RAILS_VERSION'] || '~> 4.0.0'
  end

  def rails_3?
    rails_version.split(" ").last =~ /^3/
  end

  def app_root
    Pathname.new("#{TEST_ROOT}/apps/rails-#{rails_version.scan(/\d/)[0..1].join("-")}")
  end

  def gem_home
    app_root.join "vendor/gems/#{RUBY_VERSION}"
  end

  def user_home
    app_root.join "user_home"
  end

  def spring
    gem_home.join "bin/spring"
  end

  def spring_env
    @spring_env ||= Spring::Env.new(app_root)
  end

  def stdout
    @stdout ||= IO.pipe
  end

  def stderr
    @stderr ||= IO.pipe
  end

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

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

  def app_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: app_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 e, "Output:\n\n#{dump_streams(command, read_streams)}"
  end

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

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

  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

  def alive?(pid)
    Process.kill 0, pid
    true
  rescue Errno::ESRCH
    false
  end

  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| alive?(p) }
    end
  end

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

  def assert_output(artifacts, expected)
    expected.each do |stream, output|
      assert artifacts[stream].include?(output),
             "expected #{stream} to include '#{output}'.\n\n#{debug(artifacts)}"
    end
  end

  def assert_success(command, expected_output = nil)
    artifacts = app_run(*Array(command))
    assert artifacts[:status].success?, "expected successful exit status\n\n#{debug(artifacts)}"
    assert_output artifacts, expected_output if expected_output
  end

  def assert_failure(command, expected_output = nil)
    artifacts = app_run(*Array(command))
    assert !artifacts[:status].success?, "expected unsuccessful exit status\n\n#{debug(artifacts)}"
    assert_output artifacts, expected_output if expected_output
  end

  def assert_speedup(ratio = DEFAULT_SPEEDUP)
    if ENV['CI']
      yield
    else
      @times = []
      yield
      assert (@times.last / @times.first) < ratio, "#{@times.last} was not less than #{ratio} of #{@times.first}"
      @times = nil
    end
  end

  def spring_test_command
    "#{spring} testunit #{@test}"
  end

  def generate_app
    Bundler.with_clean_env do
      assert system("(gem list rails --installed --version '#{rails_version}' || " \
                      "gem install rails --version '#{rails_version}') > /dev/null")

      # Have to shell out otherwise bundler prevents us finding the gem
      version = `ruby -e 'puts Gem::Specification.find_by_name("rails", "#{rails_version}").version'`.chomp

      assert system("rails _#{version}_ new #{app_root} --skip-bundle --skip-javascript --skip-sprockets > /dev/null")

      FileUtils.mkdir_p(gem_home)
      FileUtils.mkdir_p(user_home)
      FileUtils.rm_rf("#{app_root}/test/performance/")
    end
  end

  def install
    generate_app unless app_root.exist?

    assert system("gem build spring.gemspec 2>/dev/null 1>/dev/null")

    assert_success "gem install ../../../spring-#{Spring::VERSION}.gem"
    assert_success ["(gem list bundler | grep bundler) || gem install bundler", timeout: nil]
    assert_success ["bundle check || bundle update", timeout: nil]

    unless File.exist?(@controller)
      assert_success "bundle exec rails g scaffold post title:string"
    end

    assert_success "bundle exec rake db:migrate db:test:clone"
    @@installed = true
  end

  @@installed = false
{'fraction_non_alphanumeric': 0.13296476761619191, 'fraction_numerical': 0.005059970014992503, 'mean_word_length': 2.8447406340057637, 'pattern_counts': {'":': 0, '<': 27, '<?xml version=': 0, '>': 27, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '4525170', 'n_tokens_mistral': 3731, 'n_tokens_neox': 3583, 'n_words': 843}