require_relative "helper"
require_relative "helpers/integration"

class TestRedirectIO < TestIntegration
  parallelize_me!

  def setup
    skip_unless_signal_exist? :HUP
    super

    # Keep the Tempfile instances alive to avoid being GC'd
    @out_file = Tempfile.new('puma-out')
    @err_file = Tempfile.new('puma-err')
    @out_file_path = @out_file.path
    @err_file_path = @err_file.path
  end

  def teardown
    return if skipped?
    super

    paths = (skipped? ? [@out_file_path, @err_file_path] :
      [@out_file_path, @err_file_path, @old_out_file_path, @old_err_file_path]).compact

    File.unlink(*paths)
    @out_file = nil
    @err_file = nil
  end

  def test_sighup_redirects_io_single
    skip_if :jruby # Server isn't coming up in CI, TODO Fix

    cli_args = [
      '--redirect-stdout', @out_file_path,
      '--redirect-stderr', @err_file_path,
      'test/rackup/hello.ru'
    ]
    cli_server cli_args.join ' '

    wait_until_file_has_content @out_file_path
    assert_match 'puma startup', File.read(@out_file_path)

    wait_until_file_has_content @err_file_path
    assert_match 'puma startup', File.read(@err_file_path)

    log_rotate_output_files

    Process.kill :HUP, @server.pid

    wait_until_file_has_content @out_file_path
    assert_match 'puma startup', File.read(@out_file_path)

    wait_until_file_has_content @err_file_path
    assert_match 'puma startup', File.read(@err_file_path)
  end

  def test_sighup_redirects_io_cluster
    skip_unless :fork

    cli_args = [
      '-w', '1',
      '--redirect-stdout', @out_file_path,
      '--redirect-stderr', @err_file_path,
      'test/rackup/hello.ru'
    ]
    cli_server cli_args.join ' '

    wait_until_file_has_content @out_file_path
    assert_match 'puma startup', File.read(@out_file_path)

    wait_until_file_has_content @err_file_path
    assert_match 'puma startup', File.read(@err_file_path)

    log_rotate_output_files

    Process.kill :HUP, @server.pid

    wait_until_file_has_content @out_file_path
    assert_match 'puma startup', File.read(@out_file_path)

    wait_until_file_has_content @err_file_path
    assert_match 'puma startup', File.read(@err_file_path)
  end

  private

  def log_rotate_output_files
    # rename both files to .old
    @old_out_file_path = "#{@out_file_path}.old"
    @old_err_file_path = "#{@err_file_path}.old"
    File.rename @out_file_path, @old_out_file_path
    File.rename @err_file_path, @old_err_file_path

    File.new(@out_file_path, File::CREAT).close
    File.new(@err_file_path, File::CREAT).close
  end

  def wait_until_file_has_content(path)
    File.open(path) do |file|
      begin
        file.read_nonblock 1
        file.seek 0
      rescue EOFError
        sleep 0.1
        retry
      end
    end
  end
end
