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,21 @@
1
+ require_relative "base_integration_test"
2
+
3
+ include FileUtils
4
+
5
+ class TestCli < BaseIntegrationTest
6
+ test_that "optparse_plus CLI is properly documented" do
7
+ When { @stdout, _, __ = optparse_plus "--help" }
8
+ Then {
9
+ assert_banner(@stdout, "optparse_plus", takes_options: true, takes_arguments: { app_name: :required })
10
+ }
11
+ And {
12
+ assert_option(@stdout, "--force")
13
+ assert_option(@stdout, "--[no-]readme")
14
+ assert_option(@stdout, "-l", "--license")
15
+ assert_option(@stdout, "--log-level")
16
+ }
17
+ And {
18
+ assert_oneline_summary(@stdout)
19
+ }
20
+ end
21
+ end
@@ -0,0 +1,56 @@
1
+ require_relative "base_integration_test"
2
+
3
+ include FileUtils
4
+
5
+ class TestLicense < BaseIntegrationTest
6
+ test_that "omitting a license generates a warning" do
7
+ When { _, @stderr, __ = optparse_plus "newgem" }
8
+ Then {
9
+ assert_match(/warning: your app has no license/,@stderr)
10
+ }
11
+ end
12
+
13
+ test_that "explicitly omitting a license does not generate a warning" do
14
+ When { _, @stderr, __ = optparse_plus "newgem -l NONE" }
15
+ Then {
16
+ refute_match(/warning: your app has no license/,@stderr)
17
+ }
18
+ end
19
+
20
+ [
21
+ "apache",
22
+ "mit",
23
+ "gplv2",
24
+ "gplv3",
25
+ ].each do |license|
26
+ test_that "the #{license} license can be included" do
27
+ When { optparse_plus "newgem -l #{license}" }
28
+ Then {
29
+ assert File.exist?("newgem/LICENSE.txt")
30
+ }
31
+ And {
32
+ assert_file("newgem/newgem.gemspec", contains: /#{license.upcase}/)
33
+ }
34
+ end
35
+ end
36
+
37
+ test_that "a custom license can be included" do
38
+ When { optparse_plus "newgem -l custom" }
39
+ Then {
40
+ assert File.exist?("newgem/LICENSE.txt")
41
+ }
42
+ And {
43
+ assert_equal "", File.read("newgem/LICENSE.txt").strip
44
+ }
45
+ end
46
+
47
+ test_that "a non-custom non-supported license causes an error" do
48
+ When { _, @stderr, @result = optparse_plus "newgem -l foobar", allow_failure: true }
49
+ Then {
50
+ refute @result.success?
51
+ }
52
+ And {
53
+ assert_match(/invalid argument: -l foobar/,@stderr)
54
+ }
55
+ end
56
+ end
@@ -0,0 +1,53 @@
1
+ require_relative "base_integration_test"
2
+ class TestReadme < BaseIntegrationTest
3
+ test_that "a reasonable README is created" do
4
+ When {
5
+ optparse_plus "newgem --readme"
6
+ }
7
+ Then {
8
+ assert File.exist?("newgem/README.rdoc")
9
+ }
10
+ And {
11
+ readmes = Dir["newgem/README*"].to_a
12
+ assert_equal 1, readmes.size,"Found more than one README: #{readmes.inspect}"
13
+ }
14
+ And {
15
+ rakefile_contents = File.read("newgem/Rakefile")
16
+ assert_match(/README.rdoc/,rakefile_contents)
17
+ assert_match(/rd.main = ["']README.rdoc["']/,rakefile_contents)
18
+ }
19
+ And {
20
+ assert_file("newgem/README.rdoc",
21
+ contains: [
22
+ /newgem/,
23
+ /Author:: YOUR NAME \(YOUR EMAIL\)/,
24
+ /\* \{Source on Github\}\[LINK TO GITHUB\]/,
25
+ /RDoc\[LINK TO RDOC.INFO\]/,
26
+ /^== Install/,
27
+ /^== Examples/,
28
+ /^== Contributing/,
29
+ ])
30
+ }
31
+ end
32
+
33
+ test_that "a readme is created by default" do
34
+ When {
35
+ optparse_plus "newgem"
36
+ }
37
+ Then {
38
+ assert File.exist?("newgem/README.rdoc")
39
+ }
40
+ end
41
+
42
+ test_that "we can omit a README" do
43
+ When {
44
+ optparse_plus "--no-readme newgem"
45
+ }
46
+ Then {
47
+ refute File.exist?("newgem/README.rdoc")
48
+ }
49
+ And {
50
+ refute_match(/README/,File.read("newgem/Rakefile"))
51
+ }
52
+ end
53
+ end
@@ -0,0 +1,28 @@
1
+ require_relative "base_integration_test"
2
+
3
+ include FileUtils
4
+
5
+ class TestRSpec < BaseIntegrationTest
6
+ test_that "we can generate an app using RSpec instead of Test::Unit" do
7
+ When { optparse_plus "--rspec newgem" }
8
+ Then {
9
+ refute Dir.exist?("newgem/test")
10
+ assert Dir.exist?("newgem/spec")
11
+ assert File.exist?("newgem/spec/something_spec.rb")
12
+ }
13
+ And {
14
+ assert_file("newgem/newgem.gemspec", contains: /add_development_dependency\(["']rspec["']/)
15
+ }
16
+ And {
17
+ stdout,_ = rake("newgem", "-T")
18
+ assert_match(/rake spec/,stdout)
19
+ refute_match(/rake testa/,stdout)
20
+ }
21
+ When {
22
+ @stdout, _ = rake("newgem","spec")
23
+ }
24
+ Then {
25
+ assert_match(/1 example,.*0 failures/,@stdout)
26
+ }
27
+ end
28
+ end
@@ -0,0 +1,21 @@
1
+ require_relative "base_integration_test"
2
+
3
+ include FileUtils
4
+
5
+ class TestVersion < BaseIntegrationTest
6
+ test_that "--help shows the gem version" do
7
+ Given { optparse_plus "newgem" }
8
+ When { @stdout, _, = run_app "newgem", "--help" }
9
+ Then {
10
+ assert_match(/v\d+\.\d+\.\d+/, @stdout)
11
+ }
12
+ end
13
+
14
+ test_that "--version shows the gem version" do
15
+ Given { optparse_plus "newgem" }
16
+ When { @stdout, _, = run_app "newgem", "--version" }
17
+ Then {
18
+ assert_match(/v\d+\.\d+\.\d+/, @stdout)
19
+ }
20
+ end
21
+ end
@@ -0,0 +1,19 @@
1
+ if RUBY_PLATFORM == 'java'
2
+ puts "Simplecov seems to cause JRuby to barf, so use another ruby if you want to check coverage"
3
+ else
4
+ require 'simplecov'
5
+ SimpleCov.start do
6
+ add_filter "/test"
7
+ end
8
+ end
9
+
10
+ require 'test/unit'
11
+ require 'rspec/expectations'
12
+ require 'clean_test/test_case'
13
+ require 'ostruct'
14
+
15
+ RSpec::Matchers.configuration.syntax = :should
16
+
17
+ class BaseTest < Clean::Test::TestCase
18
+ include RSpec::Matchers
19
+ end
@@ -0,0 +1,7 @@
1
+ #!/bin/sh
2
+
3
+ echo "standard output"
4
+ if [ $# -gt 0 ]; then
5
+ echo "standard error" 1>&2
6
+ fi
7
+ exit $#
@@ -0,0 +1,24 @@
1
+ require 'base_test'
2
+
3
+ module ExecutionStrategy
4
+ class TestBase < BaseTest
5
+ include OptparsePlus::ExecutionStrategy
6
+
7
+ [
8
+ [:run_command,["ls"]],
9
+ [:exception_meaning_command_not_found,[]],
10
+ ].each do |(method,args)|
11
+ test_that "#{method} isn't implemented" do
12
+ Given {
13
+ @strategy = Base.new
14
+ }
15
+ When {
16
+ @code = lambda { @strategy.send(method,*args) }
17
+ }
18
+ Then {
19
+ assert_raises(RuntimeError,&@code)
20
+ }
21
+ end
22
+ end
23
+ end
24
+ end
@@ -0,0 +1,77 @@
1
+ require 'base_test'
2
+ require 'mocha/test_unit'
3
+
4
+ # Defined by JRuby, but this test must pass on any Ruby
5
+ class NativeException
6
+ end
7
+
8
+ module ExecutionStrategy
9
+ class TestJVM < BaseTest
10
+ include OptparsePlus::ExecutionStrategy
11
+
12
+ test_that "run_command proxies to Open3.capture3" do
13
+ Given {
14
+ @process = mock('java.lang.Process')
15
+ @runtime = mock('java.lang.Runtime')
16
+ @command = "ls"
17
+ @stdout = any_string
18
+ @stderr = any_string
19
+ @exitstatus = any_int :min => 1, :max => 127
20
+ }
21
+ When the_test_runs
22
+ Then {
23
+ expects_lang = mock()
24
+ JVM.any_instance.expects(:java).returns(expects_lang)
25
+ expects_Runtime = mock()
26
+ expects_lang.expects(:lang).returns(expects_Runtime)
27
+ runtime_klass = mock()
28
+ expects_Runtime.expects(:Runtime).returns(runtime_klass)
29
+ runtime_klass.expects(:get_runtime).returns(@runtime)
30
+ @runtime.expects(:exec).with(@command).returns(@process)
31
+
32
+ stdin = mock()
33
+ @process.expects(:get_output_stream).returns(stdin)
34
+ stdin.expects(:close)
35
+
36
+ stdout_input_stream = mock('InputStream')
37
+ @process.expects(:get_input_stream).returns(stdout_input_stream)
38
+ stdout_input_stream.expects(:read).times(2).returns(
39
+ @stdout,
40
+ -1)
41
+
42
+ stderr_input_stream = mock('InputStream')
43
+ @process.expects(:get_error_stream).returns(stderr_input_stream)
44
+ stderr_input_stream.expects(:read).times(2).returns(
45
+ @stderr,
46
+ -1)
47
+
48
+ @process.expects(:wait_for).returns(@exitstatus)
49
+ }
50
+
51
+ Given new_jvm_strategy
52
+ When {
53
+ @results = @strategy.run_command(@command)
54
+ }
55
+ Then {
56
+ @results[0].should be == @stdout
57
+ @results[1].should be == @stderr
58
+ @results[2].exitstatus.should be == @exitstatus
59
+ }
60
+ end
61
+
62
+ test_that "exception_meaning_command_not_found returns NativeException" do
63
+ Given new_jvm_strategy
64
+ When {
65
+ @klass = @strategy.exception_meaning_command_not_found
66
+ }
67
+ Then {
68
+ @klass.should be == NativeException
69
+ }
70
+ end
71
+
72
+ private
73
+ def new_jvm_strategy
74
+ lambda { @strategy = JVM.new }
75
+ end
76
+ end
77
+ end
@@ -0,0 +1,32 @@
1
+ require 'base_test'
2
+
3
+ module ExecutionStrategy
4
+ class TestMRI < BaseTest
5
+ include OptparsePlus::ExecutionStrategy
6
+
7
+ test_that "run_command isn't implemented" do
8
+ Given new_mri_strategy
9
+ When {
10
+ @code = lambda { @strategy.run_command("ls") }
11
+ }
12
+ Then {
13
+ assert_raises(RuntimeError,&@code)
14
+ }
15
+ end
16
+
17
+ test_that "exception_meaning_command_not_found returns Errno::ENOENT" do
18
+ Given new_mri_strategy
19
+ When {
20
+ @klass = @strategy.exception_meaning_command_not_found
21
+ }
22
+ Then {
23
+ @klass.should == Errno::ENOENT
24
+ }
25
+ end
26
+
27
+ private
28
+ def new_mri_strategy
29
+ lambda { @strategy = MRI.new }
30
+ end
31
+ end
32
+ end
@@ -0,0 +1,70 @@
1
+ require 'base_test'
2
+ require 'mocha/test_unit'
3
+ require 'open3'
4
+
5
+ module ExecutionStrategy
6
+ class TestOpen_3 < BaseTest
7
+ include OptparsePlus::ExecutionStrategy
8
+
9
+ test_that "run_command proxies to Open3.capture3" do
10
+ Given {
11
+ @command = any_string
12
+ @stdout = any_string
13
+ @stderr = any_string
14
+ @status = stub('Process::Status')
15
+ }
16
+ When the_test_runs
17
+ Then {
18
+ Open3.expects(:capture3).with(@command).returns([@stdout,@stderr,@status])
19
+ }
20
+
21
+ Given new_open_3_strategy
22
+ When {
23
+ @results = @strategy.run_command(@command)
24
+ }
25
+ Then {
26
+ @results[0].should be == @stdout
27
+ @results[1].should be == @stderr
28
+ @results[2].should be @status
29
+ }
30
+ end
31
+
32
+ test_that "run_command handles array arguments properly" do
33
+ Given {
34
+ @command = [any_string, any_string, any_string]
35
+ @stdout = any_string
36
+ @stderr = any_string
37
+ @status = stub('Process::Status')
38
+ }
39
+ When the_test_runs
40
+ Then {
41
+ Open3.expects(:capture3).with(*@command).returns([@stdout,@stderr,@status])
42
+ }
43
+
44
+ Given new_open_3_strategy
45
+ When {
46
+ @results = @strategy.run_command(@command)
47
+ }
48
+ Then {
49
+ @results[0].should be == @stdout
50
+ @results[1].should be == @stderr
51
+ @results[2].should be @status
52
+ }
53
+ end
54
+
55
+ test_that "exception_meaning_command_not_found returns Errno::ENOENT" do
56
+ Given new_open_3_strategy
57
+ When {
58
+ @klass = @strategy.exception_meaning_command_not_found
59
+ }
60
+ Then {
61
+ @klass.should be == Errno::ENOENT
62
+ }
63
+ end
64
+
65
+ private
66
+ def new_open_3_strategy
67
+ lambda { @strategy = Open_3.new }
68
+ end
69
+ end
70
+ end
@@ -0,0 +1,86 @@
1
+ require 'base_test'
2
+ require 'mocha/test_unit'
3
+
4
+ # Define this symbol without requiring the library;
5
+ # all we're goingn to do is mock calls to it
6
+ module Open4
7
+ end
8
+
9
+ module ExecutionStrategy
10
+ class TestOpen_4 < BaseTest
11
+ include OptparsePlus::ExecutionStrategy
12
+
13
+ test_that "run_command proxies to Open4.capture4" do
14
+ Given {
15
+ @command = any_string
16
+ @stdin_io = mock("IO")
17
+ @stdout = any_string
18
+ @stdout_io = StringIO.new(@stdout)
19
+ @stderr = any_string
20
+ @stderr_io = StringIO.new(@stderr)
21
+ @pid = any_int :min => 2, :max => 65536
22
+ @status = stub('Process::Status')
23
+ }
24
+ When the_test_runs
25
+ Then {
26
+ Open4.expects(:popen4).with(@command).returns([@pid,@stdin_io,@stdout_io,@stderr_io])
27
+ @stdin_io.expects(:close)
28
+ Process.expects(:waitpid2).with(@pid).returns([any_string,@status])
29
+ }
30
+
31
+ Given new_open_4_strategy
32
+ When {
33
+ @results = @strategy.run_command(@command)
34
+ }
35
+ Then {
36
+ @results[0].should be == @stdout
37
+ @results[1].should be == @stderr
38
+ @results[2].should be @status
39
+ }
40
+ end
41
+
42
+ test_that "run_command handles array arguments properly" do
43
+ Given {
44
+ @command = [any_string, any_string, any_string]
45
+ @stdin_io = mock("IO")
46
+ @stdout = any_string
47
+ @stdout_io = StringIO.new(@stdout)
48
+ @stderr = any_string
49
+ @stderr_io = StringIO.new(@stderr)
50
+ @pid = any_int :min => 2, :max => 65536
51
+ @status = stub('Process::Status')
52
+ }
53
+ When the_test_runs
54
+ Then {
55
+ Open4.expects(:popen4).with(*@command).returns([@pid,@stdin_io,@stdout_io,@stderr_io])
56
+ @stdin_io.expects(:close)
57
+ Process.expects(:waitpid2).with(@pid).returns([any_string,@status])
58
+ }
59
+
60
+ Given new_open_4_strategy
61
+ When {
62
+ @results = @strategy.run_command(@command)
63
+ }
64
+ Then {
65
+ @results[0].should be == @stdout
66
+ @results[1].should be == @stderr
67
+ @results[2].should be @status
68
+ }
69
+ end
70
+
71
+ test_that "exception_meaning_command_not_found returns Errno::ENOENT" do
72
+ Given new_open_4_strategy
73
+ When {
74
+ @klass = @strategy.exception_meaning_command_not_found
75
+ }
76
+ Then {
77
+ @klass.should be == Errno::ENOENT
78
+ }
79
+ end
80
+
81
+ private
82
+ def new_open_4_strategy
83
+ lambda { @strategy = Open_4.new }
84
+ end
85
+ end
86
+ end