Skip to content

Commit 16a88e6

Browse files
authoredNov 4, 2016
Merge pull request #3719 from elpaso/auth_tests_more_master
Auth tests more master
2 parents ea43ce0 + f587def commit 16a88e6

File tree

6 files changed

+308
-24
lines changed

6 files changed

+308
-24
lines changed
 

‎tests/src/python/CMakeLists.txt

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -160,5 +160,7 @@ IF (WITH_SERVER)
160160
ADD_PYTHON_TEST(PyQgsServerAccessControl test_qgsserver_accesscontrol.py)
161161
ADD_PYTHON_TEST(PyQgsServerWFST test_qgsserver_wfst.py)
162162
ADD_PYTHON_TEST(PyQgsOfflineEditingWFS test_offline_editing_wfs.py)
163-
ADD_PYTHON_TEST(PyQgsAuthManagerEndpointTest test_authmanager_endpoint.py)
163+
ADD_PYTHON_TEST(PyQgsAuthManagerPasswordOWSTest test_authmanager_password_ows.py)
164+
#ADD_PYTHON_TEST(PyQgsAuthManagerPKIOWSTest test_authmanager_pki_ows.py)
165+
ADD_PYTHON_TEST(PyQgsAuthManagerPKIPostgresTest test_authmanager_pki_postgres.py)
164166
ENDIF (WITH_SERVER)

‎tests/src/python/qgis_wrapped_server.py

Lines changed: 44 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33
QGIS Server HTTP wrapper
44
55
This script launches a QGIS Server listening on port 8081 or on the port
6-
specified on the environment variable QGIS_SERVER_PORT
6+
specified on the environment variable QGIS_SERVER_PORT.
77
QGIS_SERVER_HOST (defaults to 127.0.0.1)
88
99
For testing purposes, HTTP Basic can be enabled by setting the following
@@ -13,6 +13,21 @@
1313
* QGIS_SERVER_USERNAME (default ="username")
1414
* QGIS_SERVER_PASSWORD (default ="password")
1515
16+
PKI authentication with HTTPS can be enabled with:
17+
18+
* QGIS_SERVER_PKI_CERTIFICATE (server certificate)
19+
* QGIS_SERVER_PKI_KEY (server private key)
20+
* QGIS_SERVER_PKI_AUTHORITY (root CA)
21+
* QGIS_SERVER_PKI_USERNAME (valid username)
22+
23+
Sample run:
24+
25+
QGIS_SERVER_PKI_USERNAME=Gerardus QGIS_SERVER_PORT=47547 QGIS_SERVER_HOST=localhost \
26+
QGIS_SERVER_PKI_KEY=/home/$USER/dev/QGIS/tests/testdata/auth_system/certs_keys/localhost_ssl_key.pem \
27+
QGIS_SERVER_PKI_CERTIFICATE=/home/$USER/dev/QGIS/tests/testdata/auth_system/certs_keys/localhost_ssl_cert.pem \
28+
QGIS_SERVER_PKI_AUTHORITY=/home/$USER/dev/QGIS/tests/testdata/auth_system/certs_keys/chains_subissuer-issuer-root_issuer2-root2.pem \
29+
python3 /home/$USER/dev/QGIS/tests/src/python/qgis_wrapped_server.py
30+
1631
.. note:: This program is free software; you can redistribute it and/or modify
1732
it under the terms of the GNU General Public License as published by
1833
the Free Software Foundation; either version 2 of the License, or
@@ -32,13 +47,29 @@
3247
import os
3348
import sys
3449
import signal
50+
import ssl
3551
import urllib.parse
3652
from http.server import BaseHTTPRequestHandler, HTTPServer
3753
from qgis.core import QgsApplication
3854
from qgis.server import QgsServer
3955

4056
QGIS_SERVER_PORT = int(os.environ.get('QGIS_SERVER_PORT', '8081'))
4157
QGIS_SERVER_HOST = os.environ.get('QGIS_SERVER_HOST', '127.0.0.1')
58+
# PKI authentication
59+
QGIS_SERVER_PKI_CERTIFICATE = os.environ.get('QGIS_SERVER_PKI_CERTIFICATE')
60+
QGIS_SERVER_PKI_KEY = os.environ.get('QGIS_SERVER_PKI_KEY')
61+
QGIS_SERVER_PKI_AUTHORITY = os.environ.get('QGIS_SERVER_PKI_AUTHORITY')
62+
QGIS_SERVER_PKI_USERNAME = os.environ.get('QGIS_SERVER_PKI_USERNAME')
63+
64+
# Check if PKI - https is enabled
65+
https = (QGIS_SERVER_PKI_CERTIFICATE is not None and
66+
os.path.isfile(QGIS_SERVER_PKI_CERTIFICATE) and
67+
QGIS_SERVER_PKI_KEY is not None and
68+
os.path.isfile(QGIS_SERVER_PKI_KEY) and
69+
QGIS_SERVER_PKI_AUTHORITY is not None and
70+
os.path.isfile(QGIS_SERVER_PKI_AUTHORITY) and
71+
QGIS_SERVER_PKI_USERNAME)
72+
4273

4374
qgs_app = QgsApplication([], False)
4475
qgs_server = QgsServer()
@@ -75,6 +106,8 @@ def do_GET(self):
75106
for k, v in self.headers.items():
76107
qgs_server.putenv('HTTP_%s' % k.replace(' ', '-').replace('-', '_').replace(' ', '-').upper(), v)
77108
qgs_server.putenv('SERVER_PORT', str(self.server.server_port))
109+
if https:
110+
qgs_server.putenv('HTTPS', 'ON')
78111
qgs_server.putenv('SERVER_NAME', self.server.server_name)
79112
qgs_server.putenv('REQUEST_URI', self.path)
80113
parsed_path = urllib.parse.urlparse(self.path)
@@ -101,8 +134,16 @@ def do_POST(self):
101134

102135
if __name__ == '__main__':
103136
server = HTTPServer((QGIS_SERVER_HOST, QGIS_SERVER_PORT), Handler)
104-
print('Starting server on %s:%s, use <Ctrl-C> to stop' %
105-
(QGIS_SERVER_HOST, server.server_port), flush=True)
137+
if https:
138+
server.socket = ssl.wrap_socket(server.socket,
139+
certfile=QGIS_SERVER_PKI_CERTIFICATE,
140+
keyfile=QGIS_SERVER_PKI_KEY,
141+
ca_certs=QGIS_SERVER_PKI_AUTHORITY,
142+
cert_reqs=ssl.CERT_REQUIRED,
143+
server_side=True,
144+
ssl_version=ssl.PROTOCOL_TLSv1)
145+
print('Starting server on %s://%s:%s, use <Ctrl-C> to stop' %
146+
('https' if https else 'http', QGIS_SERVER_HOST, server.server_port), flush=True)
106147

107148
def signal_handler(signal, frame):
108149
global qgs_app

‎tests/src/python/test_authmanager_endpoint.py renamed to ‎tests/src/python/test_authmanager_password_ows.py

Lines changed: 14 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@
88
configuration to access an HTTP Basic protected endpoint.
99
1010
11-
From build dir, run: ctest -R PyQgsAuthManagerEndpointTest -V
11+
From build dir, run: ctest -R PyQgsAuthManagerPasswordOWSTest -V
1212
1313
.. note:: This program is free software; you can redistribute it and/or modify
1414
it under the terms of the GNU General Public License as published by
@@ -30,7 +30,6 @@
3030
# This will get replaced with a git SHA1 when you do a git archive
3131
__revision__ = '$Format:%H$'
3232

33-
from urllib.parse import quote
3433
from shutil import rmtree
3534

3635
from utilities import unitTestDataPath, waitServer
@@ -45,11 +44,10 @@
4544
unittest,
4645
)
4746

48-
4947
try:
5048
QGIS_SERVER_ENDPOINT_PORT = os.environ['QGIS_SERVER_ENDPOINT_PORT']
5149
except:
52-
QGIS_SERVER_ENDPOINT_PORT = '0' # Auto
50+
QGIS_SERVER_ENDPOINT_PORT = '0' # Auto
5351

5452

5553
QGIS_AUTH_DB_DIR_PATH = tempfile.mkdtemp()
@@ -74,7 +72,7 @@ def setUpClass(cls):
7472
except KeyError:
7573
pass
7674
cls.testdata_path = unitTestDataPath('qgis_server') + '/'
77-
cls.project_path = quote(cls.testdata_path + "test_project.qgs")
75+
cls.project_path = cls.testdata_path + "test_project.qgs"
7876
# Enable auth
7977
#os.environ['QGIS_AUTH_PASSWORD_FILE'] = QGIS_AUTH_PASSWORD_FILE
8078
authm = QgsAuthManager.instance()
@@ -86,26 +84,30 @@ def setUpClass(cls):
8684
cls.auth_config.setConfig('username', cls.username)
8785
cls.auth_config.setConfig('password', cls.password)
8886
assert (authm.storeAuthenticationConfig(cls.auth_config)[0])
87+
cls.hostname = '127.0.0.1'
88+
cls.protocol = 'http'
8989

9090
os.environ['QGIS_SERVER_HTTP_BASIC_AUTH'] = '1'
9191
os.environ['QGIS_SERVER_USERNAME'] = cls.username
9292
os.environ['QGIS_SERVER_PASSWORD'] = cls.password
9393
os.environ['QGIS_SERVER_PORT'] = str(cls.port)
94+
os.environ['QGIS_SERVER_HOST'] = cls.hostname
95+
9496
server_path = os.path.dirname(os.path.realpath(__file__)) + \
9597
'/qgis_wrapped_server.py'
9698
cls.server = subprocess.Popen([sys.executable, server_path],
9799
env=os.environ, stdout=subprocess.PIPE)
100+
98101
line = cls.server.stdout.readline()
99102
cls.port = int(re.findall(b':(\d+)', line)[0])
100103
assert cls.port != 0
101104
# Wait for the server process to start
102-
assert waitServer('http://127.0.0.1:%s' % cls.port), "Server is not responding!"
105+
assert waitServer('%s://%s:%s' % (cls.protocol, cls.hostname, cls.port)), "Server is not responding! %s://%s:%s" % (cls.protocol, cls.hostname, cls.port)
103106

104107
@classmethod
105108
def tearDownClass(cls):
106109
"""Run after all tests"""
107110
cls.server.terminate()
108-
cls.server.wait()
109111
rmtree(QGIS_AUTH_DB_DIR_PATH)
110112
del cls.server
111113

@@ -127,7 +129,7 @@ def _getWFSLayer(cls, type_name, layer_name=None, authcfg=None):
127129
parms = {
128130
'srsname': 'EPSG:4326',
129131
'typename': type_name,
130-
'url': 'http://127.0.0.1:%s/?map=%s' % (cls.port, cls.project_path),
132+
'url': '%s://%s:%s/?map=%s' % (cls.protocol, cls.hostname, cls.port, cls.project_path),
131133
'version': 'auto',
132134
'table': '',
133135
}
@@ -146,12 +148,12 @@ def _getWMSLayer(cls, layers, layer_name=None, authcfg=None):
146148
layer_name = 'wms_' + layers.replace(',', '')
147149
parms = {
148150
'crs': 'EPSG:4326',
149-
'url': 'http://127.0.0.1:%s/?map=%s' % (cls.port, cls.project_path),
150-
'format': 'image/png',
151+
'url': '%s://%s:%s/?map=%s' % (cls.protocol, cls.hostname, cls.port, cls.project_path),
151152
# This is needed because of a really weird implementation in QGIS Server, that
152153
# replaces _ in the the real layer name with spaces
153-
'layers': urllib.parse.quote(layers).replace('_', ' '),
154+
'layers': urllib.parse.quote(layers.replace('_', ' ')),
154155
'styles': '',
156+
'version': 'auto',
155157
#'sql': '',
156158
}
157159
if authcfg is not None:
@@ -173,7 +175,7 @@ def testInvalidAuthAccess(self):
173175
"""
174176
Access the HTTP Basic protected layer with no credentials
175177
"""
176-
wfs_layer = self._getWFSLayer('testlayer_èé')
178+
wfs_layer = self._getWFSLayer('testlayer èé')
177179
self.assertFalse(wfs_layer.isValid())
178180
wms_layer = self._getWMSLayer('testlayer_èé')
179181
self.assertFalse(wms_layer.isValid())
Lines changed: 237 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,237 @@
1+
# -*- coding: utf-8 -*-
2+
"""
3+
Tests for auth manager PKI access to postgres.
4+
5+
This is an integration test for QGIS Desktop Auth Manager postgres provider that
6+
checks if QGIS can use a stored auth manager auth configuration to access
7+
a PKI protected postgres.
8+
9+
Configuration form the environment:
10+
11+
* QGIS_POSTGRES_SERVER_PORT (default: 55432)
12+
* QGIS_POSTGRES_EXECUTABLE_PATH (default: /usr/lib/postgresql/9.4/bin)
13+
14+
15+
From build dir, run: ctest -R PyQgsAuthManagerPKIPostgresTest -V
16+
17+
or, if your postgresql path differs from the default:
18+
19+
QGIS_POSTGRES_EXECUTABLE_PATH=/usr/lib/postgresql/<your_version_goes_here>/bin \
20+
ctest -R PyQgsAuthManagerPKIPostgresTest -V
21+
22+
.. note:: This program is free software; you can redistribute it and/or modify
23+
it under the terms of the GNU General Public License as published by
24+
the Free Software Foundation; either version 2 of the License, or
25+
(at your option) any later version.
26+
"""
27+
import os
28+
import time
29+
import signal
30+
import stat
31+
import subprocess
32+
import tempfile
33+
34+
from shutil import rmtree
35+
36+
from utilities import unitTestDataPath
37+
from qgis.core import (
38+
QgsAuthManager,
39+
QgsAuthMethodConfig,
40+
QgsVectorLayer,
41+
QgsDataSourceUri,
42+
QgsWkbTypes,
43+
)
44+
45+
from qgis.PyQt.QtNetwork import QSslCertificate
46+
47+
from qgis.testing import (
48+
start_app,
49+
unittest,
50+
)
51+
52+
53+
__author__ = 'Alessandro Pasotti'
54+
__date__ = '25/10/2016'
55+
__copyright__ = 'Copyright 2016, The QGIS Project'
56+
# This will get replaced with a git SHA1 when you do a git archive
57+
__revision__ = '$Format:%H$'
58+
59+
QGIS_POSTGRES_SERVER_PORT = os.environ.get('QGIS_POSTGRES_SERVER_PORT', '55432')
60+
QGIS_POSTGRES_EXECUTABLE_PATH = os.environ.get('QGIS_POSTGRES_EXECUTABLE_PATH', '/usr/lib/postgresql/9.4/bin')
61+
62+
assert os.path.exists(QGIS_POSTGRES_EXECUTABLE_PATH)
63+
64+
QGIS_AUTH_DB_DIR_PATH = tempfile.mkdtemp()
65+
66+
# Postgres test path
67+
QGIS_PG_TEST_PATH = tempfile.mkdtemp()
68+
69+
os.environ['QGIS_AUTH_DB_DIR_PATH'] = QGIS_AUTH_DB_DIR_PATH
70+
71+
qgis_app = start_app()
72+
73+
QGIS_POSTGRES_CONF_TEMPLATE = """
74+
hba_file = '%(tempfolder)s/pg_hba.conf'
75+
listen_addresses = '*'
76+
port = %(port)s
77+
max_connections = 100
78+
unix_socket_directories = '%(tempfolder)s'
79+
ssl = true
80+
ssl_ciphers = 'DEFAULT:!LOW:!EXP:!MD5:@STRENGTH' # allowed SSL ciphers
81+
ssl_cert_file = '%(server_cert)s'
82+
ssl_key_file = '%(server_key)s'
83+
ssl_ca_file = '%(sslrootcert_path)s'
84+
password_encryption = on
85+
"""
86+
87+
QGIS_POSTGRES_HBA_TEMPLATE = """
88+
hostssl all all 0.0.0.0/0 cert clientcert=1
89+
hostssl all all ::1/0 cert clientcert=1
90+
host all all 127.0.0.1/32 trust
91+
host all all ::1/32 trust
92+
"""
93+
94+
95+
class TestAuthManager(unittest.TestCase):
96+
97+
@classmethod
98+
def setUpAuth(cls):
99+
"""Run before all tests and set up authentication"""
100+
authm = QgsAuthManager.instance()
101+
assert (authm.setMasterPassword('masterpassword', True))
102+
cls.pg_conf = os.path.join(cls.tempfolder, 'postgresql.conf')
103+
cls.pg_hba = os.path.join(cls.tempfolder, 'pg_hba.conf')
104+
# Client side
105+
cls.sslrootcert_path = os.path.join(cls.certsdata_path, 'chains_subissuer-issuer-root_issuer2-root2.pem')
106+
cls.sslcert = os.path.join(cls.certsdata_path, 'gerardus_cert.pem')
107+
cls.sslkey = os.path.join(cls.certsdata_path, 'gerardus_key.pem')
108+
assert os.path.isfile(cls.sslcert)
109+
assert os.path.isfile(cls.sslkey)
110+
assert os.path.isfile(cls.sslrootcert_path)
111+
os.chmod(cls.sslcert, stat.S_IRUSR)
112+
os.chmod(cls.sslkey, stat.S_IRUSR)
113+
os.chmod(cls.sslrootcert_path, stat.S_IRUSR)
114+
cls.auth_config = QgsAuthMethodConfig("PKI-Paths")
115+
cls.auth_config.setConfig('certpath', cls.sslcert)
116+
cls.auth_config.setConfig('keypath', cls.sslkey)
117+
cls.auth_config.setName('test_pki_auth_config')
118+
cls.username = 'Gerardus'
119+
cls.sslrootcert = QSslCertificate.fromPath(cls.sslrootcert_path)
120+
assert cls.sslrootcert is not None
121+
authm.storeCertAuthorities(cls.sslrootcert)
122+
authm.rebuildCaCertsCache()
123+
authm.rebuildTrustedCaCertsCache()
124+
authm.rebuildCertTrustCache()
125+
assert (authm.storeAuthenticationConfig(cls.auth_config)[0])
126+
assert cls.auth_config.isValid()
127+
128+
# Server side
129+
cls.server_cert = os.path.join(cls.certsdata_path, 'localhost_ssl_cert.pem')
130+
cls.server_key = os.path.join(cls.certsdata_path, 'localhost_ssl_key.pem')
131+
cls.server_rootcert = cls.sslrootcert_path
132+
os.chmod(cls.server_cert, stat.S_IRUSR)
133+
os.chmod(cls.server_key, stat.S_IRUSR)
134+
os.chmod(cls.server_rootcert, stat.S_IRUSR)
135+
136+
# Place conf in the data folder
137+
with open(cls.pg_conf, 'w+') as f:
138+
f.write(QGIS_POSTGRES_CONF_TEMPLATE % {
139+
'port': cls.port,
140+
'tempfolder': cls.tempfolder,
141+
'server_cert': cls.server_cert,
142+
'server_key': cls.server_key,
143+
'sslrootcert_path': cls.sslrootcert_path,
144+
})
145+
146+
with open(cls.pg_hba, 'w+') as f:
147+
f.write(QGIS_POSTGRES_HBA_TEMPLATE)
148+
149+
@classmethod
150+
def setUpClass(cls):
151+
"""Run before all tests:
152+
Creates an auth configuration"""
153+
cls.port = QGIS_POSTGRES_SERVER_PORT
154+
cls.dbname = 'test_pki'
155+
cls.tempfolder = QGIS_PG_TEST_PATH
156+
cls.certsdata_path = os.path.join(unitTestDataPath('auth_system'), 'certs_keys')
157+
cls.hostname = 'localhost'
158+
cls.data_path = os.path.join(cls.tempfolder, 'data')
159+
os.mkdir(cls.data_path)
160+
161+
cls.setUpAuth()
162+
subprocess.check_call([os.path.join(QGIS_POSTGRES_EXECUTABLE_PATH, 'initdb'), '-D', cls.data_path])
163+
164+
cls.server = subprocess.Popen([os.path.join(QGIS_POSTGRES_EXECUTABLE_PATH, 'postgres'), '-D',
165+
cls.data_path, '-c',
166+
"config_file=%s" % cls.pg_conf],
167+
env=os.environ,
168+
stdout=subprocess.PIPE,
169+
stderr=subprocess.PIPE)
170+
# Wait max 10 secs for the server to start
171+
end = time.time() + 10
172+
while True:
173+
line = cls.server.stderr.readline()
174+
print(line)
175+
if line.find(b"database system is ready to accept") != -1:
176+
break
177+
if time.time() > end:
178+
raise Exception("Timeout connecting to postgresql")
179+
# Create a DB
180+
subprocess.check_call([os.path.join(QGIS_POSTGRES_EXECUTABLE_PATH, 'createdb'), '-h', 'localhost', '-p', cls.port, 'test_pki'])
181+
# Inject test SQL from test path
182+
test_sql = os.path.join(unitTestDataPath('provider'), 'testdata_pg.sql')
183+
subprocess.check_call([os.path.join(QGIS_POSTGRES_EXECUTABLE_PATH, 'psql'), '-h', 'localhost', '-p', cls.port, '-f', test_sql, cls.dbname])
184+
# Create a role
185+
subprocess.check_call([os.path.join(QGIS_POSTGRES_EXECUTABLE_PATH, 'psql'), '-h', 'localhost', '-p', cls.port, '-c', 'CREATE ROLE "%s" WITH SUPERUSER LOGIN' % cls.username, cls.dbname])
186+
187+
@classmethod
188+
def tearDownClass(cls):
189+
"""Run after all tests"""
190+
cls.server.terminate()
191+
os.kill(cls.server.pid, signal.SIGABRT)
192+
del cls.server
193+
time.sleep(2)
194+
rmtree(QGIS_AUTH_DB_DIR_PATH)
195+
rmtree(cls.tempfolder)
196+
197+
def setUp(self):
198+
"""Run before each test."""
199+
pass
200+
201+
def tearDown(self):
202+
"""Run after each test."""
203+
pass
204+
205+
@classmethod
206+
def _getPostGISLayer(cls, type_name, layer_name=None, authcfg=None):
207+
"""
208+
PG layer factory
209+
"""
210+
if layer_name is None:
211+
layer_name = 'pg_' + type_name
212+
uri = QgsDataSourceUri()
213+
uri.setWkbType(QgsWkbTypes.Point)
214+
uri.setConnection("localhost", cls.port, cls.dbname, "", "", QgsDataSourceUri.SslVerifyFull, authcfg)
215+
uri.setKeyColumn('pk')
216+
uri.setSrid('EPSG:4326')
217+
uri.setDataSource('qgis_test', 'someData', "geom", "", "pk")
218+
# Note: do not expand here!
219+
layer = QgsVectorLayer(uri.uri(False), layer_name, 'postgres')
220+
return layer
221+
222+
def testValidAuthAccess(self):
223+
"""
224+
Access the protected layer with valid credentials
225+
"""
226+
pg_layer = self._getPostGISLayer('testlayer_èé', authcfg=self.auth_config.id())
227+
self.assertTrue(pg_layer.isValid())
228+
229+
def testInvalidAuthAccess(self):
230+
"""
231+
Access the protected layer with not valid credentials
232+
"""
233+
pg_layer = self._getPostGISLayer('testlayer_èé')
234+
self.assertFalse(pg_layer.isValid())
235+
236+
if __name__ == '__main__':
237+
unittest.main()

‎tests/src/python/test_qgsserver.py

Lines changed: 7 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -502,11 +502,13 @@ def _img_diff_error(self, response, headers, image, max_diff=10, max_size_diff=Q
502502
report, encoded_rendered_file.strip(), tempfile.gettempdir(), image
503503
)
504504

505-
with open(os.path.join(tempfile.gettempdir(), image + "_result_diff.png"), "rb") as diff_file:
506-
encoded_diff_file = base64.b64encode(diff_file.read())
507-
message += "\nDiff:\necho '%s' | base64 -d > %s/%s_result_diff.png" % (
508-
encoded_diff_file.strip(), tempfile.gettempdir(), image
509-
)
505+
# If the failure is in image sizes the diff file will not exists.
506+
if os.path.exists(os.path.join(tempfile.gettempdir(), image + "_result_diff.png")):
507+
with open(os.path.join(tempfile.gettempdir(), image + "_result_diff.png"), "rb") as diff_file:
508+
encoded_diff_file = base64.b64encode(diff_file.read())
509+
message += "\nDiff:\necho '%s' | base64 -d > %s/%s_result_diff.png" % (
510+
encoded_diff_file.strip(), tempfile.gettempdir(), image
511+
)
510512

511513
self.assertTrue(test, message)
512514

‎tests/src/python/utilities.py

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -19,9 +19,9 @@
1919
import platform
2020
import tempfile
2121
try:
22-
from urllib2 import urlopen, HTTPError
22+
from urllib2 import urlopen, HTTPError, URLError
2323
except ImportError:
24-
from urllib.request import urlopen, HTTPError
24+
from urllib.request import urlopen, HTTPError, URLError
2525

2626

2727
from qgis.PyQt.QtCore import QDir
@@ -847,7 +847,7 @@ def waitServer(url, timeout=10):
847847
try:
848848
urlopen(url, timeout=1)
849849
return True
850-
except HTTPError:
850+
except (HTTPError, URLError):
851851
return True
852852
except Exception as e:
853853
if now() > end:

0 commit comments

Comments
 (0)
Please sign in to comment.