Skip to content

Commit 2fe959e

Browse files
committed
Add some tests to test_cmd2.py to increase code coverage in cmd2.py
1 parent d68032e commit 2fe959e

File tree

1 file changed

+97
-0
lines changed

1 file changed

+97
-0
lines changed

tests/test_cmd2.py

Lines changed: 97 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3244,3 +3244,100 @@ class SynonymApp(cmd2.cmd2.Cmd):
32443244

32453245
assert synonym_parser is not None
32463246
assert synonym_parser is help_parser
3247+
3248+
3249+
def test_custom_completekey():
3250+
# Test setting a custom completekey
3251+
app = cmd2.Cmd(completekey='?')
3252+
assert app.completekey == '?'
3253+
3254+
3255+
def test_prompt_session_init_exception(monkeypatch):
3256+
from prompt_toolkit.shortcuts import PromptSession
3257+
3258+
# Mock PromptSession to raise ValueError on first call, then succeed
3259+
valid_session_mock = mock.MagicMock(spec=PromptSession)
3260+
mock_session = mock.MagicMock(side_effect=[ValueError, valid_session_mock])
3261+
monkeypatch.setattr("cmd2.cmd2.PromptSession", mock_session)
3262+
3263+
cmd2.Cmd()
3264+
# Check that fallback to DummyInput/Output happened
3265+
from prompt_toolkit.input import DummyInput
3266+
from prompt_toolkit.output import DummyOutput
3267+
3268+
assert mock_session.call_count == 2
3269+
# Check args of second call
3270+
call_args = mock_session.call_args_list[1]
3271+
kwargs = call_args[1]
3272+
assert isinstance(kwargs['input'], DummyInput)
3273+
assert isinstance(kwargs['output'], DummyOutput)
3274+
3275+
3276+
def test_pager_on_windows(monkeypatch):
3277+
monkeypatch.setattr("sys.platform", "win32")
3278+
app = cmd2.Cmd()
3279+
assert app.pager == 'more'
3280+
assert app.pager_chop == 'more'
3281+
3282+
3283+
def test_path_complete_users_windows(monkeypatch, base_app):
3284+
monkeypatch.setattr("sys.platform", "win32")
3285+
3286+
# Mock os.path.expanduser and isdir
3287+
monkeypatch.setattr("os.path.expanduser", lambda p: '/home/user' if p == '~user' else p)
3288+
monkeypatch.setattr("os.path.isdir", lambda p: p == '/home/user')
3289+
3290+
matches = base_app.path_complete('~user', 'cmd ~user', 0, 9)
3291+
# Should contain ~user/ (or ~user\ depending on sep)
3292+
# Since we didn't mock os.path.sep, it will use system separator.
3293+
expected = '~user' + os.path.sep
3294+
assert expected in matches
3295+
3296+
3297+
def test_async_alert_success(base_app):
3298+
import threading
3299+
3300+
success = []
3301+
3302+
def run_alert():
3303+
base_app.async_alert("Alert Message", new_prompt="(New) ")
3304+
success.append(True)
3305+
3306+
t = threading.Thread(target=run_alert)
3307+
t.start()
3308+
t.join()
3309+
3310+
assert success
3311+
assert base_app.prompt == "(New) "
3312+
3313+
3314+
def test_async_alert_main_thread_error(base_app):
3315+
with pytest.raises(RuntimeError, match="main thread"):
3316+
base_app.async_alert("fail")
3317+
3318+
3319+
def test_async_alert_lock_held(base_app):
3320+
import threading
3321+
3322+
# Acquire lock in main thread
3323+
base_app.terminal_lock.acquire()
3324+
3325+
exceptions = []
3326+
3327+
def run_alert():
3328+
try:
3329+
base_app.async_alert("fail")
3330+
except RuntimeError as e:
3331+
exceptions.append(e)
3332+
finally:
3333+
pass
3334+
3335+
try:
3336+
t = threading.Thread(target=run_alert)
3337+
t.start()
3338+
t.join()
3339+
finally:
3340+
base_app.terminal_lock.release()
3341+
3342+
assert len(exceptions) == 1
3343+
assert "another thread holds terminal_lock" in str(exceptions[0])

0 commit comments

Comments
 (0)