From ee257ff39b6483b21c2d586ca1914421c36ba0d4 Mon Sep 17 00:00:00 2001 From: Marcin Usielski Date: Mon, 27 Oct 2025 14:51:40 +0100 Subject: [PATCH 1/8] rm failure --- moler/cmd/unix/rm.py | 12 +++++++++--- test/cmd/unix/test_cmd_rm.py | 24 +++++++++++++++++++++--- 2 files changed, 30 insertions(+), 6 deletions(-) diff --git a/moler/cmd/unix/rm.py b/moler/cmd/unix/rm.py index d03fae8ac..3157a69e4 100644 --- a/moler/cmd/unix/rm.py +++ b/moler/cmd/unix/rm.py @@ -4,11 +4,12 @@ """ __author__ = 'Bartosz Odziomek, Marcin Usielski' -__copyright__ = 'Copyright (C) 2018-2023, Nokia' +__copyright__ = 'Copyright (C) 2018-2025, Nokia' __email__ = 'bartosz.odziomek@nokia.com, marcin.usielski@nokia.com' -from moler.cmd.unix.genericunix import GenericUnixCommand - +from moler.helpers import copy_list +from moler.cmd.unix.genericunix import GenericUnixCommand, cmd_failure_causes +import re class Rm(GenericUnixCommand): def __init__(self, connection, file, options=None, prompt=None, newline_chars=None, runner=None): @@ -25,6 +26,11 @@ def __init__(self, connection, file, options=None, prompt=None, newline_chars=No self.file = file self.options = options self.ret_required = False + _cmd_failure_causes = copy_list(cmd_failure_causes) + _cmd_failure_causes.append(r"cannot remove\s*'.*':\s*Permission denied") + r_cmd_failure_cause_alternatives = "|".join(_cmd_failure_causes) + self.re_fail = re.compile(r_cmd_failure_cause_alternatives, re.IGNORECASE) + def build_command_string(self): """ diff --git a/test/cmd/unix/test_cmd_rm.py b/test/cmd/unix/test_cmd_rm.py index 03b1eb119..3abd3c56d 100644 --- a/test/cmd/unix/test_cmd_rm.py +++ b/test/cmd/unix/test_cmd_rm.py @@ -3,9 +3,9 @@ Rm command module. """ -__author__ = 'Bartosz Odziomek' -__copyright__ = 'Copyright (C) 2018, Nokia' -__email__ = 'bartosz.odziomek@nokia.com' +__author__ = 'Bartosz Odziomek, Marcin Usielski' +__copyright__ = 'Copyright (C) 2018-2025, Nokia' +__email__ = 'bartosz.odziomek@nokia.com, marcin.usielski@nokia.com' def test_rm_returns_proper_command_string(buffer_connection): @@ -13,3 +13,21 @@ def test_rm_returns_proper_command_string(buffer_connection): rm_cmd = Rm(connection=buffer_connection.moler_connection, file="test.txt") assert "rm test.txt" == rm_cmd.command_string + + +def test_rm_permission_denied(buffer_connection): + from moler.cmd.unix.rm import Rm + from moler.exceptions import MolerException + output = """rm protected.txt +rm: cannot remove 'protected.txt': Permission denied + cannot remove'.*': Permission denied +moler_bash#""" + + rm_cmd = Rm(connection=buffer_connection.moler_connection, file="protected.txt") + buffer_connection.remote_inject_response([output]) + try: + rm_cmd() + except MolerException as exc: + assert "Permission denied" in str(exc) + else: + assert False, "Exception not raised for permission denied" From 39d90d972df361de58605d24d6a5c1cc008f16b6 Mon Sep 17 00:00:00 2001 From: Marcin Usielski Date: Mon, 27 Oct 2025 14:53:23 +0100 Subject: [PATCH 2/8] style --- moler/cmd/unix/rm.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/moler/cmd/unix/rm.py b/moler/cmd/unix/rm.py index 3157a69e4..af033d433 100644 --- a/moler/cmd/unix/rm.py +++ b/moler/cmd/unix/rm.py @@ -11,6 +11,7 @@ from moler.cmd.unix.genericunix import GenericUnixCommand, cmd_failure_causes import re + class Rm(GenericUnixCommand): def __init__(self, connection, file, options=None, prompt=None, newline_chars=None, runner=None): """ @@ -31,7 +32,6 @@ def __init__(self, connection, file, options=None, prompt=None, newline_chars=No r_cmd_failure_cause_alternatives = "|".join(_cmd_failure_causes) self.re_fail = re.compile(r_cmd_failure_cause_alternatives, re.IGNORECASE) - def build_command_string(self): """ Builds command string from parameters passed to object. From 12cac5e7bdb80740a0a91fd422ee658cee5b1d4e Mon Sep 17 00:00:00 2001 From: Marcin Usielski Date: Mon, 27 Oct 2025 15:26:14 +0100 Subject: [PATCH 3/8] Vesion 4.3.2 --- CHANGELOG.md | 3 +++ README.md | 2 +- setup.py | 2 +- 3 files changed, 5 insertions(+), 2 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index f2685de75..dd5fe7551 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,6 @@ +## moler 4.3.2 + * rm fails on permission denied + ## moler 4.3.1 * duplicates in ping diff --git a/README.md b/README.md index 14a8b70ef..c9b777ae8 100644 --- a/README.md +++ b/README.md @@ -1,4 +1,4 @@ -[![image](https://img.shields.io/badge/pypi-v4.3.0-blue.svg)](https://pypi.org/project/moler/) +[![image](https://img.shields.io/badge/pypi-v4.3.2-blue.svg)](https://pypi.org/project/moler/) [![image](https://img.shields.io/badge/python-3.7%20%7C%203.8%20%7C%203.9%20%7C%203.10%20%7C%203.11%20%7C%203.12%20%7C%203.13-blue.svg)](https://pypi.org/project/moler/) [![Build Status](https://github.com/nokia/moler/actions/workflows/ci.yaml/badge.svg?branch=main)](https://github.com/nokia/moler/actions) [![License](https://img.shields.io/badge/License-BSD%203--Clause-blue.svg)](./LICENSE) diff --git a/setup.py b/setup.py index a6ab78069..d0284d944 100644 --- a/setup.py +++ b/setup.py @@ -12,7 +12,7 @@ setup( name='moler', - version='4.3.1', + version='4.3.2', description='Moler is a library for working with terminals, mainly for automated tests', # Required long_description=long_description, long_description_content_type='text/markdown', From 858fedcda5d0ad033dca1761a15ee707c605aa38 Mon Sep 17 00:00:00 2001 From: Marcin Usielski Date: Tue, 28 Oct 2025 09:27:03 +0100 Subject: [PATCH 4/8] tests --- test/cmd/unix/test_cmd_sudo.py | 18 +++++++++++++++++- 1 file changed, 17 insertions(+), 1 deletion(-) diff --git a/test/cmd/unix/test_cmd_sudo.py b/test/cmd/unix/test_cmd_sudo.py index 868e13002..48ca8225b 100644 --- a/test/cmd/unix/test_cmd_sudo.py +++ b/test/cmd/unix/test_cmd_sudo.py @@ -4,7 +4,7 @@ """ __author__ = 'Marcin Usielski' -__copyright__ = 'Copyright (C) 2018-2023, Nokia' +__copyright__ = 'Copyright (C) 2018-2025, Nokia' __email__ = 'marcin.usielski@nokia.com' from moler.cmd.unix.sudo import Sudo @@ -97,6 +97,22 @@ def test_failing_calling_twice_the_same_command_object(buffer_connection, comman cmd_sudo() +def test_failing_calling_twice_the_same_command_object_failed(buffer_connection): + from moler.cmd.unix.rm import Rm + rm_output_denied = """rm important_file.txt +rm: cannot remove 'protected.txt': Permission denied +moler_bash#""" + + buffer_connection.remote_inject_response([rm_output_denied]) + + cmd_rm = Rm(connection=buffer_connection.moler_connection, file="important_file.txt") + with pytest.raises(CommandFailure): + cmd_rm() + cmd_sudo = Sudo(connection=buffer_connection.moler_connection, password="pass", cmd_object=cmd_rm) + with pytest.raises(CommandFailure) as exc: + cmd_sudo(timeout=0.3) + assert "Not allowed to run again" in str(exc.value) + def test_failing_with_timeout(buffer_connection, command_output_and_expected_result_timeout): command_output = command_output_and_expected_result_timeout buffer_connection.remote_inject_response([command_output]) From fc2c8d1623cc791262aeed4d5971112854f530d6 Mon Sep 17 00:00:00 2001 From: Marcin Usielski Date: Tue, 28 Oct 2025 09:29:02 +0100 Subject: [PATCH 5/8] --timeout --- test/cmd/unix/test_cmd_sudo.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/cmd/unix/test_cmd_sudo.py b/test/cmd/unix/test_cmd_sudo.py index 48ca8225b..689ac718a 100644 --- a/test/cmd/unix/test_cmd_sudo.py +++ b/test/cmd/unix/test_cmd_sudo.py @@ -110,7 +110,7 @@ def test_failing_calling_twice_the_same_command_object_failed(buffer_connection) cmd_rm() cmd_sudo = Sudo(connection=buffer_connection.moler_connection, password="pass", cmd_object=cmd_rm) with pytest.raises(CommandFailure) as exc: - cmd_sudo(timeout=0.3) + cmd_sudo() assert "Not allowed to run again" in str(exc.value) def test_failing_with_timeout(buffer_connection, command_output_and_expected_result_timeout): From 500381dfa2e9ca2317138feaa63a2cd8d44a8c47 Mon Sep 17 00:00:00 2001 From: Marcin Usielski Date: Tue, 28 Oct 2025 09:51:15 +0100 Subject: [PATCH 6/8] su sudo twice --- test/cmd/unix/test_cmd_su.py | 31 +++++++++++++++++++++++++++---- 1 file changed, 27 insertions(+), 4 deletions(-) diff --git a/test/cmd/unix/test_cmd_su.py b/test/cmd/unix/test_cmd_su.py index 56d95bf6f..5297ea33f 100644 --- a/test/cmd/unix/test_cmd_su.py +++ b/test/cmd/unix/test_cmd_su.py @@ -4,7 +4,7 @@ """ __author__ = 'Agnieszka Bylica, Marcin Usielski' -__copyright__ = 'Copyright (C) 2018-2023, Nokia' +__copyright__ = 'Copyright (C) 2018-2025, Nokia' __email__ = 'agnieszka.bylica@nokia.com, marcin.usielski@nokia.com' import pytest @@ -66,6 +66,29 @@ def test_sudo_su(buffer_connection): assert ret == expected_dict +def test_sudo_su_twice_failed_object(buffer_connection): + from moler.cmd.unix.sudo import Sudo + from moler.cmd.unix.rm import Rm + from moler.exceptions import CommandFailure + rm_output_denied = """rm important_file.txt +rm: cannot remove 'protected.txt': Permission denied +moler_bash#""" + + buffer_connection.remote_inject_response([rm_output_denied]) + + cmd_rm = Rm(connection=buffer_connection.moler_connection, file="important_file.txt") + with pytest.raises(CommandFailure): + cmd_rm() + + cmd_su = Su(connection=buffer_connection.moler_connection, prompt=r"moler_bash#", + cmd_object=cmd_rm) + cmd_sudo = Sudo(connection=buffer_connection.moler_connection, cmd_object=cmd_su) + with pytest.raises(CommandFailure) as exc: + cmd_sudo() + print(exc.value) + assert "Not allowed to run again" in str(exc.value) + + def test_sudo_su_object(buffer_connection, command_output_and_expected_result_ls_l): from moler.cmd.unix.sudo import Sudo from moler.cmd.unix.ls import Ls @@ -129,7 +152,7 @@ def test_su_catches_missing_binary_failure(buffer_connection): @pytest.fixture def command_output_and_expected_result_auth(): output = """xyz@debian:~/Moler$ su -Password: +Password: su: Authentication failure xyz@debian:~/Moler$""" result = dict() @@ -138,7 +161,7 @@ def command_output_and_expected_result_auth(): @pytest.fixture def command_output_and_expected_result_command_format_failure(): - output = """xyz@debian:~/Moler$ su -g + output = """xyz@debian:~/Moler$ su -g su: invalid option -- 'g' Usage: su [options] [LOGIN] @@ -201,7 +224,7 @@ def command_output_and_expected_result_ls_l(): @pytest.fixture() def command_output_and_expected_result_pwd(): output = """user@client:~/moler$ su -c 'pwd' -password: +password: /home/user/moler ute@debdev:~/moler$ """ result = { From 8e85f759952a6cbd3fbe1b30b99083b279fb64de Mon Sep 17 00:00:00 2001 From: Marcin Usielski Date: Tue, 28 Oct 2025 09:52:06 +0100 Subject: [PATCH 7/8] --print --- test/cmd/unix/test_cmd_su.py | 1 - 1 file changed, 1 deletion(-) diff --git a/test/cmd/unix/test_cmd_su.py b/test/cmd/unix/test_cmd_su.py index 5297ea33f..55f95a06c 100644 --- a/test/cmd/unix/test_cmd_su.py +++ b/test/cmd/unix/test_cmd_su.py @@ -85,7 +85,6 @@ def test_sudo_su_twice_failed_object(buffer_connection): cmd_sudo = Sudo(connection=buffer_connection.moler_connection, cmd_object=cmd_su) with pytest.raises(CommandFailure) as exc: cmd_sudo() - print(exc.value) assert "Not allowed to run again" in str(exc.value) From db28b8bdfade2f5e46b2e8e939a832b21672cbfc Mon Sep 17 00:00:00 2001 From: Marcin Usielski Date: Tue, 28 Oct 2025 10:18:52 +0100 Subject: [PATCH 8/8] test fix --- test/cmd/unix/test_cmd_su.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/cmd/unix/test_cmd_su.py b/test/cmd/unix/test_cmd_su.py index 55f95a06c..6c9978db1 100644 --- a/test/cmd/unix/test_cmd_su.py +++ b/test/cmd/unix/test_cmd_su.py @@ -71,7 +71,7 @@ def test_sudo_su_twice_failed_object(buffer_connection): from moler.cmd.unix.rm import Rm from moler.exceptions import CommandFailure rm_output_denied = """rm important_file.txt -rm: cannot remove 'protected.txt': Permission denied +rm: cannot remove 'important_file.txt': Permission denied moler_bash#""" buffer_connection.remote_inject_response([rm_output_denied])