pantry 0.0.0 → 0.1.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.gitignore +9 -0
- data/.ruby-version +1 -0
- data/.travis.yml +19 -0
- data/Gemfile +15 -0
- data/Guardfile +16 -0
- data/LICENSE +20 -0
- data/README.md +53 -0
- data/Rakefile +18 -0
- data/Vagrantfile +86 -0
- data/bin/pantry +11 -0
- data/bin/pantry-client +38 -0
- data/bin/pantry-server +33 -0
- data/dist/client.yml +79 -0
- data/dist/server.yml +56 -0
- data/dist/upstart/pantry-client.conf +12 -0
- data/dist/upstart/pantry-server.conf +12 -0
- data/doc/message_packet.dot +19 -0
- data/doc/message_packet.dot.png +0 -0
- data/doc/network_topology.dot +42 -0
- data/doc/network_topology.dot.png +0 -0
- data/lib/celluloid_zmq_patches.rb +16 -0
- data/lib/opt_parse_plus.rb +184 -0
- data/lib/pantry.rb +197 -0
- data/lib/pantry/cli.rb +154 -0
- data/lib/pantry/client.rb +131 -0
- data/lib/pantry/client_info.rb +34 -0
- data/lib/pantry/client_registry.rb +104 -0
- data/lib/pantry/command.rb +194 -0
- data/lib/pantry/command_handler.rb +53 -0
- data/lib/pantry/command_line.rb +115 -0
- data/lib/pantry/commands/create_client.rb +30 -0
- data/lib/pantry/commands/download_directory.rb +35 -0
- data/lib/pantry/commands/echo.rb +32 -0
- data/lib/pantry/commands/edit_application.rb +60 -0
- data/lib/pantry/commands/register_client.rb +38 -0
- data/lib/pantry/commands/status.rb +78 -0
- data/lib/pantry/commands/sync_directory.rb +50 -0
- data/lib/pantry/commands/update_application.rb +45 -0
- data/lib/pantry/commands/upload_file.rb +68 -0
- data/lib/pantry/communication.rb +20 -0
- data/lib/pantry/communication/client.rb +75 -0
- data/lib/pantry/communication/client_filter.rb +117 -0
- data/lib/pantry/communication/file_service.rb +125 -0
- data/lib/pantry/communication/file_service/file_progress.rb +164 -0
- data/lib/pantry/communication/file_service/receive_file.rb +97 -0
- data/lib/pantry/communication/file_service/send_file.rb +74 -0
- data/lib/pantry/communication/publish_socket.rb +20 -0
- data/lib/pantry/communication/reading_socket.rb +89 -0
- data/lib/pantry/communication/receive_socket.rb +23 -0
- data/lib/pantry/communication/security.rb +44 -0
- data/lib/pantry/communication/security/authentication.rb +98 -0
- data/lib/pantry/communication/security/curve_key_store.rb +120 -0
- data/lib/pantry/communication/security/curve_security.rb +70 -0
- data/lib/pantry/communication/security/null_security.rb +32 -0
- data/lib/pantry/communication/send_socket.rb +19 -0
- data/lib/pantry/communication/serialize_message.rb +84 -0
- data/lib/pantry/communication/server.rb +97 -0
- data/lib/pantry/communication/subscribe_socket.rb +33 -0
- data/lib/pantry/communication/wait_list.rb +45 -0
- data/lib/pantry/communication/writing_socket.rb +46 -0
- data/lib/pantry/config.rb +182 -0
- data/lib/pantry/file_editor.rb +67 -0
- data/lib/pantry/logger.rb +78 -0
- data/lib/pantry/message.rb +134 -0
- data/lib/pantry/multi_command.rb +36 -0
- data/lib/pantry/server.rb +132 -0
- data/lib/pantry/test/acceptance.rb +83 -0
- data/lib/pantry/test/support/fake_fs.rb +31 -0
- data/lib/pantry/test/support/matchers.rb +13 -0
- data/lib/pantry/test/support/minitest.rb +13 -0
- data/lib/pantry/test/support/mock_ui.rb +23 -0
- data/lib/pantry/test/unit.rb +13 -0
- data/lib/pantry/ui.rb +68 -0
- data/lib/pantry/version.rb +3 -0
- data/pantry.gemspec +40 -0
- data/test/acceptance/cli/error_handling_test.rb +7 -0
- data/test/acceptance/cli/execute_command_on_clients_test.rb +32 -0
- data/test/acceptance/cli/request_info_from_server_test.rb +44 -0
- data/test/acceptance/communication/client_requests_info_from_server_test.rb +28 -0
- data/test/acceptance/communication/heartbeat_test.rb +19 -0
- data/test/acceptance/communication/pub_sub_communication_test.rb +53 -0
- data/test/acceptance/communication/security_test.rb +117 -0
- data/test/acceptance/communication/server_requests_info_from_client_test.rb +41 -0
- data/test/acceptance/test_helper.rb +25 -0
- data/test/fixtures/config.yml +22 -0
- data/test/fixtures/empty.yml +2 -0
- data/test/fixtures/file_to_upload +3 -0
- data/test/root_dir/.gitkeep +0 -0
- data/test/unit/cli_test.rb +173 -0
- data/test/unit/client_registry_test.rb +61 -0
- data/test/unit/client_test.rb +128 -0
- data/test/unit/command_handler_test.rb +79 -0
- data/test/unit/command_line_test.rb +5 -0
- data/test/unit/command_test.rb +206 -0
- data/test/unit/commands/create_client_test.rb +25 -0
- data/test/unit/commands/download_directory_test.rb +58 -0
- data/test/unit/commands/echo_test.rb +22 -0
- data/test/unit/commands/edit_application_test.rb +84 -0
- data/test/unit/commands/register_client_test.rb +41 -0
- data/test/unit/commands/status_test.rb +81 -0
- data/test/unit/commands/sync_directory_test.rb +75 -0
- data/test/unit/commands/update_application_test.rb +35 -0
- data/test/unit/commands/upload_file_test.rb +51 -0
- data/test/unit/communication/client_filter_test.rb +262 -0
- data/test/unit/communication/client_test.rb +99 -0
- data/test/unit/communication/file_service/receive_file_test.rb +214 -0
- data/test/unit/communication/file_service/send_file_test.rb +110 -0
- data/test/unit/communication/file_service_test.rb +56 -0
- data/test/unit/communication/publish_socket_test.rb +19 -0
- data/test/unit/communication/reading_socket_test.rb +110 -0
- data/test/unit/communication/receive_socket_test.rb +20 -0
- data/test/unit/communication/security/authentication_test.rb +97 -0
- data/test/unit/communication/security/curve_key_store_test.rb +110 -0
- data/test/unit/communication/security/curve_security_test.rb +44 -0
- data/test/unit/communication/security/null_security_test.rb +15 -0
- data/test/unit/communication/security_test.rb +49 -0
- data/test/unit/communication/send_socket_test.rb +19 -0
- data/test/unit/communication/serialize_message_test.rb +128 -0
- data/test/unit/communication/server_test.rb +106 -0
- data/test/unit/communication/subscribe_socket_test.rb +46 -0
- data/test/unit/communication/wait_list_test.rb +60 -0
- data/test/unit/communication/writing_socket_test.rb +46 -0
- data/test/unit/config_test.rb +150 -0
- data/test/unit/logger_test.rb +79 -0
- data/test/unit/message_test.rb +179 -0
- data/test/unit/multi_command_test.rb +45 -0
- data/test/unit/opt_parse_plus_test.rb +218 -0
- data/test/unit/pantry_test.rb +82 -0
- data/test/unit/server_test.rb +166 -0
- data/test/unit/test_helper.rb +25 -0
- data/test/unit/ui_test.rb +58 -0
- metadata +389 -13
@@ -0,0 +1,99 @@
|
|
1
|
+
require 'unit/test_helper'
|
2
|
+
|
3
|
+
describe Pantry::Communication::Client do
|
4
|
+
|
5
|
+
before do
|
6
|
+
Pantry::Communication::SubscribeSocket.any_instance.stubs(:open)
|
7
|
+
Pantry::Communication::SendSocket.any_instance.stubs(:open)
|
8
|
+
|
9
|
+
Pantry::Communication::FileService.any_instance.stubs(:start_client)
|
10
|
+
end
|
11
|
+
|
12
|
+
it "sets up a subscribe socket for communication" do
|
13
|
+
pantry_client = Pantry::Client.new
|
14
|
+
client = Pantry::Communication::Client.new(pantry_client)
|
15
|
+
|
16
|
+
Pantry::Communication::SubscribeSocket.any_instance.expects(:add_listener).with(client)
|
17
|
+
Pantry::Communication::SubscribeSocket.any_instance.expects(:open)
|
18
|
+
|
19
|
+
client.run
|
20
|
+
end
|
21
|
+
|
22
|
+
it "configures filtering if the client has been given a scope" do
|
23
|
+
pantry_client = Pantry::Client.new(
|
24
|
+
application: "pantry", environment: "test",
|
25
|
+
roles: %w(application database), identity: "client2"
|
26
|
+
)
|
27
|
+
|
28
|
+
client = Pantry::Communication::Client.new(pantry_client)
|
29
|
+
|
30
|
+
Pantry::Communication::SubscribeSocket.any_instance.stubs(:add_listener)
|
31
|
+
Pantry::Communication::SubscribeSocket.any_instance.stubs(:open)
|
32
|
+
|
33
|
+
Pantry::Communication::SubscribeSocket.any_instance.expects(:filter_on).with(
|
34
|
+
Pantry::Communication::ClientFilter.new(
|
35
|
+
application: "pantry", environment: "test", roles: %w(application database),
|
36
|
+
identity: "client2"
|
37
|
+
)
|
38
|
+
)
|
39
|
+
|
40
|
+
client.run
|
41
|
+
end
|
42
|
+
|
43
|
+
it "sets up a Send socket for communication" do
|
44
|
+
pantry_client = Pantry::Client.new
|
45
|
+
client = Pantry::Communication::Client.new(pantry_client)
|
46
|
+
|
47
|
+
Pantry::Communication::SendSocket.any_instance.expects(:open)
|
48
|
+
|
49
|
+
client.run
|
50
|
+
end
|
51
|
+
|
52
|
+
it "starts up a local file service" do
|
53
|
+
pantry_client = Pantry::Client.new
|
54
|
+
client = Pantry::Communication::Client.new(pantry_client)
|
55
|
+
|
56
|
+
Pantry::Communication::FileService.any_instance.expects(:start_client)
|
57
|
+
|
58
|
+
client.run
|
59
|
+
end
|
60
|
+
|
61
|
+
it "sends messages through the Send socket back to the server" do
|
62
|
+
pantry_client = Pantry::Client.new
|
63
|
+
client = Pantry::Communication::Client.new(pantry_client)
|
64
|
+
message = Pantry::Message.new("message")
|
65
|
+
|
66
|
+
Pantry::Communication::SendSocket.any_instance.expects(:send_message).with(message)
|
67
|
+
|
68
|
+
client.run
|
69
|
+
client.send_message(message)
|
70
|
+
end
|
71
|
+
|
72
|
+
it "sets the source of the message to the current listener" do
|
73
|
+
pantry_client = Pantry::Client.new
|
74
|
+
client = Pantry::Communication::Client.new(pantry_client)
|
75
|
+
message = Pantry::Message.new("message")
|
76
|
+
|
77
|
+
Pantry::Communication::SendSocket.any_instance.expects(:send_message).with do |message|
|
78
|
+
message.from == pantry_client.identity
|
79
|
+
end
|
80
|
+
|
81
|
+
client.run
|
82
|
+
client.send_message(message)
|
83
|
+
end
|
84
|
+
|
85
|
+
it "sends a request to the server, returning a future" do
|
86
|
+
pantry_client = Pantry::Client.new
|
87
|
+
client = Pantry::Communication::Client.new(pantry_client)
|
88
|
+
client.run
|
89
|
+
|
90
|
+
message = Pantry::Message.new("message")
|
91
|
+
Pantry::Communication::SendSocket.any_instance.expects(:send_message).with(message)
|
92
|
+
|
93
|
+
future = client.send_request(message)
|
94
|
+
|
95
|
+
assert_not_nil future
|
96
|
+
assert_false future.ready?
|
97
|
+
end
|
98
|
+
|
99
|
+
end
|
@@ -0,0 +1,214 @@
|
|
1
|
+
require 'unit/test_helper'
|
2
|
+
|
3
|
+
describe Pantry::Communication::FileService::ReceiveFile do
|
4
|
+
|
5
|
+
class FakeReceiveService
|
6
|
+
attr_accessor :sent
|
7
|
+
def initialize
|
8
|
+
@sent = []
|
9
|
+
end
|
10
|
+
def send_message(identity, message)
|
11
|
+
@sent << {identity: identity, message: message}
|
12
|
+
end
|
13
|
+
end
|
14
|
+
|
15
|
+
let(:service) { FakeReceiveService.new }
|
16
|
+
let(:file_path) { fixture_path("file_to_upload") }
|
17
|
+
let(:receiver) { Pantry::Communication::FileService::ReceiveFile.new(service) }
|
18
|
+
|
19
|
+
def start_message(file_uuid)
|
20
|
+
Pantry::Message.new.tap do |msg|
|
21
|
+
msg.to = file_uuid
|
22
|
+
msg << "START"
|
23
|
+
end
|
24
|
+
end
|
25
|
+
|
26
|
+
def chunk(file_uuid, data = "binary data", offset: 0, size: 1_000)
|
27
|
+
Pantry::Message.new.tap do |msg|
|
28
|
+
msg.to = file_uuid
|
29
|
+
msg[:chunk_offset] = offset
|
30
|
+
msg[:chunk_size] = size
|
31
|
+
msg << "CHUNK"
|
32
|
+
msg << data
|
33
|
+
end
|
34
|
+
end
|
35
|
+
|
36
|
+
describe "#receive_file" do
|
37
|
+
it "builds and returns file upload info when asked to receive a new file" do
|
38
|
+
info = receiver.receive_file(12_000, "abc123")
|
39
|
+
|
40
|
+
assert_not_nil info, "No info returned for the file info"
|
41
|
+
assert_equal 36, info.file_uuid.length
|
42
|
+
assert_equal 12_000, info.file_size
|
43
|
+
assert_equal "abc123", info.checksum
|
44
|
+
end
|
45
|
+
|
46
|
+
it "creates and returns a tempfile path where the upload will go" do
|
47
|
+
info = receiver.receive_file(12_000, "abc123")
|
48
|
+
|
49
|
+
assert_not_nil info.uploaded_path, "Did not give a file path where upload will live"
|
50
|
+
assert File.exists?(info.uploaded_path), "Did not create a tempfile for the upload"
|
51
|
+
end
|
52
|
+
end
|
53
|
+
|
54
|
+
it "waits for a start message from the sender then sends initial chunk requests" do
|
55
|
+
info = receiver.receive_file(5_000_000, "checksum")
|
56
|
+
receiver.receive_message("sender_ident", start_message(info.file_uuid))
|
57
|
+
|
58
|
+
pipeline_size = receiver.pipeline_size
|
59
|
+
chunk_size = receiver.chunk_size
|
60
|
+
|
61
|
+
assert_equal pipeline_size, service.sent.length
|
62
|
+
|
63
|
+
service.sent.each_with_index do |msg, i|
|
64
|
+
assert_equal info.file_uuid, msg[:message].to, "Message #{i} did not set the to field properly"
|
65
|
+
end
|
66
|
+
|
67
|
+
assert_equal "sender_ident", info.sender_uuid
|
68
|
+
|
69
|
+
assert_equal "sender_ident", service.sent[0][:identity]
|
70
|
+
assert_equal "sender_ident", service.sent[1][:identity]
|
71
|
+
assert_equal "sender_ident", service.sent[2][:identity]
|
72
|
+
|
73
|
+
assert_equal ["FETCH", 0, chunk_size], service.sent[0][:message].body
|
74
|
+
assert_equal ["FETCH", chunk_size, chunk_size], service.sent[1][:message].body
|
75
|
+
assert_equal ["FETCH", chunk_size * 2, chunk_size], service.sent[2][:message].body
|
76
|
+
end
|
77
|
+
|
78
|
+
it "writes out received chunks to the given save file path" do
|
79
|
+
info = receiver.receive_file(
|
80
|
+
File.size(file_path),
|
81
|
+
"9cb63cb779e8c571db3199b783a36cc43cd9e7c076beeb496c39e9cc06196dc5"
|
82
|
+
)
|
83
|
+
receiver.receive_message("sender_ident", start_message(info.file_uuid))
|
84
|
+
receiver.receive_message("sender_ident", chunk(info.file_uuid))
|
85
|
+
|
86
|
+
assert_equal "binary data", File.read(info.uploaded_path)
|
87
|
+
end
|
88
|
+
|
89
|
+
it "keeps a certain number of chunk requests in the pipeline" do
|
90
|
+
info = receiver.receive_file(5_000_000, "checksum")
|
91
|
+
receiver.receive_message("sender_ident", start_message(info.file_uuid))
|
92
|
+
service.sent = []
|
93
|
+
|
94
|
+
receiver.receive_message("sender_ident", chunk(info.file_uuid))
|
95
|
+
|
96
|
+
# We've already requested 10 chunks. Having received one chunk we request the 11th (0-based)
|
97
|
+
assert_equal 1, service.sent.length
|
98
|
+
assert_equal ["FETCH", receiver.chunk_size * 10, receiver.chunk_size], service.sent[0][:message].body
|
99
|
+
end
|
100
|
+
|
101
|
+
it "doesn't add to the pipeline when the last chunk has been requested" do
|
102
|
+
info = receiver.receive_file(500_000, "checksum")
|
103
|
+
receiver.receive_message("sender_ident", start_message(info.file_uuid))
|
104
|
+
service.sent = []
|
105
|
+
|
106
|
+
receiver.receive_message("sender_ident", chunk(info.file_uuid))
|
107
|
+
assert_equal 0, service.sent.length
|
108
|
+
end
|
109
|
+
|
110
|
+
it "sends the finished message to the client when the file upload is successful" do
|
111
|
+
info = receiver.receive_file(
|
112
|
+
File.size(file_path),
|
113
|
+
"9cb63cb779e8c571db3199b783a36cc43cd9e7c076beeb496c39e9cc06196dc5"
|
114
|
+
)
|
115
|
+
receiver.receive_message("sender_ident", start_message(info.file_uuid))
|
116
|
+
service.sent = []
|
117
|
+
|
118
|
+
receiver.receive_message("sender_ident", chunk(info.file_uuid))
|
119
|
+
|
120
|
+
assert_equal 1, service.sent.length
|
121
|
+
assert_equal info.file_uuid, service.sent[0][:message].to
|
122
|
+
assert_equal ["FINISH"], service.sent[0][:message].body
|
123
|
+
|
124
|
+
assert info.finished?, "Did not mark info object as finished"
|
125
|
+
assert_not_nil info.wait_for_finish(1)
|
126
|
+
end
|
127
|
+
|
128
|
+
it "triggers a completion block when the file has been fully uploaded" do
|
129
|
+
info = receiver.receive_file(
|
130
|
+
File.size(file_path),
|
131
|
+
"9cb63cb779e8c571db3199b783a36cc43cd9e7c076beeb496c39e9cc06196dc5"
|
132
|
+
)
|
133
|
+
completion_called = false
|
134
|
+
info.on_complete do
|
135
|
+
completion_called = true
|
136
|
+
end
|
137
|
+
|
138
|
+
# Finish the file
|
139
|
+
receiver.receive_message("sender_ident", start_message(info.file_uuid))
|
140
|
+
receiver.receive_message("sender_ident", chunk(info.file_uuid))
|
141
|
+
|
142
|
+
info.wait_for_finish(1)
|
143
|
+
|
144
|
+
assert completion_called, "The completion block was not called"
|
145
|
+
end
|
146
|
+
|
147
|
+
it "does not trigger completion block on a failed upload" do
|
148
|
+
info = receiver.receive_file(File.size(file_path), "bad-checksum")
|
149
|
+
completion_called = false
|
150
|
+
info.on_complete do
|
151
|
+
completion_called = true
|
152
|
+
end
|
153
|
+
|
154
|
+
# Finish the file
|
155
|
+
receiver.receive_message("sender_ident", start_message(info.file_uuid))
|
156
|
+
receiver.receive_message("sender_ident", chunk(info.file_uuid))
|
157
|
+
|
158
|
+
info.wait_for_finish(1)
|
159
|
+
|
160
|
+
assert_false completion_called, "The completion block was called when it shouldn't have"
|
161
|
+
end
|
162
|
+
|
163
|
+
it "does not fall over if the completion block throws an error" do
|
164
|
+
info = receiver.receive_file(
|
165
|
+
File.size(file_path),
|
166
|
+
"9cb63cb779e8c571db3199b783a36cc43cd9e7c076beeb496c39e9cc06196dc5"
|
167
|
+
)
|
168
|
+
info.on_complete do
|
169
|
+
raise "This is an error zomg"
|
170
|
+
end
|
171
|
+
|
172
|
+
# Finish the file
|
173
|
+
receiver.receive_message("sender_ident", start_message(info.file_uuid))
|
174
|
+
receiver.receive_message("sender_ident", chunk(info.file_uuid))
|
175
|
+
|
176
|
+
info.wait_for_finish(1)
|
177
|
+
end
|
178
|
+
|
179
|
+
it "fails and deletes the file if the checksum does not match after upload complete" do
|
180
|
+
info = receiver.receive_file(File.size(file_path), "invalid")
|
181
|
+
receiver.receive_message("sender_ident", start_message(info.file_uuid))
|
182
|
+
service.sent = []
|
183
|
+
|
184
|
+
receiver.receive_message("sender_ident", chunk(info.file_uuid))
|
185
|
+
|
186
|
+
assert_false File.exists?(info.uploaded_path)
|
187
|
+
|
188
|
+
error_message = service.sent[0][:message]
|
189
|
+
assert_not_nil error_message
|
190
|
+
assert_equal info.file_uuid, error_message.to
|
191
|
+
assert_equal "ERROR", error_message.body[0]
|
192
|
+
assert_equal "Checksum did not match the uploaded file", error_message.body[1]
|
193
|
+
end
|
194
|
+
|
195
|
+
it "supports receiving file data chunks out-of-order" do
|
196
|
+
receiver.chunk_size = 5
|
197
|
+
info = receiver.receive_file(
|
198
|
+
13, "c30facc0146cfaf7e64fea5399ccb2707a060c2d739218a1f3b20b15b8d6e89d"
|
199
|
+
)
|
200
|
+
receiver.receive_message("sender_ident", start_message(info.file_uuid))
|
201
|
+
service.sent = []
|
202
|
+
|
203
|
+
receiver.receive_message("sender_ident", chunk(info.file_uuid, "ry!", offset: 10, size: 3))
|
204
|
+
receiver.receive_message("sender_ident", chunk(info.file_uuid, "Hello", offset: 0, size: 5))
|
205
|
+
receiver.receive_message("sender_ident", chunk(info.file_uuid, " Pant", offset: 5, size: 5))
|
206
|
+
|
207
|
+
success_message = service.sent[0][:message]
|
208
|
+
assert_equal "FINISH", success_message.body[0]
|
209
|
+
|
210
|
+
assert File.exists?(info.uploaded_path), "File was baleted?!"
|
211
|
+
assert_equal "Hello Pantry!", File.read(info.uploaded_path)
|
212
|
+
end
|
213
|
+
|
214
|
+
end
|
@@ -0,0 +1,110 @@
|
|
1
|
+
require 'unit/test_helper'
|
2
|
+
|
3
|
+
describe Pantry::Communication::FileService::SendFile do
|
4
|
+
|
5
|
+
mock_ui!
|
6
|
+
|
7
|
+
class FakeSendService
|
8
|
+
attr_accessor :sent
|
9
|
+
def initialize
|
10
|
+
@sent = []
|
11
|
+
end
|
12
|
+
def send_message(identity, message)
|
13
|
+
@sent << {identity: identity, message: message}
|
14
|
+
end
|
15
|
+
end
|
16
|
+
|
17
|
+
let(:service) { FakeSendService.new }
|
18
|
+
let(:file_path) { fixture_path("file_to_upload") }
|
19
|
+
let(:sender) { Pantry::Communication::FileService::SendFile.new(service) }
|
20
|
+
|
21
|
+
def fetch(uuid, seek, size)
|
22
|
+
chunk = Pantry::Message.new
|
23
|
+
chunk.to = uuid
|
24
|
+
chunk << "FETCH"
|
25
|
+
chunk << seek.to_s
|
26
|
+
chunk << size.to_s
|
27
|
+
chunk
|
28
|
+
end
|
29
|
+
|
30
|
+
describe "#send_file" do
|
31
|
+
it "opens the file and sends the receiver the START command" do
|
32
|
+
sender.send_file(file_path, "receiver_ident", "file_uuid")
|
33
|
+
|
34
|
+
assert_equal 1, service.sent.length
|
35
|
+
|
36
|
+
start_message = service.sent[0]
|
37
|
+
assert_equal "receiver_ident", start_message[:identity]
|
38
|
+
assert_equal "file_uuid", start_message[:message].to
|
39
|
+
assert_equal "START", start_message[:message].body[0]
|
40
|
+
end
|
41
|
+
|
42
|
+
it "returns a sending info object for callers to use" do
|
43
|
+
info = sender.send_file(file_path, "receiver_ident", "file_uuid")
|
44
|
+
|
45
|
+
assert_not_nil info
|
46
|
+
assert_equal file_path, info.path
|
47
|
+
end
|
48
|
+
end
|
49
|
+
|
50
|
+
it "reads the requested chunk of file and sends it along to the receiver" do
|
51
|
+
sender.send_file(file_path, "receiver", "file_uuid")
|
52
|
+
service.sent = []
|
53
|
+
|
54
|
+
sender.receive_message("receiver", fetch("file_uuid", 0, 5))
|
55
|
+
|
56
|
+
assert_equal 1, service.sent.length
|
57
|
+
|
58
|
+
chunk_data = service.sent[0][:message]
|
59
|
+
|
60
|
+
assert_equal "file_uuid", chunk_data.to
|
61
|
+
assert_equal "CHUNK", chunk_data.body[0]
|
62
|
+
assert_equal "Hello", chunk_data.body[1]
|
63
|
+
assert_equal 0, chunk_data[:chunk_offset]
|
64
|
+
assert_equal 5, chunk_data[:chunk_size]
|
65
|
+
end
|
66
|
+
|
67
|
+
it "supports sending multiple files at a time (keyed by UUID)" do
|
68
|
+
sender.send_file(file_path, "receiver", "uuid1")
|
69
|
+
sender.send_file(file_path, "receiver", "uuid2")
|
70
|
+
sender.send_file(file_path, "receiver", "uuid3")
|
71
|
+
service.sent = []
|
72
|
+
|
73
|
+
sender.receive_message("receiver", fetch("uuid1", 0, 1))
|
74
|
+
sender.receive_message("receiver", fetch("uuid2", 1, 1))
|
75
|
+
sender.receive_message("receiver", fetch("uuid3", 2, 1))
|
76
|
+
|
77
|
+
assert_equal "uuid1", service.sent[0][:message].to
|
78
|
+
assert_equal "H", service.sent[0][:message].body[1]
|
79
|
+
|
80
|
+
assert_equal "uuid2", service.sent[1][:message].to
|
81
|
+
assert_equal "e", service.sent[1][:message].body[1]
|
82
|
+
|
83
|
+
assert_equal "uuid3", service.sent[2][:message].to
|
84
|
+
assert_equal "l", service.sent[2][:message].body[1]
|
85
|
+
end
|
86
|
+
|
87
|
+
it "ignores FETCH requests of an unknown uuid" do
|
88
|
+
sender.receive_message("receiver", fetch("uuid1", 0, 1))
|
89
|
+
assert_equal 0, service.sent.length
|
90
|
+
end
|
91
|
+
|
92
|
+
it "closes up the file associated with the UUID on FINISH and notifies info" do
|
93
|
+
info = sender.send_file(file_path, "receiver", "uuid")
|
94
|
+
|
95
|
+
finish = Pantry::Message.new
|
96
|
+
finish.to = "uuid"
|
97
|
+
finish << "FINISH"
|
98
|
+
|
99
|
+
sender.receive_message("receiver", finish)
|
100
|
+
|
101
|
+
# See that further requests to this UUID are dropped
|
102
|
+
service.sent = []
|
103
|
+
sender.receive_message("receiver", fetch("uuid", 0, 1))
|
104
|
+
assert_equal [], service.sent
|
105
|
+
|
106
|
+
assert info.finished?, "Info object was not finished"
|
107
|
+
assert_not_nil info.wait_for_finish(1)
|
108
|
+
end
|
109
|
+
|
110
|
+
end
|
@@ -0,0 +1,56 @@
|
|
1
|
+
require 'unit/test_helper'
|
2
|
+
|
3
|
+
describe Pantry::Communication::FileService do
|
4
|
+
|
5
|
+
let(:security) { Pantry::Communication::Security::NullSecurity.new }
|
6
|
+
let(:file_service) { Pantry::Communication::FileService.new("host", "port", security) }
|
7
|
+
|
8
|
+
describe "#start_server" do
|
9
|
+
it "binds to the host/port when starting on the server" do
|
10
|
+
Celluloid::ZMQ::RouterSocket.any_instance.expects(:bind).with("tcp://host:port")
|
11
|
+
|
12
|
+
file_service.start_server
|
13
|
+
end
|
14
|
+
|
15
|
+
it "has the current security handler configure sockets" do
|
16
|
+
Celluloid::ZMQ::RouterSocket.any_instance.stubs(:bind)
|
17
|
+
security.expects(:configure_socket)
|
18
|
+
|
19
|
+
file_service.start_server
|
20
|
+
end
|
21
|
+
end
|
22
|
+
|
23
|
+
describe "#start_client" do
|
24
|
+
it "connects to the known server when starting on the client" do
|
25
|
+
Celluloid::ZMQ::RouterSocket.any_instance.expects(:connect).with("tcp://host:port")
|
26
|
+
|
27
|
+
file_service.start_client
|
28
|
+
end
|
29
|
+
|
30
|
+
it "has the current security handler configure sockets" do
|
31
|
+
Celluloid::ZMQ::RouterSocket.any_instance.stubs(:connect)
|
32
|
+
security.expects(:configure_socket)
|
33
|
+
|
34
|
+
file_service.start_client
|
35
|
+
end
|
36
|
+
end
|
37
|
+
|
38
|
+
it "builds receive-file information, setting the current socket's identity" do
|
39
|
+
info = file_service.receive_file(100, "checksum")
|
40
|
+
|
41
|
+
assert_not_nil info
|
42
|
+
assert_equal file_service.identity, info.receiver_uuid
|
43
|
+
end
|
44
|
+
|
45
|
+
it "sends a message to a specific identity" do
|
46
|
+
message = Pantry::Message.new
|
47
|
+
identity = "123abc"
|
48
|
+
|
49
|
+
Celluloid::ZMQ::RouterSocket.any_instance.expects(:write).with do |message|
|
50
|
+
assert_equal message[0], "123abc"
|
51
|
+
end
|
52
|
+
|
53
|
+
file_service.send_message(identity, message)
|
54
|
+
end
|
55
|
+
|
56
|
+
end
|