Added mcollective 2.3.1 package
[packages/trusty/mcollective.git] / spec / unit / rpc / stats_spec.rb
diff --git a/spec/unit/rpc/stats_spec.rb b/spec/unit/rpc/stats_spec.rb
new file mode 100755 (executable)
index 0000000..8344c46
--- /dev/null
@@ -0,0 +1,324 @@
+#!/usr/bin/env rspec
+
+require 'spec_helper'
+
+module MCollective
+  module RPC
+    describe Stats do
+      before(:each) do
+        @expected = {:discoverytime => 0,
+                     :okcount => 0,
+                     :blocktime => 0,
+                     :failcount => 0,
+                     :noresponsefrom => [],
+                     :responses => 0,
+                     :totaltime => 0,
+                     :discovered => 0,
+                     :starttime => 1300031826.0,
+                     :requestid => nil,
+                     :aggregate_summary => [],
+                     :aggregate_failures => [],
+                     :discovered_nodes => []}
+
+        @stats = Stats.new
+      end
+
+      describe "#initialize" do
+        it "should reset stats on creation" do
+          Stats.any_instance.stubs(:reset).returns(true).once
+          s = Stats.new
+        end
+      end
+
+      describe "#reset" do
+        it "should initialize data correctly" do
+          Time.stubs(:now).returns(Time.at(1300031826))
+          s = Stats.new
+
+          @expected.keys.each do |k|
+            @expected[k].should == s.send(k)
+          end
+        end
+      end
+
+      describe "#to_hash" do
+        it "should return correct stats" do
+          Time.stubs(:now).returns(Time.at(1300031826))
+          s = Stats.new
+
+          s.to_hash.should == @expected
+        end
+      end
+
+      describe "#[]" do
+        it "should return stat values" do
+          Time.stubs(:now).returns(Time.at(1300031826))
+          s = Stats.new
+
+          @expected.keys.each do |k|
+            @expected[k].should == s[k]
+          end
+        end
+
+        it "should return nil for unknown values" do
+          @stats["foo"].should == nil
+        end
+      end
+
+      describe "#ok" do
+        it "should increment stats" do
+          @stats.ok
+          @stats[:okcount].should == 1
+        end
+      end
+
+      describe "#fail" do
+        it "should increment stats" do
+          @stats.fail
+          @stats.failcount.should == 1
+        end
+      end
+
+      describe "#time_discovery" do
+        it "should set start time correctly" do
+          Time.stubs(:now).returns(Time.at(1300031826))
+
+          @stats.time_discovery(:start)
+
+          @stats.instance_variable_get("@discovery_start").should == 1300031826.0
+        end
+
+        it "should record the difference correctly" do
+          Time.stubs(:now).returns(Time.at(1300031826))
+          @stats.time_discovery(:start)
+
+          Time.stubs(:now).returns(Time.at(1300031827))
+          @stats.time_discovery(:end)
+
+          @stats.discoverytime.should == 1.0
+        end
+
+        it "should handle unknown actions and set discovery time to 0" do
+          Time.stubs(:now).returns(Time.at(1300031826))
+          @stats.time_discovery(:start)
+
+          Time.stubs(:now).returns(Time.at(1300031827))
+          @stats.time_discovery(:stop)
+
+          @stats.discoverytime.should == 0
+        end
+
+      end
+
+      describe "#client_stats=" do
+        it "should store stats correctly" do
+          data = {}
+          keys = [:noresponsefrom, :responses, :starttime, :blocktime, :totaltime, :discoverytime]
+          keys.each {|k| data[k] = k}
+
+          @stats.client_stats = data
+
+          keys.each do |k|
+            @stats[k].should == data[k]
+          end
+        end
+
+        it "should not store discovery time if it was already stored" do
+          data = {}
+          keys = [:noresponsefrom, :responses, :starttime, :blocktime, :totaltime, :discoverytime]
+          keys.each {|k| data[k] = k}
+
+          Time.stubs(:now).returns(Time.at(1300031826))
+          @stats.time_discovery(:start)
+
+          Time.stubs(:now).returns(Time.at(1300031827))
+          @stats.time_discovery(:end)
+
+          dtime = @stats.discoverytime
+
+          @stats.client_stats = data
+
+          @stats.discoverytime.should == dtime
+        end
+      end
+
+      describe "#time_block_execution" do
+        it "should set start time correctly" do
+          Time.stubs(:now).returns(Time.at(1300031826))
+
+          @stats.time_block_execution(:start)
+
+          @stats.instance_variable_get("@block_start").should == 1300031826.0
+        end
+
+        it "should record the difference correctly" do
+          Time.stubs(:now).returns(Time.at(1300031826))
+          @stats.time_block_execution(:start)
+
+          Time.stubs(:now).returns(Time.at(1300031827))
+          @stats.time_block_execution(:end)
+
+          @stats.blocktime.should == 1
+        end
+
+        it "should handle unknown actions and set discovery time to 0" do
+          Time.stubs(:now).returns(Time.at(1300031826))
+          @stats.time_block_execution(:start)
+
+          Time.stubs(:now).returns(Time.at(1300031827))
+          @stats.time_block_execution(:stop)
+
+          @stats.blocktime.should == 0
+        end
+      end
+
+      describe "#discovered_agents" do
+        it "should set discovered_nodes" do
+          nodes = ["one", "two"]
+          @stats.discovered_agents(nodes)
+          @stats.discovered_nodes.should == nodes
+        end
+
+        it "should set discovered count" do
+          nodes = ["one", "two"]
+          @stats.discovered_agents(nodes)
+          @stats.discovered.should == 2
+        end
+      end
+
+      describe "#finish_request" do
+        it "should calculate totaltime correctly" do
+          Time.stubs(:now).returns(Time.at(1300031824))
+          @stats.time_discovery(:start)
+
+          Time.stubs(:now).returns(Time.at(1300031825))
+          @stats.time_discovery(:end)
+
+          Time.stubs(:now).returns(Time.at(1300031826))
+          @stats.time_block_execution(:start)
+
+          Time.stubs(:now).returns(Time.at(1300031827))
+          @stats.time_block_execution(:end)
+
+          @stats.discovered_agents(["one", "two", "three"])
+          @stats.node_responded("one")
+          @stats.node_responded("two")
+
+          @stats.finish_request
+
+          @stats.totaltime.should == 2
+        end
+
+        it "should calculate no responses correctly" do
+          Time.stubs(:now).returns(Time.at(1300031824))
+          @stats.time_discovery(:start)
+
+          Time.stubs(:now).returns(Time.at(1300031825))
+          @stats.time_discovery(:end)
+
+          Time.stubs(:now).returns(Time.at(1300031826))
+          @stats.time_block_execution(:start)
+
+          Time.stubs(:now).returns(Time.at(1300031827))
+          @stats.time_block_execution(:end)
+
+          @stats.discovered_agents(["one", "two", "three"])
+          @stats.node_responded("one")
+          @stats.node_responded("two")
+
+          @stats.finish_request
+
+          @stats.noresponsefrom.should == ["three"]
+        end
+
+        it "should recover from failure correctly" do
+          Time.stubs(:now).returns(Time.at(1300031824))
+          @stats.time_discovery(:start)
+
+          Time.stubs(:now).returns(Time.at(1300031825))
+          @stats.time_discovery(:end)
+
+          Time.stubs(:now).returns(Time.at(1300031826))
+          @stats.time_block_execution(:start)
+
+          Time.stubs(:now).returns(Time.at(1300031827))
+          @stats.time_block_execution(:end)
+
+          # cause the .each to raise an exception
+          @stats.instance_variable_set("@responsesfrom", nil)
+          @stats.finish_request
+
+          @stats.noresponsefrom.should == []
+          @stats.totaltime.should == 0
+        end
+      end
+
+      describe "#node_responded" do
+        it "should append to the list of nodes" do
+          @stats.node_responded "foo"
+          @stats.responsesfrom.should == ["foo"]
+        end
+
+        it "should create a new array if adding fails" do
+          # cause the << to fail
+          @stats.instance_variable_set("@responsesfrom", nil)
+
+          @stats.node_responded "foo"
+          @stats.responsesfrom.should == ["foo"]
+        end
+      end
+
+      describe "#no_response_report" do
+        it "should create an empty report if all nodes responded" do
+          @stats.discovered_agents ["foo"]
+          @stats.node_responded "foo"
+          @stats.finish_request
+
+          @stats.no_response_report.should == ""
+        end
+
+        it "should list all nodes that did not respond" do
+          @stats.discovered_agents ["foo", "bar"]
+          @stats.finish_request
+
+          @stats.no_response_report.should match(Regexp.new(/No response from.+bar\s+foo/m))
+        end
+      end
+
+      describe "#text_for_aggregates" do
+        let(:aggregate){mock()}
+
+        before :each do
+          aggregate.stubs(:result).returns({:output => "success"})
+          aggregate.stubs(:action).returns("action")
+        end
+
+        it "should create the correct output text for aggregate functions" do
+          @stats.aggregate_summary = [aggregate]
+          aggregate.stubs(:is_a?).returns(true)
+          @stats.text_for_aggregates.should =~ /Summary of.*/
+        end
+
+        it "should display an error message for a failed statup hook" do
+          @stats.aggregate_failures = [{:name => "rspec", :type => :startup}]
+          @stats.text_for_aggregates.should =~  /exception raised while processing startup hook/
+        end
+
+        it "should display an error message for an unspecified output" do
+          @stats.aggregate_failures = [{:name => "rspec", :type => :create}]
+          @stats.text_for_aggregates.should =~  /unspecified output 'rspec' for the action/
+        end
+
+        it "should display an error message for a failed process_result" do
+          @stats.aggregate_failures = [{:name => "rspec", :type => :process_result}]
+          @stats.text_for_aggregates.should =~  /exception raised while processing result data/
+        end
+
+        it "should display an error message for a failed summarize" do
+          @stats.aggregate_failures = [{:name => "rspec", :type => :summarize}]
+          @stats.text_for_aggregates.should =~  /exception raised while summarizing/
+        end
+      end
+    end
+  end
+end