shift-nanite 0.4.1.2
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/LICENSE +201 -0
- data/README.rdoc +430 -0
- data/Rakefile +76 -0
- data/TODO +24 -0
- data/bin/nanite-admin +65 -0
- data/bin/nanite-agent +79 -0
- data/bin/nanite-mapper +50 -0
- data/lib/nanite.rb +74 -0
- data/lib/nanite/actor.rb +71 -0
- data/lib/nanite/actor_registry.rb +26 -0
- data/lib/nanite/admin.rb +138 -0
- data/lib/nanite/agent.rb +264 -0
- data/lib/nanite/amqp.rb +58 -0
- data/lib/nanite/cluster.rb +250 -0
- data/lib/nanite/config.rb +112 -0
- data/lib/nanite/console.rb +39 -0
- data/lib/nanite/daemonize.rb +13 -0
- data/lib/nanite/identity.rb +16 -0
- data/lib/nanite/job.rb +104 -0
- data/lib/nanite/local_state.rb +38 -0
- data/lib/nanite/log.rb +66 -0
- data/lib/nanite/log/formatter.rb +39 -0
- data/lib/nanite/mapper.rb +309 -0
- data/lib/nanite/mapper_proxy.rb +67 -0
- data/lib/nanite/nanite_dispatcher.rb +92 -0
- data/lib/nanite/packets.rb +365 -0
- data/lib/nanite/pid_file.rb +52 -0
- data/lib/nanite/reaper.rb +39 -0
- data/lib/nanite/security/cached_certificate_store_proxy.rb +24 -0
- data/lib/nanite/security/certificate.rb +55 -0
- data/lib/nanite/security/certificate_cache.rb +66 -0
- data/lib/nanite/security/distinguished_name.rb +34 -0
- data/lib/nanite/security/encrypted_document.rb +46 -0
- data/lib/nanite/security/rsa_key_pair.rb +53 -0
- data/lib/nanite/security/secure_serializer.rb +68 -0
- data/lib/nanite/security/signature.rb +46 -0
- data/lib/nanite/security/static_certificate_store.rb +35 -0
- data/lib/nanite/security_provider.rb +47 -0
- data/lib/nanite/serializer.rb +52 -0
- data/lib/nanite/state.rb +168 -0
- data/lib/nanite/streaming.rb +125 -0
- data/lib/nanite/util.rb +58 -0
- data/spec/actor_registry_spec.rb +60 -0
- data/spec/actor_spec.rb +77 -0
- data/spec/agent_spec.rb +240 -0
- data/spec/cached_certificate_store_proxy_spec.rb +34 -0
- data/spec/certificate_cache_spec.rb +49 -0
- data/spec/certificate_spec.rb +27 -0
- data/spec/cluster_spec.rb +622 -0
- data/spec/distinguished_name_spec.rb +24 -0
- data/spec/encrypted_document_spec.rb +21 -0
- data/spec/job_spec.rb +251 -0
- data/spec/local_state_spec.rb +130 -0
- data/spec/nanite_dispatcher_spec.rb +136 -0
- data/spec/packet_spec.rb +220 -0
- data/spec/rsa_key_pair_spec.rb +33 -0
- data/spec/secure_serializer_spec.rb +41 -0
- data/spec/serializer_spec.rb +107 -0
- data/spec/signature_spec.rb +30 -0
- data/spec/spec_helper.rb +33 -0
- data/spec/static_certificate_store_spec.rb +30 -0
- data/spec/util_spec.rb +63 -0
- metadata +129 -0
data/lib/nanite/util.rb
ADDED
@@ -0,0 +1,58 @@
|
|
1
|
+
class String
|
2
|
+
##
|
3
|
+
# Convert to snake case.
|
4
|
+
#
|
5
|
+
# "FooBar".snake_case #=> "foo_bar"
|
6
|
+
# "HeadlineCNNNews".snake_case #=> "headline_cnn_news"
|
7
|
+
# "CNN".snake_case #=> "cnn"
|
8
|
+
#
|
9
|
+
# @return [String] Receiver converted to snake case.
|
10
|
+
#
|
11
|
+
# @api public
|
12
|
+
def snake_case
|
13
|
+
return self.downcase if self =~ /^[A-Z]+$/
|
14
|
+
self.gsub(/([A-Z]+)(?=[A-Z][a-z]?)|\B[A-Z]/, '_\&') =~ /_*(.*)/
|
15
|
+
return $+.downcase
|
16
|
+
end
|
17
|
+
|
18
|
+
##
|
19
|
+
# Convert a constant name to a path, assuming a conventional structure.
|
20
|
+
#
|
21
|
+
# "FooBar::Baz".to_const_path # => "foo_bar/baz"
|
22
|
+
#
|
23
|
+
# @return [String] Path to the file containing the constant named by receiver
|
24
|
+
# (constantized string), assuming a conventional structure.
|
25
|
+
#
|
26
|
+
# @api public
|
27
|
+
def to_const_path
|
28
|
+
snake_case.gsub(/::/, "/")
|
29
|
+
end
|
30
|
+
end
|
31
|
+
|
32
|
+
class Object
|
33
|
+
unless defined? instance_exec # 1.9 and 1.8.7
|
34
|
+
module InstanceExecHelper; end
|
35
|
+
include InstanceExecHelper
|
36
|
+
|
37
|
+
# Evaluate the block with the given arguments within the context of
|
38
|
+
# this object, so self is set to the method receiver.
|
39
|
+
#
|
40
|
+
# From Mauricio's http://eigenclass.org/hiki/bounded+space+instance_exec
|
41
|
+
def instance_exec(*args, &block)
|
42
|
+
begin
|
43
|
+
old_critical, Thread.critical = Thread.critical, true
|
44
|
+
n = 0
|
45
|
+
n += 1 while respond_to?(method_name = "__instance_exec#{n}")
|
46
|
+
InstanceExecMethods.module_eval { define_method(method_name, &block) }
|
47
|
+
ensure
|
48
|
+
Thread.critical = old_critical
|
49
|
+
end
|
50
|
+
|
51
|
+
begin
|
52
|
+
send(method_name, *args)
|
53
|
+
ensure
|
54
|
+
InstanceExecMethods.module_eval { remove_method(method_name) } rescue nil
|
55
|
+
end
|
56
|
+
end
|
57
|
+
end
|
58
|
+
end
|
@@ -0,0 +1,60 @@
|
|
1
|
+
require File.join(File.dirname(__FILE__), 'spec_helper')
|
2
|
+
|
3
|
+
describe Nanite::ActorRegistry do
|
4
|
+
|
5
|
+
class ::WebDocumentImporter
|
6
|
+
include Nanite::Actor
|
7
|
+
expose :import, :cancel
|
8
|
+
|
9
|
+
def import
|
10
|
+
1
|
11
|
+
end
|
12
|
+
def cancel
|
13
|
+
0
|
14
|
+
end
|
15
|
+
end
|
16
|
+
|
17
|
+
module ::Actors
|
18
|
+
class ComedyActor
|
19
|
+
include Nanite::Actor
|
20
|
+
expose :fun_tricks
|
21
|
+
def fun_tricks
|
22
|
+
:rabbit_in_the_hat
|
23
|
+
end
|
24
|
+
end
|
25
|
+
end
|
26
|
+
|
27
|
+
before(:each) do
|
28
|
+
Nanite::Log.stub!(:info)
|
29
|
+
@registry = Nanite::ActorRegistry.new
|
30
|
+
end
|
31
|
+
|
32
|
+
it "should know about all services" do
|
33
|
+
@registry.register(WebDocumentImporter.new, nil)
|
34
|
+
@registry.register(Actors::ComedyActor.new, nil)
|
35
|
+
@registry.services.sort.should == ["/actors/comedy_actor/fun_tricks", "/web_document_importer/cancel", "/web_document_importer/import"]
|
36
|
+
end
|
37
|
+
|
38
|
+
it "should not register anything except Nanite::Actor" do
|
39
|
+
lambda { @registry.register(String.new, nil) }.should raise_error(ArgumentError)
|
40
|
+
end
|
41
|
+
|
42
|
+
it "should register an actor" do
|
43
|
+
importer = WebDocumentImporter.new
|
44
|
+
@registry.register(importer, nil)
|
45
|
+
@registry.actors['web_document_importer'].should == importer
|
46
|
+
end
|
47
|
+
|
48
|
+
it "should log info message that actor was registered" do
|
49
|
+
importer = WebDocumentImporter.new
|
50
|
+
Nanite::Log.should_receive(:info).with("[actor] #{importer.class.to_s}")
|
51
|
+
@registry.register(importer, nil)
|
52
|
+
end
|
53
|
+
|
54
|
+
it "should handle actors registered with a custom prefix" do
|
55
|
+
importer = WebDocumentImporter.new
|
56
|
+
@registry.register(importer, 'monkey')
|
57
|
+
@registry.actor_for('monkey').should == importer
|
58
|
+
end
|
59
|
+
|
60
|
+
end # Nanite::ActorRegistry
|
data/spec/actor_spec.rb
ADDED
@@ -0,0 +1,77 @@
|
|
1
|
+
require File.join(File.dirname(__FILE__), 'spec_helper')
|
2
|
+
|
3
|
+
describe Nanite::Actor do
|
4
|
+
class ::WebDocumentImporter
|
5
|
+
include Nanite::Actor
|
6
|
+
expose :import, :cancel
|
7
|
+
|
8
|
+
def import
|
9
|
+
1
|
10
|
+
end
|
11
|
+
def cancel
|
12
|
+
0
|
13
|
+
end
|
14
|
+
def continue
|
15
|
+
1
|
16
|
+
end
|
17
|
+
end
|
18
|
+
|
19
|
+
module ::Actors
|
20
|
+
class ComedyActor
|
21
|
+
include Nanite::Actor
|
22
|
+
expose :fun_tricks
|
23
|
+
def fun_tricks
|
24
|
+
:rabbit_in_the_hat
|
25
|
+
end
|
26
|
+
end
|
27
|
+
end
|
28
|
+
|
29
|
+
class ::Actors::InvalidActor
|
30
|
+
include Nanite::Actor
|
31
|
+
expose :non_existing
|
32
|
+
end
|
33
|
+
|
34
|
+
describe ".expose" do
|
35
|
+
before :each do
|
36
|
+
@exposed = WebDocumentImporter.instance_variable_get(:@exposed).dup
|
37
|
+
end
|
38
|
+
|
39
|
+
after :each do
|
40
|
+
WebDocumentImporter.instance_variable_set(:@exposed, @exposed)
|
41
|
+
end
|
42
|
+
|
43
|
+
|
44
|
+
it "should single expose method only once" do
|
45
|
+
3.times { WebDocumentImporter.expose(:continue) }
|
46
|
+
WebDocumentImporter.provides_for("webfiles").should == ["/webfiles/import", "/webfiles/cancel", "/webfiles/continue"]
|
47
|
+
end
|
48
|
+
end
|
49
|
+
|
50
|
+
describe ".default_prefix" do
|
51
|
+
it "is calculated as default prefix as const path of class name" do
|
52
|
+
Actors::ComedyActor.default_prefix.should == "actors/comedy_actor"
|
53
|
+
WebDocumentImporter.default_prefix.should == "web_document_importer"
|
54
|
+
end
|
55
|
+
end
|
56
|
+
|
57
|
+
describe ".provides_for(prefix)" do
|
58
|
+
before :each do
|
59
|
+
@provides = Actors::ComedyActor.provides_for("money")
|
60
|
+
end
|
61
|
+
|
62
|
+
it "returns an array" do
|
63
|
+
@provides.should be_kind_of(Array)
|
64
|
+
end
|
65
|
+
|
66
|
+
it "maps exposed service methods to prefix" do
|
67
|
+
@provides.should == ["/money/fun_tricks"]
|
68
|
+
wdi_provides = WebDocumentImporter.provides_for("webfiles")
|
69
|
+
wdi_provides.should include("/webfiles/import")
|
70
|
+
wdi_provides.should include("/webfiles/cancel")
|
71
|
+
end
|
72
|
+
|
73
|
+
it "should not include methods not existing in the actor class" do
|
74
|
+
Actors::InvalidActor.provides_for("money").should_not include("/money/non_existing")
|
75
|
+
end
|
76
|
+
end
|
77
|
+
end
|
data/spec/agent_spec.rb
ADDED
@@ -0,0 +1,240 @@
|
|
1
|
+
require File.join(File.dirname(__FILE__), 'spec_helper')
|
2
|
+
|
3
|
+
describe "Agent:" do
|
4
|
+
|
5
|
+
describe "Default Option" do
|
6
|
+
|
7
|
+
before(:all) do
|
8
|
+
EM.stub!(:add_periodic_timer)
|
9
|
+
AMQP.stub!(:connect)
|
10
|
+
@amq = mock("AMQueue", :queue => mock("queue", :subscribe => {}), :fanout => mock("fanout", :publish => nil))
|
11
|
+
MQ.stub!(:new).and_return(@amq)
|
12
|
+
@agent = Nanite::Agent.start
|
13
|
+
end
|
14
|
+
|
15
|
+
it "for daemonize is false" do
|
16
|
+
@agent.options.should include(:daemonize)
|
17
|
+
@agent.options[:daemonize].should == false
|
18
|
+
end
|
19
|
+
|
20
|
+
it "for format is marshal" do
|
21
|
+
@agent.options.should include(:format)
|
22
|
+
@agent.options[:format].should == :marshal
|
23
|
+
end
|
24
|
+
|
25
|
+
it "for console is false" do
|
26
|
+
@agent.options.should include(:console)
|
27
|
+
@agent.options[:console].should == false
|
28
|
+
end
|
29
|
+
|
30
|
+
it "for user is nanite" do
|
31
|
+
@agent.options.should include(:user)
|
32
|
+
@agent.options[:user].should == "nanite"
|
33
|
+
end
|
34
|
+
|
35
|
+
it "for pass(word) is testing" do
|
36
|
+
@agent.options.should include(:pass)
|
37
|
+
@agent.options[:pass].should == "testing"
|
38
|
+
end
|
39
|
+
|
40
|
+
it "for secure is false" do
|
41
|
+
@agent.options.should include(:secure)
|
42
|
+
@agent.options[:secure].should == false
|
43
|
+
end
|
44
|
+
|
45
|
+
it "for host is 0.0.0.0" do
|
46
|
+
@agent.options.should include(:host)
|
47
|
+
@agent.options[:host].should == "0.0.0.0"
|
48
|
+
end
|
49
|
+
|
50
|
+
it "for log_level is info" do
|
51
|
+
@agent.options.should include(:log_level)
|
52
|
+
@agent.options[:log_level].should == :info
|
53
|
+
end
|
54
|
+
|
55
|
+
it "for vhost is /nanite" do
|
56
|
+
@agent.options.should include(:vhost)
|
57
|
+
@agent.options[:vhost].should == "/nanite"
|
58
|
+
end
|
59
|
+
|
60
|
+
it "for ping_time is 15" do
|
61
|
+
@agent.options.should include(:ping_time)
|
62
|
+
@agent.options[:ping_time].should == 15
|
63
|
+
end
|
64
|
+
|
65
|
+
it "for default_services is []" do
|
66
|
+
@agent.options.should include(:default_services)
|
67
|
+
@agent.options[:default_services].should == []
|
68
|
+
end
|
69
|
+
|
70
|
+
it "for root is #{File.expand_path(File.join(File.dirname(__FILE__), '..'))}" do
|
71
|
+
@agent.options.should include(:root)
|
72
|
+
@agent.options[:root].should == File.expand_path(File.join(File.dirname(__FILE__), '..'))
|
73
|
+
end
|
74
|
+
|
75
|
+
it "for file_root is #{File.expand_path(File.join(File.dirname(__FILE__), '..', 'files'))}" do
|
76
|
+
@agent.options.should include(:file_root)
|
77
|
+
@agent.options[:file_root].should == File.expand_path(File.join(File.dirname(__FILE__), '..', 'files'))
|
78
|
+
end
|
79
|
+
|
80
|
+
end
|
81
|
+
|
82
|
+
describe "Options from config.yml" do
|
83
|
+
|
84
|
+
before(:all) do
|
85
|
+
@agent = Nanite::Agent.start
|
86
|
+
end
|
87
|
+
|
88
|
+
end
|
89
|
+
|
90
|
+
describe "Passed in Options" do
|
91
|
+
|
92
|
+
before(:each) do
|
93
|
+
EM.stub!(:add_periodic_timer)
|
94
|
+
AMQP.stub!(:connect)
|
95
|
+
@amq = mock("AMQueue", :queue => mock("queue", :subscribe => {}), :fanout => mock("fanout", :publish => nil))
|
96
|
+
MQ.stub!(:new).and_return(@amq)
|
97
|
+
end
|
98
|
+
|
99
|
+
# TODO figure out how to stub call to daemonize
|
100
|
+
# it "for daemonize should override default (false)" do
|
101
|
+
# agent = Nanite::Agent.start(:daemonize => true)
|
102
|
+
# agent.options.should include(:daemonize)
|
103
|
+
# agent.options[:daemonize].should == true
|
104
|
+
# end
|
105
|
+
|
106
|
+
it "for format should override default (marshal)" do
|
107
|
+
agent = Nanite::Agent.start(:format => :json)
|
108
|
+
agent.options.should include(:format)
|
109
|
+
agent.options[:format].should == :json
|
110
|
+
end
|
111
|
+
|
112
|
+
# TODO figure out how to avoid console output
|
113
|
+
# it "for console should override default (false)" do
|
114
|
+
# agent = Nanite::Agent.start(:console => true)
|
115
|
+
# agent.options.should include(:console)
|
116
|
+
# agent.options[:console].should == true
|
117
|
+
# end
|
118
|
+
|
119
|
+
it "for user should override default (nanite)" do
|
120
|
+
agent = Nanite::Agent.start(:user => "me")
|
121
|
+
agent.options.should include(:user)
|
122
|
+
agent.options[:user].should == "me"
|
123
|
+
end
|
124
|
+
|
125
|
+
it "for pass(word) should override default (testing)" do
|
126
|
+
agent = Nanite::Agent.start(:pass => "secret")
|
127
|
+
agent.options.should include(:pass)
|
128
|
+
agent.options[:pass].should == "secret"
|
129
|
+
end
|
130
|
+
|
131
|
+
it "for secure should override default (false)" do
|
132
|
+
agent = Nanite::Agent.start(:secure => true)
|
133
|
+
agent.options.should include(:secure)
|
134
|
+
agent.options[:secure].should == true
|
135
|
+
end
|
136
|
+
|
137
|
+
it "for host should override default (0.0.0.0)" do
|
138
|
+
agent = Nanite::Agent.start(:host => "127.0.0.1")
|
139
|
+
agent.options.should include(:host)
|
140
|
+
agent.options[:host].should == "127.0.0.1"
|
141
|
+
end
|
142
|
+
|
143
|
+
it "for log_level should override default (info)" do
|
144
|
+
agent = Nanite::Agent.start(:log_level => :debug)
|
145
|
+
agent.options.should include(:log_level)
|
146
|
+
agent.options[:log_level].should == :debug
|
147
|
+
end
|
148
|
+
|
149
|
+
it "for vhost should override default (/nanite)" do
|
150
|
+
agent = Nanite::Agent.start(:vhost => "/virtual_host")
|
151
|
+
agent.options.should include(:vhost)
|
152
|
+
agent.options[:vhost].should == "/virtual_host"
|
153
|
+
end
|
154
|
+
|
155
|
+
it "for ping_time should override default (15)" do
|
156
|
+
agent = Nanite::Agent.start(:ping_time => 5)
|
157
|
+
agent.options.should include(:ping_time)
|
158
|
+
agent.options[:ping_time].should == 5
|
159
|
+
end
|
160
|
+
|
161
|
+
it "for default_services should override default ([])" do
|
162
|
+
agent = Nanite::Agent.start(:default_services => [:test])
|
163
|
+
agent.options.should include(:default_services)
|
164
|
+
agent.options[:default_services].should == [:test]
|
165
|
+
end
|
166
|
+
|
167
|
+
it "for root should override default (#{File.expand_path(File.join(File.dirname(__FILE__), '..'))})" do
|
168
|
+
agent = Nanite::Agent.start(:root => File.expand_path(File.dirname(__FILE__)))
|
169
|
+
agent.options.should include(:root)
|
170
|
+
agent.options[:root].should == File.expand_path(File.dirname(__FILE__))
|
171
|
+
end
|
172
|
+
|
173
|
+
it "for file_root should override default (#{File.expand_path(File.join(File.dirname(__FILE__), '..', 'files'))})" do
|
174
|
+
agent = Nanite::Agent.start(:file_root => File.expand_path(File.dirname(__FILE__)))
|
175
|
+
agent.options.should include(:file_root)
|
176
|
+
agent.options[:file_root].should == File.expand_path(File.dirname(__FILE__))
|
177
|
+
end
|
178
|
+
|
179
|
+
it "for a single tag should result in the agent's tags being set" do
|
180
|
+
agent = Nanite::Agent.start(:tag => "sample_tag")
|
181
|
+
agent.tags.should include("sample_tag")
|
182
|
+
end
|
183
|
+
|
184
|
+
it "for multiple tags should result in the agent's tags being set" do
|
185
|
+
agent = Nanite::Agent.start(:tag => ["sample_tag_1", "sample_tag_2"])
|
186
|
+
agent.tags.should include("sample_tag_1")
|
187
|
+
agent.tags.should include("sample_tag_2")
|
188
|
+
end
|
189
|
+
|
190
|
+
it "for threadpool_size" do
|
191
|
+
agent = Nanite::Agent.start(:threadpool_size => 5)
|
192
|
+
agent.dispatcher.evmclass.threadpool_size.should == 5
|
193
|
+
end
|
194
|
+
|
195
|
+
end
|
196
|
+
|
197
|
+
describe "Security" do
|
198
|
+
|
199
|
+
before(:each) do
|
200
|
+
EM.stub!(:add_periodic_timer)
|
201
|
+
AMQP.stub!(:connect)
|
202
|
+
@amq = mock("AMQueue", :queue => mock("queue", :subscribe => {}, :publish => {}), :fanout => mock("fanout", :publish => nil))
|
203
|
+
MQ.stub!(:new).and_return(@amq)
|
204
|
+
serializer = Nanite::Serializer.new
|
205
|
+
@request = Nanite::Request.new('/foo/bar', '')
|
206
|
+
@push = Nanite::Push.new('/foo/bar', '')
|
207
|
+
@agent = Nanite::Agent.start
|
208
|
+
end
|
209
|
+
|
210
|
+
it 'should correctly deny requests' do
|
211
|
+
security = mock("Security")
|
212
|
+
@agent.register_security(security)
|
213
|
+
|
214
|
+
security.should_receive(:authorize).twice.and_return(false)
|
215
|
+
@agent.dispatcher.should_not_receive(:dispatch)
|
216
|
+
@agent.__send__(:receive, @request)
|
217
|
+
@agent.__send__(:receive, @push)
|
218
|
+
end
|
219
|
+
|
220
|
+
it 'should correctly authorize requests' do
|
221
|
+
security = mock("Security")
|
222
|
+
@agent.register_security(security)
|
223
|
+
|
224
|
+
security.should_receive(:authorize).twice.and_return(true)
|
225
|
+
@agent.dispatcher.stub!(:dispatch)
|
226
|
+
@agent.dispatcher.should_receive(:dispatch).twice
|
227
|
+
@agent.__send__(:receive, @request)
|
228
|
+
@agent.__send__(:receive, @push)
|
229
|
+
end
|
230
|
+
|
231
|
+
it 'should be ignored when not specified' do
|
232
|
+
@agent.dispatcher.stub!(:dispatch)
|
233
|
+
@agent.dispatcher.should_receive(:dispatch).twice
|
234
|
+
@agent.__send__(:receive, @request)
|
235
|
+
@agent.__send__(:receive, @push)
|
236
|
+
end
|
237
|
+
|
238
|
+
end
|
239
|
+
|
240
|
+
end
|
@@ -0,0 +1,34 @@
|
|
1
|
+
require File.join(File.dirname(__FILE__), 'spec_helper')
|
2
|
+
|
3
|
+
describe Nanite::CachedCertificateStoreProxy do
|
4
|
+
|
5
|
+
include SpecHelpers
|
6
|
+
|
7
|
+
before(:all) do
|
8
|
+
@signer, key = issue_cert
|
9
|
+
@recipient, key = issue_cert
|
10
|
+
@store = mock("Store")
|
11
|
+
@proxy = Nanite::CachedCertificateStoreProxy.new(@store)
|
12
|
+
end
|
13
|
+
|
14
|
+
it 'should not raise and return nil for non existent certificates' do
|
15
|
+
res = nil
|
16
|
+
@store.should_receive(:get_recipients).with(nil).and_return(nil)
|
17
|
+
lambda { res = @proxy.get_recipients(nil) }.should_not raise_error
|
18
|
+
res.should == nil
|
19
|
+
@store.should_receive(:get_signer).with(nil).and_return(nil)
|
20
|
+
lambda { res = @proxy.get_signer(nil) }.should_not raise_error
|
21
|
+
res.should == nil
|
22
|
+
end
|
23
|
+
|
24
|
+
it 'should return recipient certificates' do
|
25
|
+
@store.should_receive(:get_recipients).with('anything').and_return(@recipient)
|
26
|
+
@proxy.get_recipients('anything').should == @recipient
|
27
|
+
end
|
28
|
+
|
29
|
+
it 'should return signer certificates' do
|
30
|
+
@store.should_receive(:get_signer).with('anything').and_return(@signer)
|
31
|
+
@proxy.get_signer('anything').should == @signer
|
32
|
+
end
|
33
|
+
|
34
|
+
end
|