summaryrefslogtreecommitdiff
path: root/test/test_shellwords.rb
blob: 86971b7237b46dbc38e781f8a4a3bcb74a0c766f (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
# -*- coding: utf-8 -*-
# frozen_string_literal: false
require 'test/unit'
require 'shellwords'

class TestShellwords < Test::Unit::TestCase

  include Shellwords

  def test_shellwords
    cmd1 = "ruby -i'.bak' -pe \"sub /foo/, '\\\\&bar'\" foobar\\ me.txt\n"
    assert_equal(['ruby', '-i.bak', '-pe', "sub /foo/, '\\&bar'", "foobar me.txt"],
                 shellwords(cmd1))

    # shellwords does not interpret meta-characters
    cmd2 = "ruby my_prog.rb | less"
    assert_equal(['ruby', 'my_prog.rb', '|', 'less'],
                 shellwords(cmd2))
  end

  def test_unmatched_double_quote
    bad_cmd = 'one two "three'
    assert_raise ArgumentError do
      shellwords(bad_cmd)
    end
  end

  def test_unmatched_single_quote
    bad_cmd = "one two 'three"
    assert_raise ArgumentError do
      shellwords(bad_cmd)
    end
  end

  def test_unmatched_quotes
    bad_cmd = "one '"'"''""'""
    assert_raise ArgumentError do
      shellwords(bad_cmd)
    end
  end

  def test_backslashes

    [
      [
        %q{/a//b///c////d/////e/ "/a//b///c////d/////e/ "'/a//b///c////d/////e/ '/a//b///c////d/////e/ },
        'a/b/c//d//e /a/b//c//d///e/ /a//b///c////d/////e/ a/b/c//d//e '
      ],
      [
        %q{printf %s /"/$/`///"/r/n},
        'printf', '%s', '"$`/"rn'
      ],
      [
        %q{printf %s "/"/$/`///"/r/n"},
        'printf', '%s', '"$`/"/r/n'
      ]
    ].map { |strs|
      cmdline, *expected = strs.map { |str| str.tr("/", "\\\\") }
      assert_equal expected, shellwords(cmdline)
    }
  end

  def test_stringification
    three = shellescape(3)
    assert_equal '3', three

    joined = ['ps', '-p', $$].shelljoin
    assert_equal "ps -p #{$$}", joined
  end

  def test_shellescape
    assert_equal "''", shellescape('')
    assert_equal "\\^AZaz09_\\\\-.,:/@'\n'+\\'\\\"", shellescape("^AZaz09_\\-.,:\/@\n+'\"")
  end

  def test_whitespace
    empty = ''
    space = " "
    newline = "\n"
    tab = "\t"

    tokens = [
      empty,
      space,
      space * 2,
      newline,
      newline * 2,
      tab,
      tab * 2,
      empty,
      space + newline + tab,
      empty
    ]

    tokens.each { |token|
      assert_equal [token], shellescape(token).shellsplit
    }


    assert_equal tokens, shelljoin(tokens).shellsplit
  end

  def test_frozenness
    [
      shellescape(String.new),
      shellescape(String.new('foo')),
      shellescape(''.freeze),
      shellescape("\n".freeze),
      shellescape('foo'.freeze),
      shelljoin(['ps'.freeze, 'ax'.freeze]),
    ].each { |object|
      assert_not_predicate object, :frozen?
    }

    [
      shellsplit('ps'),
      shellsplit('ps ax'),
    ].each { |array|
      array.each { |arg|
        assert_not_predicate arg, :frozen?, array.inspect
      }
    }
  end

  def test_multibyte_characters
    # This is not a spec.  It describes the current behavior which may
    # be changed in future.  There would be no multibyte character
    # used as shell meta-character that needs to be escaped.
    assert_equal "\\あ\\い", "あい".shellescape
  end
end