FreeCAD

Форк
0
399 строк · 15.0 Кб
1
# SPDX-License-Identifier: LGPL-2.1-or-later
2
# ***************************************************************************
3
# *                                                                         *
4
# *   Copyright (c) 2022-2023 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
import tempfile
24
import unittest
25
import os
26
import sys
27

28
sys.path.append("../../")
29

30
from Addon import Addon, INTERNAL_WORKBENCHES
31
from addonmanager_macro import Macro
32

33

34
class TestAddon(unittest.TestCase):
35
    MODULE = "test_addon"  # file name without extension
36

37
    def setUp(self):
38
        self.test_dir = os.path.join(os.path.dirname(__file__), "..", "data")
39

40
    def test_display_name(self):
41
        # Case 1: No display name set elsewhere: name == display_name
42
        addon = Addon(
43
            "FreeCAD",
44
            "https://github.com/FreeCAD/FreeCAD",
45
            Addon.Status.NOT_INSTALLED,
46
            "master",
47
        )
48
        self.assertEqual(addon.name, "FreeCAD")
49
        self.assertEqual(addon.display_name, "FreeCAD")
50

51
        # Case 2: Package.xml metadata file sets a display name:
52
        addon.load_metadata_file(os.path.join(self.test_dir, "good_package.xml"))
53
        self.assertEqual(addon.name, "FreeCAD")
54
        self.assertEqual(addon.display_name, "Test Workbench")
55

56
    def test_git_url_cleanup(self):
57
        base_url = "https://github.com/FreeCAD/FreeCAD"
58
        test_urls = [f"  {base_url}  ", f"{base_url}.git", f"  {base_url}.git  "]
59
        for url in test_urls:
60
            addon = Addon("FreeCAD", url, Addon.Status.NOT_INSTALLED, "master")
61
            self.assertEqual(addon.url, base_url)
62

63
    def test_tag_extraction(self):
64
        addon = Addon(
65
            "FreeCAD",
66
            "https://github.com/FreeCAD/FreeCAD",
67
            Addon.Status.NOT_INSTALLED,
68
            "master",
69
        )
70
        addon.load_metadata_file(os.path.join(self.test_dir, "good_package.xml"))
71

72
        tags = addon.tags
73
        self.assertEqual(len(tags), 5)
74
        expected_tags = set()
75
        expected_tags.add("Tag0")
76
        expected_tags.add("Tag1")
77
        expected_tags.add("TagA")
78
        expected_tags.add("TagB")
79
        expected_tags.add("TagC")
80
        self.assertEqual(expected_tags, tags)
81

82
    def test_contains_functions(self):
83
        # Test package.xml combinations:
84

85
        # Workbenches
86
        addon_with_workbench = Addon(
87
            "FreeCAD",
88
            "https://github.com/FreeCAD/FreeCAD",
89
            Addon.Status.NOT_INSTALLED,
90
            "master",
91
        )
92
        addon_with_workbench.load_metadata_file(os.path.join(self.test_dir, "workbench_only.xml"))
93
        self.assertTrue(addon_with_workbench.contains_workbench())
94
        self.assertFalse(addon_with_workbench.contains_macro())
95
        self.assertFalse(addon_with_workbench.contains_preference_pack())
96

97
        # Macros
98
        addon_with_macro = Addon(
99
            "FreeCAD",
100
            "https://github.com/FreeCAD/FreeCAD",
101
            Addon.Status.NOT_INSTALLED,
102
            "master",
103
        )
104
        addon_with_macro.load_metadata_file(os.path.join(self.test_dir, "macro_only.xml"))
105
        self.assertFalse(addon_with_macro.contains_workbench())
106
        self.assertTrue(addon_with_macro.contains_macro())
107
        self.assertFalse(addon_with_macro.contains_preference_pack())
108

109
        # Preference Packs
110
        addon_with_prefpack = Addon(
111
            "FreeCAD",
112
            "https://github.com/FreeCAD/FreeCAD",
113
            Addon.Status.NOT_INSTALLED,
114
            "master",
115
        )
116
        addon_with_prefpack.load_metadata_file(os.path.join(self.test_dir, "prefpack_only.xml"))
117
        self.assertFalse(addon_with_prefpack.contains_workbench())
118
        self.assertFalse(addon_with_prefpack.contains_macro())
119
        self.assertTrue(addon_with_prefpack.contains_preference_pack())
120

121
        # Combination
122
        addon_with_all = Addon(
123
            "FreeCAD",
124
            "https://github.com/FreeCAD/FreeCAD",
125
            Addon.Status.NOT_INSTALLED,
126
            "master",
127
        )
128
        addon_with_all.load_metadata_file(os.path.join(self.test_dir, "combination.xml"))
129
        self.assertTrue(addon_with_all.contains_workbench())
130
        self.assertTrue(addon_with_all.contains_macro())
131
        self.assertTrue(addon_with_all.contains_preference_pack())
132

133
        # Now do the simple, explicitly-set cases
134
        addon_wb = Addon(
135
            "FreeCAD",
136
            "https://github.com/FreeCAD/FreeCAD",
137
            Addon.Status.NOT_INSTALLED,
138
            "master",
139
        )
140
        addon_wb.repo_type = Addon.Kind.WORKBENCH
141
        self.assertTrue(addon_wb.contains_workbench())
142
        self.assertFalse(addon_wb.contains_macro())
143
        self.assertFalse(addon_wb.contains_preference_pack())
144

145
        addon_m = Addon(
146
            "FreeCAD",
147
            "https://github.com/FreeCAD/FreeCAD",
148
            Addon.Status.NOT_INSTALLED,
149
            "master",
150
        )
151
        addon_m.repo_type = Addon.Kind.MACRO
152
        self.assertFalse(addon_m.contains_workbench())
153
        self.assertTrue(addon_m.contains_macro())
154
        self.assertFalse(addon_m.contains_preference_pack())
155

156
        # There is no equivalent for preference packs, they are always accompanied by a
157
        # metadata file
158

159
    def test_create_from_macro(self):
160
        macro_file = os.path.join(self.test_dir, "DoNothing.FCMacro")
161
        macro = Macro("DoNothing")
162
        macro.fill_details_from_file(macro_file)
163
        addon = Addon.from_macro(macro)
164

165
        self.assertEqual(addon.repo_type, Addon.Kind.MACRO)
166
        self.assertEqual(addon.name, "DoNothing")
167
        self.assertEqual(
168
            addon.macro.comment,
169
            "Do absolutely nothing. For Addon Manager integration tests.",
170
        )
171
        self.assertEqual(addon.url, "https://github.com/FreeCAD/FreeCAD")
172
        self.assertEqual(addon.macro.version, "1.0")
173
        self.assertEqual(len(addon.macro.other_files), 3)
174
        self.assertEqual(addon.macro.author, "Chris Hennes")
175
        self.assertEqual(addon.macro.date, "2022-02-28")
176
        self.assertEqual(addon.macro.icon, "not_real.png")
177
        self.assertNotEqual(addon.macro.xpm, "")
178

179
    def test_cache(self):
180
        addon = Addon(
181
            "FreeCAD",
182
            "https://github.com/FreeCAD/FreeCAD",
183
            Addon.Status.NOT_INSTALLED,
184
            "master",
185
        )
186
        cache_data = addon.to_cache()
187
        second_addon = Addon.from_cache(cache_data)
188

189
        self.assertTrue(addon.__dict__, second_addon.__dict__)
190

191
    def test_dependency_resolution(self):
192
        addonA = Addon(
193
            "AddonA",
194
            "https://github.com/FreeCAD/FakeAddonA",
195
            Addon.Status.NOT_INSTALLED,
196
            "master",
197
        )
198
        addonB = Addon(
199
            "AddonB",
200
            "https://github.com/FreeCAD/FakeAddonB",
201
            Addon.Status.NOT_INSTALLED,
202
            "master",
203
        )
204
        addonC = Addon(
205
            "AddonC",
206
            "https://github.com/FreeCAD/FakeAddonC",
207
            Addon.Status.NOT_INSTALLED,
208
            "master",
209
        )
210
        addonD = Addon(
211
            "AddonD",
212
            "https://github.com/FreeCAD/FakeAddonD",
213
            Addon.Status.NOT_INSTALLED,
214
            "master",
215
        )
216

217
        addonA.requires.add("AddonB")
218
        addonB.requires.add("AddonC")
219
        addonB.requires.add("AddonD")
220
        addonD.requires.add("CAM")
221

222
        all_addons = {
223
            addonA.name: addonA,
224
            addonB.name: addonB,
225
            addonC.name: addonC,
226
            addonD.name: addonD,
227
        }
228

229
        deps = Addon.Dependencies()
230
        addonA.walk_dependency_tree(all_addons, deps)
231

232
        self.assertEqual(len(deps.required_external_addons), 3)
233
        addon_strings = [addon.name for addon in deps.required_external_addons]
234
        self.assertTrue(
235
            "AddonB" in addon_strings,
236
            "AddonB not in required dependencies, and it should be.",
237
        )
238
        self.assertTrue(
239
            "AddonC" in addon_strings,
240
            "AddonC not in required dependencies, and it should be.",
241
        )
242
        self.assertTrue(
243
            "AddonD" in addon_strings,
244
            "AddonD not in required dependencies, and it should be.",
245
        )
246
        self.assertTrue(
247
            "CAM" in deps.internal_workbenches,
248
            "CAM not in workbench dependencies, and it should be.",
249
        )
250

251
    def test_internal_workbench_list(self):
252
        addon = Addon(
253
            "FreeCAD",
254
            "https://github.com/FreeCAD/FreeCAD",
255
            Addon.Status.NOT_INSTALLED,
256
            "master",
257
        )
258
        addon.load_metadata_file(os.path.join(self.test_dir, "depends_on_all_workbenches.xml"))
259
        deps = Addon.Dependencies()
260
        addon.walk_dependency_tree({}, deps)
261
        self.assertEqual(len(deps.internal_workbenches), len(INTERNAL_WORKBENCHES))
262

263
    def test_version_check(self):
264
        addon = Addon(
265
            "FreeCAD",
266
            "https://github.com/FreeCAD/FreeCAD",
267
            Addon.Status.NOT_INSTALLED,
268
            "master",
269
        )
270
        addon.load_metadata_file(os.path.join(self.test_dir, "test_version_detection.xml"))
271

272
        self.assertEqual(
273
            len(addon.tags),
274
            1,
275
            "Wrong number of tags found: version requirements should have restricted to only one",
276
        )
277
        self.assertFalse(
278
            "TagA" in addon.tags,
279
            "Found 'TagA' in tags, it should have been excluded by version requirement",
280
        )
281
        self.assertTrue(
282
            "TagB" in addon.tags,
283
            "Failed to find 'TagB' in tags, it should have been included",
284
        )
285
        self.assertFalse(
286
            "TagC" in addon.tags,
287
            "Found 'TagA' in tags, it should have been excluded by version requirement",
288
        )
289

290
    def test_try_find_wbname_in_files_empty_dir(self):
291
        with tempfile.TemporaryDirectory() as mod_dir:
292
            # Arrange
293
            test_addon = Addon("test")
294
            test_addon.mod_directory = mod_dir
295
            os.mkdir(os.path.join(mod_dir, test_addon.name))
296

297
            # Act
298
            wb_name = test_addon.try_find_wbname_in_files()
299

300
            # Assert
301
            self.assertEqual(wb_name, "")
302

303
    def test_try_find_wbname_in_files_non_python_ignored(self):
304
        with tempfile.TemporaryDirectory() as mod_dir:
305
            # Arrange
306
            test_addon = Addon("test")
307
            test_addon.mod_directory = mod_dir
308
            base_path = os.path.join(mod_dir, test_addon.name)
309
            os.mkdir(base_path)
310
            file_path = os.path.join(base_path, "test.txt")
311
            with open(file_path, "w", encoding="utf-8") as f:
312
                f.write("Gui.addWorkbench(TestWorkbench())")
313

314
            # Act
315
            wb_name = test_addon.try_find_wbname_in_files()
316

317
            # Assert
318
            self.assertEqual(wb_name, "")
319

320
    def test_try_find_wbname_in_files_simple(self):
321
        with tempfile.TemporaryDirectory() as mod_dir:
322
            # Arrange
323
            test_addon = Addon("test")
324
            test_addon.mod_directory = mod_dir
325
            base_path = os.path.join(mod_dir, test_addon.name)
326
            os.mkdir(base_path)
327
            file_path = os.path.join(base_path, "test.py")
328
            with open(file_path, "w", encoding="utf-8") as f:
329
                f.write("Gui.addWorkbench(TestWorkbench())")
330

331
            # Act
332
            wb_name = test_addon.try_find_wbname_in_files()
333

334
            # Assert
335
            self.assertEqual(wb_name, "TestWorkbench")
336

337
    def test_try_find_wbname_in_files_subdir(self):
338
        with tempfile.TemporaryDirectory() as mod_dir:
339
            # Arrange
340
            test_addon = Addon("test")
341
            test_addon.mod_directory = mod_dir
342
            base_path = os.path.join(mod_dir, test_addon.name)
343
            os.mkdir(base_path)
344
            subdir = os.path.join(base_path, "subdirectory")
345
            os.mkdir(subdir)
346
            file_path = os.path.join(subdir, "test.py")
347
            with open(file_path, "w", encoding="utf-8") as f:
348
                f.write("Gui.addWorkbench(TestWorkbench())")
349

350
            # Act
351
            wb_name = test_addon.try_find_wbname_in_files()
352

353
            # Assert
354
            self.assertEqual(wb_name, "TestWorkbench")
355

356
    def test_try_find_wbname_in_files_variable_used(self):
357
        with tempfile.TemporaryDirectory() as mod_dir:
358
            # Arrange
359
            test_addon = Addon("test")
360
            test_addon.mod_directory = mod_dir
361
            base_path = os.path.join(mod_dir, test_addon.name)
362
            os.mkdir(base_path)
363
            file_path = os.path.join(base_path, "test.py")
364
            with open(file_path, "w", encoding="utf-8") as f:
365
                f.write("Gui.addWorkbench(wb)")
366

367
            # Act
368
            wb_name = test_addon.try_find_wbname_in_files()
369

370
            # Assert
371
            self.assertEqual(wb_name, "")
372

373
    def test_try_find_wbname_in_files_variants(self):
374
        variants = [
375
            "Gui.addWorkbench(TestWorkbench())",
376
            "Gui.addWorkbench (TestWorkbench())",
377
            "Gui.addWorkbench( TestWorkbench() )",
378
            "Gui.addWorkbench(TestWorkbench( ))",
379
            "Gui.addWorkbench( TestWorkbench( ) )",
380
            "Gui.addWorkbench( TestWorkbench ( ) )",
381
            "Gui.addWorkbench ( TestWorkbench ( ) )",
382
        ]
383
        for variant in variants:
384
            with self.subTest(variant=variant):
385
                with tempfile.TemporaryDirectory() as mod_dir:
386
                    # Arrange
387
                    test_addon = Addon("test")
388
                    test_addon.mod_directory = mod_dir
389
                    base_path = os.path.join(mod_dir, test_addon.name)
390
                    os.mkdir(base_path)
391
                    file_path = os.path.join(base_path, "test.py")
392
                    with open(file_path, "w", encoding="utf-8") as f:
393
                        f.write(variant)
394

395
                    # Act
396
                    wb_name = test_addon.try_find_wbname_in_files()
397

398
                    # Assert
399
                    self.assertEqual(wb_name, "TestWorkbench")
400

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

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

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

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