summaryrefslogtreecommitdiff
path: root/spec/unit/util/command_line_utils/puppet_option_parser_spec.rb
blob: 676da54f3ef1647068350a79d42d3a7b4c991264 (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
require 'spec_helper'
require 'puppet/util/command_line/puppet_option_parser'

describe Puppet::Util::CommandLine::PuppetOptionParser do
  let(:option_parser) { described_class.new }

  describe "an option with a value" do
    it "parses a 'long' option with a value" do
      parses(
        :option => ["--angry", "Angry", :REQUIRED],
        :from_arguments => ["--angry", "foo"],
        :expects => "foo"
      )
    end

    it "parses a 'short' option with a value" do
      parses(
        :option => ["--angry", "-a", "Angry", :REQUIRED],
        :from_arguments => ["-a", "foo"],
        :expects => "foo"
      )
    end

    it "overrides a previous argument with a later one" do
      parses(
        :option => ["--later", "Later", :REQUIRED],
        :from_arguments => ["--later", "tomorrow", "--later", "morgen"],
        :expects => "morgen"
      )
    end
  end

  describe "an option without a value" do
    it "parses a 'long' option" do
      parses(
        :option => ["--angry", "Angry", :NONE],
        :from_arguments => ["--angry"],
        :expects => true
      )
    end

    it "parses a 'short' option" do
      parses(
        :option => ["--angry", "-a", "Angry", :NONE],
        :from_arguments => ["-a"],
        :expects => true
      )
    end

    it "supports the '--no-blah' syntax" do
      parses(
        :option => ["--[no-]rage", "Rage", :NONE],
        :from_arguments => ["--no-rage"],
        :expects => false
      )
    end

    it "overrides a previous argument with a later one" do
      parses(
        :option => ["--[no-]rage", "Rage", :NONE],
        :from_arguments => ["--rage", "--no-rage"],
        :expects => false
      )
    end
  end

  it "does not accept an unknown option specification" do
    expect {
      option_parser.on("not", "enough")
    }.to raise_error(ArgumentError, /this method only takes 3 or 4 arguments/)
  end

  it "does not modify the original argument array" do
    option_parser.on("--foo", "Foo", :NONE) { |val| }
    args = ["--foo"]

    option_parser.parse(args)

    args.length.should == 1
  end

  # The ruby stdlib OptionParser has an awesome "feature" that you cannot disable, whereby if
  #  it sees a short option that you haven't specifically registered with it (e.g., "-r"), it
  #  will automatically attempt to expand it out to whatever long options that you might have
  #  registered.  Since we need to do our option parsing in two passes (one pass against only
  #  the global/puppet-wide settings definitions, and then a second pass that includes the
  #  application or face settings--because we can't load the app/face until we've determined
  #  the libdir), it is entirely possible that we intend to define our "short" option as part
  #  of the second pass.  Therefore, if the option parser attempts to expand it out into a
  #  long option during the first pass, terrible things will happen.
  #
  # A long story short: we need to have the ability to control this kind of behavior in our
  #  option parser, and this test simply affirms that we do.
  it "does not try to expand short options that weren't explicitly registered" do

    [
     ["--ridiculous", "This is ridiculous", :REQUIRED],
     ["--rage-inducing", "This is rage-inducing", :REQUIRED]
    ].each do |option|
      option_parser.on(*option) {}
    end

    expect { option_parser.parse(["-r"]) }.to raise_error(Puppet::Util::CommandLine::PuppetOptionError)
  end

  it "respects :ignore_invalid_options" do
    option_parser.ignore_invalid_options = true
    expect { option_parser.parse(["--unknown-option"]) }.not_to raise_error
  end

  it "raises if there is an invalid option and :ignore_invalid_options is not set" do
    expect { option_parser.parse(["--unknown-option"]) }.to raise_error(Puppet::Util::CommandLine::PuppetOptionError)
  end

  def parses(option_case)
    option = option_case[:option]
    expected_value = option_case[:expects]
    arguments = option_case[:from_arguments]

    seen_value = nil
    option_parser.on(*option) do |val|
      seen_value = val
    end

    option_parser.parse(arguments)

    seen_value.should == expected_value
  end
end