mcollective-client 2.5.3 → 2.6.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- data/lib/mcollective.rb +1 -1
- data/lib/mcollective/application.rb +21 -6
- data/lib/mcollective/client.rb +7 -0
- data/lib/mcollective/config.rb +13 -1
- data/lib/mcollective/connector/base.rb +2 -0
- data/lib/mcollective/facts/base.rb +18 -5
- data/lib/mcollective/log.rb +7 -0
- data/lib/mcollective/logger/base.rb +12 -8
- data/lib/mcollective/logger/file_logger.rb +7 -0
- data/lib/mcollective/message.rb +1 -1
- data/lib/mcollective/optionparser.rb +4 -0
- data/lib/mcollective/registration/base.rb +24 -10
- data/lib/mcollective/rpc/agent.rb +7 -1
- data/lib/mcollective/rpc/client.rb +89 -35
- data/lib/mcollective/rpc/helpers.rb +8 -3
- data/lib/mcollective/rpc/result.rb +4 -0
- data/lib/mcollective/rpc/stats.rb +6 -2
- data/lib/mcollective/shell.rb +2 -0
- data/lib/mcollective/ssl.rb +5 -0
- data/lib/mcollective/util.rb +29 -1
- data/lib/mcollective/validator.rb +9 -4
- data/spec/spec_helper.rb +6 -0
- data/spec/unit/config_spec.rb +10 -0
- data/spec/unit/connector/base_spec.rb +28 -0
- data/spec/unit/facts/base_spec.rb +35 -0
- data/spec/unit/log_spec.rb +9 -0
- data/spec/unit/logger/base_spec.rb +12 -2
- data/spec/unit/logger/file_logger_spec.rb +82 -0
- data/spec/unit/plugins/mcollective/application/plugin_spec.rb +1 -0
- data/spec/unit/plugins/mcollective/connector/activemq_spec.rb +44 -17
- data/spec/unit/plugins/mcollective/connector/rabbitmq_spec.rb +20 -19
- data/spec/unit/plugins/mcollective/data/fact_data_spec.rb +92 -0
- data/spec/unit/registration/base_spec.rb +46 -0
- data/spec/unit/rpc/agent_spec.rb +37 -0
- data/spec/unit/rpc/client_spec.rb +68 -15
- data/spec/unit/rpc/result_spec.rb +21 -0
- data/spec/unit/runner_spec.rb +97 -19
- data/spec/unit/shell_spec.rb +5 -0
- data/spec/unit/ssl_spec.rb +5 -0
- data/spec/unit/util_spec.rb +163 -1
- metadata +215 -209
@@ -264,9 +264,14 @@ module MCollective
|
|
264
264
|
parser.on('--one', '-1', 'Send request to only one discovered nodes') do |v|
|
265
265
|
options[:mcollective_limit_targets] = 1
|
266
266
|
end
|
267
|
-
|
268
|
-
parser.on('--batch SIZE',
|
269
|
-
|
267
|
+
|
268
|
+
parser.on('--batch SIZE', 'Do requests in batches') do |v|
|
269
|
+
# validate batch string. Is it x% where x > 0 or is it an integer
|
270
|
+
if ((v =~ /^(\d+)%$/ && Integer($1) != 0) || v =~ /^(\d+)$/)
|
271
|
+
options[:batch_size] = v
|
272
|
+
else
|
273
|
+
raise(::OptionParser::InvalidArgument.new(v))
|
274
|
+
end
|
270
275
|
end
|
271
276
|
|
272
277
|
parser.on('--batch-sleep SECONDS', Float, 'Sleep time between batches') do |v|
|
@@ -242,8 +242,12 @@ module MCollective
|
|
242
242
|
result_text.puts Util.colorize(:red, "No response from:")
|
243
243
|
result_text.puts
|
244
244
|
|
245
|
-
@noresponsefrom
|
246
|
-
|
245
|
+
field_size = Util.field_size(@noresponsefrom, 30)
|
246
|
+
fields_num = Util.field_number(field_size)
|
247
|
+
format = " " + ( " %-#{field_size}s" * fields_num )
|
248
|
+
|
249
|
+
@noresponsefrom.sort.in_groups_of(fields_num) do |c|
|
250
|
+
result_text.puts format % c
|
247
251
|
end
|
248
252
|
|
249
253
|
result_text.puts
|
data/lib/mcollective/shell.rb
CHANGED
@@ -57,7 +57,9 @@ module MCollective
|
|
57
57
|
@environment = {}
|
58
58
|
else
|
59
59
|
@environment.merge!(val.dup)
|
60
|
+
@environment = @environment.delete_if { |k,v| v.nil? }
|
60
61
|
end
|
62
|
+
|
61
63
|
when "timeout"
|
62
64
|
raise "timeout should be a positive integer or the symbol :on_thread_exit symbol" unless val.eql?(:on_thread_exit) || ( val.is_a?(Fixnum) && val>0 )
|
63
65
|
@timeout = val
|
data/lib/mcollective/ssl.rb
CHANGED
@@ -193,6 +193,11 @@ module MCollective
|
|
193
193
|
end
|
194
194
|
|
195
195
|
def self.base64_decode(string)
|
196
|
+
# The Base 64 character set is A-Z a-z 0-9 + / =
|
197
|
+
# Also allow for whitespace, but raise if we get anything else
|
198
|
+
if string !~ /^[A-Za-z0-9+\/=\s]+$/
|
199
|
+
raise ArgumentError, 'invalid base64'
|
200
|
+
end
|
196
201
|
Base64.decode64(string)
|
197
202
|
end
|
198
203
|
|
data/lib/mcollective/util.rb
CHANGED
@@ -75,11 +75,21 @@ module MCollective
|
|
75
75
|
return false if fact.nil?
|
76
76
|
|
77
77
|
fact = fact.clone
|
78
|
+
case fact
|
79
|
+
when Array
|
80
|
+
return fact.any? { |element| test_fact_value(element, value, operator)}
|
81
|
+
when Hash
|
82
|
+
return fact.keys.any? { |element| test_fact_value(element, value, operator)}
|
83
|
+
else
|
84
|
+
return test_fact_value(fact, value, operator)
|
85
|
+
end
|
86
|
+
end
|
78
87
|
|
88
|
+
def self.test_fact_value(fact, value, operator)
|
79
89
|
if operator == '=~'
|
80
90
|
# to maintain backward compat we send the value
|
81
91
|
# as /.../ which is what 1.0.x needed. this strips
|
82
|
-
# off the /'s
|
92
|
+
# off the /'s which is what we need here
|
83
93
|
if value =~ /^\/(.+)\/$/
|
84
94
|
value = $1
|
85
95
|
end
|
@@ -104,6 +114,7 @@ module MCollective
|
|
104
114
|
|
105
115
|
false
|
106
116
|
end
|
117
|
+
private_class_method :test_fact_value
|
107
118
|
|
108
119
|
# Checks if the configured identity matches the one supplied
|
109
120
|
#
|
@@ -492,5 +503,22 @@ module MCollective
|
|
492
503
|
template_path = File.join("/etc/mcollective", template_file)
|
493
504
|
return template_path
|
494
505
|
end
|
506
|
+
|
507
|
+
# subscribe to the direct addressing queue
|
508
|
+
def self.subscribe_to_direct_addressing_queue
|
509
|
+
subscribe(make_subscriptions("mcollective", :directed))
|
510
|
+
end
|
511
|
+
|
512
|
+
# Get field size for printing
|
513
|
+
def self.field_size(elements, min_size=40)
|
514
|
+
max_length = elements.max_by { |e| e.length }.length
|
515
|
+
max_length > min_size ? max_length : min_size
|
516
|
+
end
|
517
|
+
|
518
|
+
# Calculate number of fields for printing
|
519
|
+
def self.field_number(field_size, max_size=90)
|
520
|
+
number = (max_size/field_size).to_i
|
521
|
+
(number == 0) ? 1 : number
|
522
|
+
end
|
495
523
|
end
|
496
524
|
end
|
@@ -1,12 +1,18 @@
|
|
1
1
|
module MCollective
|
2
2
|
module Validator
|
3
3
|
@last_load = nil
|
4
|
+
@@validator_mutex = Mutex.new
|
4
5
|
|
5
6
|
# Loads the validator plugins. Validators will only be loaded every 5 minutes
|
6
7
|
def self.load_validators
|
7
|
-
|
8
|
-
|
9
|
-
|
8
|
+
begin
|
9
|
+
@@validator_mutex.lock
|
10
|
+
if load_validators?
|
11
|
+
@last_load = Time.now.to_i
|
12
|
+
PluginManager.find_and_load("validator")
|
13
|
+
end
|
14
|
+
ensure
|
15
|
+
@@validator_mutex.unlock
|
10
16
|
end
|
11
17
|
end
|
12
18
|
|
@@ -44,7 +50,6 @@ module MCollective
|
|
44
50
|
|
45
51
|
def self.load_validators?
|
46
52
|
return true if @last_load.nil?
|
47
|
-
|
48
53
|
(@last_load - Time.now.to_i) > 300
|
49
54
|
end
|
50
55
|
|
data/spec/spec_helper.rb
CHANGED
@@ -28,3 +28,9 @@ RSpec.configure do |config|
|
|
28
28
|
MCollective::PluginManager.clear
|
29
29
|
end
|
30
30
|
end
|
31
|
+
|
32
|
+
# With the addition of the ddl requirement for connectors its becomes necessary
|
33
|
+
# to stub the inherited method. Because tests don't use a real config files libdirs
|
34
|
+
# aren't set and connectors have no way of finding their ddls so we stub it out
|
35
|
+
# in the general case and test for is specifically.
|
36
|
+
MCollective::Connector::Base.stubs(:inherited)
|
data/spec/unit/config_spec.rb
CHANGED
@@ -141,6 +141,16 @@ module MCollective
|
|
141
141
|
Config.instance.loadconfig("/nonexisting")
|
142
142
|
end
|
143
143
|
end
|
144
|
+
|
145
|
+
it 'should enable agents by default' do
|
146
|
+
File.expects(:readlines).with("/nonexisting").returns(["libdir=/nonexistinglib"])
|
147
|
+
File.expects(:exists?).with("/nonexisting").returns(true)
|
148
|
+
PluginManager.stubs(:loadclass)
|
149
|
+
PluginManager.stubs("<<")
|
150
|
+
|
151
|
+
Config.instance.loadconfig("/nonexisting")
|
152
|
+
Config.instance.activate_agents.should == true
|
153
|
+
end
|
144
154
|
end
|
145
155
|
|
146
156
|
describe "#read_plugin_config_dir" do
|
@@ -0,0 +1,28 @@
|
|
1
|
+
#!/usr/bin/env rspec
|
2
|
+
|
3
|
+
require 'spec_helper'
|
4
|
+
|
5
|
+
module MCollective
|
6
|
+
module Connector
|
7
|
+
describe "base" do
|
8
|
+
|
9
|
+
before :each do
|
10
|
+
Base.unstub(:inherited)
|
11
|
+
end
|
12
|
+
|
13
|
+
it "should fail if the ddl isn't valid" do
|
14
|
+
PluginManager.expects(:<<).never
|
15
|
+
|
16
|
+
expect {
|
17
|
+
class TestConnectorA<Connector::Base;end
|
18
|
+
}.to raise_error RuntimeError
|
19
|
+
end
|
20
|
+
|
21
|
+
it "should load the ddl and add the connector to the PluginManager" do
|
22
|
+
DDL.stubs(:new)
|
23
|
+
class TestConnectorB<Connector::Base;end
|
24
|
+
PluginManager["connector_plugin"].class.should == MCollective::Connector::TestConnectorB
|
25
|
+
end
|
26
|
+
end
|
27
|
+
end
|
28
|
+
end
|
@@ -114,5 +114,40 @@ module MCollective::Facts
|
|
114
114
|
end
|
115
115
|
end
|
116
116
|
|
117
|
+
describe '#normalize_facts' do
|
118
|
+
it 'should make symbols that are keys be strings' do
|
119
|
+
Testfacts.new.send(:normalize_facts, {
|
120
|
+
:foo => "1",
|
121
|
+
"bar" => "2",
|
122
|
+
}).should == {
|
123
|
+
"foo" => "1",
|
124
|
+
"bar" => "2",
|
125
|
+
}
|
126
|
+
end
|
127
|
+
|
128
|
+
it 'should make values that are not strings be strings' do
|
129
|
+
Testfacts.new.send(:normalize_facts, {
|
130
|
+
"foo" => 1,
|
131
|
+
"bar" => :baz,
|
132
|
+
}).should == {
|
133
|
+
"foo" => "1",
|
134
|
+
"bar" => "baz",
|
135
|
+
}
|
136
|
+
end
|
137
|
+
|
138
|
+
it 'should not flatten arrays or hashes' do
|
139
|
+
Testfacts.new.send(:normalize_facts, {
|
140
|
+
"foo" => [ "1", "quux", 2 ],
|
141
|
+
"bar" => {
|
142
|
+
:baz => "quux",
|
143
|
+
},
|
144
|
+
}).should == {
|
145
|
+
"foo" => [ "1", "quux", "2" ],
|
146
|
+
"bar" => {
|
147
|
+
"baz" => "quux",
|
148
|
+
},
|
149
|
+
}
|
150
|
+
end
|
151
|
+
end
|
117
152
|
end
|
118
153
|
end
|
data/spec/unit/log_spec.rb
CHANGED
@@ -53,6 +53,15 @@ module MCollective
|
|
53
53
|
end
|
54
54
|
end
|
55
55
|
|
56
|
+
describe '#reopen' do
|
57
|
+
it 'should delegate the the logger' do
|
58
|
+
@logger.expects(:reopen)
|
59
|
+
|
60
|
+
Log.configure(@logger)
|
61
|
+
Log.reopen
|
62
|
+
end
|
63
|
+
end
|
64
|
+
|
56
65
|
describe "#from" do
|
57
66
|
let(:execution_stack) do
|
58
67
|
if Util.windows?
|
@@ -42,7 +42,7 @@ module MCollective::Logger
|
|
42
42
|
logger = Base.new
|
43
43
|
|
44
44
|
expect {
|
45
|
-
logger.
|
45
|
+
logger.log(nil, nil, nil)
|
46
46
|
}.to raise_error("The logging class did not supply a log method")
|
47
47
|
end
|
48
48
|
end
|
@@ -52,11 +52,21 @@ module MCollective::Logger
|
|
52
52
|
logger = Base.new
|
53
53
|
|
54
54
|
expect {
|
55
|
-
logger.
|
55
|
+
logger.start
|
56
56
|
}.to raise_error("The logging class did not supply a start method")
|
57
57
|
end
|
58
58
|
end
|
59
59
|
|
60
|
+
describe '#reopen' do
|
61
|
+
it 'should do nothing' do
|
62
|
+
logger = Base.new
|
63
|
+
|
64
|
+
expect {
|
65
|
+
logger.reopen
|
66
|
+
}.to_not raise_error
|
67
|
+
end
|
68
|
+
end
|
69
|
+
|
60
70
|
describe "#map_level" do
|
61
71
|
it "should map levels correctly" do
|
62
72
|
logger = Base.new
|
@@ -0,0 +1,82 @@
|
|
1
|
+
#!/usr/bin/env rspec
|
2
|
+
|
3
|
+
require 'spec_helper'
|
4
|
+
|
5
|
+
module MCollective
|
6
|
+
require 'mcollective/logger/file_logger'
|
7
|
+
|
8
|
+
module Logger
|
9
|
+
describe File_logger do
|
10
|
+
let(:mock_logger) { mock('logger') }
|
11
|
+
|
12
|
+
before :each do
|
13
|
+
Config.instance.stubs(:loglevel).returns("error")
|
14
|
+
Config.instance.stubs(:logfile).returns("testfile")
|
15
|
+
Config.instance.stubs(:keeplogs).returns(false)
|
16
|
+
Config.instance.stubs(:max_log_size).returns(42)
|
17
|
+
::Logger.stubs(:new).returns(mock_logger)
|
18
|
+
mock_logger.stubs(:formatter=)
|
19
|
+
mock_logger.stubs(:level=)
|
20
|
+
end
|
21
|
+
|
22
|
+
describe "#start" do
|
23
|
+
it "should set the level to be that specfied in the config" do
|
24
|
+
logger = File_logger.new
|
25
|
+
|
26
|
+
logger.expects(:set_level).with(:error)
|
27
|
+
logger.start
|
28
|
+
end
|
29
|
+
end
|
30
|
+
|
31
|
+
describe 'reopen' do
|
32
|
+
let(:logger) {
|
33
|
+
logger = File_logger.new
|
34
|
+
logger.instance_variable_set(:@logger, mock_logger)
|
35
|
+
logger
|
36
|
+
}
|
37
|
+
|
38
|
+
before :each do
|
39
|
+
mock_logger.stubs(:level)
|
40
|
+
mock_logger.stubs(:close)
|
41
|
+
logger.stubs(:start)
|
42
|
+
mock_logger.stubs(:level=)
|
43
|
+
end
|
44
|
+
|
45
|
+
it 'should close the current handle' do
|
46
|
+
mock_logger.expects(:close)
|
47
|
+
logger.reopen
|
48
|
+
end
|
49
|
+
|
50
|
+
it 'should open a new handle' do
|
51
|
+
logger.expects(:start)
|
52
|
+
logger.reopen
|
53
|
+
end
|
54
|
+
|
55
|
+
it 'should preserve the level' do
|
56
|
+
mock_logger.expects(:level).returns(12252)
|
57
|
+
mock_logger.expects(:level=).with(12252)
|
58
|
+
logger.reopen
|
59
|
+
end
|
60
|
+
end
|
61
|
+
|
62
|
+
describe '#set_logging_level' do
|
63
|
+
it 'should set the level' do
|
64
|
+
logger = File_logger.new
|
65
|
+
logger.instance_variable_set(:@logger, mock_logger)
|
66
|
+
mock_logger.expects(:level=).with(::Logger::ERROR)
|
67
|
+
logger.set_level("error")
|
68
|
+
end
|
69
|
+
end
|
70
|
+
|
71
|
+
describe "#log" do
|
72
|
+
it "should delegate to logger" do
|
73
|
+
logger = File_logger.new
|
74
|
+
logger.instance_variable_set(:@logger, mock_logger)
|
75
|
+
|
76
|
+
mock_logger.expects(:add).with(::Logger::INFO)
|
77
|
+
logger.log(:info, "rspec", "message")
|
78
|
+
end
|
79
|
+
end
|
80
|
+
end
|
81
|
+
end
|
82
|
+
end
|
@@ -22,6 +22,7 @@ module MCollective
|
|
22
22
|
PluginManager.stubs(:find).with(:data, "ddl").returns([""])
|
23
23
|
PluginManager.stubs(:find).with(:discovery, "ddl").returns([""])
|
24
24
|
PluginManager.stubs(:find).with(:validator, "ddl").returns([""])
|
25
|
+
PluginManager.stubs(:find).with(:connector, "ddl").returns([""])
|
25
26
|
@app.stubs(:load_plugin_ddl).with('rspec', :agent).returns(ddl)
|
26
27
|
ddl.expects(:help).with("rspec-helptemplate.erb").returns("agent_template")
|
27
28
|
@app.expects(:puts).with("agent_template")
|
@@ -47,9 +47,9 @@ module MCollective
|
|
47
47
|
|
48
48
|
let(:subscription) do
|
49
49
|
sub = mock
|
50
|
-
sub.stubs(
|
51
|
-
sub.stubs(
|
52
|
-
sub.stubs(
|
50
|
+
sub.stubs(:<<).returns(true)
|
51
|
+
sub.stubs(:include?).returns(false)
|
52
|
+
sub.stubs(:delete).returns(false)
|
53
53
|
sub
|
54
54
|
end
|
55
55
|
|
@@ -452,46 +452,46 @@ module MCollective
|
|
452
452
|
end
|
453
453
|
|
454
454
|
it "should use the make_target correctly" do
|
455
|
-
connector.expects(
|
455
|
+
connector.expects(:make_target).with("test", :broadcast, "mcollective").returns({:name => "test", :headers => {}})
|
456
456
|
connector.subscribe("test", :broadcast, "mcollective")
|
457
457
|
end
|
458
458
|
|
459
459
|
it "should check for existing subscriptions" do
|
460
|
-
connector.expects(
|
461
|
-
subscription.expects(
|
460
|
+
connector.expects(:make_target).with("test", :broadcast, "mcollective").returns({:name => "test", :headers => {}, :id => "rspec"})
|
461
|
+
subscription.expects(:include?).with("rspec").returns(false)
|
462
462
|
connection.expects(:subscribe).never
|
463
463
|
|
464
464
|
connector.subscribe("test", :broadcast, "mcollective")
|
465
465
|
end
|
466
466
|
|
467
467
|
it "should subscribe to the middleware" do
|
468
|
-
connector.expects(
|
468
|
+
connector.expects(:make_target).with("test", :broadcast, "mcollective").returns({:name => "test", :headers => {}, :id => "rspec"})
|
469
469
|
connection.expects(:subscribe).with("test", {}, "rspec")
|
470
470
|
connector.subscribe("test", :broadcast, "mcollective")
|
471
471
|
end
|
472
472
|
|
473
473
|
it "should add to the list of subscriptions" do
|
474
|
-
connector.expects(
|
475
|
-
subscription.expects(
|
474
|
+
connector.expects(:make_target).with("test", :broadcast, "mcollective").returns({:name => "test", :headers => {}, :id => "rspec"})
|
475
|
+
subscription.expects(:<<).with("rspec")
|
476
476
|
connector.subscribe("test", :broadcast, "mcollective")
|
477
477
|
end
|
478
478
|
end
|
479
479
|
|
480
480
|
describe "#unsubscribe" do
|
481
481
|
it "should use make_target correctly" do
|
482
|
-
connector.expects(
|
482
|
+
connector.expects(:make_target).with("test", :broadcast, "mcollective").returns({:name => "test", :headers => {}})
|
483
483
|
connector.unsubscribe("test", :broadcast, "mcollective")
|
484
484
|
end
|
485
485
|
|
486
486
|
it "should unsubscribe from the target" do
|
487
|
-
connector.expects(
|
487
|
+
connector.expects(:make_target).with("test", :broadcast, "mcollective").returns({:name => "test", :headers => {}, :id => "rspec"})
|
488
488
|
connection.expects(:unsubscribe).with("test", {}, "rspec").once
|
489
489
|
|
490
490
|
connector.unsubscribe("test", :broadcast, "mcollective")
|
491
491
|
end
|
492
492
|
|
493
493
|
it "should delete the source from subscriptions" do
|
494
|
-
connector.expects(
|
494
|
+
connector.expects(:make_target).with("test", :broadcast, "mcollective").returns({:name => "test", :headers => {}, :id => "rspec"})
|
495
495
|
subscription.expects(:delete).with("rspec").once
|
496
496
|
|
497
497
|
connector.unsubscribe("test", :broadcast, "mcollective")
|
@@ -633,11 +633,38 @@ module MCollective
|
|
633
633
|
|
634
634
|
describe "#make_target" do
|
635
635
|
it "should create correct targets" do
|
636
|
-
|
637
|
-
connector.make_target("test", :
|
638
|
-
|
639
|
-
|
640
|
-
|
636
|
+
Client.stubs(:request_sequence).returns(42)
|
637
|
+
connector.make_target("test", :reply, "mcollective").should == {
|
638
|
+
:name => "/queue/mcollective.reply.rspec_#{$$}.42",
|
639
|
+
:headers => {},
|
640
|
+
:id => "/queue/mcollective.reply.rspec_#{$$}.42",
|
641
|
+
}
|
642
|
+
|
643
|
+
connector.make_target("test", :broadcast, "mcollective").should == {
|
644
|
+
:name => "/topic/mcollective.test.agent",
|
645
|
+
:headers => {},
|
646
|
+
:id => "/topic/mcollective.test.agent",
|
647
|
+
}
|
648
|
+
|
649
|
+
connector.make_target("test", :request, "mcollective").should == {
|
650
|
+
:name => "/topic/mcollective.test.agent",
|
651
|
+
:headers => {},
|
652
|
+
:id => "/topic/mcollective.test.agent",
|
653
|
+
}
|
654
|
+
|
655
|
+
connector.make_target("test", :direct_request, "mcollective").should == {
|
656
|
+
:name => "/queue/mcollective.nodes",
|
657
|
+
:headers => {},
|
658
|
+
:id => "/queue/mcollective.nodes",
|
659
|
+
}
|
660
|
+
|
661
|
+
connector.make_target("test", :directed, "mcollective").should == {
|
662
|
+
:name => "/queue/mcollective.nodes",
|
663
|
+
:headers => {
|
664
|
+
"selector" => "mc_identity = 'rspec'",
|
665
|
+
},
|
666
|
+
:id => "mcollective_directed_to_identity",
|
667
|
+
}
|
641
668
|
end
|
642
669
|
|
643
670
|
it "should raise an error for unknown collectives" do
|