optparse-plus 3.0.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (69) hide show
  1. checksums.yaml +7 -0
  2. data/.gitignore +17 -0
  3. data/.ruby-gemset +1 -0
  4. data/.ruby-version +1 -0
  5. data/.travis.yml +7 -0
  6. data/CHANGES.md +66 -0
  7. data/Gemfile +5 -0
  8. data/LICENSE.txt +201 -0
  9. data/README.rdoc +173 -0
  10. data/Rakefile +94 -0
  11. data/bin/optparse_plus +130 -0
  12. data/fix.rb +29 -0
  13. data/lib/optparse-plus.rb +1 -0
  14. data/lib/optparse_plus.rb +15 -0
  15. data/lib/optparse_plus/argv_parser.rb +50 -0
  16. data/lib/optparse_plus/cli.rb +116 -0
  17. data/lib/optparse_plus/cli_logger.rb +133 -0
  18. data/lib/optparse_plus/cli_logging.rb +138 -0
  19. data/lib/optparse_plus/cucumber.rb +119 -0
  20. data/lib/optparse_plus/error.rb +32 -0
  21. data/lib/optparse_plus/execution_strategy/base.rb +34 -0
  22. data/lib/optparse_plus/execution_strategy/jvm.rb +37 -0
  23. data/lib/optparse_plus/execution_strategy/mri.rb +16 -0
  24. data/lib/optparse_plus/execution_strategy/open_3.rb +16 -0
  25. data/lib/optparse_plus/execution_strategy/open_4.rb +22 -0
  26. data/lib/optparse_plus/execution_strategy/rbx_open_4.rb +12 -0
  27. data/lib/optparse_plus/exit_now.rb +40 -0
  28. data/lib/optparse_plus/main.rb +603 -0
  29. data/lib/optparse_plus/process_status.rb +45 -0
  30. data/lib/optparse_plus/sh.rb +223 -0
  31. data/lib/optparse_plus/test/base_integration_test.rb +31 -0
  32. data/lib/optparse_plus/test/integration_test_assertions.rb +65 -0
  33. data/lib/optparse_plus/version.rb +3 -0
  34. data/optparse_plus.gemspec +28 -0
  35. data/templates/full/.gitignore.erb +4 -0
  36. data/templates/full/README.rdoc.erb +24 -0
  37. data/templates/full/Rakefile.erb +71 -0
  38. data/templates/full/_license_head.txt.erb +2 -0
  39. data/templates/full/apache_LICENSE.txt.erb +203 -0
  40. data/templates/full/bin/executable.erb +45 -0
  41. data/templates/full/custom_LICENSE.txt.erb +0 -0
  42. data/templates/full/gplv2_LICENSE.txt.erb +14 -0
  43. data/templates/full/gplv3_LICENSE.txt.erb +14 -0
  44. data/templates/full/mit_LICENSE.txt.erb +7 -0
  45. data/templates/rspec/spec/something_spec.rb.erb +5 -0
  46. data/templates/test_unit/test/integration/test_cli.rb.erb +11 -0
  47. data/templates/test_unit/test/unit/test_something.rb.erb +7 -0
  48. data/test/integration/base_integration_test.rb +60 -0
  49. data/test/integration/test_bootstrap.rb +150 -0
  50. data/test/integration/test_cli.rb +21 -0
  51. data/test/integration/test_license.rb +56 -0
  52. data/test/integration/test_readme.rb +53 -0
  53. data/test/integration/test_rspec.rb +28 -0
  54. data/test/integration/test_version.rb +21 -0
  55. data/test/unit/base_test.rb +19 -0
  56. data/test/unit/command_for_tests.sh +7 -0
  57. data/test/unit/execution_strategy/test_base.rb +24 -0
  58. data/test/unit/execution_strategy/test_jvm.rb +77 -0
  59. data/test/unit/execution_strategy/test_mri.rb +32 -0
  60. data/test/unit/execution_strategy/test_open_3.rb +70 -0
  61. data/test/unit/execution_strategy/test_open_4.rb +86 -0
  62. data/test/unit/execution_strategy/test_rbx_open_4.rb +25 -0
  63. data/test/unit/test/test_integration_test_assertions.rb +211 -0
  64. data/test/unit/test_cli_logger.rb +219 -0
  65. data/test/unit/test_cli_logging.rb +243 -0
  66. data/test/unit/test_exit_now.rb +37 -0
  67. data/test/unit/test_main.rb +840 -0
  68. data/test/unit/test_sh.rb +404 -0
  69. metadata +260 -0
@@ -0,0 +1,25 @@
1
+ require 'base_test'
2
+ require 'mocha/test_unit'
3
+
4
+ # Define this symbol without requiring the library;
5
+ # all we're going to do is mock calls to it
6
+ module Open4
7
+ end
8
+
9
+ module ExecutionStrategy
10
+ class TestRBXOpen_4 < BaseTest
11
+ include OptparsePlus::ExecutionStrategy
12
+
13
+ test_that "exception_meaning_command_not_found returns Errno::EINVAL" do
14
+ Given {
15
+ @strategy = RBXOpen_4.new
16
+ }
17
+ When {
18
+ @klass = @strategy.exception_meaning_command_not_found
19
+ }
20
+ Then {
21
+ @klass.should == [Errno::EINVAL,Errno::ENOENT]
22
+ }
23
+ end
24
+ end
25
+ end
@@ -0,0 +1,211 @@
1
+ require 'base_test'
2
+ require 'optparse_plus'
3
+ require 'optparse_plus/test/integration_test_assertions'
4
+ require 'fileutils'
5
+ require 'tmpdir'
6
+
7
+ class TestIntegrationTestAssertions < BaseTest
8
+ include OptparsePlus::IntegrationTestAssertions
9
+ include FileUtils
10
+
11
+ def setup
12
+ @pwd = pwd
13
+ @tmpdir = Dir.mktmpdir
14
+ chdir @tmpdir
15
+ end
16
+
17
+ def teardown
18
+ chdir @pwd
19
+ rm_rf @tmpdir
20
+ end
21
+
22
+ test_that "assert_file works with one regexp" do
23
+ Given { some_file }
24
+ When {
25
+ @code = ->() { assert_file("some_file.txt", contains: /foo/) }
26
+ }
27
+ Then { refute_raises(&@code) }
28
+ end
29
+
30
+ test_that "assert_file works with many regexps" do
31
+ Given { some_file }
32
+ When {
33
+ @code = ->() { assert_file("some_file.txt", contains: [ /foo/, /bar/ ]) }
34
+ }
35
+ Then { refute_raises(&@code) }
36
+ end
37
+
38
+ test_that "assert_file fails if any regexp fails to match" do
39
+ Given { some_file }
40
+ When {
41
+ @code = ->() { assert_file("some_file.txt", contains: [ /foo/, /baz/ ]) }
42
+ }
43
+ Then { assert_raises(&@code) }
44
+ end
45
+
46
+ test_that "assert_banner without takes_options passes for a banner with the bin name and no '[options]'" do
47
+ Given {
48
+ @bin_name = "foobar"
49
+ @stdout = "Usage: foobar"
50
+ }
51
+ When {
52
+ @code = ->() { assert_banner(@stdout,@bin_name,takes_options: false) }
53
+ }
54
+ Then { refute_raises(&@code) }
55
+ end
56
+
57
+ test_that "assert_banner without takes_options fails for a banner with the bin name and '[options]'" do
58
+ Given {
59
+ @bin_name = "foobar"
60
+ @stdout = "Usage: foobar [options]"
61
+ }
62
+ When {
63
+ @code = ->() { assert_banner(@stdout,@bin_name,takes_options: false) }
64
+ }
65
+ Then { assert_raises(&@code) }
66
+ end
67
+
68
+ test_that "assert_banner with takes_options passes for a banner with the bin name and '[options]'" do
69
+ Given {
70
+ @bin_name = "foobar"
71
+ @stdout = "Usage: foobar [options]\nOptions\n --help"
72
+ }
73
+ When {
74
+ @code = ->() { assert_banner(@stdout,@bin_name,takes_options: true) }
75
+ }
76
+ Then { refute_raises(&@code) }
77
+ end
78
+
79
+ test_that "assert_banner with takes_options fails for a banner with the bin name but no '[options]'" do
80
+ Given {
81
+ @bin_name = "foobar"
82
+ @stdout = "Usage: foobar\nOptions\n --help"
83
+ }
84
+ When {
85
+ @code = ->() { assert_banner(@stdout,@bin_name,takes_options: true) }
86
+ }
87
+ Then { assert_raises(&@code) }
88
+ end
89
+
90
+ test_that "assert_banner with takes_options and takes_arguments passes for a banner with the bin name, '[options]' and the arg list" do
91
+ Given {
92
+ @bin_name = "foobar"
93
+ @stdout = "Usage: foobar [options] some_arg [some_other_arg]\nOptions\n --help"
94
+ }
95
+ When {
96
+ @code = ->() {
97
+ assert_banner(@stdout,
98
+ @bin_name,
99
+ takes_options: true,
100
+ takes_arguments: { some_arg: :required, some_other_arg: :optional }
101
+ )
102
+ }
103
+ }
104
+ Then { refute_raises(&@code) }
105
+ end
106
+
107
+ test_that "assert_banner with takes_options and takes_arguments failes for a banner with the bin name, '[options]' and no arg list" do
108
+ Given {
109
+ @bin_name = "foobar"
110
+ @stdout = "Usage: foobar [options]\nOptions\n --help"
111
+ }
112
+ When {
113
+ @code = ->() {
114
+ assert_banner(@stdout,
115
+ @bin_name,
116
+ takes_options: true,
117
+ takes_arguments: { some_arg: :required, some_other_arg: :optional }
118
+ )
119
+ }
120
+ }
121
+ Then { assert_raises(&@code) }
122
+ end
123
+
124
+ test_that "assert_options with one option passes when stdout contains that option" do
125
+ Given { @stdout = some_options }
126
+ When { @code = ->() { assert_option(@stdout,"--help") } }
127
+ Then { refute_raises(&@code) }
128
+ end
129
+
130
+ test_that "assert_options with many option passes when stdout contains that option" do
131
+ Given { @stdout = some_options }
132
+ When { @code = ->() { assert_option(@stdout,"-h", "--help") } }
133
+ Then { refute_raises(&@code) }
134
+ end
135
+
136
+ test_that "assert_options fails when stdout does not the option" do
137
+ Given { @stdout = some_options }
138
+ When { @code = ->() { assert_option(@stdout,"--bleorg") } }
139
+ Then { assert_raises(&@code) }
140
+ end
141
+
142
+ test_that "assert_oneline_summary passes when the stdout has at least three lines, the second of which is blank and the third of which has some words in it" do
143
+ Given {
144
+ @stdout = [
145
+ "Usage: foobar",
146
+ "",
147
+ "The awesome app of awesome",
148
+ ].join("\n")
149
+ }
150
+ When { @code = ->() { assert_oneline_summary(@stdout) } }
151
+ Then { refute_raises(&@code) }
152
+ end
153
+
154
+ test_that "assert_oneline_summary fails when the stdout has at least three lines, the second of which is blank and the third of which has only one word in it" do
155
+ Given {
156
+ @stdout = [
157
+ "Usage: foobar",
158
+ "",
159
+ "awesome",
160
+ ].join("\n")
161
+ }
162
+ When { @code = ->() { assert_oneline_summary(@stdout) } }
163
+ Then { assert_raises(&@code) }
164
+ end
165
+
166
+ test_that "assert_oneline_summary fails when the stdout has at least three lines, the second of which is not blank and the third of which has words in it" do
167
+ Given {
168
+ @stdout = [
169
+ "Usage: foobar",
170
+ "foo",
171
+ "awesome app of awesome",
172
+ ].join("\n")
173
+ }
174
+ When { @code = ->() { assert_oneline_summary(@stdout) } }
175
+ Then { assert_raises(&@code) }
176
+ end
177
+
178
+ test_that "assert_oneline_summary fails when the stdout has less than three lines" do
179
+ Given {
180
+ @stdout = [
181
+ "Usage: foobar",
182
+ "awesome app of awesome",
183
+ ].join("\n")
184
+ }
185
+ When { @code = ->() { assert_oneline_summary(@stdout) } }
186
+ Then { assert_raises(&@code) }
187
+ end
188
+
189
+ private
190
+
191
+ def some_options
192
+ [
193
+ "-h, --help Get Help",
194
+ "--version Show the version",
195
+ "--[no-]output Print output",
196
+ ].join("\n")
197
+ end
198
+
199
+ def refute_raises(&block)
200
+ block.()
201
+ rescue Exception => ex
202
+ assert false, "Expected block NOT to raise, but got a #{ex.class}/#{ex.message}"
203
+ end
204
+
205
+ def some_file
206
+ File.open("some_file.txt","w") do |file|
207
+ file.puts "foo"
208
+ file.puts "bar"
209
+ end
210
+ end
211
+ end
@@ -0,0 +1,219 @@
1
+ require 'base_test'
2
+ require 'optparse_plus'
3
+ require 'stringio'
4
+ require 'tempfile'
5
+
6
+ class TestCLILogger < BaseTest
7
+ include OptparsePlus
8
+
9
+ def setup
10
+ @blank_format = proc { |severity,datetime,progname,msg|
11
+ msg + "\n"
12
+ }
13
+ @real_stderr = $stderr
14
+ @real_stdout = $stdout
15
+ $stderr = StringIO.new
16
+ $stdout = StringIO.new
17
+ end
18
+
19
+ def teardown
20
+ $stderr = @real_stderr
21
+ $stdout = @real_stdout
22
+ end
23
+
24
+ test_that "when both stderr and stdin are ttys, split the log messages between them and don't format" do
25
+ Given {
26
+ class << $stderr
27
+ def tty?; true; end
28
+ end
29
+ class << $stdout
30
+ def tty?; true; end
31
+ end
32
+
33
+ @logger = CLILogger.new
34
+ @logger.level = Logger::DEBUG
35
+ }
36
+
37
+ When log_all_levels
38
+
39
+ Then {
40
+ $stdout.string.should be == "debug\ninfo\n"
41
+ $stderr.string.should be == "warn\nerror\nfatal\n"
42
+ }
43
+ end
44
+
45
+ test_that "when both stderr and stdin are ttys, setting the level higher than WARN should affect the error logger" do
46
+ Given {
47
+ class << $stderr
48
+ def tty?; true; end
49
+ end
50
+ class << $stdout
51
+ def tty?; true; end
52
+ end
53
+
54
+ @logger = CLILogger.new
55
+ @logger.level = Logger::ERROR
56
+ }
57
+
58
+ When log_all_levels
59
+
60
+ Then {
61
+ $stdout.string.should be == ""
62
+ $stderr.string.should be == "error\nfatal\n"
63
+ }
64
+ end
65
+
66
+ test_that "logger sends debug and info to stdout, and warns, errors, and fatals to stderr" do
67
+ Given a_logger_with_blank_format
68
+ When log_all_levels
69
+
70
+ Then stdout_should_have_everything
71
+ And {
72
+ $stderr.string.should be == "warn\nerror\nfatal\n"
73
+ }
74
+ end
75
+
76
+ test_that "we can control what goes to stderr" do
77
+ Given a_logger_with_blank_format :at_error_level => Logger::Severity::FATAL
78
+
79
+ When log_all_levels
80
+
81
+ Then stdout_should_have_everything
82
+ And {
83
+ $stderr.string.should be == "fatal\n"
84
+ }
85
+ end
86
+
87
+ test_that "we can log to alternate devices easily" do
88
+ Given {
89
+ @out = StringIO.new
90
+ @err = StringIO.new
91
+
92
+ @logger = CLILogger.new(@out,@err)
93
+ @logger.level = Logger::DEBUG
94
+ @logger.formatter = @blank_format
95
+ }
96
+
97
+ When log_all_levels
98
+
99
+ Then {
100
+ @out.string.should be == "debug\ninfo\nwarn\nerror\nfatal\n"
101
+ @err.string.should be == "warn\nerror\nfatal\n"
102
+ }
103
+ end
104
+
105
+
106
+ test_that "error logger ignores the log level" do
107
+ Given a_logger_with_blank_format :at_level => Logger::Severity::FATAL
108
+ When log_all_levels
109
+
110
+ Then {
111
+ $stdout.string.should be == "fatal\n"
112
+ $stderr.string.should be == "warn\nerror\nfatal\n"
113
+ }
114
+ end
115
+
116
+ test_that "both loggers use the same date format" do
117
+ Given {
118
+ @logger = CLILogger.new
119
+ @logger.level = Logger::DEBUG
120
+ @logger.datetime_format = "the time"
121
+ }
122
+
123
+ When {
124
+ @logger.debug("debug")
125
+ @logger.error("error")
126
+ }
127
+
128
+ Then {
129
+ $stdout.string.should match(/the time.*DEBUG.*debug/)
130
+ $stderr.string.should match(/the time.*ERROR.*error/)
131
+ }
132
+ end
133
+
134
+ test_that "error logger does not get <<" do
135
+ Given a_logger_with_blank_format
136
+ When {
137
+ @logger << "foo"
138
+ }
139
+ Then {
140
+ $stdout.string.should be == "foo"
141
+ $stderr.string.should be == ""
142
+ }
143
+ end
144
+
145
+ test_that "error logger can have a different format" do
146
+ Given {
147
+ @logger = logger_with_blank_format
148
+ @logger.error_formatter = proc do |severity,datetime,progname,msg|
149
+ "ERROR_LOGGER: #{msg}\n"
150
+ end
151
+ }
152
+ When {
153
+ @logger.debug("debug")
154
+ @logger.error("error")
155
+ }
156
+ Then {
157
+ $stdout.string.should be == "debug\nerror\n"
158
+ $stderr.string.should be == "ERROR_LOGGER: error\n"
159
+ }
160
+ end
161
+
162
+ test_that "we can use filenames as log devices" do
163
+ Given {
164
+ tempfile = Tempfile.new("stderr_log")
165
+ @stdout_file = tempfile.path
166
+ tempfile.close
167
+
168
+ tempfile = Tempfile.new("stdout_log")
169
+ @stderr_file = tempfile.path
170
+ tempfile.close
171
+ }
172
+ When {
173
+ @logger = CLILogger.new(@stdout_file,@stderr_file)
174
+ @logger.info("some info")
175
+ @logger.error("some error")
176
+ }
177
+ Then {
178
+ File.read(@stdout_file).should =~ /some info/
179
+ File.read(@stderr_file).should =~ /some error/
180
+ }
181
+ end
182
+
183
+ private
184
+
185
+ def log_all_levels
186
+ proc do
187
+ @logger.debug("debug")
188
+ @logger.info("info")
189
+ @logger.warn("warn")
190
+ @logger.error("error")
191
+ @logger.fatal("fatal")
192
+ end
193
+ end
194
+
195
+
196
+ def logger_with_blank_format
197
+ logger = CLILogger.new
198
+ logger.formatter = @blank_format
199
+ logger.level = Logger::Severity::DEBUG
200
+ logger
201
+ end
202
+
203
+ # options - :at_level - level to set the logger
204
+ def a_logger_with_blank_format(options = {})
205
+ proc do
206
+ @logger = logger_with_blank_format
207
+ @logger.level = options[:at_level] if options[:at_level]
208
+ @logger.error_level = options[:at_error_level] if options[:at_error_level]
209
+ end
210
+ end
211
+
212
+ def stdout_should_have_everything
213
+ proc do
214
+ $stdout.string.should be == "debug\ninfo\nwarn\nerror\nfatal\n"
215
+ end
216
+ end
217
+
218
+
219
+ end