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.
@@ -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