require File.dirname(__FILE__) + '/../lib/cmd' require 'test/unit' require 'stringio' class TCmdException < StandardError end class CustomException < StandardError end class AnotherCustomException < StandardError end class Cmd def in @stdin end def out @stdout end end class TCmdBasic < Cmd end class TCmdWithCommands < Cmd prompt_with ENV['USER'] handle CustomException, :handle_custom_exception handle AnotherCustomException, 'Handled another custom exception' handle ZeroDivisionError, 'Division by zero' def do_exit_violently raise TCmdException end def do_trigger_custom_exception raise CustomException end def do_trigger_another_custom_exception raise AnotherCustomException end def do_trigger_zero_division_error 1 / 0 end def do_simple write 'Ran simple command' end def do_shell_type end protected def handle_custom_exception write 'Handled custom exception' end def handle_exception(exception) write 'Exception was raised' end def empty_line write 'Empty line was entered' end end class TCmdLifecycle < Cmd def methods_ran (@methods_ran ||= []).sort! @methods_ran end protected def setup; methods_ran << 'setup' end def preloop; methods_ran << 'preloop' end def postloop; methods_ran << 'postloop' end def precmd(line) methods_ran << 'precmd' line end def postcmd(line) methods_ran << 'postcmd' line end end class TC_Cmd < Test::Unit::TestCase def setup @basic = setup_mock_cmd(TCmdBasic) @cmd = setup_mock_cmd(TCmdWithCommands) @lifecycle = setup_mock_cmd(TCmdLifecycle) end def test_simple_command run_command 'simple' assert_stdout_equal "Ran simple command\n" end def test_custom_exception run_command 'trigger_custom_exception' assert_stdout_equal "Handled custom exception\n" end def test_another_custom_exception run_command 'trigger_another_custom_exception' assert_stdout_equal "Handled another custom exception\n" end def test_zero_division_error run_command 'trigger_zero_division_error' assert_stdout_equal "Division by zero\n" end def test_prompt assert_equal ENV['USER'], @cmd.send(:prompt) end def test_abbrev_command_lookup run_command 'si' assert_stdout_equal "Ran simple command\n" end def test_abbrev_command_ambiguous_lookup run_command 's' assert_stdout_equal "No such command 's'\n" end def test_empty_line run_command ' ' assert_stdout_equal "Empty line was entered\n" end def test_lifecycle_callbacks run_command 'exit', @lifecycle assert_equal %w(postcmd postloop precmd preloop setup), @lifecycle.methods_ran end def test_command_list assert_equal %w(exit help shell), @basic.send(:command_list).sort end def test_subcommand_list assert_equal %w(exit_violently shell_type), @cmd.send(:subcommand_list).sort end def test_complete assert_equal %w(exit help shell), @basic.send(:complete, '').sort assert_equal %w(help), @basic.send(:complete, 'h') assert_equal [], @basic.send(:complete, 'asdf') end def test_has_subcommands? assert ! @cmd.send(:has_subcommands?, 'help') assert ! @basic.send(:has_subcommands?, 'help') assert @cmd.send(:has_subcommands?, 'exit') assert @cmd.send(:has_subcommands?, '!') end def test_subcommand_lookup assert_equal [], @basic.send(:subcommands, 'help') assert_equal %w(exit_violently), @cmd.send(:subcommands, 'exit') assert_equal %w(shell_type), @cmd.send(:subcommands, '!') end def test_documented_commands_list assert_equal %w(exit help shell), @basic.send(:documented_commands).sort end def test_handle_exception run_command 'exit violently' assert_stdout_equal "Exception was raised\n" end def test_undocummented_commands_list assert ! @basic.send(:undocumented_commands?) assert_equal [], @basic.send(:undocumented_commands) end def test_translate_shortcut assert_equal 'help', @basic.send(:translate_shortcut, 'help') assert_equal 'help', @basic.send(:translate_shortcut, '?') end def test_has_shortcuts? assert @cmd.send(:has_shortcuts?, 'help') assert !@cmd.send(:has_shortcuts?, 'exit') end def test_command_shortcuts assert_equal ['?'], @basic.send(:command_shortcuts, 'help') end def test_find_subcommand_in_args assert_equal 'help_me', @basic.send(:find_subcommand_in_args, %w(help_you help_me help_him), %w(help me help you)) assert_equal 'help_me', @basic.send(:find_subcommand_in_args, %w(help_you help_me help_him), %w(help me)) assert_equal nil, @basic.send(:find_subcommand_in_args, %w(help_you help_me help_him), %w(help her)) end def test_command_missing run_command '??' assert_stdout_equal "No such command '??'\n" end def test_no_help run_command '? flarp' assert_stdout_equal "No help for command 'flarp'\n" end def test_current_command run_command 'help' assert_equal 'help', @cmd.send(:current_command) end def test_current_command_with_shortcut run_command '?' assert_equal 'help', @cmd.send(:current_command) end def test_help_on_single_command @basic.send(:execute_line, '? ?') actual = @basic.out.string @basic.out.rewind @basic.send(:print_help, 'help') expected = @basic.out.string assert_equal expected, actual @basic.send(:execute_line, 'help not-a-command') actual = @basic.out.string @basic.out.rewind @basic.send(:no_help, 'not-a-command') expected = @basic.out.string assert_equal expected, actual end def test_parse_line assert_equal ['help', nil], @basic.send(:parse_line, 'help') assert_equal ['help', nil], @basic.send(:parse_line, 'help ') assert_equal ['help', 'shell'], @basic.send(:parse_line, 'help shell') assert_equal ['shell_type', nil], @cmd.send(:parse_line, 'shell type') assert_equal ['shell_type', 'zsh'], @cmd.send(:parse_line, 'shell type zsh') end protected def run_command(line, obj = @cmd) obj.in << line obj.in.rewind obj.run obj.out.pos = obj.send(:prompt).size end def assert_stdout_equal(line, obj = @cmd) assert_equal line, obj.out.read end def setup_mock_cmd(klass) obj = klass.new obj.stdin = StringIO.new obj.stdout = StringIO.new obj.send :stoploop obj.turn_off_readline obj end end