633b8ad85afe8a1630f67bc74b7df5e23fcdd748
[packages/precise/mcollective.git] / spec / unit / aggregate_spec.rb
1 #!/usr/bin/env rspec
2
3 require 'spec_helper'
4
5 module MCollective
6   describe Aggregate do
7     let(:ddl) do
8       {
9         :aggregate => [{:function => :func, :args=>[:foo, {:format => "%s"}]}],
10         :action => "test_action",
11         :output => {:foo => nil, :bar => nil}
12       }
13     end
14
15     describe '#create_functions' do
16       let(:function){mock}
17
18       it "should load all the functions with a format if defined" do
19         function.expects(:new).with(:foo, {}, "%s", 'test_action')
20         Aggregate.any_instance.expects(:contains_output?).returns(true)
21         Aggregate.any_instance.expects(:load_function).once.returns(function)
22         Aggregate.new(ddl)
23       end
24
25       it "should load all the functions without a format if it isn't defined" do
26         function.expects(:new).with(:foo, {}, nil, 'test_action')
27         Aggregate.any_instance.expects(:load_function).once.returns(function)
28         ddl[:aggregate].first[:args][1][:format] = nil
29         Aggregate.new(ddl)
30       end
31
32       it "should not summarize functions where the output is not specified in the ddl" do
33         invalid_ddl = { :aggregate => [{:function => :func, :args=>[:foo], :format => "%s"}, {:function => :func, :args=>[:fail], :format => "%s"}],
34                         :action => "test_action",
35                         :output => {:foo => nil, :bar => nil}}
36
37         function.stubs(:new).returns("function")
38         Aggregate.any_instance.stubs(:load_function).returns(function)
39
40         Log.expects(:error)
41         aggregate = Aggregate.new(invalid_ddl)
42         aggregate.functions.should == ["function"]
43         aggregate.failed.should == [{:type=>:create, :name=>:fail}]
44       end
45
46       it "should pass additional arguments if specified in the ddl" do
47         function.expects(:new).with(:foo, {:extra => "extra"}, "%s", 'test_action')
48         Aggregate.any_instance.expects(:load_function).once.returns(function)
49         ddl[:aggregate].first[:args][1][:extra] = "extra"
50         Aggregate.new(ddl)
51       end
52
53       it "should not summarize functions if the startup hook raises an exception" do
54         function.stubs(:new).raises("rspec")
55         Aggregate.any_instance.expects(:load_function).returns(function)
56
57         Log.expects(:error)
58         aggregate = Aggregate.new(ddl)
59         aggregate.failed.should == [{:type=>:startup, :name =>:foo }]
60       end
61     end
62
63     describe '#contains_ouput?' do
64       before :all do
65         Aggregate.any_instance.stubs(:create_functions)
66         @aggregate = Aggregate.new(ddl)
67       end
68
69       it "should return false if the ddl output does not include the function's input" do
70         result = @aggregate.contains_output?(:baz)
71         result.should == false
72       end
73
74       it "should return true if the ddl output includes the function's input" do
75         result = @aggregate.contains_output?(:foo)
76         result.should == true
77       end
78     end
79
80     describe '#call_functions' do
81       let(:aggregate){ Aggregate.new(ddl)}
82       let(:result){ RPC::Result.new("rspec", "rspec", :sender => "rspec", :statuscode => 0, :statusmsg => "rspec", :data => {:test => :result})}
83       let(:function) {mock}
84
85       before :each do
86         Aggregate.any_instance.stubs(:create_functions)
87       end
88
89       it "should call all of the functions" do
90         function.expects(:process_result).with(:result, result).once
91         function.expects(:output_name).returns(:test)
92         aggregate.functions = [function]
93
94         aggregate.call_functions(result)
95       end
96
97       it "should not fail if 'process_result' method raises an exception" do
98         aggregate.functions = [function]
99         function.stubs(:output_name).returns(:test)
100         function.stubs(:process_result).raises("Failed")
101
102         Log.expects(:error)
103         aggregate.call_functions(result)
104         aggregate.failed.should == [:name => :test, :type => :process_result]
105       end
106
107       it "should not fail if 'summarize' method raises en exception" do
108         function.stubs(:summarize).raises("Failed")
109         function.stubs(:output_name).returns("rspec")
110         aggregate.functions = [function]
111
112         Log.expects(:error)
113         result = aggregate.summarize
114       end
115     end
116
117     describe '#summarize' do
118       it "should return the ordered function results" do
119         Aggregate.any_instance.stubs(:create_functions)
120         aggregate = Aggregate.new(ddl)
121
122         func1 = mock
123         func1.expects(:summarize).returns(func1)
124         func1.stubs(:result).returns(:output => 5)
125
126         func2 = mock
127         func2.expects(:summarize).returns(func2)
128         func2.stubs(:result).returns(:output => 2)
129
130         aggregate.functions = [func1, func2]
131
132         result = aggregate.summarize
133         result.should == [func2, func1]
134       end
135
136       it "should not summarise data that raises an exception" do
137         Aggregate.any_instance.stubs(:create_functions)
138         aggregate = Aggregate.new(ddl)
139         func = mock
140         func.stubs(:summarize).raises("rspec")
141         func.stubs(:output_name).returns("rspec")
142         aggregate.functions = [func]
143         Log.expects(:error)
144
145         aggregate.summarize
146         aggregate.failed.should == [{:name => "rspec", :type => :summarize}]
147       end
148     end
149
150     describe '#load_function' do
151       before :all do
152         Aggregate.any_instance.stubs(:create_functions)
153         @aggregate = Aggregate.new(ddl)
154       end
155
156       it "should return a class object if it can be loaded" do
157         PluginManager.expects(:loadclass).with("MCollective::Aggregate::Test")
158         Aggregate.expects(:const_get).with("Test")
159         function = @aggregate.load_function("test")
160       end
161
162       it "should raise an exception if the class object cannot be loaded" do
163         PluginManager.expects(:loadclass).with("MCollective::Aggregate::Test")
164         expect {
165           function = @aggregate.load_function("test")
166         }.to raise_error("Aggregate function file 'test.rb' cannot be loaded")
167       end
168     end
169   end
170 end