mcollective-client 1.3.3

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 (103) hide show
  1. data/bin/mc-call-agent +54 -0
  2. data/bin/mco +27 -0
  3. data/lib/mcollective.rb +70 -0
  4. data/lib/mcollective/agents.rb +160 -0
  5. data/lib/mcollective/application.rb +354 -0
  6. data/lib/mcollective/applications.rb +145 -0
  7. data/lib/mcollective/client.rb +292 -0
  8. data/lib/mcollective/config.rb +202 -0
  9. data/lib/mcollective/connector.rb +18 -0
  10. data/lib/mcollective/connector/base.rb +24 -0
  11. data/lib/mcollective/facts.rb +39 -0
  12. data/lib/mcollective/facts/base.rb +86 -0
  13. data/lib/mcollective/log.rb +103 -0
  14. data/lib/mcollective/logger.rb +5 -0
  15. data/lib/mcollective/logger/base.rb +73 -0
  16. data/lib/mcollective/logger/console_logger.rb +61 -0
  17. data/lib/mcollective/logger/file_logger.rb +46 -0
  18. data/lib/mcollective/logger/syslog_logger.rb +53 -0
  19. data/lib/mcollective/matcher.rb +16 -0
  20. data/lib/mcollective/matcher/parser.rb +93 -0
  21. data/lib/mcollective/matcher/scanner.rb +123 -0
  22. data/lib/mcollective/message.rb +201 -0
  23. data/lib/mcollective/monkey_patches.rb +104 -0
  24. data/lib/mcollective/optionparser.rb +164 -0
  25. data/lib/mcollective/pluginmanager.rb +180 -0
  26. data/lib/mcollective/pluginpackager.rb +26 -0
  27. data/lib/mcollective/pluginpackager/agent_definition.rb +79 -0
  28. data/lib/mcollective/pluginpackager/standard_definition.rb +59 -0
  29. data/lib/mcollective/registration.rb +16 -0
  30. data/lib/mcollective/registration/base.rb +75 -0
  31. data/lib/mcollective/rpc.rb +188 -0
  32. data/lib/mcollective/rpc/actionrunner.rb +142 -0
  33. data/lib/mcollective/rpc/agent.rb +441 -0
  34. data/lib/mcollective/rpc/audit.rb +38 -0
  35. data/lib/mcollective/rpc/client.rb +793 -0
  36. data/lib/mcollective/rpc/ddl.rb +258 -0
  37. data/lib/mcollective/rpc/helpers.rb +339 -0
  38. data/lib/mcollective/rpc/progress.rb +63 -0
  39. data/lib/mcollective/rpc/reply.rb +61 -0
  40. data/lib/mcollective/rpc/request.rb +51 -0
  41. data/lib/mcollective/rpc/result.rb +41 -0
  42. data/lib/mcollective/rpc/stats.rb +185 -0
  43. data/lib/mcollective/runnerstats.rb +90 -0
  44. data/lib/mcollective/security.rb +26 -0
  45. data/lib/mcollective/security/base.rb +237 -0
  46. data/lib/mcollective/shell.rb +87 -0
  47. data/lib/mcollective/ssl.rb +246 -0
  48. data/lib/mcollective/unix_daemon.rb +37 -0
  49. data/lib/mcollective/util.rb +274 -0
  50. data/lib/mcollective/vendor.rb +41 -0
  51. data/lib/mcollective/vendor/require_vendored.rb +2 -0
  52. data/lib/mcollective/windows_daemon.rb +25 -0
  53. data/spec/Rakefile +16 -0
  54. data/spec/fixtures/application/test.rb +7 -0
  55. data/spec/fixtures/test-cert.pem +15 -0
  56. data/spec/fixtures/test-private.pem +15 -0
  57. data/spec/fixtures/test-public.pem +6 -0
  58. data/spec/monkey_patches/instance_variable_defined.rb +7 -0
  59. data/spec/spec.opts +1 -0
  60. data/spec/spec_helper.rb +25 -0
  61. data/spec/unit/agents_spec.rb +280 -0
  62. data/spec/unit/application_spec.rb +636 -0
  63. data/spec/unit/applications_spec.rb +155 -0
  64. data/spec/unit/array.rb +30 -0
  65. data/spec/unit/config_spec.rb +148 -0
  66. data/spec/unit/facts/base_spec.rb +118 -0
  67. data/spec/unit/facts_spec.rb +39 -0
  68. data/spec/unit/log_spec.rb +71 -0
  69. data/spec/unit/logger/base_spec.rb +110 -0
  70. data/spec/unit/logger/syslog_logger_spec.rb +86 -0
  71. data/spec/unit/matcher/parser_spec.rb +106 -0
  72. data/spec/unit/matcher/scanner_spec.rb +71 -0
  73. data/spec/unit/message_spec.rb +401 -0
  74. data/spec/unit/optionparser_spec.rb +113 -0
  75. data/spec/unit/pluginmanager_spec.rb +173 -0
  76. data/spec/unit/pluginpackager/agent_definition_spec.rb +130 -0
  77. data/spec/unit/pluginpackager/standard_definition_spec.rb +75 -0
  78. data/spec/unit/plugins/mcollective/connector/activemq_spec.rb +533 -0
  79. data/spec/unit/plugins/mcollective/connector/stomp/eventlogger_spec.rb +34 -0
  80. data/spec/unit/plugins/mcollective/connector/stomp_spec.rb +417 -0
  81. data/spec/unit/plugins/mcollective/packagers/ospackage_spec.rb +229 -0
  82. data/spec/unit/plugins/mcollective/security/psk_spec.rb +156 -0
  83. data/spec/unit/registration/base_spec.rb +77 -0
  84. data/spec/unit/rpc/actionrunner_spec.rb +213 -0
  85. data/spec/unit/rpc/agent_spec.rb +155 -0
  86. data/spec/unit/rpc/client_spec.rb +523 -0
  87. data/spec/unit/rpc/ddl_spec.rb +388 -0
  88. data/spec/unit/rpc/helpers_spec.rb +55 -0
  89. data/spec/unit/rpc/reply_spec.rb +143 -0
  90. data/spec/unit/rpc/request_spec.rb +115 -0
  91. data/spec/unit/rpc/result_spec.rb +66 -0
  92. data/spec/unit/rpc/stats_spec.rb +288 -0
  93. data/spec/unit/runnerstats_spec.rb +40 -0
  94. data/spec/unit/security/base_spec.rb +279 -0
  95. data/spec/unit/shell_spec.rb +144 -0
  96. data/spec/unit/ssl_spec.rb +244 -0
  97. data/spec/unit/symbol.rb +11 -0
  98. data/spec/unit/unix_daemon.rb +41 -0
  99. data/spec/unit/util_spec.rb +342 -0
  100. data/spec/unit/vendor_spec.rb +34 -0
  101. data/spec/unit/windows_daemon.rb +43 -0
  102. data/spec/windows_spec.opts +1 -0
  103. metadata +242 -0
@@ -0,0 +1,34 @@
1
+ #!/usr/bin/env rspec
2
+
3
+ require 'spec_helper'
4
+
5
+ MCollective::PluginManager.clear
6
+
7
+ require File.dirname(__FILE__) + '/../../../../../../plugins/mcollective/connector/stomp.rb'
8
+
9
+ module MCollective
10
+ module Connector
11
+ class Stomp
12
+ describe EventLogger do
13
+ before do
14
+ end
15
+
16
+ it "should have valid call back methods" do
17
+ plugin = EventLogger.new
18
+
19
+ [:on_miscerr, :on_connecting, :on_connected, :on_disconnect, :on_connectfail, :on_ssl_connecting, :on_ssl_connected].each do |meth|
20
+ plugin.respond_to?(meth).should == true
21
+ end
22
+ end
23
+
24
+ describe "#stomp_url" do
25
+ it "should create valid stomp urls" do
26
+ EventLogger.new.stomp_url({:cur_login => "rspec", :cur_host => "localhost", :cur_port => 123}).should == "stomp://rspec@localhost:123"
27
+ EventLogger.new.stomp_url({:cur_login => "rspec", :cur_host => "localhost", :cur_port => 123, :cur_ssl => false}).should == "stomp://rspec@localhost:123"
28
+ EventLogger.new.stomp_url({:cur_login => "rspec", :cur_host => "localhost", :cur_port => 123, :cur_ssl => true}).should == "stomp+ssl://rspec@localhost:123"
29
+ end
30
+ end
31
+ end
32
+ end
33
+ end
34
+ end
@@ -0,0 +1,417 @@
1
+ #!/usr/bin/env rspec
2
+
3
+ require 'spec_helper'
4
+
5
+ MCollective::PluginManager.clear
6
+
7
+ require File.dirname(__FILE__) + '/../../../../../plugins/mcollective/connector/stomp.rb'
8
+
9
+ module MCollective
10
+ module Connector
11
+ describe Stomp do
12
+ before do
13
+ unless ::Stomp::Error.constants.map{|c| c.to_s}.include?("NoCurrentConnection")
14
+ class ::Stomp::Error::NoCurrentConnection < RuntimeError ; end
15
+ end
16
+
17
+ @config = mock
18
+ @config.stubs(:configured).returns(true)
19
+ @config.stubs(:identity).returns("rspec")
20
+ @config.stubs(:collectives).returns(["mcollective"])
21
+ @config.stubs(:topicprefix).returns("/topic/")
22
+ @config.stubs(:topicsep).returns(".")
23
+
24
+ logger = mock
25
+ logger.stubs(:log)
26
+ logger.stubs(:start)
27
+ Log.configure(logger)
28
+
29
+ Config.stubs(:instance).returns(@config)
30
+
31
+ @msg = mock
32
+ @msg.stubs(:base64_encode!)
33
+ @msg.stubs(:payload).returns("msg")
34
+ @msg.stubs(:agent).returns("agent")
35
+ @msg.stubs(:type).returns(:reply)
36
+ @msg.stubs(:collective).returns("mcollective")
37
+
38
+ @subscription = mock
39
+ @subscription.stubs("<<").returns(true)
40
+ @subscription.stubs("include?").returns(false)
41
+ @subscription.stubs("delete").returns(false)
42
+
43
+ @connection = mock
44
+ @connection.stubs(:subscribe).returns(true)
45
+ @connection.stubs(:unsubscribe).returns(true)
46
+
47
+ @c = Stomp.new
48
+ @c.instance_variable_set("@subscriptions", @subscription)
49
+ @c.instance_variable_set("@connection", @connection)
50
+ end
51
+
52
+ describe "#initialize" do
53
+ it "should set the @config variable" do
54
+ c = Stomp.new
55
+ c.instance_variable_get("@config").should == @config
56
+ end
57
+
58
+ it "should set @subscriptions to an empty list" do
59
+ c = Stomp.new
60
+ c.instance_variable_get("@subscriptions").should == []
61
+ end
62
+ end
63
+
64
+ describe "#connect" do
65
+ it "should not try to reconnect if already connected" do
66
+ Log.expects(:debug).with("Already connection, not re-initializing connection").once
67
+ @c.connect
68
+ end
69
+
70
+ it "should support old style config" do
71
+ @config.expects(:pluginconf).returns({}).at_least_once
72
+ @c.expects(:get_bool_option).with("stomp.base64", false)
73
+ @c.expects(:get_option).with("stomp.priority", 0)
74
+ @c.expects(:get_env_or_option).with("STOMP_SERVER", "stomp.host").returns("host")
75
+ @c.expects(:get_env_or_option).with("STOMP_PORT", "stomp.port", 6163).returns(6163)
76
+ @c.expects(:get_env_or_option).with("STOMP_USER", "stomp.user").returns("test_user")
77
+ @c.expects(:get_env_or_option).with("STOMP_PASSWORD", "stomp.password").returns("test_password")
78
+
79
+ connector = mock
80
+ connector.expects(:new).with("test_user", "test_password", "host", 6163, true)
81
+
82
+ @c.instance_variable_set("@connection", nil)
83
+ @c.connect(connector)
84
+ end
85
+
86
+ it "should support new style config" do
87
+ pluginconf = {"stomp.pool.size" => "2",
88
+ "stomp.pool.host1" => "host1",
89
+ "stomp.pool.port1" => "6163",
90
+ "stomp.pool.user1" => "user1",
91
+ "stomp.pool.password1" => "password1",
92
+ "stomp.pool.ssl1" => "false",
93
+ "stomp.pool.host2" => "host2",
94
+ "stomp.pool.port2" => "6164",
95
+ "stomp.pool.user2" => "user2",
96
+ "stomp.pool.password2" => "password2",
97
+ "stomp.pool.ssl2" => "true",
98
+ "stomp.pool.initial_reconnect_delay" => "0.02",
99
+ "stomp.pool.max_reconnect_delay" => "40",
100
+ "stomp.pool.use_exponential_back_off" => "false",
101
+ "stomp.pool.back_off_multiplier" => "3",
102
+ "stomp.pool.max_reconnect_attempts" => "5",
103
+ "stomp.pool.randomize" => "true",
104
+ "stomp.pool.backup" => "true",
105
+ "stomp.pool.timeout" => "1"}
106
+
107
+
108
+ ENV.delete("STOMP_USER")
109
+ ENV.delete("STOMP_PASSWORD")
110
+
111
+ @config.expects(:pluginconf).returns(pluginconf).at_least_once
112
+
113
+ Stomp::EventLogger.expects(:new).returns("logger")
114
+
115
+ connector = mock
116
+ connector.expects(:new).with(:backup => true,
117
+ :back_off_multiplier => 2,
118
+ :max_reconnect_delay => 40.0,
119
+ :timeout => 1,
120
+ :use_exponential_back_off => false,
121
+ :max_reconnect_attempts => 5,
122
+ :initial_reconnect_delay => 0.02,
123
+ :randomize => true,
124
+ :reliable => true,
125
+ :logger => "logger",
126
+ :hosts => [{:passcode => 'password1',
127
+ :host => 'host1',
128
+ :port => 6163,
129
+ :ssl => false,
130
+ :login => 'user1'},
131
+ {:passcode => 'password2',
132
+ :host => 'host2',
133
+ :port => 6164,
134
+ :ssl => true,
135
+ :login => 'user2'}
136
+ ])
137
+
138
+ @c.instance_variable_set("@connection", nil)
139
+ @c.connect(connector)
140
+ end
141
+ end
142
+
143
+ describe "#receive" do
144
+ it "should receive from the middleware" do
145
+ payload = mock
146
+ payload.stubs(:body).returns("msg")
147
+ payload.stubs(:headers).returns("headers")
148
+
149
+ @connection.expects(:receive).returns(payload)
150
+
151
+ Message.expects(:new).with("msg", payload, :base64 => true, :headers => "headers").returns("message")
152
+ @c.instance_variable_set("@base64", true)
153
+
154
+ received = @c.receive
155
+ received.should == "message"
156
+ end
157
+
158
+ it "should sleep and retry if recieving while disconnected" do
159
+ payload = mock
160
+ payload.stubs(:body).returns("msg")
161
+ payload.stubs(:headers).returns("headers")
162
+
163
+ Message.stubs(:new).returns("rspec")
164
+ @connection.expects(:receive).raises(::Stomp::Error::NoCurrentConnection).returns(payload).twice
165
+ @c.expects(:sleep).with(1)
166
+
167
+ @c.receive.should == "rspec"
168
+ end
169
+ end
170
+
171
+ describe "#publish" do
172
+ before do
173
+ @connection.stubs("respond_to?").with("publish").returns(true)
174
+ @connection.stubs(:publish).with("test", "msg", {}).returns(true)
175
+ end
176
+
177
+ it "should base64 encode a message if configured to do so" do
178
+ @c.instance_variable_set("@base64", true)
179
+ @c.expects(:msgheaders).returns({})
180
+ @c.expects(:make_target).returns("test")
181
+ @connection.expects(:publish).with("test", "msg", {})
182
+
183
+ @msg.stubs(:reply_to)
184
+
185
+ @c.publish(@msg)
186
+ end
187
+
188
+ it "should not base64 encode if not configured to do so" do
189
+ @c.instance_variable_set("@base64", false)
190
+ @c.expects(:msgheaders).returns({})
191
+ @c.expects(:make_target).returns("test")
192
+
193
+ @connection.expects(:publish).with("test", "msg", {})
194
+
195
+ @msg.stubs(:reply_to)
196
+
197
+ @c.publish(@msg)
198
+ end
199
+
200
+ it "should publish direct requests for each discovered host" do
201
+ @msg.expects(:type).returns(:direct_request).times(3)
202
+ @msg.expects(:discovered_hosts).returns(["one", "two"])
203
+
204
+ @c.expects(:make_target).with("agent", :direct_request, "mcollective", "one").returns("target_one")
205
+ @c.expects(:make_target).with("agent", :direct_request, "mcollective", "two").returns("target_two")
206
+
207
+ @c.expects(:publish_msg).with("target_one", "msg")
208
+ @c.expects(:publish_msg).with("target_two", "msg")
209
+
210
+ @msg.stubs(:reply_to)
211
+
212
+ @c.publish(@msg)
213
+ end
214
+
215
+ it "should raise an error if specific reply targets are requested" do
216
+ @c.instance_variable_set("@base64", false)
217
+
218
+ @msg.expects(:reply_to).returns(:foo)
219
+
220
+ expect { @c.publish(@msg) }.to raise_error("Cannot set specific reply to targets with the STOMP plugin")
221
+ end
222
+ end
223
+
224
+ describe "#publish_msg" do
225
+ it "should use the publish method if it exists" do
226
+ @connection.expects("respond_to?").with("publish").returns(true)
227
+ @connection.expects(:publish).with("test", "msg", {}).once
228
+ @c.stubs(:msgheaders).returns({})
229
+
230
+ @c.publish_msg("test", "msg")
231
+ end
232
+
233
+ it "should use the send method if publish does not exist" do
234
+ @connection.expects("respond_to?").with('publish').returns(false)
235
+ @connection.expects(:send).with("test", "msg", {}).once
236
+ @c.stubs(:msgheaders).returns({})
237
+
238
+ @c.publish_msg("test", "msg")
239
+ end
240
+
241
+ it "should publish the correct message to the correct target with msgheaders" do
242
+ @connection.expects("respond_to?").with("publish").returns(true)
243
+ @connection.expects(:publish).with("test", "msg", {"test" => "test"}).once
244
+ @c.expects(:msgheaders).returns({"test" => "test"})
245
+
246
+ @c.publish_msg("test", "msg")
247
+ end
248
+
249
+ end
250
+
251
+ describe "#make_target" do
252
+ it "should create correct targets" do
253
+ @config.expects(:queueprefix).returns("/queue/").twice
254
+
255
+ @c.make_target("test", :broadcast, "mcollective").should == "/topic/mcollective.test.command"
256
+ @c.make_target("test", :directed, "mcollective").should == "/queue/mcollective.2bc84dc69b73db9383b9c6711d2011b7"
257
+ @c.make_target("test", :direct_request, "mcollective", "rspec").should == "/queue/mcollective.2bc84dc69b73db9383b9c6711d2011b7"
258
+ @c.make_target("test", :reply, "mcollective").should == "/topic/mcollective.test.reply"
259
+ @c.make_target("test", :request, "mcollective").should == "/topic/mcollective.test.command"
260
+ end
261
+
262
+ it "should raise an error for unknown collectives" do
263
+ expect {
264
+ @c.make_target("test", :broadcast, "foo")
265
+ }.to raise_error("Unknown collective 'foo' known collectives are 'mcollective'")
266
+ end
267
+
268
+ it "should raise an error for unknown types" do
269
+ expect {
270
+ @c.make_target("test", :test, "mcollective")
271
+ }.to raise_error("Unknown target type test")
272
+ end
273
+ end
274
+
275
+ describe "#unsubscribe" do
276
+ it "should use make_target correctly" do
277
+ @c.expects("make_target").with("test", :broadcast, "mcollective").returns({:target => "test", :headers => {}})
278
+ @c.unsubscribe("test", :broadcast, "mcollective")
279
+ end
280
+
281
+ it "should unsubscribe from the target" do
282
+ @c.expects("make_target").with("test", :broadcast, "mcollective").returns("test")
283
+ @connection.expects(:unsubscribe).with("test").once
284
+
285
+ @c.unsubscribe("test", :broadcast, "mcollective")
286
+ end
287
+
288
+ it "should delete the source from subscriptions" do
289
+ @c.expects("make_target").with("test", :broadcast, "mcollective").returns({:target => "test", :headers => {}})
290
+ @subscription.expects(:delete).with({:target => "test", :headers => {}}).once
291
+
292
+ @c.unsubscribe("test", :broadcast, "mcollective")
293
+ end
294
+ end
295
+
296
+ describe "#subscribe" do
297
+ it "should use the make_target correctly" do
298
+ @c.expects("make_target").with("test", :broadcast, "mcollective").returns("test")
299
+ @c.subscribe("test", :broadcast, "mcollective")
300
+ end
301
+
302
+ it "should check for existing subscriptions" do
303
+ @c.expects("make_target").returns("test").once
304
+ @subscription.expects("include?").with("test").returns(false)
305
+ @connection.expects(:subscribe).never
306
+
307
+ @c.subscribe("test", :broadcast, "mcollective")
308
+ end
309
+
310
+ it "should subscribe to the middleware" do
311
+ @c.expects("make_target").returns("test")
312
+ @connection.expects(:subscribe).with("test").once
313
+ @c.subscribe("test", :broadcast, "mcollective")
314
+ end
315
+
316
+ it "should add to the list of subscriptions" do
317
+ @c.expects("make_target").returns("test")
318
+ @subscription.expects("<<").with("test")
319
+ @c.subscribe("test", :broadcast, "mcollective")
320
+ end
321
+ end
322
+
323
+ describe "#disconnect" do
324
+ it "should disconnect from the stomp connection" do
325
+ @connection.expects(:disconnect)
326
+ @c.disconnect
327
+ end
328
+ end
329
+
330
+ describe "#msgheaders" do
331
+ it "should return empty headers if priority is 0" do
332
+ @c.instance_variable_set("@msgpriority", 0)
333
+ @c.msgheaders.should == {}
334
+ end
335
+
336
+ it "should return a priority if prioritu is non 0" do
337
+ @c.instance_variable_set("@msgpriority", 1)
338
+ @c.msgheaders.should == {"priority" => 1}
339
+ end
340
+ end
341
+
342
+ describe "#get_env_or_option" do
343
+ it "should return the environment variable if set" do
344
+ ENV["test"] = "rspec_env_test"
345
+
346
+ @c.get_env_or_option("test", nil, nil).should == "rspec_env_test"
347
+
348
+ ENV.delete("test")
349
+ end
350
+
351
+ it "should return the config option if set" do
352
+ @config.expects(:pluginconf).returns({"test" => "rspec_test"}).twice
353
+ @c.get_env_or_option("test", "test", "test").should == "rspec_test"
354
+ end
355
+
356
+ it "should return default if nothing else matched" do
357
+ @config.expects(:pluginconf).returns({}).once
358
+ @c.get_env_or_option("test", "test", "test").should == "test"
359
+ end
360
+
361
+ it "should raise an error if no default is supplied" do
362
+ @config.expects(:pluginconf).returns({}).once
363
+
364
+ expect {
365
+ @c.get_env_or_option("test", "test")
366
+ }.to raise_error("No test environment or plugin.test configuration option given")
367
+ end
368
+ end
369
+
370
+ describe "#get_option" do
371
+ it "should return the config option if set" do
372
+ @config.expects(:pluginconf).returns({"test" => "rspec_test"}).twice
373
+ @c.get_option("test").should == "rspec_test"
374
+ end
375
+
376
+ it "should return default option was not found" do
377
+ @config.expects(:pluginconf).returns({}).once
378
+ @c.get_option("test", "test").should == "test"
379
+ end
380
+
381
+ it "should raise an error if no default is supplied" do
382
+ @config.expects(:pluginconf).returns({}).once
383
+
384
+ expect {
385
+ @c.get_option("test")
386
+ }.to raise_error("No plugin.test configuration option given")
387
+ end
388
+ end
389
+
390
+ describe "#get_bool_option" do
391
+ it "should return the default if option isnt set" do
392
+ @config.expects(:pluginconf).returns({}).once
393
+ @c.get_bool_option("test", "default").should == "default"
394
+ end
395
+
396
+ ["1", "yes", "true"].each do |boolean|
397
+ it "should map options to true correctly" do
398
+ @config.expects(:pluginconf).returns({"test" => boolean}).twice
399
+ @c.get_bool_option("test", "default").should == true
400
+ end
401
+ end
402
+
403
+ ["0", "no", "false"].each do |boolean|
404
+ it "should map options to false correctly" do
405
+ @config.expects(:pluginconf).returns({"test" => boolean}).twice
406
+ @c.get_bool_option("test", "default").should == false
407
+ end
408
+ end
409
+
410
+ it "should return default for non boolean options" do
411
+ @config.expects(:pluginconf).returns({"test" => "foo"}).twice
412
+ @c.get_bool_option("test", "default").should == "default"
413
+ end
414
+ end
415
+ end
416
+ end
417
+ end