Fix up the version tests and remove old references to 'versionchecker'

This commit is contained in:
Raoul Snyman 2017-09-12 23:08:38 -07:00
parent 6fb4381588
commit 2f8cdc81e0
9 changed files with 273 additions and 140 deletions

View File

@ -496,6 +496,8 @@ class MainWindow(QtWidgets.QMainWindow, Ui_MainWindow, RegistryProperties):
"""
super(MainWindow, self).__init__()
Registry().register('main_window', self)
self.version_thread = None
self.version_worker = None
self.clipboard = self.application.clipboard()
self.arguments = ''.join(self.application.args)
# Set up settings sections for the main application (not for use by plugins).
@ -1009,6 +1011,17 @@ class MainWindow(QtWidgets.QMainWindow, Ui_MainWindow, RegistryProperties):
if not self.application.is_event_loop_active:
event.ignore()
return
# Sometimes the version thread hasn't finished, let's wait for it
try:
if self.version_thread and self.version_thread.isRunning():
wait_dialog = QtWidgets.QProgressDialog('Waiting for some things to finish...', '', 0, 0, self)
wait_dialog.setWindowModality(QtCore.Qt.WindowModal)
wait_dialog.setAutoClose(False)
self.version_thread.wait()
wait_dialog.close()
except RuntimeError:
# Ignore the RuntimeError that is thrown when Qt has already deleted the C++ thread object
pass
# If we just did a settings import, close without saving changes.
if self.settings_imported:
self.clean_up(False)

View File

@ -26,7 +26,8 @@ import logging
import os
import platform
import sys
from datetime import datetime
import time
from datetime import date
from distutils.version import LooseVersion
from subprocess import Popen, PIPE
@ -52,7 +53,7 @@ class VersionWorker(QtCore.QObject):
no_internet = QtCore.pyqtSignal()
quit = QtCore.pyqtSignal()
def __init__(self, last_check_date):
def __init__(self, last_check_date, current_version):
"""
Constructor for the version check worker.
@ -61,6 +62,7 @@ class VersionWorker(QtCore.QObject):
log.debug('VersionWorker - Initialise')
super(VersionWorker, self).__init__(None)
self.last_check_date = last_check_date
self.current_version = current_version
def start(self):
"""
@ -74,15 +76,14 @@ class VersionWorker(QtCore.QObject):
"""
log.debug('VersionWorker - Start')
# I'm not entirely sure why this was here, I'm commenting it out until I hit the same scenario
# time.sleep(1)
current_version = get_version()
time.sleep(1)
download_url = 'http://www.openlp.org/files/version.txt'
if current_version['build']:
if self.current_version['build']:
download_url = 'http://www.openlp.org/files/nightly_version.txt'
elif int(current_version['version'].split('.')[1]) % 2 != 0:
elif int(self.current_version['version'].split('.')[1]) % 2 != 0:
download_url = 'http://www.openlp.org/files/dev_version.txt'
headers = {
'User-Agent', 'OpenLP/{version} {system}/{release}; '.format(version=current_version['full'],
'User-Agent': 'OpenLP/{version} {system}/{release}; '.format(version=self.current_version['full'],
system=platform.system(),
release=platform.release())
}
@ -94,18 +95,23 @@ class VersionWorker(QtCore.QObject):
remote_version = response.text
log.debug('New version found: %s', remote_version)
break
except requests.exceptions.ConnectionError:
except IOError:
log.exception('Unable to connect to OpenLP server to download version file')
self.no_internet.emit()
retries += 1
except requests.exceptions.RequestException:
log.exception('Error occurred while connecting to OpenLP server to download version file')
retries += 1
if remote_version and LooseVersion(remote_version) > LooseVersion(current_version['full']):
else:
self.no_internet.emit()
if remote_version and LooseVersion(remote_version) > LooseVersion(self.current_version['full']):
self.new_version.emit(remote_version)
self.quit.emit()
def update_check_date():
"""
Save when we last checked for an update
"""
Settings().setValue('core/last version test', date.today().strftime('%Y-%m-%d'))
def check_for_update(parent):
"""
Run a thread to download and check the version of OpenLP
@ -113,11 +119,12 @@ def check_for_update(parent):
:param MainWindow parent: The parent object for the thread. Usually the OpenLP main window.
"""
last_check_date = Settings().value('core/last version test')
if datetime.date().strftime('%Y-%m-%d') <= last_check_date:
if date.today().strftime('%Y-%m-%d') <= last_check_date:
log.debug('Version check skipped, last checked today')
return
worker = VersionWorker(last_check_date)
worker = VersionWorker(last_check_date, get_version())
worker.new_version.connect(parent.on_new_version)
worker.quit.connect(update_check_date)
# TODO: Use this to figure out if there's an Internet connection?
# worker.no_internet.connect(parent.on_no_internet)
run_thread(parent, worker, 'version')
@ -132,6 +139,7 @@ def get_version():
global APPLICATION_VERSION
if APPLICATION_VERSION:
return APPLICATION_VERSION
print(sys.argv)
if '--dev-version' in sys.argv or '-d' in sys.argv:
# NOTE: The following code is a duplicate of the code in setup.py. Any fix applied here should also be applied
# there.

View File

@ -62,7 +62,7 @@ import re
from lxml import etree, objectify
from openlp.core.common import translate, Settings
from openlp.core.common.versionchecker import get_application_version
from openlp.core.version import get_version
from openlp.core.lib import FormattingTags
from openlp.plugins.songs.lib import VerseType, clean_song
from openlp.plugins.songs.lib.db import Author, AuthorType, Book, Song, Topic
@ -234,7 +234,7 @@ class OpenLyrics(object):
# Append the necessary meta data to the song.
song_xml.set('xmlns', NAMESPACE)
song_xml.set('version', OpenLyrics.IMPLEMENTED_VERSION)
application_name = 'OpenLP ' + get_application_version()['version']
application_name = 'OpenLP ' + get_version()['version']
song_xml.set('createdIn', application_name)
song_xml.set('modifiedIn', application_name)
# "Convert" 2012-08-27 11:49:15 to 2012-08-27T11:49:15.

View File

@ -26,7 +26,7 @@ This script is used to check dependencies of OpenLP. It checks availability
of required python modules and their version. To verify availability of Python
modules, simply run this script::
@:~$ ./check_dependencies.py
$ ./check_dependencies.py
"""
import os
@ -45,7 +45,7 @@ IS_MAC = sys.platform.startswith('dar')
VERS = {
'Python': '3.0',
'Python': '3.4',
'PyQt5': '5.0',
'Qt5': '5.0',
'sqlalchemy': '0.5',
@ -97,7 +97,8 @@ MODULES = [
'asyncio',
'waitress',
'six',
'webob'
'webob',
'requests'
]

View File

@ -0,0 +1,204 @@
# -*- coding: utf-8 -*-
# vim: autoindent shiftwidth=4 expandtab textwidth=120 tabstop=4 softtabstop=4
###############################################################################
# OpenLP - Open Source Lyrics Projection #
# --------------------------------------------------------------------------- #
# Copyright (c) 2008-2017 OpenLP Developers #
# --------------------------------------------------------------------------- #
# This program is free software; you can redistribute it and/or modify it #
# under the terms of the GNU General Public License as published by the Free #
# Software Foundation; version 2 of the License. #
# #
# This program is distributed in the hope that it will be useful, but WITHOUT #
# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or #
# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for #
# more details. #
# #
# You should have received a copy of the GNU General Public License along #
# with this program; if not, write to the Free Software Foundation, Inc., 59 #
# Temple Place, Suite 330, Boston, MA 02111-1307 USA #
###############################################################################
"""
Package to test the openlp.core.version package.
"""
import sys
from datetime import date
from unittest.mock import MagicMock, patch
from requests.exceptions import ConnectionError
from openlp.core.version import VersionWorker, check_for_update, get_version, update_check_date
def test_worker_init():
"""Test the VersionWorker constructor"""
# GIVEN: A last check date and a current version
last_check_date = '1970-01-01'
current_version = '2.0'
# WHEN: A worker is created
worker = VersionWorker(last_check_date, current_version)
# THEN: The correct attributes should have been set
assert worker.last_check_date == last_check_date
assert worker.current_version == current_version
@patch('openlp.core.version.platform')
@patch('openlp.core.version.requests')
def test_worker_start(mock_requests, mock_platform):
"""Test the VersionWorkder.start() method"""
# GIVEN: A last check date, current version, and an instance of worker
last_check_date = '1970-01-01'
current_version = {'full': '2.0', 'version': '2.0', 'build': None}
mock_platform.system.return_value = 'Linux'
mock_platform.release.return_value = '4.12.0-1-amd64'
mock_requests.get.return_value = MagicMock(text='2.4.6')
worker = VersionWorker(last_check_date, current_version)
# WHEN: The worker is run
with patch.object(worker, 'new_version') as mock_new_version, \
patch.object(worker, 'quit') as mock_quit:
worker.start()
# THEN: The check completes and the signal is emitted
expected_download_url = 'http://www.openlp.org/files/version.txt'
expected_headers = {'User-Agent': 'OpenLP/2.0 Linux/4.12.0-1-amd64; '}
mock_requests.get.assert_called_once_with(expected_download_url, headers=expected_headers)
mock_new_version.emit.assert_called_once_with('2.4.6')
mock_quit.emit.assert_called_once_with()
@patch('openlp.core.version.platform')
@patch('openlp.core.version.requests')
def test_worker_start_dev_version(mock_requests, mock_platform):
"""Test the VersionWorkder.start() method for dev versions"""
# GIVEN: A last check date, current version, and an instance of worker
last_check_date = '1970-01-01'
current_version = {'full': '2.1.3', 'version': '2.1.3', 'build': None}
mock_platform.system.return_value = 'Linux'
mock_platform.release.return_value = '4.12.0-1-amd64'
mock_requests.get.return_value = MagicMock(text='2.4.6')
worker = VersionWorker(last_check_date, current_version)
# WHEN: The worker is run
with patch.object(worker, 'new_version') as mock_new_version, \
patch.object(worker, 'quit') as mock_quit:
worker.start()
# THEN: The check completes and the signal is emitted
expected_download_url = 'http://www.openlp.org/files/dev_version.txt'
expected_headers = {'User-Agent': 'OpenLP/2.1.3 Linux/4.12.0-1-amd64; '}
mock_requests.get.assert_called_once_with(expected_download_url, headers=expected_headers)
mock_new_version.emit.assert_called_once_with('2.4.6')
mock_quit.emit.assert_called_once_with()
@patch('openlp.core.version.platform')
@patch('openlp.core.version.requests')
def test_worker_start_nightly_version(mock_requests, mock_platform):
"""Test the VersionWorkder.start() method for nightlies"""
# GIVEN: A last check date, current version, and an instance of worker
last_check_date = '1970-01-01'
current_version = {'full': '2.1-bzr2345', 'version': '2.1', 'build': '2345'}
mock_platform.system.return_value = 'Linux'
mock_platform.release.return_value = '4.12.0-1-amd64'
mock_requests.get.return_value = MagicMock(text='2.4.6')
worker = VersionWorker(last_check_date, current_version)
# WHEN: The worker is run
with patch.object(worker, 'new_version') as mock_new_version, \
patch.object(worker, 'quit') as mock_quit:
worker.start()
# THEN: The check completes and the signal is emitted
expected_download_url = 'http://www.openlp.org/files/nightly_version.txt'
expected_headers = {'User-Agent': 'OpenLP/2.1-bzr2345 Linux/4.12.0-1-amd64; '}
mock_requests.get.assert_called_once_with(expected_download_url, headers=expected_headers)
mock_new_version.emit.assert_called_once_with('2.4.6')
mock_quit.emit.assert_called_once_with()
@patch('openlp.core.version.platform')
@patch('openlp.core.version.requests')
def test_worker_start_connection_error(mock_requests, mock_platform):
"""Test the VersionWorkder.start() method when a ConnectionError happens"""
# GIVEN: A last check date, current version, and an instance of worker
last_check_date = '1970-01-01'
current_version = {'full': '2.0', 'version': '2.0', 'build': None}
mock_platform.system.return_value = 'Linux'
mock_platform.release.return_value = '4.12.0-1-amd64'
mock_requests.get.side_effect = ConnectionError('Could not connect')
worker = VersionWorker(last_check_date, current_version)
# WHEN: The worker is run
with patch.object(worker, 'no_internet') as mocked_no_internet, \
patch.object(worker, 'quit') as mocked_quit:
worker.start()
# THEN: The check completes and the signal is emitted
expected_download_url = 'http://www.openlp.org/files/version.txt'
expected_headers = {'User-Agent': 'OpenLP/2.0 Linux/4.12.0-1-amd64; '}
mock_requests.get.assert_called_with(expected_download_url, headers=expected_headers)
assert mock_requests.get.call_count == 3
mocked_no_internet.emit.assert_called_once_with()
mocked_quit.emit.assert_called_once_with()
@patch('openlp.core.version.Settings')
def test_update_check_date(MockSettings):
"""Test that the update_check_date() function writes the correct date"""
# GIVEN: A mocked Settings object
mocked_settings = MagicMock()
MockSettings.return_value = mocked_settings
# WHEN: update_check_date() is called
update_check_date()
# THEN: The correct date should have been saved
mocked_settings.setValue.assert_called_once_with('core/last version test', date.today().strftime('%Y-%m-%d'))
@patch('openlp.core.version.Settings')
@patch('openlp.core.version.run_thread')
def test_check_for_update(mocked_run_thread, MockSettings):
"""Test the check_for_update() function"""
# GIVEN: A mocked settings object
mocked_settings = MagicMock()
mocked_settings.value.return_value = '1970-01-01'
MockSettings.return_value = mocked_settings
# WHEN: check_for_update() is called
check_for_update(MagicMock())
# THEN: The right things should have been called and a thread set in motion
assert mocked_run_thread.call_count == 1
@patch('openlp.core.version.Settings')
@patch('openlp.core.version.run_thread')
def test_check_for_update_skipped(mocked_run_thread, MockSettings):
"""Test that the check_for_update() function skips running if it already ran today"""
# GIVEN: A mocked settings object
mocked_settings = MagicMock()
mocked_settings.value.return_value = date.today().strftime('%Y-%m-%d')
MockSettings.return_value = mocked_settings
# WHEN: check_for_update() is called
check_for_update(MagicMock())
# THEN: The right things should have been called and a thread set in motion
assert mocked_run_thread.call_count == 0
def test_get_version_dev_version():
"""Test the get_version() function"""
# GIVEN: We're in dev mode
with patch.object(sys, 'argv', ['--dev-version']), \
patch('openlp.core.version.APPLICATION_VERSION', None):
# WHEN: get_version() is run
version = get_version()
# THEN: version is something
assert version

View File

@ -1,64 +0,0 @@
# -*- coding: utf-8 -*-
# vim: autoindent shiftwidth=4 expandtab textwidth=120 tabstop=4 softtabstop=4
###############################################################################
# OpenLP - Open Source Lyrics Projection #
# --------------------------------------------------------------------------- #
# Copyright (c) 2008-2017 OpenLP Developers #
# --------------------------------------------------------------------------- #
# This program is free software; you can redistribute it and/or modify it #
# under the terms of the GNU General Public License as published by the Free #
# Software Foundation; version 2 of the License. #
# #
# This program is distributed in the hope that it will be useful, but WITHOUT #
# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or #
# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for #
# more details. #
# #
# You should have received a copy of the GNU General Public License along #
# with this program; if not, write to the Free Software Foundation, Inc., 59 #
# Temple Place, Suite 330, Boston, MA 02111-1307 USA #
###############################################################################
"""
Package to test the openlp.core.common.versionchecker package.
"""
from unittest import TestCase
from unittest.mock import MagicMock, patch
from openlp.core.common.settings import Settings
from openlp.core.common.versionchecker import VersionThread
from tests.helpers.testmixin import TestMixin
class TestVersionchecker(TestMixin, TestCase):
def setUp(self):
"""
Create an instance and a few example actions.
"""
self.build_settings()
def tearDown(self):
"""
Clean up
"""
self.destroy_settings()
def test_version_thread_triggered(self):
"""
Test the version thread call does not trigger UI
:return:
"""
# GIVEN: a equal version setup and the data is not today.
mocked_main_window = MagicMock()
Settings().setValue('core/last version test', '1950-04-01')
# WHEN: We check to see if the version is different .
with patch('PyQt5.QtCore.QThread'),\
patch('openlp.core.common.versionchecker.get_application_version') as mocked_get_application_version:
mocked_get_application_version.return_value = {'version': '1.0.0', 'build': '', 'full': '2.0.4'}
version_thread = VersionThread(mocked_main_window)
version_thread.run()
# THEN: If the version has changed the main window is notified
self.assertTrue(mocked_main_window.openlp_version_check.emit.called,
'The main windows should have been notified')

View File

@ -47,13 +47,13 @@ class TestFirstTimeForm(TestCase, TestMixin):
# THEN: A web browser is opened
mocked_webbrowser.open_new.assert_called_with('http://openlp.org/en/contribute')
@patch('openlp.core.ui.aboutform.get_application_version')
def test_about_form_build_number(self, mocked_get_application_version):
@patch('openlp.core.ui.aboutform.get_version')
def test_about_form_build_number(self, mocked_get_version):
"""
Test that the build number is added to the about form
"""
# GIVEN: A mocked out get_application_version function
mocked_get_application_version.return_value = {'version': '3.1.5', 'build': '3000'}
# GIVEN: A mocked out get_version function
mocked_get_version.return_value = {'version': '3.1.5', 'build': '3000'}
# WHEN: The about form is created
about_form = AboutForm(None)

View File

@ -53,7 +53,7 @@ MAIL_ITEM_TEXT = ('**OpenLP Bug Report**\nVersion: Trunk Test\n\n--- Details of
@patch("openlp.core.ui.exceptionform.Qt.qVersion")
@patch("openlp.core.ui.exceptionform.QtGui.QDesktopServices.openUrl")
@patch("openlp.core.ui.exceptionform.get_application_version")
@patch("openlp.core.ui.exceptionform.get_version")
@patch("openlp.core.ui.exceptionform.sqlalchemy")
@patch("openlp.core.ui.exceptionform.bs4")
@patch("openlp.core.ui.exceptionform.etree")
@ -64,18 +64,10 @@ class TestExceptionForm(TestMixin, TestCase):
"""
Test functionality of exception form functions
"""
def __method_template_for_class_patches(self,
__PLACEHOLDER_FOR_LOCAL_METHOD_PATCH_DECORATORS_GO_HERE__,
mocked_python_version,
mocked_platform,
mocked_is_linux,
mocked_etree,
mocked_bs4,
mocked_sqlalchemy,
mocked_application_version,
mocked_openlurl,
mocked_qversion,
):
def __method_template_for_class_patches(self, __PLACEHOLDER_FOR_LOCAL_METHOD_PATCH_DECORATORS_GO_HERE__,
mocked_python_version, mocked_platform, mocked_is_linux,
mocked_etree, mocked_bs4, mocked_sqlalchemy, mocked_get_version,
mocked_openlurl, mocked_qversion):
"""
Template so you don't have to remember the layout of class mock options for methods
"""
@ -86,7 +78,7 @@ class TestExceptionForm(TestMixin, TestCase):
mocked_platform.return_value = 'Nose Test'
mocked_qversion.return_value = 'Qt5 test'
mocked_is_linux.return_value = False
mocked_application_version.return_value = 'Trunk Test'
mocked_get_version.return_value = 'Trunk Test'
def setUp(self):
self.setup_application()
@ -107,22 +99,10 @@ class TestExceptionForm(TestMixin, TestCase):
@patch("openlp.core.ui.exceptionform.QtCore.QUrl")
@patch("openlp.core.ui.exceptionform.QtCore.QUrlQuery.addQueryItem")
@patch("openlp.core.ui.exceptionform.Qt")
def test_on_send_report_button_clicked(self,
mocked_qt,
mocked_add_query_item,
mocked_qurl,
mocked_file_dialog,
mocked_ui_exception_dialog,
mocked_python_version,
mocked_platform,
mocked_is_linux,
mocked_etree,
mocked_bs4,
mocked_sqlalchemy,
mocked_application_version,
mocked_openlurl,
mocked_qversion,
):
def test_on_send_report_button_clicked(self, mocked_qt, mocked_add_query_item, mocked_qurl, mocked_file_dialog,
mocked_ui_exception_dialog, mocked_python_version, mocked_platform,
mocked_is_linux, mocked_etree, mocked_bs4, mocked_sqlalchemy,
mocked_get_version, mocked_openlurl, mocked_qversion):
"""
Test send report creates the proper system information text
"""
@ -134,10 +114,10 @@ class TestExceptionForm(TestMixin, TestCase):
mocked_platform.return_value = 'Nose Test'
mocked_qversion.return_value = 'Qt5 test'
mocked_is_linux.return_value = False
mocked_application_version.return_value = 'Trunk Test'
mocked_get_version.return_value = 'Trunk Test'
mocked_qt.PYQT_VERSION_STR = 'PyQt5 Test'
mocked_is_linux.return_value = False
mocked_application_version.return_value = 'Trunk Test'
mocked_get_version.return_value = 'Trunk Test'
test_form = exceptionform.ExceptionForm()
test_form.file_attachment = None
@ -157,19 +137,10 @@ class TestExceptionForm(TestMixin, TestCase):
@patch("openlp.core.ui.exceptionform.FileDialog.getSaveFileName")
@patch("openlp.core.ui.exceptionform.Qt")
def test_on_save_report_button_clicked(self,
mocked_qt,
mocked_save_filename,
mocked_python_version,
mocked_platform,
mocked_is_linux,
mocked_etree,
mocked_bs4,
mocked_sqlalchemy,
mocked_application_version,
mocked_openlurl,
mocked_qversion,
):
def test_on_save_report_button_clicked(self, mocked_qt, mocked_save_filename, mocked_python_version,
mocked_platform, mocked_is_linux, mocked_etree, mocked_bs4,
mocked_sqlalchemy, mocked_get_version, mocked_openlurl,
mocked_qversion):
"""
Test save report saves the correct information to a file
"""
@ -181,7 +152,7 @@ class TestExceptionForm(TestMixin, TestCase):
mocked_qversion.return_value = 'Qt5 test'
mocked_qt.PYQT_VERSION_STR = 'PyQt5 Test'
mocked_is_linux.return_value = False
mocked_application_version.return_value = 'Trunk Test'
mocked_get_version.return_value = 'Trunk Test'
mocked_save_filename.return_value = (Path('testfile.txt'), 'filter')
test_form = exceptionform.ExceptionForm()

View File

@ -24,11 +24,11 @@ Package to test the openlp.core.__init__ package.
"""
import os
from unittest import TestCase
from unittest.mock import MagicMock, patch, call
from unittest.mock import MagicMock, patch
from PyQt5 import QtCore, QtWidgets
from openlp.core import OpenLP, parse_options
from openlp.core import OpenLP
from openlp.core.common import Settings
from tests.helpers.testmixin import TestMixin
@ -96,9 +96,9 @@ class TestInit(TestCase, TestMixin):
'build': 'bzr000'
}
Settings().setValue('core/application version', '2.2.0')
with patch('openlp.core.get_application_version') as mocked_get_application_version,\
with patch('openlp.core.get_version') as mocked_get_version,\
patch('openlp.core.QtWidgets.QMessageBox.question') as mocked_question:
mocked_get_application_version.return_value = MOCKED_VERSION
mocked_get_version.return_value = MOCKED_VERSION
mocked_question.return_value = QtWidgets.QMessageBox.No
# WHEN: We check if a backup should be created
@ -122,9 +122,9 @@ class TestInit(TestCase, TestMixin):
Settings().setValue('core/application version', '2.0.5')
self.openlp.splash = MagicMock()
self.openlp.splash.isVisible.return_value = True
with patch('openlp.core.get_application_version') as mocked_get_application_version,\
with patch('openlp.core.get_version') as mocked_get_version, \
patch('openlp.core.QtWidgets.QMessageBox.question') as mocked_question:
mocked_get_application_version.return_value = MOCKED_VERSION
mocked_get_version.return_value = MOCKED_VERSION
mocked_question.return_value = QtWidgets.QMessageBox.No
# WHEN: We check if a backup should be created