require 'spec_helper'
require 'debci/experiment'
require 'debci/experiment_test'
require 'debci/package'

describe Debci::Experiment do
  include_context 'no-rabbitmq'

  let(:experiment) { Debci::Experiment.new }

  let(:package_foobar) { Debci::Package.new(name: 'foobar') }
  let(:package_bazqux) { Debci::Package.new(name: 'bazqux') }
  before do
    package_foobar.save!
    package_bazqux.save!
  end

  let(:user) do
    Debci::User.create!(username: 'theuser')
  end

  let(:new_experiment) do
    Debci::Experiment.new(
      suite: 'testing',
      arch: 'arm64',
      package_selector: { "name" => "foobar" },
      test_parameters: { "trigger" => "test" },
      owner: user,
    )
  end

  it 'requires only suite, arch, package_selector and test_parameters' do
    experiment = new_experiment
    expect(experiment.save!).to be_truthy
  end

  context 'when selecting packages' do
    it 'selects packages using a selector Hash' do
      experiment.package_selector = { "name" => "foobar" }
      expect(experiment.packages).to include(package_foobar)
      expect(experiment.packages).to_not include(package_bazqux)
      expect(experiment.packages.count).to eq(1)
    end
  end

  context 'when starting' do
    let(:experiment) do
      new_experiment.tap do |e|
        e.save!
      end
    end

    it 'submits jobs and records them in experiment tests' do
      experiment.start

      expect(experiment.tests.count).to eq(1)
      test = experiment.tests.first
      expect(test.control_job.package).to eq(package_foobar)
      expect(test.test_job.package).to eq(package_foobar)
    end

    it 'applies priority' do
      experiment.priority = 7
      experiment.start

      test = Debci::ExperimentTest.last
      job1 = test.control_job
      job2 = test.test_job

      expect(job1.priority).to eq(7)
      expect(job2.priority).to eq(7)
    end

    it 'applies control parameters' do
      experiment.control_parameters = { requested_backend: "lxc" }
      experiment.start
      test = experiment.tests.first
      expect(test.control_job.requested_backend).to eq("lxc")
    end

    it 'applies test parameters' do
      experiment.test_parameters = { requested_backend: "incus-lxc" }
      experiment.start
      test = experiment.tests.first
      expect(test.test_job.requested_backend).to eq("incus-lxc")
    end

    it 'marks experiment as started' do
      experiment.start
      expect(experiment).to be_started
    end

    it 'skips jobs for packages in the reject list' do
      pkg = package_foobar.name
      allow(Debci.reject_list).to receive(:include?).with(pkg, Hash).and_return(true)

      experiment.start
      test = Debci::ExperimentTest.last
      expect(test.control_job.status).to eq('fail')
      expect(test.test_job.status).to eq('fail')
    end

    it 'is able to calculate completion percentage' do
      experiment = new_experiment
      experiment.package_selector = { name: ["foobar", "bazqux"] }
      experiment.save!
      experiment.start
      test = Debci::ExperimentTest.last
      test.control_job.update!(status: 'pass', date: Time.now)
      test.test_job.update!(status: 'pass', date: Time.now)

      expect(experiment.percent_completed).to eq(50)
    end

    it 'is 0% complete if not started' do
      experiment = new_experiment.tap(&:save!)
      expect(experiment.percent_completed).to be_zero
    end
  end
end
