Merge remote-tracking branch 'origin/pr/205'

* origin/pr/205:
  Added better exception handling on Backup Cancel
  Tests fixed for new features and bugfixes
  Removed not needed workaround for check-updates on dom0
  Fixed default install_system state for Create New VM
  Fixed manager tests to use Qt5
This commit is contained in:
Marek Marczykowski-Górecki 2019-10-24 03:20:28 +02:00
commit 1dabce0f54
No known key found for this signature in database
GPG Key ID: 063938BA42CFA724
10 changed files with 313 additions and 426 deletions

View File

@ -357,9 +357,15 @@ class BackupVMsWindow(ui_backupdlg.Ui_Backup, QtWidgets.QWizard):
def reject(self): def reject(self):
if (self.currentPage() is self.commit_page) and \ if (self.currentPage() is self.commit_page) and \
self.button(self.CancelButton).isEnabled(): self.button(self.CancelButton).isEnabled():
try:
self.qubes_app.qubesd_call( self.qubes_app.qubesd_call(
'dom0', 'admin.backup.Cancel', 'dom0', 'admin.backup.Cancel',
backup_utils.get_profile_name(True)) backup_utils.get_profile_name(True))
except exc.QubesException as ex:
QtWidgets.QMessageBox.warning(
self, self.tr("Error cancelling backup!"),
self.tr("ERROR: {}").format(str(ex)))
self.thread.wait() self.thread.wait()
QtWidgets.QMessageBox.warning( QtWidgets.QMessageBox.warning(
self, self.tr("Backup aborted!"), self, self.tr("Backup aborted!"),

View File

@ -20,8 +20,6 @@
# #
# #
import os
import os.path
import subprocess import subprocess
from PyQt5 import QtWidgets # pylint: disable=import-error from PyQt5 import QtWidgets # pylint: disable=import-error
@ -245,15 +243,11 @@ class GlobalSettingsWindow(ui_globalsettingsdlg.Ui_GlobalSettings,
qmemman_config_file.close() qmemman_config_file.close()
def __init_updates__(self): def __init_updates__(self):
# TODO: remove workaround when it is no longer needed
self.dom0_updates_file_path = '/var/lib/qubes/updates/disable-updates'
try: try:
self.updates_dom0_val = bool(self.qvm_collection.domains[ self.updates_dom0_val = bool(self.qvm_collection.domains[
'dom0'].features['service.qubes-update-check']) 'dom0'].features['service.qubes-update-check'])
except KeyError: except KeyError:
self.updates_dom0_val =\ self.updates_dom0_val = True
not os.path.isfile(self.dom0_updates_file_path)
self.updates_dom0.setChecked(self.updates_dom0_val) self.updates_dom0.setChecked(self.updates_dom0_val)

View File

@ -0,0 +1,16 @@
import asyncio
import sys
import quamash
from PyQt5 import QtWidgets
qtapp = None
loop = None
def init_qtapp():
global qtapp, loop
if qtapp is None:
qtapp = QtWidgets.QApplication(sys.argv)
loop = quamash.QEventLoop(qtapp)
asyncio.set_event_loop(loop)
return qtapp, loop

View File

@ -20,21 +20,36 @@
# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. # 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
# #
import logging.handlers import logging.handlers
import sys
import unittest import unittest
import unittest.mock import unittest.mock
from PyQt4 import QtGui, QtTest, QtCore from PyQt5 import QtTest, QtCore, QtWidgets
from qubesadmin import Qubes, events, utils, exc from qubesadmin import Qubes, events, utils, exc
from qubesmanager import backup from qubesmanager import backup
import quamash from qubesmanager.tests import init_qtapp
import asyncio
import gc
class BackupTest(unittest.TestCase): class BackupTest(unittest.TestCase):
@classmethod
def setUpClass(cls):
qapp = Qubes()
cls.dom0_name = "dom0"
cls.vms = []
cls.running_vm = None
for vm in qapp.domains:
if vm.klass != "AdminVM" and vm.is_running():
cls.running_vm = vm.name
if vm.klass != "AdminVM" and vm.get_disk_utilization() > 0:
cls.vms.append(vm.name)
if cls.running_vm and len(cls.vms) >= 3:
break
def setUp(self): def setUp(self):
super(BackupTest, self).setUp() super(BackupTest, self).setUp()
self.qtapp, self.loop = init_qtapp()
# mock up nonexistence of saved backup settings # mock up nonexistence of saved backup settings
self.patcher_open = unittest.mock.patch('builtins.open') self.patcher_open = unittest.mock.patch('builtins.open')
@ -49,43 +64,14 @@ class BackupTest(unittest.TestCase):
self.addCleanup(self.patcher_thread.stop) self.addCleanup(self.patcher_thread.stop)
self.qapp = Qubes() self.qapp = Qubes()
self.qtapp = QtGui.QApplication(["test", "-style", "cleanlooks"])
self.dispatcher = events.EventsDispatcher(self.qapp) self.dispatcher = events.EventsDispatcher(self.qapp)
self.loop = quamash.QEventLoop(self.qtapp)
self.dialog = backup.BackupVMsWindow( self.dialog = backup.BackupVMsWindow(
self.qtapp, self.qapp, self.dispatcher) self.qtapp, self.qapp, self.dispatcher)
self.dialog.show() self.dialog.show()
def tearDown(self): def tearDown(self):
self.dialog.hide() self.dialog.done(0)
# process any pending events before destroying the object
self.qtapp.processEvents()
# queue destroying the QApplication object, do that for any other QT
# related objects here too
self.qtapp.deleteLater()
self.dialog.deleteLater()
# process any pending events (other than just queued destroy),
# just in case
self.qtapp.processEvents()
# execute main loop, which will process all events, _
# including just queued destroy_
self.loop.run_until_complete(asyncio.sleep(0))
# at this point it QT objects are destroyed, cleanup all remaining
# references;
# del other QT object here too
self.loop.close()
del self.dialog
del self.qtapp
del self.loop
gc.collect()
super(BackupTest, self).tearDown() super(BackupTest, self).tearDown()
def test_00_window_loads(self): def test_00_window_loads(self):
@ -106,7 +92,8 @@ class BackupTest(unittest.TestCase):
"Compress backup should be checked by default") "Compress backup should be checked by default")
# correct VMs are selected # correct VMs are selected
include_in_backups_no = len([vm for vm in self.qapp.domains include_in_backups_no = len(
[vm for vm in self.qapp.domains
if not vm.features.get('internal', False) if not vm.features.get('internal', False)
and getattr(vm, 'include_in_backups', True)]) and getattr(vm, 'include_in_backups', True)])
selected_no = self.dialog.select_vms_widget.selected_list.count() selected_no = self.dialog.select_vms_widget.selected_list.count()
@ -137,7 +124,7 @@ class BackupTest(unittest.TestCase):
self.dialog.select_vms_widget.available_list.count(), self.dialog.select_vms_widget.available_list.count(),
"Remove All VMs does not work") "Remove All VMs does not work")
self._select_vm("work") self._select_vm(self.vms[0])
self.assertEqual(self.dialog.select_vms_widget.selected_list.count(), self.assertEqual(self.dialog.select_vms_widget.selected_list.count(),
1, "Select a single VM does not work") 1, "Select a single VM does not work")
@ -206,12 +193,16 @@ class BackupTest(unittest.TestCase):
def test_07_disk_space_correct(self): def test_07_disk_space_correct(self):
for i in range(self.dialog.select_vms_widget.available_list.count()): for i in range(self.dialog.select_vms_widget.available_list.count()):
item = self.dialog.select_vms_widget.available_list.item(i) item = self.dialog.select_vms_widget.available_list.item(i)
if item.vm.name == "dom0" or item.vm.get_disk_utilization() > 0: if item.vm.name == self.dom0_name or \
item.vm.get_disk_utilization() > 0:
self.assertGreater( self.assertGreater(
item.size, 0, item.size, 0,
"{} size incorrectly reported as 0".format(item.vm.name)) "{} size incorrectly reported as 0".format(item.vm.name))
def test_08_total_size_correct(self): def test_08_total_size_correct(self):
if len(self.vms) < 3:
self.skipTest("Insufficient number of VMs with positive "
"disk utilization")
# select nothing # select nothing
self.dialog.select_vms_widget.remove_all_button.click() self.dialog.select_vms_widget.remove_all_button.click()
self.assertEqual(self.dialog.total_size_label.text(), "0", self.assertEqual(self.dialog.total_size_label.text(), "0",
@ -219,27 +210,27 @@ class BackupTest(unittest.TestCase):
current_size = 0 current_size = 0
# select a single VM # select a single VM
self._select_vm("sys-net") self._select_vm(self.vms[0])
current_size += self.qapp.domains["sys-net"].get_disk_utilization() current_size += self.qapp.domains[self.vms[0]].get_disk_utilization()
self.assertEqual(self.dialog.total_size_label.text(), self.assertEqual(self.dialog.total_size_label.text(),
utils.size_to_human(current_size), utils.size_to_human(current_size),
"Size incorrectly listed for a single VM") "Size incorrectly listed for a single VM")
# add two more # add two more
self._select_vm("sys-firewall") self._select_vm(self.vms[1])
self._select_vm("work") self._select_vm(self.vms[2])
current_size += self.qapp.domains["sys-firewall"].get_disk_utilization() current_size += self.qapp.domains[self.vms[1]].get_disk_utilization()
current_size += self.qapp.domains["work"].get_disk_utilization() current_size += self.qapp.domains[self.vms[2]].get_disk_utilization()
self.assertEqual(self.dialog.total_size_label.text(), self.assertEqual(self.dialog.total_size_label.text(),
utils.size_to_human(current_size), utils.size_to_human(current_size),
"Size incorrectly listed for several VMs") "Size incorrectly listed for several VMs")
# remove one # remove one
self._deselect_vm("sys-net") self._deselect_vm(self.vms[0])
current_size -= self.qapp.domains["sys-net"].get_disk_utilization() current_size -= self.qapp.domains[self.vms[0]].get_disk_utilization()
self.assertEqual(self.dialog.total_size_label.text(), self.assertEqual(self.dialog.total_size_label.text(),
utils.size_to_human(current_size), utils.size_to_human(current_size),
"Size incorrectly listed for several VMs") "Size incorrectly listed for several VMs")
@ -252,7 +243,7 @@ class BackupTest(unittest.TestCase):
is self.dialog.select_vms_page) is self.dialog.select_vms_page)
self.dialog.select_vms_widget.remove_all_button.click() self.dialog.select_vms_widget.remove_all_button.click()
self._select_vm("work") self._select_vm(self.vms[0])
self._click_next() self._click_next()
@ -260,16 +251,16 @@ class BackupTest(unittest.TestCase):
is self.dialog.select_dir_page) is self.dialog.select_dir_page)
# setup backup # setup backup
self._select_location("dom0") self._select_location(self.dom0_name)
self.dialog.dir_line_edit.setText("/home") self.dialog.dir_line_edit.setText("/home")
self.dialog.passphrase_line_edit.setText("pass") self.dialog.passphrase_line_edit.setText("pass")
self.dialog.passphrase_line_edit_verify.setText("pass") self.dialog.passphrase_line_edit_verify.setText("pass")
self.dialog.save_profile_checkbox.setChecked(True) self.dialog.save_profile_checkbox.setChecked(True)
self.dialog.turn_off_checkbox.setChecked(False) self.dialog.turn_off_checkbox.setChecked(False)
self.dialog.compress_checkbox.setChecked(False) self.dialog.compress_checkbox.setChecked(False)
expected_settings = {'destination_vm': "dom0", expected_settings = {'destination_vm': self.dom0_name,
'destination_path': "/home", 'destination_path': "/home",
'include': ["work"], 'include': [self.vms[0]],
'passphrase_text': "pass", 'passphrase_text': "pass",
'compression': False} 'compression': False}
with unittest.mock.patch.object(self.dialog.textEdit, 'setText')\ with unittest.mock.patch.object(self.dialog.textEdit, 'setText')\
@ -287,7 +278,8 @@ class BackupTest(unittest.TestCase):
# make sure the backup is executed # make sure the backup is executed
self._click_next() self._click_next()
self.mock_thread.assert_called_once_with(self.qapp.domains["dom0"]) self.mock_thread.assert_called_once_with(
self.qapp.domains[self.dom0_name])
self.mock_thread().start.assert_called_once_with() self.mock_thread().start.assert_called_once_with()
@unittest.mock.patch('qubesmanager.backup_utils.write_backup_profile') @unittest.mock.patch('qubesmanager.backup_utils.write_backup_profile')
@ -298,9 +290,9 @@ class BackupTest(unittest.TestCase):
is self.dialog.select_vms_page) is self.dialog.select_vms_page)
self.dialog.select_vms_widget.remove_all_button.click() self.dialog.select_vms_widget.remove_all_button.click()
self._select_vm("work") self._select_vm(self.dom0_name)
self._select_vm("sys-net") self._select_vm(self.vms[0])
self._select_vm("dom0") self._select_vm(self.vms[1])
self._click_next() self._click_next()
@ -308,16 +300,17 @@ class BackupTest(unittest.TestCase):
is self.dialog.select_dir_page) is self.dialog.select_dir_page)
# setup backup # setup backup
self._select_location("sys-net") self._select_location(self.running_vm)
self.dialog.dir_line_edit.setText("/home") self.dialog.dir_line_edit.setText("/home")
self.dialog.passphrase_line_edit.setText("longerPassPhrase") self.dialog.passphrase_line_edit.setText("longerPassPhrase")
self.dialog.passphrase_line_edit_verify.setText("longerPassPhrase") self.dialog.passphrase_line_edit_verify.setText("longerPassPhrase")
self.dialog.save_profile_checkbox.setChecked(False) self.dialog.save_profile_checkbox.setChecked(False)
self.dialog.turn_off_checkbox.setChecked(False) self.dialog.turn_off_checkbox.setChecked(False)
self.dialog.compress_checkbox.setChecked(True) self.dialog.compress_checkbox.setChecked(True)
expected_settings = {'destination_vm': "sys-net", expected_settings = {'destination_vm': self.running_vm,
'destination_path': "/home", 'destination_path': "/home",
'include': ["dom0", "sys-net", "work"], 'include': sorted([self.dom0_name, self.vms[0],
self.vms[1]]),
'passphrase_text': "longerPassPhrase", 'passphrase_text': "longerPassPhrase",
'compression': True} 'compression': True}
with unittest.mock.patch.object(self.dialog.textEdit, 'setText')\ with unittest.mock.patch.object(self.dialog.textEdit, 'setText')\
@ -335,16 +328,17 @@ class BackupTest(unittest.TestCase):
# make sure the backup is executed # make sure the backup is executed
self._click_next() self._click_next()
self.mock_thread.assert_called_once_with(self.qapp.domains["sys-net"]) self.mock_thread.assert_called_once_with(
self.qapp.domains[self.running_vm])
self.mock_thread().start.assert_called_once_with() self.mock_thread().start.assert_called_once_with()
@unittest.mock.patch('qubesmanager.backup_utils.load_backup_profile') @unittest.mock.patch('qubesmanager.backup_utils.load_backup_profile')
def test_20_loading_settings(self, mock_load): def test_20_loading_settings(self, mock_load):
mock_load.return_value = { mock_load.return_value = {
'destination_vm': "sys-net", 'destination_vm': self.running_vm,
'destination_path': "/home", 'destination_path': "/home",
'include': ["dom0", "sys-net", "work"], 'include': [self.dom0_name, self.vms[0], self.vms[1]],
'passphrase_text': "longerPassPhrase", 'passphrase_text': "longerPassPhrase",
'compression': True 'compression': True
} }
@ -358,7 +352,8 @@ class BackupTest(unittest.TestCase):
self.dialog.show() self.dialog.show()
# check if settings were loaded # check if settings were loaded
self.assertEqual(self.dialog.appvm_combobox.currentText(), "sys-net", self.assertEqual(self.dialog.appvm_combobox.currentText(),
self.running_vm,
"Destination VM not loaded") "Destination VM not loaded")
self.assertEqual(self.dialog.dir_line_edit.text(), "/home", self.assertEqual(self.dialog.dir_line_edit.text(), "/home",
"Destination path not loaded") "Destination path not loaded")
@ -399,7 +394,7 @@ class BackupTest(unittest.TestCase):
self.assertTrue(self.dialog.unrecognized_config_label.isVisible()) self.assertTrue(self.dialog.unrecognized_config_label.isVisible())
@unittest.mock.patch('qubesmanager.backup_utils.load_backup_profile') @unittest.mock.patch('qubesmanager.backup_utils.load_backup_profile')
@unittest.mock.patch('PyQt4.QtGui.QMessageBox.information') @unittest.mock.patch('PyQt5.QtWidgets.QMessageBox.information')
def test_22_loading_settings_exc(self, mock_info, mock_load): def test_22_loading_settings_exc(self, mock_info, mock_load):
mock_load.side_effect = exc.QubesException('Error') mock_load.side_effect = exc.QubesException('Error')
@ -423,7 +418,7 @@ class BackupTest(unittest.TestCase):
self.assertTrue(self.dialog.currentPage() self.assertTrue(self.dialog.currentPage()
is self.dialog.select_dir_page) is self.dialog.select_dir_page)
self._select_location("dom0") self._select_location(self.dom0_name)
self.dialog.dir_line_edit.setText("/home") self.dialog.dir_line_edit.setText("/home")
self.dialog.passphrase_line_edit.setText("pass") self.dialog.passphrase_line_edit.setText("pass")
self.dialog.passphrase_line_edit_verify.setText("pass") self.dialog.passphrase_line_edit_verify.setText("pass")
@ -436,7 +431,7 @@ class BackupTest(unittest.TestCase):
mock_remove.assert_called_once_with( mock_remove.assert_called_once_with(
'/etc/qubes/backup/qubes-manager-backup-tmp.conf') '/etc/qubes/backup/qubes-manager-backup-tmp.conf')
@unittest.mock.patch('PyQt4.QtGui.QMessageBox.warning') @unittest.mock.patch('PyQt5.QtWidgets.QMessageBox.warning')
@unittest.mock.patch('qubesmanager.backup_utils.write_backup_profile') @unittest.mock.patch('qubesmanager.backup_utils.write_backup_profile')
@unittest.mock.patch('qubesadmin.Qubes.qubesd_call', @unittest.mock.patch('qubesadmin.Qubes.qubesd_call',
return_value=b'backup output') return_value=b'backup output')
@ -445,7 +440,7 @@ class BackupTest(unittest.TestCase):
self.assertTrue(self.dialog.currentPage() self.assertTrue(self.dialog.currentPage()
is self.dialog.select_dir_page) is self.dialog.select_dir_page)
self._select_location("dom0") self._select_location(self.dom0_name)
self.dialog.dir_line_edit.setText("/home") self.dialog.dir_line_edit.setText("/home")
self.dialog.passphrase_line_edit.setText("pass") self.dialog.passphrase_line_edit.setText("pass")
self.dialog.passphrase_line_edit_verify.setText("pass") self.dialog.passphrase_line_edit_verify.setText("pass")
@ -461,7 +456,7 @@ class BackupTest(unittest.TestCase):
mock_remove.assert_called_once_with( mock_remove.assert_called_once_with(
'/etc/qubes/backup/qubes-manager-backup-tmp.conf') '/etc/qubes/backup/qubes-manager-backup-tmp.conf')
@unittest.mock.patch('PyQt4.QtGui.QMessageBox.warning') @unittest.mock.patch('PyQt5.QtWidgets.QMessageBox.warning')
@unittest.mock.patch('os.system') @unittest.mock.patch('os.system')
@unittest.mock.patch('os.remove') @unittest.mock.patch('os.remove')
@unittest.mock.patch('qubesmanager.backup_utils.write_backup_profile') @unittest.mock.patch('qubesmanager.backup_utils.write_backup_profile')
@ -473,7 +468,7 @@ class BackupTest(unittest.TestCase):
self.assertTrue(self.dialog.currentPage() self.assertTrue(self.dialog.currentPage()
is self.dialog.select_dir_page) is self.dialog.select_dir_page)
self._select_location("dom0") self._select_location(self.dom0_name)
self.dialog.dir_line_edit.setText("/home") self.dialog.dir_line_edit.setText("/home")
self.dialog.passphrase_line_edit.setText("pass") self.dialog.passphrase_line_edit.setText("pass")
self.dialog.passphrase_line_edit_verify.setText("pass") self.dialog.passphrase_line_edit_verify.setText("pass")
@ -501,7 +496,7 @@ class BackupTest(unittest.TestCase):
self.assertEqual(mock_warning.call_count, 0, self.assertEqual(mock_warning.call_count, 0,
"Backup succeeded but received warning") "Backup succeeded but received warning")
@unittest.mock.patch('PyQt4.QtGui.QMessageBox.warning') @unittest.mock.patch('PyQt5.QtWidgets.QMessageBox.warning')
@unittest.mock.patch('os.system') @unittest.mock.patch('os.system')
@unittest.mock.patch('os.remove') @unittest.mock.patch('os.remove')
@unittest.mock.patch('qubesmanager.backup_utils.write_backup_profile') @unittest.mock.patch('qubesmanager.backup_utils.write_backup_profile')
@ -513,7 +508,7 @@ class BackupTest(unittest.TestCase):
self.assertTrue(self.dialog.currentPage() self.assertTrue(self.dialog.currentPage()
is self.dialog.select_dir_page) is self.dialog.select_dir_page)
self._select_location("dom0") self._select_location(self.dom0_name)
self.dialog.dir_line_edit.setText("/home") self.dialog.dir_line_edit.setText("/home")
self.dialog.passphrase_line_edit.setText("pass") self.dialog.passphrase_line_edit.setText("pass")
self.dialog.passphrase_line_edit_verify.setText("pass") self.dialog.passphrase_line_edit_verify.setText("pass")
@ -540,7 +535,7 @@ class BackupTest(unittest.TestCase):
self.assertEqual(mock_warning.call_count, 0, self.assertEqual(mock_warning.call_count, 0,
"Backup succeeded but received warning") "Backup succeeded but received warning")
@unittest.mock.patch('PyQt4.QtGui.QMessageBox.warning') @unittest.mock.patch('PyQt5.QtWidgets.QMessageBox.warning')
@unittest.mock.patch('os.system') @unittest.mock.patch('os.system')
@unittest.mock.patch('os.remove') @unittest.mock.patch('os.remove')
@unittest.mock.patch('qubesmanager.backup_utils.write_backup_profile') @unittest.mock.patch('qubesmanager.backup_utils.write_backup_profile')
@ -552,7 +547,7 @@ class BackupTest(unittest.TestCase):
self.assertTrue(self.dialog.currentPage() self.assertTrue(self.dialog.currentPage()
is self.dialog.select_dir_page) is self.dialog.select_dir_page)
self._select_location("dom0") self._select_location(self.dom0_name)
self.dialog.dir_line_edit.setText("/home") self.dialog.dir_line_edit.setText("/home")
self.dialog.passphrase_line_edit.setText("pass") self.dialog.passphrase_line_edit.setText("pass")
self.dialog.passphrase_line_edit_verify.setText("pass") self.dialog.passphrase_line_edit_verify.setText("pass")
@ -578,19 +573,19 @@ class BackupTest(unittest.TestCase):
"Attempted shutdown at failed backup") "Attempted shutdown at failed backup")
self.assertEqual(mock_warn.call_count, 1) self.assertEqual(mock_warn.call_count, 1)
@unittest.mock.patch('PyQt4.QtGui.QMessageBox.warning') @unittest.mock.patch('PyQt5.QtWidgets.QMessageBox.warning')
@unittest.mock.patch('os.system') @unittest.mock.patch('os.system')
@unittest.mock.patch('os.remove') @unittest.mock.patch('os.remove')
@unittest.mock.patch('qubesmanager.backup_utils.write_backup_profile') @unittest.mock.patch('qubesmanager.backup_utils.write_backup_profile')
@unittest.mock.patch('qubesadmin.Qubes.qubesd_call', @unittest.mock.patch('qubesadmin.Qubes.qubesd_call',
return_value=b'backup output') return_value=b'backup output')
def test_28_progress( def test_28_progress(
self, _a, _b, mock_remove, mock_system, mock_warn): self, _a, _b, _mock_remove, _mock_system, _mock_warn):
self._click_next() self._click_next()
self.assertTrue(self.dialog.currentPage() self.assertTrue(self.dialog.currentPage()
is self.dialog.select_dir_page) is self.dialog.select_dir_page)
self._select_location("dom0") self._select_location(self.dom0_name)
self.dialog.dir_line_edit.setText("/home") self.dialog.dir_line_edit.setText("/home")
self.dialog.passphrase_line_edit.setText("pass") self.dialog.passphrase_line_edit.setText("pass")
self.dialog.passphrase_line_edit_verify.setText("pass") self.dialog.passphrase_line_edit_verify.setText("pass")
@ -626,11 +621,11 @@ class BackupTest(unittest.TestCase):
widget.setCurrentIndex(widget.currentIndex() + 1) widget.setCurrentIndex(widget.currentIndex() + 1)
def _click_next(self): def _click_next(self):
next_widget = self.dialog.button(QtGui.QWizard.NextButton) next_widget = self.dialog.button(QtWidgets.QWizard.NextButton)
QtTest.QTest.mouseClick(next_widget, QtCore.Qt.LeftButton) QtTest.QTest.mouseClick(next_widget, QtCore.Qt.LeftButton)
def _click_cancel(self): def _click_cancel(self):
cancel_widget = self.dialog.button(QtGui.QWizard.CancelButton) cancel_widget = self.dialog.button(QtWidgets.QWizard.CancelButton)
QtTest.QTest.mouseClick(cancel_widget, QtCore.Qt.LeftButton) QtTest.QTest.mouseClick(cancel_widget, QtCore.Qt.LeftButton)
def _select_vm(self, name_starts_with): def _select_vm(self, name_starts_with):

View File

@ -21,50 +21,22 @@
# #
import logging.handlers import logging.handlers
import unittest.mock import unittest.mock
import quamash from PyQt5 import QtWidgets
import asyncio
import gc
from PyQt4 import QtGui
from qubesadmin import Qubes from qubesadmin import Qubes
from qubesmanager import backup_utils from qubesmanager import backup_utils
from qubesmanager.tests import init_qtapp
class BackupUtilsTest(unittest.TestCase): class BackupUtilsTest(unittest.TestCase):
def setUp(self): def setUp(self):
super(BackupUtilsTest, self).setUp() super(BackupUtilsTest, self).setUp()
self.qtapp, self.loop = init_qtapp()
self.qapp = Qubes() self.qapp = Qubes()
self.qtapp = QtGui.QApplication(["test", "-style", "cleanlooks"])
self.loop = quamash.QEventLoop(self.qtapp)
def tearDown(self):
# process any pending events before destroying the object
self.qtapp.processEvents()
# queue destroying the QApplication object, do that for any other QT
# related objects here too
self.qtapp.deleteLater()
# process any pending events (other than just queued destroy),
# just in case
self.qtapp.processEvents()
# execute main loop, which will process all events, _
# including just queued destroy_
self.loop.run_until_complete(asyncio.sleep(0))
# at this point it QT objects are destroyed, cleanup all remaining
# references;
# del other QT object here too
self.loop.close()
del self.qtapp
del self.loop
gc.collect()
super(BackupUtilsTest, self).tearDown()
def test_01_fill_apvms(self): def test_01_fill_apvms(self):
dialog = QtGui.QDialog() dialog = QtWidgets.QDialog()
combobox = QtGui.QComboBox() combobox = QtWidgets.QComboBox()
dialog.appvm_combobox = combobox dialog.appvm_combobox = combobox
dialog.qubes_app = self.qapp dialog.qubes_app = self.qapp
@ -87,8 +59,6 @@ class BackupUtilsTest(unittest.TestCase):
"VM list not filled correctly") "VM list not filled correctly")
if __name__ == "__main__": if __name__ == "__main__":
ha_syslog = logging.handlers.SysLogHandler('/dev/log') ha_syslog = logging.handlers.SysLogHandler('/dev/log')
ha_syslog.setFormatter( ha_syslog.setFormatter(

View File

@ -20,25 +20,22 @@
# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. # 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
# #
import logging.handlers import logging.handlers
import quamash
import asyncio
import unittest import unittest
import unittest.mock import unittest.mock
import qubesadmin import qubesadmin
import gc
from PyQt4 import QtGui, QtTest, QtCore from PyQt5 import QtTest, QtCore
from qubesadmin import Qubes from qubesadmin import Qubes
from qubesmanager.tests import init_qtapp
from qubesmanager import create_new_vm from qubesmanager import create_new_vm
class NewVmTest(unittest.TestCase): class NewVmTest(unittest.TestCase):
def setUp(self): def setUp(self):
super(NewVmTest, self).setUp() super(NewVmTest, self).setUp()
self.qtapp, self.loop = init_qtapp()
self.qapp = Qubes() self.qapp = Qubes()
self.qtapp = QtGui.QApplication(["test", "-style", "cleanlooks"])
self.loop = quamash.QEventLoop(self.qtapp)
# mock up the Create VM Thread to avoid changing system state # mock up the Create VM Thread to avoid changing system state
self.patcher_thread = unittest.mock.patch( self.patcher_thread = unittest.mock.patch(
@ -48,40 +45,11 @@ class NewVmTest(unittest.TestCase):
# mock the progress dialog to speed testing up # mock the progress dialog to speed testing up
self.patcher_progress = unittest.mock.patch( self.patcher_progress = unittest.mock.patch(
'PyQt4.QtGui.QProgressDialog') 'PyQt5.QtWidgets.QProgressDialog')
self.mock_progress = self.patcher_progress.start() self.mock_progress = self.patcher_progress.start()
self.addCleanup(self.patcher_progress.stop) self.addCleanup(self.patcher_progress.stop)
self.dialog = create_new_vm.NewVmDlg( self.dialog = create_new_vm.NewVmDlg(self.qtapp, self.qapp)
self.qtapp, self.qapp)
def tearDown(self):
# process any pending events before destroying the object
self.qtapp.processEvents()
# queue destroying the QApplication object, do that for any other QT
# related objects here too
self.qtapp.deleteLater()
self.dialog.deleteLater()
# process any pending events (other than just queued destroy),
# just in case
self.qtapp.processEvents()
# execute main loop, which will process all events, _
# including just queued destroy_
self.loop.run_until_complete(asyncio.sleep(0))
# at this point it QT objects are destroyed, cleanup all remaining
# references;
# del other QT object here too
self.loop.close()
del self.dialog
del self.qtapp
del self.loop
gc.collect()
super(NewVmTest, self).tearDown()
def test_00_window_loads(self): def test_00_window_loads(self):
self.assertGreater(self.dialog.template_vm.count(), 0, self.assertGreater(self.dialog.template_vm.count(), 0,
@ -94,13 +62,13 @@ class NewVmTest(unittest.TestCase):
"Attempted to create VM on cancel") "Attempted to create VM on cancel")
def test_02_create_simple_vm(self): def test_02_create_simple_vm(self):
self.dialog.name.setText("testvm") self.dialog.name.setText("test-vm")
self.__click_ok() self.__click_ok()
self.mock_thread.assert_called_once_with( self.mock_thread.assert_called_once_with(
self.qapp, "AppVM", "testvm", self.qapp, "AppVM", "test-vm",
unittest.mock.ANY, qubesadmin.DEFAULT, unittest.mock.ANY, qubesadmin.DEFAULT,
{'provides_network': False}) {'provides_network': False}, unittest.mock.ANY)
self.mock_thread().start.assert_called_once_with() self.mock_thread().start.assert_called_once_with()
def test_03_label(self): def test_03_label(self):
@ -109,13 +77,13 @@ class NewVmTest(unittest.TestCase):
self.dialog.label.setCurrentIndex(i) self.dialog.label.setCurrentIndex(i)
break break
self.dialog.name.setText("testvm") self.dialog.name.setText("test-vm")
self.__click_ok() self.__click_ok()
self.mock_thread.assert_called_once_with( self.mock_thread.assert_called_once_with(
self.qapp, "AppVM", "testvm", self.qapp, "AppVM", "test-vm",
self.qapp.labels['blue'], qubesadmin.DEFAULT, self.qapp.labels['blue'], qubesadmin.DEFAULT,
unittest.mock.ANY) unittest.mock.ANY, unittest.mock.ANY)
self.mock_thread().start.assert_called_once_with() self.mock_thread().start.assert_called_once_with()
def test_04_template(self): def test_04_template(self):
@ -126,13 +94,13 @@ class NewVmTest(unittest.TestCase):
template = self.dialog.template_vm.currentText() template = self.dialog.template_vm.currentText()
break break
self.dialog.name.setText("testvm") self.dialog.name.setText("test-vm")
self.__click_ok() self.__click_ok()
self.mock_thread.assert_called_once_with( self.mock_thread.assert_called_once_with(
self.qapp, "AppVM", "testvm", self.qapp, "AppVM", "test-vm",
unittest.mock.ANY, template, unittest.mock.ANY, template,
unittest.mock.ANY) unittest.mock.ANY, unittest.mock.ANY)
def test_05_netvm(self): def test_05_netvm(self):
netvm = None netvm = None
@ -142,53 +110,53 @@ class NewVmTest(unittest.TestCase):
netvm = self.dialog.netvm.currentText() netvm = self.dialog.netvm.currentText()
break break
self.dialog.name.setText("testvm") self.dialog.name.setText("test-vm")
self.__click_ok() self.__click_ok()
self.mock_thread.assert_called_once_with( self.mock_thread.assert_called_once_with(
self.qapp, "AppVM", "testvm", self.qapp, "AppVM", "test-vm",
unittest.mock.ANY, unittest.mock.ANY, unittest.mock.ANY, unittest.mock.ANY,
{'netvm': netvm, 'provides_network': False}) {'netvm': netvm, 'provides_network': False}, unittest.mock.ANY)
def test_06_provides_network(self): def test_06_provides_network(self):
self.dialog.provides_network.setChecked(True) self.dialog.provides_network.setChecked(True)
self.dialog.name.setText("testvm") self.dialog.name.setText("test-vm")
self.__click_ok() self.__click_ok()
self.mock_thread.assert_called_once_with( self.mock_thread.assert_called_once_with(
self.qapp, "AppVM", "testvm", self.qapp, "AppVM", "test-vm",
unittest.mock.ANY, unittest.mock.ANY, unittest.mock.ANY, unittest.mock.ANY,
{'provides_network': True}) {'provides_network': True}, unittest.mock.ANY)
@unittest.mock.patch('subprocess.check_call') @unittest.mock.patch('subprocess.check_call')
def test_07_launch_settings(self, mock_call): def test_07_launch_settings(self, mock_call):
self.dialog.launch_settings.setChecked(True) self.dialog.launch_settings.setChecked(True)
self.dialog.name.setText("testvm") self.dialog.name.setText("test-vm")
self.__click_ok() self.__click_ok()
# make sure the thread is not reporting an error # make sure the thread is not reporting an error
self.mock_thread.assert_called_once_with( self.mock_thread.assert_called_once_with(
self.qapp, "AppVM", "testvm", self.qapp, "AppVM", "test-vm",
unittest.mock.ANY, unittest.mock.ANY, unittest.mock.ANY, unittest.mock.ANY,
unittest.mock.ANY) unittest.mock.ANY, unittest.mock.ANY)
self.mock_thread().msg = None self.mock_thread().msg = None
self.dialog.create_finished() self.dialog.create_finished()
mock_call.assert_called_once_with(['qubes-vm-settings', "testvm"]) mock_call.assert_called_once_with(['qubes-vm-settings', "test-vm"])
def test_08_progress_hides(self): def test_08_progress_hides(self):
self.dialog.name.setText("testvm") self.dialog.name.setText("test-vm")
self.__click_ok() self.__click_ok()
self.mock_thread.assert_called_once_with( self.mock_thread.assert_called_once_with(
self.qapp, "AppVM", "testvm", self.qapp, "AppVM", "test-vm",
unittest.mock.ANY, unittest.mock.ANY, unittest.mock.ANY, unittest.mock.ANY,
unittest.mock.ANY) unittest.mock.ANY, unittest.mock.ANY)
# make sure the thread is not reporting an error # make sure the thread is not reporting an error
self.mock_thread().start.assert_called_once_with() self.mock_thread().start.assert_called_once_with()
@ -201,7 +169,7 @@ class NewVmTest(unittest.TestCase):
self.mock_progress().hide.assert_called_once_with() self.mock_progress().hide.assert_called_once_with()
def test_09_standalone_clone(self): def test_09_standalone_clone(self):
self.dialog.name.setText("testvm") self.dialog.name.setText("test-vm")
for i in range(self.dialog.vm_type.count()): for i in range(self.dialog.vm_type.count()):
opt_text = self.dialog.vm_type.itemText(i).lower() opt_text = self.dialog.vm_type.itemText(i).lower()
if "standalone" in opt_text and "template" in opt_text and\ if "standalone" in opt_text and "template" in opt_text and\
@ -211,13 +179,13 @@ class NewVmTest(unittest.TestCase):
self.__click_ok() self.__click_ok()
self.mock_thread.assert_called_once_with( self.mock_thread.assert_called_once_with(
self.qapp, "StandaloneVM", "testvm", self.qapp, "StandaloneVM", "test-vm",
unittest.mock.ANY, unittest.mock.ANY, unittest.mock.ANY, unittest.mock.ANY,
unittest.mock.ANY) unittest.mock.ANY, unittest.mock.ANY)
@unittest.mock.patch('subprocess.check_call') @unittest.mock.patch('subprocess.check_call')
def test_10_standalone_empty(self, mock_call): def test_10_standalone_empty(self, mock_call):
self.dialog.name.setText("testvm") self.dialog.name.setText("test-vm")
for i in range(self.dialog.vm_type.count()): for i in range(self.dialog.vm_type.count()):
opt_text = self.dialog.vm_type.itemText(i).lower() opt_text = self.dialog.vm_type.itemText(i).lower()
if "standalone" in opt_text and\ if "standalone" in opt_text and\
@ -227,19 +195,19 @@ class NewVmTest(unittest.TestCase):
self.__click_ok() self.__click_ok()
self.mock_thread.assert_called_once_with( self.mock_thread.assert_called_once_with(
self.qapp, "StandaloneVM", "testvm", self.qapp, "StandaloneVM", "test-vm",
unittest.mock.ANY, None, unittest.mock.ANY, None,
unittest.mock.ANY) unittest.mock.ANY, unittest.mock.ANY)
self.mock_thread().msg = None self.mock_thread().msg = None
self.dialog.create_finished() self.dialog.create_finished()
mock_call.assert_called_once_with(['qubes-vm-boot-from-device', mock_call.assert_called_once_with(['qubes-vm-boot-from-device',
'testvm']) 'test-vm'])
@unittest.mock.patch('subprocess.check_call') @unittest.mock.patch('subprocess.check_call')
def test_11_standalone_empty_not_install(self, mock_call): def test_11_standalone_empty_not_install(self, mock_call):
self.dialog.name.setText("testvm") self.dialog.name.setText("test-vm")
for i in range(self.dialog.vm_type.count()): for i in range(self.dialog.vm_type.count()):
opt_text = self.dialog.vm_type.itemText(i).lower() opt_text = self.dialog.vm_type.itemText(i).lower()
@ -252,9 +220,9 @@ class NewVmTest(unittest.TestCase):
self.__click_ok() self.__click_ok()
self.mock_thread.assert_called_once_with( self.mock_thread.assert_called_once_with(
self.qapp, "StandaloneVM", "testvm", self.qapp, "StandaloneVM", "test-vm",
unittest.mock.ANY, None, unittest.mock.ANY, None,
unittest.mock.ANY) unittest.mock.ANY, unittest.mock.ANY)
self.mock_thread().msg = None self.mock_thread().msg = None
self.dialog.create_finished() self.dialog.create_finished()

View File

@ -20,24 +20,21 @@
# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. # 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
# #
import logging.handlers import logging.handlers
import quamash
import asyncio
import unittest import unittest
import unittest.mock import unittest.mock
import gc
from PyQt4 import QtGui, QtTest, QtCore from PyQt5 import QtTest, QtCore, QtWidgets
from qubesadmin import Qubes from qubesadmin import Qubes
from qubesmanager.tests import init_qtapp
import qubesmanager.global_settings as global_settings import qubesmanager.global_settings as global_settings
class GlobalSettingsTest(unittest.TestCase): class GlobalSettingsTest(unittest.TestCase):
def setUp(self): def setUp(self):
super(GlobalSettingsTest, self).setUp() super(GlobalSettingsTest, self).setUp()
self.qtapp, self.loop = init_qtapp()
self.qapp = Qubes() self.qapp = Qubes()
self.qtapp = QtGui.QApplication(["test", "-style", "cleanlooks"])
self.loop = quamash.QEventLoop(self.qtapp)
self.dialog = global_settings.GlobalSettingsWindow(self.qtapp, self.dialog = global_settings.GlobalSettingsWindow(self.qtapp,
self.qapp) self.qapp)
@ -46,33 +43,6 @@ class GlobalSettingsTest(unittest.TestCase):
self.setattr_mock = self.setattr_patcher.start() self.setattr_mock = self.setattr_patcher.start()
self.addCleanup(self.setattr_patcher.stop) self.addCleanup(self.setattr_patcher.stop)
def tearDown(self):
# process any pending events before destroying the object
self.qtapp.processEvents()
# queue destroying the QApplication object, do that for any other QT
# related objects here too
self.qtapp.deleteLater()
self.dialog.deleteLater()
# process any pending events (other than just queued destroy),
# just in case
self.qtapp.processEvents()
# execute main loop, which will process all events, _
# including just queued destroy_
self.loop.run_until_complete(asyncio.sleep(0))
# at this point it QT objects are destroyed, cleanup all remaining
# references;
# del other QT object here too
self.loop.close()
del self.dialog
del self.qtapp
del self.loop
gc.collect()
super(GlobalSettingsTest, self).tearDown()
def test_00_settings_started(self): def test_00_settings_started(self):
# non-empty drop-downs # non-empty drop-downs
self.assertNotEqual( self.assertNotEqual(
@ -152,8 +122,7 @@ class GlobalSettingsTest(unittest.TestCase):
dom0_updates = self.qapp.domains[ dom0_updates = self.qapp.domains[
'dom0'].features['service.qubes-update-check'] 'dom0'].features['service.qubes-update-check']
except KeyError: except KeyError:
self.skipTest("check_updates_dom0 property not implemented") dom0_updates = True
return
self.assertEqual(bool(dom0_updates), self.assertEqual(bool(dom0_updates),
self.dialog.updates_dom0.isChecked(), self.dialog.updates_dom0.isChecked(),
@ -290,8 +259,8 @@ class GlobalSettingsTest(unittest.TestCase):
self.setattr_mock.assert_called_once_with('check_updates_vm', self.setattr_mock.assert_called_once_with('check_updates_vm',
not current_state) not current_state)
@unittest.mock.patch("PyQt4.QtGui.QMessageBox.question", @unittest.mock.patch("PyQt5.QtWidgets.QMessageBox.question",
return_value=QtGui.QMessageBox.Yes) return_value=QtWidgets.QMessageBox.Yes)
@unittest.mock.patch('qubesadmin.features.Features.__setitem__') @unittest.mock.patch('qubesadmin.features.Features.__setitem__')
def test_72_set_all_vms_true(self, mock_features, msgbox): def test_72_set_all_vms_true(self, mock_features, msgbox):
@ -308,8 +277,8 @@ class GlobalSettingsTest(unittest.TestCase):
self.assertListEqual(call_list_expected, self.assertListEqual(call_list_expected,
mock_features.call_args_list) mock_features.call_args_list)
@unittest.mock.patch("PyQt4.QtGui.QMessageBox.question", @unittest.mock.patch("PyQt5.QtWidgets.QMessageBox.question",
return_value=QtGui.QMessageBox.Yes) return_value=QtWidgets.QMessageBox.Yes)
@unittest.mock.patch('qubesadmin.features.Features.__setitem__') @unittest.mock.patch('qubesadmin.features.Features.__setitem__')
def test_73_set_all_vms_false(self, mock_features, msgbox): def test_73_set_all_vms_false(self, mock_features, msgbox):

View File

@ -22,66 +22,36 @@
import asyncio import asyncio
import contextlib import contextlib
import logging.handlers import logging.handlers
import sys
import unittest import unittest
import unittest.mock import unittest.mock
import gc
import subprocess import subprocess
import datetime import datetime
import time import time
import quamash from PyQt5 import QtTest, QtCore, QtWidgets
from PyQt4 import QtGui, QtTest, QtCore
from qubesadmin import Qubes, events, exc from qubesadmin import Qubes, events, exc
import qubesmanager.qube_manager as qube_manager import qubesmanager.qube_manager as qube_manager
from qubesmanager.tests import init_qtapp
class QubeManagerTest(unittest.TestCase): class QubeManagerTest(unittest.TestCase):
def setUp(self): def setUp(self):
super(QubeManagerTest, self).setUp() super(QubeManagerTest, self).setUp()
self.qtapp, self.loop = init_qtapp()
self.mock_qprogress = unittest.mock.patch('PyQt4.QtGui.QProgressDialog') self.mock_qprogress = unittest.mock.patch(
'PyQt5.QtWidgets.QProgressDialog')
self.mock_qprogress.start() self.mock_qprogress.start()
self.addCleanup(self.mock_qprogress.stop) self.addCleanup(self.mock_qprogress.stop)
self.qapp = Qubes() self.qapp = Qubes()
self.qtapp = QtGui.QApplication(["test", "-style", "cleanlooks"])
self.dispatcher = events.EventsDispatcher(self.qapp) self.dispatcher = events.EventsDispatcher(self.qapp)
self.loop = quamash.QEventLoop(self.qtapp)
self.dialog = qube_manager.VmManagerWindow( self.dialog = qube_manager.VmManagerWindow(
self.qtapp, self.qapp, self.dispatcher) self.qtapp, self.qapp, self.dispatcher)
def tearDown(self):
# process any pending events before destroying the object
self.qtapp.processEvents()
# queue destroying the QApplication object, do that for any other QT
# related objects here too
self.qtapp.deleteLater()
self.dialog.deleteLater()
# process any pending events (other than just queued destroy),
# just in case
self.qtapp.processEvents()
# execute main loop, which will process all events, _
# including just queued destroy_
self.loop.run_until_complete(asyncio.sleep(0))
# at this point it QT objects are destroyed, cleanup all remaining
# references;
# del other QT object here too
self.loop.close()
del self.dialog
del self.qtapp
del self.loop
gc.collect()
super(QubeManagerTest, self).tearDown()
def test_000_window_loads(self): def test_000_window_loads(self):
self.assertTrue(self.dialog.table is not None, "Window did not load") self.assertTrue(self.dialog.table is not None, "Window did not load")
@ -207,6 +177,10 @@ class QubeManagerTest(unittest.TestCase):
vm = self._get_table_item(row, "Name").vm vm = self._get_table_item(row, "Name").vm
def_dispvm_item = self._get_table_item(row, "Default DispVM") def_dispvm_item = self._get_table_item(row, "Default DispVM")
if vm.property_is_default("default_dispvm"):
def_dispvm_value = "default ({})".format(
self.qapp.default_dispvm)
else:
def_dispvm_value = getattr(vm, "default_dispvm", None) def_dispvm_value = getattr(vm, "default_dispvm", None)
self.assertEqual( self.assertEqual(
@ -262,8 +236,9 @@ class QubeManagerTest(unittest.TestCase):
mock_settings.side_effect = ( mock_settings.side_effect = (
lambda x, *args, **kwargs: settings_result_dict.get(x)) lambda x, *args, **kwargs: settings_result_dict.get(x))
with unittest.mock.patch('PyQt4.QtCore.QSettings.value', mock_settings),\ with unittest.mock.patch('PyQt5.QtCore.QSettings.value',
unittest.mock.patch('PyQt4.QtGui.QMessageBox.warning')\ mock_settings),\
unittest.mock.patch('PyQt5.QtWidgets.QMessageBox.warning')\
as mock_warning: as mock_warning:
self.dialog = qube_manager.VmManagerWindow( self.dialog = qube_manager.VmManagerWindow(
self.qtapp, self.qapp, self.dispatcher) self.qtapp, self.qapp, self.dispatcher)
@ -271,10 +246,12 @@ class QubeManagerTest(unittest.TestCase):
def test_100_sorting(self): def test_100_sorting(self):
self.dialog.table.sortByColumn(self.dialog.columns_indices["Template"]) self.dialog.table.sortByColumn(self.dialog.columns_indices["Template"],
QtCore.Qt.AscendingOrder)
self.__check_sorting("Template") self.__check_sorting("Template")
self.dialog.table.sortByColumn(self.dialog.columns_indices["Name"]) self.dialog.table.sortByColumn(self.dialog.columns_indices["Name"],
QtCore.Qt.AscendingOrder)
self.__check_sorting("Name") self.__check_sorting("Name")
@unittest.mock.patch('qubesmanager.qube_manager.QtCore.QSettings.setValue') @unittest.mock.patch('qubesmanager.qube_manager.QtCore.QSettings.setValue')
@ -357,8 +334,8 @@ class QubeManagerTest(unittest.TestCase):
self.assertFalse(self.dialog.action_set_keyboard_layout.isEnabled()) self.assertFalse(self.dialog.action_set_keyboard_layout.isEnabled())
@unittest.mock.patch("PyQt4.QtGui.QMessageBox.question", @unittest.mock.patch("PyQt5.QtWidgets.QMessageBox.question",
return_value=QtGui.QMessageBox.Yes) return_value=QtWidgets.QMessageBox.Yes)
def test_207_update_vm_not_running(self, _): def test_207_update_vm_not_running(self, _):
selected_vm = self._select_templatevm(running=False) selected_vm = self._select_templatevm(running=False)
self.assertIsNotNone(selected_vm, "No valid template VM found") self.assertIsNotNone(selected_vm, "No valid template VM found")
@ -387,7 +364,7 @@ class QubeManagerTest(unittest.TestCase):
mock_update.assert_called_once_with(selected_vm) mock_update.assert_called_once_with(selected_vm)
mock_update().start.assert_called_once_with() mock_update().start.assert_called_once_with()
@unittest.mock.patch("PyQt4.QtGui.QInputDialog.getText", @unittest.mock.patch("PyQt5.QtWidgets.QInputDialog.getText",
return_value=("command to run", True)) return_value=("command to run", True))
def test_209_run_command_in_vm(self, _): def test_209_run_command_in_vm(self, _):
selected_vm = self._select_non_admin_vm() selected_vm = self._select_non_admin_vm()
@ -408,7 +385,7 @@ class QubeManagerTest(unittest.TestCase):
self.assertFalse(self.dialog.action_run_command_in_vm.isEnabled(), self.assertFalse(self.dialog.action_run_command_in_vm.isEnabled(),
"Should not be able to run commands for dom0") "Should not be able to run commands for dom0")
@unittest.mock.patch("PyQt4.QtGui.QMessageBox.warning") @unittest.mock.patch("PyQt5.QtWidgets.QMessageBox.warning")
def test_211_pausevm(self, mock_warn): def test_211_pausevm(self, mock_warn):
selected_vm = self._select_non_admin_vm(running=True) selected_vm = self._select_non_admin_vm(running=True)
@ -446,9 +423,9 @@ class QubeManagerTest(unittest.TestCase):
self._select_non_admin_vm(running=True) self._select_non_admin_vm(running=True)
self.assertFalse(self.dialog.action_resumevm.isEnabled()) self.assertFalse(self.dialog.action_resumevm.isEnabled())
@unittest.mock.patch("PyQt4.QtGui.QMessageBox.question", @unittest.mock.patch("PyQt5.QtWidgets.QMessageBox.question",
return_value=QtGui.QMessageBox.Yes) return_value=QtWidgets.QMessageBox.Yes)
@unittest.mock.patch('PyQt4.QtCore.QTimer.singleShot') @unittest.mock.patch('PyQt5.QtCore.QTimer.singleShot')
@unittest.mock.patch('qubesmanager.qube_manager.VmShutdownMonitor') @unittest.mock.patch('qubesmanager.qube_manager.VmShutdownMonitor')
def test_214_shutdownvm(self, mock_monitor, mock_timer, _): def test_214_shutdownvm(self, mock_monitor, mock_timer, _):
selected_vm = self._select_non_admin_vm(running=True) selected_vm = self._select_non_admin_vm(running=True)
@ -484,20 +461,20 @@ class QubeManagerTest(unittest.TestCase):
self.assertFalse(self.dialog.action_removevm.isEnabled()) self.assertFalse(self.dialog.action_removevm.isEnabled())
@unittest.mock.patch("PyQt4.QtGui.QMessageBox") @unittest.mock.patch("PyQt5.QtWidgets.QMessageBox")
@unittest.mock.patch('qubesadmin.utils.vm_dependencies') @unittest.mock.patch('qubesadmin.utils.vm_dependencies')
def test_218_remove_vm_dependencies(self, mock_dependencies, mock_msgbox): def test_218_remove_vm_dependencies(self, mock_dependencies, mock_msgbox):
action = self.dialog.action_removevm action = self.dialog.action_removevm
mock_vm = unittest.mock.Mock(spec=['name'], mock_vm = unittest.mock.Mock(spec=['name'],
**{'name.return_value': 'testvm'}) **{'name.return_value': 'test-vm'})
mock_dependencies.return_value = [(mock_vm, "test_prop")] mock_dependencies.return_value = [(mock_vm, "test_prop")]
action.trigger() action.trigger()
mock_msgbox().show.assert_called_with() mock_msgbox().show.assert_called_with()
@unittest.mock.patch('PyQt4.QtGui.QMessageBox.warning') @unittest.mock.patch('PyQt5.QtWidgets.QMessageBox.warning')
@unittest.mock.patch("PyQt4.QtGui.QInputDialog.getText") @unittest.mock.patch("PyQt5.QtWidgets.QInputDialog.getText")
@unittest.mock.patch('qubesadmin.utils.vm_dependencies') @unittest.mock.patch('qubesadmin.utils.vm_dependencies')
def test_219_remove_vm_no_depencies( def test_219_remove_vm_no_depencies(
self, mock_dependencies, mock_input, mock_warning): self, mock_dependencies, mock_input, mock_warning):
@ -531,10 +508,10 @@ class QubeManagerTest(unittest.TestCase):
self._select_non_admin_vm(running=False) self._select_non_admin_vm(running=False)
self.assertFalse(self.dialog.action_restartvm.isEnabled()) self.assertFalse(self.dialog.action_restartvm.isEnabled())
@unittest.mock.patch('PyQt4.QtCore.QTimer.singleShot') @unittest.mock.patch('PyQt5.QtCore.QTimer.singleShot')
@unittest.mock.patch('qubesmanager.qube_manager.VmShutdownMonitor') @unittest.mock.patch('qubesmanager.qube_manager.VmShutdownMonitor')
@unittest.mock.patch("PyQt4.QtGui.QMessageBox.question", @unittest.mock.patch("PyQt5.QtWidgets.QMessageBox.question",
return_value=QtGui.QMessageBox.Yes) return_value=QtWidgets.QMessageBox.Yes)
def test_221_restartvm_running_vm(self, _msgbox, mock_monitor, _qtimer): def test_221_restartvm_running_vm(self, _msgbox, mock_monitor, _qtimer):
selected_vm = self._select_non_admin_vm(running=True) selected_vm = self._select_non_admin_vm(running=True)
@ -550,8 +527,8 @@ class QubeManagerTest(unittest.TestCase):
unittest.mock.ANY, True, unittest.mock.ANY) unittest.mock.ANY, True, unittest.mock.ANY)
@unittest.mock.patch('qubesmanager.qube_manager.StartVMThread') @unittest.mock.patch('qubesmanager.qube_manager.StartVMThread')
@unittest.mock.patch("PyQt4.QtGui.QMessageBox.question", @unittest.mock.patch("PyQt5.QtWidgets.QMessageBox.question",
return_value=QtGui.QMessageBox.Yes) return_value=QtWidgets.QMessageBox.Yes)
def test_222_restartvm_shutdown_meantime(self, _, mock_thread): def test_222_restartvm_shutdown_meantime(self, _, mock_thread):
selected_vm = self._select_non_admin_vm(running=True) selected_vm = self._select_non_admin_vm(running=True)
@ -577,8 +554,8 @@ class QubeManagerTest(unittest.TestCase):
self.dialog.clear_threads) self.dialog.clear_threads)
mock_thread().start.assert_called_once_with() mock_thread().start.assert_called_once_with()
@unittest.mock.patch("PyQt4.QtGui.QMessageBox.question", @unittest.mock.patch("PyQt5.QtWidgets.QMessageBox.question",
return_value=QtGui.QMessageBox.Yes) return_value=QtWidgets.QMessageBox.Yes)
@unittest.mock.patch('qubesmanager.qube_manager.UpdateVMThread') @unittest.mock.patch('qubesmanager.qube_manager.UpdateVMThread')
def test_224_updatevm_halted(self, mock_thread, _): def test_224_updatevm_halted(self, mock_thread, _):
selected_vm = self._select_non_admin_vm(running=False) selected_vm = self._select_non_admin_vm(running=False)
@ -590,8 +567,8 @@ class QubeManagerTest(unittest.TestCase):
self.dialog.clear_threads) self.dialog.clear_threads)
mock_thread().start.assert_called_once_with() mock_thread().start.assert_called_once_with()
@unittest.mock.patch("PyQt4.QtGui.QMessageBox.question", @unittest.mock.patch("PyQt5.QtWidgets.QMessageBox.question",
return_value=QtGui.QMessageBox.Yes) return_value=QtWidgets.QMessageBox.Yes)
def test_224_killvm(self, _): def test_224_killvm(self, _):
selected_vm = self._select_non_admin_vm(running=True) selected_vm = self._select_non_admin_vm(running=True)
action = self.dialog.action_killvm action = self.dialog.action_killvm
@ -600,8 +577,8 @@ class QubeManagerTest(unittest.TestCase):
action.trigger() action.trigger()
mock_kill.assert_called_once_with() mock_kill.assert_called_once_with()
@unittest.mock.patch("PyQt4.QtGui.QMessageBox.question", @unittest.mock.patch("PyQt5.QtWidgets.QMessageBox.question",
return_value=QtGui.QMessageBox.Cancel) return_value=QtWidgets.QMessageBox.Cancel)
def test_225_killvm_cancel(self, _): def test_225_killvm_cancel(self, _):
selected_vm = self._select_non_admin_vm(running=True) selected_vm = self._select_non_admin_vm(running=True)
action = self.dialog.action_killvm action = self.dialog.action_killvm
@ -659,7 +636,7 @@ class QubeManagerTest(unittest.TestCase):
mock_subprocess.assert_called_once_with('qubes-template-manager') mock_subprocess.assert_called_once_with('qubes-template-manager')
@unittest.mock.patch('qubesmanager.common_threads.CloneVMThread') @unittest.mock.patch('qubesmanager.common_threads.CloneVMThread')
@unittest.mock.patch('PyQt4.QtGui.QInputDialog.getText') @unittest.mock.patch('PyQt5.QtWidgets.QInputDialog.getText')
def test_232_clonevm(self, mock_input, mock_thread): def test_232_clonevm(self, mock_input, mock_thread):
action = self.dialog.action_clonevm action = self.dialog.action_clonevm
@ -714,7 +691,7 @@ class QubeManagerTest(unittest.TestCase):
"Incorrect number of vms shown for cleared search box") "Incorrect number of vms shown for cleared search box")
def test_235_hide_show_toolbars(self): def test_235_hide_show_toolbars(self):
with unittest.mock.patch('PyQt4.QtCore.QSettings.setValue')\ with unittest.mock.patch('PyQt5.QtCore.QSettings.setValue')\
as mock_setvalue: as mock_setvalue:
self.dialog.action_menubar.trigger() self.dialog.action_menubar.trigger()
mock_setvalue.assert_called_with('view/menubar_visible', False) mock_setvalue.assert_called_with('view/menubar_visible', False)
@ -741,8 +718,8 @@ class QubeManagerTest(unittest.TestCase):
self.assertEqual(expected_number, actual_number, self.assertEqual(expected_number, actual_number,
"Incorrect number of vms shown for cleared search box") "Incorrect number of vms shown for cleared search box")
@unittest.mock.patch('PyQt4.QtGui.QMessageBox.information') @unittest.mock.patch('PyQt5.QtWidgets.QMessageBox.information')
@unittest.mock.patch('PyQt4.QtGui.QMessageBox.warning') @unittest.mock.patch('PyQt5.QtWidgets.QMessageBox.warning')
def test_300_clear_threads(self, mock_warning, mock_info): def test_300_clear_threads(self, mock_warning, mock_info):
mock_thread_finished_ok = unittest.mock.Mock( mock_thread_finished_ok = unittest.mock.Mock(
spec=['isFinished', 'msg', 'msg_is_success'], spec=['isFinished', 'msg', 'msg_is_success'],
@ -791,10 +768,10 @@ class QubeManagerTest(unittest.TestCase):
def test_400_event_domain_added(self): def test_400_event_domain_added(self):
number_of_vms = self.dialog.table.rowCount() number_of_vms = self.dialog.table.rowCount()
self.addCleanup(subprocess.call, ["qvm-remove", "-f", "testvm"]) self.addCleanup(subprocess.call, ["qvm-remove", "-f", "test-vm"])
self._run_command_and_process_events( self._run_command_and_process_events(
["qvm-create", "--label", "red", "testvm"]) ["qvm-create", "--label", "red", "test-vm"])
# a single row was added to the table # a single row was added to the table
self.assertEqual(self.dialog.table.rowCount(), number_of_vms + 1) self.assertEqual(self.dialog.table.rowCount(), number_of_vms + 1)
@ -815,26 +792,26 @@ class QubeManagerTest(unittest.TestCase):
# try opening settings for the added vm # try opening settings for the added vm
for row in range(self.dialog.table.rowCount()): for row in range(self.dialog.table.rowCount()):
name = self._get_table_item(row, "Name") name = self._get_table_item(row, "Name")
if name.text() == "testvm": if name.text() == "test-vm":
self.dialog.table.setCurrentItem(name) self.dialog.table.setCurrentItem(name)
break break
with unittest.mock.patch('qubesmanager.settings.VMSettingsWindow')\ with unittest.mock.patch('qubesmanager.settings.VMSettingsWindow')\
as mock_settings: as mock_settings:
self.dialog.action_settings.trigger() self.dialog.action_settings.trigger()
mock_settings.assert_called_once_with( mock_settings.assert_called_once_with(
self.qapp.domains["testvm"], self.qtapp, "basic") self.qapp.domains["test-vm"], self.qtapp, "basic")
def test_401_event_domain_removed(self): def test_401_event_domain_removed(self):
initial_vms = self._create_set_of_current_vms() initial_vms = self._create_set_of_current_vms()
self._run_command_and_process_events( self._run_command_and_process_events(
["qvm-create", "--label", "red", "testvm"]) ["qvm-create", "--label", "red", "test-vm"])
current_vms = self._create_set_of_current_vms() current_vms = self._create_set_of_current_vms()
self.assertEqual(len(initial_vms) + 1, len(current_vms)) self.assertEqual(len(initial_vms) + 1, len(current_vms))
self._run_command_and_process_events( self._run_command_and_process_events(
["qvm-remove", "--force", "testvm"]) ["qvm-remove", "--force", "test-vm"])
current_vms = self._create_set_of_current_vms() current_vms = self._create_set_of_current_vms()
self.assertEqual(initial_vms, current_vms) self.assertEqual(initial_vms, current_vms)
@ -1210,12 +1187,13 @@ class QubeManagerTest(unittest.TestCase):
events events
:param command: list of strings, containing the command and all its :param command: list of strings, containing the command and all its
parameters parameters
:param timeout: default 20 seconds :param timeout: default 5 seconds
:return: :return:
""" """
asyncio.set_event_loop(self.loop) asyncio.set_event_loop(self.loop)
future1 = asyncio.ensure_future(self.dispatcher.listen_for_events()) future1 = asyncio.ensure_future(self.dispatcher.listen_for_events())
self.loop.run_until_complete(asyncio.sleep(0))
future2 = asyncio.create_subprocess_exec(*command, future2 = asyncio.create_subprocess_exec(*command,
stdout=subprocess.DEVNULL, stdout=subprocess.DEVNULL,
stderr=subprocess.DEVNULL) stderr=subprocess.DEVNULL)
@ -1422,8 +1400,8 @@ class QubeManagerThreadTest(unittest.TestCase):
class VMShutdownMonitorTest(unittest.TestCase): class VMShutdownMonitorTest(unittest.TestCase):
@unittest.mock.patch('PyQt4.QtGui.QMessageBox.question') @unittest.mock.patch('PyQt5.QtWidgets.QMessageBox')
@unittest.mock.patch('PyQt4.QtCore.QTimer') @unittest.mock.patch('PyQt5.QtCore.QTimer')
def test_01_vm_shutdown_correct(self, mock_timer, mock_question): def test_01_vm_shutdown_correct(self, mock_timer, mock_question):
mock_vm = unittest.mock.Mock() mock_vm = unittest.mock.Mock()
mock_vm.is_running.return_value = False mock_vm.is_running.return_value = False
@ -1437,10 +1415,12 @@ class VMShutdownMonitorTest(unittest.TestCase):
self.assertEqual(mock_timer.call_count, 0) self.assertEqual(mock_timer.call_count, 0)
monitor.restart_vm_if_needed.assert_called_once_with() monitor.restart_vm_if_needed.assert_called_once_with()
@unittest.mock.patch('PyQt4.QtGui.QMessageBox.question', @unittest.mock.patch('PyQt5.QtWidgets.QMessageBox')
return_value=1) @unittest.mock.patch('PyQt5.QtCore.QTimer.singleShot')
@unittest.mock.patch('PyQt4.QtCore.QTimer.singleShot')
def test_02_vm_not_shutdown_wait(self, mock_timer, mock_question): def test_02_vm_not_shutdown_wait(self, mock_timer, mock_question):
mock_question().clickedButton.return_value = 1
mock_question().addButton.return_value = 0
mock_vm = unittest.mock.Mock() mock_vm = unittest.mock.Mock()
mock_vm.is_running.return_value = True mock_vm.is_running.return_value = True
mock_vm.start_time = datetime.datetime.now().timestamp() - 3000 mock_vm.start_time = datetime.datetime.now().timestamp() - 3000
@ -1450,13 +1430,14 @@ class VMShutdownMonitorTest(unittest.TestCase):
monitor.check_if_vm_has_shutdown() monitor.check_if_vm_has_shutdown()
self.assertEqual(mock_question.call_count, 1)
self.assertEqual(mock_timer.call_count, 1) self.assertEqual(mock_timer.call_count, 1)
@unittest.mock.patch('PyQt4.QtGui.QMessageBox.question', @unittest.mock.patch('PyQt5.QtWidgets.QMessageBox')
return_value=0) @unittest.mock.patch('PyQt5.QtCore.QTimer.singleShot')
@unittest.mock.patch('PyQt4.QtCore.QTimer.singleShot')
def test_03_vm_kill(self, mock_timer, mock_question): def test_03_vm_kill(self, mock_timer, mock_question):
mock_question().clickedButton.return_value = 1
mock_question().addButton.return_value = 1
mock_vm = unittest.mock.Mock() mock_vm = unittest.mock.Mock()
mock_vm.is_running.return_value = True mock_vm.is_running.return_value = True
mock_vm.start_time = datetime.datetime.now().timestamp() - 3000 mock_vm.start_time = datetime.datetime.now().timestamp() - 3000
@ -1467,14 +1448,12 @@ class VMShutdownMonitorTest(unittest.TestCase):
monitor.check_if_vm_has_shutdown() monitor.check_if_vm_has_shutdown()
self.assertEqual(mock_question.call_count, 1)
self.assertEqual(mock_timer.call_count, 0) self.assertEqual(mock_timer.call_count, 0)
mock_vm.kill.assert_called_once_with() mock_vm.kill.assert_called_once_with()
monitor.restart_vm_if_needed.assert_called_once_with() monitor.restart_vm_if_needed.assert_called_once_with()
@unittest.mock.patch('PyQt4.QtGui.QMessageBox.question', @unittest.mock.patch('PyQt5.QtWidgets.QMessageBox')
return_value=0) @unittest.mock.patch('PyQt5.QtCore.QTimer.singleShot')
@unittest.mock.patch('PyQt4.QtCore.QTimer.singleShot')
def test_04_check_later(self, mock_timer, mock_question): def test_04_check_later(self, mock_timer, mock_question):
mock_vm = unittest.mock.Mock() mock_vm = unittest.mock.Mock()
mock_vm.is_running.return_value = True mock_vm.is_running.return_value = True

View File

@ -23,106 +23,87 @@ import logging.handlers
import unittest import unittest
import unittest.mock import unittest.mock
import gc from PyQt5 import QtTest, QtCore
import quamash
import asyncio
from PyQt4 import QtGui, QtTest, QtCore
from qubesadmin import Qubes from qubesadmin import Qubes
import qubesmanager.settings as vm_settings import qubesmanager.settings as vm_settings
from qubesmanager.tests import init_qtapp
class VMSettingsTest(unittest.TestCase): class VMSettingsTest(unittest.TestCase):
def setUp(self): def setUp(self):
super(VMSettingsTest, self).setUp() super(VMSettingsTest, self).setUp()
self.qtapp, self.loop = init_qtapp()
self.mock_qprogress = unittest.mock.patch('PyQt4.QtGui.QProgressDialog') self.mock_qprogress = unittest.mock.patch(
'PyQt5.QtWidgets.QProgressDialog')
self.mock_qprogress.start() self.mock_qprogress.start()
self.addCleanup(self.mock_qprogress.stop) self.addCleanup(self.mock_qprogress.stop)
self.qapp = Qubes() self.qapp = Qubes()
self.qtapp = QtGui.QApplication(["test", "-style", "cleanlooks"])
self.loop = quamash.QEventLoop(self.qtapp) if "test-vm" in self.qapp.domains:
del self.qapp.domains["test-vm"]
def tearDown(self): def tearDown(self):
del self.qapp.domains["testvm"] if "test-vm" in self.qapp.domains:
del self.qapp.domains["test-vm"]
# process any pending events before destroying the object
self.qtapp.processEvents()
# queue destroying the QApplication object, do that for any other QT
# related objects here too
self.dialog.deleteLater()
self.qtapp.deleteLater()
# process any pending events (other than just queued destroy),
# just in case
self.qtapp.processEvents()
self.qtapp.processEvents()
self.qtapp.processEvents()
# execute main loop, which will process all events, _
# including just queued destroy_
self.loop.run_until_complete(asyncio.sleep(0))
# at this point it QT objects are destroyed, cleanup all remaining
# references;
# del other QT object here too
self.loop.close()
del self.dialog
del self.qtapp
del self.loop
gc.collect()
super(VMSettingsTest, self).tearDown() super(VMSettingsTest, self).tearDown()
def test_00_load_correct_tab(self): def test_00_load_correct_tab(self):
self.vm = self.qapp.add_new_vm("AppVM", "testvm", "red") self.vm = self.qapp.add_new_vm("AppVM", "test-vm", "red")
self.dialog = vm_settings.VMSettingsWindow( self.dialog = vm_settings.VMSettingsWindow(
self.vm, self.qtapp, "basic") self.vm, qapp=self.qtapp, qubesapp=self.qapp, init_page="basic")
self.assertTrue( self.assertTrue(
self.dialog.tabWidget.currentWidget() is self.dialog.basic_tab) self.dialog.tabWidget.currentWidget() is self.dialog.basic_tab)
self.dialog.deleteLater() self.dialog.deleteLater()
self.qtapp.processEvents()
self.dialog = vm_settings.VMSettingsWindow( self.dialog = vm_settings.VMSettingsWindow(
self.vm, self.qtapp, "advanced") self.vm, qapp=self.qtapp, qubesapp=self.qapp, init_page="advanced")
self.assertTrue( self.assertTrue(
self.dialog.tabWidget.currentWidget() is self.dialog.advanced_tab) self.dialog.tabWidget.currentWidget() is self.dialog.advanced_tab)
self.dialog.deleteLater() self.dialog.deleteLater()
self.qtapp.processEvents()
self.dialog = vm_settings.VMSettingsWindow( self.dialog = vm_settings.VMSettingsWindow(
self.vm, self.qtapp, "firewall") self.vm, qapp=self.qtapp, qubesapp=self.qapp, init_page="firewall")
self.assertTrue( self.assertTrue(
self.dialog.tabWidget.currentWidget() is self.dialog.firewall_tab) self.dialog.tabWidget.currentWidget() is self.dialog.firewall_tab)
self.dialog.deleteLater() self.dialog.deleteLater()
self.qtapp.processEvents()
self.dialog = vm_settings.VMSettingsWindow( self.dialog = vm_settings.VMSettingsWindow(
self.vm, self.qtapp, "devices") self.vm, qapp=self.qtapp, qubesapp=self.qapp, init_page="devices")
self.assertTrue( self.assertTrue(
self.dialog.tabWidget.currentWidget() is self.dialog.devices_tab) self.dialog.tabWidget.currentWidget() is self.dialog.devices_tab)
self.dialog.deleteLater() self.dialog.deleteLater()
self.qtapp.processEvents()
self.dialog = vm_settings.VMSettingsWindow( self.dialog = vm_settings.VMSettingsWindow(
self.vm, self.qtapp, "applications") self.vm, qapp=self.qtapp, qubesapp=self.qapp,
init_page="applications")
self.assertTrue( self.assertTrue(
self.dialog.tabWidget.currentWidget() is self.dialog.apps_tab) self.dialog.tabWidget.currentWidget() is self.dialog.apps_tab)
self.dialog.deleteLater() self.dialog.deleteLater()
self.qtapp.processEvents()
self.dialog = vm_settings.VMSettingsWindow( self.dialog = vm_settings.VMSettingsWindow(
self.vm, self.qtapp, "services") self.vm, qapp=self.qtapp, qubesapp=self.qapp, init_page="services")
self.assertTrue( self.assertTrue(
self.dialog.tabWidget.currentWidget() is self.dialog.services_tab) self.dialog.tabWidget.currentWidget() is self.dialog.services_tab)
self.dialog.deleteLater() self.dialog.deleteLater()
self.qtapp.processEvents()
def test_01_basic_tab_default(self): def test_01_basic_tab_default(self):
self.vm = self.qapp.add_new_vm("AppVM", "testvm", "blue") self.vm = self.qapp.add_new_vm("AppVM", "test-vm", "blue")
# set the vm to have a default template and netvm # set the vm to have a default template and netvm
self.dialog = vm_settings.VMSettingsWindow( self.dialog = vm_settings.VMSettingsWindow(
self.vm, self.qtapp, "basic") self.vm, qapp=self.qtapp, qubesapp=self.qapp, init_page="basic")
self.assertEqual(self.dialog.vmname.text(), "testvm", self.assertEqual(self.dialog.vmname.text(), "test-vm",
"Name displayed incorrectly") "Name displayed incorrectly")
self.assertTrue("blue" in self.dialog.vmlabel.currentText(), self.assertTrue("blue" in self.dialog.vmlabel.currentText(),
@ -177,12 +158,12 @@ class VMSettingsTest(unittest.TestCase):
"Incorrect max private root size") "Incorrect max private root size")
def test_02_basic_tab_nones(self): def test_02_basic_tab_nones(self):
self.vm = self.qapp.add_new_vm("StandaloneVM", "testvm", "blue") self.vm = self.qapp.add_new_vm("StandaloneVM", "test-vm", "blue")
# set the vm to have a default template and netvm # set the vm to have a default template and netvm
self.vm.netvm = None self.vm.netvm = None
self.dialog = vm_settings.VMSettingsWindow( self.dialog = vm_settings.VMSettingsWindow(
self.vm, self.qtapp, "basic") self.vm, qapp=self.qtapp, qubesapp=self.qapp, init_page="basic")
self.assertEqual("", self.dialog.template_name.currentText(), self.assertEqual("", self.dialog.template_name.currentText(),
"No template incorrectly displayed") "No template incorrectly displayed")
@ -206,12 +187,11 @@ class VMSettingsTest(unittest.TestCase):
"---", "---",
"Incorrect gateway displayed") "Incorrect gateway displayed")
@unittest.expectedFailure
def test_03_change_label(self): def test_03_change_label(self):
# this test fails due to error where we check whether label is visible self.vm = self.qapp.add_new_vm("AppVM", "test-vm", "blue")
self.vm = self.qapp.add_new_vm("AppVM", "testvm", "blue")
self.dialog = vm_settings.VMSettingsWindow( self.dialog = vm_settings.VMSettingsWindow(
self.vm, self.qtapp, "basic") self.vm, qapp=self.qtapp, qubesapp=self.qapp, init_page="basic")
self.dialog.show()
new_label = self._set_noncurrent(self.dialog.vmlabel) new_label = self._set_noncurrent(self.dialog.vmlabel)
self._click_ok() self._click_ok()
@ -220,9 +200,9 @@ class VMSettingsTest(unittest.TestCase):
"Label is not set correctly") "Label is not set correctly")
def test_04_change_template(self): def test_04_change_template(self):
self.vm = self.qapp.add_new_vm("AppVM", "testvm", "blue") self.vm = self.qapp.add_new_vm("AppVM", "test-vm", "blue")
self.dialog = vm_settings.VMSettingsWindow( self.dialog = vm_settings.VMSettingsWindow(
self.vm, self.qtapp, "basic") self.vm, qapp=self.qtapp, qubesapp=self.qapp, init_page="basic")
new_template = self._set_noncurrent(self.dialog.template_name) new_template = self._set_noncurrent(self.dialog.template_name)
self._click_ok() self._click_ok()
@ -231,9 +211,9 @@ class VMSettingsTest(unittest.TestCase):
"Template is not set correctly") "Template is not set correctly")
def test_05_change_networking(self): def test_05_change_networking(self):
self.vm = self.qapp.add_new_vm("AppVM", "testvm", "blue") self.vm = self.qapp.add_new_vm("AppVM", "test-vm", "blue")
self.dialog = vm_settings.VMSettingsWindow( self.dialog = vm_settings.VMSettingsWindow(
self.vm, self.qtapp, "basic") self.vm, qapp=self.qtapp, qubesapp=self.qapp, init_page="basic")
new_netvm = self._set_noncurrent(self.dialog.netVM) new_netvm = self._set_noncurrent(self.dialog.netVM)
self._click_ok() self._click_ok()
@ -242,9 +222,9 @@ class VMSettingsTest(unittest.TestCase):
"NetVM is not set correctly") "NetVM is not set correctly")
def test_06_change_networking_none(self): def test_06_change_networking_none(self):
self.vm = self.qapp.add_new_vm("AppVM", "testvm", "blue") self.vm = self.qapp.add_new_vm("AppVM", "test-vm", "blue")
self.dialog = vm_settings.VMSettingsWindow( self.dialog = vm_settings.VMSettingsWindow(
self.vm, self.qtapp, "basic") self.vm, qapp=self.qtapp, qubesapp=self.qapp, init_page="basic")
self._set_none(self.dialog.netVM) self._set_none(self.dialog.netVM)
self._click_ok() self._click_ok()
@ -253,7 +233,7 @@ class VMSettingsTest(unittest.TestCase):
"None netVM is not set correctly") "None netVM is not set correctly")
def test_07_change_networking_to_default(self): def test_07_change_networking_to_default(self):
self.vm = self.qapp.add_new_vm("AppVM", "testvm", "blue") self.vm = self.qapp.add_new_vm("AppVM", "test-vm", "blue")
for vm in self.qapp.domains: for vm in self.qapp.domains:
if getattr(vm, 'provides_network', False)\ if getattr(vm, 'provides_network', False)\
@ -262,7 +242,7 @@ class VMSettingsTest(unittest.TestCase):
break break
self.dialog = vm_settings.VMSettingsWindow( self.dialog = vm_settings.VMSettingsWindow(
self.vm, self.qtapp, "basic") self.vm, qapp=self.qtapp, qubesapp=self.qapp, init_page="basic")
new_netvm = self._set_default(self.dialog.netVM) new_netvm = self._set_default(self.dialog.netVM)
self._click_ok() self._click_ok()
@ -271,11 +251,11 @@ class VMSettingsTest(unittest.TestCase):
"NetVM is not set correctly") "NetVM is not set correctly")
self.assertTrue(self.vm.property_is_default('netvm')) self.assertTrue(self.vm.property_is_default('netvm'))
@unittest.expectedFailure
def test_08_basic_checkboxes_true(self): def test_08_basic_checkboxes_true(self):
self.vm = self.qapp.add_new_vm("AppVM", "testvm", "blue") self.vm = self.qapp.add_new_vm("AppVM", "test-vm", "blue")
self.dialog = vm_settings.VMSettingsWindow( self.dialog = vm_settings.VMSettingsWindow(
self.vm, self.qtapp, "basic") self.vm, qapp=self.qtapp, qubesapp=self.qapp, init_page="basic")
self.dialog.show()
self.dialog.include_in_backups.setChecked(True) self.dialog.include_in_backups.setChecked(True)
self.dialog.autostart_vm.setChecked(True) self.dialog.autostart_vm.setChecked(True)
@ -290,11 +270,11 @@ class VMSettingsTest(unittest.TestCase):
self.assertTrue(self.vm.debug, self.assertTrue(self.vm.debug,
"Debug mode not set to true") "Debug mode not set to true")
@unittest.expectedFailure
def test_09_basic_checkboxes_false(self): def test_09_basic_checkboxes_false(self):
self.vm = self.qapp.add_new_vm("AppVM", "testvm", "blue") self.vm = self.qapp.add_new_vm("AppVM", "test-vm", "blue")
self.dialog = vm_settings.VMSettingsWindow( self.dialog = vm_settings.VMSettingsWindow(
self.vm, self.qtapp, "basic") self.vm, qapp=self.qtapp, qubesapp=self.qapp, init_page="basic")
self.dialog.show()
self.dialog.include_in_backups.setChecked(False) self.dialog.include_in_backups.setChecked(False)
self.dialog.autostart_vm.setChecked(False) self.dialog.autostart_vm.setChecked(False)
@ -310,9 +290,9 @@ class VMSettingsTest(unittest.TestCase):
"Debug mode not set to false") "Debug mode not set to false")
def test_10_increase_private_storage(self): def test_10_increase_private_storage(self):
self.vm = self.qapp.add_new_vm("AppVM", "testvm", "blue") self.vm = self.qapp.add_new_vm("AppVM", "test-vm", "blue")
self.dialog = vm_settings.VMSettingsWindow( self.dialog = vm_settings.VMSettingsWindow(
self.vm, self.qtapp, "basic") self.vm, qapp=self.qtapp, qubesapp=self.qapp, init_page="basic")
current_storage = self.vm.volumes['private'].size // 1024**2 current_storage = self.vm.volumes['private'].size // 1024**2
new_storage = current_storage + 512 new_storage = current_storage + 512
@ -325,58 +305,58 @@ class VMSettingsTest(unittest.TestCase):
# TODO are dependencies correctly processed # TODO are dependencies correctly processed
@unittest.mock.patch('PyQt4.QtGui.QProgressDialog') @unittest.mock.patch('PyQt5.QtWidgets.QProgressDialog')
@unittest.mock.patch('PyQt4.QtGui.QInputDialog.getText') @unittest.mock.patch('PyQt5.QtWidgets.QInputDialog.getText')
@unittest.mock.patch('qubesmanager.settings.RenameVMThread') @unittest.mock.patch('qubesmanager.settings.RenameVMThread')
def test_11_rename_vm(self, mock_thread, mock_input, _): def test_11_rename_vm(self, mock_thread, mock_input, _):
self.vm = self.qapp.add_new_vm("AppVM", "testvm", "blue") self.vm = self.qapp.add_new_vm("AppVM", "test-vm", "blue")
self.dialog = vm_settings.VMSettingsWindow( self.dialog = vm_settings.VMSettingsWindow(
self.vm, self.qtapp, "basic") self.vm, qapp=self.qtapp, qubesapp=self.qapp, init_page="basic")
self.assertTrue(self.dialog.rename_vm_button.isEnabled()) self.assertTrue(self.dialog.rename_vm_button.isEnabled())
mock_input.return_value = ("testvm2", True) mock_input.return_value = ("test-vm2", True)
self.dialog.rename_vm_button.click() self.dialog.rename_vm_button.click()
mock_thread.assert_called_with(self.vm, "testvm2", unittest.mock.ANY) mock_thread.assert_called_with(self.vm, "test-vm2", unittest.mock.ANY)
mock_thread().start.assert_called_with() mock_thread().start.assert_called_with()
# TODO: thread tests for rename # TODO: thread tests for rename
@unittest.mock.patch('PyQt4.QtGui.QProgressDialog') @unittest.mock.patch('PyQt5.QtWidgets.QProgressDialog')
@unittest.mock.patch('PyQt4.QtGui.QInputDialog.getText') @unittest.mock.patch('PyQt5.QtWidgets.QInputDialog.getText')
@unittest.mock.patch('qubesmanager.common_threads.CloneVMThread') @unittest.mock.patch('qubesmanager.common_threads.CloneVMThread')
def test_12_clone_vm(self, mock_thread, mock_input, _): def test_12_clone_vm(self, mock_thread, mock_input, _):
self.vm = self.qapp.add_new_vm("AppVM", "testvm", "blue") self.vm = self.qapp.add_new_vm("AppVM", "test-vm", "blue")
self.dialog = vm_settings.VMSettingsWindow( self.dialog = vm_settings.VMSettingsWindow(
self.vm, self.qtapp, "basic") self.vm, qapp=self.qtapp, qubesapp=self.qapp, init_page="basic")
self.assertTrue(self.dialog.clone_vm_button.isEnabled()) self.assertTrue(self.dialog.clone_vm_button.isEnabled())
mock_input.return_value = ("testvm2", True) mock_input.return_value = ("test-vm2", True)
self.dialog.clone_vm_button.click() self.dialog.clone_vm_button.click()
mock_thread.assert_called_with(self.vm, "testvm2") mock_thread.assert_called_with(self.vm, "test-vm2")
mock_thread().start.assert_called_with() mock_thread().start.assert_called_with()
@unittest.mock.patch('PyQt4.QtGui.QMessageBox.warning') @unittest.mock.patch('PyQt5.QtWidgets.QMessageBox.warning')
@unittest.mock.patch('PyQt4.QtGui.QProgressDialog') @unittest.mock.patch('PyQt5.QtWidgets.QProgressDialog')
@unittest.mock.patch('PyQt4.QtGui.QInputDialog.getText') @unittest.mock.patch('PyQt5.QtWidgets.QInputDialog.getText')
@unittest.mock.patch('qubesmanager.common_threads.RemoveVMThread') @unittest.mock.patch('qubesmanager.common_threads.RemoveVMThread')
def test_13_remove_vm(self, mock_thread, mock_input, _, mock_warning): def test_13_remove_vm(self, mock_thread, mock_input, _, mock_warning):
self.vm = self.qapp.add_new_vm("AppVM", "testvm", "blue") self.vm = self.qapp.add_new_vm("AppVM", "test-vm", "blue")
self.dialog = vm_settings.VMSettingsWindow( self.dialog = vm_settings.VMSettingsWindow(
self.vm, self.qtapp, "basic") self.vm, qapp=self.qtapp, qubesapp=self.qapp, init_page="basic")
self.assertTrue(self.dialog.delete_vm_button.isEnabled()) self.assertTrue(self.dialog.delete_vm_button.isEnabled())
# try with a wrong name # try with a wrong name
mock_input.return_value = ("testvm2", True) mock_input.return_value = ("test-vm2", True)
self.dialog.delete_vm_button.click() self.dialog.delete_vm_button.click()
self.assertEqual(mock_warning.call_count, 1) self.assertEqual(mock_warning.call_count, 1)
# and now correct one # and now correct one
mock_input.return_value = ("testvm", True) mock_input.return_value = ("test-vm", True)
self.dialog.delete_vm_button.click() self.dialog.delete_vm_button.click()
mock_thread.assert_called_with(self.vm) mock_thread.assert_called_with(self.vm)
@ -384,9 +364,9 @@ class VMSettingsTest(unittest.TestCase):
# Advanced Tab # Advanced Tab
def test_20_advanced_loads(self): def test_20_advanced_loads(self):
self.vm = self.qapp.add_new_vm("AppVM", "testvm", "blue") self.vm = self.qapp.add_new_vm("AppVM", "test-vm", "blue")
self.dialog = vm_settings.VMSettingsWindow( self.dialog = vm_settings.VMSettingsWindow(
self.vm, self.qtapp, "advanced") self.vm, qapp=self.qtapp, qubesapp=self.qapp, init_page="advanced")
self.assertEqual(self.dialog.init_mem.value(), self.vm.memory, self.assertEqual(self.dialog.init_mem.value(), self.vm.memory,
"Incorrect initial memory") "Incorrect initial memory")
@ -417,11 +397,11 @@ class VMSettingsTest(unittest.TestCase):
self.assertTrue("PVH" in self.dialog.virt_mode.currentText()) self.assertTrue("PVH" in self.dialog.virt_mode.currentText())
def test_21_nondefaultmaxmem(self): def test_21_nondefaultmaxmem(self):
self.vm = self.qapp.add_new_vm("AppVM", "testvm", "blue") self.vm = self.qapp.add_new_vm("AppVM", "test-vm", "blue")
self.vm.maxmem = 5000 self.vm.maxmem = 5000
self.dialog = vm_settings.VMSettingsWindow( self.dialog = vm_settings.VMSettingsWindow(
self.vm, self.qtapp, "advanced") self.vm, qapp=self.qtapp, qubesapp=self.qapp, init_page="advanced")
self.assertEqual(self.dialog.max_mem_size.value(), 5000) self.assertEqual(self.dialog.max_mem_size.value(), 5000)
@ -431,9 +411,10 @@ class VMSettingsTest(unittest.TestCase):
self.assertEqual(self.vm.maxmem, 0) self.assertEqual(self.vm.maxmem, 0)
self.dialog.deleteLater() self.dialog.deleteLater()
self.qtapp.processEvents()
self.dialog = vm_settings.VMSettingsWindow( self.dialog = vm_settings.VMSettingsWindow(
self.vm, self.qtapp, "advanced") self.vm, qapp=self.qtapp, qubesapp=self.qapp, init_page="advanced")
self.assertFalse(self.dialog.include_in_balancing.isChecked()) self.assertFalse(self.dialog.include_in_balancing.isChecked())
self.dialog.include_in_balancing.setChecked(True) self.dialog.include_in_balancing.setChecked(True)
@ -443,11 +424,11 @@ class VMSettingsTest(unittest.TestCase):
self.assertEqual(self.vm.maxmem, 5000) self.assertEqual(self.vm.maxmem, 5000)
def test_22_initmem(self): def test_22_initmem(self):
self.vm = self.qapp.add_new_vm("AppVM", "testvm", "blue") self.vm = self.qapp.add_new_vm("AppVM", "test-vm", "blue")
self.vm.memory = 500 self.vm.memory = 500
self.dialog = vm_settings.VMSettingsWindow( self.dialog = vm_settings.VMSettingsWindow(
self.vm, self.qtapp, "advanced") self.vm, qapp=self.qtapp, qubesapp=self.qapp, init_page="advanced")
self.assertEqual(self.dialog.init_mem.value(), 500, self.assertEqual(self.dialog.init_mem.value(), 500,
"Incorrect initial memory") "Incorrect initial memory")
@ -457,11 +438,11 @@ class VMSettingsTest(unittest.TestCase):
self.assertEqual(self.vm.memory, 600, "Setting initial memory failed") self.assertEqual(self.vm.memory, 600, "Setting initial memory failed")
def test_23_vcpus(self): def test_23_vcpus(self):
self.vm = self.qapp.add_new_vm("AppVM", "testvm", "blue") self.vm = self.qapp.add_new_vm("AppVM", "test-vm", "blue")
self.vm.vcpus = 1 self.vm.vcpus = 1
self.dialog = vm_settings.VMSettingsWindow( self.dialog = vm_settings.VMSettingsWindow(
self.vm, self.qtapp, "advanced") self.vm, qapp=self.qtapp, qubesapp=self.qapp, init_page="advanced")
self.assertEqual(self.dialog.vcpus.value(), 1, self.assertEqual(self.dialog.vcpus.value(), 1,
"Incorrect number of VCPUs") "Incorrect number of VCPUs")
@ -472,9 +453,10 @@ class VMSettingsTest(unittest.TestCase):
"Incorrect number of VCPUs") "Incorrect number of VCPUs")
def test_24_kernel(self): def test_24_kernel(self):
self.vm = self.qapp.add_new_vm("AppVM", "testvm", "blue") self.vm = self.qapp.add_new_vm("AppVM", "test-vm", "blue")
self.dialog = vm_settings.VMSettingsWindow( self.dialog = vm_settings.VMSettingsWindow(
self.vm, self.qtapp, "advanced") self.vm, qapp=self.qtapp, qubesapp=self.qapp, init_page="advanced")
self.dialog.show()
new_kernel = self._set_noncurrent(self.dialog.kernel) new_kernel = self._set_noncurrent(self.dialog.kernel)
self._click_ok() self._click_ok()
@ -482,22 +464,25 @@ class VMSettingsTest(unittest.TestCase):
self.assertEqual(self.vm.kernel, new_kernel) self.assertEqual(self.vm.kernel, new_kernel)
self.dialog.deleteLater() self.dialog.deleteLater()
self.qtapp.processEvents()
self.dialog = vm_settings.VMSettingsWindow( self.dialog = vm_settings.VMSettingsWindow(
self.vm, self.qtapp, "advanced") self.vm, qapp=self.qtapp, qubesapp=self.qapp, init_page="advanced")
self.dialog.show()
self._set_default(self.dialog.kernel) self._set_default(self.dialog.kernel)
self._click_ok() self._click_ok()
self.assertTrue(self.vm.property_is_default('kernel')) self.assertTrue(self.vm.property_is_default('kernel'))
def test_25_virtmode_change(self): def test_25_virtmode_change(self):
self.vm = self.qapp.add_new_vm("AppVM", "testvm", "blue") self.vm = self.qapp.add_new_vm("AppVM", "test-vm", "blue")
modes = ["HVM", "PVH", "PV"] modes = ["HVM", "PVH", "PV"]
for mode in modes: for mode in modes:
self.dialog = vm_settings.VMSettingsWindow( self.dialog = vm_settings.VMSettingsWindow(
self.vm, self.qtapp, "advanced") self.vm, qapp=self.qtapp, qubesapp=self.qapp,
init_page="advanced")
self._set_value(self.dialog.virt_mode, mode) self._set_value(self.dialog.virt_mode, mode)
self._click_ok() self._click_ok()
@ -505,19 +490,20 @@ class VMSettingsTest(unittest.TestCase):
self.assertEqual(self.vm.virt_mode.upper(), mode) self.assertEqual(self.vm.virt_mode.upper(), mode)
self.dialog.deleteLater() self.dialog.deleteLater()
self.qtapp.processEvents()
self.dialog = vm_settings.VMSettingsWindow( self.dialog = vm_settings.VMSettingsWindow(
self.vm, self.qtapp, "advanced") self.vm, qapp=self.qtapp, qubesapp=self.qapp, init_page="advanced")
self._set_default(self.dialog.virt_mode) self._set_default(self.dialog.virt_mode)
self._click_ok() self._click_ok()
self.assertTrue(self.vm.property_is_default('virt_mode')) self.assertTrue(self.vm.property_is_default('virt_mode'))
def test_26_default_dispvm(self): def test_26_default_dispvm(self):
self.vm = self.qapp.add_new_vm("AppVM", "testvm", "blue") self.vm = self.qapp.add_new_vm("AppVM", "test-vm", "blue")
self.dialog = vm_settings.VMSettingsWindow( self.dialog = vm_settings.VMSettingsWindow(
self.vm, self.qtapp, "advanced") self.vm, qapp=self.qtapp, qubesapp=self.qapp, init_page="advanced")
new_dvm = self._set_noncurrent(self.dialog.default_dispvm) new_dvm = self._set_noncurrent(self.dialog.default_dispvm)
self._click_ok() self._click_ok()
@ -525,9 +511,10 @@ class VMSettingsTest(unittest.TestCase):
self.assertEqual(self.vm.default_dispvm.name, new_dvm) self.assertEqual(self.vm.default_dispvm.name, new_dvm)
self.dialog.deleteLater() self.dialog.deleteLater()
self.qtapp.processEvents()
self.dialog = vm_settings.VMSettingsWindow( self.dialog = vm_settings.VMSettingsWindow(
self.vm, self.qtapp, "advanced") self.vm, qapp=self.qtapp, qubesapp=self.qapp, init_page="advanced")
self._set_default(self.dialog.default_dispvm) self._set_default(self.dialog.default_dispvm)
self._click_ok() self._click_ok()
@ -535,13 +522,13 @@ class VMSettingsTest(unittest.TestCase):
@unittest.mock.patch('subprocess.check_call') @unittest.mock.patch('subprocess.check_call')
def test_27_boot_cdrom(self, mock_call): def test_27_boot_cdrom(self, mock_call):
self.vm = self.qapp.add_new_vm("AppVM", "testvm", "blue") self.vm = self.qapp.add_new_vm("AppVM", "test-vm", "blue")
self.dialog = vm_settings.VMSettingsWindow( self.dialog = vm_settings.VMSettingsWindow(
self.vm, self.qtapp, "advanced") self.vm, qapp=self.qtapp, qubesapp=self.qapp, init_page="advanced")
self.dialog.boot_from_device_button.click() self.dialog.boot_from_device_button.click()
mock_call.assert_called_with(['qubes-vm-boot-from-device', "testvm"]) mock_call.assert_called_with(['qubes-vm-boot-from-device', "test-vm"])
def _click_ok(self): def _click_ok(self):
okwidget = self.dialog.buttonBox.button( okwidget = self.dialog.buttonBox.button(

View File

@ -210,6 +210,9 @@
</item> </item>
<item row="2" column="0" colspan="2"> <item row="2" column="0" colspan="2">
<widget class="QCheckBox" name="install_system"> <widget class="QCheckBox" name="install_system">
<property name="enabled">
<bool>false</bool>
</property>
<property name="text"> <property name="text">
<string>install system from device (also available from settings)</string> <string>install system from device (also available from settings)</string>
</property> </property>