chef-config 17.9.52 → 17.10.19
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/LICENSE +201 -201
- data/Rakefile +14 -14
- data/chef-config.gemspec +39 -39
- data/lib/chef-config/config.rb +1297 -1297
- data/lib/chef-config/exceptions.rb +27 -27
- data/lib/chef-config/fips.rb +53 -53
- data/lib/chef-config/logger.rb +53 -53
- data/lib/chef-config/mixin/credentials.rb +102 -102
- data/lib/chef-config/mixin/dot_d.rb +44 -44
- data/lib/chef-config/mixin/fuzzy_hostname_matcher.rb +49 -49
- data/lib/chef-config/mixin/train_transport.rb +143 -143
- data/lib/chef-config/path_helper.rb +350 -350
- data/lib/chef-config/version.rb +19 -19
- data/lib/chef-config/windows.rb +24 -24
- data/lib/chef-config/workstation_config_loader.rb +281 -281
- data/lib/chef-config.rb +20 -20
- data/spec/spec_helper.rb +75 -75
- data/spec/unit/config_spec.rb +1390 -1390
- data/spec/unit/fips_spec.rb +128 -128
- data/spec/unit/path_helper_spec.rb +372 -372
- data/spec/unit/workstation_config_loader_spec.rb +633 -633
- metadata +4 -4
@@ -1,372 +1,372 @@
|
|
1
|
-
#
|
2
|
-
# Author:: Bryan McLellan <btm@loftninjas.org>
|
3
|
-
# Copyright:: Copyright (c) Chef Software Inc.
|
4
|
-
# License:: Apache License, Version 2.0
|
5
|
-
#
|
6
|
-
# Licensed under the Apache License, Version 2.0 (the "License");
|
7
|
-
# you may not use this file except in compliance with the License.
|
8
|
-
# You may obtain a copy of the License at
|
9
|
-
#
|
10
|
-
# http://www.apache.org/licenses/LICENSE-2.0
|
11
|
-
#
|
12
|
-
# Unless required by applicable law or agreed to in writing, software
|
13
|
-
# distributed under the License is distributed on an "AS IS" BASIS,
|
14
|
-
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
15
|
-
# See the License for the specific language governing permissions and
|
16
|
-
# limitations under the License.
|
17
|
-
#
|
18
|
-
|
19
|
-
require "chef-config/path_helper"
|
20
|
-
require "spec_helper"
|
21
|
-
|
22
|
-
RSpec.describe ChefConfig::PathHelper do
|
23
|
-
|
24
|
-
let(:path_helper) { described_class }
|
25
|
-
|
26
|
-
context "common functionality" do
|
27
|
-
context "join" do
|
28
|
-
it "joins starting with '' resolve to absolute paths" do
|
29
|
-
expect(path_helper.join("", "a", "b")).to eq("#{path_helper.path_separator}a#{path_helper.path_separator}b")
|
30
|
-
end
|
31
|
-
|
32
|
-
it "joins ending with '' add a / to the end" do
|
33
|
-
expect(path_helper.join("a", "b", "")).to eq("a#{path_helper.path_separator}b#{path_helper.path_separator}")
|
34
|
-
end
|
35
|
-
end
|
36
|
-
|
37
|
-
context "dirname" do
|
38
|
-
it "dirname('abc') is '.'" do
|
39
|
-
expect(path_helper.dirname("abc")).to eq(".")
|
40
|
-
end
|
41
|
-
it "dirname('/') is '/'" do
|
42
|
-
expect(path_helper.dirname(path_helper.path_separator)).to eq(path_helper.path_separator)
|
43
|
-
end
|
44
|
-
it "dirname('a/b/c') is 'a/b'" do
|
45
|
-
expect(path_helper.dirname(path_helper.join("a", "b", "c"))).to eq(path_helper.join("a", "b"))
|
46
|
-
end
|
47
|
-
it "dirname('a/b/c/') is 'a/b'" do
|
48
|
-
expect(path_helper.dirname(path_helper.join("a", "b", "c", ""))).to eq(path_helper.join("a", "b"))
|
49
|
-
end
|
50
|
-
it "dirname('/a/b/c') is '/a/b'" do
|
51
|
-
expect(path_helper.dirname(path_helper.join("", "a", "b", "c"))).to eq(path_helper.join("", "a", "b"))
|
52
|
-
end
|
53
|
-
end
|
54
|
-
end
|
55
|
-
|
56
|
-
context "forcing windows/non-windows" do
|
57
|
-
context "forcing windows" do
|
58
|
-
it "path_separator is \\" do
|
59
|
-
expect(path_helper.path_separator(windows: true)).to eq("\\")
|
60
|
-
end
|
61
|
-
|
62
|
-
context "platform-specific #join behavior" do
|
63
|
-
it "joins components on Windows when some end with unix separators" do
|
64
|
-
expected = "C:\\foo\\bar\\baz"
|
65
|
-
expect(path_helper.join("C:\\foo/", "bar", "baz", windows: true)).to eq(expected)
|
66
|
-
end
|
67
|
-
|
68
|
-
it "joins components when some end with separators" do
|
69
|
-
expected = "C:\\foo\\bar\\baz"
|
70
|
-
expect(path_helper.join("C:\\foo\\", "bar", "baz", windows: true)).to eq(expected)
|
71
|
-
end
|
72
|
-
|
73
|
-
it "joins components when some end and start with separators" do
|
74
|
-
expected = "C:\\foo\\bar\\baz"
|
75
|
-
expect(path_helper.join("C:\\foo\\", "bar/", "/baz", windows: true)).to eq(expected)
|
76
|
-
end
|
77
|
-
|
78
|
-
it "joins components that don't end in separators" do
|
79
|
-
expected = "C:\\foo\\bar\\baz"
|
80
|
-
expect(path_helper.join("C:\\foo", "bar", "baz", windows: true)).to eq(expected)
|
81
|
-
end
|
82
|
-
end
|
83
|
-
|
84
|
-
it "cleanpath changes slashes into backslashes and leaves backslashes alone" do
|
85
|
-
expect(path_helper.cleanpath("/a/b\\c/d/", windows: true)).to eq("\\a\\b\\c\\d")
|
86
|
-
end
|
87
|
-
|
88
|
-
it "cleanpath does not remove leading double backslash" do
|
89
|
-
expect(path_helper.cleanpath("\\\\a/b\\c/d/", windows: true)).to eq("\\\\a\\b\\c\\d")
|
90
|
-
end
|
91
|
-
end
|
92
|
-
|
93
|
-
context "forcing unix" do
|
94
|
-
it "path_separator is /" do
|
95
|
-
expect(path_helper.path_separator(windows: false)).to eq("/")
|
96
|
-
end
|
97
|
-
|
98
|
-
it "cleanpath removes extra slashes alone" do
|
99
|
-
expect(path_helper.cleanpath("/a///b/c/d/", windows: false)).to eq("/a/b/c/d")
|
100
|
-
end
|
101
|
-
|
102
|
-
context "platform-specific #join behavior" do
|
103
|
-
it "joins components when some end with separators" do
|
104
|
-
expected = "/foo/bar/baz"
|
105
|
-
expect(path_helper.join("/foo/", "bar", "baz", windows: false)).to eq(expected)
|
106
|
-
end
|
107
|
-
|
108
|
-
it "joins components when some end and start with separators" do
|
109
|
-
expected = "/foo/bar/baz"
|
110
|
-
expect(path_helper.join("/foo/", "bar/", "/baz", windows: false)).to eq(expected)
|
111
|
-
end
|
112
|
-
|
113
|
-
it "joins components that don't end in separators" do
|
114
|
-
expected = "/foo/bar/baz"
|
115
|
-
expect(path_helper.join("/foo", "bar", "baz", windows: false)).to eq(expected)
|
116
|
-
end
|
117
|
-
end
|
118
|
-
|
119
|
-
it "cleanpath changes backslashes into slashes and leaves slashes alone" do
|
120
|
-
expect(path_helper.cleanpath("/a/b\\c/d/", windows: false)).to eq("/a/b/c/d")
|
121
|
-
end
|
122
|
-
|
123
|
-
it "cleanpath does not remove leading double backslash" do
|
124
|
-
expect(path_helper.cleanpath("\\\\a/b\\c/d/", windows: false)).to eq("//a/b/c/d")
|
125
|
-
end
|
126
|
-
end
|
127
|
-
end
|
128
|
-
|
129
|
-
context "on windows", :windows_only do
|
130
|
-
|
131
|
-
before(:each) do
|
132
|
-
allow(ChefUtils).to receive(:windows?).and_return(true)
|
133
|
-
end
|
134
|
-
|
135
|
-
it "path_separator is \\" do
|
136
|
-
expect(path_helper.path_separator).to eq("\\")
|
137
|
-
end
|
138
|
-
|
139
|
-
context "platform-specific #join behavior" do
|
140
|
-
it "joins components on Windows when some end with unix separators" do
|
141
|
-
expected = "C:\\foo\\bar\\baz"
|
142
|
-
expect(path_helper.join("C:\\foo/", "bar", "baz")).to eq(expected)
|
143
|
-
end
|
144
|
-
|
145
|
-
it "joins components when some end with separators" do
|
146
|
-
expected = "C:\\foo\\bar\\baz"
|
147
|
-
expect(path_helper.join("C:\\foo\\", "bar", "baz")).to eq(expected)
|
148
|
-
end
|
149
|
-
|
150
|
-
it "joins components when some end and start with separators" do
|
151
|
-
expected = "C:\\foo\\bar\\baz"
|
152
|
-
expect(path_helper.join("C:\\foo\\", "bar/", "/baz")).to eq(expected)
|
153
|
-
end
|
154
|
-
|
155
|
-
it "joins components that don't end in separators" do
|
156
|
-
expected = "C:\\foo\\bar\\baz"
|
157
|
-
expect(path_helper.join("C:\\foo", "bar", "baz")).to eq(expected)
|
158
|
-
end
|
159
|
-
end
|
160
|
-
|
161
|
-
it "cleanpath changes slashes into backslashes and leaves backslashes alone" do
|
162
|
-
expect(path_helper.cleanpath("/a/b\\c/d/")).to eq("\\a\\b\\c\\d")
|
163
|
-
end
|
164
|
-
|
165
|
-
it "cleanpath does not remove leading double backslash" do
|
166
|
-
expect(path_helper.cleanpath("\\\\a/b\\c/d/")).to eq("\\\\a\\b\\c\\d")
|
167
|
-
end
|
168
|
-
end
|
169
|
-
|
170
|
-
context "on unix", :unix_only do
|
171
|
-
before(:each) do
|
172
|
-
allow(ChefUtils).to receive(:windows?).and_return(false)
|
173
|
-
end
|
174
|
-
|
175
|
-
it "path_separator is /" do
|
176
|
-
expect(path_helper.path_separator).to eq("/")
|
177
|
-
end
|
178
|
-
|
179
|
-
it "cleanpath removes extra slashes alone" do
|
180
|
-
expect(path_helper.cleanpath("/a///b/c/d/")).to eq("/a/b/c/d")
|
181
|
-
end
|
182
|
-
|
183
|
-
context "platform-specific #join behavior" do
|
184
|
-
it "joins components when some end with separators" do
|
185
|
-
expected = path_helper.cleanpath("/foo/bar/baz")
|
186
|
-
expect(path_helper.join("/foo/", "bar", "baz")).to eq(expected)
|
187
|
-
end
|
188
|
-
|
189
|
-
it "joins components when some end and start with separators" do
|
190
|
-
expected = path_helper.cleanpath("/foo/bar/baz")
|
191
|
-
expect(path_helper.join("/foo/", "bar/", "/baz")).to eq(expected)
|
192
|
-
end
|
193
|
-
|
194
|
-
it "joins components that don't end in separators" do
|
195
|
-
expected = path_helper.cleanpath("/foo/bar/baz")
|
196
|
-
expect(path_helper.join("/foo", "bar", "baz")).to eq(expected)
|
197
|
-
end
|
198
|
-
end
|
199
|
-
|
200
|
-
it "cleanpath changes backslashes into slashes and leaves slashes alone" do
|
201
|
-
expect(path_helper.cleanpath("/a/b\\c/d/", windows: false)).to eq("/a/b/c/d")
|
202
|
-
end
|
203
|
-
|
204
|
-
# NOTE: this seems a bit weird to me, but this is just the way Pathname#cleanpath works
|
205
|
-
it "cleanpath does not remove leading double backslash" do
|
206
|
-
expect(path_helper.cleanpath("\\\\a/b\\c/d/")).to eq("//a/b/c/d")
|
207
|
-
end
|
208
|
-
end
|
209
|
-
|
210
|
-
context "validate_path" do
|
211
|
-
context "on windows" do
|
212
|
-
before(:each) do
|
213
|
-
# pass by default
|
214
|
-
allow(ChefUtils).to receive(:windows?).and_return(true)
|
215
|
-
allow(path_helper).to receive(:printable?).and_return(true)
|
216
|
-
allow(path_helper).to receive(:windows_max_length_exceeded?).and_return(false)
|
217
|
-
end
|
218
|
-
|
219
|
-
it "returns the path if the path passes the tests" do
|
220
|
-
expect(path_helper.validate_path("C:\\ThisIsRigged")).to eql("C:\\ThisIsRigged")
|
221
|
-
end
|
222
|
-
|
223
|
-
it "does not raise an error if everything looks great" do
|
224
|
-
expect { path_helper.validate_path("C:\\cool path\\dude.exe") }.not_to raise_error
|
225
|
-
end
|
226
|
-
|
227
|
-
it "raises an error if the path has invalid characters" do
|
228
|
-
allow(path_helper).to receive(:printable?).and_return(false)
|
229
|
-
expect { path_helper.validate_path("Newline!\n") }.to raise_error(ChefConfig::InvalidPath)
|
230
|
-
end
|
231
|
-
|
232
|
-
it "Adds the \\\\?\\ prefix if the path exceeds MAX_LENGTH and does not have it" do
|
233
|
-
long_path = "C:\\" + "a" * 250 + "\\" + "b" * 250
|
234
|
-
prefixed_long_path = "\\\\?\\" + long_path
|
235
|
-
allow(path_helper).to receive(:windows_max_length_exceeded?).and_return(true)
|
236
|
-
expect(path_helper.validate_path(long_path)).to eql(prefixed_long_path)
|
237
|
-
end
|
238
|
-
end
|
239
|
-
end
|
240
|
-
|
241
|
-
context "windows_max_length_exceeded?" do
|
242
|
-
it "returns true if the path is too long (259 + NUL) for the API" do
|
243
|
-
expect(path_helper.windows_max_length_exceeded?("C:\\" + "a" * 250 + "\\" + "b" * 6)).to be_truthy
|
244
|
-
end
|
245
|
-
|
246
|
-
it "returns false if the path is not too long (259 + NUL) for the standard API" do
|
247
|
-
expect(path_helper.windows_max_length_exceeded?("C:\\" + "a" * 250 + "\\" + "b" * 5)).to be_falsey
|
248
|
-
end
|
249
|
-
|
250
|
-
it "returns false if the path is over 259 characters but uses the \\\\?\\ prefix" do
|
251
|
-
expect(path_helper.windows_max_length_exceeded?("\\\\?\\C:\\" + "a" * 250 + "\\" + "b" * 250)).to be_falsey
|
252
|
-
end
|
253
|
-
end
|
254
|
-
|
255
|
-
context "printable?" do
|
256
|
-
it "returns true if the string contains no non-printable characters" do
|
257
|
-
expect(path_helper.printable?("C:\\Program Files (x86)\\Microsoft Office\\Files.lst")).to be_truthy
|
258
|
-
end
|
259
|
-
|
260
|
-
it "returns true when given 'abc' in unicode" do
|
261
|
-
expect(path_helper.printable?("\u0061\u0062\u0063")).to be_truthy
|
262
|
-
end
|
263
|
-
|
264
|
-
it "returns true when given japanese unicode" do
|
265
|
-
expect(path_helper.printable?("\uff86\uff87\uff88")).to be_truthy
|
266
|
-
end
|
267
|
-
|
268
|
-
it "returns false if the string contains a non-printable character" do
|
269
|
-
expect(path_helper.printable?("\my files\work\notes.txt")).to be_falsey
|
270
|
-
end
|
271
|
-
|
272
|
-
# This isn't necessarily a requirement, but here to be explicit about functionality.
|
273
|
-
it "returns false if the string contains a newline or tab" do
|
274
|
-
expect(path_helper.printable?("\tThere's no way,\n\t *no* way,\n\t that you came from my loins.\n")).to be_falsey
|
275
|
-
end
|
276
|
-
end
|
277
|
-
|
278
|
-
context "canonical_path" do
|
279
|
-
context "on windows", :windows_only do
|
280
|
-
it "returns an absolute path with backslashes instead of slashes" do
|
281
|
-
expect(path_helper.canonical_path("\\\\?\\C:/windows/win.ini")).to eq("\\\\?\\c:\\windows\\win.ini")
|
282
|
-
end
|
283
|
-
|
284
|
-
it "adds the \\\\?\\ prefix if it is missing" do
|
285
|
-
expect(path_helper.canonical_path("C:/windows/win.ini")).to eq("\\\\?\\c:\\windows\\win.ini")
|
286
|
-
end
|
287
|
-
|
288
|
-
it "returns a lowercase path" do
|
289
|
-
expect(path_helper.canonical_path("\\\\?\\C:\\CASE\\INSENSITIVE")).to eq("\\\\?\\c:\\case\\insensitive")
|
290
|
-
end
|
291
|
-
end
|
292
|
-
|
293
|
-
context "not on windows", :unix_only do
|
294
|
-
it "returns a canonical path" do
|
295
|
-
expect(path_helper.canonical_path("/etc//apache.d/sites-enabled/../sites-available/default")).to eq("/etc/apache.d/sites-available/default")
|
296
|
-
end
|
297
|
-
end
|
298
|
-
end
|
299
|
-
|
300
|
-
context "paths_eql?" do
|
301
|
-
it "returns true if the paths are the same" do
|
302
|
-
allow(path_helper).to receive(:canonical_path).with("bandit", windows: ChefUtils.windows?).and_return("c:/bandit/bandit")
|
303
|
-
allow(path_helper).to receive(:canonical_path).with("../bandit/bandit", windows: ChefUtils.windows?).and_return("c:/bandit/bandit")
|
304
|
-
expect(path_helper.paths_eql?("bandit", "../bandit/bandit")).to be_truthy
|
305
|
-
end
|
306
|
-
|
307
|
-
it "returns false if the paths are different" do
|
308
|
-
allow(path_helper).to receive(:canonical_path).with("bandit", windows: ChefUtils.windows?).and_return("c:/Bo/Bandit")
|
309
|
-
allow(path_helper).to receive(:canonical_path).with("../bandit/bandit", windows: ChefUtils.windows?).and_return("c:/bandit/bandit")
|
310
|
-
expect(path_helper.paths_eql?("bandit", "../bandit/bandit")).to be_falsey
|
311
|
-
end
|
312
|
-
end
|
313
|
-
|
314
|
-
context "escape_glob" do
|
315
|
-
it "escapes characters reserved by glob" do
|
316
|
-
path = "C:\\this\\*path\\[needs]\\escaping?"
|
317
|
-
escaped_path = "C:\\\\this\\\\\\*path\\\\\\[needs\\]\\\\escaping\\?"
|
318
|
-
expect(path_helper.escape_glob(path, windows: true)).to eq(escaped_path)
|
319
|
-
end
|
320
|
-
|
321
|
-
context "when given more than one argument" do
|
322
|
-
it "joins, cleanpaths, and escapes characters reserved by glob" do
|
323
|
-
args = ["this/*path", "[needs]", "escaping?"]
|
324
|
-
escaped_path = if ChefUtils.windows?
|
325
|
-
"this\\\\\\*path\\\\\\[needs\\]\\\\escaping\\?"
|
326
|
-
else
|
327
|
-
"this/\\*path/\\[needs\\]/escaping\\?"
|
328
|
-
end
|
329
|
-
expect(path_helper.escape_glob(*args)).to eq(escaped_path)
|
330
|
-
end
|
331
|
-
end
|
332
|
-
end
|
333
|
-
|
334
|
-
context "escape_glob_dir" do
|
335
|
-
it "escapes characters reserved by glob without using backslashes for path separators" do
|
336
|
-
path = "C:/this/*path/[needs]/escaping?"
|
337
|
-
escaped_path = "C:/this/\\*path/\\[needs\\]/escaping\\?"
|
338
|
-
expect(path_helper.escape_glob_dir(path)).to eq(escaped_path)
|
339
|
-
end
|
340
|
-
|
341
|
-
context "when given more than one argument" do
|
342
|
-
it "joins, cleanpaths, and escapes characters reserved by glob" do
|
343
|
-
args = ["this/*path", "[needs]", "escaping?"]
|
344
|
-
escaped_path = "this/\\*path/\\[needs\\]/escaping\\?"
|
345
|
-
expect(path_helper).to receive(:join).with(*args).and_call_original
|
346
|
-
expect(path_helper.escape_glob_dir(*args)).to eq(escaped_path)
|
347
|
-
end
|
348
|
-
end
|
349
|
-
end
|
350
|
-
|
351
|
-
context "all_homes" do
|
352
|
-
before do
|
353
|
-
stub_const("ENV", env)
|
354
|
-
allow(ChefUtils).to receive(:windows?).and_return(is_windows)
|
355
|
-
end
|
356
|
-
|
357
|
-
context "on windows" do
|
358
|
-
let(:is_windows) { true }
|
359
|
-
end
|
360
|
-
|
361
|
-
context "on unix" do
|
362
|
-
let(:is_windows) { false }
|
363
|
-
|
364
|
-
context "when HOME is not set" do
|
365
|
-
let(:env) { {} }
|
366
|
-
it "returns an empty array" do
|
367
|
-
expect(path_helper.all_homes).to eq([])
|
368
|
-
end
|
369
|
-
end
|
370
|
-
end
|
371
|
-
end
|
372
|
-
end
|
1
|
+
#
|
2
|
+
# Author:: Bryan McLellan <btm@loftninjas.org>
|
3
|
+
# Copyright:: Copyright (c) Chef Software Inc.
|
4
|
+
# License:: Apache License, Version 2.0
|
5
|
+
#
|
6
|
+
# Licensed under the Apache License, Version 2.0 (the "License");
|
7
|
+
# you may not use this file except in compliance with the License.
|
8
|
+
# You may obtain a copy of the License at
|
9
|
+
#
|
10
|
+
# http://www.apache.org/licenses/LICENSE-2.0
|
11
|
+
#
|
12
|
+
# Unless required by applicable law or agreed to in writing, software
|
13
|
+
# distributed under the License is distributed on an "AS IS" BASIS,
|
14
|
+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
15
|
+
# See the License for the specific language governing permissions and
|
16
|
+
# limitations under the License.
|
17
|
+
#
|
18
|
+
|
19
|
+
require "chef-config/path_helper"
|
20
|
+
require "spec_helper"
|
21
|
+
|
22
|
+
RSpec.describe ChefConfig::PathHelper do
|
23
|
+
|
24
|
+
let(:path_helper) { described_class }
|
25
|
+
|
26
|
+
context "common functionality" do
|
27
|
+
context "join" do
|
28
|
+
it "joins starting with '' resolve to absolute paths" do
|
29
|
+
expect(path_helper.join("", "a", "b")).to eq("#{path_helper.path_separator}a#{path_helper.path_separator}b")
|
30
|
+
end
|
31
|
+
|
32
|
+
it "joins ending with '' add a / to the end" do
|
33
|
+
expect(path_helper.join("a", "b", "")).to eq("a#{path_helper.path_separator}b#{path_helper.path_separator}")
|
34
|
+
end
|
35
|
+
end
|
36
|
+
|
37
|
+
context "dirname" do
|
38
|
+
it "dirname('abc') is '.'" do
|
39
|
+
expect(path_helper.dirname("abc")).to eq(".")
|
40
|
+
end
|
41
|
+
it "dirname('/') is '/'" do
|
42
|
+
expect(path_helper.dirname(path_helper.path_separator)).to eq(path_helper.path_separator)
|
43
|
+
end
|
44
|
+
it "dirname('a/b/c') is 'a/b'" do
|
45
|
+
expect(path_helper.dirname(path_helper.join("a", "b", "c"))).to eq(path_helper.join("a", "b"))
|
46
|
+
end
|
47
|
+
it "dirname('a/b/c/') is 'a/b'" do
|
48
|
+
expect(path_helper.dirname(path_helper.join("a", "b", "c", ""))).to eq(path_helper.join("a", "b"))
|
49
|
+
end
|
50
|
+
it "dirname('/a/b/c') is '/a/b'" do
|
51
|
+
expect(path_helper.dirname(path_helper.join("", "a", "b", "c"))).to eq(path_helper.join("", "a", "b"))
|
52
|
+
end
|
53
|
+
end
|
54
|
+
end
|
55
|
+
|
56
|
+
context "forcing windows/non-windows" do
|
57
|
+
context "forcing windows" do
|
58
|
+
it "path_separator is \\" do
|
59
|
+
expect(path_helper.path_separator(windows: true)).to eq("\\")
|
60
|
+
end
|
61
|
+
|
62
|
+
context "platform-specific #join behavior" do
|
63
|
+
it "joins components on Windows when some end with unix separators" do
|
64
|
+
expected = "C:\\foo\\bar\\baz"
|
65
|
+
expect(path_helper.join("C:\\foo/", "bar", "baz", windows: true)).to eq(expected)
|
66
|
+
end
|
67
|
+
|
68
|
+
it "joins components when some end with separators" do
|
69
|
+
expected = "C:\\foo\\bar\\baz"
|
70
|
+
expect(path_helper.join("C:\\foo\\", "bar", "baz", windows: true)).to eq(expected)
|
71
|
+
end
|
72
|
+
|
73
|
+
it "joins components when some end and start with separators" do
|
74
|
+
expected = "C:\\foo\\bar\\baz"
|
75
|
+
expect(path_helper.join("C:\\foo\\", "bar/", "/baz", windows: true)).to eq(expected)
|
76
|
+
end
|
77
|
+
|
78
|
+
it "joins components that don't end in separators" do
|
79
|
+
expected = "C:\\foo\\bar\\baz"
|
80
|
+
expect(path_helper.join("C:\\foo", "bar", "baz", windows: true)).to eq(expected)
|
81
|
+
end
|
82
|
+
end
|
83
|
+
|
84
|
+
it "cleanpath changes slashes into backslashes and leaves backslashes alone" do
|
85
|
+
expect(path_helper.cleanpath("/a/b\\c/d/", windows: true)).to eq("\\a\\b\\c\\d")
|
86
|
+
end
|
87
|
+
|
88
|
+
it "cleanpath does not remove leading double backslash" do
|
89
|
+
expect(path_helper.cleanpath("\\\\a/b\\c/d/", windows: true)).to eq("\\\\a\\b\\c\\d")
|
90
|
+
end
|
91
|
+
end
|
92
|
+
|
93
|
+
context "forcing unix" do
|
94
|
+
it "path_separator is /" do
|
95
|
+
expect(path_helper.path_separator(windows: false)).to eq("/")
|
96
|
+
end
|
97
|
+
|
98
|
+
it "cleanpath removes extra slashes alone" do
|
99
|
+
expect(path_helper.cleanpath("/a///b/c/d/", windows: false)).to eq("/a/b/c/d")
|
100
|
+
end
|
101
|
+
|
102
|
+
context "platform-specific #join behavior" do
|
103
|
+
it "joins components when some end with separators" do
|
104
|
+
expected = "/foo/bar/baz"
|
105
|
+
expect(path_helper.join("/foo/", "bar", "baz", windows: false)).to eq(expected)
|
106
|
+
end
|
107
|
+
|
108
|
+
it "joins components when some end and start with separators" do
|
109
|
+
expected = "/foo/bar/baz"
|
110
|
+
expect(path_helper.join("/foo/", "bar/", "/baz", windows: false)).to eq(expected)
|
111
|
+
end
|
112
|
+
|
113
|
+
it "joins components that don't end in separators" do
|
114
|
+
expected = "/foo/bar/baz"
|
115
|
+
expect(path_helper.join("/foo", "bar", "baz", windows: false)).to eq(expected)
|
116
|
+
end
|
117
|
+
end
|
118
|
+
|
119
|
+
it "cleanpath changes backslashes into slashes and leaves slashes alone" do
|
120
|
+
expect(path_helper.cleanpath("/a/b\\c/d/", windows: false)).to eq("/a/b/c/d")
|
121
|
+
end
|
122
|
+
|
123
|
+
it "cleanpath does not remove leading double backslash" do
|
124
|
+
expect(path_helper.cleanpath("\\\\a/b\\c/d/", windows: false)).to eq("//a/b/c/d")
|
125
|
+
end
|
126
|
+
end
|
127
|
+
end
|
128
|
+
|
129
|
+
context "on windows", :windows_only do
|
130
|
+
|
131
|
+
before(:each) do
|
132
|
+
allow(ChefUtils).to receive(:windows?).and_return(true)
|
133
|
+
end
|
134
|
+
|
135
|
+
it "path_separator is \\" do
|
136
|
+
expect(path_helper.path_separator).to eq("\\")
|
137
|
+
end
|
138
|
+
|
139
|
+
context "platform-specific #join behavior" do
|
140
|
+
it "joins components on Windows when some end with unix separators" do
|
141
|
+
expected = "C:\\foo\\bar\\baz"
|
142
|
+
expect(path_helper.join("C:\\foo/", "bar", "baz")).to eq(expected)
|
143
|
+
end
|
144
|
+
|
145
|
+
it "joins components when some end with separators" do
|
146
|
+
expected = "C:\\foo\\bar\\baz"
|
147
|
+
expect(path_helper.join("C:\\foo\\", "bar", "baz")).to eq(expected)
|
148
|
+
end
|
149
|
+
|
150
|
+
it "joins components when some end and start with separators" do
|
151
|
+
expected = "C:\\foo\\bar\\baz"
|
152
|
+
expect(path_helper.join("C:\\foo\\", "bar/", "/baz")).to eq(expected)
|
153
|
+
end
|
154
|
+
|
155
|
+
it "joins components that don't end in separators" do
|
156
|
+
expected = "C:\\foo\\bar\\baz"
|
157
|
+
expect(path_helper.join("C:\\foo", "bar", "baz")).to eq(expected)
|
158
|
+
end
|
159
|
+
end
|
160
|
+
|
161
|
+
it "cleanpath changes slashes into backslashes and leaves backslashes alone" do
|
162
|
+
expect(path_helper.cleanpath("/a/b\\c/d/")).to eq("\\a\\b\\c\\d")
|
163
|
+
end
|
164
|
+
|
165
|
+
it "cleanpath does not remove leading double backslash" do
|
166
|
+
expect(path_helper.cleanpath("\\\\a/b\\c/d/")).to eq("\\\\a\\b\\c\\d")
|
167
|
+
end
|
168
|
+
end
|
169
|
+
|
170
|
+
context "on unix", :unix_only do
|
171
|
+
before(:each) do
|
172
|
+
allow(ChefUtils).to receive(:windows?).and_return(false)
|
173
|
+
end
|
174
|
+
|
175
|
+
it "path_separator is /" do
|
176
|
+
expect(path_helper.path_separator).to eq("/")
|
177
|
+
end
|
178
|
+
|
179
|
+
it "cleanpath removes extra slashes alone" do
|
180
|
+
expect(path_helper.cleanpath("/a///b/c/d/")).to eq("/a/b/c/d")
|
181
|
+
end
|
182
|
+
|
183
|
+
context "platform-specific #join behavior" do
|
184
|
+
it "joins components when some end with separators" do
|
185
|
+
expected = path_helper.cleanpath("/foo/bar/baz")
|
186
|
+
expect(path_helper.join("/foo/", "bar", "baz")).to eq(expected)
|
187
|
+
end
|
188
|
+
|
189
|
+
it "joins components when some end and start with separators" do
|
190
|
+
expected = path_helper.cleanpath("/foo/bar/baz")
|
191
|
+
expect(path_helper.join("/foo/", "bar/", "/baz")).to eq(expected)
|
192
|
+
end
|
193
|
+
|
194
|
+
it "joins components that don't end in separators" do
|
195
|
+
expected = path_helper.cleanpath("/foo/bar/baz")
|
196
|
+
expect(path_helper.join("/foo", "bar", "baz")).to eq(expected)
|
197
|
+
end
|
198
|
+
end
|
199
|
+
|
200
|
+
it "cleanpath changes backslashes into slashes and leaves slashes alone" do
|
201
|
+
expect(path_helper.cleanpath("/a/b\\c/d/", windows: false)).to eq("/a/b/c/d")
|
202
|
+
end
|
203
|
+
|
204
|
+
# NOTE: this seems a bit weird to me, but this is just the way Pathname#cleanpath works
|
205
|
+
it "cleanpath does not remove leading double backslash" do
|
206
|
+
expect(path_helper.cleanpath("\\\\a/b\\c/d/")).to eq("//a/b/c/d")
|
207
|
+
end
|
208
|
+
end
|
209
|
+
|
210
|
+
context "validate_path" do
|
211
|
+
context "on windows" do
|
212
|
+
before(:each) do
|
213
|
+
# pass by default
|
214
|
+
allow(ChefUtils).to receive(:windows?).and_return(true)
|
215
|
+
allow(path_helper).to receive(:printable?).and_return(true)
|
216
|
+
allow(path_helper).to receive(:windows_max_length_exceeded?).and_return(false)
|
217
|
+
end
|
218
|
+
|
219
|
+
it "returns the path if the path passes the tests" do
|
220
|
+
expect(path_helper.validate_path("C:\\ThisIsRigged")).to eql("C:\\ThisIsRigged")
|
221
|
+
end
|
222
|
+
|
223
|
+
it "does not raise an error if everything looks great" do
|
224
|
+
expect { path_helper.validate_path("C:\\cool path\\dude.exe") }.not_to raise_error
|
225
|
+
end
|
226
|
+
|
227
|
+
it "raises an error if the path has invalid characters" do
|
228
|
+
allow(path_helper).to receive(:printable?).and_return(false)
|
229
|
+
expect { path_helper.validate_path("Newline!\n") }.to raise_error(ChefConfig::InvalidPath)
|
230
|
+
end
|
231
|
+
|
232
|
+
it "Adds the \\\\?\\ prefix if the path exceeds MAX_LENGTH and does not have it" do
|
233
|
+
long_path = "C:\\" + "a" * 250 + "\\" + "b" * 250
|
234
|
+
prefixed_long_path = "\\\\?\\" + long_path
|
235
|
+
allow(path_helper).to receive(:windows_max_length_exceeded?).and_return(true)
|
236
|
+
expect(path_helper.validate_path(long_path)).to eql(prefixed_long_path)
|
237
|
+
end
|
238
|
+
end
|
239
|
+
end
|
240
|
+
|
241
|
+
context "windows_max_length_exceeded?" do
|
242
|
+
it "returns true if the path is too long (259 + NUL) for the API" do
|
243
|
+
expect(path_helper.windows_max_length_exceeded?("C:\\" + "a" * 250 + "\\" + "b" * 6)).to be_truthy
|
244
|
+
end
|
245
|
+
|
246
|
+
it "returns false if the path is not too long (259 + NUL) for the standard API" do
|
247
|
+
expect(path_helper.windows_max_length_exceeded?("C:\\" + "a" * 250 + "\\" + "b" * 5)).to be_falsey
|
248
|
+
end
|
249
|
+
|
250
|
+
it "returns false if the path is over 259 characters but uses the \\\\?\\ prefix" do
|
251
|
+
expect(path_helper.windows_max_length_exceeded?("\\\\?\\C:\\" + "a" * 250 + "\\" + "b" * 250)).to be_falsey
|
252
|
+
end
|
253
|
+
end
|
254
|
+
|
255
|
+
context "printable?" do
|
256
|
+
it "returns true if the string contains no non-printable characters" do
|
257
|
+
expect(path_helper.printable?("C:\\Program Files (x86)\\Microsoft Office\\Files.lst")).to be_truthy
|
258
|
+
end
|
259
|
+
|
260
|
+
it "returns true when given 'abc' in unicode" do
|
261
|
+
expect(path_helper.printable?("\u0061\u0062\u0063")).to be_truthy
|
262
|
+
end
|
263
|
+
|
264
|
+
it "returns true when given japanese unicode" do
|
265
|
+
expect(path_helper.printable?("\uff86\uff87\uff88")).to be_truthy
|
266
|
+
end
|
267
|
+
|
268
|
+
it "returns false if the string contains a non-printable character" do
|
269
|
+
expect(path_helper.printable?("\my files\work\notes.txt")).to be_falsey
|
270
|
+
end
|
271
|
+
|
272
|
+
# This isn't necessarily a requirement, but here to be explicit about functionality.
|
273
|
+
it "returns false if the string contains a newline or tab" do
|
274
|
+
expect(path_helper.printable?("\tThere's no way,\n\t *no* way,\n\t that you came from my loins.\n")).to be_falsey
|
275
|
+
end
|
276
|
+
end
|
277
|
+
|
278
|
+
context "canonical_path" do
|
279
|
+
context "on windows", :windows_only do
|
280
|
+
it "returns an absolute path with backslashes instead of slashes" do
|
281
|
+
expect(path_helper.canonical_path("\\\\?\\C:/windows/win.ini")).to eq("\\\\?\\c:\\windows\\win.ini")
|
282
|
+
end
|
283
|
+
|
284
|
+
it "adds the \\\\?\\ prefix if it is missing" do
|
285
|
+
expect(path_helper.canonical_path("C:/windows/win.ini")).to eq("\\\\?\\c:\\windows\\win.ini")
|
286
|
+
end
|
287
|
+
|
288
|
+
it "returns a lowercase path" do
|
289
|
+
expect(path_helper.canonical_path("\\\\?\\C:\\CASE\\INSENSITIVE")).to eq("\\\\?\\c:\\case\\insensitive")
|
290
|
+
end
|
291
|
+
end
|
292
|
+
|
293
|
+
context "not on windows", :unix_only do
|
294
|
+
it "returns a canonical path" do
|
295
|
+
expect(path_helper.canonical_path("/etc//apache.d/sites-enabled/../sites-available/default")).to eq("/etc/apache.d/sites-available/default")
|
296
|
+
end
|
297
|
+
end
|
298
|
+
end
|
299
|
+
|
300
|
+
context "paths_eql?" do
|
301
|
+
it "returns true if the paths are the same" do
|
302
|
+
allow(path_helper).to receive(:canonical_path).with("bandit", windows: ChefUtils.windows?).and_return("c:/bandit/bandit")
|
303
|
+
allow(path_helper).to receive(:canonical_path).with("../bandit/bandit", windows: ChefUtils.windows?).and_return("c:/bandit/bandit")
|
304
|
+
expect(path_helper.paths_eql?("bandit", "../bandit/bandit")).to be_truthy
|
305
|
+
end
|
306
|
+
|
307
|
+
it "returns false if the paths are different" do
|
308
|
+
allow(path_helper).to receive(:canonical_path).with("bandit", windows: ChefUtils.windows?).and_return("c:/Bo/Bandit")
|
309
|
+
allow(path_helper).to receive(:canonical_path).with("../bandit/bandit", windows: ChefUtils.windows?).and_return("c:/bandit/bandit")
|
310
|
+
expect(path_helper.paths_eql?("bandit", "../bandit/bandit")).to be_falsey
|
311
|
+
end
|
312
|
+
end
|
313
|
+
|
314
|
+
context "escape_glob" do
|
315
|
+
it "escapes characters reserved by glob" do
|
316
|
+
path = "C:\\this\\*path\\[needs]\\escaping?"
|
317
|
+
escaped_path = "C:\\\\this\\\\\\*path\\\\\\[needs\\]\\\\escaping\\?"
|
318
|
+
expect(path_helper.escape_glob(path, windows: true)).to eq(escaped_path)
|
319
|
+
end
|
320
|
+
|
321
|
+
context "when given more than one argument" do
|
322
|
+
it "joins, cleanpaths, and escapes characters reserved by glob" do
|
323
|
+
args = ["this/*path", "[needs]", "escaping?"]
|
324
|
+
escaped_path = if ChefUtils.windows?
|
325
|
+
"this\\\\\\*path\\\\\\[needs\\]\\\\escaping\\?"
|
326
|
+
else
|
327
|
+
"this/\\*path/\\[needs\\]/escaping\\?"
|
328
|
+
end
|
329
|
+
expect(path_helper.escape_glob(*args)).to eq(escaped_path)
|
330
|
+
end
|
331
|
+
end
|
332
|
+
end
|
333
|
+
|
334
|
+
context "escape_glob_dir" do
|
335
|
+
it "escapes characters reserved by glob without using backslashes for path separators" do
|
336
|
+
path = "C:/this/*path/[needs]/escaping?"
|
337
|
+
escaped_path = "C:/this/\\*path/\\[needs\\]/escaping\\?"
|
338
|
+
expect(path_helper.escape_glob_dir(path)).to eq(escaped_path)
|
339
|
+
end
|
340
|
+
|
341
|
+
context "when given more than one argument" do
|
342
|
+
it "joins, cleanpaths, and escapes characters reserved by glob" do
|
343
|
+
args = ["this/*path", "[needs]", "escaping?"]
|
344
|
+
escaped_path = "this/\\*path/\\[needs\\]/escaping\\?"
|
345
|
+
expect(path_helper).to receive(:join).with(*args).and_call_original
|
346
|
+
expect(path_helper.escape_glob_dir(*args)).to eq(escaped_path)
|
347
|
+
end
|
348
|
+
end
|
349
|
+
end
|
350
|
+
|
351
|
+
context "all_homes" do
|
352
|
+
before do
|
353
|
+
stub_const("ENV", env)
|
354
|
+
allow(ChefUtils).to receive(:windows?).and_return(is_windows)
|
355
|
+
end
|
356
|
+
|
357
|
+
context "on windows" do
|
358
|
+
let(:is_windows) { true }
|
359
|
+
end
|
360
|
+
|
361
|
+
context "on unix" do
|
362
|
+
let(:is_windows) { false }
|
363
|
+
|
364
|
+
context "when HOME is not set" do
|
365
|
+
let(:env) { {} }
|
366
|
+
it "returns an empty array" do
|
367
|
+
expect(path_helper.all_homes).to eq([])
|
368
|
+
end
|
369
|
+
end
|
370
|
+
end
|
371
|
+
end
|
372
|
+
end
|