From d92c782ec9a11df3f3e7467fb290abe270ebf138 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marta=20Marczykowska-G=C3=B3recka?= Date: Sun, 12 May 2019 19:45:06 +0200 Subject: [PATCH] Tests for Create New VM --- qubesmanager/tests/test_create_new_vm.py | 245 ++++++++++++++++++++++- rpm_spec/qmgr.spec.in | 2 + 2 files changed, 241 insertions(+), 6 deletions(-) diff --git a/qubesmanager/tests/test_create_new_vm.py b/qubesmanager/tests/test_create_new_vm.py index d1d5904..d889773 100644 --- a/qubesmanager/tests/test_create_new_vm.py +++ b/qubesmanager/tests/test_create_new_vm.py @@ -23,6 +23,7 @@ import logging.handlers import sys import unittest import unittest.mock +import qubesadmin from PyQt4 import QtGui, QtTest, QtCore from qubesadmin import Qubes, events, utils, exc @@ -34,23 +35,255 @@ class NewVmTest(unittest.TestCase): super(NewVmTest, self).setUp() self.qapp = Qubes() - self.qtapp = QtGui.QApplication(sys.argv) - self.dispatcher = events.EventsDispatcher(self.qapp) + self.qtapp = QtGui.QApplication(["test", "-style", "cleanlooks"]) + + # mock up the Create VM Thread to avoid changing system state + self.patcher_thread = unittest.mock.patch( + 'qubesmanager.create_new_vm.CreateVMThread') + self.mock_thread = self.patcher_thread.start() + self.addCleanup(self.patcher_thread.stop) + + # mock the progress dialog to speed testing up + self.patcher_progress = unittest.mock.patch( + 'PyQt4.QtGui.QProgressDialog') + self.mock_progress = self.patcher_progress.start() + self.addCleanup(self.patcher_progress.stop) self.dialog = create_new_vm.NewVmDlg( self.qtapp, self.qapp) def tearDown(self): self.dialog.deleteLater() + self.qtapp.deleteLater() + self.qtapp.processEvents() + super(NewVmTest, self).tearDown() def test_00_window_loads(self): - self.assertTrue(self.dialog.select_vms_widget is not None) + self.assertGreater(self.dialog.template_vm.count(), 0, + "No templates shown") + self.assertGreater(self.dialog.netvm.count(), 0, "No netvm listed") - def test_01_vms_load_correctly(self): - pass + def test_01_cancel_works(self): + self.__click_cancel() + self.assertEqual(self.mock_thread.call_count, 0, + "Attempted to create VM on cancel") -class CreatteVMThreadTest(unittest.TestCase): + def test_02_create_simple_vm(self): + self.dialog.name.setText("testvm") + self.__click_ok() + + self.mock_thread.assert_called_once_with( + self.qapp, "AppVM", "testvm", + unittest.mock.ANY, qubesadmin.DEFAULT, + {'provides_network': False}) + self.mock_thread().start.assert_called_once_with() + + def test_03_label(self): + for i in range(self.dialog.label.count()): + if self.dialog.label.itemText(i) == 'blue': + self.dialog.label.setCurrentIndex(i) + break + + self.dialog.name.setText("testvm") + self.__click_ok() + + self.mock_thread.assert_called_once_with( + self.qapp, "AppVM", "testvm", + self.qapp.labels['blue'], qubesadmin.DEFAULT, + unittest.mock.ANY) + self.mock_thread().start.assert_called_once_with() + + def test_04_template(self): + template = None + for i in range(self.dialog.template_vm.count()): + if not self.dialog.template_vm.itemText(i).startswith('default'): + self.dialog.template_vm.setCurrentIndex(i) + template = self.dialog.template_vm.currentText() + break + + self.dialog.name.setText("testvm") + self.__click_ok() + + self.mock_thread.assert_called_once_with( + self.qapp, "AppVM", "testvm", + unittest.mock.ANY, template, + unittest.mock.ANY) + + def test_05_netvm(self): + netvm = None + for i in range(self.dialog.netvm.count()): + if not self.dialog.netvm.itemText(i).startswith('default'): + self.dialog.netvm.setCurrentIndex(i) + netvm = self.dialog.netvm.currentText() + break + + self.dialog.name.setText("testvm") + self.__click_ok() + + self.mock_thread.assert_called_once_with( + self.qapp, "AppVM", "testvm", + unittest.mock.ANY, unittest.mock.ANY, + {'netvm': netvm, 'provides_network': False}) + + def test_06_provides_network(self): + self.dialog.provides_network.setChecked(True) + + self.dialog.name.setText("testvm") + self.__click_ok() + + self.mock_thread.assert_called_once_with( + self.qapp, "AppVM", "testvm", + unittest.mock.ANY, unittest.mock.ANY, + {'provides_network': True}) + + @unittest.mock.patch('subprocess.check_call') + def test_07_launch_settings(self, mock_call): + self.dialog.launch_settings.setChecked(True) + + self.dialog.name.setText("testvm") + + self.__click_ok() + + # make sure the thread is not reporting an error + self.mock_thread.assert_called_once_with( + self.qapp, "AppVM", "testvm", + unittest.mock.ANY, unittest.mock.ANY, + unittest.mock.ANY) + + self.mock_thread().msg = None + self.dialog.create_finished() + + mock_call.assert_called_once_with(['qubes-vm-settings', "testvm"]) + + def test_08_progress_hides(self): + self.dialog.name.setText("testvm") + + self.__click_ok() + + self.mock_thread.assert_called_once_with( + self.qapp, "AppVM", "testvm", + unittest.mock.ANY, unittest.mock.ANY, + unittest.mock.ANY) + + # make sure the thread is not reporting an error + self.mock_thread().start.assert_called_once_with() + self.mock_thread().msg = None + + self.mock_progress().show.assert_called_once_with() + + self.dialog.create_finished() + + self.mock_progress().hide.assert_called_once_with() + + def test_09_standalone_clone(self): + self.dialog.name.setText("testvm") + for i in range(self.dialog.vm_type.count()): + opt_text = self.dialog.vm_type.itemText(i).lower() + if "standalone" in opt_text and "template" in opt_text and\ + "not based" not in opt_text and "empty" not in opt_text: + self.dialog.vm_type.setCurrentIndex(i) + break + + self.__click_ok() + self.mock_thread.assert_called_once_with( + self.qapp, "StandaloneVM", "testvm", + unittest.mock.ANY, unittest.mock.ANY, + unittest.mock.ANY) + + @unittest.mock.patch('subprocess.check_call') + def test_10_standalone_empty(self, mock_call): + self.dialog.name.setText("testvm") + for i in range(self.dialog.vm_type.count()): + opt_text = self.dialog.vm_type.itemText(i).lower() + if "standalone" in opt_text and\ + ("not based" in opt_text or "empty" in opt_text): + self.dialog.vm_type.setCurrentIndex(i) + break + + self.__click_ok() + self.mock_thread.assert_called_once_with( + self.qapp, "StandaloneVM", "testvm", + unittest.mock.ANY, None, + unittest.mock.ANY) + + self.mock_thread().msg = None + self.dialog.create_finished() + + mock_call.assert_called_once_with(['qubes-vm-boot-from-device', + 'testvm']) + + @unittest.mock.patch('subprocess.check_call') + def test_11_standalone_empty_not_install(self, mock_call): + self.dialog.name.setText("testvm") + + for i in range(self.dialog.vm_type.count()): + opt_text = self.dialog.vm_type.itemText(i).lower() + if "standalone" in opt_text and\ + ("not based" in opt_text or "empty" in opt_text): + self.dialog.vm_type.setCurrentIndex(i) + break + + self.dialog.install_system.setChecked(False) + + self.__click_ok() + self.mock_thread.assert_called_once_with( + self.qapp, "StandaloneVM", "testvm", + unittest.mock.ANY, None, + unittest.mock.ANY) + + self.mock_thread().msg = None + self.dialog.create_finished() + + self.assertEqual(mock_call.call_count, 0) + + def test_12_setting_change(self): + # cannot install system on a template-based appvm + for i in range(self.dialog.vm_type.count()): + opt_text = self.dialog.vm_type.itemText(i).lower() + if "appvm" in opt_text and "standalone" not in opt_text: + self.dialog.vm_type.setCurrentIndex(i) + break + self.assertFalse(self.dialog.install_system.isEnabled()) + self.assertTrue(self.dialog.launch_settings.isEnabled()) + self.assertTrue(self.dialog.template_vm.isEnabled()) + + # or on a standalone vm cloned from a template + for i in range(self.dialog.vm_type.count()): + opt_text = self.dialog.vm_type.itemText(i).lower() + if "standalone" in opt_text and "template" in opt_text and\ + "not based" not in opt_text and "empty" not in opt_text: + self.dialog.vm_type.setCurrentIndex(i) + break + self.assertFalse(self.dialog.install_system.isEnabled()) + self.assertTrue(self.dialog.launch_settings.isEnabled()) + self.assertTrue(self.dialog.template_vm.isEnabled()) + + # cannot set a template but can install system on a truly empty AppVM + for i in range(self.dialog.vm_type.count()): + opt_text = self.dialog.vm_type.itemText(i).lower() + if "standalone" in opt_text and\ + ("not based" in opt_text or "empty" in opt_text): + self.dialog.vm_type.setCurrentIndex(i) + break + self.assertTrue(self.dialog.install_system.isEnabled()) + self.assertTrue(self.dialog.launch_settings.isEnabled()) + self.assertFalse(self.dialog.template_vm.isEnabled()) + + def __click_ok(self): + okwidget = self.dialog.buttonBox.button( + self.dialog.buttonBox.Ok) + + QtTest.QTest.mouseClick(okwidget, QtCore.Qt.LeftButton) + + def __click_cancel(self): + cancelwidget = self.dialog.buttonBox.button( + self.dialog.buttonBox.Cancel) + + QtTest.QTest.mouseClick(cancelwidget, QtCore.Qt.LeftButton) + + +# class CreatteVMThreadTest(unittest.TestCase): if __name__ == "__main__": diff --git a/rpm_spec/qmgr.spec.in b/rpm_spec/qmgr.spec.in index 69959ae..49a3d59 100644 --- a/rpm_spec/qmgr.spec.in +++ b/rpm_spec/qmgr.spec.in @@ -127,6 +127,8 @@ rm -rf $RPM_BUILD_ROOT %{python3_sitelib}/qubesmanager/tests/test_backup_utils.py %{python3_sitelib}/qubesmanager/tests/test_global_settings.py %{python3_sitelib}/qubesmanager/tests/test_qube_manager.py +%{python3_sitelib}/qubesmanager/tests/test_create_new_vm.py +%{python3_sitelib}/qubesmanager/tests/test_vm_settings.py %dir %{python3_sitelib}/qubesmanager-*.egg-info %{python3_sitelib}/qubesmanager-*.egg-info/*