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

  def new_job
    Debci::Job.new(
      requestor: user,
      suite: 'testing',
      arch: 'arm64',
      package: package_foobar,
    )
  end

  let(:job1) { new_job.tap(&:save!) }
  let(:job2) { new_job.tap(&:save!) }

  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
      allow(Debci::Job).to receive(:create!).and_return(job1, job2)

      experiment.priority = 7
      experiment.start

      expect(job1).to have_received(:enqueue).with(7)
      expect(job2).to have_received(:enqueue).with(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
  end
end
