require "cc/cli/command"

module ProcHelpers
  def capture_io
    stdout = $stdout
    stderr = $stdout

    $stdout = StringIO.new
    $stderr = StringIO.new

    yield

    [$stdout.string, $stderr.string]
  ensure
    $stdout = stdout
    $stderr = stdout
  end

  def capture_io_and_exit_code
    exit_code = 0

    stdout, stderr = capture_io do
      begin
        yield
      rescue SystemExit => ex
        exit_code = ex.status
      end
    end

    return stdout, stderr, exit_code
  end
end

RSpec.configure do |conf|
  conf.include(ProcHelpers)
end

require "cc/cli/command"

module ProcHelpers
  def capture_io
    stdout = $stdout
    stderr = $stdout

    $stdout = StringIO.new
    $stderr = StringIO.new

    yield

    [$stdout.string, $stderr.string]
  rescue SystemExit => ex
    fail  "Unexpected SystemExit in capture_io: stdout=#{$stdout.string}, stderr=#{$stderr.string}"
  ensure
    $stdout = stdout
    $stderr = stdout
  end

  def capture_io_and_exit_code
    exit_code = 0

    stdout, stderr = capture_io do
      begin
        yield
      rescue SystemExit => ex
        exit_code = ex.status
      end
    end

    return stdout, stderr, exit_code
  end
end

RSpec.configure do |conf|
  conf.include(ProcHelpers)
end

Improve capture_io handling of unexpected exceptions
Improve capture_io handling of unexpected exceptions

We frequently use `capture_io` in specs for testing running CLI
commands, many of which will indirectly end up calling `exit 1` in
failure conditions.

For a happy-path spec, if a regression breaks the spec, this is
problematic because `exit 1` gets called & `rspec` exits prematurely.
And, since stderr & stdout are being captured at the time of exit, you
don't see any message associated with the exit, and it's very
mysterious.

This add a rescue similar to `capture_io_and_exit_code` (which is
explicitly intended to test failure cases) to `capture_io` which will
fail the spec with an informative message if something does call `exit`.
