|
@@ -33,6 +33,7 @@ import time
|
|
|
from qubes.qubes import QubesVmCollection, defaults, QubesException
|
|
|
|
|
|
import qubes.tests
|
|
|
+import re
|
|
|
|
|
|
TEST_DATA = "0123456789" * 1024
|
|
|
|
|
@@ -528,16 +529,123 @@ class TC_00_AppVMMixin(qubes.tests.SystemTestsMixin):
|
|
|
self.fail("Timeout, probably deadlock")
|
|
|
self.assertEqual(result.value, 0, "Service call failed")
|
|
|
|
|
|
- @unittest.skipUnless(spawn.find_executable('xdotool'),
|
|
|
- "xdotool not installed")
|
|
|
+ def test_080_qrexec_service_argument_allow_default(self):
|
|
|
+ """Qrexec service call with argument"""
|
|
|
+ self.testvm1.start()
|
|
|
+ self.testvm2.start()
|
|
|
+ p = self.testvm2.run("cat > /etc/qubes-rpc/test.Argument", user="root",
|
|
|
+ passio_popen=True)
|
|
|
+ p.communicate("/bin/echo $1")
|
|
|
+
|
|
|
+ with open("/etc/qubes-rpc/policy/test.Argument", "w") as policy:
|
|
|
+ policy.write("%s %s allow" % (self.testvm1.name, self.testvm2.name))
|
|
|
+ self.addCleanup(os.unlink, "/etc/qubes-rpc/policy/test.Argument")
|
|
|
+
|
|
|
+ p = self.testvm1.run("/usr/lib/qubes/qrexec-client-vm {} "
|
|
|
+ "test.Argument+argument".format(self.testvm2.name),
|
|
|
+ passio_popen=True)
|
|
|
+ (stdout, stderr) = p.communicate()
|
|
|
+ self.assertEqual(stdout, "argument\n")
|
|
|
+
|
|
|
+ def test_081_qrexec_service_argument_allow_specific(self):
|
|
|
+ """Qrexec service call with argument - allow only specific value"""
|
|
|
+ self.testvm1.start()
|
|
|
+ self.testvm2.start()
|
|
|
+ p = self.testvm2.run("cat > /etc/qubes-rpc/test.Argument", user="root",
|
|
|
+ passio_popen=True)
|
|
|
+ p.communicate("/bin/echo $1")
|
|
|
+
|
|
|
+ with open("/etc/qubes-rpc/policy/test.Argument", "w") as policy:
|
|
|
+ policy.write("$anyvm $anyvm deny")
|
|
|
+ self.addCleanup(os.unlink, "/etc/qubes-rpc/policy/test.Argument")
|
|
|
+
|
|
|
+ with open("/etc/qubes-rpc/policy/test.Argument+argument", "w") as \
|
|
|
+ policy:
|
|
|
+ policy.write("%s %s allow" % (self.testvm1.name, self.testvm2.name))
|
|
|
+ self.addCleanup(os.unlink,
|
|
|
+ "/etc/qubes-rpc/policy/test.Argument+argument")
|
|
|
+
|
|
|
+ p = self.testvm1.run("/usr/lib/qubes/qrexec-client-vm {} "
|
|
|
+ "test.Argument+argument".format(self.testvm2.name),
|
|
|
+ passio_popen=True)
|
|
|
+ (stdout, stderr) = p.communicate()
|
|
|
+ self.assertEqual(stdout, "argument\n")
|
|
|
+
|
|
|
+ def test_082_qrexec_service_argument_deny_specific(self):
|
|
|
+ """Qrexec service call with argument - deny specific value"""
|
|
|
+ self.testvm1.start()
|
|
|
+ self.testvm2.start()
|
|
|
+ p = self.testvm2.run("cat > /etc/qubes-rpc/test.Argument", user="root",
|
|
|
+ passio_popen=True)
|
|
|
+ p.communicate("/bin/echo $1")
|
|
|
+
|
|
|
+ with open("/etc/qubes-rpc/policy/test.Argument", "w") as policy:
|
|
|
+ policy.write("$anyvm $anyvm allow")
|
|
|
+ self.addCleanup(os.unlink, "/etc/qubes-rpc/policy/test.Argument")
|
|
|
+
|
|
|
+ with open("/etc/qubes-rpc/policy/test.Argument+argument", "w") as \
|
|
|
+ policy:
|
|
|
+ policy.write("%s %s deny" % (self.testvm1.name, self.testvm2.name))
|
|
|
+ self.addCleanup(os.unlink,
|
|
|
+ "/etc/qubes-rpc/policy/test.Argument+argument")
|
|
|
+
|
|
|
+ p = self.testvm1.run("/usr/lib/qubes/qrexec-client-vm {} "
|
|
|
+ "test.Argument+argument".format(self.testvm2.name),
|
|
|
+ passio_popen=True)
|
|
|
+ (stdout, stderr) = p.communicate()
|
|
|
+ self.assertEqual(stdout, "")
|
|
|
+ self.assertEqual(p.returncode, 1, "Service request should be denied")
|
|
|
+
|
|
|
+ def test_083_qrexec_service_argument_specific_implementation(self):
|
|
|
+ """Qrexec service call with argument - argument specific
|
|
|
+ implementatation"""
|
|
|
+ self.testvm1.start()
|
|
|
+ self.testvm2.start()
|
|
|
+ p = self.testvm2.run("cat > /etc/qubes-rpc/test.Argument", user="root",
|
|
|
+ passio_popen=True)
|
|
|
+ p.communicate("/bin/echo $1")
|
|
|
+
|
|
|
+ p = self.testvm2.run("cat > /etc/qubes-rpc/test.Argument+argument",
|
|
|
+ user="root", passio_popen=True)
|
|
|
+ p.communicate("/bin/echo specific: $1")
|
|
|
+
|
|
|
+ with open("/etc/qubes-rpc/policy/test.Argument", "w") as policy:
|
|
|
+ policy.write("%s %s allow" % (self.testvm1.name, self.testvm2.name))
|
|
|
+ self.addCleanup(os.unlink, "/etc/qubes-rpc/policy/test.Argument")
|
|
|
+
|
|
|
+ p = self.testvm1.run("/usr/lib/qubes/qrexec-client-vm {} "
|
|
|
+ "test.Argument+argument".format(self.testvm2.name),
|
|
|
+ passio_popen=True)
|
|
|
+ (stdout, stderr) = p.communicate()
|
|
|
+ self.assertEqual(stdout, "specific: argument\n")
|
|
|
+
|
|
|
+ def test_084_qrexec_service_argument_extra_env(self):
|
|
|
+ """Qrexec service call with argument - extra env variables"""
|
|
|
+ self.testvm1.start()
|
|
|
+ self.testvm2.start()
|
|
|
+ p = self.testvm2.run("cat > /etc/qubes-rpc/test.Argument", user="root",
|
|
|
+ passio_popen=True)
|
|
|
+ p.communicate("/bin/echo $QREXEC_SERVICE_FULL_NAME "
|
|
|
+ "$QREXEC_SERVICE_ARGUMENT")
|
|
|
+
|
|
|
+ with open("/etc/qubes-rpc/policy/test.Argument", "w") as policy:
|
|
|
+ policy.write("%s %s allow" % (self.testvm1.name, self.testvm2.name))
|
|
|
+ self.addCleanup(os.unlink, "/etc/qubes-rpc/policy/test.Argument")
|
|
|
+
|
|
|
+ p = self.testvm1.run("/usr/lib/qubes/qrexec-client-vm {} "
|
|
|
+ "test.Argument+argument".format(self.testvm2.name),
|
|
|
+ passio_popen=True)
|
|
|
+ (stdout, stderr) = p.communicate()
|
|
|
+ self.assertEqual(stdout, "test.Argument+argument argument\n")
|
|
|
+
|
|
|
def test_100_qrexec_filecopy(self):
|
|
|
self.testvm1.start()
|
|
|
self.testvm2.start()
|
|
|
+ self.qrexec_policy('qubes.Filecopy', self.testvm1.name,
|
|
|
+ self.testvm2.name)
|
|
|
p = self.testvm1.run("qvm-copy-to-vm %s /etc/passwd" %
|
|
|
self.testvm2.name, passio_popen=True,
|
|
|
passio_stderr=True)
|
|
|
- # Confirm transfer
|
|
|
- self.enter_keys_in_window('Question', ['y'])
|
|
|
p.wait()
|
|
|
self.assertEqual(p.returncode, 0, "qvm-copy-to-vm failed: %s" %
|
|
|
p.stderr.read())
|
|
@@ -547,15 +655,34 @@ class TC_00_AppVMMixin(qubes.tests.SystemTestsMixin):
|
|
|
wait=True)
|
|
|
self.assertEqual(retcode, 0, "file differs")
|
|
|
|
|
|
- @unittest.skipUnless(spawn.find_executable('xdotool'),
|
|
|
- "xdotool not installed")
|
|
|
+ def test_105_qrexec_filemove(self):
|
|
|
+ self.testvm1.start()
|
|
|
+ self.testvm2.start()
|
|
|
+ self.qrexec_policy('qubes.Filecopy', self.testvm1.name,
|
|
|
+ self.testvm2.name)
|
|
|
+ retcode = self.testvm1.run("cp /etc/passwd passwd", wait=True)
|
|
|
+ assert retcode == 0, "Failed to prepare source file"
|
|
|
+ p = self.testvm1.run("qvm-move-to-vm %s passwd" %
|
|
|
+ self.testvm2.name, passio_popen=True,
|
|
|
+ passio_stderr=True)
|
|
|
+ p.wait()
|
|
|
+ self.assertEqual(p.returncode, 0, "qvm-move-to-vm failed: %s" %
|
|
|
+ p.stderr.read())
|
|
|
+ retcode = self.testvm2.run("diff /etc/passwd "
|
|
|
+ "/home/user/QubesIncoming/{}/passwd".format(
|
|
|
+ self.testvm1.name),
|
|
|
+ wait=True)
|
|
|
+ self.assertEqual(retcode, 0, "file differs")
|
|
|
+ retcode = self.testvm1.run("test -f passwd", wait=True)
|
|
|
+ self.assertEqual(retcode, 1, "source file not removed")
|
|
|
+
|
|
|
def test_101_qrexec_filecopy_with_autostart(self):
|
|
|
self.testvm1.start()
|
|
|
+ self.qrexec_policy('qubes.Filecopy', self.testvm1.name,
|
|
|
+ self.testvm2.name)
|
|
|
p = self.testvm1.run("qvm-copy-to-vm %s /etc/passwd" %
|
|
|
self.testvm2.name, passio_popen=True,
|
|
|
passio_stderr=True)
|
|
|
- # Confirm transfer
|
|
|
- self.enter_keys_in_window('Question', ['y'])
|
|
|
p.wait()
|
|
|
self.assertEqual(p.returncode, 0, "qvm-copy-to-vm failed: %s" %
|
|
|
p.stderr.read())
|
|
@@ -570,15 +697,13 @@ class TC_00_AppVMMixin(qubes.tests.SystemTestsMixin):
|
|
|
wait=True)
|
|
|
self.assertEqual(retcode, 0, "file differs")
|
|
|
|
|
|
- @unittest.skipUnless(spawn.find_executable('xdotool'),
|
|
|
- "xdotool not installed")
|
|
|
def test_110_qrexec_filecopy_deny(self):
|
|
|
self.testvm1.start()
|
|
|
self.testvm2.start()
|
|
|
+ self.qrexec_policy('qubes.Filecopy', self.testvm1.name,
|
|
|
+ self.testvm2.name, allow=False)
|
|
|
p = self.testvm1.run("qvm-copy-to-vm %s /etc/passwd" %
|
|
|
self.testvm2.name, passio_popen=True)
|
|
|
- # Deny transfer
|
|
|
- self.enter_keys_in_window('Question', ['n'])
|
|
|
p.wait()
|
|
|
self.assertNotEqual(p.returncode, 0, "qvm-copy-to-vm unexpectedly "
|
|
|
"succeeded")
|
|
@@ -590,15 +715,13 @@ class TC_00_AppVMMixin(qubes.tests.SystemTestsMixin):
|
|
|
|
|
|
@unittest.skip("Xen gntalloc driver crashes when page is mapped in the "
|
|
|
"same domain")
|
|
|
- @unittest.skipUnless(spawn.find_executable('xdotool'),
|
|
|
- "xdotool not installed")
|
|
|
def test_120_qrexec_filecopy_self(self):
|
|
|
self.testvm1.start()
|
|
|
+ self.qrexec_policy('qubes.Filecopy', self.testvm1.name,
|
|
|
+ self.testvm1.name)
|
|
|
p = self.testvm1.run("qvm-copy-to-vm %s /etc/passwd" %
|
|
|
self.testvm1.name, passio_popen=True,
|
|
|
passio_stderr=True)
|
|
|
- # Confirm transfer
|
|
|
- self.enter_keys_in_window('Question', ['y'])
|
|
|
p.wait()
|
|
|
self.assertEqual(p.returncode, 0, "qvm-copy-to-vm failed: %s" %
|
|
|
p.stderr.read())
|
|
@@ -613,6 +736,8 @@ class TC_00_AppVMMixin(qubes.tests.SystemTestsMixin):
|
|
|
def test_130_qrexec_filemove_disk_full(self):
|
|
|
self.testvm1.start()
|
|
|
self.testvm2.start()
|
|
|
+ self.qrexec_policy('qubes.Filecopy', self.testvm1.name,
|
|
|
+ self.testvm2.name)
|
|
|
# Prepare test file
|
|
|
prepare_cmd = ("yes teststring | dd of=testfile bs=1M "
|
|
|
"count=50 iflag=fullblock")
|
|
@@ -633,8 +758,6 @@ class TC_00_AppVMMixin(qubes.tests.SystemTestsMixin):
|
|
|
p = self.testvm1.run("qvm-move-to-vm %s testfile" %
|
|
|
self.testvm2.name, passio_popen=True,
|
|
|
passio_stderr=True)
|
|
|
- # Confirm transfer
|
|
|
- self.enter_keys_in_window('Question', ['y'])
|
|
|
# Close GUI error message
|
|
|
self.enter_keys_in_window('Error', ['Return'])
|
|
|
p.wait()
|
|
@@ -689,6 +812,10 @@ class TC_00_AppVMMixin(qubes.tests.SystemTestsMixin):
|
|
|
self.assertEquals(retcode, 0,
|
|
|
"qvm-sync-clock failed with code {}".
|
|
|
format(retcode))
|
|
|
+ # qvm-sync-clock is asynchronous - it spawns qubes.SetDateTime
|
|
|
+ # service, send it timestamp value and exists without waiting for
|
|
|
+ # actual time set
|
|
|
+ time.sleep(1)
|
|
|
(vm_time, _) = self.testvm1.run("date -u +%s",
|
|
|
passio_popen=True).communicate()
|
|
|
self.assertAlmostEquals(int(vm_time), int(start_time), delta=30)
|
|
@@ -733,7 +860,6 @@ class TC_00_AppVMMixin(qubes.tests.SystemTestsMixin):
|
|
|
# some safety margin for FS metadata
|
|
|
self.assertGreater(int(new_size.strip()), 5.8*1024**2)
|
|
|
|
|
|
-
|
|
|
class TC_05_StandaloneVM(qubes.tests.SystemTestsMixin, qubes.tests.QubesTestCase):
|
|
|
def test_000_create_start(self):
|
|
|
testvm1 = self.qc.add_new_vm("QubesAppVm",
|
|
@@ -1204,6 +1330,298 @@ class TC_40_PVGrub(qubes.tests.SystemTestsMixin):
|
|
|
(actual_kver, _) = p.communicate()
|
|
|
self.assertEquals(actual_kver.strip(), kver)
|
|
|
|
|
|
+@unittest.skipUnless(
|
|
|
+ spawn.find_executable('xprop') and
|
|
|
+ spawn.find_executable('xdotool') and
|
|
|
+ spawn.find_executable('wmctrl'),
|
|
|
+ "xprop or xdotool or wmctrl not installed")
|
|
|
+class TC_50_MimeHandlers(qubes.tests.SystemTestsMixin):
|
|
|
+ @classmethod
|
|
|
+ def setUpClass(cls):
|
|
|
+ if cls.template == 'whonix-gw' or 'minimal' in cls.template:
|
|
|
+ raise unittest.SkipTest(
|
|
|
+ 'Template {} not supported by this test'.format(cls.template))
|
|
|
+
|
|
|
+ if cls.template == 'whonix-ws':
|
|
|
+ # TODO remove when Whonix-based DispVMs will work (Whonix 13?)
|
|
|
+ raise unittest.SkipTest(
|
|
|
+ 'Template {} not supported by this test'.format(cls.template))
|
|
|
+
|
|
|
+ qc = QubesVmCollection()
|
|
|
+
|
|
|
+ cls._kill_test_vms(qc, prefix=qubes.tests.CLSVMPREFIX)
|
|
|
+
|
|
|
+ qc.lock_db_for_writing()
|
|
|
+ qc.load()
|
|
|
+
|
|
|
+ cls._remove_test_vms(qc, qubes.qubes.vmm.libvirt_conn,
|
|
|
+ prefix=qubes.tests.CLSVMPREFIX)
|
|
|
+
|
|
|
+ cls.source_vmname = cls.make_vm_name('source', True)
|
|
|
+ source_vm = qc.add_new_vm("QubesAppVm",
|
|
|
+ template=qc.get_vm_by_name(cls.template),
|
|
|
+ name=cls.source_vmname)
|
|
|
+ source_vm.create_on_disk(verbose=False)
|
|
|
+
|
|
|
+ cls.target_vmname = cls.make_vm_name('target', True)
|
|
|
+ target_vm = qc.add_new_vm("QubesAppVm",
|
|
|
+ template=qc.get_vm_by_name(cls.template),
|
|
|
+ name=cls.target_vmname)
|
|
|
+ target_vm.create_on_disk(verbose=False)
|
|
|
+
|
|
|
+ qc.save()
|
|
|
+ qc.unlock_db()
|
|
|
+ source_vm.start()
|
|
|
+ target_vm.start()
|
|
|
+
|
|
|
+ # make sure that DispVMs will be started of the same template
|
|
|
+ retcode = subprocess.call(['/usr/bin/qvm-create-default-dvm',
|
|
|
+ cls.template],
|
|
|
+ stderr=open(os.devnull, 'w'))
|
|
|
+ assert retcode == 0, "Error preparing DispVM"
|
|
|
+
|
|
|
+ def setUp(self):
|
|
|
+ super(TC_50_MimeHandlers, self).setUp()
|
|
|
+ self.source_vm = self.qc.get_vm_by_name(self.source_vmname)
|
|
|
+ self.target_vm = self.qc.get_vm_by_name(self.target_vmname)
|
|
|
+
|
|
|
+ def get_window_class(self, winid, dispvm=False):
|
|
|
+ (vm_winid, _) = subprocess.Popen(
|
|
|
+ ['xprop', '-id', winid, '_QUBES_VMWINDOWID'],
|
|
|
+ stdout=subprocess.PIPE
|
|
|
+ ).communicate()
|
|
|
+ vm_winid = vm_winid.split("#")[1].strip('\n" ')
|
|
|
+ if dispvm:
|
|
|
+ (vmname, _) = subprocess.Popen(
|
|
|
+ ['xprop', '-id', winid, '_QUBES_VMNAME'],
|
|
|
+ stdout=subprocess.PIPE
|
|
|
+ ).communicate()
|
|
|
+ vmname = vmname.split("=")[1].strip('\n" ')
|
|
|
+ window_class = None
|
|
|
+ while window_class is None:
|
|
|
+ # XXX to use self.qc.get_vm_by_name would require reloading
|
|
|
+ # qubes.xml, so use qvm-run instead
|
|
|
+ xprop = subprocess.Popen(
|
|
|
+ ['qvm-run', '-p', vmname, 'xprop -id {} WM_CLASS'.format(
|
|
|
+ vm_winid)], stdout=subprocess.PIPE)
|
|
|
+ (window_class, _) = xprop.communicate()
|
|
|
+ if xprop.returncode != 0:
|
|
|
+ self.skipTest("xprop failed, not installed?")
|
|
|
+ if 'not found' in window_class:
|
|
|
+ # WM_CLASS not set yet, wait a little
|
|
|
+ time.sleep(0.1)
|
|
|
+ window_class = None
|
|
|
+ else:
|
|
|
+ window_class = None
|
|
|
+ while window_class is None:
|
|
|
+ xprop = self.target_vm.run(
|
|
|
+ 'xprop -id {} WM_CLASS'.format(vm_winid),
|
|
|
+ passio_popen=True)
|
|
|
+ (window_class, _) = xprop.communicate()
|
|
|
+ if xprop.returncode != 0:
|
|
|
+ self.skipTest("xprop failed, not installed?")
|
|
|
+ if 'not found' in window_class:
|
|
|
+ # WM_CLASS not set yet, wait a little
|
|
|
+ time.sleep(0.1)
|
|
|
+ window_class = None
|
|
|
+ # output: WM_CLASS(STRING) = "gnome-terminal-server", "Gnome-terminal"
|
|
|
+ try:
|
|
|
+ window_class = window_class.split("=")[1].split(",")[0].strip('\n" ')
|
|
|
+ except IndexError:
|
|
|
+ raise Exception(
|
|
|
+ "Unexpected output from xprop: '{}'".format(window_class))
|
|
|
+
|
|
|
+ return window_class
|
|
|
+
|
|
|
+ def open_file_and_check_viewer(self, filename, expected_app_titles,
|
|
|
+ expected_app_classes, dispvm=False):
|
|
|
+ self.qc.unlock_db()
|
|
|
+ if dispvm:
|
|
|
+ p = self.source_vm.run("qvm-open-in-dvm {}".format(filename),
|
|
|
+ passio_popen=True)
|
|
|
+ vmpattern = "disp*"
|
|
|
+ else:
|
|
|
+ self.qrexec_policy('qubes.Filecopy', self.source_vm.name,
|
|
|
+ self.target_vmname)
|
|
|
+ p = self.source_vm.run("qvm-open-in-vm {} {}".format(
|
|
|
+ self.target_vmname, filename), passio_popen=True)
|
|
|
+ vmpattern = self.target_vmname
|
|
|
+ wait_count = 0
|
|
|
+ winid = None
|
|
|
+ window_title = None
|
|
|
+ while True:
|
|
|
+ search = subprocess.Popen(['xdotool', 'search',
|
|
|
+ '--onlyvisible', '--class', vmpattern],
|
|
|
+ stdout=subprocess.PIPE,
|
|
|
+ stderr=open(os.path.devnull, 'w'))
|
|
|
+ retcode = search.wait()
|
|
|
+ if retcode == 0:
|
|
|
+ winid = search.stdout.read().strip()
|
|
|
+ # get window title
|
|
|
+ (window_title, _) = subprocess.Popen(
|
|
|
+ ['xdotool', 'getwindowname', winid], stdout=subprocess.PIPE). \
|
|
|
+ communicate()
|
|
|
+ window_title = window_title.strip()
|
|
|
+ # ignore LibreOffice splash screen and window with no title
|
|
|
+ # set yet
|
|
|
+ if window_title and not window_title.startswith("LibreOffice")\
|
|
|
+ and not window_title == 'VMapp command':
|
|
|
+ break
|
|
|
+ wait_count += 1
|
|
|
+ if wait_count > 100:
|
|
|
+ self.fail("Timeout while waiting for editor window")
|
|
|
+ time.sleep(0.3)
|
|
|
+
|
|
|
+ # get window class
|
|
|
+ window_class = self.get_window_class(winid, dispvm)
|
|
|
+ # close the window - we've got the window class, it is no longer needed
|
|
|
+ subprocess.check_call(['wmctrl', '-i', '-c', winid])
|
|
|
+ p.wait()
|
|
|
+ self.wait_for_window(window_title, show=False)
|
|
|
+
|
|
|
+ def check_matches(obj, patterns):
|
|
|
+ return any((pat.search(obj) if isinstance(pat, type(re.compile('')))
|
|
|
+ else pat in obj) for pat in patterns)
|
|
|
+
|
|
|
+ if not check_matches(window_title, expected_app_titles) and \
|
|
|
+ not check_matches(window_class, expected_app_classes):
|
|
|
+ self.fail("Opening file {} resulted in window '{} ({})', which is "
|
|
|
+ "none of {!r} ({!r})".format(
|
|
|
+ filename, window_title, window_class,
|
|
|
+ expected_app_titles, expected_app_classes))
|
|
|
+
|
|
|
+ def prepare_txt(self, filename):
|
|
|
+ p = self.source_vm.run("cat > {}".format(filename), passio_popen=True)
|
|
|
+ p.stdin.write("This is test\n")
|
|
|
+ p.stdin.close()
|
|
|
+ retcode = p.wait()
|
|
|
+ assert retcode == 0, "Failed to write {} file".format(filename)
|
|
|
+
|
|
|
+ def prepare_pdf(self, filename):
|
|
|
+ self.prepare_txt("/tmp/source.txt")
|
|
|
+ cmd = "convert /tmp/source.txt {}".format(filename)
|
|
|
+ retcode = self.source_vm.run(cmd, wait=True)
|
|
|
+ assert retcode == 0, "Failed to run '{}'".format(cmd)
|
|
|
+
|
|
|
+ def prepare_doc(self, filename):
|
|
|
+ self.prepare_txt("/tmp/source.txt")
|
|
|
+ cmd = "unoconv -f doc -o {} /tmp/source.txt".format(filename)
|
|
|
+ retcode = self.source_vm.run(cmd, wait=True)
|
|
|
+ if retcode != 0:
|
|
|
+ self.skipTest("Failed to run '{}', not installed?".format(cmd))
|
|
|
+
|
|
|
+ def prepare_pptx(self, filename):
|
|
|
+ self.prepare_txt("/tmp/source.txt")
|
|
|
+ cmd = "unoconv -f pptx -o {} /tmp/source.txt".format(filename)
|
|
|
+ retcode = self.source_vm.run(cmd, wait=True)
|
|
|
+ if retcode != 0:
|
|
|
+ self.skipTest("Failed to run '{}', not installed?".format(cmd))
|
|
|
+
|
|
|
+ def prepare_png(self, filename):
|
|
|
+ self.prepare_txt("/tmp/source.txt")
|
|
|
+ cmd = "convert /tmp/source.txt {}".format(filename)
|
|
|
+ retcode = self.source_vm.run(cmd, wait=True)
|
|
|
+ if retcode != 0:
|
|
|
+ self.skipTest("Failed to run '{}', not installed?".format(cmd))
|
|
|
+
|
|
|
+ def prepare_jpg(self, filename):
|
|
|
+ self.prepare_txt("/tmp/source.txt")
|
|
|
+ cmd = "convert /tmp/source.txt {}".format(filename)
|
|
|
+ retcode = self.source_vm.run(cmd, wait=True)
|
|
|
+ if retcode != 0:
|
|
|
+ self.skipTest("Failed to run '{}', not installed?".format(cmd))
|
|
|
+
|
|
|
+ def test_000_txt(self):
|
|
|
+ filename = "/home/user/test_file.txt"
|
|
|
+ self.prepare_txt(filename)
|
|
|
+ self.open_file_and_check_viewer(filename, ["vim"],
|
|
|
+ ["gedit", "emacs"])
|
|
|
+
|
|
|
+ def test_001_pdf(self):
|
|
|
+ filename = "/home/user/test_file.pdf"
|
|
|
+ self.prepare_pdf(filename)
|
|
|
+ self.open_file_and_check_viewer(filename, [],
|
|
|
+ ["evince"])
|
|
|
+
|
|
|
+ def test_002_doc(self):
|
|
|
+ filename = "/home/user/test_file.doc"
|
|
|
+ self.prepare_doc(filename)
|
|
|
+ self.open_file_and_check_viewer(filename, [],
|
|
|
+ ["libreoffice", "abiword"])
|
|
|
+
|
|
|
+ def test_003_pptx(self):
|
|
|
+ filename = "/home/user/test_file.pptx"
|
|
|
+ self.prepare_pptx(filename)
|
|
|
+ self.open_file_and_check_viewer(filename, [],
|
|
|
+ ["libreoffice"])
|
|
|
+
|
|
|
+ def test_004_png(self):
|
|
|
+ filename = "/home/user/test_file.png"
|
|
|
+ self.prepare_png(filename)
|
|
|
+ self.open_file_and_check_viewer(filename, [],
|
|
|
+ ["shotwell", "eog", "display"])
|
|
|
+
|
|
|
+ def test_005_jpg(self):
|
|
|
+ filename = "/home/user/test_file.jpg"
|
|
|
+ self.prepare_jpg(filename)
|
|
|
+ self.open_file_and_check_viewer(filename, [],
|
|
|
+ ["shotwell", "eog", "display"])
|
|
|
+
|
|
|
+ def test_006_jpeg(self):
|
|
|
+ filename = "/home/user/test_file.jpeg"
|
|
|
+ self.prepare_jpg(filename)
|
|
|
+ self.open_file_and_check_viewer(filename, [],
|
|
|
+ ["shotwell", "eog", "display"])
|
|
|
+
|
|
|
+ def test_100_txt_dispvm(self):
|
|
|
+ filename = "/home/user/test_file.txt"
|
|
|
+ self.prepare_txt(filename)
|
|
|
+ self.open_file_and_check_viewer(filename, ["vim"],
|
|
|
+ ["gedit", "emacs"],
|
|
|
+ dispvm=True)
|
|
|
+
|
|
|
+ def test_101_pdf_dispvm(self):
|
|
|
+ filename = "/home/user/test_file.pdf"
|
|
|
+ self.prepare_pdf(filename)
|
|
|
+ self.open_file_and_check_viewer(filename, [],
|
|
|
+ ["evince"],
|
|
|
+ dispvm=True)
|
|
|
+
|
|
|
+ def test_102_doc_dispvm(self):
|
|
|
+ filename = "/home/user/test_file.doc"
|
|
|
+ self.prepare_doc(filename)
|
|
|
+ self.open_file_and_check_viewer(filename, [],
|
|
|
+ ["libreoffice", "abiword"],
|
|
|
+ dispvm=True)
|
|
|
+
|
|
|
+ def test_103_pptx_dispvm(self):
|
|
|
+ filename = "/home/user/test_file.pptx"
|
|
|
+ self.prepare_pptx(filename)
|
|
|
+ self.open_file_and_check_viewer(filename, [],
|
|
|
+ ["libreoffice"],
|
|
|
+ dispvm=True)
|
|
|
+
|
|
|
+ def test_104_png_dispvm(self):
|
|
|
+ filename = "/home/user/test_file.png"
|
|
|
+ self.prepare_png(filename)
|
|
|
+ self.open_file_and_check_viewer(filename, [],
|
|
|
+ ["shotwell", "eog", "display"],
|
|
|
+ dispvm=True)
|
|
|
+
|
|
|
+ def test_105_jpg_dispvm(self):
|
|
|
+ filename = "/home/user/test_file.jpg"
|
|
|
+ self.prepare_jpg(filename)
|
|
|
+ self.open_file_and_check_viewer(filename, [],
|
|
|
+ ["shotwell", "eog", "display"],
|
|
|
+ dispvm=True)
|
|
|
+
|
|
|
+ def test_106_jpeg_dispvm(self):
|
|
|
+ filename = "/home/user/test_file.jpeg"
|
|
|
+ self.prepare_jpg(filename)
|
|
|
+ self.open_file_and_check_viewer(filename, [],
|
|
|
+ ["shotwell", "eog", "display"],
|
|
|
+ dispvm=True)
|
|
|
+
|
|
|
|
|
|
def load_tests(loader, tests, pattern):
|
|
|
try:
|
|
@@ -1233,4 +1651,10 @@ def load_tests(loader, tests, pattern):
|
|
|
(TC_40_PVGrub, qubes.tests.QubesTestCase),
|
|
|
{'template': template})))
|
|
|
|
|
|
+ tests.addTests(loader.loadTestsFromTestCase(
|
|
|
+ type(
|
|
|
+ 'TC_50_MimeHandlers_' + template,
|
|
|
+ (TC_50_MimeHandlers, qubes.tests.QubesTestCase),
|
|
|
+ {'template': template})))
|
|
|
+
|
|
|
return tests
|