FreeCAD
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# ***************************************************************************
23import tempfile24import unittest25import os26import sys27
28sys.path.append("../../")29
30from Addon import Addon, INTERNAL_WORKBENCHES31from addonmanager_macro import Macro32
33
34class TestAddon(unittest.TestCase):35MODULE = "test_addon" # file name without extension36
37def setUp(self):38self.test_dir = os.path.join(os.path.dirname(__file__), "..", "data")39
40def test_display_name(self):41# Case 1: No display name set elsewhere: name == display_name42addon = Addon(43"FreeCAD",44"https://github.com/FreeCAD/FreeCAD",45Addon.Status.NOT_INSTALLED,46"master",47)48self.assertEqual(addon.name, "FreeCAD")49self.assertEqual(addon.display_name, "FreeCAD")50
51# Case 2: Package.xml metadata file sets a display name:52addon.load_metadata_file(os.path.join(self.test_dir, "good_package.xml"))53self.assertEqual(addon.name, "FreeCAD")54self.assertEqual(addon.display_name, "Test Workbench")55
56def test_git_url_cleanup(self):57base_url = "https://github.com/FreeCAD/FreeCAD"58test_urls = [f" {base_url} ", f"{base_url}.git", f" {base_url}.git "]59for url in test_urls:60addon = Addon("FreeCAD", url, Addon.Status.NOT_INSTALLED, "master")61self.assertEqual(addon.url, base_url)62
63def test_tag_extraction(self):64addon = Addon(65"FreeCAD",66"https://github.com/FreeCAD/FreeCAD",67Addon.Status.NOT_INSTALLED,68"master",69)70addon.load_metadata_file(os.path.join(self.test_dir, "good_package.xml"))71
72tags = addon.tags73self.assertEqual(len(tags), 5)74expected_tags = set()75expected_tags.add("Tag0")76expected_tags.add("Tag1")77expected_tags.add("TagA")78expected_tags.add("TagB")79expected_tags.add("TagC")80self.assertEqual(expected_tags, tags)81
82def test_contains_functions(self):83# Test package.xml combinations:84
85# Workbenches86addon_with_workbench = Addon(87"FreeCAD",88"https://github.com/FreeCAD/FreeCAD",89Addon.Status.NOT_INSTALLED,90"master",91)92addon_with_workbench.load_metadata_file(os.path.join(self.test_dir, "workbench_only.xml"))93self.assertTrue(addon_with_workbench.contains_workbench())94self.assertFalse(addon_with_workbench.contains_macro())95self.assertFalse(addon_with_workbench.contains_preference_pack())96
97# Macros98addon_with_macro = Addon(99"FreeCAD",100"https://github.com/FreeCAD/FreeCAD",101Addon.Status.NOT_INSTALLED,102"master",103)104addon_with_macro.load_metadata_file(os.path.join(self.test_dir, "macro_only.xml"))105self.assertFalse(addon_with_macro.contains_workbench())106self.assertTrue(addon_with_macro.contains_macro())107self.assertFalse(addon_with_macro.contains_preference_pack())108
109# Preference Packs110addon_with_prefpack = Addon(111"FreeCAD",112"https://github.com/FreeCAD/FreeCAD",113Addon.Status.NOT_INSTALLED,114"master",115)116addon_with_prefpack.load_metadata_file(os.path.join(self.test_dir, "prefpack_only.xml"))117self.assertFalse(addon_with_prefpack.contains_workbench())118self.assertFalse(addon_with_prefpack.contains_macro())119self.assertTrue(addon_with_prefpack.contains_preference_pack())120
121# Combination122addon_with_all = Addon(123"FreeCAD",124"https://github.com/FreeCAD/FreeCAD",125Addon.Status.NOT_INSTALLED,126"master",127)128addon_with_all.load_metadata_file(os.path.join(self.test_dir, "combination.xml"))129self.assertTrue(addon_with_all.contains_workbench())130self.assertTrue(addon_with_all.contains_macro())131self.assertTrue(addon_with_all.contains_preference_pack())132
133# Now do the simple, explicitly-set cases134addon_wb = Addon(135"FreeCAD",136"https://github.com/FreeCAD/FreeCAD",137Addon.Status.NOT_INSTALLED,138"master",139)140addon_wb.repo_type = Addon.Kind.WORKBENCH141self.assertTrue(addon_wb.contains_workbench())142self.assertFalse(addon_wb.contains_macro())143self.assertFalse(addon_wb.contains_preference_pack())144
145addon_m = Addon(146"FreeCAD",147"https://github.com/FreeCAD/FreeCAD",148Addon.Status.NOT_INSTALLED,149"master",150)151addon_m.repo_type = Addon.Kind.MACRO152self.assertFalse(addon_m.contains_workbench())153self.assertTrue(addon_m.contains_macro())154self.assertFalse(addon_m.contains_preference_pack())155
156# There is no equivalent for preference packs, they are always accompanied by a157# metadata file158
159def test_create_from_macro(self):160macro_file = os.path.join(self.test_dir, "DoNothing.FCMacro")161macro = Macro("DoNothing")162macro.fill_details_from_file(macro_file)163addon = Addon.from_macro(macro)164
165self.assertEqual(addon.repo_type, Addon.Kind.MACRO)166self.assertEqual(addon.name, "DoNothing")167self.assertEqual(168addon.macro.comment,169"Do absolutely nothing. For Addon Manager integration tests.",170)171self.assertEqual(addon.url, "https://github.com/FreeCAD/FreeCAD")172self.assertEqual(addon.macro.version, "1.0")173self.assertEqual(len(addon.macro.other_files), 3)174self.assertEqual(addon.macro.author, "Chris Hennes")175self.assertEqual(addon.macro.date, "2022-02-28")176self.assertEqual(addon.macro.icon, "not_real.png")177self.assertNotEqual(addon.macro.xpm, "")178
179def test_cache(self):180addon = Addon(181"FreeCAD",182"https://github.com/FreeCAD/FreeCAD",183Addon.Status.NOT_INSTALLED,184"master",185)186cache_data = addon.to_cache()187second_addon = Addon.from_cache(cache_data)188
189self.assertTrue(addon.__dict__, second_addon.__dict__)190
191def test_dependency_resolution(self):192addonA = Addon(193"AddonA",194"https://github.com/FreeCAD/FakeAddonA",195Addon.Status.NOT_INSTALLED,196"master",197)198addonB = Addon(199"AddonB",200"https://github.com/FreeCAD/FakeAddonB",201Addon.Status.NOT_INSTALLED,202"master",203)204addonC = Addon(205"AddonC",206"https://github.com/FreeCAD/FakeAddonC",207Addon.Status.NOT_INSTALLED,208"master",209)210addonD = Addon(211"AddonD",212"https://github.com/FreeCAD/FakeAddonD",213Addon.Status.NOT_INSTALLED,214"master",215)216
217addonA.requires.add("AddonB")218addonB.requires.add("AddonC")219addonB.requires.add("AddonD")220addonD.requires.add("CAM")221
222all_addons = {223addonA.name: addonA,224addonB.name: addonB,225addonC.name: addonC,226addonD.name: addonD,227}228
229deps = Addon.Dependencies()230addonA.walk_dependency_tree(all_addons, deps)231
232self.assertEqual(len(deps.required_external_addons), 3)233addon_strings = [addon.name for addon in deps.required_external_addons]234self.assertTrue(235"AddonB" in addon_strings,236"AddonB not in required dependencies, and it should be.",237)238self.assertTrue(239"AddonC" in addon_strings,240"AddonC not in required dependencies, and it should be.",241)242self.assertTrue(243"AddonD" in addon_strings,244"AddonD not in required dependencies, and it should be.",245)246self.assertTrue(247"CAM" in deps.internal_workbenches,248"CAM not in workbench dependencies, and it should be.",249)250
251def test_internal_workbench_list(self):252addon = Addon(253"FreeCAD",254"https://github.com/FreeCAD/FreeCAD",255Addon.Status.NOT_INSTALLED,256"master",257)258addon.load_metadata_file(os.path.join(self.test_dir, "depends_on_all_workbenches.xml"))259deps = Addon.Dependencies()260addon.walk_dependency_tree({}, deps)261self.assertEqual(len(deps.internal_workbenches), len(INTERNAL_WORKBENCHES))262
263def test_version_check(self):264addon = Addon(265"FreeCAD",266"https://github.com/FreeCAD/FreeCAD",267Addon.Status.NOT_INSTALLED,268"master",269)270addon.load_metadata_file(os.path.join(self.test_dir, "test_version_detection.xml"))271
272self.assertEqual(273len(addon.tags),2741,275"Wrong number of tags found: version requirements should have restricted to only one",276)277self.assertFalse(278"TagA" in addon.tags,279"Found 'TagA' in tags, it should have been excluded by version requirement",280)281self.assertTrue(282"TagB" in addon.tags,283"Failed to find 'TagB' in tags, it should have been included",284)285self.assertFalse(286"TagC" in addon.tags,287"Found 'TagA' in tags, it should have been excluded by version requirement",288)289
290def test_try_find_wbname_in_files_empty_dir(self):291with tempfile.TemporaryDirectory() as mod_dir:292# Arrange293test_addon = Addon("test")294test_addon.mod_directory = mod_dir295os.mkdir(os.path.join(mod_dir, test_addon.name))296
297# Act298wb_name = test_addon.try_find_wbname_in_files()299
300# Assert301self.assertEqual(wb_name, "")302
303def test_try_find_wbname_in_files_non_python_ignored(self):304with tempfile.TemporaryDirectory() as mod_dir:305# Arrange306test_addon = Addon("test")307test_addon.mod_directory = mod_dir308base_path = os.path.join(mod_dir, test_addon.name)309os.mkdir(base_path)310file_path = os.path.join(base_path, "test.txt")311with open(file_path, "w", encoding="utf-8") as f:312f.write("Gui.addWorkbench(TestWorkbench())")313
314# Act315wb_name = test_addon.try_find_wbname_in_files()316
317# Assert318self.assertEqual(wb_name, "")319
320def test_try_find_wbname_in_files_simple(self):321with tempfile.TemporaryDirectory() as mod_dir:322# Arrange323test_addon = Addon("test")324test_addon.mod_directory = mod_dir325base_path = os.path.join(mod_dir, test_addon.name)326os.mkdir(base_path)327file_path = os.path.join(base_path, "test.py")328with open(file_path, "w", encoding="utf-8") as f:329f.write("Gui.addWorkbench(TestWorkbench())")330
331# Act332wb_name = test_addon.try_find_wbname_in_files()333
334# Assert335self.assertEqual(wb_name, "TestWorkbench")336
337def test_try_find_wbname_in_files_subdir(self):338with tempfile.TemporaryDirectory() as mod_dir:339# Arrange340test_addon = Addon("test")341test_addon.mod_directory = mod_dir342base_path = os.path.join(mod_dir, test_addon.name)343os.mkdir(base_path)344subdir = os.path.join(base_path, "subdirectory")345os.mkdir(subdir)346file_path = os.path.join(subdir, "test.py")347with open(file_path, "w", encoding="utf-8") as f:348f.write("Gui.addWorkbench(TestWorkbench())")349
350# Act351wb_name = test_addon.try_find_wbname_in_files()352
353# Assert354self.assertEqual(wb_name, "TestWorkbench")355
356def test_try_find_wbname_in_files_variable_used(self):357with tempfile.TemporaryDirectory() as mod_dir:358# Arrange359test_addon = Addon("test")360test_addon.mod_directory = mod_dir361base_path = os.path.join(mod_dir, test_addon.name)362os.mkdir(base_path)363file_path = os.path.join(base_path, "test.py")364with open(file_path, "w", encoding="utf-8") as f:365f.write("Gui.addWorkbench(wb)")366
367# Act368wb_name = test_addon.try_find_wbname_in_files()369
370# Assert371self.assertEqual(wb_name, "")372
373def test_try_find_wbname_in_files_variants(self):374variants = [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]383for variant in variants:384with self.subTest(variant=variant):385with tempfile.TemporaryDirectory() as mod_dir:386# Arrange387test_addon = Addon("test")388test_addon.mod_directory = mod_dir389base_path = os.path.join(mod_dir, test_addon.name)390os.mkdir(base_path)391file_path = os.path.join(base_path, "test.py")392with open(file_path, "w", encoding="utf-8") as f:393f.write(variant)394
395# Act396wb_name = test_addon.try_find_wbname_in_files()397
398# Assert399self.assertEqual(wb_name, "TestWorkbench")400