mcollective-client 2.2.4 → 2.4.0

Sign up to get free protection for your applications and to get access to all the features.

Potentially problematic release.


This version of mcollective-client might be problematic. Click here for more details.

Files changed (66) hide show
  1. checksums.yaml +7 -0
  2. data/lib/mcollective/application.rb +25 -34
  3. data/lib/mcollective/client.rb +91 -33
  4. data/lib/mcollective/config.rb +42 -43
  5. data/lib/mcollective/data/base.rb +1 -1
  6. data/lib/mcollective/data/result.rb +6 -2
  7. data/lib/mcollective/ddl/agentddl.rb +28 -1
  8. data/lib/mcollective/ddl/base.rb +8 -6
  9. data/lib/mcollective/log.rb +11 -3
  10. data/lib/mcollective/logger/file_logger.rb +4 -4
  11. data/lib/mcollective/matcher.rb +9 -1
  12. data/lib/mcollective/message.rb +14 -23
  13. data/lib/mcollective/optionparser.rb +9 -1
  14. data/lib/mcollective/pluginpackager.rb +24 -3
  15. data/lib/mcollective/pluginpackager/agent_definition.rb +12 -12
  16. data/lib/mcollective/pluginpackager/standard_definition.rb +12 -12
  17. data/lib/mcollective/rpc/agent.rb +15 -12
  18. data/lib/mcollective/rpc/client.rb +67 -31
  19. data/lib/mcollective/rpc/helpers.rb +7 -1
  20. data/lib/mcollective/rpc/reply.rb +3 -1
  21. data/lib/mcollective/shell.rb +45 -8
  22. data/lib/mcollective/util.rb +37 -1
  23. data/lib/mcollective/windows_daemon.rb +14 -3
  24. data/spec/spec_helper.rb +2 -0
  25. data/spec/unit/application_spec.rb +45 -26
  26. data/spec/unit/cache_spec.rb +3 -3
  27. data/spec/unit/client_spec.rb +269 -24
  28. data/spec/unit/config_spec.rb +89 -26
  29. data/spec/unit/data/base_spec.rb +1 -0
  30. data/spec/unit/data/result_spec.rb +19 -1
  31. data/spec/unit/data_spec.rb +3 -0
  32. data/spec/unit/ddl/agentddl_spec.rb +32 -0
  33. data/spec/unit/ddl/base_spec.rb +4 -0
  34. data/spec/unit/ddl/dataddl_spec.rb +1 -1
  35. data/spec/unit/log_spec.rb +44 -27
  36. data/spec/unit/logger/base_spec.rb +1 -1
  37. data/spec/unit/matcher_spec.rb +14 -0
  38. data/spec/unit/message_spec.rb +24 -0
  39. data/spec/unit/optionparser_spec.rb +99 -0
  40. data/spec/unit/pluginpackager/agent_definition_spec.rb +48 -17
  41. data/spec/unit/pluginpackager/standard_definition_spec.rb +44 -20
  42. data/spec/unit/pluginpackager_spec.rb +31 -7
  43. data/spec/unit/plugins/mcollective/agent/rpcutil_spec.rb +176 -0
  44. data/spec/unit/plugins/mcollective/application/plugin_spec.rb +81 -0
  45. data/spec/unit/plugins/mcollective/audit/logfile_spec.rb +44 -0
  46. data/spec/unit/plugins/mcollective/connector/activemq_spec.rb +118 -27
  47. data/spec/unit/plugins/mcollective/connector/rabbitmq_spec.rb +168 -34
  48. data/spec/unit/plugins/mcollective/data/agent_data_spec.rb +1 -0
  49. data/spec/unit/plugins/mcollective/data/fstat_data_spec.rb +1 -0
  50. data/spec/unit/plugins/mcollective/discovery/flatfile_spec.rb +10 -0
  51. data/spec/unit/plugins/mcollective/discovery/stdin_spec.rb +65 -0
  52. data/spec/unit/plugins/mcollective/facts/yaml_facts_spec.rb +65 -0
  53. data/spec/unit/plugins/mcollective/packagers/debpackage_packager_spec.rb +240 -219
  54. data/spec/unit/plugins/mcollective/packagers/modulepackage_packager_spec.rb +209 -0
  55. data/spec/unit/plugins/mcollective/packagers/rpmpackage_packager_spec.rb +223 -109
  56. data/spec/unit/rpc/actionrunner_spec.rb +2 -1
  57. data/spec/unit/rpc/agent_spec.rb +130 -1
  58. data/spec/unit/rpc/client_spec.rb +169 -3
  59. data/spec/unit/security/base_spec.rb +0 -1
  60. data/spec/unit/shell_spec.rb +76 -3
  61. data/spec/unit/util_spec.rb +69 -1
  62. data/spec/unit/windows_daemon_spec.rb +30 -9
  63. metadata +104 -90
  64. data/spec/unit/plugins/mcollective/connector/stomp/eventlogger_spec.rb +0 -34
  65. data/spec/unit/plugins/mcollective/connector/stomp_spec.rb +0 -424
  66. data/spec/unit/plugins/mcollective/validator/any_validator_spec.rb +0 -15
@@ -5,6 +5,34 @@ require 'spec_helper'
5
5
  module MCollective
6
6
  describe Config do
7
7
  describe "#loadconfig" do
8
+ it "should fail when no libdir is set" do
9
+ File.expects(:exists?).with("/nonexisting").returns(true)
10
+ File.expects(:readlines).with("/nonexisting").returns([])
11
+ Config.instance.stubs(:set_config_defaults)
12
+ expect { Config.instance.loadconfig("/nonexisting") }.to raise_error("The /nonexisting config file does not specify a libdir setting, cannot continue")
13
+ end
14
+
15
+ it "should only test that libdirs are absolute paths" do
16
+ Util.expects(:absolute_path?).with("/one").returns(true)
17
+ Util.expects(:absolute_path?).with("/two").returns(true)
18
+ Util.expects(:absolute_path?).with("/three").returns(true)
19
+ Util.expects(:absolute_path?).with("four").returns(false)
20
+
21
+ File.stubs(:exists?).with("/nonexisting").returns(true)
22
+
23
+ ["/one#{File::PATH_SEPARATOR}/two", "/three"].each do |path|
24
+ File.expects(:readlines).with("/nonexisting").returns(["libdir = #{path}"])
25
+
26
+ Config.instance.loadconfig("/nonexisting")
27
+
28
+ PluginManager.clear
29
+ end
30
+
31
+ File.expects(:readlines).with("/nonexisting").returns(["libdir = four"])
32
+
33
+ expect { Config.instance.loadconfig("/nonexisting") }.to raise_error(/should be absolute paths/)
34
+ end
35
+
8
36
  it "should not allow any path like construct for identities" do
9
37
  # Taken from puppet test cases
10
38
  ['../foo', '..\\foo', './../foo', '.\\..\\foo',
@@ -16,9 +44,8 @@ module MCollective
16
44
  "\\\\?\\c:\\foo", "//?/UNC/bar", "//foo/bar",
17
45
  "//?/c:/foo"
18
46
  ].each do |input|
19
- File.expects(:open).with("/nonexisting", "r").returns(StringIO.new("identity = #{input}"))
47
+ File.expects(:readlines).with("/nonexisting").returns(["identity = #{input}", "libdir=/nonexistinglib"])
20
48
  File.expects(:exists?).with("/nonexisting").returns(true)
21
- File.expects(:exists?).with(File.join(File.dirname("/nonexisting"), "rpc-help.erb")).returns(true)
22
49
 
23
50
  expect {
24
51
  Config.instance.loadconfig("/nonexisting")
@@ -26,11 +53,19 @@ module MCollective
26
53
  end
27
54
  end
28
55
 
56
+ it "should strip whitespaces from config keys" do
57
+ File.expects(:exists?).with("/nonexisting").returns(true)
58
+ File.expects(:readlines).with("/nonexisting").returns([" identity= your.example.com ", "libdir=/nonexisting"])
59
+
60
+ config = Config.instance
61
+ config.loadconfig("/nonexisting")
62
+ config.identity.should == "your.example.com"
63
+ end
64
+
29
65
  it "should allow valid identities" do
30
66
  ["foo", "foo_bar", "foo-bar", "foo-bar-123", "foo.bar", "foo_bar_123"].each do |input|
31
- File.expects(:open).with("/nonexisting", "r").returns(StringIO.new("identity = #{input}"))
67
+ File.expects(:readlines).with("/nonexisting").returns(["identity = #{input}", "libdir=/nonexistinglib"])
32
68
  File.expects(:exists?).with("/nonexisting").returns(true)
33
- File.expects(:exists?).with(File.join(File.dirname("/nonexisting"), "rpc-help.erb")).returns(true)
34
69
  PluginManager.stubs(:loadclass)
35
70
  PluginManager.stubs("<<")
36
71
 
@@ -38,54 +73,74 @@ module MCollective
38
73
  end
39
74
  end
40
75
 
41
- it "should not allow the syslog logger type on windows" do
42
- Util.expects("windows?").returns(true).twice
43
- File.expects(:open).with("/nonexisting", "r").returns(StringIO.new("logger_type = syslog"))
76
+ it "should set direct_addressing to true by default" do
77
+ File.expects(:readlines).with("/nonexisting").returns(["libdir=/nonexistinglib"])
44
78
  File.expects(:exists?).with("/nonexisting").returns(true)
45
- File.expects(:exists?).with(File.join(File.dirname("/nonexisting"), "rpc-help.erb")).returns(true)
46
79
  PluginManager.stubs(:loadclass)
47
80
  PluginManager.stubs("<<")
48
81
 
49
- expect { Config.instance.loadconfig("/nonexisting") }.to raise_error("The sylog logger is not usable on the Windows platform")
82
+ Config.instance.loadconfig("/nonexisting")
83
+ Config.instance.direct_addressing.should == true
50
84
  end
51
85
 
52
- it "should default to finding the help template in the same dir as the config file" do
53
- path = File.join(File.dirname("/nonexisting"), "rpc-help.erb")
54
-
55
- File.expects(:open).with("/nonexisting", "r").returns(StringIO.new(""))
86
+ it "should allow direct_addressing to be disabled in the config file" do
87
+ File.expects(:readlines).with("/nonexisting").returns(["libdir=/nonexistinglib", "direct_addressing=n"])
56
88
  File.expects(:exists?).with("/nonexisting").returns(true)
57
89
  PluginManager.stubs(:loadclass)
58
90
  PluginManager.stubs("<<")
59
91
 
60
- File.expects(:exists?).with(path).returns(true)
61
-
62
92
  Config.instance.loadconfig("/nonexisting")
63
- Config.instance.rpchelptemplate.should == path
93
+ Config.instance.direct_addressing.should == false
64
94
  end
65
95
 
66
- it "should fall back to old behavior if the help template file does not exist in the config dir" do
67
- path = File.join(File.dirname("/nonexisting"), "rpc-help.erb")
68
-
69
- File.expects(:open).with("/nonexisting", "r").returns(StringIO.new(""))
96
+ it "should not allow the syslog logger type on windows" do
97
+ Util.expects("windows?").returns(true).twice
98
+ File.expects(:readlines).with("/nonexisting").returns(["libdir=/nonexistinglib", "logger_type=syslog"])
70
99
  File.expects(:exists?).with("/nonexisting").returns(true)
71
- File.expects(:exists?).with(path).returns(false)
72
100
  PluginManager.stubs(:loadclass)
73
101
  PluginManager.stubs("<<")
74
102
 
75
- Config.instance.loadconfig("/nonexisting")
76
- Config.instance.rpchelptemplate.should == "/etc/mcollective/rpc-help.erb"
103
+ expect { Config.instance.loadconfig("/nonexisting") }.to raise_error("The sylog logger is not usable on the Windows platform")
77
104
  end
78
105
 
79
106
  it "should support multiple default_discovery_options" do
80
- File.expects(:open).with("/nonexisting", "r").returns(StringIO.new("default_discovery_options = 1\ndefault_discovery_options = 2"))
107
+ File.expects(:readlines).with("/nonexisting").returns(["default_discovery_options = 1", "default_discovery_options = 2", "libdir=/nonexistinglib"])
81
108
  File.expects(:exists?).with("/nonexisting").returns(true)
82
- File.expects(:exists?).with(File.join(File.dirname("/nonexisting"), "rpc-help.erb")).returns(true)
83
109
  PluginManager.stubs(:loadclass)
84
110
  PluginManager.stubs("<<")
85
111
 
86
112
  Config.instance.loadconfig("/nonexisting")
87
113
  Config.instance.default_discovery_options.should == ["1", "2"]
88
114
  end
115
+
116
+ it "should not allow non integer values when expecting an integer value" do
117
+ PluginManager.stubs(:loadclass)
118
+ PluginManager.stubs("<<")
119
+
120
+ ["registerinterval", "max_log_size", "direct_addressing_threshold", "publish_timeout",
121
+ "fact_cache_time", "ttl"].each do |key|
122
+ File.expects(:readlines).with("/nonexisting").returns(["#{key} = nan"])
123
+ File.expects(:exists?).with("/nonexisting").returns(true)
124
+
125
+ expect{
126
+ Config.instance.loadconfig("/nonexisting")
127
+ }.to raise_error "Could not parse value for configuration option '#{key}' with value 'nan'"
128
+ end
129
+ end
130
+
131
+ it 'should log a warning when using a deprecated option' do
132
+ PluginManager.stubs(:loadclass)
133
+ PluginManager.stubs("<<")
134
+
135
+ ["topicprefix", "topicsep", "queueprefix", "rpchelptemplate", "helptemplatedir"].each do |key|
136
+ File.expects(:exists?).with("/nonexisting").returns(true)
137
+ File.expects(:readlines).with("/nonexisting").returns(["#{key} = nan", "libdir = /nonexistinglib"])
138
+
139
+ Log.stubs(:warn)
140
+ Log.expects(:warn).with("Use of deprecated '#{key}' option. This option is ignored and should be removed from '/nonexisting'")
141
+ Config.instance.loadconfig("/nonexisting")
142
+ end
143
+ end
89
144
  end
90
145
 
91
146
  describe "#read_plugin_config_dir" do
@@ -124,6 +179,13 @@ module MCollective
124
179
  Config.instance.pluginconf.should == {"foo.rspec" => "test"}
125
180
  end
126
181
 
182
+ it "should strip whitespaces from config keys" do
183
+ Dir.expects(:new).with(@plugindir).returns(["foo.cfg"])
184
+ File.expects(:open).with(File.join(@plugindir, "foo.cfg"), "r").returns([" rspec = test"])
185
+ Config.instance.read_plugin_config_dir(@plugindir)
186
+ Config.instance.pluginconf.should == {"foo.rspec" => "test"}
187
+ end
188
+
127
189
  it "should override main config file" do
128
190
  configfile = File.join(@plugindir, "foo.cfg")
129
191
  servercfg = File.join(File.dirname(@plugindir), "server.cfg")
@@ -133,7 +195,8 @@ module MCollective
133
195
  File.stubs(:exists?).returns(true)
134
196
  File.stubs(:directory?).with(@plugindir).returns(true)
135
197
  File.stubs(:exists?).with(servercfg).returns(true)
136
- File.expects(:open).with(servercfg, "r").returns(["plugin.rspec.key = default"])
198
+ File.expects(:readlines).with(servercfg).returns(["plugin.rspec.key = default", "libdir=/nonexisting"])
199
+ File.stubs(:directory?).with("/nonexisting").returns(true)
137
200
 
138
201
  Dir.expects(:new).with(@plugindir).returns(["rspec.cfg"])
139
202
  File.expects(:open).with(File.join(@plugindir, "rspec.cfg"), "r").returns(["key = overridden"])
@@ -7,6 +7,7 @@ module MCollective
7
7
  describe Base do
8
8
  before do
9
9
  @ddl = mock
10
+ @ddl.stubs(:dataquery_interface).returns({:output => {'rspec' => {}}})
10
11
  @ddl.stubs(:meta).returns({:timeout => 1})
11
12
  end
12
13
 
@@ -6,7 +6,21 @@ module MCollective
6
6
  module Data
7
7
  describe Result do
8
8
  before(:each) do
9
- @result = Result.new
9
+ @result = Result.new({})
10
+ end
11
+
12
+ describe "#initialize" do
13
+ it "should initialize empty values for all output fields" do
14
+ result = Result.new({:rspec1 => {}, :rspec2 => {}})
15
+ result[:rspec1].should == nil
16
+ result[:rspec2].should == nil
17
+ end
18
+
19
+ it "should set default values for all output fields" do
20
+ result = Result.new({:rspec1 => {:default => 1}, :rspec2 => {}})
21
+ result[:rspec1].should == 1
22
+ result[:rspec2].should == nil
23
+ end
10
24
  end
11
25
 
12
26
  describe "#[]=" do
@@ -58,6 +72,10 @@ module MCollective
58
72
  end
59
73
 
60
74
  describe "#method_missing" do
75
+ it "should raise the correct exception for unknown keys" do
76
+ expect { @result.nosuchdata }.to raise_error(NoMethodError)
77
+ end
78
+
61
79
  it "should retrieve the correct data" do
62
80
  @result["rspec"] = "rspec value"
63
81
  @result.rspec.should == "rspec value"
@@ -17,6 +17,8 @@ module MCollective
17
17
 
18
18
  ddl = mock
19
19
  ddl.stubs(:meta).returns({:timeout => 1})
20
+ ddl.stubs(:dataquery_interface).returns({:rspec => nil})
21
+ ddl.stubs(:dataquery_interface).returns({:output => {}})
20
22
  DDL.stubs(:new).returns(ddl)
21
23
  Data::Base.expects(:activate?).returns(false)
22
24
  PluginManager.expects("[]").with("rspec_data").returns(Data::Base.new)
@@ -30,6 +32,7 @@ module MCollective
30
32
 
31
33
  ddl = mock
32
34
  ddl.stubs(:meta).returns({:timeout => 1})
35
+ ddl.stubs(:dataquery_interface).returns({:output => {}})
33
36
  DDL.stubs(:new).returns(ddl)
34
37
  Data::Base.expects(:activate?).raises("rspec failure")
35
38
  Log.expects(:debug).once.with("Disabling data plugin rspec_data due to exception RuntimeError: rspec failure")
@@ -17,6 +17,36 @@ module MCollective
17
17
  end
18
18
  end
19
19
 
20
+ describe "#set_default_input_arguments" do
21
+ before do
22
+ @ddl.action(:test, :description => "rspec")
23
+ @ddl.instance_variable_set("@current_entity", :test)
24
+
25
+ @ddl.input(:optional, :prompt => "prompt", :description => "descr",
26
+ :type => :string, :optional => true, :validation => "",
27
+ :maxlength => 1, :default => "default")
28
+ @ddl.input(:required, :prompt => "prompt", :description => "descr",
29
+ :type => :string, :optional => false, :validation => "",
30
+ :maxlength => 1, :default => "default")
31
+ end
32
+
33
+ it "should correctly add default arguments to required inputs" do
34
+ args = {}
35
+
36
+ @ddl.set_default_input_arguments(:test, args)
37
+
38
+ args.should == {:required => "default"}
39
+ end
40
+
41
+ it "should not override any existing arguments" do
42
+ args = {:required => "specified"}
43
+
44
+ @ddl.set_default_input_arguments(:test, args)
45
+
46
+ args.should == {:required => "specified"}
47
+ end
48
+ end
49
+
20
50
  describe "#validate_rpc_request" do
21
51
  it "should ensure the action is known" do
22
52
  @ddl.action(:test, :description => "rspec")
@@ -38,6 +68,8 @@ module MCollective
38
68
  :type => :string, :optional => false, :validation => "",
39
69
  :maxlength => 1)
40
70
 
71
+ @ddl.stubs(:validate_input_argument).returns(true)
72
+
41
73
  expect {
42
74
  @ddl.validate_rpc_request(:test, {})
43
75
  }.to raise_error("Action test needs a required argument")
@@ -18,6 +18,8 @@ module MCollective
18
18
 
19
19
  it "should return correct new path for other ddls" do
20
20
  @ddl.instance_variable_set("@plugintype", :data)
21
+ @ddl.stubs(:helptemplatedir).returns("/etc/mcollective")
22
+ Util.stubs(:templatepath).with("data-help.erb").returns("/etc/mcollective/data-help.erb")
21
23
  File.expects(:exists?).with("/etc/mcollective/data-help.erb").returns(true)
22
24
  @ddl.template_for_plugintype.should == "data-help.erb"
23
25
  end
@@ -31,6 +33,8 @@ module MCollective
31
33
  end
32
34
 
33
35
  it "should use template from help template path when provided template name is not an absolute file path" do
36
+ Util.stubs(:absolute_path?).returns(false)
37
+ Util.stubs(:templatepath).returns("/etc/mcollective/foo", "/etc/mcollective/metadata-help.erb")
34
38
  File.expects(:read).with("/etc/mcollective/foo").returns("rspec")
35
39
  File.expects(:read).with("/etc/mcollective/metadata-help.erb").returns("rspec")
36
40
  @ddl.help("foo").should == "rspec"
@@ -34,7 +34,7 @@ module MCollective
34
34
  end
35
35
 
36
36
  @ddl.dataquery_interface.should == {:description => "rspec",
37
- :input => {:query => input.merge(:optional => nil)},
37
+ :input => {:query => input.merge(:optional => nil, :default => nil)},
38
38
  :output => {:rspec => output}}
39
39
  end
40
40
  end
@@ -10,9 +10,17 @@ module MCollective
10
10
  @logger.stubs(:start)
11
11
  @logger.stubs(:set_logging_level)
12
12
  @logger.stubs(:valid_levels)
13
+ @logger.stubs(:new).returns(@logger)
14
+
15
+ # we stub it out at the top of the test suite
16
+ Log.unstub(:log)
17
+ Log.unstub(:logexception)
18
+ Log.unstub(:logmsg)
19
+
20
+ Log.set_logger(@logger)
13
21
  end
14
22
 
15
- describe "#cofigure" do
23
+ describe "#configure" do
16
24
  it "should default to console logging if called prior to configuration" do
17
25
  Config.instance.instance_variable_set("@configured", false)
18
26
  Log.configure
@@ -28,43 +36,52 @@ module MCollective
28
36
  end
29
37
 
30
38
  describe "#log" do
31
- it "should log at debug level" do
32
- @logger.expects(:log).with(:debug, anything, regexp_matches(/debug test/))
33
- Log.configure(@logger)
34
- Log.debug("debug test")
39
+ it "should log at the right levels" do
40
+ [:debug, :info, :fatal, :error, :warn].each do |level|
41
+ @logger.expects(:log).with(level, anything, regexp_matches(/#{level} test/))
42
+ Log.send(level, "#{level} test")
43
+ end
35
44
  end
45
+ end
36
46
 
37
- it "should log at info level" do
38
- @logger.expects(:log).with(:info, anything, regexp_matches(/info test/))
39
- Log.configure(@logger)
40
- Log.info("info test")
41
- end
47
+ describe "#cycle_level" do
48
+ it "should cycle logger class levels" do
49
+ @logger.expects(:cycle_level)
42
50
 
43
- it "should log at fatal level" do
44
- @logger.expects(:log).with(:fatal, anything, regexp_matches(/fatal test/))
45
51
  Log.configure(@logger)
46
- Log.fatal("fatal test")
52
+ Log.cycle_level
47
53
  end
54
+ end
48
55
 
49
- it "should log at error level" do
50
- @logger.expects(:log).with(:error, anything, regexp_matches(/error test/))
51
- Log.configure(@logger)
52
- Log.error("error test")
56
+ describe "#from" do
57
+ let(:execution_stack) do
58
+ if Util.windows?
59
+ ['C:\rspec\test1:52:in `rspec block1\'',
60
+ 'C:\rspec\test2:52:in `rspec block2\'',
61
+ 'C:\rspec\test3:52:in `rspec block3\'',
62
+ 'C:\rspec\test4:52:in `rspec block4\'']
63
+ else
64
+ ["/rspec/test1:52:in `rspec block1'",
65
+ "/rspec/test2:52:in `rspec block2'",
66
+ "/rspec/test3:52:in `rspec block3'",
67
+ "/rspec/test4:52:in `rspec block4'"]
68
+ end
53
69
  end
54
70
 
55
- it "should log at warning level" do
56
- @logger.expects(:log).with(:warn, anything, regexp_matches(/warn test/))
57
- Log.configure(@logger)
58
- Log.warn("warn test")
71
+ it "should return the correct from string when given file, line, block" do
72
+ Log.stubs(:execution_stack).returns(execution_stack)
73
+ Log.from.should == "test4:52:in `rspec block4'"
59
74
  end
60
- end
61
75
 
62
- describe "#cycle_level" do
63
- it "should cycle logger class levels" do
64
- @logger.expects(:cycle_level)
76
+ it "should return the correct from string shen given file and line" do
77
+ if Util.windows?
78
+ execution_stack[3] = 'C:\rspec\test4:52'
79
+ else
80
+ execution_stack[3] = '/rspec/test4:52'
81
+ end
65
82
 
66
- Log.configure(@logger)
67
- Log.cycle_level
83
+ Log.stubs(:execution_stack).returns(execution_stack)
84
+ Log.from.should == "test4:52"
68
85
  end
69
86
  end
70
87
  end
@@ -23,7 +23,7 @@ module MCollective::Logger
23
23
  end
24
24
 
25
25
  it "should accept correct levels" do
26
- Base.new
26
+ expect { Base.new }.to_not raise_error
27
27
  end
28
28
  end
29
29
 
@@ -117,6 +117,14 @@ module MCollective
117
117
  result = Matcher.execute_function({"name" => "foo", "params" => "bar"})
118
118
  result.should == "success"
119
119
  end
120
+
121
+ it "should return nil if the result cannot be evaluated" do
122
+ data = mock
123
+ data.expects(:send).with("value").raises("error")
124
+ Data.expects(:send).with("foo", "bar").returns(data)
125
+ result = Matcher.execute_function({"name" => "foo", "params" => "bar", "value" => "value"})
126
+ result.should == nil
127
+ end
120
128
  end
121
129
 
122
130
  describe "#eval_compound_statement" do
@@ -170,6 +178,12 @@ module MCollective
170
178
  result = Matcher.eval_compound_fstatement(function_hash)
171
179
  result.should == false
172
180
  end
181
+
182
+ it "should return false immediately if the function execution returns nil" do
183
+ Matcher.expects(:execute_function).returns(nil)
184
+ result = Matcher.eval_compound_fstatement(function_hash)
185
+ result.should == false
186
+ end
173
187
  end
174
188
 
175
189
  describe "it should return false if backticks are present in parameters and if non strings are compared with regex's" do