FreeCAD

Форк
0
/
test_update_all_gui.py 
258 строк · 10.0 Кб
1
# SPDX-License-Identifier: LGPL-2.1-or-later
2
# ***************************************************************************
3
# *                                                                         *
4
# *   Copyright (c) 2022 FreeCAD Project Association                        *
5
# *                                                                         *
6
# *   This file is part of FreeCAD.                                         *
7
# *                                                                         *
8
# *   FreeCAD is free software: you can redistribute it and/or modify it    *
9
# *   under the terms of the GNU Lesser General Public License as           *
10
# *   published by the Free Software Foundation, either version 2.1 of the  *
11
# *   License, or (at your option) any later version.                       *
12
# *                                                                         *
13
# *   FreeCAD is distributed in the hope that it will be useful, but        *
14
# *   WITHOUT ANY WARRANTY; without even the implied warranty of            *
15
# *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU      *
16
# *   Lesser General Public License for more details.                       *
17
# *                                                                         *
18
# *   You should have received a copy of the GNU Lesser General Public      *
19
# *   License along with FreeCAD. If not, see                               *
20
# *   <https://www.gnu.org/licenses/>.                                      *
21
# *                                                                         *
22
# ***************************************************************************
23

24
from time import sleep
25
import unittest
26
import FreeCAD
27

28
from Addon import Addon
29

30
from PySide import QtCore, QtWidgets
31

32
from addonmanager_update_all_gui import UpdateAllGUI, AddonStatus
33

34

35
class MockUpdater(QtCore.QObject):
36
    success = QtCore.Signal(object)
37
    failure = QtCore.Signal(object)
38
    finished = QtCore.Signal()
39

40
    def __init__(self, addon, addons=[]):
41
        super().__init__()
42
        self.addon_to_install = addon
43
        self.addons = addons
44
        self.has_run = False
45
        self.emit_success = True
46
        self.work_function = None  # Set to some kind of callable to make this function take time
47

48
    def run(self):
49
        self.has_run = True
50
        if self.work_function is not None and callable(self.work_function):
51
            self.work_function()
52
        if self.emit_success:
53
            self.success.emit(self.addon_to_install)
54
        else:
55
            self.failure.emit(self.addon_to_install)
56
        self.finished.emit()
57

58

59
class MockUpdaterFactory:
60
    def __init__(self, addons):
61
        self.addons = addons
62
        self.work_function = None
63
        self.updater = None
64

65
    def get_updater(self, addon):
66
        self.updater = MockUpdater(addon, self.addons)
67
        self.updater.work_function = self.work_function
68
        return self.updater
69

70

71
class MockAddon:
72
    def __init__(self, name):
73
        self.display_name = name
74
        self.name = name
75
        self.macro = None
76

77
    def status(self):
78
        return Addon.Status.UPDATE_AVAILABLE
79

80

81
class CallInterceptor:
82
    def __init__(self):
83
        self.called = False
84
        self.args = None
85

86
    def intercept(self, *args):
87
        self.called = True
88
        self.args = args
89

90

91
class TestUpdateAllGui(unittest.TestCase):
92
    def setUp(self):
93
        self.addons = []
94
        for i in range(3):
95
            self.addons.append(MockAddon(f"Mock Addon {i}"))
96
        self.factory = MockUpdaterFactory(self.addons)
97
        self.test_object = UpdateAllGUI(self.addons)
98
        self.test_object.updater_factory = self.factory
99

100
    def tearDown(self):
101
        pass
102

103
    def test_run(self):
104
        self.factory.work_function = lambda: sleep(0.1)
105
        self.test_object.run()
106
        while self.test_object.is_running():
107
            QtCore.QCoreApplication.processEvents(QtCore.QEventLoop.AllEvents, 100)
108
        self.test_object.dialog.accept()
109

110
    def test_setup_dialog(self):
111
        self.test_object._setup_dialog()
112
        self.assertIsNotNone(
113
            self.test_object.dialog.buttonBox.button(QtWidgets.QDialogButtonBox.Cancel)
114
        )
115
        self.assertEqual(self.test_object.dialog.tableWidget.rowCount(), 3)
116

117
    def test_cancelling_installation(self):
118
        class Worker:
119
            def __init__(self):
120
                self.counter = 0
121
                self.LIMIT = 100
122
                self.limit_reached = False
123

124
            def run(self):
125
                while self.counter < self.LIMIT:
126
                    if QtCore.QThread.currentThread().isInterruptionRequested():
127
                        return
128
                    self.counter += 1
129
                    sleep(0.01)
130
                self.limit_reached = True
131

132
        worker = Worker()
133
        self.factory.work_function = worker.run
134
        self.test_object.run()
135
        cancel_timer = QtCore.QTimer()
136
        cancel_timer.timeout.connect(
137
            self.test_object.dialog.buttonBox.button(QtWidgets.QDialogButtonBox.Cancel).click
138
        )
139
        cancel_timer.start(90)
140
        while self.test_object.is_running():
141
            QtCore.QCoreApplication.processEvents(QtCore.QEventLoop.AllEvents, 10)
142
        self.assertGreater(len(self.test_object.addons_with_update), 0)
143

144
    def test_add_addon_to_table(self):
145
        mock_addon = MockAddon("MockAddon")
146
        self.test_object.dialog.tableWidget.clear()
147
        self.test_object._add_addon_to_table(mock_addon)
148
        self.assertEqual(self.test_object.dialog.tableWidget.rowCount(), 1)
149

150
    def test_update_addon_status(self):
151
        self.test_object._setup_dialog()
152
        self.test_object._update_addon_status(0, AddonStatus.WAITING)
153
        self.assertEqual(
154
            self.test_object.dialog.tableWidget.item(0, 1).text(),
155
            AddonStatus.WAITING.ui_string(),
156
        )
157
        self.test_object._update_addon_status(0, AddonStatus.INSTALLING)
158
        self.assertEqual(
159
            self.test_object.dialog.tableWidget.item(0, 1).text(),
160
            AddonStatus.INSTALLING.ui_string(),
161
        )
162
        self.test_object._update_addon_status(0, AddonStatus.SUCCEEDED)
163
        self.assertEqual(
164
            self.test_object.dialog.tableWidget.item(0, 1).text(),
165
            AddonStatus.SUCCEEDED.ui_string(),
166
        )
167
        self.test_object._update_addon_status(0, AddonStatus.FAILED)
168
        self.assertEqual(
169
            self.test_object.dialog.tableWidget.item(0, 1).text(),
170
            AddonStatus.FAILED.ui_string(),
171
        )
172

173
    def test_process_next_update(self):
174
        self.test_object._setup_dialog()
175
        self.test_object._launch_active_installer = lambda: None
176
        self.test_object._process_next_update()
177
        self.assertEqual(
178
            self.test_object.dialog.tableWidget.item(0, 1).text(),
179
            AddonStatus.INSTALLING.ui_string(),
180
        )
181

182
        self.test_object._process_next_update()
183
        self.assertEqual(
184
            self.test_object.dialog.tableWidget.item(1, 1).text(),
185
            AddonStatus.INSTALLING.ui_string(),
186
        )
187

188
        self.test_object._process_next_update()
189
        self.assertEqual(
190
            self.test_object.dialog.tableWidget.item(2, 1).text(),
191
            AddonStatus.INSTALLING.ui_string(),
192
        )
193

194
        self.test_object._process_next_update()
195

196
    def test_launch_active_installer(self):
197
        self.test_object.active_installer = self.factory.get_updater(self.addons[0])
198
        self.test_object._update_succeeded = lambda _: None
199
        self.test_object._update_failed = lambda _: None
200
        self.test_object.process_next_update = lambda: None
201
        self.test_object._launch_active_installer()
202
        # The above call does not block, so spin until it has completed (basically instantly in testing)
203
        while self.test_object.worker_thread.isRunning():
204
            QtCore.QCoreApplication.processEvents(QtCore.QEventLoop.AllEvents, 100)
205
        self.test_object.dialog.accept()
206

207
    def test_update_succeeded(self):
208
        self.test_object._setup_dialog()
209
        self.test_object._update_succeeded(self.addons[0])
210
        self.assertEqual(
211
            self.test_object.dialog.tableWidget.item(0, 1).text(),
212
            AddonStatus.SUCCEEDED.ui_string(),
213
        )
214

215
    def test_update_failed(self):
216
        self.test_object._setup_dialog()
217
        self.test_object._update_failed(self.addons[0])
218
        self.assertEqual(
219
            self.test_object.dialog.tableWidget.item(0, 1).text(),
220
            AddonStatus.FAILED.ui_string(),
221
        )
222

223
    def test_update_finished(self):
224
        self.test_object._setup_dialog()
225
        call_interceptor = CallInterceptor()
226
        self.test_object.worker_thread = QtCore.QThread()
227
        self.test_object.worker_thread.start()
228
        self.test_object._process_next_update = call_interceptor.intercept
229
        self.test_object.active_installer = self.factory.get_updater(self.addons[0])
230
        self.test_object._update_finished()
231
        self.assertFalse(self.test_object.worker_thread.isRunning())
232
        self.test_object.worker_thread.quit()
233
        self.assertTrue(call_interceptor.called)
234
        self.test_object.worker_thread.wait()
235

236
    def test_finalize(self):
237
        self.test_object._setup_dialog()
238
        self.test_object.worker_thread = QtCore.QThread()
239
        self.test_object.worker_thread.start()
240
        self.test_object._finalize()
241
        self.assertFalse(self.test_object.worker_thread.isRunning())
242
        self.test_object.worker_thread.quit()
243
        self.test_object.worker_thread.wait()
244
        self.assertFalse(self.test_object.running)
245
        self.assertIsNotNone(
246
            self.test_object.dialog.buttonBox.button(QtWidgets.QDialogButtonBox.Close)
247
        )
248
        self.assertIsNone(
249
            self.test_object.dialog.buttonBox.button(QtWidgets.QDialogButtonBox.Cancel)
250
        )
251

252
    def test_is_running(self):
253
        self.assertFalse(self.test_object.is_running())
254
        self.test_object.run()
255
        self.assertTrue(self.test_object.is_running())
256
        while self.test_object.is_running():
257
            QtCore.QCoreApplication.processEvents(QtCore.QEventLoop.AllEvents, 100)
258
        self.test_object.dialog.accept()
259

Использование cookies

Мы используем файлы cookie в соответствии с Политикой конфиденциальности и Политикой использования cookies.

Нажимая кнопку «Принимаю», Вы даете АО «СберТех» согласие на обработку Ваших персональных данных в целях совершенствования нашего веб-сайта и Сервиса GitVerse, а также повышения удобства их использования.

Запретить использование cookies Вы можете самостоятельно в настройках Вашего браузера.