mirror of
https://github.com/freedombox/FreedomBox.git
synced 2026-01-28 08:03:36 +00:00
Tests: - All tests in patch series have been done with this patch applied - Unit tests pass Signed-off-by: Sunil Mohan Adapa <sunil@medhas.org> Reviewed-by: James Valleroy <jvalleroy@mailbox.org>
143 lines
4.0 KiB
Python
143 lines
4.0 KiB
Python
# SPDX-License-Identifier: AGPL-3.0-or-later
|
|
"""
|
|
Test module for actions utilities that modify configuration.
|
|
|
|
Verify that privileged actions perform as expected. See actions.py for a full
|
|
description of the expectations.
|
|
|
|
"""
|
|
|
|
import json
|
|
import os
|
|
import subprocess
|
|
from unittest.mock import Mock, call, patch
|
|
|
|
import pytest
|
|
|
|
from plinth import cfg
|
|
from plinth.actions import privileged
|
|
|
|
|
|
@pytest.fixture(name='popen')
|
|
def fixture_popen():
|
|
"""A fixture to patch subprocess.Popen called by privileged action."""
|
|
|
|
with patch('subprocess.Popen') as popen:
|
|
|
|
def call_popen(command, **kwargs):
|
|
write_fd = int(command[8])
|
|
if not isinstance(popen.called_with_write_fd, list):
|
|
popen.called_with_write_fd = []
|
|
|
|
popen.called_with_write_fd.append(write_fd)
|
|
os.write(write_fd, bytes(popen.return_value, encoding='utf-8'))
|
|
proc = Mock()
|
|
proc.communicate.return_value = ('', '')
|
|
proc.returncode = 0
|
|
return proc
|
|
|
|
popen.side_effect = call_popen
|
|
yield popen
|
|
|
|
|
|
def test_privileged_properties():
|
|
"""Test that privileged decorator sets proper properties on the method."""
|
|
|
|
def func():
|
|
return
|
|
|
|
wrapped_func = privileged(func)
|
|
assert wrapped_func._privileged
|
|
assert wrapped_func.__wrapped__ == func
|
|
|
|
|
|
def test_privileged_argument_vararg_check():
|
|
"""Test that privileged decorator checks for simple arguments."""
|
|
|
|
def func_with_varargs(*_args):
|
|
return
|
|
|
|
def func_with_kwargs(**_kwargs):
|
|
return
|
|
|
|
def func_with_kwonlyargs(*_args, _kwarg):
|
|
return
|
|
|
|
def func_with_kwonlydefaults(*_args, _kwargs='foo'):
|
|
return
|
|
|
|
for func in (func_with_varargs, func_with_kwargs, func_with_kwonlyargs,
|
|
func_with_kwonlydefaults):
|
|
with pytest.raises(SyntaxError):
|
|
privileged(func)
|
|
|
|
|
|
def test_privileged_argument_annotation_check():
|
|
"""Test that privileged decorator checks for annotations to arguments."""
|
|
|
|
def func1(_a):
|
|
return
|
|
|
|
def func2(_a: int, _b):
|
|
return
|
|
|
|
def func_valid(_a: int, _b: dict[int, str]):
|
|
return
|
|
|
|
for func in (func1, func2):
|
|
with pytest.raises(SyntaxError):
|
|
privileged(func)
|
|
|
|
privileged(func_valid)
|
|
|
|
|
|
@patch('plinth.actions._get_privileged_action_module_name')
|
|
def test_privileged_method_call(get_module_name, popen):
|
|
"""Test that privileged method calls the superuser action properly."""
|
|
|
|
def func_with_args(_a: int, _b: str, _c: int = 1, _d: str = 'dval',
|
|
_e: str = 'eval'):
|
|
return
|
|
|
|
get_module_name.return_value = 'tests'
|
|
popen.return_value = json.dumps({'result': 'success', 'return': 'bar'})
|
|
wrapped_func = privileged(func_with_args)
|
|
return_value = wrapped_func(1, 'bval', None, _d='dnewval')
|
|
assert return_value == 'bar'
|
|
|
|
input_ = {'args': [1, 'bval', None], 'kwargs': {'_d': 'dnewval'}}
|
|
input_ = json.dumps(input_)
|
|
write_fd = popen.called_with_write_fd[0]
|
|
close_from_fd = str(write_fd + 1)
|
|
popen.assert_has_calls([
|
|
call([
|
|
'sudo', '--non-interactive', '--close-from', close_from_fd,
|
|
cfg.actions_dir + '/actions', 'tests', 'func_with_args',
|
|
'--write-fd',
|
|
str(write_fd)
|
|
], stdin=subprocess.PIPE, stdout=subprocess.PIPE,
|
|
stderr=subprocess.PIPE, shell=False, pass_fds=[write_fd])
|
|
])
|
|
|
|
|
|
@patch('plinth.actions._get_privileged_action_module_name')
|
|
def test_privileged_method_exceptions(get_module_name, popen):
|
|
"""Test that exceptions on privileged methods are return properly."""
|
|
|
|
def func_with_exception():
|
|
raise TypeError('type error')
|
|
|
|
get_module_name.return_value = 'tests'
|
|
popen.return_value = json.dumps({
|
|
'result': 'exception',
|
|
'exception': {
|
|
'module': 'builtins',
|
|
'name': 'TypeError',
|
|
'args': ['type error'],
|
|
'traceback': ['']
|
|
}
|
|
})
|
|
wrapped_func = privileged(func_with_exception)
|
|
with pytest.raises(TypeError, match='type error'):
|
|
wrapped_func()
|