pantry 0.0.0 → 0.1.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.
- 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,79 @@
|
|
|
1
|
+
require 'unit/test_helper'
|
|
2
|
+
|
|
3
|
+
describe Pantry::Logger do
|
|
4
|
+
|
|
5
|
+
let(:mock_logger) {
|
|
6
|
+
logger = stub
|
|
7
|
+
logger.stubs(:level=)
|
|
8
|
+
logger
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
after do
|
|
12
|
+
# Unset global state caused by these tests
|
|
13
|
+
Celluloid.logger = nil
|
|
14
|
+
end
|
|
15
|
+
|
|
16
|
+
it "is accessible through top level Pantry.logger" do
|
|
17
|
+
logger = Pantry.logger = Pantry::Logger.new
|
|
18
|
+
assert_equal logger, Pantry.logger
|
|
19
|
+
end
|
|
20
|
+
|
|
21
|
+
it "sets the celluloid logger" do
|
|
22
|
+
logger = Pantry::Logger.new
|
|
23
|
+
|
|
24
|
+
assert Celluloid.logger.is_a?(::Logger), "Celluloid logger not set properly"
|
|
25
|
+
end
|
|
26
|
+
|
|
27
|
+
it "sets celluloid logger to a path if one given" do
|
|
28
|
+
config = Pantry::Config.new
|
|
29
|
+
config.log_to = File.expand_path("../../test.log", __FILE__)
|
|
30
|
+
|
|
31
|
+
logger = Pantry::Logger.new(config)
|
|
32
|
+
|
|
33
|
+
assert Celluloid.logger.is_a?(::Logger), "Celluloid logger not set properly"
|
|
34
|
+
end
|
|
35
|
+
|
|
36
|
+
it "sets the logger to go to Syslog if so configured" do
|
|
37
|
+
config = Pantry::Config.new
|
|
38
|
+
config.log_to = "syslog"
|
|
39
|
+
|
|
40
|
+
Syslog::Logger.expects(:new).with("pantry").returns(mock_logger)
|
|
41
|
+
|
|
42
|
+
logger = Pantry::Logger.new(config)
|
|
43
|
+
end
|
|
44
|
+
|
|
45
|
+
it "configures the Syslog program name if one given in the config" do
|
|
46
|
+
config = Pantry::Config.new
|
|
47
|
+
config.log_to = "syslog"
|
|
48
|
+
config.syslog_program_name = "pantry-client"
|
|
49
|
+
|
|
50
|
+
Syslog::Logger.expects(:new).with("pantry-client").returns(mock_logger)
|
|
51
|
+
|
|
52
|
+
logger = Pantry::Logger.new(config)
|
|
53
|
+
end
|
|
54
|
+
|
|
55
|
+
it "sets the log's level according to config.log_level" do
|
|
56
|
+
Pantry.config.log_level = :info
|
|
57
|
+
logger = Pantry::Logger.new
|
|
58
|
+
|
|
59
|
+
assert_equal ::Logger::INFO, Celluloid.logger.level
|
|
60
|
+
end
|
|
61
|
+
|
|
62
|
+
it "allows symbols when setting log level" do
|
|
63
|
+
config = Pantry::Config.new
|
|
64
|
+
config.log_level = :warn
|
|
65
|
+
|
|
66
|
+
logger = Pantry::Logger.new(config)
|
|
67
|
+
|
|
68
|
+
assert_equal ::Logger::WARN, Celluloid.logger.level
|
|
69
|
+
end
|
|
70
|
+
|
|
71
|
+
it "forwards unknown messages to the celluloid logger" do
|
|
72
|
+
logger = Pantry::Logger.new
|
|
73
|
+
|
|
74
|
+
Celluloid.logger.expects(:info).with("Message!")
|
|
75
|
+
|
|
76
|
+
logger.info("Message!")
|
|
77
|
+
end
|
|
78
|
+
|
|
79
|
+
end
|
|
@@ -0,0 +1,179 @@
|
|
|
1
|
+
require 'unit/test_helper'
|
|
2
|
+
|
|
3
|
+
describe Pantry::Message do
|
|
4
|
+
|
|
5
|
+
it "takes a message type in constructor" do
|
|
6
|
+
message = Pantry::Message.new("message_type")
|
|
7
|
+
assert_equal "message_type", message.type
|
|
8
|
+
end
|
|
9
|
+
|
|
10
|
+
it "generates a UUID on construction" do
|
|
11
|
+
message = Pantry::Message.new("message_type")
|
|
12
|
+
assert_not_nil message.uuid
|
|
13
|
+
assert message.uuid.length > 10
|
|
14
|
+
end
|
|
15
|
+
|
|
16
|
+
it "knows who the message is meant for" do
|
|
17
|
+
message = Pantry::Message.new("")
|
|
18
|
+
message.to = "stream"
|
|
19
|
+
assert_equal "stream", message.to
|
|
20
|
+
end
|
|
21
|
+
|
|
22
|
+
it "defaults the #to value to all (the empty string)" do
|
|
23
|
+
message = Pantry::Message.new("")
|
|
24
|
+
assert_equal "", message.to
|
|
25
|
+
end
|
|
26
|
+
|
|
27
|
+
it "can be given strings for the body parts" do
|
|
28
|
+
message = Pantry::Message.new("type")
|
|
29
|
+
message << "Part 1"
|
|
30
|
+
message << "Part 2"
|
|
31
|
+
|
|
32
|
+
assert_equal ["Part 1", "Part 2"], message.body
|
|
33
|
+
end
|
|
34
|
+
|
|
35
|
+
it "can be given the identity of the sending party" do
|
|
36
|
+
message = Pantry::Message.new("type")
|
|
37
|
+
message.from = "server1"
|
|
38
|
+
|
|
39
|
+
assert_equal "server1", message.from
|
|
40
|
+
end
|
|
41
|
+
|
|
42
|
+
it "can pull the identity string from an object that responds to identity" do
|
|
43
|
+
message = Pantry::Message.new("type")
|
|
44
|
+
client = Pantry::Client.new identity: "johnsonville"
|
|
45
|
+
message.from = client
|
|
46
|
+
|
|
47
|
+
assert_equal "johnsonville", message.from
|
|
48
|
+
end
|
|
49
|
+
|
|
50
|
+
it "can be flagged to require a response" do
|
|
51
|
+
message = Pantry::Message.new("type")
|
|
52
|
+
message.requires_response!
|
|
53
|
+
|
|
54
|
+
assert message.requires_response?
|
|
55
|
+
end
|
|
56
|
+
|
|
57
|
+
it "can build a response version of itself" do
|
|
58
|
+
message = Pantry::Message.new("type")
|
|
59
|
+
message << "Body part 1"
|
|
60
|
+
message << "Body part 2"
|
|
61
|
+
message.to = "server"
|
|
62
|
+
message.from = "client"
|
|
63
|
+
message.forwarded!
|
|
64
|
+
message.requires_response!
|
|
65
|
+
|
|
66
|
+
response = message.build_response
|
|
67
|
+
|
|
68
|
+
assert_equal "type", response.type
|
|
69
|
+
assert_equal [], response.body
|
|
70
|
+
assert_false response.requires_response?, "Message shouldn't require a response"
|
|
71
|
+
assert_equal "client", response.to
|
|
72
|
+
assert_equal "server", response.from
|
|
73
|
+
assert response.forwarded?
|
|
74
|
+
|
|
75
|
+
assert_equal message.uuid, response.uuid
|
|
76
|
+
end
|
|
77
|
+
|
|
78
|
+
it "clones custom metadata in a response message" do
|
|
79
|
+
message = Pantry::Message.new("type")
|
|
80
|
+
message[:custom_data] = "one"
|
|
81
|
+
|
|
82
|
+
response = message.build_response
|
|
83
|
+
|
|
84
|
+
assert_equal "one", response[:custom_data]
|
|
85
|
+
|
|
86
|
+
response[:custom_data] = "two"
|
|
87
|
+
assert_equal "one", message[:custom_data]
|
|
88
|
+
assert_equal "two", response[:custom_data]
|
|
89
|
+
end
|
|
90
|
+
|
|
91
|
+
it "can be flagged as being forwarded" do
|
|
92
|
+
message = Pantry::Message.new("type")
|
|
93
|
+
assert_false message.forwarded?
|
|
94
|
+
|
|
95
|
+
message.forwarded!
|
|
96
|
+
assert message.forwarded?
|
|
97
|
+
end
|
|
98
|
+
|
|
99
|
+
it "has a hash of metadata" do
|
|
100
|
+
message = Pantry::Message.new
|
|
101
|
+
message.type = "read_stuff"
|
|
102
|
+
message.requires_response!
|
|
103
|
+
message.forwarded!
|
|
104
|
+
message.from = "99 Luftballoons"
|
|
105
|
+
message.to = "streamer"
|
|
106
|
+
|
|
107
|
+
assert_not_nil message.metadata[:uuid]
|
|
108
|
+
assert_equal "read_stuff", message.metadata[:type]
|
|
109
|
+
assert_equal "99 Luftballoons", message.metadata[:from]
|
|
110
|
+
assert_equal "streamer", message.metadata[:to]
|
|
111
|
+
assert message.metadata[:requires_response]
|
|
112
|
+
assert message.metadata[:forwarded]
|
|
113
|
+
end
|
|
114
|
+
|
|
115
|
+
it "ensures the #to field is always a string when writing metadata" do
|
|
116
|
+
message = Pantry::Message.new
|
|
117
|
+
assert_equal "", message.metadata[:to]
|
|
118
|
+
end
|
|
119
|
+
|
|
120
|
+
it "knows if it came from the server or a client" do
|
|
121
|
+
message = Pantry::Message.new
|
|
122
|
+
message.from = Pantry::SERVER_IDENTITY
|
|
123
|
+
|
|
124
|
+
assert message.from_server?
|
|
125
|
+
end
|
|
126
|
+
|
|
127
|
+
it "takes a hash of metadata and parses out approriate values" do
|
|
128
|
+
message = Pantry::Message.new
|
|
129
|
+
message.metadata = {
|
|
130
|
+
type: "read_stuff",
|
|
131
|
+
requires_response: true,
|
|
132
|
+
forwarded: true,
|
|
133
|
+
from: "99 Luftballoons",
|
|
134
|
+
to: "streamer",
|
|
135
|
+
uuid: "123-4567-890-1234"
|
|
136
|
+
}
|
|
137
|
+
|
|
138
|
+
assert_equal "123-4567-890-1234", message.uuid
|
|
139
|
+
assert_equal "read_stuff", message.type
|
|
140
|
+
assert_equal "99 Luftballoons", message.from
|
|
141
|
+
assert_equal "streamer", message.to
|
|
142
|
+
assert message.requires_response?
|
|
143
|
+
assert message.forwarded?
|
|
144
|
+
end
|
|
145
|
+
|
|
146
|
+
it "ensures the #to field is always a string when reading metadata" do
|
|
147
|
+
message = Pantry::Message.new
|
|
148
|
+
message.metadata = {
|
|
149
|
+
to: nil,
|
|
150
|
+
}
|
|
151
|
+
assert_equal "", message.to
|
|
152
|
+
end
|
|
153
|
+
|
|
154
|
+
it "allows custom metadata entries" do
|
|
155
|
+
message = Pantry::Message.new
|
|
156
|
+
message[:metadata_1] = "my metadata"
|
|
157
|
+
message[:some_name] = "johnson"
|
|
158
|
+
|
|
159
|
+
assert_equal "my metadata", message[:metadata_1]
|
|
160
|
+
assert_equal "johnson", message[:some_name]
|
|
161
|
+
|
|
162
|
+
assert_equal "my metadata", message.metadata[:custom][:metadata_1]
|
|
163
|
+
assert_equal "johnson", message.metadata[:custom][:some_name]
|
|
164
|
+
end
|
|
165
|
+
|
|
166
|
+
it "loads unknown metadata keys into the custom metadata" do
|
|
167
|
+
message = Pantry::Message.new
|
|
168
|
+
message.metadata = {
|
|
169
|
+
custom: {
|
|
170
|
+
metadata_1: "my metadata",
|
|
171
|
+
some_name: "johnson"
|
|
172
|
+
}
|
|
173
|
+
}
|
|
174
|
+
|
|
175
|
+
assert_equal "my metadata", message[:metadata_1]
|
|
176
|
+
assert_equal "johnson", message[:some_name]
|
|
177
|
+
end
|
|
178
|
+
|
|
179
|
+
end
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
require 'unit/test_helper'
|
|
2
|
+
|
|
3
|
+
describe Pantry::MultiCommand do
|
|
4
|
+
|
|
5
|
+
class TestPart1 < Pantry::Command
|
|
6
|
+
def perform(message)
|
|
7
|
+
[1, client.identity, message.type]
|
|
8
|
+
end
|
|
9
|
+
end
|
|
10
|
+
|
|
11
|
+
class TestPart2 < Pantry::Command
|
|
12
|
+
def perform(message)
|
|
13
|
+
[2, client.identity, message.type]
|
|
14
|
+
end
|
|
15
|
+
end
|
|
16
|
+
|
|
17
|
+
class TestPart3 < Pantry::Command
|
|
18
|
+
def perform(message)
|
|
19
|
+
[3, client.identity, message.type]
|
|
20
|
+
end
|
|
21
|
+
end
|
|
22
|
+
|
|
23
|
+
class TestMultiCommand < Pantry::MultiCommand
|
|
24
|
+
performs [
|
|
25
|
+
TestPart1,
|
|
26
|
+
TestPart2,
|
|
27
|
+
TestPart3
|
|
28
|
+
]
|
|
29
|
+
end
|
|
30
|
+
|
|
31
|
+
it "runs multiple commands in order, combining return values" do
|
|
32
|
+
client = Pantry::Client.new identity: "Client"
|
|
33
|
+
command = TestMultiCommand.new
|
|
34
|
+
command.client = client
|
|
35
|
+
|
|
36
|
+
results = command.perform(Pantry::Message.new("Message"))
|
|
37
|
+
|
|
38
|
+
assert_equal [
|
|
39
|
+
[1, "Client", "Message"],
|
|
40
|
+
[2, "Client", "Message"],
|
|
41
|
+
[3, "Client", "Message"],
|
|
42
|
+
], results
|
|
43
|
+
end
|
|
44
|
+
|
|
45
|
+
end
|
|
@@ -0,0 +1,218 @@
|
|
|
1
|
+
require 'unit/test_helper'
|
|
2
|
+
|
|
3
|
+
describe OptParsePlus do
|
|
4
|
+
|
|
5
|
+
it "adds block and option support to optparse" do
|
|
6
|
+
parser = OptParsePlus.new
|
|
7
|
+
parser.add_options do
|
|
8
|
+
option "-a", "--application APPLICATION", String, "An option"
|
|
9
|
+
end
|
|
10
|
+
|
|
11
|
+
command_line = %w(-a application_name)
|
|
12
|
+
options = parser.parse!(command_line)
|
|
13
|
+
|
|
14
|
+
assert_equal "application_name", options['application']
|
|
15
|
+
assert_equal "application_name", options[:application]
|
|
16
|
+
assert_equal [], command_line
|
|
17
|
+
end
|
|
18
|
+
|
|
19
|
+
it "adds command support to optparse" do
|
|
20
|
+
parser = OptParsePlus.new
|
|
21
|
+
parser.add_command("one") do
|
|
22
|
+
option "-a", "--application APPLICATION", String, "An option"
|
|
23
|
+
end
|
|
24
|
+
|
|
25
|
+
command_line = %w(one -a application_name)
|
|
26
|
+
options = parser.parse!(command_line)
|
|
27
|
+
|
|
28
|
+
assert_equal "application_name", options['one']['application']
|
|
29
|
+
assert_equal "application_name", options[:one][:application]
|
|
30
|
+
assert_equal [], command_line
|
|
31
|
+
end
|
|
32
|
+
|
|
33
|
+
it "allows setting an explicit banner" do
|
|
34
|
+
parser = OptParsePlus.new
|
|
35
|
+
parser.banner "pantry [command]"
|
|
36
|
+
|
|
37
|
+
help_text = parser.help
|
|
38
|
+
assert_match /pantry \[command\]/, help_text
|
|
39
|
+
end
|
|
40
|
+
|
|
41
|
+
it "allows specifying a description" do
|
|
42
|
+
parser = OptParsePlus.new
|
|
43
|
+
parser.add_options do
|
|
44
|
+
description "This is interesting yes!"
|
|
45
|
+
end
|
|
46
|
+
|
|
47
|
+
help_text = parser.help
|
|
48
|
+
assert_match /This is interesting/, help_text
|
|
49
|
+
end
|
|
50
|
+
|
|
51
|
+
it "works with commands with no block" do
|
|
52
|
+
parser = OptParsePlus.new
|
|
53
|
+
parser.add_command("run")
|
|
54
|
+
|
|
55
|
+
options = parser.parse!(%w(run))
|
|
56
|
+
assert_equal "run", options.command_found
|
|
57
|
+
end
|
|
58
|
+
|
|
59
|
+
it "allows specifying argument usage in the command name" do
|
|
60
|
+
parser = OptParsePlus.new
|
|
61
|
+
parser.add_command("run COMMAND")
|
|
62
|
+
|
|
63
|
+
command_line = %w(run Something)
|
|
64
|
+
options = parser.parse!(command_line)
|
|
65
|
+
|
|
66
|
+
assert_equal "run", options.command_found
|
|
67
|
+
assert_equal %w(Something), command_line
|
|
68
|
+
end
|
|
69
|
+
|
|
70
|
+
it "gives the command options the arguments as per the description string (???)"
|
|
71
|
+
|
|
72
|
+
it "processes arguments in order to support global and command options" do
|
|
73
|
+
parser = OptParsePlus.new
|
|
74
|
+
parser.add_options do
|
|
75
|
+
option "-L", "--log-level LEVEL"
|
|
76
|
+
end
|
|
77
|
+
|
|
78
|
+
parser.add_command("run") do
|
|
79
|
+
option "-c", "--command COMMAND"
|
|
80
|
+
end
|
|
81
|
+
|
|
82
|
+
command_line = %w(-L debug run --command DoThisNow)
|
|
83
|
+
options = parser.parse!(command_line)
|
|
84
|
+
|
|
85
|
+
assert_equal "run", options.command_found
|
|
86
|
+
assert_equal "debug", options['log-level']
|
|
87
|
+
assert_equal "DoThisNow", options['run']['command']
|
|
88
|
+
end
|
|
89
|
+
|
|
90
|
+
it "groups commands together, sorting subcommands alphabetically" do
|
|
91
|
+
parser = OptParsePlus.new
|
|
92
|
+
parser.add_command("run") do
|
|
93
|
+
group "Exercise"
|
|
94
|
+
end
|
|
95
|
+
|
|
96
|
+
parser.add_command("bike") do
|
|
97
|
+
group "Exercise"
|
|
98
|
+
end
|
|
99
|
+
|
|
100
|
+
parser.add_command("sleep") do
|
|
101
|
+
group "Lazy"
|
|
102
|
+
end
|
|
103
|
+
|
|
104
|
+
output, err = capture_io do
|
|
105
|
+
parser.parse!(%w(--help))
|
|
106
|
+
end
|
|
107
|
+
|
|
108
|
+
# Group subheadings
|
|
109
|
+
assert_match /Exercise commands/, output
|
|
110
|
+
assert_match /Lazy commands/, output
|
|
111
|
+
|
|
112
|
+
# Check alphabetical sort
|
|
113
|
+
assert_match /bike.*run/m, output
|
|
114
|
+
end
|
|
115
|
+
|
|
116
|
+
it "adds a global help option" do
|
|
117
|
+
parser = OptParsePlus.new
|
|
118
|
+
|
|
119
|
+
options = nil
|
|
120
|
+
output, err = capture_io do
|
|
121
|
+
options = parser.parse!(%w(-h))
|
|
122
|
+
end
|
|
123
|
+
|
|
124
|
+
assert_match /Show this help message/, output
|
|
125
|
+
assert options['help'], "Help flag was not set"
|
|
126
|
+
end
|
|
127
|
+
|
|
128
|
+
it "adds help option to each command configured" do
|
|
129
|
+
parser = OptParsePlus.new
|
|
130
|
+
parser.add_command("run")
|
|
131
|
+
|
|
132
|
+
options = nil
|
|
133
|
+
output, err = capture_io do
|
|
134
|
+
options = parser.parse!(%w(run --help))
|
|
135
|
+
end
|
|
136
|
+
|
|
137
|
+
assert_match /Show this help message/, output
|
|
138
|
+
assert options['help']
|
|
139
|
+
end
|
|
140
|
+
|
|
141
|
+
it "allows explicitly getting the help text" do
|
|
142
|
+
parser = OptParsePlus.new
|
|
143
|
+
help_text = parser.help
|
|
144
|
+
|
|
145
|
+
assert_match /Show this help message/, help_text
|
|
146
|
+
end
|
|
147
|
+
|
|
148
|
+
it "includes all known commands in the top-level help text" do
|
|
149
|
+
parser = OptParsePlus.new
|
|
150
|
+
parser.add_command("run") do
|
|
151
|
+
description "Run something"
|
|
152
|
+
end
|
|
153
|
+
|
|
154
|
+
parser.add_command("stop") do
|
|
155
|
+
description "Stop something from running"
|
|
156
|
+
end
|
|
157
|
+
|
|
158
|
+
parser.add_command("stock ITEM") do
|
|
159
|
+
description "Stock the item"
|
|
160
|
+
end
|
|
161
|
+
|
|
162
|
+
help_text = parser.help
|
|
163
|
+
|
|
164
|
+
assert_match /run\s+Run something/, help_text
|
|
165
|
+
assert_match /stop\s+Stop something/, help_text
|
|
166
|
+
assert_match /stock\s+Stock the item/, help_text
|
|
167
|
+
end
|
|
168
|
+
|
|
169
|
+
it "only shows the first line of a command's description in top-level help" do
|
|
170
|
+
parser = OptParsePlus.new
|
|
171
|
+
parser.add_command("run") do
|
|
172
|
+
description "Run something.
|
|
173
|
+
Run fast.
|
|
174
|
+
Don't run slow"
|
|
175
|
+
end
|
|
176
|
+
|
|
177
|
+
help_text = parser.help
|
|
178
|
+
|
|
179
|
+
assert_match /Run something/, help_text
|
|
180
|
+
assert_no_match /Run fast/, help_text
|
|
181
|
+
assert_no_match /Don't run slow/, help_text
|
|
182
|
+
end
|
|
183
|
+
|
|
184
|
+
it "includes sub-command descriptions and banner strings in help text" do
|
|
185
|
+
parser = OptParsePlus.new
|
|
186
|
+
parser.add_command("display MESSAGE") do
|
|
187
|
+
description "Show the given message"
|
|
188
|
+
option "-c", "--cap", "Capitalize the message"
|
|
189
|
+
end
|
|
190
|
+
|
|
191
|
+
help_text, error = capture_io do
|
|
192
|
+
parser.parse!(["display", "--help"])
|
|
193
|
+
end
|
|
194
|
+
|
|
195
|
+
assert_match /display \[options\] MESSAGE/, help_text
|
|
196
|
+
assert_match /-c, --cap/, help_text
|
|
197
|
+
assert_match /Capitalize the message/, help_text
|
|
198
|
+
assert_match /Show the given message/, help_text
|
|
199
|
+
end
|
|
200
|
+
|
|
201
|
+
it "cleans up extra white space in full command descriptions" do
|
|
202
|
+
parser = OptParsePlus.new
|
|
203
|
+
parser.add_command("display MESSAGE") do
|
|
204
|
+
description "Show the given message.
|
|
205
|
+
Requires a MESSAGE to be passed in.
|
|
206
|
+
and will Error out otherwise"
|
|
207
|
+
end
|
|
208
|
+
|
|
209
|
+
help_text, error = capture_io do
|
|
210
|
+
parser.parse!(["display", "--help"])
|
|
211
|
+
end
|
|
212
|
+
|
|
213
|
+
assert_match /^Show the given message/, help_text
|
|
214
|
+
assert_match /^Requires a MESSAGE/, help_text
|
|
215
|
+
assert_match /^and will Error/, help_text
|
|
216
|
+
end
|
|
217
|
+
|
|
218
|
+
end
|