xref: /qemu/tests/avocado/vnc.py (revision ec6f3fc3)
1# Simple functional tests for VNC functionality
2#
3# Copyright (c) 2018 Red Hat, Inc.
4#
5# Author:
6#  Cleber Rosa <crosa@redhat.com>
7#
8# This work is licensed under the terms of the GNU GPL, version 2 or
9# later.  See the COPYING file in the top-level directory.
10
11import socket
12from typing import List
13
14from avocado_qemu import QemuSystemTest
15
16
17VNC_ADDR = '127.0.0.1'
18VNC_PORT_START = 32768
19VNC_PORT_END = VNC_PORT_START + 1024
20
21
22def check_bind(port: int) -> bool:
23    with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as sock:
24        try:
25            sock.bind((VNC_ADDR, port))
26        except OSError:
27            return False
28
29    return True
30
31
32def check_connect(port: int) -> bool:
33    with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as sock:
34        try:
35            sock.connect((VNC_ADDR, port))
36        except ConnectionRefusedError:
37            return False
38
39    return True
40
41
42def find_free_ports(count: int) -> List[int]:
43    result = []
44    for port in range(VNC_PORT_START, VNC_PORT_END):
45        if check_bind(port):
46            result.append(port)
47            if len(result) >= count:
48                break
49    assert len(result) == count
50    return result
51
52
53class Vnc(QemuSystemTest):
54    """
55    :avocado: tags=vnc,quick
56    :avocado: tags=machine:none
57    """
58    def test_no_vnc(self):
59        self.vm.add_args('-nodefaults', '-S')
60        self.vm.launch()
61        self.assertFalse(self.vm.qmp('query-vnc')['return']['enabled'])
62
63    def test_no_vnc_change_password(self):
64        self.vm.add_args('-nodefaults', '-S')
65        self.vm.launch()
66        self.assertFalse(self.vm.qmp('query-vnc')['return']['enabled'])
67        set_password_response = self.vm.qmp('change-vnc-password',
68                                            password='new_password')
69        self.assertIn('error', set_password_response)
70        self.assertEqual(set_password_response['error']['class'],
71                         'GenericError')
72        self.assertEqual(set_password_response['error']['desc'],
73                         'Could not set password')
74
75    def test_change_password_requires_a_password(self):
76        self.vm.add_args('-nodefaults', '-S', '-vnc', ':0')
77        self.vm.launch()
78        self.assertTrue(self.vm.qmp('query-vnc')['return']['enabled'])
79        set_password_response = self.vm.qmp('change-vnc-password',
80                                            password='new_password')
81        self.assertIn('error', set_password_response)
82        self.assertEqual(set_password_response['error']['class'],
83                         'GenericError')
84        self.assertEqual(set_password_response['error']['desc'],
85                         'Could not set password')
86
87    def test_change_password(self):
88        self.vm.add_args('-nodefaults', '-S', '-vnc', ':0,password=on')
89        self.vm.launch()
90        self.assertTrue(self.vm.qmp('query-vnc')['return']['enabled'])
91        self.vm.cmd('change-vnc-password',
92                    password='new_password')
93
94    def test_change_listen(self):
95        a, b, c = find_free_ports(3)
96        self.assertFalse(check_connect(a))
97        self.assertFalse(check_connect(b))
98        self.assertFalse(check_connect(c))
99
100        self.vm.add_args('-nodefaults', '-S', '-vnc', f'{VNC_ADDR}:{a - 5900}')
101        self.vm.launch()
102        self.assertEqual(self.vm.qmp('query-vnc')['return']['service'], str(a))
103        self.assertTrue(check_connect(a))
104        self.assertFalse(check_connect(b))
105        self.assertFalse(check_connect(c))
106
107        self.vm.cmd('display-update', type='vnc',
108                    addresses=[{'type': 'inet', 'host': VNC_ADDR,
109                                'port': str(b)},
110                               {'type': 'inet', 'host': VNC_ADDR,
111                                'port': str(c)}])
112        self.assertEqual(self.vm.qmp('query-vnc')['return']['service'], str(b))
113        self.assertFalse(check_connect(a))
114        self.assertTrue(check_connect(b))
115        self.assertTrue(check_connect(c))
116