chef-config 13.8.5 → 13.9.1

Sign up to get free protection for your applications and to get access to all the features.
@@ -1,128 +1,128 @@
1
- #
2
- # Author:: Matt Wrock (<matt@mattwrock.com>)
3
- # Copyright:: Copyright (c) 2016-2017, 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/fips"
20
- require "spec_helper"
21
-
22
- begin
23
- require "win32/registry"
24
- rescue LoadError
25
- # not on unix
26
- end
27
-
28
- RSpec.describe "ChefConfig.fips?" do
29
- let(:enabled) { "0" }
30
-
31
- context "on *nix" do
32
- let(:fips_path) { "/proc/sys/crypto/fips_enabled" }
33
-
34
- before(:each) do
35
- allow(ChefConfig).to receive(:windows?).and_return(false)
36
- allow(::File).to receive(:exist?).with(fips_path).and_return(true)
37
- allow(::File).to receive(:read).with(fips_path).and_return(enabled)
38
- end
39
-
40
- context "fips file is present and contains 1" do
41
- let(:enabled) { "1" }
42
-
43
- it "returns true" do
44
- expect(ChefConfig.fips?).to be(true)
45
- end
46
- end
47
-
48
- context "fips file does not contain 1" do
49
- let(:enabled) { "0" }
50
-
51
- it "returns false" do
52
- expect(ChefConfig.fips?).to be(false)
53
- end
54
- end
55
-
56
- context "fips file is not present" do
57
- before do
58
- allow(::File).to receive(:exist?).with(fips_path).and_return(false)
59
- end
60
-
61
- it "returns false" do
62
- expect(ChefConfig.fips?).to be(false)
63
- end
64
- end
65
- end
66
-
67
- context "on windows", :windows_only do
68
- let(:fips_key) { 'System\CurrentControlSet\Control\Lsa\FIPSAlgorithmPolicy' }
69
- let(:win_reg_entry) { { "Enabled" => enabled } }
70
-
71
- before(:each) do
72
- allow(ChefConfig).to receive(:windows?).and_return(true)
73
- allow(Win32::Registry::HKEY_LOCAL_MACHINE).to receive(:open).with(fips_key, arch).and_yield(win_reg_entry)
74
- end
75
-
76
- shared_examples "fips_detection" do
77
- context "fips enabled key is set to 1" do
78
- let(:enabled) { 1 }
79
-
80
- it "returns true" do
81
- expect(ChefConfig.fips?).to be(true)
82
- end
83
- end
84
-
85
- context "fips enabled key is set to 0" do
86
- let(:enabled) { 0 }
87
-
88
- it "returns false" do
89
- expect(ChefConfig.fips?).to be(false)
90
- end
91
- end
92
-
93
- context "fips key does not exist" do
94
- before do
95
- allow(Win32::Registry::HKEY_LOCAL_MACHINE).to receive(:open).and_raise(Win32::Registry::Error, 50)
96
- end
97
-
98
- it "returns false" do
99
- expect(ChefConfig.fips?).to be(false)
100
- end
101
- end
102
- end
103
-
104
- context "on 32 bit ruby" do
105
- let(:arch) { Win32::Registry::KEY_READ | 0x100 }
106
-
107
- before { stub_const("::RbConfig::CONFIG", { "target_cpu" => "i386" } ) }
108
-
109
- it_behaves_like "fips_detection"
110
- end
111
-
112
- context "on 64 bit ruby" do
113
- let(:arch) { Win32::Registry::KEY_READ | 0x200 }
114
-
115
- before { stub_const("::RbConfig::CONFIG", { "target_cpu" => "x86_64" } ) }
116
-
117
- it_behaves_like "fips_detection"
118
- end
119
-
120
- context "on unknown ruby" do
121
- let(:arch) { Win32::Registry::KEY_READ }
122
-
123
- before { stub_const("::RbConfig::CONFIG", { "target_cpu" => nil } ) }
124
-
125
- it_behaves_like "fips_detection"
126
- end
127
- end
128
- end
1
+ #
2
+ # Author:: Matt Wrock (<matt@mattwrock.com>)
3
+ # Copyright:: Copyright (c) 2016-2017, 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/fips"
20
+ require "spec_helper"
21
+
22
+ begin
23
+ require "win32/registry"
24
+ rescue LoadError
25
+ # not on unix
26
+ end
27
+
28
+ RSpec.describe "ChefConfig.fips?" do
29
+ let(:enabled) { "0" }
30
+
31
+ context "on *nix" do
32
+ let(:fips_path) { "/proc/sys/crypto/fips_enabled" }
33
+
34
+ before(:each) do
35
+ allow(ChefConfig).to receive(:windows?).and_return(false)
36
+ allow(::File).to receive(:exist?).with(fips_path).and_return(true)
37
+ allow(::File).to receive(:read).with(fips_path).and_return(enabled)
38
+ end
39
+
40
+ context "fips file is present and contains 1" do
41
+ let(:enabled) { "1" }
42
+
43
+ it "returns true" do
44
+ expect(ChefConfig.fips?).to be(true)
45
+ end
46
+ end
47
+
48
+ context "fips file does not contain 1" do
49
+ let(:enabled) { "0" }
50
+
51
+ it "returns false" do
52
+ expect(ChefConfig.fips?).to be(false)
53
+ end
54
+ end
55
+
56
+ context "fips file is not present" do
57
+ before do
58
+ allow(::File).to receive(:exist?).with(fips_path).and_return(false)
59
+ end
60
+
61
+ it "returns false" do
62
+ expect(ChefConfig.fips?).to be(false)
63
+ end
64
+ end
65
+ end
66
+
67
+ context "on windows", :windows_only do
68
+ let(:fips_key) { 'System\CurrentControlSet\Control\Lsa\FIPSAlgorithmPolicy' }
69
+ let(:win_reg_entry) { { "Enabled" => enabled } }
70
+
71
+ before(:each) do
72
+ allow(ChefConfig).to receive(:windows?).and_return(true)
73
+ allow(Win32::Registry::HKEY_LOCAL_MACHINE).to receive(:open).with(fips_key, arch).and_yield(win_reg_entry)
74
+ end
75
+
76
+ shared_examples "fips_detection" do
77
+ context "fips enabled key is set to 1" do
78
+ let(:enabled) { 1 }
79
+
80
+ it "returns true" do
81
+ expect(ChefConfig.fips?).to be(true)
82
+ end
83
+ end
84
+
85
+ context "fips enabled key is set to 0" do
86
+ let(:enabled) { 0 }
87
+
88
+ it "returns false" do
89
+ expect(ChefConfig.fips?).to be(false)
90
+ end
91
+ end
92
+
93
+ context "fips key does not exist" do
94
+ before do
95
+ allow(Win32::Registry::HKEY_LOCAL_MACHINE).to receive(:open).and_raise(Win32::Registry::Error, 50)
96
+ end
97
+
98
+ it "returns false" do
99
+ expect(ChefConfig.fips?).to be(false)
100
+ end
101
+ end
102
+ end
103
+
104
+ context "on 32 bit ruby" do
105
+ let(:arch) { Win32::Registry::KEY_READ | 0x100 }
106
+
107
+ before { stub_const("::RbConfig::CONFIG", { "target_cpu" => "i386" } ) }
108
+
109
+ it_behaves_like "fips_detection"
110
+ end
111
+
112
+ context "on 64 bit ruby" do
113
+ let(:arch) { Win32::Registry::KEY_READ | 0x200 }
114
+
115
+ before { stub_const("::RbConfig::CONFIG", { "target_cpu" => "x86_64" } ) }
116
+
117
+ it_behaves_like "fips_detection"
118
+ end
119
+
120
+ context "on unknown ruby" do
121
+ let(:arch) { Win32::Registry::KEY_READ }
122
+
123
+ before { stub_const("::RbConfig::CONFIG", { "target_cpu" => nil } ) }
124
+
125
+ it_behaves_like "fips_detection"
126
+ end
127
+ end
128
+ end
@@ -1,307 +1,307 @@
1
- #
2
- # Author:: Bryan McLellan <btm@loftninjas.org>
3
- # Copyright:: Copyright 2014-2016, 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
- shared_examples_for "common_functionality" do
27
- describe "join" do
28
-
29
- it "joins starting with '' resolve to absolute paths" do
30
- expect(path_helper.join("", "a", "b")).to eq("#{path_helper.path_separator}a#{path_helper.path_separator}b")
31
- end
32
-
33
- it "joins ending with '' add a / to the end" do
34
- expect(path_helper.join("a", "b", "")).to eq("a#{path_helper.path_separator}b#{path_helper.path_separator}")
35
- end
36
-
37
- end
38
-
39
- describe "dirname" do
40
- it "dirname('abc') is '.'" do
41
- expect(path_helper.dirname("abc")).to eq(".")
42
- end
43
- it "dirname('/') is '/'" do
44
- expect(path_helper.dirname(path_helper.path_separator)).to eq(path_helper.path_separator)
45
- end
46
- it "dirname('a/b/c') is 'a/b'" do
47
- expect(path_helper.dirname(path_helper.join("a", "b", "c"))).to eq(path_helper.join("a", "b"))
48
- end
49
- it "dirname('a/b/c/') is 'a/b'" do
50
- expect(path_helper.dirname(path_helper.join("a", "b", "c", ""))).to eq(path_helper.join("a", "b"))
51
- end
52
- it "dirname('/a/b/c') is '/a/b'" do
53
- expect(path_helper.dirname(path_helper.join("", "a", "b", "c"))).to eq(path_helper.join("", "a", "b"))
54
- end
55
- end
56
- end
57
-
58
- context "on windows" do
59
-
60
- before(:each) do
61
- allow(ChefConfig).to receive(:windows?).and_return(true)
62
- end
63
-
64
- include_examples("common_functionality")
65
-
66
- it "path_separator is \\" do
67
- expect(path_helper.path_separator).to eq('\\')
68
- end
69
-
70
- describe "platform-specific #join behavior" do
71
-
72
- it "joins components on Windows when some end with unix separators" do
73
- expect(path_helper.join('C:\\foo/', "bar", "baz")).to eq('C:\\foo\\bar\\baz')
74
- end
75
-
76
- it "joins components when some end with separators" do
77
- expected = path_helper.cleanpath("/foo/bar/baz")
78
- expected = "C:#{expected}"
79
- expect(path_helper.join('C:\\foo\\', "bar", "baz")).to eq(expected)
80
- end
81
-
82
- it "joins components when some end and start with separators" do
83
- expected = path_helper.cleanpath("/foo/bar/baz")
84
- expected = "C:#{expected}"
85
- expect(path_helper.join('C:\\foo\\', "bar/", "/baz")).to eq(expected)
86
- end
87
-
88
- it "joins components that don't end in separators" do
89
- expected = path_helper.cleanpath("/foo/bar/baz")
90
- expected = "C:#{expected}"
91
- expect(path_helper.join('C:\\foo', "bar", "baz")).to eq(expected)
92
- end
93
-
94
- end
95
-
96
- it "cleanpath changes slashes into backslashes and leaves backslashes alone" do
97
- expect(path_helper.cleanpath('/a/b\\c/d/')).to eq('\\a\\b\\c\\d')
98
- end
99
-
100
- it "cleanpath does not remove leading double backslash" do
101
- expect(path_helper.cleanpath('\\\\a/b\\c/d/')).to eq('\\\\a\\b\\c\\d')
102
- end
103
-
104
- end
105
-
106
- context "on unix" do
107
-
108
- before(:each) do
109
- allow(ChefConfig).to receive(:windows?).and_return(false)
110
- end
111
-
112
- include_examples("common_functionality")
113
-
114
- it "path_separator is /" do
115
- expect(path_helper.path_separator).to eq("/")
116
- end
117
-
118
- it "cleanpath removes extra slashes alone" do
119
- expect(path_helper.cleanpath("/a///b/c/d/")).to eq("/a/b/c/d")
120
- end
121
-
122
- describe "platform-specific #join behavior" do
123
-
124
- it "joins components when some end with separators" do
125
- expected = path_helper.cleanpath("/foo/bar/baz")
126
- expect(path_helper.join("/foo/", "bar", "baz")).to eq(expected)
127
- end
128
-
129
- it "joins components when some end and start with separators" do
130
- expected = path_helper.cleanpath("/foo/bar/baz")
131
- expect(path_helper.join("/foo/", "bar/", "/baz")).to eq(expected)
132
- end
133
-
134
- it "joins components that don't end in separators" do
135
- expected = path_helper.cleanpath("/foo/bar/baz")
136
- expect(path_helper.join("/foo", "bar", "baz")).to eq(expected)
137
- end
138
-
139
- end
140
-
141
- end
142
-
143
- describe "validate_path" do
144
- context "on windows" do
145
- before(:each) do
146
- # pass by default
147
- allow(ChefConfig).to receive(:windows?).and_return(true)
148
- allow(path_helper).to receive(:printable?).and_return(true)
149
- allow(path_helper).to receive(:windows_max_length_exceeded?).and_return(false)
150
- end
151
-
152
- it "returns the path if the path passes the tests" do
153
- expect(path_helper.validate_path("C:\\ThisIsRigged")).to eql("C:\\ThisIsRigged")
154
- end
155
-
156
- it "does not raise an error if everything looks great" do
157
- expect { path_helper.validate_path("C:\\cool path\\dude.exe") }.not_to raise_error
158
- end
159
-
160
- it "raises an error if the path has invalid characters" do
161
- allow(path_helper).to receive(:printable?).and_return(false)
162
- expect { path_helper.validate_path("Newline!\n") }.to raise_error(ChefConfig::InvalidPath)
163
- end
164
-
165
- it "Adds the \\\\?\\ prefix if the path exceeds MAX_LENGTH and does not have it" do
166
- long_path = "C:\\" + "a" * 250 + "\\" + "b" * 250
167
- prefixed_long_path = "\\\\?\\" + long_path
168
- allow(path_helper).to receive(:windows_max_length_exceeded?).and_return(true)
169
- expect(path_helper.validate_path(long_path)).to eql(prefixed_long_path)
170
- end
171
- end
172
- end
173
-
174
- describe "windows_max_length_exceeded?" do
175
- it "returns true if the path is too long (259 + NUL) for the API" do
176
- expect(path_helper.windows_max_length_exceeded?("C:\\" + "a" * 250 + "\\" + "b" * 6)).to be_truthy
177
- end
178
-
179
- it "returns false if the path is not too long (259 + NUL) for the standard API" do
180
- expect(path_helper.windows_max_length_exceeded?("C:\\" + "a" * 250 + "\\" + "b" * 5)).to be_falsey
181
- end
182
-
183
- it "returns false if the path is over 259 characters but uses the \\\\?\\ prefix" do
184
- expect(path_helper.windows_max_length_exceeded?("\\\\?\\C:\\" + "a" * 250 + "\\" + "b" * 250)).to be_falsey
185
- end
186
- end
187
-
188
- describe "printable?" do
189
- it "returns true if the string contains no non-printable characters" do
190
- expect(path_helper.printable?("C:\\Program Files (x86)\\Microsoft Office\\Files.lst")).to be_truthy
191
- end
192
-
193
- it "returns true when given 'abc' in unicode" do
194
- expect(path_helper.printable?("\u0061\u0062\u0063")).to be_truthy
195
- end
196
-
197
- it "returns true when given japanese unicode" do
198
- expect(path_helper.printable?("\uff86\uff87\uff88")).to be_truthy
199
- end
200
-
201
- it "returns false if the string contains a non-printable character" do
202
- expect(path_helper.printable?("\my files\work\notes.txt")).to be_falsey
203
- end
204
-
205
- # This isn't necessarily a requirement, but here to be explicit about functionality.
206
- it "returns false if the string contains a newline or tab" do
207
- expect(path_helper.printable?("\tThere's no way,\n\t *no* way,\n\t that you came from my loins.\n")).to be_falsey
208
- end
209
- end
210
-
211
- describe "canonical_path" do
212
- context "on windows", :windows_only do
213
- it "returns an absolute path with backslashes instead of slashes" do
214
- expect(path_helper.canonical_path("\\\\?\\C:/windows/win.ini")).to eq("\\\\?\\c:\\windows\\win.ini")
215
- end
216
-
217
- it "adds the \\\\?\\ prefix if it is missing" do
218
- expect(path_helper.canonical_path("C:/windows/win.ini")).to eq("\\\\?\\c:\\windows\\win.ini")
219
- end
220
-
221
- it "returns a lowercase path" do
222
- expect(path_helper.canonical_path("\\\\?\\C:\\CASE\\INSENSITIVE")).to eq("\\\\?\\c:\\case\\insensitive")
223
- end
224
- end
225
-
226
- context "not on windows", :unix_only do
227
- it "returns a canonical path" do
228
- expect(path_helper.canonical_path("/etc//apache.d/sites-enabled/../sites-available/default")).to eq("/etc/apache.d/sites-available/default")
229
- end
230
- end
231
- end
232
-
233
- describe "paths_eql?" do
234
- it "returns true if the paths are the same" do
235
- allow(path_helper).to receive(:canonical_path).with("bandit").and_return("c:/bandit/bandit")
236
- allow(path_helper).to receive(:canonical_path).with("../bandit/bandit").and_return("c:/bandit/bandit")
237
- expect(path_helper.paths_eql?("bandit", "../bandit/bandit")).to be_truthy
238
- end
239
-
240
- it "returns false if the paths are different" do
241
- allow(path_helper).to receive(:canonical_path).with("bandit").and_return("c:/Bo/Bandit")
242
- allow(path_helper).to receive(:canonical_path).with("../bandit/bandit").and_return("c:/bandit/bandit")
243
- expect(path_helper.paths_eql?("bandit", "../bandit/bandit")).to be_falsey
244
- end
245
- end
246
-
247
- describe "escape_glob" do
248
- it "escapes characters reserved by glob" do
249
- path = "C:\\this\\*path\\[needs]\\escaping?"
250
- escaped_path = "C:\\\\this\\\\\\*path\\\\\\[needs\\]\\\\escaping\\?"
251
- expect(path_helper.escape_glob(path)).to eq(escaped_path)
252
- end
253
-
254
- context "when given more than one argument" do
255
- it "joins, cleanpaths, and escapes characters reserved by glob" do
256
- args = ["this/*path", "[needs]", "escaping?"]
257
- escaped_path = if ChefConfig.windows?
258
- "this\\\\\\*path\\\\\\[needs\\]\\\\escaping\\?"
259
- else
260
- "this/\\*path/\\[needs\\]/escaping\\?"
261
- end
262
- expect(path_helper).to receive(:join).with(*args).and_call_original
263
- expect(path_helper).to receive(:cleanpath).and_call_original
264
- expect(path_helper.escape_glob(*args)).to eq(escaped_path)
265
- end
266
- end
267
- end
268
-
269
- describe "escape_glob_dir" do
270
- it "escapes characters reserved by glob without using backslashes for path separators" do
271
- path = "C:/this/*path/[needs]/escaping?"
272
- escaped_path = "C:/this/\\*path/\\[needs\\]/escaping\\?"
273
- expect(path_helper.escape_glob_dir(path)).to eq(escaped_path)
274
- end
275
-
276
- context "when given more than one argument" do
277
- it "joins, cleanpaths, and escapes characters reserved by glob" do
278
- args = ["this/*path", "[needs]", "escaping?"]
279
- escaped_path = "this/\\*path/\\[needs\\]/escaping\\?"
280
- expect(path_helper).to receive(:join).with(*args).and_call_original
281
- expect(path_helper.escape_glob_dir(*args)).to eq(escaped_path)
282
- end
283
- end
284
- end
285
-
286
- describe "all_homes" do
287
- before do
288
- stub_const("ENV", env)
289
- allow(ChefConfig).to receive(:windows?).and_return(is_windows)
290
- end
291
-
292
- context "on windows" do
293
- let (:is_windows) { true }
294
- end
295
-
296
- context "on unix" do
297
- let (:is_windows) { false }
298
-
299
- context "when HOME is not set" do
300
- let (:env) { {} }
301
- it "returns an empty array" do
302
- expect(path_helper.all_homes).to eq([])
303
- end
304
- end
305
- end
306
- end
307
- end
1
+ #
2
+ # Author:: Bryan McLellan <btm@loftninjas.org>
3
+ # Copyright:: Copyright 2014-2016, 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
+ shared_examples_for "common_functionality" do
27
+ describe "join" do
28
+
29
+ it "joins starting with '' resolve to absolute paths" do
30
+ expect(path_helper.join("", "a", "b")).to eq("#{path_helper.path_separator}a#{path_helper.path_separator}b")
31
+ end
32
+
33
+ it "joins ending with '' add a / to the end" do
34
+ expect(path_helper.join("a", "b", "")).to eq("a#{path_helper.path_separator}b#{path_helper.path_separator}")
35
+ end
36
+
37
+ end
38
+
39
+ describe "dirname" do
40
+ it "dirname('abc') is '.'" do
41
+ expect(path_helper.dirname("abc")).to eq(".")
42
+ end
43
+ it "dirname('/') is '/'" do
44
+ expect(path_helper.dirname(path_helper.path_separator)).to eq(path_helper.path_separator)
45
+ end
46
+ it "dirname('a/b/c') is 'a/b'" do
47
+ expect(path_helper.dirname(path_helper.join("a", "b", "c"))).to eq(path_helper.join("a", "b"))
48
+ end
49
+ it "dirname('a/b/c/') is 'a/b'" do
50
+ expect(path_helper.dirname(path_helper.join("a", "b", "c", ""))).to eq(path_helper.join("a", "b"))
51
+ end
52
+ it "dirname('/a/b/c') is '/a/b'" do
53
+ expect(path_helper.dirname(path_helper.join("", "a", "b", "c"))).to eq(path_helper.join("", "a", "b"))
54
+ end
55
+ end
56
+ end
57
+
58
+ context "on windows" do
59
+
60
+ before(:each) do
61
+ allow(ChefConfig).to receive(:windows?).and_return(true)
62
+ end
63
+
64
+ include_examples("common_functionality")
65
+
66
+ it "path_separator is \\" do
67
+ expect(path_helper.path_separator).to eq('\\')
68
+ end
69
+
70
+ describe "platform-specific #join behavior" do
71
+
72
+ it "joins components on Windows when some end with unix separators" do
73
+ expect(path_helper.join('C:\\foo/', "bar", "baz")).to eq('C:\\foo\\bar\\baz')
74
+ end
75
+
76
+ it "joins components when some end with separators" do
77
+ expected = path_helper.cleanpath("/foo/bar/baz")
78
+ expected = "C:#{expected}"
79
+ expect(path_helper.join('C:\\foo\\', "bar", "baz")).to eq(expected)
80
+ end
81
+
82
+ it "joins components when some end and start with separators" do
83
+ expected = path_helper.cleanpath("/foo/bar/baz")
84
+ expected = "C:#{expected}"
85
+ expect(path_helper.join('C:\\foo\\', "bar/", "/baz")).to eq(expected)
86
+ end
87
+
88
+ it "joins components that don't end in separators" do
89
+ expected = path_helper.cleanpath("/foo/bar/baz")
90
+ expected = "C:#{expected}"
91
+ expect(path_helper.join('C:\\foo', "bar", "baz")).to eq(expected)
92
+ end
93
+
94
+ end
95
+
96
+ it "cleanpath changes slashes into backslashes and leaves backslashes alone" do
97
+ expect(path_helper.cleanpath('/a/b\\c/d/')).to eq('\\a\\b\\c\\d')
98
+ end
99
+
100
+ it "cleanpath does not remove leading double backslash" do
101
+ expect(path_helper.cleanpath('\\\\a/b\\c/d/')).to eq('\\\\a\\b\\c\\d')
102
+ end
103
+
104
+ end
105
+
106
+ context "on unix" do
107
+
108
+ before(:each) do
109
+ allow(ChefConfig).to receive(:windows?).and_return(false)
110
+ end
111
+
112
+ include_examples("common_functionality")
113
+
114
+ it "path_separator is /" do
115
+ expect(path_helper.path_separator).to eq("/")
116
+ end
117
+
118
+ it "cleanpath removes extra slashes alone" do
119
+ expect(path_helper.cleanpath("/a///b/c/d/")).to eq("/a/b/c/d")
120
+ end
121
+
122
+ describe "platform-specific #join behavior" do
123
+
124
+ it "joins components when some end with separators" do
125
+ expected = path_helper.cleanpath("/foo/bar/baz")
126
+ expect(path_helper.join("/foo/", "bar", "baz")).to eq(expected)
127
+ end
128
+
129
+ it "joins components when some end and start with separators" do
130
+ expected = path_helper.cleanpath("/foo/bar/baz")
131
+ expect(path_helper.join("/foo/", "bar/", "/baz")).to eq(expected)
132
+ end
133
+
134
+ it "joins components that don't end in separators" do
135
+ expected = path_helper.cleanpath("/foo/bar/baz")
136
+ expect(path_helper.join("/foo", "bar", "baz")).to eq(expected)
137
+ end
138
+
139
+ end
140
+
141
+ end
142
+
143
+ describe "validate_path" do
144
+ context "on windows" do
145
+ before(:each) do
146
+ # pass by default
147
+ allow(ChefConfig).to receive(:windows?).and_return(true)
148
+ allow(path_helper).to receive(:printable?).and_return(true)
149
+ allow(path_helper).to receive(:windows_max_length_exceeded?).and_return(false)
150
+ end
151
+
152
+ it "returns the path if the path passes the tests" do
153
+ expect(path_helper.validate_path("C:\\ThisIsRigged")).to eql("C:\\ThisIsRigged")
154
+ end
155
+
156
+ it "does not raise an error if everything looks great" do
157
+ expect { path_helper.validate_path("C:\\cool path\\dude.exe") }.not_to raise_error
158
+ end
159
+
160
+ it "raises an error if the path has invalid characters" do
161
+ allow(path_helper).to receive(:printable?).and_return(false)
162
+ expect { path_helper.validate_path("Newline!\n") }.to raise_error(ChefConfig::InvalidPath)
163
+ end
164
+
165
+ it "Adds the \\\\?\\ prefix if the path exceeds MAX_LENGTH and does not have it" do
166
+ long_path = "C:\\" + "a" * 250 + "\\" + "b" * 250
167
+ prefixed_long_path = "\\\\?\\" + long_path
168
+ allow(path_helper).to receive(:windows_max_length_exceeded?).and_return(true)
169
+ expect(path_helper.validate_path(long_path)).to eql(prefixed_long_path)
170
+ end
171
+ end
172
+ end
173
+
174
+ describe "windows_max_length_exceeded?" do
175
+ it "returns true if the path is too long (259 + NUL) for the API" do
176
+ expect(path_helper.windows_max_length_exceeded?("C:\\" + "a" * 250 + "\\" + "b" * 6)).to be_truthy
177
+ end
178
+
179
+ it "returns false if the path is not too long (259 + NUL) for the standard API" do
180
+ expect(path_helper.windows_max_length_exceeded?("C:\\" + "a" * 250 + "\\" + "b" * 5)).to be_falsey
181
+ end
182
+
183
+ it "returns false if the path is over 259 characters but uses the \\\\?\\ prefix" do
184
+ expect(path_helper.windows_max_length_exceeded?("\\\\?\\C:\\" + "a" * 250 + "\\" + "b" * 250)).to be_falsey
185
+ end
186
+ end
187
+
188
+ describe "printable?" do
189
+ it "returns true if the string contains no non-printable characters" do
190
+ expect(path_helper.printable?("C:\\Program Files (x86)\\Microsoft Office\\Files.lst")).to be_truthy
191
+ end
192
+
193
+ it "returns true when given 'abc' in unicode" do
194
+ expect(path_helper.printable?("\u0061\u0062\u0063")).to be_truthy
195
+ end
196
+
197
+ it "returns true when given japanese unicode" do
198
+ expect(path_helper.printable?("\uff86\uff87\uff88")).to be_truthy
199
+ end
200
+
201
+ it "returns false if the string contains a non-printable character" do
202
+ expect(path_helper.printable?("\my files\work\notes.txt")).to be_falsey
203
+ end
204
+
205
+ # This isn't necessarily a requirement, but here to be explicit about functionality.
206
+ it "returns false if the string contains a newline or tab" do
207
+ expect(path_helper.printable?("\tThere's no way,\n\t *no* way,\n\t that you came from my loins.\n")).to be_falsey
208
+ end
209
+ end
210
+
211
+ describe "canonical_path" do
212
+ context "on windows", :windows_only do
213
+ it "returns an absolute path with backslashes instead of slashes" do
214
+ expect(path_helper.canonical_path("\\\\?\\C:/windows/win.ini")).to eq("\\\\?\\c:\\windows\\win.ini")
215
+ end
216
+
217
+ it "adds the \\\\?\\ prefix if it is missing" do
218
+ expect(path_helper.canonical_path("C:/windows/win.ini")).to eq("\\\\?\\c:\\windows\\win.ini")
219
+ end
220
+
221
+ it "returns a lowercase path" do
222
+ expect(path_helper.canonical_path("\\\\?\\C:\\CASE\\INSENSITIVE")).to eq("\\\\?\\c:\\case\\insensitive")
223
+ end
224
+ end
225
+
226
+ context "not on windows", :unix_only do
227
+ it "returns a canonical path" do
228
+ expect(path_helper.canonical_path("/etc//apache.d/sites-enabled/../sites-available/default")).to eq("/etc/apache.d/sites-available/default")
229
+ end
230
+ end
231
+ end
232
+
233
+ describe "paths_eql?" do
234
+ it "returns true if the paths are the same" do
235
+ allow(path_helper).to receive(:canonical_path).with("bandit").and_return("c:/bandit/bandit")
236
+ allow(path_helper).to receive(:canonical_path).with("../bandit/bandit").and_return("c:/bandit/bandit")
237
+ expect(path_helper.paths_eql?("bandit", "../bandit/bandit")).to be_truthy
238
+ end
239
+
240
+ it "returns false if the paths are different" do
241
+ allow(path_helper).to receive(:canonical_path).with("bandit").and_return("c:/Bo/Bandit")
242
+ allow(path_helper).to receive(:canonical_path).with("../bandit/bandit").and_return("c:/bandit/bandit")
243
+ expect(path_helper.paths_eql?("bandit", "../bandit/bandit")).to be_falsey
244
+ end
245
+ end
246
+
247
+ describe "escape_glob" do
248
+ it "escapes characters reserved by glob" do
249
+ path = "C:\\this\\*path\\[needs]\\escaping?"
250
+ escaped_path = "C:\\\\this\\\\\\*path\\\\\\[needs\\]\\\\escaping\\?"
251
+ expect(path_helper.escape_glob(path)).to eq(escaped_path)
252
+ end
253
+
254
+ context "when given more than one argument" do
255
+ it "joins, cleanpaths, and escapes characters reserved by glob" do
256
+ args = ["this/*path", "[needs]", "escaping?"]
257
+ escaped_path = if ChefConfig.windows?
258
+ "this\\\\\\*path\\\\\\[needs\\]\\\\escaping\\?"
259
+ else
260
+ "this/\\*path/\\[needs\\]/escaping\\?"
261
+ end
262
+ expect(path_helper).to receive(:join).with(*args).and_call_original
263
+ expect(path_helper).to receive(:cleanpath).and_call_original
264
+ expect(path_helper.escape_glob(*args)).to eq(escaped_path)
265
+ end
266
+ end
267
+ end
268
+
269
+ describe "escape_glob_dir" do
270
+ it "escapes characters reserved by glob without using backslashes for path separators" do
271
+ path = "C:/this/*path/[needs]/escaping?"
272
+ escaped_path = "C:/this/\\*path/\\[needs\\]/escaping\\?"
273
+ expect(path_helper.escape_glob_dir(path)).to eq(escaped_path)
274
+ end
275
+
276
+ context "when given more than one argument" do
277
+ it "joins, cleanpaths, and escapes characters reserved by glob" do
278
+ args = ["this/*path", "[needs]", "escaping?"]
279
+ escaped_path = "this/\\*path/\\[needs\\]/escaping\\?"
280
+ expect(path_helper).to receive(:join).with(*args).and_call_original
281
+ expect(path_helper.escape_glob_dir(*args)).to eq(escaped_path)
282
+ end
283
+ end
284
+ end
285
+
286
+ describe "all_homes" do
287
+ before do
288
+ stub_const("ENV", env)
289
+ allow(ChefConfig).to receive(:windows?).and_return(is_windows)
290
+ end
291
+
292
+ context "on windows" do
293
+ let (:is_windows) { true }
294
+ end
295
+
296
+ context "on unix" do
297
+ let (:is_windows) { false }
298
+
299
+ context "when HOME is not set" do
300
+ let (:env) { {} }
301
+ it "returns an empty array" do
302
+ expect(path_helper.all_homes).to eq([])
303
+ end
304
+ end
305
+ end
306
+ end
307
+ end