437 changes: 250 additions & 187 deletions qubesadmin/tests/tools/qvm_template.py

Large diffs are not rendered by default.

130 changes: 73 additions & 57 deletions qubesadmin/tests/tools/qvm_template_postprocess.py
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,9 @@
#
# You should have received a copy of the GNU Lesser General Public License along
# with this program; if not, see <http://www.gnu.org/licenses/>.

# pylint: disable=missing-docstring

import argparse
import asyncio
import os
Expand All @@ -30,29 +33,30 @@

class QubesLocalMock(qubesadmin.tests.QubesTest):
def __init__(self):
super(QubesLocalMock, self).__init__()
super().__init__()
self.__class__ = qubesadmin.app.QubesLocal

qubesd_call = qubesadmin.tests.QubesTest.qubesd_call
run_service = qubesadmin.tests.QubesTest.run_service

class TC_00_qvm_template_postprocess(qubesadmin.tests.QubesTestCase):
def setUp(self):
super(TC_00_qvm_template_postprocess, self).setUp()
super().setUp()
# pylint: disable=consider-using-with
self.source_dir = tempfile.TemporaryDirectory()

def tearDown(self):
try:
self.source_dir.cleanup()
except FileNotFoundError:
pass
super(TC_00_qvm_template_postprocess, self).tearDown()
super().tearDown()

def test_000_import_root_img_raw(self):
root_img = os.path.join(self.source_dir.name, 'root.img')
volume_data = b'volume data'
with open(root_img, 'wb') as f:
f.write(volume_data)
with open(root_img, 'wb') as f_root:
f_root.write(volume_data)

self.app.expected_calls[('dom0', 'admin.vm.List', None, None)] = \
b'0\0test-vm class=TemplateVM state=Halted\n'
Expand All @@ -71,8 +75,8 @@ def test_000_import_root_img_raw(self):
def test_001_import_root_img_tar_pre_mar_2024(self):
root_img = os.path.join(self.source_dir.name, 'root.img')
volume_data = b'volume data' * 1000
with open(root_img, 'wb') as f:
f.write(volume_data)
with open(root_img, 'wb') as f_root:
f_root.write(volume_data)

subprocess.check_call(['tar', 'cf', 'root.img.tar', 'root.img'],
cwd=self.source_dir.name)
Expand Down Expand Up @@ -102,8 +106,8 @@ def test_001_import_root_img_tar_pre_mar_2024(self):
def test_001_import_root_img_tar(self):
root_img = os.path.join(self.source_dir.name, 'root.img')
volume_data = b'volume data' * 1000
with open(root_img, 'wb') as f:
f.write(volume_data)
with open(root_img, 'wb') as f_root:
f_root.write(volume_data)

subprocess.check_call(['tar', 'cf', 'root.img.tar', 'root.img'],
cwd=self.source_dir.name)
Expand All @@ -112,8 +116,8 @@ def test_001_import_root_img_tar(self):
os.unlink(root_img)

spec = os.path.join(self.source_dir.name, 'template.spec')
with open(spec, 'w') as f:
f.writelines((
with open(spec, 'w', encoding="utf-8") as f_spec:
f_spec.writelines((
'%define _rpmdir %{expand:%%(pwd)}/build\n',
'Name: test\n',
'Summary: testing\n',
Expand Down Expand Up @@ -167,8 +171,8 @@ def test_002_import_root_img_no_overwrite(self):
os.makedirs(template_dir)
root_img = os.path.join(template_dir, 'root.img')
volume_data = b'volume data'
with open(root_img, 'wb') as f:
f.write(volume_data)
with open(root_img, 'wb') as f_root:
f_root.write(volume_data)

self.app.expected_calls[('dom0', 'admin.vm.List', None, None)] = \
b'0\0test-vm class=TemplateVM state=Halted\n'
Expand Down Expand Up @@ -226,17 +230,20 @@ def test_010_import_appmenus(self):
'org.gnome.Terminal.desktop',
'nm-connection-editor.desktop']
with open(os.path.join(self.source_dir.name,
'vm-whitelisted-appmenus.list'), 'w') as f:
'vm-whitelisted-appmenus.list'), 'w',
encoding="utf-8") as f_list:
for entry in default_menu_items:
f.write(entry + '\n')
f_list.write(entry + '\n')
with open(os.path.join(self.source_dir.name,
'whitelisted-appmenus.list'), 'w') as f:
'whitelisted-appmenus.list'), 'w',
encoding="utf-8") as f_list:
for entry in menu_items:
f.write(entry + '\n')
f_list.write(entry + '\n')
with open(os.path.join(self.source_dir.name,
'netvm-whitelisted-appmenus.list'), 'w') as f:
'netvm-whitelisted-appmenus.list'), 'w',
encoding="utf-8") as f_list:
for entry in netvm_menu_items:
f.write(entry + '\n')
f_list.write(entry + '\n')

self.app.expected_calls[('dom0', 'admin.vm.List', None, None)] = \
b'0\0test-vm class=TemplateVM state=Halted\n'
Expand Down Expand Up @@ -283,17 +290,20 @@ def test_011_import_appmenus_as_root(self, mock_getuid, mock_getgrnam):
'org.gnome.Terminal.desktop',
'nm-connection-editor.desktop']
with open(os.path.join(self.source_dir.name,
'vm-whitelisted-appmenus.list'), 'w') as f:
'vm-whitelisted-appmenus.list'), 'w',
encoding="utf-8") as f_list:
for entry in default_menu_items:
f.write(entry + '\n')
f_list.write(entry + '\n')
with open(os.path.join(self.source_dir.name,
'whitelisted-appmenus.list'), 'w') as f:
'whitelisted-appmenus.list'), 'w',
encoding="utf-8") as f_list:
for entry in menu_items:
f.write(entry + '\n')
f_list.write(entry + '\n')
with open(os.path.join(self.source_dir.name,
'netvm-whitelisted-appmenus.list'), 'w') as f:
'netvm-whitelisted-appmenus.list'), 'w',
encoding="utf-8") as f_list:
for entry in netvm_menu_items:
f.write(entry + '\n')
f_list.write(entry + '\n')
self.app.expected_calls[(
'test-vm',
'admin.vm.feature.Set',
Expand Down Expand Up @@ -337,14 +347,16 @@ def test_011_import_appmenus_as_root(self, mock_getuid, mock_getgrnam):
@mock.patch('os.getuid')
def test_012_import_appmenus_missing_user(self, mock_getuid, mock_getgrnam):
with open(os.path.join(self.source_dir.name,
'vm-whitelisted-appmenus.list'), 'w') as f:
f.write('org.gnome.Terminal.desktop\n')
f.write('firefox.desktop\n')
'vm-whitelisted-appmenus.list'), 'w',
encoding="utf-8") as f_list:
f_list.write('org.gnome.Terminal.desktop\n')
f_list.write('firefox.desktop\n')
with open(os.path.join(self.source_dir.name,
'whitelisted-appmenus.list'), 'w') as f:
f.write('org.gnome.Terminal.desktop\n')
f.write('org.gnome.Software.desktop\n')
f.write('gnome-control-center.desktop\n')
'whitelisted-appmenus.list'), 'w',
encoding="utf-8") as f_list:
f_list.write('org.gnome.Terminal.desktop\n')
f_list.write('org.gnome.Software.desktop\n')
f_list.write('gnome-control-center.desktop\n')

self.app.expected_calls[('dom0', 'admin.vm.List', None, None)] = \
b'0\0test-vm class=TemplateVM state=Halted\n'
Expand All @@ -359,7 +371,7 @@ def test_012_import_appmenus_missing_user(self, mock_getuid, mock_getgrnam):
self.assertEqual(mock_proc.mock_calls, [])
self.assertAllCalled()

def add_new_vm_side_effect(self, *args, **kwargs):
def add_new_vm_side_effect(self, *_args, **_kwargs):
self.app.expected_calls[('dom0', 'admin.vm.List', None, None)] = \
b'0\0test-vm class=TemplateVM state=Halted\n'
self.app.domains.clear_cache()
Expand Down Expand Up @@ -523,8 +535,8 @@ def test_030_pre_remove(self):
= b'0\0'
self.app.expected_calls[
('test-vm', 'admin.vm.property.Get', 'template', None)] = \
b'2\0QubesNoSuchPropertyError\0\0invalid property \'template\' of ' \
b'test-vm\0'
b'2\0QubesNoSuchPropertyError\0\0invalid property ' \
b'\'template\' of test-vm\0'

ret = qubesadmin.tools.qvm_template_postprocess.main([
'--really', 'pre-remove', 'test-vm',
Expand All @@ -540,8 +552,8 @@ def test_031_pre_remove_existing_appvm(self):
b'test-vm2 class=AppVM state=Halted\n'
self.app.expected_calls[
('test-vm', 'admin.vm.property.Get', 'template', None)] = \
b'2\0QubesNoSuchPropertyError\0\0invalid property \'template\' of ' \
b'test-vm\0'
b'2\0QubesNoSuchPropertyError\0\0invalid property ' \
b'\'template\' of test-vm\0'
self.app.expected_calls[
('test-vm2', 'admin.vm.property.Get', 'template', None)] = \
b'0\0default=no type=vm test-vm'
Expand Down Expand Up @@ -572,8 +584,8 @@ def test_050_template_config(self):
kernel=
"""
template_conf = os.path.join(self.source_dir.name, 'template.conf')
with open(template_conf, 'w') as f:
f.write(template_config)
with open(template_conf, 'w', encoding="utf-8") as f_conf:
f_conf.write(template_config)
self.app.expected_calls[('dom0', 'admin.vm.List', None, None)] = \
b'0\0test-vm class=TemplateVM state=Halted\n'
self.app.expected_calls[(
Expand All @@ -583,11 +595,14 @@ def test_050_template_config(self):
self.app.expected_calls[(
'test-vm', 'admin.vm.feature.Set', 'linux-stubdom', b'1')] = b'0\0'
self.app.expected_calls[(
'test-vm', 'admin.vm.feature.Set', 'net.fake-ip', b'192.168.1.100')] = b'0\0'
'test-vm', 'admin.vm.feature.Set', 'net.fake-ip',
b'192.168.1.100')] = b'0\0'
self.app.expected_calls[(
'test-vm', 'admin.vm.feature.Set', 'net.fake-netmask', b'255.255.255.0')] = b'0\0'
'test-vm', 'admin.vm.feature.Set', 'net.fake-netmask',
b'255.255.255.0')] = b'0\0'
self.app.expected_calls[(
'test-vm', 'admin.vm.feature.Set', 'net.fake-gateway', b'192.168.1.1')] = b'0\0'
'test-vm', 'admin.vm.feature.Set', 'net.fake-gateway',
b'192.168.1.1')] = b'0\0'
self.app.expected_calls[(
'test-vm', 'admin.vm.property.Set', 'virt_mode', b'hvm')] = b'0\0'
self.app.expected_calls[(
Expand All @@ -611,40 +626,40 @@ def test_051_template_config_invalid(self):
with self.subTest('invalid feature value'):
template_config = "gui=false\n"
template_conf = os.path.join(self.source_dir.name, 'template.conf')
with open(template_conf, 'w') as f:
f.write(template_config)
with open(template_conf, 'w', encoding="utf-8") as f_conf:
f_conf.write(template_config)
qubesadmin.tools.qvm_template_postprocess.import_template_config(
args, template_conf, vm)

with self.subTest('invalid feature name'):
template_config = "invalid=1\n"
template_conf = os.path.join(self.source_dir.name, 'template.conf')
with open(template_conf, 'w') as f:
f.write(template_config)
with open(template_conf, 'w', encoding="utf-8") as f_conf:
f_conf.write(template_config)
qubesadmin.tools.qvm_template_postprocess.import_template_config(
args, template_conf, vm)

with self.subTest('invalid ip'):
template_config = "net.fake-ip=1.2.3.4.5\n"
template_conf = os.path.join(self.source_dir.name, 'template.conf')
with open(template_conf, 'w') as f:
f.write(template_config)
with open(template_conf, 'w', encoding="utf-8") as f_conf:
f_conf.write(template_config)
qubesadmin.tools.qvm_template_postprocess.import_template_config(
args, template_conf, vm)

with self.subTest('invalid virt-mode'):
template_config = "virt-mode=invalid\n"
template_conf = os.path.join(self.source_dir.name, 'template.conf')
with open(template_conf, 'w') as f:
f.write(template_config)
with open(template_conf, 'w', encoding="utf-8") as f_conf:
f_conf.write(template_config)
qubesadmin.tools.qvm_template_postprocess.import_template_config(
args, template_conf, vm)

with self.subTest('invalid kernel'):
template_config = "kernel=1.2.3.4.5\n"
template_conf = os.path.join(self.source_dir.name, 'template.conf')
with open(template_conf, 'w') as f:
f.write(template_config)
with open(template_conf, 'w', encoding="utf-8") as f_conf:
f_conf.write(template_config)
qubesadmin.tools.qvm_template_postprocess.import_template_config(
args, template_conf, vm)
self.assertAllCalled()
Expand All @@ -659,20 +674,21 @@ def test_052_template_config_virt_mode_pv(self):
with self.subTest('not allowed'):
template_config = "virt-mode=pv\n"
template_conf = os.path.join(self.source_dir.name, 'template.conf')
with open(template_conf, 'w') as f:
f.write(template_config)
with open(template_conf, 'w', encoding="utf-8") as f_conf:
f_conf.write(template_config)
qubesadmin.tools.qvm_template_postprocess.import_template_config(
args, template_conf, vm)
with self.subTest('allowed'):
args = argparse.Namespace(
allow_pv=True,
)
self.app.expected_calls[(
'test-vm', 'admin.vm.property.Set', 'virt_mode', b'pv')] = b'0\0'
'test-vm', 'admin.vm.property.Set', 'virt_mode',
b'pv')] = b'0\0'
template_config = "virt-mode=pv\n"
template_conf = os.path.join(self.source_dir.name, 'template.conf')
with open(template_conf, 'w') as f:
f.write(template_config)
with open(template_conf, 'w', encoding="utf-8") as f_conf:
f_conf.write(template_config)
qubesadmin.tools.qvm_template_postprocess.import_template_config(
args, template_conf, vm)
self.assertAllCalled()
2 changes: 2 additions & 0 deletions qubesadmin/tests/tools/qvm_unpause.py
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,8 @@
# You should have received a copy of the GNU Lesser General Public License along
# with this program; if not, see <http://www.gnu.org/licenses/>.

# pylint: disable=missing-docstring

import qubesadmin.tests
import qubesadmin.tools.qvm_unpause

Expand Down
29 changes: 17 additions & 12 deletions qubesadmin/tests/tools/qvm_volume.py
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,9 @@
#
# You should have received a copy of the GNU Lesser General Public License along
# with this program; if not, see <http://www.gnu.org/licenses/>.

# pylint: disable=missing-docstring

import tempfile
import unittest.mock

Expand Down Expand Up @@ -257,8 +260,8 @@ def test_020_revert(self):
('testvm', 'admin.vm.volume.ListSnapshots', 'private', None)] = \
b'0\x00200101010000\n200201010000\n200301010000\n'
self.app.expected_calls[
('testvm', 'admin.vm.volume.Revert', 'private', b'200301010000')] = \
b'0\x00'
('testvm', 'admin.vm.volume.Revert', 'private',
b'200301010000')] = b'0\x00'
self.assertEqual(0,
qubesadmin.tools.qvm_volume.main(
['revert', 'testvm:private'],
Expand All @@ -275,7 +278,8 @@ def test_021_revert_error(self):
('testvm', 'admin.vm.volume.ListSnapshots', 'private', None)] = \
b'0\x00200101010000\n200201010000\n200301010000\n'
self.app.expected_calls[
('testvm', 'admin.vm.volume.Revert', 'private', b'200301010000')] = \
('testvm', 'admin.vm.volume.Revert', 'private',
b'200301010000')] = \
b'2\x00StoragePoolException\x00\x00Failed to revert volume: ' \
b'some error\x00'
with qubesadmin.tests.tools.StderrBuffer() as stderr:
Expand Down Expand Up @@ -562,8 +566,8 @@ def test_050_import_file(self):
('testvm', 'admin.vm.volume.List', None, None)] = \
b'0\x00root\nprivate\n'
self.app.expected_calls[
('testvm', 'admin.vm.volume.ImportWithSize', 'private', b'9\ntest-data')] = \
b'0\x00'
('testvm', 'admin.vm.volume.ImportWithSize', 'private',
b'9\ntest-data')] = b'0\x00'
with tempfile.NamedTemporaryFile() as input_file:
input_file.write(b'test-data')
input_file.seek(0)
Expand All @@ -581,8 +585,8 @@ def test_051_import_stdin(self):
('testvm', 'admin.vm.volume.List', None, None)] = \
b'0\x00root\nprivate\n'
self.app.expected_calls[
('testvm', 'admin.vm.volume.ImportWithSize', 'private', b'9\ntest-data')] = \
b'0\x00'
('testvm', 'admin.vm.volume.ImportWithSize', 'private',
b'9\ntest-data')] = b'0\x00'
with tempfile.NamedTemporaryFile() as input_file:
input_file.write(b'test-data')
input_file.seek(0)
Expand All @@ -601,8 +605,8 @@ def test_052_import_file_size(self):
('testvm', 'admin.vm.volume.List', None, None)] = \
b'0\x00root\nprivate\n'
self.app.expected_calls[
('testvm', 'admin.vm.volume.ImportWithSize', 'private', b'512\ntest-data')] = \
b'0\x00'
('testvm', 'admin.vm.volume.ImportWithSize', 'private',
b'512\ntest-data')] = b'0\x00'
with tempfile.NamedTemporaryFile() as input_file:
input_file.write(b'test-data')
input_file.seek(0)
Expand All @@ -628,7 +632,8 @@ def test_053_import_file_noresize(self):
input_file.flush()
self.assertEqual(0,
qubesadmin.tools.qvm_volume.main(
['import', '--no-resize', 'testvm:private', input_file.name],
['import', '--no-resize', 'testvm:private',
input_file.name],
app=self.app))
self.assertAllCalled()

Expand All @@ -639,8 +644,8 @@ def test_053_import_file_matching_size(self):
('testvm', 'admin.vm.volume.List', None, None)] = \
b'0\x00root\nprivate\n'
self.app.expected_calls[
('testvm', 'admin.vm.volume.ImportWithSize', 'private', b'9\ntest-data')] = \
b'0\x00'
('testvm', 'admin.vm.volume.ImportWithSize', 'private',
b'9\ntest-data')] = b'0\x00'
with tempfile.NamedTemporaryFile() as input_file:
input_file.write(b'test-data')
input_file.seek(0)
Expand Down
4 changes: 3 additions & 1 deletion qubesadmin/tests/utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -18,13 +18,15 @@
# You should have received a copy of the GNU Lesser General Public License along
# with this program; if not, see <http://www.gnu.org/licenses/>.

# pylint: disable=missing-docstring

import qubesadmin.tests
import qubesadmin.utils


class TestVMUsage(qubesadmin.tests.QubesTestCase):
def setUp(self):
super(TestVMUsage, self).setUp()
super().setUp()

self.app.expected_calls[
('dom0', 'admin.vm.List', None, None)] = \
Expand Down
4 changes: 3 additions & 1 deletion qubesadmin/tests/vm/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -18,12 +18,14 @@
# You should have received a copy of the GNU Lesser General Public License along
# with this program; if not, see <http://www.gnu.org/licenses/>.

# pylint: disable=missing-docstring

import qubesadmin.tests


class VMTestCase(qubesadmin.tests.QubesTestCase):
def setUp(self):
super(VMTestCase, self).setUp()
super().setUp()
self.app.expected_calls[('dom0', 'admin.vm.List', None, None)] = \
b'0\x00test-vm class=AppVM state=Running\n'
self.vm = self.app.domains['test-vm']
18 changes: 13 additions & 5 deletions qubesadmin/tests/vm/actions.py
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,9 @@
#
# You should have received a copy of the GNU Lesser General Public License along
# with this program; if not, see <http://www.gnu.org/licenses/>.

# pylint: disable=missing-docstring

import unittest

import qubesadmin.tests.vm
Expand Down Expand Up @@ -96,8 +99,10 @@ def test_011_run_windows(self):

def test_015_run_with_args_shell(self):
self.app.expected_calls[
('test-vm', 'admin.vm.feature.CheckWithTemplate', 'vmexec', None)] = \
b'2\x00QubesFeatureNotFoundError\x00\x00Feature \'vmexec\' not set\x00'
('test-vm', 'admin.vm.feature.CheckWithTemplate', 'vmexec',
None)] = \
b'2\x00QubesFeatureNotFoundError\x00\x00' \
b'Feature \'vmexec\' not set\x00'
self.app.expected_calls[
('test-vm', 'admin.vm.feature.CheckWithTemplate', 'os', None)] = \
b'2\x00QubesFeatureNotFoundError\x00\x00Feature \'os\' not set\x00'
Expand All @@ -112,15 +117,18 @@ def test_015_run_with_args_shell(self):

def test_016_run_with_args_exec(self):
self.app.expected_calls[
('test-vm', 'admin.vm.feature.CheckWithTemplate', 'vmexec', None)] = \
('test-vm', 'admin.vm.feature.CheckWithTemplate', 'vmexec',
None)] = \
b'0\x001'
self.vm.run_with_args('some', 'argument with spaces',
'and $pecial; chars')
self.assertEqual(self.app.service_calls, [
('test-vm',
'qubes.VMExec+some+argument-20with-20spaces+and-20-24pecial-3B-20chars',
'qubes.VMExec+some+argument-20with-20spaces+and-20-24'
'pecial-3B-20chars',
{}),
('test-vm',
'qubes.VMExec+some+argument-20with-20spaces+and-20-24pecial-3B-20chars',
'qubes.VMExec+some+argument-20with-20spaces+and-20-24'
'pecial-3B-20chars',
b''),
])
10 changes: 6 additions & 4 deletions qubesadmin/tests/vm/dispvm.py
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,8 @@
# You should have received a copy of the GNU Lesser General Public License along
# with this program; if not, see <http://www.gnu.org/licenses/>.

# pylint: disable=missing-docstring

import qubesadmin.tests
import qubesadmin.vm

Expand All @@ -32,7 +34,7 @@ def test_000_local_create_default(self):
('disp123', 'admin.vm.property.Get', 'qrexec_timeout', None)] = \
b'0\0default=yes type=int 30'
vm = qubesadmin.vm.DispVM.from_appvm(self.app, None)
(stdout, stderr) = vm.run_service_for_stdio('test.service')
vm.run_service_for_stdio('test.service')
vm.cleanup()
self.assertEqual(self.app.service_calls, [
('disp123', 'test.service', {'connect_timeout': 30}),
Expand All @@ -51,7 +53,7 @@ def test_001_local_create_specific(self):
('disp123', 'admin.vm.property.Get', 'qrexec_timeout', None)] = \
b'0\0default=yes type=int 30'
vm = qubesadmin.vm.DispVM.from_appvm(self.app, 'test-vm')
(stdout, stderr) = vm.run_service_for_stdio('test.service')
vm.run_service_for_stdio('test.service')
vm.cleanup()
self.assertEqual(self.app.service_calls, [
('disp123', 'test.service', {'connect_timeout': 30}),
Expand All @@ -68,7 +70,7 @@ def test_002_local_no_run_cleanup(self):

def test_010_remote_create_default(self):
vm = qubesadmin.vm.DispVM.from_appvm(self.app, None)
(stdout, stderr) = vm.run_service_for_stdio('test.service')
vm.run_service_for_stdio('test.service')
vm.cleanup()
self.assertEqual(self.app.service_calls, [
('$dispvm', 'test.service', {}),
Expand All @@ -78,7 +80,7 @@ def test_010_remote_create_default(self):

def test_011_remote_create_specific(self):
vm = qubesadmin.vm.DispVM.from_appvm(self.app, 'test-vm')
(stdout, stderr) = vm.run_service_for_stdio('test.service')
vm.run_service_for_stdio('test.service')
vm.cleanup()
self.assertEqual(self.app.service_calls, [
('$dispvm:test-vm', 'test.service', {}),
Expand Down
24 changes: 18 additions & 6 deletions qubesadmin/tests/vm/properties.py
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,8 @@
# You should have received a copy of the GNU Lesser General Public License along
# with this program; if not, see <http://www.gnu.org/licenses/>.

# pylint: disable=missing-docstring

import qubesadmin.tests.vm


Expand Down Expand Up @@ -73,6 +75,7 @@ def test_006_get_none_bool(self):
('test-vm', 'admin.vm.property.Get', 'prop1', None)] = \
b'0\x00default=False type=bool '
with self.assertRaises(AttributeError):
# pylint: disable=pointless-statement
self.vm.prop1
self.assertAllCalled()

Expand All @@ -81,6 +84,7 @@ def test_007_get_none_int(self):
('test-vm', 'admin.vm.property.Get', 'prop1', None)] = \
b'0\x00default=False type=int '
with self.assertRaises(AttributeError):
# pylint: disable=pointless-statement
self.vm.prop1
self.assertAllCalled()

Expand Down Expand Up @@ -111,6 +115,7 @@ def test_012_get_invalid(self):
b'2\x00QubesNoSuchPropertyError\x00\x00Invalid property ' \
b'\'invalid\' on test-vm\x00'
with self.assertRaises(qubesadmin.exc.QubesNoSuchPropertyError):
# pylint: disable=pointless-statement
self.vm.invalid
self.assertFalse(hasattr(self.vm, 'invalid'))
self.assertAllCalled()
Expand Down Expand Up @@ -201,6 +206,7 @@ def test_050_get_all(self):
self.app.cache_enabled = True
self.assertEqual(self.vm.name, 'test-vm')
with self.assertRaises(AttributeError):
# pylint: disable=pointless-statement
self.vm.backup_timestamp
self.assertEqual(self.vm.debug, False)
self.assertEqual(self.vm.qid, 3)
Expand Down Expand Up @@ -240,42 +246,48 @@ def test_001_set_name(self):
self.app.actual_calls = []
del self.app.expected_calls[
('test-vm', 'admin.vm.property.Set', 'name', b'test-vm2')]
vm = self.app.domains['test-vm']
# pylint: disable=pointless-statement
self.app.domains['test-vm']
self.assertAllCalled()

def test_010_power_state_running(self):
self.app.expected_calls[('test-vm', 'admin.vm.CurrentState', None, None)] = \
self.app.expected_calls[
('test-vm', 'admin.vm.CurrentState', None, None)] = \
b'0\x00power_state=Running'
self.assertEqual(self.vm.get_power_state(), 'Running')
self.assertTrue(self.vm.is_running())
self.assertFalse(self.vm.is_halted())
self.assertFalse(self.vm.is_paused())

def test_011_power_state_paused(self):
self.app.expected_calls[('test-vm', 'admin.vm.CurrentState', None, None)] = \
self.app.expected_calls[
('test-vm', 'admin.vm.CurrentState', None, None)] = \
b'0\x00power_state=Paused'
self.assertEqual(self.vm.get_power_state(), 'Paused')
self.assertTrue(self.vm.is_running())
self.assertFalse(self.vm.is_halted())
self.assertTrue(self.vm.is_paused())

def test_012_power_state_halted(self):
self.app.expected_calls[('test-vm', 'admin.vm.CurrentState', None, None)] = \
self.app.expected_calls[
('test-vm', 'admin.vm.CurrentState', None, None)] = \
b'0\x00power_state=Halted'
self.assertEqual(self.vm.get_power_state(), 'Halted')
self.assertFalse(self.vm.is_running())
self.assertTrue(self.vm.is_halted())
self.assertFalse(self.vm.is_paused())

def test_012_power_state_transient(self):
self.app.expected_calls[('test-vm', 'admin.vm.CurrentState', None, None)] = \
self.app.expected_calls[
('test-vm', 'admin.vm.CurrentState', None, None)] = \
b'0\x00power_state=Transient'
self.assertEqual(self.vm.get_power_state(), 'Transient')
self.assertTrue(self.vm.is_running())
self.assertFalse(self.vm.is_halted())
self.assertFalse(self.vm.is_paused())

def test_015_mem(self):
self.app.expected_calls[('test-vm', 'admin.vm.CurrentState', None, None)] = \
self.app.expected_calls[
('test-vm', 'admin.vm.CurrentState', None, None)] = \
b'0\x00mem=1234'
self.assertEqual(self.vm.get_mem(), 1234)
2 changes: 2 additions & 0 deletions qubesadmin/tests/vm/storage.py
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,8 @@
# You should have received a copy of the GNU Lesser General Public License along
# with this program; if not, see <http://www.gnu.org/licenses/>.

# pylint: disable=missing-docstring,protected-access

import qubesadmin.tests.vm


Expand Down
1 change: 1 addition & 0 deletions qubesadmin/tools/qvm_start_daemon.py
Original file line number Diff line number Diff line change
Expand Up @@ -110,6 +110,7 @@ def validator_color(color: str) -> bool:
('startup_timeout', 'int', (lambda x: isinstance(x, int) and x >= 0)),
('max_clipboard_size', 'int', \
(lambda x: isinstance(x, int) and 256 <= x <= 256000)),
('events_max_delay', 'int', (lambda x: isinstance(x, int) and x >= 0)),
]

formatter = logging.Formatter(
Expand Down
3 changes: 2 additions & 1 deletion qubesadmin/tools/qvm_template.py
Original file line number Diff line number Diff line change
Expand Up @@ -581,7 +581,8 @@ def qrexec_repoquery(
'%Y-%m-%d %H:%M')
elif buildtime.isnumeric():
# DNF5 provides seconds since epoch
buildtime = datetime.datetime.fromtimestamp(int(buildtime))
buildtime = datetime.datetime.fromtimestamp(int(buildtime),
tz=datetime.timezone.utc)
else:
raise ValueError
# XXX: Perhaps whitelist licenses directly?
Expand Down
2 changes: 1 addition & 1 deletion version
Original file line number Diff line number Diff line change
@@ -1 +1 @@
4.3.7
4.3.8