fig 2.0.0.pre.alpha.4 → 2.0.0.pre.alpha.5

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.
Files changed (40) hide show
  1. checksums.yaml +4 -4
  2. data/lib/fig/spec_utils.rb +312 -0
  3. data/lib/fig/version.rb +1 -1
  4. data/spec/application_configuration_spec.rb +73 -0
  5. data/spec/command/clean_spec.rb +62 -0
  6. data/spec/command/command_line_vs_package_spec.rb +32 -0
  7. data/spec/command/dump_package_definition_spec.rb +104 -0
  8. data/spec/command/environment_variables_spec.rb +62 -0
  9. data/spec/command/grammar_asset_spec.rb +391 -0
  10. data/spec/command/grammar_command_spec.rb +88 -0
  11. data/spec/command/grammar_environment_variable_spec.rb +384 -0
  12. data/spec/command/grammar_retrieve_spec.rb +74 -0
  13. data/spec/command/grammar_spec.rb +87 -0
  14. data/spec/command/grammar_spec_helper.rb +23 -0
  15. data/spec/command/include_file_spec.rb +73 -0
  16. data/spec/command/listing_spec.rb +1574 -0
  17. data/spec/command/miscellaneous_spec.rb +145 -0
  18. data/spec/command/publish_local_and_updates_spec.rb +32 -0
  19. data/spec/command/publishing_retrieval_spec.rb +423 -0
  20. data/spec/command/publishing_spec.rb +596 -0
  21. data/spec/command/running_commands_spec.rb +354 -0
  22. data/spec/command/suppress_includes_spec.rb +65 -0
  23. data/spec/command/suppress_warning_include_statement_missing_version_spec.rb +134 -0
  24. data/spec/command/update_lock_response_spec.rb +47 -0
  25. data/spec/command/usage_errors_spec.rb +481 -0
  26. data/spec/command_options_spec.rb +184 -0
  27. data/spec/command_spec.rb +49 -0
  28. data/spec/deparser/v1_spec.rb +64 -0
  29. data/spec/environment_variables_spec.rb +91 -0
  30. data/spec/figrc_spec.rb +144 -0
  31. data/spec/parser_spec.rb +398 -0
  32. data/spec/repository_spec.rb +117 -0
  33. data/spec/runtime_environment_spec.rb +357 -0
  34. data/spec/spec_helper.rb +1 -0
  35. data/spec/split_repo_url_spec.rb +190 -0
  36. data/spec/statement/asset_spec.rb +203 -0
  37. data/spec/statement/configuration_spec.rb +41 -0
  38. data/spec/support/formatters/seed_spitter.rb +12 -0
  39. data/spec/working_directory_maintainer_spec.rb +102 -0
  40. metadata +42 -5
@@ -0,0 +1,64 @@
1
+ # coding: utf-8
2
+
3
+ require File.expand_path(File.dirname(__FILE__) + '/../spec_helper')
4
+
5
+ require 'fig/deparser/v1'
6
+ require 'fig/statement/archive'
7
+ require 'fig/statement/resource'
8
+
9
+ describe Fig::Deparser::V1 do
10
+ let(:deparser) {
11
+ Fig::Deparser::V1.new :emit_as_input, '<indent>', 1
12
+ }
13
+
14
+ describe 'deparses' do
15
+ {
16
+ Fig::Statement::Archive => 'archive',
17
+ Fig::Statement::Resource => 'resource',
18
+ }.each_pair do
19
+ |statement_class, keyword|
20
+
21
+ describe keyword do
22
+ it %q<«chocolate*pizza» with globbing> do
23
+ statement =
24
+ statement_class.new(nil, nil, 'chocolate*pizza', :glob_if_not_url)
25
+
26
+ deparser.deparse([statement]).should ==
27
+ %Q[<indent>#{keyword} "chocolate*pizza"\n]
28
+ end
29
+
30
+ it %q<«chocolate*pizza» without globbing> do
31
+ statement =
32
+ statement_class.new(nil, nil, 'chocolate*pizza', false)
33
+
34
+ deparser.deparse([statement]).should ==
35
+ %Q[<indent>#{keyword} 'chocolate*pizza'\n]
36
+ end
37
+
38
+ it %q<«chocolate\\pizza» with globbing> do
39
+ statement =
40
+ statement_class.new(nil, nil, 'chocolate\\pizza', :glob_if_not_url)
41
+
42
+ deparser.deparse([statement]).should ==
43
+ %Q[<indent>#{keyword} "chocolate\\\\pizza"\n]
44
+ end
45
+
46
+ it %q<«chocolate\\pizza» without globbing> do
47
+ statement = statement_class.new(nil, nil, 'chocolate\\pizza', false)
48
+
49
+ deparser.deparse([statement]).should ==
50
+ %Q[<indent>#{keyword} 'chocolate\\\\pizza'\n]
51
+ end
52
+
53
+ it %q<«chocolate'"pizza»> do
54
+ statement = statement_class.new(nil, nil, %q<chocolate'"pizza>, false)
55
+
56
+ deparser.deparse([statement]).should ==
57
+ %Q[<indent>#{keyword} 'chocolate\\'"pizza'\n]
58
+ end
59
+ end
60
+ end
61
+ end
62
+ end
63
+
64
+ # vim: set fileencoding=utf8 :
@@ -0,0 +1,91 @@
1
+ # coding: utf-8
2
+
3
+ require File.expand_path(File.dirname(__FILE__) + '/spec_helper')
4
+
5
+ require 'fig/environment_variables/case_insensitive'
6
+ require 'fig/environment_variables/case_sensitive'
7
+
8
+ def find_diffs(primary_hash, secondary_hash, diff_hash)
9
+ primary_hash.each do |key, value|
10
+ if ! secondary_hash.has_key?(key)
11
+ diff_hash[key] = value
12
+ elsif primary_hash[key] != secondary_hash[key]
13
+ diff_hash[key] = value
14
+ end
15
+ end
16
+
17
+ return
18
+ end
19
+
20
+ def hash_differences(hash_one, hash_two)
21
+ hash_differences = {}
22
+ find_diffs(hash_one, hash_two, hash_differences)
23
+ find_diffs(hash_two, hash_one, hash_differences)
24
+
25
+ return hash_differences
26
+ end
27
+
28
+ describe 'EnvironmentVariables' do
29
+ it 'correctly sets and unsets the system environment variables' do
30
+ env_vars = Fig::EnvironmentVariables::CaseSensitive.new({ 'Foo' => 'BAR' })
31
+
32
+ sys_vars_prior = {}
33
+ sys_vars_prior.merge!(ENV.to_hash)
34
+ sys_vars_set = {}
35
+ sys_vars_after = {}
36
+
37
+ env_vars['BAR'] = 'BAZ'
38
+ env_vars.with_environment { sys_vars_set.merge!(ENV.to_hash) }
39
+ sys_vars_after.merge!(ENV.to_hash)
40
+
41
+ hash_differences(sys_vars_prior, sys_vars_after).should be_empty
42
+ before_and_during_diff = hash_differences(sys_vars_prior, sys_vars_set)
43
+ hash_differences(before_and_during_diff, {'BAR' => 'BAZ', 'Foo' => 'BAR'}).should be_empty
44
+ end
45
+
46
+ describe 'case sensitive' do
47
+ it 'sets and retrieves variables' do
48
+ env_vars = Fig::EnvironmentVariables::CaseSensitive.new({ 'Foo' => 'BAR' })
49
+
50
+ env_vars['FOO'].should == nil
51
+ env_vars['Foo'].should == 'BAR'
52
+
53
+ env_vars['BAR'] = 'BAZ'
54
+ env_vars['BAR'].should == 'BAZ'
55
+ env_vars['bar'].should == nil
56
+ end
57
+
58
+ it 'prepends values onto variables' do
59
+ env_vars = Fig::EnvironmentVariables::CaseSensitive.new({ 'Foo' => 'BAR' })
60
+
61
+ env_vars.prepend_variable('Foo', 'BAZ')
62
+ env_vars['Foo'].should == 'BAZ' + File::PATH_SEPARATOR + 'BAR'
63
+
64
+ env_vars.prepend_variable('FOO', 'XYZZY')
65
+ env_vars['FOO'].should == 'XYZZY'
66
+ end
67
+ end
68
+
69
+ describe 'case sensitive' do
70
+ it 'sets and retrieves variables' do
71
+ env_vars = Fig::EnvironmentVariables::CaseInsensitive.new({ 'Foo' => 'BAR' })
72
+
73
+ env_vars['FOO'].should == 'BAR'
74
+ env_vars['foo'].should == 'BAR'
75
+
76
+ env_vars['BAR'] = 'BAZ'
77
+ env_vars['BAR'].should == 'BAZ'
78
+ env_vars['bar'].should == 'BAZ'
79
+ end
80
+
81
+ it 'prepends values onto variables' do
82
+ env_vars = Fig::EnvironmentVariables::CaseInsensitive.new({ 'Foo' => 'BAR' })
83
+
84
+ env_vars.prepend_variable('Foo', 'BAZ')
85
+ env_vars['Foo'].should == 'BAZ' + File::PATH_SEPARATOR + 'BAR'
86
+
87
+ env_vars.prepend_variable('FOO', 'XYZZY')
88
+ env_vars['Foo'].should == 'XYZZY' + File::PATH_SEPARATOR + 'BAZ' + File::PATH_SEPARATOR + 'BAR'
89
+ end
90
+ end
91
+ end
@@ -0,0 +1,144 @@
1
+ # coding: utf-8
2
+
3
+ require File.expand_path(File.dirname(__FILE__) + '/spec_helper')
4
+
5
+ require 'stringio'
6
+ require 'tempfile'
7
+
8
+ require 'fig/figrc'
9
+ require 'fig/operating_system'
10
+ require 'fig/repository'
11
+ require 'fig/working_directory_maintainer'
12
+
13
+ describe 'FigRC' do
14
+ def create_override_file(foo, bar = nil)
15
+ tempfile = Tempfile.new('some_json_tempfile')
16
+ tempfile << %Q< { "foo" : "#{foo}" >
17
+ if not bar.nil?
18
+ tempfile << %Q< , "bar" : "#{bar}" >
19
+ end
20
+ tempfile << %Q< } >
21
+ tempfile.close
22
+ return tempfile
23
+ end
24
+
25
+ def create_override_file_with_repository_url()
26
+ tempfile = Tempfile.new('some_json_tempfile')
27
+ tempfile << %Q< { "default FIG_DOWNLOAD_URL" : "#{FIG_DOWNLOAD_URL}", "default FIG_UPLOAD_URL" : "#{FIG_UPLOAD_URL}" } >
28
+ tempfile.close
29
+ return tempfile
30
+ end
31
+
32
+ def create_remote_config(foo, bar = nil)
33
+ FileUtils.mkdir_p(
34
+ File.join(FIG_DOWNLOAD_DIR, Fig::Repository::METADATA_SUBDIRECTORY)
35
+ )
36
+ figrc_path = File.join(FIG_DOWNLOAD_DIR, Fig::FigRC::REPOSITORY_CONFIGURATION)
37
+ file_handle = File.new(figrc_path,'w')
38
+ file_handle.write( %Q< { "foo" : "#{foo}" > )
39
+ if not bar.nil?
40
+ file_handle.write( %Q< , "bar" : "#{bar}" > )
41
+ end
42
+ file_handle.write( %Q< } > )
43
+ file_handle.close
44
+ return
45
+ end
46
+
47
+ def invoke_find(override_path, download_repository_url, upload_repository_url = nil)
48
+ return Fig::FigRC.find(
49
+ override_path,
50
+ download_repository_url,
51
+ upload_repository_url,
52
+ Fig::OperatingSystem.new(false),
53
+ FIG_HOME,
54
+ true
55
+ )
56
+ end
57
+
58
+ before(:all) do
59
+ clean_up_test_environment
60
+ set_up_test_environment
61
+ end
62
+
63
+ after(:each) do
64
+ clean_up_test_environment
65
+ end
66
+
67
+ it 'handles override path with a remote repository' do
68
+ tempfile = create_override_file('loaded as override')
69
+
70
+ create_remote_config("loaded from repository (shouldn't be)")
71
+ configuration = invoke_find tempfile.path, FIG_DOWNLOAD_URL, FIG_UPLOAD_URL
72
+ tempfile.unlink
73
+
74
+ configuration['foo'].should == 'loaded as override'
75
+ end
76
+
77
+ it 'handles no override, no repository (full stop)' do
78
+ configuration = invoke_find nil, nil
79
+ configuration['foo'].should == nil
80
+ end
81
+
82
+ it 'handles no override, repository specified as the empty string' do
83
+ configuration = invoke_find nil, ''
84
+ configuration['foo'].should == nil
85
+ end
86
+
87
+ it 'handles no override, repository specified as whitespace' do
88
+ configuration = invoke_find nil, " \n\t"
89
+ configuration['foo'].should == nil
90
+ end
91
+
92
+ it 'handles no repository config and no override specified, and config does NOT exist on server' do
93
+ configuration = invoke_find nil, 'file:///does_not_exist/'
94
+ configuration['foo'].should == nil
95
+ end
96
+
97
+ it 'retrieves configuration from repository with no override' do
98
+ create_remote_config('loaded from repository')
99
+
100
+ configuration = invoke_find nil, FIG_DOWNLOAD_URL
101
+ configuration['foo'].should == 'loaded from repository'
102
+ end
103
+
104
+ it 'has a remote config but gets its config from the override file provided' do
105
+ create_remote_config('loaded from remote repository')
106
+ tempfile = create_override_file('loaded as override to override remote config')
107
+ configuration = invoke_find tempfile.path, FIG_DOWNLOAD_URL
108
+ configuration['foo'].should == 'loaded as override to override remote config'
109
+ end
110
+
111
+ it 'merges override file config over remote config' do
112
+ create_remote_config('loaded from remote repository', 'should not be overwritten')
113
+ tempfile = create_override_file('loaded as override to override remote config')
114
+ configuration = invoke_find tempfile.path, FIG_DOWNLOAD_URL, FIG_UPLOAD_URL
115
+ configuration['foo'].should == 'loaded as override to override remote config'
116
+ configuration['bar'].should == 'should not be overwritten'
117
+ end
118
+
119
+ it 'retrieves configuration from repository specified by override file' do
120
+ tempfile = create_override_file_with_repository_url
121
+ create_remote_config('loaded from repository')
122
+
123
+ configuration = invoke_find tempfile.path, nil, nil
124
+ configuration['foo'].should == 'loaded from repository'
125
+ end
126
+
127
+ it 'ignores unknown settings without errors' do
128
+ tempfile = Tempfile.new('unknown_settings_test')
129
+ tempfile << %Q< { "foo": "bar", "fig_2x_setting": "future setting value" } >
130
+ tempfile.close
131
+
132
+ # This should not raise any errors despite unknown setting
133
+ configuration = invoke_find(tempfile.path, nil)
134
+
135
+ # Known setting works
136
+ configuration['foo'].should == 'bar'
137
+
138
+ # Unknown setting is accessible but would be ignored by code not looking for it
139
+ configuration['fig_2x_setting'].should == 'future setting value'
140
+
141
+ # Completely nonexistent setting returns nil
142
+ configuration['nonexistent'].should be_nil
143
+ end
144
+ end
@@ -0,0 +1,398 @@
1
+ # coding: utf-8
2
+ require File.expand_path(File.dirname(__FILE__) + '/spec_helper')
3
+
4
+ require 'fig/application_configuration'
5
+ require 'fig/not_yet_parsed_package'
6
+ require 'fig/package_descriptor'
7
+ require 'fig/package_parse_error'
8
+ require 'fig/parser'
9
+
10
+ describe 'Parser' do
11
+ def new_configuration
12
+ application_configuration = Fig::ApplicationConfiguration.new
13
+
14
+ application_configuration.base_whitelisted_url = 'http://example/'
15
+ application_configuration.remote_download_url = 'http://example/'
16
+ application_configuration.remote_upload_url = 'http://example/upload/'
17
+
18
+ return application_configuration
19
+ end
20
+
21
+ def test_no_parse_exception(fig_input)
22
+ application_configuration = new_configuration
23
+
24
+ unparsed_package = Fig::NotYetParsedPackage.new
25
+ unparsed_package.descriptor =
26
+ Fig::PackageDescriptor.new('package_name', '0.1.1', nil)
27
+ unparsed_package.working_directory =
28
+ unparsed_package.include_file_base_directory =
29
+ 'foo_directory'
30
+ unparsed_package.source_description = 'source description'
31
+ unparsed_package.unparsed_text = fig_input
32
+
33
+ package = Fig::Parser.new(application_configuration, false).parse_package(
34
+ unparsed_package
35
+ )
36
+ # Got no exception.
37
+
38
+ return package
39
+ end
40
+
41
+ def test_error(fig_input, error_class, message_pattern)
42
+ application_configuration = new_configuration
43
+
44
+ unparsed_package = Fig::NotYetParsedPackage.new
45
+ unparsed_package.descriptor =
46
+ Fig::PackageDescriptor.new('package_name', '0.1.1', nil)
47
+ unparsed_package.working_directory =
48
+ unparsed_package.include_file_base_directory =
49
+ 'foo_directory'
50
+ unparsed_package.source_description = 'source description'
51
+ unparsed_package.unparsed_text = fig_input
52
+
53
+ expect {
54
+ Fig::Parser.new(application_configuration, false).parse_package(
55
+ unparsed_package
56
+ )
57
+ }.to raise_error(error_class, message_pattern)
58
+
59
+ return
60
+ end
61
+
62
+ def test_user_input_error(fig_input, message_pattern)
63
+ test_error(fig_input, Fig::UserInputError, message_pattern)
64
+
65
+ return
66
+ end
67
+
68
+ def test_package_parse_error(
69
+ fig_input, message_pattern = /source description/
70
+ )
71
+ test_error(fig_input, Fig::PackageParseError, message_pattern)
72
+
73
+ return
74
+ end
75
+
76
+ describe 'base syntax' do
77
+ it 'throws the correct exception on syntax error' do
78
+ application_configuration = new_configuration
79
+
80
+ unparsed_package = Fig::NotYetParsedPackage.new
81
+ unparsed_package.descriptor =
82
+ Fig::PackageDescriptor.new('package_name', '0.1.1', nil)
83
+ unparsed_package.working_directory =
84
+ unparsed_package.include_file_base_directory =
85
+ 'foo_directory'
86
+ unparsed_package.source_description = 'source description'
87
+ unparsed_package.unparsed_text = <<-END
88
+ this is invalid syntax
89
+ END
90
+
91
+ expect {
92
+ Fig::Parser.new(application_configuration, false).parse_package(
93
+ unparsed_package
94
+ )
95
+ }.to raise_error(
96
+ Fig::PackageParseError
97
+ )
98
+ end
99
+
100
+ it 'assigns the correct line and column number to Statement objects.' do
101
+ fig_package=<<-FIG_PACKAGE
102
+
103
+ # Blank line above to ensure that we can handle starting whitespace.
104
+ resource http://example/is/awesome.tgz
105
+
106
+ # Indentation in here is weird to test we get things right.
107
+
108
+ # Also, we need a comment in here to make sure that cleaning them out
109
+ # does not affect values for statements.
110
+
111
+ archive http://svpsvn/my/repo/is/cool.jar
112
+
113
+ config default
114
+ include package/some-version
115
+
116
+ set VARIABLE=VALUE
117
+ end
118
+ FIG_PACKAGE
119
+
120
+ unparsed_package = Fig::NotYetParsedPackage.new
121
+ unparsed_package.descriptor =
122
+ Fig::PackageDescriptor.new('package_name', '0.1.1', nil)
123
+ unparsed_package.working_directory =
124
+ unparsed_package.include_file_base_directory =
125
+ 'foo_directory'
126
+ unparsed_package.source_description = 'source description'
127
+ unparsed_package.unparsed_text = fig_package
128
+
129
+ application_configuration = new_configuration
130
+ package = Fig::Parser.new(application_configuration, false).parse_package(
131
+ unparsed_package
132
+ )
133
+
134
+ package.walk_statements do
135
+ |statement|
136
+
137
+ case statement
138
+ when Fig::Statement::Resource
139
+ statement.line.should == 3
140
+ statement.column.should == 9
141
+ when Fig::Statement::Archive
142
+ statement.line.should == 10
143
+ statement.column.should == 10
144
+ when Fig::Statement::Configuration
145
+ statement.line.should == 12
146
+ statement.column.should == 9
147
+ when Fig::Statement::Include
148
+ statement.line.should == 13
149
+ statement.column.should == 17
150
+ when Fig::Statement::Set
151
+ statement.line.should == 15
152
+ statement.column.should == 12
153
+ end
154
+ end
155
+ end
156
+ end
157
+
158
+ describe 'validating URLs' do
159
+ it 'passes valid, whitelisted ones' do
160
+ fig_package=<<-FIG_PACKAGE
161
+ resource http://example/is/awesome.tgz
162
+
163
+ archive http://svpsvn/my/repo/is/cool.jar
164
+ FIG_PACKAGE
165
+ application_configuration = new_configuration
166
+ application_configuration.push_dataset( { 'url whitelist' => 'http://svpsvn/' } )
167
+
168
+ unparsed_package = Fig::NotYetParsedPackage.new
169
+ unparsed_package.descriptor =
170
+ Fig::PackageDescriptor.new('package_name', '0.1.1', nil)
171
+ unparsed_package.working_directory =
172
+ unparsed_package.include_file_base_directory =
173
+ 'foo_directory'
174
+ unparsed_package.source_description = 'source description'
175
+ unparsed_package.unparsed_text = fig_package
176
+
177
+ package = Fig::Parser.new(application_configuration, false).parse_package(
178
+ unparsed_package
179
+ )
180
+ package.should_not == nil
181
+ end
182
+
183
+ it 'rejects non-whitelisted ones' do
184
+ fig_package=<<-FIG_PACKAGE
185
+ resource http://evil_url/is/bad.tgz
186
+
187
+ archive http://evil_repo/my/repo/is/bad.jar
188
+ FIG_PACKAGE
189
+ application_configuration = new_configuration
190
+ application_configuration.push_dataset( { 'url whitelist' => 'http://svpsvn/' } )
191
+
192
+ unparsed_package = Fig::NotYetParsedPackage.new
193
+ unparsed_package.descriptor =
194
+ Fig::PackageDescriptor.new('package_name', '0.1.1', nil)
195
+ unparsed_package.working_directory =
196
+ unparsed_package.include_file_base_directory =
197
+ 'foo_directory'
198
+ unparsed_package.source_description = 'source description'
199
+ unparsed_package.unparsed_text = fig_package
200
+
201
+ exception = nil
202
+ begin
203
+ package =
204
+ Fig::Parser.new(application_configuration, false).parse_package(
205
+ unparsed_package
206
+ )
207
+ rescue Fig::URLAccessDisallowedError => exception
208
+ end
209
+ exception.should_not == nil
210
+ exception.urls.should =~ %w<http://evil_url/is/bad.tgz http://evil_repo/my/repo/is/bad.jar>
211
+ exception.descriptor.name.should == 'package_name'
212
+ exception.descriptor.version.should == '0.1.1'
213
+ end
214
+ end
215
+
216
+ describe 'command statements' do
217
+ %w< 0 1 >.each do
218
+ |version|
219
+
220
+ command_terminator = version.to_i == 0 ? '' : ' end'
221
+ describe %Q<in the v#{version} grammar> do
222
+ it 'reject multiple commands in config file' do
223
+ input = <<-"END_PACKAGE"
224
+ grammar v#{version}
225
+ config default
226
+ command "echo foo"#{command_terminator}
227
+ command "echo bar"#{command_terminator}
228
+ end
229
+ END_PACKAGE
230
+
231
+ test_user_input_error(
232
+ input,
233
+ /found a second "command" statement within a "config" block/i
234
+ )
235
+ end
236
+
237
+ it 'accept multiple configs, each with a single command' do
238
+ test_no_parse_exception(<<-"END_PACKAGE")
239
+ grammar v#{version}
240
+ config default
241
+ command "echo foo"#{command_terminator}
242
+ end
243
+ config another
244
+ command "echo bar"#{command_terminator}
245
+ end
246
+ END_PACKAGE
247
+ end
248
+
249
+ it 'reject multiple configs where one has multiple commands' do
250
+ input = <<-"END_PACKAGE"
251
+ grammar v#{version}
252
+ config default
253
+ command "echo foo"#{command_terminator}
254
+ end
255
+ config another
256
+ command "echo bar"#{command_terminator}
257
+ command "echo baz"#{command_terminator}
258
+ end
259
+ END_PACKAGE
260
+
261
+ test_user_input_error(
262
+ input,
263
+ /found a second "command" statement within a "config" block/i
264
+ )
265
+ end
266
+ end
267
+ end
268
+ end
269
+
270
+ describe 'path statements' do
271
+ {
272
+ ';' => ';',
273
+ ':' => ':',
274
+ '"' => '"',
275
+ '<' => '<',
276
+ '>' => '>',
277
+ '|' => '|',
278
+ ' ' => ' ',
279
+ '\t' => "\t",
280
+ '\r' => "\r",
281
+ '\n' => "\n"
282
+ }.each do
283
+ |display, character|
284
+
285
+ it %Q<reject "#{display}" in a PATH component in the v0 grammar> do
286
+ input = <<-"END_PACKAGE"
287
+ grammar v0
288
+ config default
289
+ append PATH_VARIABLE=#{character}
290
+ end
291
+ END_PACKAGE
292
+
293
+ test_user_input_error(
294
+ input, /(?i:invalid append statement).*\bPATH_VARIABLE\b/
295
+ )
296
+ end
297
+
298
+ it %Q<accept "#{display}" in a PATH component in the v1 grammar> do
299
+ right_hand_side = nil
300
+ if character == '"' or character =~ /\s/
301
+ right_hand_side = %Q<'#{character}'>
302
+ else
303
+ right_hand_side = character
304
+ end
305
+
306
+ test_no_parse_exception(<<-"END_PACKAGE")
307
+ grammar v1
308
+ config default
309
+ append PATH_VARIABLE=#{right_hand_side}
310
+ end
311
+ END_PACKAGE
312
+ end
313
+ end
314
+ end
315
+
316
+ %w< archive resource >.each do
317
+ |asset_type|
318
+
319
+ describe "#{asset_type} statements" do
320
+ %w< ' " >.each do
321
+ |character|
322
+
323
+ %w< 0 1 >.each do
324
+ |version|
325
+
326
+ it %Q<produce a parse error with unescaped «#{character}» in a URL in the v#{version} grammar> do
327
+ input = <<-"END_PACKAGE"
328
+ grammar v#{version}
329
+ #{asset_type} #{character}
330
+ END_PACKAGE
331
+
332
+ test_package_parse_error(input)
333
+ end
334
+ end
335
+ end
336
+
337
+ %w[ @ < > | ].each do
338
+ |character|
339
+
340
+
341
+ it %Q<produce a parse error with «#{character}» in a URL in the v0 grammar> do
342
+ input = <<-"END_PACKAGE"
343
+ #{asset_type} #{character}
344
+ END_PACKAGE
345
+
346
+ test_package_parse_error(input)
347
+ end
348
+
349
+ %w< 1 >.each do
350
+ |version|
351
+
352
+ it %Q<handles «#{character}» in a URL in the v#{version} grammar> do
353
+ package = test_no_parse_exception(<<-"END_PACKAGE")
354
+ grammar v#{version}
355
+ #{asset_type} foo#{character}bar
356
+ config default
357
+ end
358
+ END_PACKAGE
359
+
360
+ url =
361
+ [package.archive_locations, package.resource_locations].flatten[0]
362
+ url.should == "foo#{character}bar"
363
+ end
364
+ end
365
+ end
366
+
367
+ it %q<handles octothorpes in a URL in the v1 grammar> do
368
+ package = test_no_parse_exception(<<-"END_PACKAGE")
369
+ grammar v1
370
+ #{asset_type} 'foo#bar'
371
+ config default
372
+ end
373
+ END_PACKAGE
374
+
375
+ url = [package.archive_locations, package.resource_locations].flatten[0]
376
+ url.should == 'foo#bar'
377
+ end
378
+
379
+ describe %Q<handles plus signs in the path (e.g. for C++ libraries)> do
380
+ %w< 0 1 >.each do
381
+ |version|
382
+
383
+ it %Q<in the v#{version} grammar> do
384
+ test_no_parse_exception(<<-"END_PACKAGE")
385
+ grammar v#{version}
386
+ #{asset_type} testlib++.whatever
387
+ config default
388
+ append LIBPATH=@/testlib++
389
+ end
390
+ END_PACKAGE
391
+ end
392
+ end
393
+ end
394
+ end
395
+ end
396
+ end
397
+
398
+ # vim: set fileencoding=utf8 :