# SPDX-License-Identifier: GPL-3.0-only OR LicenseRef-KDE-Accepted-GPL
# SPDX-FileCopyrightText: 2019 Harald Sitter <sitter@kde.org>

require_relative 'test_helper'

class AptTest < Minitest::Test
  attr_accessor :apt
  attr_accessor :apt_get

  # system() variant which sets up merge-coverage. simplecov supports merging
  # of multiple coverage sets. we use this to get coverage metrics on the
  # binaries without having to refactor the script into runnable classes.
  def covered_system(cmd, *argv)
    pid = fork do
      # minitest is a right prick. Its autorun functionality is implemented
      # through at_exit handlers that explicitly call exit with codes. This would
      # override the actual script exit every time. As a simple way to skip the
      # original process' at_exit we'll run an argless exit! which skips any
      # further handlers and exits immediately. Because it is argless this does
      # not override an exit code set by the script. IOW exit(0) is preserved
      # becuase the the argless exit! prevents minitest from overriding it with
      # exit(1).
      at_exit { $!.is_a?(SystemExit) ? exit!($!.status) : exit!(1) }

      Object.any_instance.expects(:exec).never
      yield if block_given?

      begin
        require 'simplecov'
        SimpleCov.start do
          command_name "#{cmd}_#{__test_method_name__}"
        end
      rescue LoadError
        warn 'SimpleCov not loaded'
      end

      ARGV.replace(argv)
      warn "\nload"
      load cmd
      puts 'all good, fork ending!'
      exit 0
    end
    waitedpid, status = Process.waitpid2(pid)
    assert_equal(pid, waitedpid)
    status.success? # behave like system and return the success only
  end

  def expect_exec(*argv)
    Object.any_instance.expects(:exec).with(*argv)
  end

  def setup
    @bindir = File.join(__dir__, '../usr/sbin/')
    @apt = File.join(@bindir, 'apt')
    @apt_get = File.join(@bindir, 'apt-get')
  end

  def test_correct_command
    ret = covered_system(apt, 'dist-upgrade') do
      expect_exec('/usr/bin/apt', 'dist-upgrade')
    end
    assert(ret)
  end

  def test_correct_command_full
    ret = covered_system(apt, 'full-upgrade') do
      expect_exec('/usr/bin/apt', 'full-upgrade')
    end
    assert(ret)
  end

  def test_bad_command
    ret = covered_system(apt, 'upgrade')
    refute(ret)
  end

  def test_bad_command_but_yes
    ret = covered_system(apt, 'upgrade', '-y') do
      expect_exec('/usr/bin/apt', 'upgrade', '-y')
    end
    assert(ret)
  end

  def test_get_correct_command
    ret = covered_system(apt_get, 'dist-upgrade') do
      expect_exec('/usr/bin/apt-get', 'dist-upgrade')
    end
    assert(ret)
  end

  def test_get_bad_command
    ret = covered_system(apt_get, 'upgrade')
    refute(ret)
  end
end
