scout_agent 3.0.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/AUTHORS +4 -0
- data/CHANGELOG +3 -0
- data/COPYING +340 -0
- data/INSTALL +17 -0
- data/LICENSE +6 -0
- data/README +3 -0
- data/Rakefile +123 -0
- data/TODO +3 -0
- data/bin/scout_agent +11 -0
- data/lib/scout_agent.rb +73 -0
- data/lib/scout_agent/agent.rb +42 -0
- data/lib/scout_agent/agent/communication_agent.rb +85 -0
- data/lib/scout_agent/agent/master_agent.rb +301 -0
- data/lib/scout_agent/api.rb +241 -0
- data/lib/scout_agent/assignment.rb +105 -0
- data/lib/scout_agent/assignment/configuration.rb +30 -0
- data/lib/scout_agent/assignment/identify.rb +110 -0
- data/lib/scout_agent/assignment/queue.rb +95 -0
- data/lib/scout_agent/assignment/reset.rb +91 -0
- data/lib/scout_agent/assignment/snapshot.rb +92 -0
- data/lib/scout_agent/assignment/start.rb +149 -0
- data/lib/scout_agent/assignment/status.rb +44 -0
- data/lib/scout_agent/assignment/stop.rb +60 -0
- data/lib/scout_agent/assignment/upload_log.rb +61 -0
- data/lib/scout_agent/core_extensions.rb +260 -0
- data/lib/scout_agent/database.rb +386 -0
- data/lib/scout_agent/database/mission_log.rb +282 -0
- data/lib/scout_agent/database/queue.rb +126 -0
- data/lib/scout_agent/database/snapshots.rb +187 -0
- data/lib/scout_agent/database/statuses.rb +65 -0
- data/lib/scout_agent/dispatcher.rb +157 -0
- data/lib/scout_agent/id_card.rb +143 -0
- data/lib/scout_agent/lifeline.rb +243 -0
- data/lib/scout_agent/mission.rb +212 -0
- data/lib/scout_agent/order.rb +58 -0
- data/lib/scout_agent/order/check_in_order.rb +32 -0
- data/lib/scout_agent/order/snapshot_order.rb +33 -0
- data/lib/scout_agent/plan.rb +306 -0
- data/lib/scout_agent/server.rb +123 -0
- data/lib/scout_agent/tracked.rb +59 -0
- data/lib/scout_agent/wire_tap.rb +513 -0
- data/setup.rb +1360 -0
- data/test/tc_core_extensions.rb +89 -0
- data/test/tc_id_card.rb +115 -0
- data/test/tc_plan.rb +285 -0
- data/test/test_helper.rb +22 -0
- data/test/ts_all.rb +7 -0
- metadata +171 -0
@@ -0,0 +1,89 @@
|
|
1
|
+
#!/usr/bin/env ruby -wKU
|
2
|
+
|
3
|
+
require "test/unit"
|
4
|
+
|
5
|
+
require "scout_agent/core_extensions"
|
6
|
+
|
7
|
+
class TestCoreExtensions < Test::Unit::TestCase
|
8
|
+
def test_to_word_list
|
9
|
+
{ %w[] => "",
|
10
|
+
%w[one] => "one",
|
11
|
+
%w[one two] => "one and two",
|
12
|
+
%w[one two three] => "one, two, and three",
|
13
|
+
%w[one two three four] => "one, two, three, and four" }.each do |arr, str|
|
14
|
+
assert_equal(str, arr.to_word_list)
|
15
|
+
end
|
16
|
+
end
|
17
|
+
|
18
|
+
def test_to_word_list_with_custom_conjunction
|
19
|
+
assert_equal("one, two, or three", %w[one two three].to_word_list("or"))
|
20
|
+
end
|
21
|
+
|
22
|
+
def test_string_camel_case
|
23
|
+
{ "class_name" => "ClassName",
|
24
|
+
"symbols::are/removed" => "SymbolsAreRemoved",
|
25
|
+
"spaces are removed" => "SpacesAreRemoved",
|
26
|
+
"agent_99_smart" => "Agent99Smart",
|
27
|
+
"NoChange" => "NoChange" }.each do |snake_case, camel_case|
|
28
|
+
assert_equal(camel_case, snake_case.CamelCase)
|
29
|
+
end
|
30
|
+
end
|
31
|
+
|
32
|
+
def test_string_camel_case_alias
|
33
|
+
str = "test_string"
|
34
|
+
assert_equal(str.CamelCase, str.camel_case)
|
35
|
+
end
|
36
|
+
|
37
|
+
def test_string_snake_case
|
38
|
+
{ "ClassName" => "class_name",
|
39
|
+
"Symbols::Are/Unified" => "symbols_are_unified",
|
40
|
+
"Spaces Are Converted" => "spaces_are_converted",
|
41
|
+
"Agent99Smart" => "agent_99_smart",
|
42
|
+
"no_change" => "no_change" }.each do |camel_case, snake_case|
|
43
|
+
assert_equal(snake_case, camel_case.snake_case)
|
44
|
+
end
|
45
|
+
end
|
46
|
+
|
47
|
+
def test_string_trim_with_default
|
48
|
+
heredoc = <<-END_DEFAULT.trim
|
49
|
+
I am indented on purpose.
|
50
|
+
Leading space should be removed.
|
51
|
+
|
52
|
+
but not these two spaces
|
53
|
+
END_DEFAULT
|
54
|
+
assert_match(/^I/, heredoc)
|
55
|
+
assert_match(/^Leading/, heredoc)
|
56
|
+
assert_match(/^ but/, heredoc)
|
57
|
+
end
|
58
|
+
|
59
|
+
def test_string_trim_with_width
|
60
|
+
heredoc = <<-END_WIDTH.trim(2)
|
61
|
+
I'm indented four,
|
62
|
+
but we will just trim two.
|
63
|
+
END_WIDTH
|
64
|
+
assert_match(/^ I'm/, heredoc)
|
65
|
+
assert_match(/^ but/, heredoc)
|
66
|
+
end
|
67
|
+
|
68
|
+
def test_to_question
|
69
|
+
assert_match(/\? \z/, "A simple question?\n\t ".to_question)
|
70
|
+
end
|
71
|
+
|
72
|
+
def test_word_wrap_with_default
|
73
|
+
assert_no_match(/^.{61}/, ("A short and simple string." * 1000).word_wrap)
|
74
|
+
end
|
75
|
+
|
76
|
+
def test_word_wrap_with_width
|
77
|
+
assert_no_match( /^.{11}/,
|
78
|
+
("A short and simple string." * 1000).word_wrap(10) )
|
79
|
+
end
|
80
|
+
|
81
|
+
def test_word_wrap_skips_unbroken_content
|
82
|
+
assert_equal("0123456789", "0123456789".word_wrap(4))
|
83
|
+
end
|
84
|
+
|
85
|
+
def test_word_wrap_strips_and_simplifes_space
|
86
|
+
assert_equal( "one two\nthree",
|
87
|
+
" \t\none\n \ttwo three\n\n \t".word_wrap(10) )
|
88
|
+
end
|
89
|
+
end
|
data/test/tc_id_card.rb
ADDED
@@ -0,0 +1,115 @@
|
|
1
|
+
#!/usr/bin/env ruby -wKU
|
2
|
+
|
3
|
+
require "test_helper"
|
4
|
+
|
5
|
+
require "scout_agent"
|
6
|
+
|
7
|
+
class TestIDCard < Test::Unit::TestCase
|
8
|
+
def setup
|
9
|
+
plan.prefix_path = test_prefix
|
10
|
+
plan.build_pid_dir(Process.egid)
|
11
|
+
end
|
12
|
+
|
13
|
+
def teardown
|
14
|
+
id_card(:test).revoke
|
15
|
+
test_prefix.rmtree if test_prefix.exist?
|
16
|
+
plan.reset_defaults
|
17
|
+
end
|
18
|
+
|
19
|
+
def test_authorize_creates_pid_file
|
20
|
+
@card = id_card(:test)
|
21
|
+
assert(!@card.pid_file.exist?, "PID file already existed")
|
22
|
+
assert(@card.authorize, "Failed to authorize our PID")
|
23
|
+
assert(@card.pid_file.exist?, "PID wasn't created")
|
24
|
+
assert_equal("#{Process.pid}\n", @card.pid_file.read)
|
25
|
+
end
|
26
|
+
|
27
|
+
def test_authorize_fails_for_an_existing_pid
|
28
|
+
test_authorize_creates_pid_file # make sure we already have a file
|
29
|
+
assert(!@card.authorize, "Authorized with an existing PID file")
|
30
|
+
end
|
31
|
+
|
32
|
+
def test_authorize_will_clear_a_stale_pid_file
|
33
|
+
create_and_kill_another_process
|
34
|
+
card = id_card(:test)
|
35
|
+
assert_not_equal(Process.pid, card.pid_file.read)
|
36
|
+
assert(card.authorize, "Failed to replace stale PID file")
|
37
|
+
assert_equal("#{Process.pid}\n", card.pid_file.read)
|
38
|
+
end
|
39
|
+
|
40
|
+
def test_successful_authorize_updates_me
|
41
|
+
ScoutAgent::IDCard.me = nil
|
42
|
+
test_authorize_creates_pid_file
|
43
|
+
assert_equal(@card, ScoutAgent::IDCard.me)
|
44
|
+
end
|
45
|
+
|
46
|
+
def test_revoke_clears_a_pid_file
|
47
|
+
test_authorize_creates_pid_file # create a file
|
48
|
+
assert(@card.revoke, "Failed to clear file")
|
49
|
+
end
|
50
|
+
|
51
|
+
def test_revoke_return_true_if_cleared_false_otherwise
|
52
|
+
test_authorize_creates_pid_file # create a file
|
53
|
+
assert(@card.revoke, "Failed to clear file")
|
54
|
+
assert(!@card.revoke, "Clear a PID file that was already cleared")
|
55
|
+
end
|
56
|
+
|
57
|
+
def test_pid_file_is_named_file
|
58
|
+
card = id_card(:my_name)
|
59
|
+
assert_match(/my_name\.pid\z/, card.pid_file.to_s)
|
60
|
+
end
|
61
|
+
|
62
|
+
def test_pid_is_a_shorcut_for_reading_pid_file
|
63
|
+
test_authorize_creates_pid_file # create a file
|
64
|
+
assert_equal(@card.pid_file.read.to_i, @card.pid)
|
65
|
+
end
|
66
|
+
|
67
|
+
def test_pid_returns_nil_for_a_missing_pid_file
|
68
|
+
assert_nil(id_card(:does_not_exist).pid)
|
69
|
+
end
|
70
|
+
|
71
|
+
def test_signal_delivers_messages
|
72
|
+
received_message = false
|
73
|
+
trap("USR1") { received_message = true }
|
74
|
+
test_authorize_creates_pid_file
|
75
|
+
|
76
|
+
# have another process send us a signal
|
77
|
+
other_pid = fork { @card.signal("USR1") }
|
78
|
+
Process.wait(other_pid)
|
79
|
+
|
80
|
+
assert(received_message, "Didn't receive signal")
|
81
|
+
end
|
82
|
+
|
83
|
+
def test_signal_returns_false_for_missing_pid_files
|
84
|
+
assert(!id_card(:does_not_exist).signal(0), "Signal was sent without a PID")
|
85
|
+
end
|
86
|
+
|
87
|
+
def test_signal_errors_bubble_up_to_caller
|
88
|
+
create_and_kill_another_process
|
89
|
+
card = id_card(:test)
|
90
|
+
assert_raise(Errno::ESRCH) { card.signal("KILL") }
|
91
|
+
end
|
92
|
+
|
93
|
+
def test_to_s_includes_process_name_and_pid
|
94
|
+
test_authorize_creates_pid_file # make an identity
|
95
|
+
assert_equal("test (#{Process.pid})", @card.to_s)
|
96
|
+
end
|
97
|
+
|
98
|
+
def test_to_s_uses_unauthorized_for_a_missing_pid
|
99
|
+
assert_equal("missing (unauthorized)", id_card(:missing).to_s)
|
100
|
+
end
|
101
|
+
|
102
|
+
private
|
103
|
+
|
104
|
+
def id_card(*args)
|
105
|
+
ScoutAgent::IDCard.new(*args)
|
106
|
+
end
|
107
|
+
|
108
|
+
def create_and_kill_another_process
|
109
|
+
other_pid = fork do
|
110
|
+
test_authorize_creates_pid_file # make sure we claim the PID file
|
111
|
+
exit! # and exist without clearing it
|
112
|
+
end
|
113
|
+
Process.wait(other_pid)
|
114
|
+
end
|
115
|
+
end
|
data/test/tc_plan.rb
ADDED
@@ -0,0 +1,285 @@
|
|
1
|
+
#!/usr/bin/env ruby -wKU
|
2
|
+
|
3
|
+
require "test_helper"
|
4
|
+
require "tempfile"
|
5
|
+
|
6
|
+
require "scout_agent"
|
7
|
+
|
8
|
+
class TestPlan < Test::Unit::TestCase
|
9
|
+
def teardown
|
10
|
+
test_prefix.rmtree if test_prefix.exist?
|
11
|
+
end
|
12
|
+
|
13
|
+
############
|
14
|
+
### Type ###
|
15
|
+
############
|
16
|
+
|
17
|
+
def test_plan_is_a_customized_ostruct
|
18
|
+
assert_instance_of(OpenStruct, plan)
|
19
|
+
end
|
20
|
+
|
21
|
+
########################
|
22
|
+
### Loading a Config ###
|
23
|
+
########################
|
24
|
+
|
25
|
+
def test_updating_plan_from_a_config_file
|
26
|
+
c = load_config_file(<<-END_SETTINGS)
|
27
|
+
config.string_setting = "just a String"
|
28
|
+
config.integer_setting = 42
|
29
|
+
END_SETTINGS
|
30
|
+
assert_equal(plan, c)
|
31
|
+
assert_equal("just a String", c.string_setting)
|
32
|
+
assert_equal(42, c.integer_setting)
|
33
|
+
end
|
34
|
+
|
35
|
+
def test_exceptions_bubble_up_to_the_caller_from_config_file
|
36
|
+
assert_raise(RuntimeError) do
|
37
|
+
load_config_file('raise "Oops!"')
|
38
|
+
end
|
39
|
+
end
|
40
|
+
|
41
|
+
def test_updating_plan_from_switches
|
42
|
+
assert_nil(plan.switch_one)
|
43
|
+
assert_nil(plan.switch_two)
|
44
|
+
plan.update_from_switches(:switch_one => "One", :switch_two => "Two")
|
45
|
+
assert_equal("One", plan.switch_one)
|
46
|
+
assert_equal("Two", plan.switch_two)
|
47
|
+
end
|
48
|
+
|
49
|
+
################
|
50
|
+
### Defaults ###
|
51
|
+
################
|
52
|
+
|
53
|
+
def test_defaults_are_available_in_an_enumerable_list
|
54
|
+
assert_kind_of(Enumerable, plan.defaults)
|
55
|
+
end
|
56
|
+
|
57
|
+
# def test_agent_name_is_set
|
58
|
+
# assert_match(/\A\w+\z/, plan.agent_name)
|
59
|
+
# assert_equal( plan.agent_name.split("_"),
|
60
|
+
# plan.proper_agent_name.downcase.split(" ") )
|
61
|
+
# end
|
62
|
+
#
|
63
|
+
# def test_agent_namespace_returns_module_based_on_agent_name
|
64
|
+
# assert_equal(ScoutAgent, plan.agent_namespace)
|
65
|
+
# end
|
66
|
+
|
67
|
+
def test_all_paths_return_pathname_objects
|
68
|
+
%w[ prefix_path
|
69
|
+
os_config_path
|
70
|
+
os_db_path
|
71
|
+
os_pid_path
|
72
|
+
os_log_path
|
73
|
+
config_file
|
74
|
+
db_dir
|
75
|
+
pid_dir
|
76
|
+
log_dir ].each do |path|
|
77
|
+
assert_instance_of(Pathname, plan(path))
|
78
|
+
end
|
79
|
+
end
|
80
|
+
|
81
|
+
def test_prefix_path_defaults_to_the_root_path
|
82
|
+
assert_equal(Pathname.new("/"), plan.prefix_path)
|
83
|
+
end
|
84
|
+
|
85
|
+
def test_default_os_paths_are_set
|
86
|
+
%w[ os_config_path
|
87
|
+
os_db_path
|
88
|
+
os_pid_path
|
89
|
+
os_log_path ].each do |path|
|
90
|
+
assert_path_match(%r{\A(?:/\w+)+/?\z}, path)
|
91
|
+
end
|
92
|
+
end
|
93
|
+
|
94
|
+
def test_default_paths_are_set
|
95
|
+
assert_path_match(%r{\A(?:/\w+)+\.\w+\z}, :config_file)
|
96
|
+
%w[db_dir pid_dir log_dir].each do |dir|
|
97
|
+
assert_path_match(%r{\A(?:/\w+)+/?\z}, dir)
|
98
|
+
end
|
99
|
+
end
|
100
|
+
|
101
|
+
def test_server_url_is_set
|
102
|
+
assert_match(%r{\Ahttps://}, plan.server_url)
|
103
|
+
end
|
104
|
+
|
105
|
+
def test_run_as_daemon_is_set
|
106
|
+
assert(plan.run_as_daemon, "Daemon mode should default to on")
|
107
|
+
end
|
108
|
+
|
109
|
+
def test_run_as_daemon_alias
|
110
|
+
assert_equal(plan.run_as_daemon, plan.run_as_daemon?)
|
111
|
+
end
|
112
|
+
|
113
|
+
def test_user_choices_is_set
|
114
|
+
assert_equal(%w[daemon nobody], plan.user_choices)
|
115
|
+
end
|
116
|
+
|
117
|
+
def test_group_choices_is_set
|
118
|
+
assert_equal(%w[daemon nogroup], plan.group_choices)
|
119
|
+
end
|
120
|
+
|
121
|
+
def test_reset_defaults
|
122
|
+
current = plan.defaults.map { |name, _| [name, plan(name)] }
|
123
|
+
plan.defaults.each { |name, _| plan("#{name}=", "Junk!") }
|
124
|
+
current.each { |name, value| assert_not_equal(value, plan(name)) }
|
125
|
+
|
126
|
+
plan.reset_defaults
|
127
|
+
current.each { |name, value| assert_equal(value, plan(name)) }
|
128
|
+
end
|
129
|
+
|
130
|
+
####################
|
131
|
+
### Nested Paths ###
|
132
|
+
####################
|
133
|
+
|
134
|
+
def test_prefix_path_prepends_to_all_paths
|
135
|
+
%w[ os_config_path
|
136
|
+
os_db_path
|
137
|
+
os_pid_path
|
138
|
+
os_log_path
|
139
|
+
config_file
|
140
|
+
db_dir
|
141
|
+
pid_dir
|
142
|
+
log_dir ].each do |path|
|
143
|
+
configure(:prefix_path => test_prefix) do
|
144
|
+
assert_path_match(%r{\A#{test_prefix}/.+\z}, path)
|
145
|
+
end
|
146
|
+
end
|
147
|
+
end
|
148
|
+
|
149
|
+
def test_os_paths_prepends_to_full_paths
|
150
|
+
{ :config_file => :os_config_path,
|
151
|
+
:db_dir => :os_db_path,
|
152
|
+
:pid_dir => :os_pid_path,
|
153
|
+
:log_dir => :os_log_path }.each do |path, parent|
|
154
|
+
assert_prepends_path(path, parent)
|
155
|
+
end
|
156
|
+
end
|
157
|
+
|
158
|
+
def test_prefix_path_nests_with_os_paths
|
159
|
+
dir = "test_dir"
|
160
|
+
{ :config_file => :os_config_path,
|
161
|
+
:db_dir => :os_db_path,
|
162
|
+
:pid_dir => :os_pid_path,
|
163
|
+
:log_dir => :os_log_path }.each do |path, parent|
|
164
|
+
configure(:prefix_path => test_prefix, parent => dir) do
|
165
|
+
assert_path_match(%r{\A#{test_prefix}/#{dir}/.+\z}, path)
|
166
|
+
end
|
167
|
+
end
|
168
|
+
end
|
169
|
+
|
170
|
+
################
|
171
|
+
### Creation ###
|
172
|
+
################
|
173
|
+
|
174
|
+
def test_write_default_config_file_creates_a_readable_ruby_configuration_file
|
175
|
+
configure(:prefix_path => test_prefix) do
|
176
|
+
assert(!File.exist?(plan.config_file), "Configuration already existed")
|
177
|
+
assert(plan.write_default_config_file, "Could not create config file")
|
178
|
+
assert(File.exist?(plan.config_file), "Configuration not created")
|
179
|
+
assert_equal("755", plan.config_file.stat.mode.to_s(8)[-3..-1])
|
180
|
+
end
|
181
|
+
end
|
182
|
+
|
183
|
+
def test_write_default_config_file_wont_replace_an_existing_file
|
184
|
+
configure(:prefix_path => test_prefix) do
|
185
|
+
assert(plan.write_default_config_file, "Could not create config file")
|
186
|
+
assert(!plan.write_default_config_file, "Replaced config file")
|
187
|
+
end
|
188
|
+
end
|
189
|
+
|
190
|
+
def test_builders_fails_if_they_dont_have_permission
|
191
|
+
configure(:prefix_path => test_prefix) do
|
192
|
+
{ :write_default_config_file => :os_config_path,
|
193
|
+
:build_db_dir => :os_db_path,
|
194
|
+
:build_pid_dir => :os_pid_path,
|
195
|
+
:build_log_dir => :os_log_path }.each do |builder, dir|
|
196
|
+
plan(dir).mkpath
|
197
|
+
plan(dir).chmod(0444) # read only
|
198
|
+
args = builder == :write_default_config_file ? [ ] : [Process.egid]
|
199
|
+
assert(!plan(builder, *args), "Built without permission")
|
200
|
+
end
|
201
|
+
end
|
202
|
+
end
|
203
|
+
|
204
|
+
# def test_directory_builders_create_a_readable_and_writable_directory
|
205
|
+
# configure(:prefix_path => test_prefix) do
|
206
|
+
# %w[db_dir pid_dir log_dir].each do |dir|
|
207
|
+
# assert(!File.exist?(plan(dir)), "Directory already existed")
|
208
|
+
# assert(plan("build_#{dir}", Process.egid), "Could not create directory")
|
209
|
+
# assert(File.exist?(plan(dir)), "Directory not created")
|
210
|
+
# assert_equal("775", plan(dir).stat.mode.to_s(8)[-3..-1])
|
211
|
+
# end
|
212
|
+
# end
|
213
|
+
# end
|
214
|
+
|
215
|
+
###################
|
216
|
+
### Validations ###
|
217
|
+
###################
|
218
|
+
|
219
|
+
# def test_plan_is_present
|
220
|
+
# configure(:prefix_path => test_prefix) do
|
221
|
+
# assert(!plan.present?, "Card was present when missing")
|
222
|
+
# # add some config
|
223
|
+
# %w[db_dir log_dir].each do |dir|
|
224
|
+
# assert(plan("build_#{dir}", Process.egid), "Could not create directory")
|
225
|
+
# end
|
226
|
+
# assert(!plan.present?, "Card was present when partially build")
|
227
|
+
# # complete config
|
228
|
+
# assert(plan.write_default_config_file, "Could not create config file")
|
229
|
+
# assert(plan.present?, "Complete card was not present")
|
230
|
+
# end
|
231
|
+
# end
|
232
|
+
#
|
233
|
+
# def test_plan_is_valid
|
234
|
+
# configure(:prefix_path => test_prefix) do
|
235
|
+
# assert(!plan.valid?, "Card was valid when missing")
|
236
|
+
# # add config
|
237
|
+
# %w[db_dir log_dir].each do |dir|
|
238
|
+
# assert(plan("build_#{dir}", Process.egid), "Could not create directory")
|
239
|
+
# end
|
240
|
+
# assert(plan.write_default_config_file, "Could not create config file")
|
241
|
+
# assert(plan.valid?, "Complete card was not valid")
|
242
|
+
# # break premissions
|
243
|
+
# plan.db_dir.chmod(0444) # read only
|
244
|
+
# assert(!plan.valid?, "Card was valid when read only")
|
245
|
+
# end
|
246
|
+
# end
|
247
|
+
|
248
|
+
#######
|
249
|
+
private
|
250
|
+
#######
|
251
|
+
|
252
|
+
# Creates a Tempfile, dumps configuration to it, and loads it.
|
253
|
+
def load_config_file(content = String.new)
|
254
|
+
cf = Tempfile.new("agent_config_test")
|
255
|
+
cf << content
|
256
|
+
cf.flush
|
257
|
+
plan.update_from_config_file(cf.path)
|
258
|
+
end
|
259
|
+
|
260
|
+
#
|
261
|
+
# Applies +settings+ to the configuaration, runs the passed block, then resets
|
262
|
+
# configuaration defaults.
|
263
|
+
#
|
264
|
+
def configure(settings)
|
265
|
+
settings.each { |name, value| plan("#{name}=", value) }
|
266
|
+
begin
|
267
|
+
yield
|
268
|
+
ensure
|
269
|
+
plan.reset_defaults
|
270
|
+
end
|
271
|
+
end
|
272
|
+
|
273
|
+
# Checks a Pathname +path+ against a +regexp+.
|
274
|
+
def assert_path_match(regexp, path)
|
275
|
+
assert_match(regexp, plan(path).to_s)
|
276
|
+
end
|
277
|
+
|
278
|
+
# Sets the +parent+ dir and ensures that +path+ is updated as a result.
|
279
|
+
def assert_prepends_path(path, parent)
|
280
|
+
dir = "test_dir"
|
281
|
+
configure(parent => dir) do
|
282
|
+
assert_path_match(%r{\A/#{dir}/.+\z}, path)
|
283
|
+
end
|
284
|
+
end
|
285
|
+
end
|