require "spec_helper" describe SimControl::Controller do describe "#execute" do it "creates a new controller instance and runs it with the called arguments" do hostname = "a-hostname" simulation_description = double("simulation_description") scenario_description = double("scenario_description") results_directory = double("results_directory") instance = double(SimControl::Controller) SimControl::Controller.should_receive(:new).with(hostname, simulation_description, scenario_description, results_directory).and_return(instance) instance.should_receive(:run) SimControl::Controller.execute(hostname, simulation_description, scenario_description, results_directory) end it "calls methods called from the simulation description on the controller instance" do simulation_description = <<Controlfile hosts Controlfile instance = SimControl::Controller.new("", simulation_description, "", "") instance.should_receive(:hosts) instance.run end it "calls methods called from the scenario description on the controller instance" do scenario_description = <<scenario simulate scenario instance = SimControl::Controller.new("", "", scenario_description, "") instance.should_receive(:simulate) instance.run end end describe "#hosts" do it "yields the given block" do proc = Proc.new do end hosts = double("Hosts") hosts.should_receive(:process).with(&proc) instance = SimControl::Controller.new("", "", "", "", hosts: hosts) instance.hosts &proc end end describe "#repetitions" do it "allows to specify the number of repetitions" do instance = SimControl::Controller.new("", "", "", "") instance.repetitions 10 expect(instance.seeds.length).to eq(10) instance.run end end describe "#simulation" do let(:klass) { double("Klass") } it "creates a new instance of the given class and passes the hash" do script = "a-script" hash = double("Hash") instance = SimControl::Controller.new("", "", "", "") klass.should_receive(:new).with(script, hash) instance.simulation klass, script, hash end it "allows for the instance to be obtained as #current_simulation" do simulation_instance = double("simulation_instance") instance = SimControl::Controller.new("", "", "", "") klass.stub(:new) { simulation_instance } instance.simulation klass, "script", {} expect(instance.current_simulation).to be(simulation_instance) end end describe "#scenario" do it "stores all provided scenarios in all_scenarios" do scenario_a = {foo: 1} scenario_b = {foo: 2} instance = SimControl::Controller.new("", "", "", "") instance.simulate scenario_a instance.simulate scenario_b expect(instance.all_scenarios).to include(scenario_a) expect(instance.all_scenarios).to include(scenario_b) end end describe "#run" do let(:hostname) { "a-hostname" } let(:scenario_a) { {setting: "a-value"} } let(:scenario_b) { {setting: "another-value"} } let(:seeds) { [1, 2] } let(:simulation_instance) { double("simulation_instance") } let(:hosts) { double("Hosts") } subject { SimControl::Controller.new(hostname, "", "", "", hosts: hosts).tap do |c| c.stub(:seeds).and_return(seeds) c.stub(:current_simulation).and_return(simulation_instance) end } it "calls execute on the simulation instance for each parameter combination for the given host" do per_host_scenarios = [[scenario_a, scenario_b]] hosts.should_receive(:partition).with(anything(), hostname).and_return(per_host_scenarios) simulation_instance.should_receive(:simulate).ordered.with(scenario_a, seeds) simulation_instance.should_receive(:simulate).ordered.with(scenario_b, seeds) subject.run end it "passes all_scenarios to partition" do scenarios = [scenario_a, scenario_b] subject.should_receive(:all_scenarios).and_return(scenarios) hosts.should_receive(:partition).with(scenarios, anything()).and_return([scenarios]) simulation_instance.stub(:simulate) subject.run end it "spawns multiple threads if the hosts support it" do per_host_scenarios = [[scenario_a], [ scenario_b]] hosts.should_receive(:partition).with(anything(), hostname).and_return(per_host_scenarios) thread = double("Thread") Thread.should_receive(:new).twice.and_return(thread) thread.should_receive(:join).twice subject.run end end end