|
@@ -114,6 +114,8 @@ class TC_00_AppVMMixin(object):
|
|
|
def test_011_run_gnome_terminal(self):
|
|
|
if "minimal" in self.template:
|
|
|
self.skipTest("Minimal template doesn't have 'gnome-terminal'")
|
|
|
+ if 'whonix' in self.template:
|
|
|
+ self.skipTest("Whonix template doesn't have 'gnome-terminal'")
|
|
|
self.loop.run_until_complete(self.testvm1.start())
|
|
|
self.assertEqual(self.testvm1.get_power_state(), "Running")
|
|
|
self.loop.run_until_complete(self.wait_for_session(self.testvm1))
|
|
@@ -221,7 +223,6 @@ class TC_00_AppVMMixin(object):
|
|
|
self.assertFalse(stderr,
|
|
|
'Some data was printed to stderr')
|
|
|
|
|
|
- @unittest.skip('#2851, because there is no GUI in vm')
|
|
|
def test_051_qrexec_simple_eof_reverse(self):
|
|
|
"""Test for EOF transmission VM->dom0"""
|
|
|
|
|
@@ -239,7 +240,7 @@ class TC_00_AppVMMixin(object):
|
|
|
p.stdin.write(TEST_DATA)
|
|
|
yield from p.stdin.drain()
|
|
|
p.stdin.close()
|
|
|
- self.assertEqual(stdout.strip(), 'test',
|
|
|
+ self.assertEqual(stdout.strip(), b'test',
|
|
|
'Received data differs from what was expected')
|
|
|
# this may hang in some buggy cases
|
|
|
self.assertFalse((yield from p.stderr.read()),
|
|
@@ -252,15 +253,18 @@ class TC_00_AppVMMixin(object):
|
|
|
"probably EOF wasn't transferred from the VM process")
|
|
|
|
|
|
self.loop.run_until_complete(self.testvm1.start())
|
|
|
+ self.loop.run_until_complete(self.wait_for_session(self.testvm1))
|
|
|
self.loop.run_until_complete(run(self))
|
|
|
|
|
|
- @unittest.skip('#2851, because there is no GUI in vm')
|
|
|
def test_052_qrexec_vm_service_eof(self):
|
|
|
"""Test for EOF transmission VM(src)->VM(dst)"""
|
|
|
|
|
|
self.loop.run_until_complete(asyncio.wait([
|
|
|
self.testvm1.start(),
|
|
|
self.testvm2.start()]))
|
|
|
+ self.loop.run_until_complete(asyncio.wait([
|
|
|
+ self.wait_for_session(self.testvm1),
|
|
|
+ self.wait_for_session(self.testvm2)]))
|
|
|
self.loop.run_until_complete(self.testvm2.run_for_stdio(
|
|
|
'cat > /etc/qubes-rpc/test.EOF',
|
|
|
user='root',
|
|
@@ -277,7 +281,7 @@ class TC_00_AppVMMixin(object):
|
|
|
except asyncio.TimeoutError:
|
|
|
self.fail("Timeout, probably EOF wasn't transferred")
|
|
|
|
|
|
- self.assertEqual(stdout, b'test',
|
|
|
+ self.assertEqual(stdout, b'test\n',
|
|
|
'Received data differs from what was expected')
|
|
|
|
|
|
@unittest.expectedFailure
|
|
@@ -398,23 +402,14 @@ class TC_00_AppVMMixin(object):
|
|
|
except asyncio.TimeoutError:
|
|
|
self.fail('Timeout, probably deadlock')
|
|
|
|
|
|
- @unittest.skip('localcmd= argument went away')
|
|
|
def test_071_qrexec_dom0_simultaneous_write(self):
|
|
|
"""Test for simultaneous write in dom0(src)->VM(dst) connection
|
|
|
|
|
|
Similar to test_070_qrexec_vm_simultaneous_write, but with dom0
|
|
|
as a source.
|
|
|
"""
|
|
|
- def run(self):
|
|
|
- result.value = self.testvm2.run_service(
|
|
|
- "test.write", localcmd="/bin/sh -c '"
|
|
|
- # first write a lot of data to fill all the buffers
|
|
|
- "dd if=/dev/zero bs=993 count=10000 iflag=fullblock & "
|
|
|
- # then after some time start reading
|
|
|
- "sleep 1; "
|
|
|
- "dd of=/dev/null bs=993 count=10000 iflag=fullblock; "
|
|
|
- "wait"
|
|
|
- "'")
|
|
|
+
|
|
|
+ self.loop.run_until_complete(self.testvm2.start())
|
|
|
|
|
|
self.create_remote_file(self.testvm2, '/etc/qubes-rpc/test.write', '''\
|
|
|
# first write a lot of data
|
|
@@ -422,58 +417,93 @@ class TC_00_AppVMMixin(object):
|
|
|
# and only then read something
|
|
|
dd of=/dev/null bs=993 count=10000 iflag=fullblock
|
|
|
''')
|
|
|
- self.create_local_file('/etc/qubes-rpc/policy/test.write',
|
|
|
- '{} {} allow'.format(self.testvm1.name, self.testvm2.name))
|
|
|
-
|
|
|
- t = multiprocessing.Process(target=run, args=(self,))
|
|
|
- t.start()
|
|
|
- t.join(timeout=10)
|
|
|
- if t.is_alive():
|
|
|
- t.terminate()
|
|
|
+
|
|
|
+ # can't use subprocess.PIPE, because asyncio will claim those FDs
|
|
|
+ pipe1_r, pipe1_w = os.pipe()
|
|
|
+ pipe2_r, pipe2_w = os.pipe()
|
|
|
+ try:
|
|
|
+ local_proc = self.loop.run_until_complete(
|
|
|
+ asyncio.create_subprocess_shell(
|
|
|
+ # first write a lot of data to fill all the buffers
|
|
|
+ "dd if=/dev/zero bs=993 count=10000 iflag=fullblock & "
|
|
|
+ # then after some time start reading
|
|
|
+ "sleep 1; "
|
|
|
+ "dd of=/dev/null bs=993 count=10000 iflag=fullblock; "
|
|
|
+ "wait", stdin=pipe1_r, stdout=pipe2_w))
|
|
|
+
|
|
|
+ service_proc = self.loop.run_until_complete(self.testvm2.run_service(
|
|
|
+ "test.write", stdin=pipe2_r, stdout=pipe1_w))
|
|
|
+ finally:
|
|
|
+ os.close(pipe1_r)
|
|
|
+ os.close(pipe1_w)
|
|
|
+ os.close(pipe2_r)
|
|
|
+ os.close(pipe2_w)
|
|
|
+
|
|
|
+ try:
|
|
|
+ self.loop.run_until_complete(
|
|
|
+ asyncio.wait_for(service_proc.wait(), timeout=10))
|
|
|
+ except asyncio.TimeoutError:
|
|
|
self.fail("Timeout, probably deadlock")
|
|
|
- self.assertEqual(result.value, 0, "Service call failed")
|
|
|
+ else:
|
|
|
+ self.assertEqual(service_proc.returncode, 0,
|
|
|
+ "Service call failed")
|
|
|
+ finally:
|
|
|
+ try:
|
|
|
+ service_proc.terminate()
|
|
|
+ except ProcessLookupError:
|
|
|
+ pass
|
|
|
|
|
|
- @unittest.skip('localcmd= argument went away')
|
|
|
def test_072_qrexec_to_dom0_simultaneous_write(self):
|
|
|
"""Test for simultaneous write in dom0(src)<-VM(dst) connection
|
|
|
|
|
|
Similar to test_071_qrexec_dom0_simultaneous_write, but with dom0
|
|
|
as a "hanging" side.
|
|
|
"""
|
|
|
- result = multiprocessing.Value('i', -1)
|
|
|
-
|
|
|
- def run(self):
|
|
|
- result.value = self.testvm2.run_service(
|
|
|
- "test.write", localcmd="/bin/sh -c '"
|
|
|
- # first write a lot of data to fill all the buffers
|
|
|
- "dd if=/dev/zero bs=993 count=10000 iflag=fullblock "
|
|
|
- # then, only when all written, read something
|
|
|
- "dd of=/dev/null bs=993 count=10000 iflag=fullblock; "
|
|
|
- "'")
|
|
|
|
|
|
self.loop.run_until_complete(self.testvm2.start())
|
|
|
- p = self.testvm2.run("cat > /etc/qubes-rpc/test.write", user="root",
|
|
|
- passio_popen=True)
|
|
|
- # first write a lot of data
|
|
|
- p.stdin.write(b"dd if=/dev/zero bs=993 count=10000 iflag=fullblock &\n")
|
|
|
- # and only then read something
|
|
|
- p.stdin.write(b"dd of=/dev/null bs=993 count=10000 iflag=fullblock\n")
|
|
|
- p.stdin.write(b"sleep 1; \n")
|
|
|
- p.stdin.write(b"wait\n")
|
|
|
- p.stdin.close()
|
|
|
- p.wait()
|
|
|
- policy = open("/etc/qubes-rpc/policy/test.write", "w")
|
|
|
- policy.write("%s %s allow" % (self.testvm1.name, self.testvm2.name))
|
|
|
- policy.close()
|
|
|
- self.addCleanup(os.unlink, "/etc/qubes-rpc/policy/test.write")
|
|
|
|
|
|
- t = multiprocessing.Process(target=run, args=(self,))
|
|
|
- t.start()
|
|
|
- t.join(timeout=10)
|
|
|
- if t.is_alive():
|
|
|
- t.terminate()
|
|
|
+ self.create_remote_file(self.testvm2, '/etc/qubes-rpc/test.write', '''\
|
|
|
+ # first write a lot of data
|
|
|
+ dd if=/dev/zero bs=993 count=10000 iflag=fullblock &
|
|
|
+ # and only then read something
|
|
|
+ dd of=/dev/null bs=993 count=10000 iflag=fullblock
|
|
|
+ sleep 1;
|
|
|
+ wait
|
|
|
+ ''')
|
|
|
+
|
|
|
+ # can't use subprocess.PIPE, because asyncio will claim those FDs
|
|
|
+ pipe1_r, pipe1_w = os.pipe()
|
|
|
+ pipe2_r, pipe2_w = os.pipe()
|
|
|
+ try:
|
|
|
+ local_proc = self.loop.run_until_complete(
|
|
|
+ asyncio.create_subprocess_shell(
|
|
|
+ # first write a lot of data to fill all the buffers
|
|
|
+ "dd if=/dev/zero bs=993 count=10000 iflag=fullblock & "
|
|
|
+ # then, only when all written, read something
|
|
|
+ "dd of=/dev/null bs=993 count=10000 iflag=fullblock; ",
|
|
|
+ stdin=pipe1_r, stdout=pipe2_w))
|
|
|
+
|
|
|
+ service_proc = self.loop.run_until_complete(self.testvm2.run_service(
|
|
|
+ "test.write", stdin=pipe2_r, stdout=pipe1_w))
|
|
|
+ finally:
|
|
|
+ os.close(pipe1_r)
|
|
|
+ os.close(pipe1_w)
|
|
|
+ os.close(pipe2_r)
|
|
|
+ os.close(pipe2_w)
|
|
|
+
|
|
|
+ try:
|
|
|
+ self.loop.run_until_complete(
|
|
|
+ asyncio.wait_for(service_proc.wait(), timeout=10))
|
|
|
+ except asyncio.TimeoutError:
|
|
|
self.fail("Timeout, probably deadlock")
|
|
|
- self.assertEqual(result.value, 0, "Service call failed")
|
|
|
+ else:
|
|
|
+ self.assertEqual(service_proc.returncode, 0,
|
|
|
+ "Service call failed")
|
|
|
+ finally:
|
|
|
+ try:
|
|
|
+ service_proc.terminate()
|
|
|
+ except ProcessLookupError:
|
|
|
+ pass
|
|
|
|
|
|
def test_080_qrexec_service_argument_allow_default(self):
|
|
|
"""Qrexec service call with argument"""
|
|
@@ -746,7 +776,8 @@ class TC_00_AppVMMixin(object):
|
|
|
if self.template.startswith('whonix-'):
|
|
|
self.skipTest('qvm-sync-clock disabled for Whonix VMs')
|
|
|
self.loop.run_until_complete(asyncio.wait([
|
|
|
- self.testvm1.start()]))
|
|
|
+ self.testvm1.start(),
|
|
|
+ self.testvm2.start(),]))
|
|
|
start_time = subprocess.check_output(['date', '-u', '+%s'])
|
|
|
|
|
|
try:
|
|
@@ -756,11 +787,11 @@ class TC_00_AppVMMixin(object):
|
|
|
subprocess.check_call(['sudo', 'date', '-s', '2001-01-01T12:34:56'],
|
|
|
stdout=subprocess.DEVNULL)
|
|
|
self.loop.run_until_complete(
|
|
|
- self.testvm1.run_for_stdio('date -s 2001-01-01T12:34:56',
|
|
|
+ self.testvm2.run_for_stdio('date -s 2001-01-01T12:34:56',
|
|
|
user='root'))
|
|
|
|
|
|
self.loop.run_until_complete(
|
|
|
- self.testvm1.run_for_stdio('qvm-sync-clock',
|
|
|
+ self.testvm2.run_for_stdio('qvm-sync-clock',
|
|
|
user='root'))
|
|
|
|
|
|
p = self.loop.run_until_complete(
|
|
@@ -769,7 +800,7 @@ class TC_00_AppVMMixin(object):
|
|
|
self.loop.run_until_complete(p.wait())
|
|
|
self.assertEqual(p.returncode, 0)
|
|
|
vm_time, _ = self.loop.run_until_complete(
|
|
|
- self.testvm1.run_for_stdio('date -u +%s'))
|
|
|
+ self.testvm2.run_for_stdio('date -u +%s'))
|
|
|
self.assertAlmostEquals(int(vm_time), int(start_time), delta=30)
|
|
|
|
|
|
dom0_time = subprocess.check_output(['date', '-u', '+%s'])
|
|
@@ -786,6 +817,8 @@ class TC_00_AppVMMixin(object):
|
|
|
@unittest.skipUnless(spawn.find_executable('parecord'),
|
|
|
"pulseaudio-utils not installed in dom0")
|
|
|
def test_220_audio_playback(self):
|
|
|
+ if 'whonix-gw' in self.template:
|
|
|
+ self.skipTest('whonix-gw have no audio')
|
|
|
self.loop.run_until_complete(self.testvm1.start())
|
|
|
try:
|
|
|
self.loop.run_until_complete(
|
|
@@ -847,6 +880,8 @@ class TC_00_AppVMMixin(object):
|
|
|
@unittest.skipUnless(spawn.find_executable('parecord'),
|
|
|
"pulseaudio-utils not installed in dom0")
|
|
|
def test_221_audio_record_muted(self):
|
|
|
+ if 'whonix-gw' in self.template:
|
|
|
+ self.skipTest('whonix-gw have no audio')
|
|
|
self.loop.run_until_complete(self.testvm1.start())
|
|
|
try:
|
|
|
self.loop.run_until_complete(
|
|
@@ -886,6 +921,8 @@ class TC_00_AppVMMixin(object):
|
|
|
@unittest.skipUnless(spawn.find_executable('parecord'),
|
|
|
"pulseaudio-utils not installed in dom0")
|
|
|
def test_222_audio_record_unmuted(self):
|
|
|
+ if 'whonix-gw' in self.template:
|
|
|
+ self.skipTest('whonix-gw have no audio')
|
|
|
self.loop.run_until_complete(self.testvm1.start())
|
|
|
try:
|
|
|
self.loop.run_until_complete(
|
|
@@ -1028,10 +1065,10 @@ int main(int argc, char **argv) {
|
|
|
input=allocator_c.encode())
|
|
|
|
|
|
try:
|
|
|
- stdout, stderr = yield from self.testvm1.run_for_stdio(
|
|
|
+ yield from self.testvm1.run_for_stdio(
|
|
|
'gcc allocator.c -o allocator')
|
|
|
- except subprocess.CalledProcessError:
|
|
|
- self.skipTest('allocator compile failed: {}'.format(stderr))
|
|
|
+ except subprocess.CalledProcessError as e:
|
|
|
+ self.skipTest('allocator compile failed: {}'.format(e.stderr))
|
|
|
|
|
|
# drop caches to have even more memory pressure
|
|
|
yield from self.testvm1.run_for_stdio(
|