X-Git-Url: https://review.fuel-infra.org/gitweb?a=blobdiff_plain;f=spec%2Funit%2Fagents_spec.rb;fp=spec%2Funit%2Fagents_spec.rb;h=ce01aade056b4bf690d460f4d01d68bb94e963ca;hb=b87d2f4e68281062df1913440ca5753ae63314a9;hp=0000000000000000000000000000000000000000;hpb=ab0ea530b8ac956091f17b104ab2311336cfc250;p=packages%2Fprecise%2Fmcollective.git diff --git a/spec/unit/agents_spec.rb b/spec/unit/agents_spec.rb new file mode 100755 index 0000000..ce01aad --- /dev/null +++ b/spec/unit/agents_spec.rb @@ -0,0 +1,295 @@ +#!/usr/bin/env rspec + +require 'spec_helper' + +module MCollective + describe Agents do + before do + tmpfile = Tempfile.new("mc_agents_spec") + path = tmpfile.path + tmpfile.close! + + @tmpdir = FileUtils.mkdir_p(path) + @tmpdir = @tmpdir[0] if @tmpdir.is_a?(Array) # ruby 1.9.2 + + @agentsdir = File.join([@tmpdir, "mcollective", "agent"]) + FileUtils.mkdir_p(@agentsdir) + + logger = mock + logger.stubs(:log) + logger.stubs(:start) + Log.configure(logger) + end + + after do + FileUtils.rm_r(@tmpdir) + end + + describe "#initialize" do + it "should fail if configuration has not been loaded" do + Config.instance.expects(:configured).returns(false) + + expect { + Agents.new + }.to raise_error("Configuration has not been loaded, can't load agents") + end + + it "should load agents" do + Config.instance.expects(:configured).returns(true) + Agents.any_instance.expects(:loadagents).once + + Agents.new + end + end + + describe "#clear!" do + it "should delete and unsubscribe all loaded agents" do + Config.instance.expects(:configured).returns(true).at_least_once + Config.instance.expects(:libdir).returns([@tmpdir]) + PluginManager.expects(:delete).with("foo_agent").once + Util.expects(:make_subscriptions).with("foo", :broadcast).returns("foo_target") + Util.expects(:unsubscribe).with("foo_target") + + a = Agents.new({"foo" => 1}) + end + end + + describe "#loadagents" do + before do + Config.instance.stubs(:configured).returns(true) + Config.instance.stubs(:libdir).returns([@tmpdir]) + Agents.any_instance.stubs("clear!").returns(true) + end + + it "should delete all existing agents" do + Agents.any_instance.expects("clear!").once + a = Agents.new + end + + it "should attempt to load agents from all libdirs" do + Config.instance.expects(:libdir).returns(["/nonexisting", "/nonexisting"]) + File.expects("directory?").with("/nonexisting/mcollective/agent").twice + + a = Agents.new + end + + it "should load found agents" do + Agents.any_instance.expects("loadagent").with("test").once + + FileUtils.touch(File.join([@agentsdir, "test.rb"])) + + a = Agents.new + end + + it "should load each agent unless already loaded" do + Agents.any_instance.expects("loadagent").with("test").never + + FileUtils.touch(File.join([@agentsdir, "test.rb"])) + + PluginManager << {:type => "test_agent", :class => String.new} + a = Agents.new + end + end + + describe "#loadagent" do + before do + FileUtils.touch(File.join([@agentsdir, "test.rb"])) + Config.instance.stubs(:configured).returns(true) + Config.instance.stubs(:libdir).returns([@tmpdir]) + Agents.any_instance.stubs("clear!").returns(true) + PluginManager.stubs(:loadclass).returns(true) + PluginManager.stubs("[]").with("test_agent").returns(true) + Util.stubs(:make_subscriptions).with("test", :broadcast).returns([{:agent => "test", :type => :broadcast, :collective => "test"}]) + Util.stubs(:subscribe).with([{:agent => "test", :type => :broadcast, :collective => "test"}]).returns(true) + Agents.stubs(:findagentfile).returns(File.join([@agentsdir, "test.rb"])) + Agents.any_instance.stubs("activate_agent?").returns(true) + + @a = Agents.new + end + + it "should return false if the agent file is missing" do + Agents.any_instance.expects(:findagentfile).returns(false).once + @a.loadagent("test").should == false + end + + it "should delete the agent before loading again" do + PluginManager.expects(:delete).with("test_agent").twice + @a.loadagent("test") + end + + it "should load the agent class from disk" do + PluginManager.expects(:loadclass).with("MCollective::Agent::Test") + @a.loadagent("test") + end + + it "should check if the agent should be activated" do + Agents.any_instance.expects(:findagentfile).with("test").returns(File.join([@agentsdir, "test.rb"])) + Agents.any_instance.expects("activate_agent?").with("test").returns(true) + @a.loadagent("test").should == true + end + + it "should set discovery and registration to be single instance plugins" do + PluginManager.expects("<<").with({:type => "registration_agent", :class => "MCollective::Agent::Registration", :single_instance => true}).once + PluginManager.expects("<<").with({:type => "discovery_agent", :class => "MCollective::Agent::Discovery", :single_instance => true}).once + Agents.any_instance.expects("activate_agent?").with("registration").returns(true) + Agents.any_instance.expects("activate_agent?").with("discovery").returns(true) + + PluginManager.expects(:loadclass).with("MCollective::Agent::Registration").returns(true).once + PluginManager.expects(:loadclass).with("MCollective::Agent::Discovery").returns(true).once + + FileUtils.touch(File.join([@agentsdir, "registration.rb"])) + FileUtils.touch(File.join([@agentsdir, "discovery.rb"])) + + @a.loadagent("registration") + @a.loadagent("discovery") + end + + it "should add general plugins as multiple instance plugins" do + PluginManager.expects("<<").with({:type => "test_agent", :class => "MCollective::Agent::Test", :single_instance => false}).once + @a.loadagent("test") + end + + it "should add the agent to the plugin manager and subscribe" do + PluginManager.expects("<<").with({:type => "foo_agent", :class => "MCollective::Agent::Foo", :single_instance => false}) + Util.stubs(:make_subscriptions).with("foo", :broadcast).returns([{:agent => "foo", :type => :broadcast, :collective => "test"}]) + Util.expects("subscribe").with([{:type => :broadcast, :agent => 'foo', :collective => 'test'}]).returns(true) + Agents.any_instance.expects(:findagentfile).with("foo").returns(File.join([@agentsdir, "foo.rb"])) + FileUtils.touch(File.join([@agentsdir, "foo.rb"])) + Agents.any_instance.expects("activate_agent?").with("foo").returns(true) + PluginManager.stubs("[]").with("foo_agent").returns(true) + + @a.loadagent("foo") + end + + it "should check if an agent is loadable and remove it from the list if not" do + PluginManager.expects("<<").with({:type => "foo_agent", :class => "MCollective::Agent::Foo", :single_instance => false}) + Agents.any_instance.expects(:findagentfile).with("foo").returns(File.join([@agentsdir, "foo.rb"])) + FileUtils.touch(File.join([@agentsdir, "foo.rb"])) + Agents.any_instance.expects("activate_agent?").with("foo").returns(true) + PluginManager.stubs("[]").with("foo_agent").raises("rspec") + + Log.expects(:error).once.with("Loading agent foo failed: rspec") + + @a.loadagent("foo").should == false + Agents.agentlist.include?("foo").should == false + end + + it "should add the agent to the agent list" do + Agents.agentlist.should == ["test"] + end + + it "should return true on success" do + @a.loadagent("test").should == true + end + + it "should handle load exceptions" do + Agents.any_instance.expects(:findagentfile).with("foo").returns(File.join([@agentsdir, "foo.rb"])) + Log.expects(:error).with(regexp_matches(/Loading agent foo failed/)) + @a.loadagent("foo").should == false + end + + it "should delete plugins that failed to load" do + Agents.any_instance.expects(:findagentfile).with("foo").returns(File.join([@agentsdir, "foo.rb"])) + PluginManager.expects(:delete).with("foo_agent").twice + + @a.loadagent("foo").should == false + end + end + + describe "#class_for_agent" do + it "should return the correct class" do + Config.instance.stubs(:configured).returns(true) + Agents.any_instance.stubs(:loadagents).returns(true) + Agents.new.class_for_agent("foo").should == "MCollective::Agent::Foo" + end + end + + describe "#activate_agent?" do + before do + Config.instance.stubs(:configured).returns(true) + Agents.any_instance.stubs(:loadagents).returns(true) + @a = Agents.new + + module MCollective::Agent;end + class MCollective::Agent::Test; end + end + + it "should check if the correct class has an activation method" do + Agent::Test.expects("respond_to?").with("activate?").once + + @a.activate_agent?("test") + end + + it "should call the activation method" do + Agent::Test.expects("activate?").returns(true).once + @a.activate_agent?("test") + end + + it "should log a debug message and return true if the class has no activation method" do + Agent::Test.expects("respond_to?").with("activate?").returns(false).once + Log.expects(:debug).with("MCollective::Agent::Test does not have an activate? method, activating as default") + + @a.activate_agent?("test").should == true + end + + it "should handle exceptions in the activation as false" do + Agent::Test.expects("activate?").raises(RuntimeError) + @a.activate_agent?("test").should == false + end + end + + describe "#findagentfile" do + before do + Config.instance.stubs(:configured).returns(true) + Config.instance.stubs(:libdir).returns([@tmpdir]) + Agents.any_instance.stubs(:loadagents).returns(true) + @a = Agents.new + end + + it "should support multiple libdirs" do + Config.instance.expects(:libdir).returns([@tmpdir, @tmpdir]).once + File.expects("exist?").returns(false).twice + @a.findagentfile("test") + end + + it "should look for the correct filename in the libdir" do + File.expects("exist?").with(File.join([@tmpdir, "mcollective", "agent", "test.rb"])).returns(false).once + @a.findagentfile("test") + end + + it "should return the full path if the agent is found" do + agentfile = File.join([@tmpdir, "mcollective", "agent", "test.rb"]) + File.expects("exist?").with(agentfile).returns(true).once + @a.findagentfile("test").should == agentfile + end + + it "should return false if no agent is found" do + @a.findagentfile("foo").should == false + end + end + + describe "#include?" do + it "should correctly report the plugin state" do + Config.instance.stubs(:configured).returns(true) + Config.instance.stubs(:libdir).returns([@tmpdir]) + Agents.any_instance.stubs(:loadagents).returns(true) + PluginManager.expects("include?").with("test_agent").returns(true) + + @a = Agents.new + + @a.include?("test").should == true + end + end + + describe "#agentlist" do + it "should return the correct agent list" do + Config.instance.stubs(:configured).returns(true) + Config.instance.stubs(:libdir).returns([@tmpdir]) + Agents.any_instance.stubs(:loadagents).returns(true) + + @a = Agents.new("test" => true) + Agents.agentlist.should == ["test"] + end + end + end +end