summaryrefslogtreecommitdiff
path: root/spec
diff options
context:
space:
mode:
authorLamont Granquist <lamont@scriptkiddie.org>2019-06-06 15:10:43 -0700
committerLamont Granquist <lamont@scriptkiddie.org>2019-06-06 15:10:43 -0700
commit9b36f2431b3b3bd86e9801556815b150baa9f4d2 (patch)
treeac9bb613a66f66f6e0fd21bb95c6b2c1c2b83328 /spec
parent35f1d3636974838cd623c65f18b861fa2d16b777 (diff)
downloadmixlib-shellout-9b36f2431b3b3bd86e9801556815b150baa9f4d2.tar.gz
Support array args on windowslcg/win-array-args
Implements correct quoting and escaping of arguments on windows. That means that this works right now: ```ruby filename = "c:\program files" shell_out("dir", filename); ``` So all the defensive coding around quotes-around-filepaths -- which were all actually buggy even when they worked (trailing backslashes would fail) -- are unnecessary and arguments can just be passed in as an array and this code will sort it out. We rely on the existing determination of if metacharacters mean it needs to run under cmd and if it needs the ^ quoting which seems to be well tested, and which all runs after this does. Signed-off-by: Lamont Granquist <lamont@scriptkiddie.org>
Diffstat (limited to 'spec')
-rw-r--r--spec/mixlib/shellout/windows_spec.rb84
1 files changed, 84 insertions, 0 deletions
diff --git a/spec/mixlib/shellout/windows_spec.rb b/spec/mixlib/shellout/windows_spec.rb
index d4edabc..1011560 100644
--- a/spec/mixlib/shellout/windows_spec.rb
+++ b/spec/mixlib/shellout/windows_spec.rb
@@ -307,4 +307,88 @@ describe "Mixlib::ShellOut::Windows", :windows_only do
end
end
end
+
+ context "#combine_args" do
+ let(:shell_out) { Mixlib::ShellOut.new }
+ subject { shell_out.send(:combine_args, *largs) }
+
+ def self.with_args(*args, &example)
+ context "with command #{args}" do
+ let(:largs) { args }
+ it(&example)
+ end
+ end
+
+ with_args("echo", "%PATH%") do
+ is_expected.to eql(%q{echo %PATH%})
+ end
+
+ with_args("echo %PATH%") do
+ is_expected.to eql(%q{echo %PATH%})
+ end
+
+ # Note carefully for the following that single quotes in ruby support '\\' as an escape sequence for a single
+ # literal backslash. It is not mandatory to always use this since '\d' does not escape the 'd' and is literally
+ # a backlash followed by an 'd'. However, in the following all backslashes are escaped for consistency. Otherwise
+ # it becomes prohibitively confusing to track when you need and do not need the escape the backslash (particularly
+ # when the literal string has a trailing backslash such that '\\' must be used instead of '\' which would escape
+ # the intended terminating single quote or %q{\} which escapes the terminating delimiter).
+
+ with_args("child.exe", "argument1", "argument 2", '\\some\\path with\\spaces') do
+ is_expected.to eql('child.exe argument1 "argument 2" "\\some\\path with\\spaces"')
+ end
+
+ with_args("child.exe", "argument1", 'she said, "you had me at hello"', '\\some\\path with\\spaces') do
+ is_expected.to eql('child.exe argument1 "she said, \\"you had me at hello\\"" "\\some\\path with\\spaces"')
+ end
+
+ with_args("child.exe", "argument1", 'argument\\\\"2\\\\"', "argument3", "argument4") do
+ is_expected.to eql('child.exe argument1 "argument\\\\\\\\\\"2\\\\\\\\\\"" argument3 argument4')
+ end
+
+ with_args("child.exe", '\\some\\directory with\\spaces\\', "argument2") do
+ is_expected.to eql('child.exe "\\some\\directory with\\spaces\\\\" argument2')
+ end
+
+ with_args("child.exe", '\\some\\directory with\\\\\\spaces\\\\\\', "argument2") do
+ is_expected.to eql('child.exe "\\some\\directory with\\\\\\spaces\\\\\\\\\\\\" argument2')
+ end
+ end
+
+ context "#run_command" do
+ let(:shell_out) { Mixlib::ShellOut.new(*largs) }
+ subject { shell_out.send(:run_command) }
+
+ def self.with_args(*args, &example)
+ context "with command #{args}" do
+ let(:largs) { args }
+ it(&example)
+ end
+ end
+
+ with_args("echo", "FOO") do
+ is_expected.not_to be_error
+ end
+
+ # Test box is going to have to have c:\program files on it, which is perhaps brittle in principle, but
+ # I don't know enough windows to come up with a less brittle test. Fix it if you've got a better idea.
+ # The tests need to fail though if the argument is not quoted correctly so using `echo` would be poor
+ # because `echo FOO BAR` and `echo "FOO BAR"` aren't any different.
+
+ with_args('dir c:\\program files') do
+ is_expected.to be_error
+ end
+
+ with_args('dir "c:\\program files"') do
+ is_expected.not_to be_error
+ end
+
+ with_args("dir", 'c:\\program files') do
+ is_expected.not_to be_error
+ end
+
+ with_args("dir", 'c:\\program files\\') do
+ is_expected.not_to be_error
+ end
+ end
end