TestProfiles.py 9.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182
  1. # Copyright (c) 2020 Ultimaker B.V.
  2. # Cura is released under the terms of the LGPLv3 or higher.
  3. from unittest.mock import MagicMock
  4. import configparser # To read the profiles.
  5. import os
  6. import os.path
  7. import pytest
  8. from UM.FastConfigParser import FastConfigParser
  9. from cura.CuraApplication import CuraApplication # To compare against the current SettingVersion.
  10. from UM.Settings.DefinitionContainer import DefinitionContainer
  11. from UM.Settings.InstanceContainer import InstanceContainer
  12. from UM.VersionUpgradeManager import VersionUpgradeManager
  13. def collectAllQualities():
  14. result = []
  15. for root, directories, filenames in os.walk(os.path.abspath(os.path.join(os.path.dirname(__file__), "..", "..", "resources", "quality"))):
  16. for filename in filenames:
  17. result.append(os.path.join(root, filename))
  18. return result
  19. def collecAllDefinitionIds():
  20. result = []
  21. for root, directories, filenames in os.walk(os.path.abspath(os.path.join(os.path.dirname(__file__), "..", "..", "resources", "definitions"))):
  22. for filename in filenames:
  23. result.append(os.path.basename(filename).split(".")[0])
  24. return result
  25. def collectAllSettingIds():
  26. VersionUpgradeManager._VersionUpgradeManager__instance = VersionUpgradeManager(MagicMock())
  27. CuraApplication._initializeSettingDefinitions()
  28. definition_container = DefinitionContainer("whatever")
  29. with open(os.path.join(os.path.dirname(__file__), "..", "..", "resources", "definitions", "fdmprinter.def.json"), encoding = "utf-8") as data:
  30. definition_container.deserialize(data.read())
  31. return definition_container.getAllKeys()
  32. def collectAllVariants():
  33. result = []
  34. for root, directories, filenames in os.walk(os.path.abspath(os.path.join(os.path.dirname(__file__), "..", "..", "resources", "variants"))):
  35. for filename in filenames:
  36. result.append(os.path.join(root, filename))
  37. return result
  38. def collectAllIntents():
  39. result = []
  40. for root, directories, filenames in os.walk(os.path.abspath(os.path.join(os.path.dirname(__file__), "..", "..", "resources", "intent"))):
  41. for filename in filenames:
  42. result.append(os.path.join(root, filename))
  43. return result
  44. all_definition_ids = collecAllDefinitionIds()
  45. quality_filepaths = collectAllQualities()
  46. all_setting_ids = collectAllSettingIds()
  47. variant_filepaths = collectAllVariants()
  48. intent_filepaths = collectAllIntents()
  49. def test_uniqueID():
  50. """Check if the ID's from the qualities, variants & intents are unique."""
  51. all_paths = quality_filepaths + variant_filepaths + intent_filepaths
  52. all_ids = {}
  53. for path in all_paths:
  54. profile_id = os.path.basename(path)
  55. profile_id = profile_id.replace(".inst.cfg", "")
  56. if profile_id not in all_ids:
  57. all_ids[profile_id] = []
  58. all_ids[profile_id].append(path)
  59. duplicated_ids_with_paths = {profile_id: paths for profile_id, paths in all_ids.items() if len(paths) > 1}
  60. if len(duplicated_ids_with_paths.keys()) == 0:
  61. return # No issues!
  62. assert False, "Duplicate profile ID's were detected! Ensure that every profile ID is unique: %s" % duplicated_ids_with_paths
  63. @pytest.mark.parametrize("file_name", quality_filepaths)
  64. def test_validateQualityProfiles(file_name):
  65. """Attempt to load all the quality profiles."""
  66. try:
  67. with open(file_name, encoding = "utf-8") as data:
  68. serialized = data.read()
  69. result = InstanceContainer._readAndValidateSerialized(serialized)
  70. # Fairly obvious, but all the types here should be of the type quality
  71. assert InstanceContainer.getConfigurationTypeFromSerialized(serialized) == "quality"
  72. # All quality profiles must be linked to an existing definition.
  73. assert result["general"]["definition"] in all_definition_ids, "The quality profile %s links to an unknown definition (%s)" % (file_name, result["general"]["definition"])
  74. # We don't care what the value is, as long as it's there.
  75. assert result["metadata"].get("quality_type", None) is not None
  76. # Check that all the values that we say something about are known.
  77. if "values" in result:
  78. quality_setting_keys = set(result["values"])
  79. # Prune all the comments from the values
  80. quality_setting_keys = {key for key in quality_setting_keys if not key.startswith("#")}
  81. has_unknown_settings = not quality_setting_keys.issubset(all_setting_ids)
  82. if has_unknown_settings:
  83. assert False, "The following setting(s) %s are defined in the quality %s, but not in fdmprinter.def.json" % ([key for key in quality_setting_keys if key not in all_setting_ids], file_name)
  84. except Exception as e:
  85. # File can't be read, header sections missing, whatever the case, this shouldn't happen!
  86. assert False, f"Got an Exception while reading the file [{file_name}]: {e}"
  87. @pytest.mark.parametrize("file_name", intent_filepaths)
  88. def test_validateIntentProfiles(file_name):
  89. try:
  90. with open(file_name, encoding = "utf-8") as f:
  91. serialized = f.read()
  92. result = InstanceContainer._readAndValidateSerialized(serialized)
  93. assert InstanceContainer.getConfigurationTypeFromSerialized(serialized) == "intent", "The intent folder must only contain intent profiles."
  94. assert result["general"]["definition"] in all_definition_ids, "The definition for this intent profile must exist."
  95. assert result["metadata"].get("intent_category", None) is not None, "All intent profiles must have some intent category."
  96. assert result["metadata"].get("quality_type", None) is not None, "All intent profiles must be linked to some quality type."
  97. assert result["metadata"].get("material", None) is not None, "All intent profiles must be linked to some material."
  98. assert result["metadata"].get("variant", None) is not None, "All intent profiles must be linked to some variant."
  99. # Check that all the values that we say something about are known.
  100. if "values" in result:
  101. intent_setting_keys = set(result["values"])
  102. unknown_settings = intent_setting_keys - all_setting_ids
  103. assert len(unknown_settings) == 0, "The settings {setting_list} are defined in the intent {file_name}, but not in fdmprinter.def.json".format(setting_list = unknown_settings, file_name = file_name)
  104. except Exception as e:
  105. # File can't be read, header sections missing, whatever the case, this shouldn't happen!
  106. assert False, "Got an exception while reading the file {file_name}: {err}".format(file_name = file_name, err = str(e))
  107. @pytest.mark.parametrize("file_name", variant_filepaths)
  108. def test_validateVariantProfiles(file_name):
  109. """Attempt to load all the variant profiles."""
  110. try:
  111. with open(file_name, encoding = "utf-8") as data:
  112. serialized = data.read()
  113. result = InstanceContainer._readAndValidateSerialized(serialized)
  114. # Fairly obvious, but all the types here should be of the type quality
  115. assert InstanceContainer.getConfigurationTypeFromSerialized(serialized) == "variant", "The profile %s should be of type variant, but isn't" % file_name
  116. # All quality profiles must be linked to an existing definition.
  117. assert result["general"]["definition"] in all_definition_ids, "The profile %s isn't associated with a definition" % file_name
  118. # Check that all the values that we say something about are known.
  119. if "values" in result:
  120. variant_setting_keys = set(result["values"])
  121. # Prune all the comments from the values
  122. variant_setting_keys = {key for key in variant_setting_keys if not key.startswith("#")}
  123. has_unknown_settings = not variant_setting_keys.issubset(all_setting_ids)
  124. if has_unknown_settings:
  125. assert False, "The following setting(s) %s are defined in the variant %s, but not in fdmprinter.def.json" % ([key for key in variant_setting_keys if key not in all_setting_ids], file_name)
  126. except Exception as e:
  127. # File can't be read, header sections missing, whatever the case, this shouldn't happen!
  128. assert False, "Got an exception while reading the file {file_name}: {err}".format(file_name = file_name, err = str(e))
  129. @pytest.mark.parametrize("file_name", quality_filepaths + variant_filepaths + intent_filepaths)
  130. def test_versionUpToDate(file_name):
  131. try:
  132. with open(file_name, encoding = "utf-8") as data:
  133. parser = FastConfigParser(data.read())
  134. assert "general" in parser
  135. assert "version" in parser["general"]
  136. assert int(parser["general"]["version"]) == InstanceContainer.Version, "The version of this profile is not up to date!"
  137. assert "metadata" in parser
  138. assert "setting_version" in parser["metadata"]
  139. assert int(parser["metadata"]["setting_version"]) == CuraApplication.SettingVersion, "The version of this profile is not up to date!"
  140. except Exception as e:
  141. # File can't be read, header sections missing, whatever the case, this shouldn't happen!
  142. assert False, "Got an exception while reading the file {file_name}: {err}".format(file_name = file_name, err = str(e))