chef-config 18.2.5 → 18.3.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -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