mirror of
https://github.com/freedombox/FreedomBox.git
synced 2026-05-20 10:34:30 +00:00
tests: Merge actions related test files
Signed-off-by: Sunil Mohan Adapa <sunil@medhas.org> Reviewed-by: James Valleroy <jvalleroy@mailbox.org>
This commit is contained in:
parent
a14578c50d
commit
157abb023a
@ -10,13 +10,16 @@ description of the expectations.
|
|||||||
import json
|
import json
|
||||||
import os
|
import os
|
||||||
import subprocess
|
import subprocess
|
||||||
|
import typing
|
||||||
from unittest.mock import Mock, call, patch
|
from unittest.mock import Mock, call, patch
|
||||||
|
|
||||||
import pytest
|
import pytest
|
||||||
|
|
||||||
from plinth import cfg
|
from plinth import actions, cfg
|
||||||
from plinth.actions import privileged
|
from plinth.actions import privileged
|
||||||
|
|
||||||
|
actions_name = 'actions'
|
||||||
|
|
||||||
|
|
||||||
@pytest.fixture(name='popen')
|
@pytest.fixture(name='popen')
|
||||||
def fixture_popen():
|
def fixture_popen():
|
||||||
@ -140,3 +143,171 @@ def test_privileged_method_exceptions(get_module_name, popen):
|
|||||||
wrapped_func = privileged(func_with_exception)
|
wrapped_func = privileged(func_with_exception)
|
||||||
with pytest.raises(TypeError, match='type error'):
|
with pytest.raises(TypeError, match='type error'):
|
||||||
wrapped_func()
|
wrapped_func()
|
||||||
|
|
||||||
|
|
||||||
|
@patch('importlib.import_module')
|
||||||
|
@patch('plinth.module_loader.get_module_import_path')
|
||||||
|
@patch('os.getuid')
|
||||||
|
def test_call_syntax_checks(getuid, get_module_import_path, import_module):
|
||||||
|
"""Test that calling a method results in proper syntax checks."""
|
||||||
|
privileged_call = actions._privileged_call
|
||||||
|
|
||||||
|
# Module name validation
|
||||||
|
getuid.return_value = 0
|
||||||
|
with pytest.raises(SyntaxError, match='Invalid module name'):
|
||||||
|
privileged_call('foo.bar', 'x-action', {})
|
||||||
|
|
||||||
|
# Module import test
|
||||||
|
get_module_import_path.return_value = 'plinth.modules.test_module'
|
||||||
|
import_module.side_effect = ModuleNotFoundError
|
||||||
|
with pytest.raises(SyntaxError, match='Specified module not found'):
|
||||||
|
privileged_call('test_module', 'x-action', {})
|
||||||
|
|
||||||
|
import_module.assert_has_calls(
|
||||||
|
[call('plinth.modules.test_module.privileged')])
|
||||||
|
|
||||||
|
# Finding action in a module
|
||||||
|
module = type('', (), {})
|
||||||
|
import_module.side_effect = None
|
||||||
|
import_module.return_value = module
|
||||||
|
with pytest.raises(SyntaxError, match='Specified action not found'):
|
||||||
|
privileged_call('test_module', 'x-action', {})
|
||||||
|
|
||||||
|
# Checking if action is privileged
|
||||||
|
def unprivileged_func():
|
||||||
|
pass
|
||||||
|
|
||||||
|
setattr(module, 'func', unprivileged_func)
|
||||||
|
with pytest.raises(SyntaxError,
|
||||||
|
match='Specified action is not privileged action'):
|
||||||
|
privileged_call('test-module', 'func', {})
|
||||||
|
|
||||||
|
# Argument validation
|
||||||
|
@actions.privileged
|
||||||
|
def func():
|
||||||
|
return 'foo'
|
||||||
|
|
||||||
|
setattr(module, 'func', func)
|
||||||
|
with pytest.raises(SyntaxError, match='Invalid arguments format'):
|
||||||
|
privileged_call('test-module', 'func', {})
|
||||||
|
|
||||||
|
# Successful call
|
||||||
|
return_value = privileged_call('test-module', 'func', {
|
||||||
|
'args': [],
|
||||||
|
'kwargs': {}
|
||||||
|
})
|
||||||
|
assert return_value == {'result': 'success', 'return': 'foo'}
|
||||||
|
|
||||||
|
# Exception call
|
||||||
|
@actions.privileged
|
||||||
|
def exception_func():
|
||||||
|
raise RuntimeError('foo exception')
|
||||||
|
|
||||||
|
setattr(module, 'func', exception_func)
|
||||||
|
return_value = privileged_call('test-module', 'func', {
|
||||||
|
'args': [],
|
||||||
|
'kwargs': {}
|
||||||
|
})
|
||||||
|
assert return_value['result'] == 'exception'
|
||||||
|
assert return_value['exception']['module'] == 'builtins'
|
||||||
|
assert return_value['exception']['name'] == 'RuntimeError'
|
||||||
|
assert return_value['exception']['args'] == ('foo exception', )
|
||||||
|
assert isinstance(return_value['exception']['traceback'], list)
|
||||||
|
for line in return_value['exception']['traceback']:
|
||||||
|
assert isinstance(line, str)
|
||||||
|
|
||||||
|
|
||||||
|
def test_assert_valid_arguments():
|
||||||
|
"""Test that checking valid arguments works."""
|
||||||
|
assert_valid = actions._privileged_assert_valid_arguments
|
||||||
|
|
||||||
|
values = [
|
||||||
|
None, [], 10, {}, {
|
||||||
|
'args': []
|
||||||
|
}, {
|
||||||
|
'kwargs': {}
|
||||||
|
}, {
|
||||||
|
'args': {},
|
||||||
|
'kwargs': {}
|
||||||
|
}, {
|
||||||
|
'args': [],
|
||||||
|
'kwargs': []
|
||||||
|
}
|
||||||
|
]
|
||||||
|
for value in values:
|
||||||
|
with pytest.raises(SyntaxError, match='Invalid arguments format'):
|
||||||
|
assert_valid(lambda: None, value)
|
||||||
|
|
||||||
|
def func(a: int, b: str, c: int = 3, d: str = 'foo'):
|
||||||
|
pass
|
||||||
|
|
||||||
|
with pytest.raises(SyntaxError, match='Too many arguments'):
|
||||||
|
assert_valid(func, {'args': [1, 2, 3], 'kwargs': {'c': 3, 'd': 4}})
|
||||||
|
|
||||||
|
with pytest.raises(SyntaxError, match='Too many arguments'):
|
||||||
|
assert_valid(func, {'args': [1, 2, 3, 4, 5], 'kwargs': {}})
|
||||||
|
|
||||||
|
with pytest.raises(SyntaxError, match='Too many arguments'):
|
||||||
|
assert_valid(func, {
|
||||||
|
'args': [],
|
||||||
|
'kwargs': {
|
||||||
|
'a': 1,
|
||||||
|
'b': '2',
|
||||||
|
'c': 3,
|
||||||
|
'd': '4',
|
||||||
|
'e': 5
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
with pytest.raises(SyntaxError, match='Argument not provided: b'):
|
||||||
|
assert_valid(func, {'args': [1], 'kwargs': {}})
|
||||||
|
|
||||||
|
with pytest.raises(SyntaxError, match='Unknown argument: e'):
|
||||||
|
assert_valid(func, {'args': [1, '2'], 'kwargs': {'e': 5}})
|
||||||
|
|
||||||
|
with pytest.raises(SyntaxError, match='Duplicate argument: c'):
|
||||||
|
assert_valid(func, {'args': [1, '2', 3], 'kwargs': {'c': 4}})
|
||||||
|
|
||||||
|
with pytest.raises(TypeError, match='Expected type str for arg #1'):
|
||||||
|
assert_valid(func, {'args': [1, 2], 'kwargs': {}})
|
||||||
|
|
||||||
|
with pytest.raises(TypeError, match='Expected type int for arg c'):
|
||||||
|
assert_valid(func, {'args': [1, '2'], 'kwargs': {'c': '3'}})
|
||||||
|
|
||||||
|
|
||||||
|
def test_assert_valid_type():
|
||||||
|
"""Test that type validation works as expected."""
|
||||||
|
assert_valid = actions._privileged_assert_valid_type
|
||||||
|
|
||||||
|
assert_valid(None, None, typing.Any)
|
||||||
|
|
||||||
|
# Invalid values for int, str, float and Optional
|
||||||
|
values = [[1, bool], ['foo', int], [1, str], [1, float],
|
||||||
|
[1, typing.Optional[str]], [1, str | None],
|
||||||
|
[1.1, typing.Union[int, str]], [1.1, int | str], [1, list],
|
||||||
|
[1, dict], [[1], list[str]], [{
|
||||||
|
'a': 'b'
|
||||||
|
}, dict[int, str]], [{
|
||||||
|
1: 2
|
||||||
|
}, dict[int, str]]]
|
||||||
|
for value in values:
|
||||||
|
with pytest.raises(TypeError):
|
||||||
|
assert_valid('arg', *value)
|
||||||
|
|
||||||
|
# Valid values
|
||||||
|
assert_valid('arg', True, bool)
|
||||||
|
assert_valid('arg', 1, int)
|
||||||
|
assert_valid('arg', '1', str)
|
||||||
|
assert_valid('arg', 1.1, float)
|
||||||
|
assert_valid('arg', None, typing.Optional[int])
|
||||||
|
assert_valid('arg', 1, typing.Optional[int])
|
||||||
|
assert_valid('arg', None, int | None)
|
||||||
|
assert_valid('arg', 1, int | None)
|
||||||
|
assert_valid('arg', 1, typing.Union[int, str])
|
||||||
|
assert_valid('arg', '1', typing.Union[int, str])
|
||||||
|
assert_valid('arg', 1, int | str)
|
||||||
|
assert_valid('arg', '1', int | str)
|
||||||
|
assert_valid('arg', [], list[int])
|
||||||
|
assert_valid('arg', ['foo'], list[str])
|
||||||
|
assert_valid('arg', {}, dict[int, str])
|
||||||
|
assert_valid('arg', {1: 'foo'}, dict[int, str])
|
||||||
|
|||||||
@ -1,176 +0,0 @@
|
|||||||
# SPDX-License-Identifier: AGPL-3.0-or-later
|
|
||||||
"""
|
|
||||||
Test module for code that runs methods are privileged actions.
|
|
||||||
"""
|
|
||||||
|
|
||||||
import typing
|
|
||||||
from unittest.mock import call as mock_call
|
|
||||||
from unittest.mock import patch
|
|
||||||
|
|
||||||
import pytest
|
|
||||||
|
|
||||||
from plinth import actions
|
|
||||||
|
|
||||||
actions_name = 'actions'
|
|
||||||
|
|
||||||
|
|
||||||
@patch('importlib.import_module')
|
|
||||||
@patch('plinth.module_loader.get_module_import_path')
|
|
||||||
@patch('os.getuid')
|
|
||||||
def test_call_syntax_checks(getuid, get_module_import_path, import_module):
|
|
||||||
"""Test that calling a method results in proper syntax checks."""
|
|
||||||
call = actions._privileged_call
|
|
||||||
|
|
||||||
# Module name validation
|
|
||||||
getuid.return_value = 0
|
|
||||||
with pytest.raises(SyntaxError, match='Invalid module name'):
|
|
||||||
call('foo.bar', 'x-action', {})
|
|
||||||
|
|
||||||
# Module import test
|
|
||||||
get_module_import_path.return_value = 'plinth.modules.test_module'
|
|
||||||
import_module.side_effect = ModuleNotFoundError
|
|
||||||
with pytest.raises(SyntaxError, match='Specified module not found'):
|
|
||||||
call('test_module', 'x-action', {})
|
|
||||||
|
|
||||||
import_module.assert_has_calls(
|
|
||||||
[mock_call('plinth.modules.test_module.privileged')])
|
|
||||||
|
|
||||||
# Finding action in a module
|
|
||||||
module = type('', (), {})
|
|
||||||
import_module.side_effect = None
|
|
||||||
import_module.return_value = module
|
|
||||||
with pytest.raises(SyntaxError, match='Specified action not found'):
|
|
||||||
call('test_module', 'x-action', {})
|
|
||||||
|
|
||||||
# Checking if action is privileged
|
|
||||||
def unprivileged_func():
|
|
||||||
pass
|
|
||||||
|
|
||||||
setattr(module, 'func', unprivileged_func)
|
|
||||||
with pytest.raises(SyntaxError,
|
|
||||||
match='Specified action is not privileged action'):
|
|
||||||
call('test-module', 'func', {})
|
|
||||||
|
|
||||||
# Argument validation
|
|
||||||
@actions.privileged
|
|
||||||
def func():
|
|
||||||
return 'foo'
|
|
||||||
|
|
||||||
setattr(module, 'func', func)
|
|
||||||
with pytest.raises(SyntaxError, match='Invalid arguments format'):
|
|
||||||
call('test-module', 'func', {})
|
|
||||||
|
|
||||||
# Successful call
|
|
||||||
return_value = call('test-module', 'func', {'args': [], 'kwargs': {}})
|
|
||||||
assert return_value == {'result': 'success', 'return': 'foo'}
|
|
||||||
|
|
||||||
# Exception call
|
|
||||||
@actions.privileged
|
|
||||||
def exception_func():
|
|
||||||
raise RuntimeError('foo exception')
|
|
||||||
|
|
||||||
setattr(module, 'func', exception_func)
|
|
||||||
return_value = call('test-module', 'func', {'args': [], 'kwargs': {}})
|
|
||||||
assert return_value['result'] == 'exception'
|
|
||||||
assert return_value['exception']['module'] == 'builtins'
|
|
||||||
assert return_value['exception']['name'] == 'RuntimeError'
|
|
||||||
assert return_value['exception']['args'] == ('foo exception', )
|
|
||||||
assert isinstance(return_value['exception']['traceback'], list)
|
|
||||||
for line in return_value['exception']['traceback']:
|
|
||||||
assert isinstance(line, str)
|
|
||||||
|
|
||||||
|
|
||||||
def test_assert_valid_arguments():
|
|
||||||
"""Test that checking valid arguments works."""
|
|
||||||
assert_valid = actions._privileged_assert_valid_arguments
|
|
||||||
|
|
||||||
values = [
|
|
||||||
None, [], 10, {}, {
|
|
||||||
'args': []
|
|
||||||
}, {
|
|
||||||
'kwargs': {}
|
|
||||||
}, {
|
|
||||||
'args': {},
|
|
||||||
'kwargs': {}
|
|
||||||
}, {
|
|
||||||
'args': [],
|
|
||||||
'kwargs': []
|
|
||||||
}
|
|
||||||
]
|
|
||||||
for value in values:
|
|
||||||
with pytest.raises(SyntaxError, match='Invalid arguments format'):
|
|
||||||
assert_valid(lambda: None, value)
|
|
||||||
|
|
||||||
def func(a: int, b: str, c: int = 3, d: str = 'foo'):
|
|
||||||
pass
|
|
||||||
|
|
||||||
with pytest.raises(SyntaxError, match='Too many arguments'):
|
|
||||||
assert_valid(func, {'args': [1, 2, 3], 'kwargs': {'c': 3, 'd': 4}})
|
|
||||||
|
|
||||||
with pytest.raises(SyntaxError, match='Too many arguments'):
|
|
||||||
assert_valid(func, {'args': [1, 2, 3, 4, 5], 'kwargs': {}})
|
|
||||||
|
|
||||||
with pytest.raises(SyntaxError, match='Too many arguments'):
|
|
||||||
assert_valid(func, {
|
|
||||||
'args': [],
|
|
||||||
'kwargs': {
|
|
||||||
'a': 1,
|
|
||||||
'b': '2',
|
|
||||||
'c': 3,
|
|
||||||
'd': '4',
|
|
||||||
'e': 5
|
|
||||||
}
|
|
||||||
})
|
|
||||||
|
|
||||||
with pytest.raises(SyntaxError, match='Argument not provided: b'):
|
|
||||||
assert_valid(func, {'args': [1], 'kwargs': {}})
|
|
||||||
|
|
||||||
with pytest.raises(SyntaxError, match='Unknown argument: e'):
|
|
||||||
assert_valid(func, {'args': [1, '2'], 'kwargs': {'e': 5}})
|
|
||||||
|
|
||||||
with pytest.raises(SyntaxError, match='Duplicate argument: c'):
|
|
||||||
assert_valid(func, {'args': [1, '2', 3], 'kwargs': {'c': 4}})
|
|
||||||
|
|
||||||
with pytest.raises(TypeError, match='Expected type str for arg #1'):
|
|
||||||
assert_valid(func, {'args': [1, 2], 'kwargs': {}})
|
|
||||||
|
|
||||||
with pytest.raises(TypeError, match='Expected type int for arg c'):
|
|
||||||
assert_valid(func, {'args': [1, '2'], 'kwargs': {'c': '3'}})
|
|
||||||
|
|
||||||
|
|
||||||
def test_assert_valid_type():
|
|
||||||
"""Test that type validation works as expected."""
|
|
||||||
assert_valid = actions._privileged_assert_valid_type
|
|
||||||
|
|
||||||
assert_valid(None, None, typing.Any)
|
|
||||||
|
|
||||||
# Invalid values for int, str, float and Optional
|
|
||||||
values = [[1, bool], ['foo', int], [1, str], [1, float],
|
|
||||||
[1, typing.Optional[str]], [1, str | None],
|
|
||||||
[1.1, typing.Union[int, str]], [1.1, int | str], [1, list],
|
|
||||||
[1, dict], [[1], list[str]], [{
|
|
||||||
'a': 'b'
|
|
||||||
}, dict[int, str]], [{
|
|
||||||
1: 2
|
|
||||||
}, dict[int, str]]]
|
|
||||||
for value in values:
|
|
||||||
with pytest.raises(TypeError):
|
|
||||||
assert_valid('arg', *value)
|
|
||||||
|
|
||||||
# Valid values
|
|
||||||
assert_valid('arg', True, bool)
|
|
||||||
assert_valid('arg', 1, int)
|
|
||||||
assert_valid('arg', '1', str)
|
|
||||||
assert_valid('arg', 1.1, float)
|
|
||||||
assert_valid('arg', None, typing.Optional[int])
|
|
||||||
assert_valid('arg', 1, typing.Optional[int])
|
|
||||||
assert_valid('arg', None, int | None)
|
|
||||||
assert_valid('arg', 1, int | None)
|
|
||||||
assert_valid('arg', 1, typing.Union[int, str])
|
|
||||||
assert_valid('arg', '1', typing.Union[int, str])
|
|
||||||
assert_valid('arg', 1, int | str)
|
|
||||||
assert_valid('arg', '1', int | str)
|
|
||||||
assert_valid('arg', [], list[int])
|
|
||||||
assert_valid('arg', ['foo'], list[str])
|
|
||||||
assert_valid('arg', {}, dict[int, str])
|
|
||||||
assert_valid('arg', {1: 'foo'}, dict[int, str])
|
|
||||||
Loading…
x
Reference in New Issue
Block a user