201 lines
8.5 KiB
Python
201 lines
8.5 KiB
Python
# SPDX-License-Identifier: LGPL-2.1-or-later
|
|
# ***************************************************************************
|
|
# * *
|
|
# * Copyright (c) 2022-2023 FreeCAD Project Association *
|
|
# * *
|
|
# * This file is part of FreeCAD. *
|
|
# * *
|
|
# * FreeCAD is free software: you can redistribute it and/or modify it *
|
|
# * under the terms of the GNU Lesser General Public License as *
|
|
# * published by the Free Software Foundation, either version 2.1 of the *
|
|
# * License, or (at your option) any later version. *
|
|
# * *
|
|
# * FreeCAD 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 *
|
|
# * Lesser General Public License for more details. *
|
|
# * *
|
|
# * You should have received a copy of the GNU Lesser General Public *
|
|
# * License along with FreeCAD. If not, see *
|
|
# * <https://www.gnu.org/licenses/>. *
|
|
# * *
|
|
# ***************************************************************************
|
|
|
|
import json
|
|
import unittest
|
|
import os
|
|
import tempfile
|
|
|
|
import FreeCAD
|
|
|
|
from PySide import QtCore
|
|
|
|
import NetworkManager
|
|
from Addon import Addon
|
|
from addonmanager_workers_startup import (
|
|
CreateAddonListWorker,
|
|
LoadPackagesFromCacheWorker,
|
|
LoadMacrosFromCacheWorker,
|
|
)
|
|
|
|
run_slow_tests = False
|
|
|
|
|
|
class TestWorkersStartup(unittest.TestCase):
|
|
|
|
MODULE = "test_workers_startup" # file name without extension
|
|
|
|
@unittest.skipUnless(run_slow_tests, "This integration test is slow and uses the network")
|
|
def setUp(self):
|
|
"""Set up the test"""
|
|
self.test_dir = os.path.join(
|
|
FreeCAD.getHomePath(), "Mod", "AddonManager", "AddonManagerTest", "data"
|
|
)
|
|
|
|
self.saved_mod_directory = Addon.mod_directory
|
|
self.saved_cache_directory = Addon.cache_directory
|
|
Addon.mod_directory = os.path.join(tempfile.gettempdir(), "FreeCADTesting", "Mod")
|
|
Addon.cache_directory = os.path.join(tempfile.gettempdir(), "FreeCADTesting", "Cache")
|
|
|
|
os.makedirs(Addon.mod_directory, mode=0o777, exist_ok=True)
|
|
os.makedirs(Addon.cache_directory, mode=0o777, exist_ok=True)
|
|
|
|
url = "https://api.github.com/zen"
|
|
NetworkManager.InitializeNetworkManager()
|
|
result = NetworkManager.AM_NETWORK_MANAGER.blocking_get(url)
|
|
if result is None:
|
|
self.skipTest("No active internet connection detected")
|
|
|
|
self.addon_list = []
|
|
self.macro_counter = 0
|
|
self.workbench_counter = 0
|
|
self.prefpack_counter = 0
|
|
self.addon_from_cache_counter = 0
|
|
self.macro_from_cache_counter = 0
|
|
|
|
self.package_cache = {}
|
|
self.macro_cache = []
|
|
|
|
self.package_cache_filename = os.path.join(Addon.cache_directory, "packages.json")
|
|
self.macro_cache_filename = os.path.join(Addon.cache_directory, "macros.json")
|
|
|
|
# Store the user's preference for whether git is enabled or disabled
|
|
pref = FreeCAD.ParamGet("User parameter:BaseApp/Preferences/Addons")
|
|
self.saved_git_disabled_status = pref.GetBool("disableGit", False)
|
|
|
|
def tearDown(self):
|
|
"""Tear down the test"""
|
|
Addon.mod_directory = self.saved_mod_directory
|
|
Addon.cache_directory = self.saved_cache_directory
|
|
pref = FreeCAD.ParamGet("User parameter:BaseApp/Preferences/Addons")
|
|
pref.SetBool("disableGit", self.saved_git_disabled_status)
|
|
|
|
def test_create_addon_list_worker(self):
|
|
"""Test whether any addons are added: runs the full query, so this potentially is a SLOW
|
|
test."""
|
|
worker = CreateAddonListWorker()
|
|
worker.addon_repo.connect(self._addon_added)
|
|
worker.start()
|
|
while worker.isRunning():
|
|
QtCore.QCoreApplication.processEvents(QtCore.QEventLoop.AllEvents, 50)
|
|
QtCore.QCoreApplication.processEvents(QtCore.QEventLoop.AllEvents)
|
|
|
|
self.assertGreater(self.macro_counter, 0, "No macros returned")
|
|
self.assertGreater(self.workbench_counter, 0, "No workbenches returned")
|
|
|
|
# Make sure there are no duplicates:
|
|
addon_name_set = set()
|
|
for addon in self.addon_list:
|
|
addon_name_set.add(addon.name)
|
|
self.assertEqual(
|
|
len(addon_name_set), len(self.addon_list), "Duplicate names are not allowed"
|
|
)
|
|
|
|
# Write the cache data
|
|
if hasattr(self, "package_cache"):
|
|
with open(self.package_cache_filename, "w", encoding="utf-8") as f:
|
|
f.write(json.dumps(self.package_cache, indent=" "))
|
|
if hasattr(self, "macro_cache"):
|
|
with open(self.macro_cache_filename, "w", encoding="utf-8") as f:
|
|
f.write(json.dumps(self.macro_cache, indent=" "))
|
|
|
|
original_macro_counter = self.macro_counter
|
|
original_addon_list = self.addon_list.copy()
|
|
self.macro_counter = 0
|
|
self.workbench_counter = 0
|
|
self.addon_list.clear()
|
|
|
|
# Now try loading the same data from the cache we just created
|
|
worker = LoadPackagesFromCacheWorker(self.package_cache_filename)
|
|
worker.override_metadata_cache_path(os.path.join(Addon.cache_directory, "PackageMetadata"))
|
|
worker.addon_repo.connect(self._addon_added)
|
|
|
|
worker.start()
|
|
while worker.isRunning():
|
|
QtCore.QCoreApplication.processEvents(QtCore.QEventLoop.AllEvents, 50)
|
|
QtCore.QCoreApplication.processEvents(QtCore.QEventLoop.AllEvents)
|
|
|
|
worker = LoadMacrosFromCacheWorker(self.macro_cache_filename)
|
|
worker.add_macro_signal.connect(self._addon_added)
|
|
|
|
worker.start()
|
|
while worker.isRunning():
|
|
QtCore.QCoreApplication.processEvents(QtCore.QEventLoop.AllEvents, 50)
|
|
QtCore.QCoreApplication.processEvents(QtCore.QEventLoop.AllEvents)
|
|
|
|
# Make sure that every addon in the original list is also in the new list
|
|
fail_counter = 0
|
|
for original_addon in original_addon_list:
|
|
found = False
|
|
for addon in self.addon_list:
|
|
if addon.name == original_addon.name:
|
|
found = True
|
|
break
|
|
if not found:
|
|
print(f"Failed to load {addon.name} from cache")
|
|
fail_counter += 1
|
|
self.assertEqual(fail_counter, 0)
|
|
|
|
# Make sure there are no duplicates:
|
|
addon_name_set.clear()
|
|
for addon in self.addon_list:
|
|
addon_name_set.add(addon.name)
|
|
|
|
self.assertEqual(len(addon_name_set), len(self.addon_list))
|
|
self.assertEqual(len(original_addon_list), len(self.addon_list))
|
|
|
|
self.assertEqual(
|
|
original_macro_counter,
|
|
self.macro_counter,
|
|
"Cache loaded a different number of macros",
|
|
)
|
|
# We can't check workbench and preference pack counting at this point, because that relies
|
|
# on the package.xml metadata file, which this test does not download.
|
|
|
|
def test_create_addon_list_git_disabled(self):
|
|
"""If the user has git enabled, also test the addon manager with git disabled"""
|
|
if self.saved_git_disabled_status:
|
|
self.skipTest("Git is disabled, this test is redundant")
|
|
|
|
pref = FreeCAD.ParamGet("User parameter:BaseApp/Preferences/Addons")
|
|
pref.SetBool("disableGit", True)
|
|
|
|
self.test_create_addon_list_worker()
|
|
|
|
def _addon_added(self, addon: Addon):
|
|
"""Callback for adding an Addon: tracks the list, and counts the various types"""
|
|
print(f"Addon added: {addon.name}")
|
|
self.addon_list.append(addon)
|
|
if addon.contains_workbench():
|
|
self.workbench_counter += 1
|
|
if addon.contains_macro():
|
|
self.macro_counter += 1
|
|
if addon.contains_preference_pack():
|
|
self.prefpack_counter += 1
|
|
|
|
# Also record the information for cache purposes
|
|
if addon.macro is None:
|
|
self.package_cache[addon.name] = addon.to_cache()
|
|
else:
|
|
self.macro_cache.append(addon.macro.to_cache())
|