TestGlobalStack.py 31 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624
  1. # Copyright (c) 2017 Ultimaker B.V.
  2. # Cura is released under the terms of the AGPLv3 or higher.
  3. import os.path #To find the test files.
  4. import pytest #This module contains unit tests.
  5. import unittest.mock #To monkeypatch some mocks in place of dependencies.
  6. import functools
  7. import cura.Settings.GlobalStack #The module we're testing.
  8. import cura.Settings.CuraContainerStack #To get the list of container types.
  9. from cura.Settings.Exceptions import TooManyExtrudersError, InvalidContainerError, InvalidOperationError #To test raising these errors.
  10. from UM.Settings.DefinitionContainer import DefinitionContainer #To test against the class DefinitionContainer.
  11. from UM.Settings.InstanceContainer import InstanceContainer #To test against the class InstanceContainer.
  12. import UM.Settings.ContainerRegistry
  13. import UM.Settings.ContainerStack
  14. class MockContainer:
  15. def __init__(self, container_id, type = "mock"):
  16. self._id = container_id
  17. self._type = type
  18. self._property_map = {}
  19. def getId(self):
  20. return self._id
  21. def getMetaDataEntry(self, entry, default = None):
  22. if entry == "type":
  23. return self._type
  24. return default
  25. def getProperty(self, key, property_name):
  26. if key not in self._property_map:
  27. return None
  28. if property_name not in self._property_map[key]:
  29. return None
  30. return self._property_map[key][property_name]
  31. def setProperty(self, key, property_name, value):
  32. if key not in self._property_map:
  33. self._property_map[key] = {}
  34. self._property_map[key][property_name] = value
  35. propertyChanged = unittest.mock.MagicMock()
  36. ## Fake container registry that always provides all containers you ask of.
  37. @pytest.yield_fixture()
  38. def container_registry():
  39. registry = unittest.mock.MagicMock()
  40. registry.typeMetaData = "registry_mock"
  41. def findInstanceContainers(registry, **kwargs):
  42. container_id = kwargs.get("id", default = "test_container")
  43. return [MockContainer(container_id, registry.typeMetaData)]
  44. registry.findInstanceContainers = functools.partial(findInstanceContainers, registry)
  45. def findContainers(registry, container_type = None, id = None):
  46. if not id:
  47. id = "test_container"
  48. return [MockContainer(id, registry.typeMetaData)]
  49. registry.findContainers = functools.partial(findContainers, registry)
  50. def getEmptyInstanceContainer():
  51. return MockContainer(container_id = "empty")
  52. registry.getEmptyInstanceContainer = getEmptyInstanceContainer
  53. UM.Settings.ContainerRegistry.ContainerRegistry._ContainerRegistry__instance = registry
  54. UM.Settings.ContainerStack._containerRegistry = registry
  55. yield registry
  56. UM.Settings.ContainerRegistry.ContainerRegistry._ContainerRegistry__instance = None
  57. UM.Settings.ContainerStack._containerRegistry = None
  58. #An empty global stack to test with.
  59. @pytest.fixture()
  60. def global_stack() -> cura.Settings.GlobalStack.GlobalStack:
  61. return cura.Settings.GlobalStack.GlobalStack("TestStack")
  62. @pytest.fixture()
  63. def writable_global_stack(global_stack):
  64. global_stack.userChanges = MockContainer("test_user_changes", "user")
  65. global_stack.qualityChanges = MockContainer("test_quality_changes", "quality_changes")
  66. global_stack.quality = MockContainer("test_quality", "quality")
  67. global_stack.material = MockContainer("test_material", "material")
  68. global_stack.variant = MockContainer("test_variant", "variant")
  69. global_stack.definitionChanges = MockContainer("test_definition_changes", "definition_changes")
  70. global_stack.definition = DefinitionContainerSubClass()
  71. return global_stack
  72. ## Place-in function for findContainer that finds only containers that start
  73. # with "some_".
  74. def findSomeContainers(container_id = "*", container_type = None, type = None, category = "*"):
  75. if container_id.startswith("some_"):
  76. return UM.Settings.ContainerRegistry._EmptyInstanceContainer(container_id)
  77. if container_type == DefinitionContainer:
  78. definition_mock = unittest.mock.MagicMock()
  79. definition_mock.getId = unittest.mock.MagicMock(return_value = "some_definition") #getId returns some_definition.
  80. return definition_mock
  81. ## Helper function to read the contents of a container stack in the test
  82. # stack folder.
  83. #
  84. # \param filename The name of the file in the "stacks" folder to read from.
  85. # \return The contents of that file.
  86. def readStack(filename):
  87. with open(os.path.join(os.path.dirname(os.path.abspath(__file__)), "stacks", filename)) as file_handle:
  88. serialized = file_handle.read()
  89. return serialized
  90. class DefinitionContainerSubClass(DefinitionContainer):
  91. def __init__(self):
  92. super().__init__(container_id = "SubDefinitionContainer")
  93. class InstanceContainerSubClass(InstanceContainer):
  94. def __init__(self):
  95. super().__init__(container_id = "SubInstanceContainer")
  96. #############################START OF TEST CASES################################
  97. ## Tests whether adding a container is properly forbidden.
  98. def test_addContainer(global_stack):
  99. with pytest.raises(InvalidOperationError):
  100. global_stack.addContainer(unittest.mock.MagicMock())
  101. ## Tests adding extruders to the global stack.
  102. def test_addExtruder(global_stack):
  103. mock_definition = unittest.mock.MagicMock()
  104. mock_definition.getProperty = lambda key, property: 2 if key == "machine_extruder_count" and property == "value" else None
  105. with unittest.mock.patch("cura.Settings.CuraContainerStack.DefinitionContainer", unittest.mock.MagicMock):
  106. global_stack.definition = mock_definition
  107. assert len(global_stack.extruders) == 0
  108. first_extruder = unittest.mock.MagicMock()
  109. with unittest.mock.patch("cura.Settings.CuraContainerStack.DefinitionContainer", unittest.mock.MagicMock):
  110. global_stack.addExtruder(first_extruder)
  111. assert len(global_stack.extruders) == 1
  112. assert global_stack.extruders[0] == first_extruder
  113. second_extruder = unittest.mock.MagicMock()
  114. with unittest.mock.patch("cura.Settings.CuraContainerStack.DefinitionContainer", unittest.mock.MagicMock):
  115. global_stack.addExtruder(second_extruder)
  116. assert len(global_stack.extruders) == 2
  117. assert global_stack.extruders[1] == second_extruder
  118. with unittest.mock.patch("cura.Settings.CuraContainerStack.DefinitionContainer", unittest.mock.MagicMock):
  119. with pytest.raises(TooManyExtrudersError): #Should be limited to 2 extruders because of machine_extruder_count.
  120. global_stack.addExtruder(unittest.mock.MagicMock())
  121. assert len(global_stack.extruders) == 2 #Didn't add the faulty extruder.
  122. ## Tests whether the container types are properly enforced on the stack.
  123. #
  124. # When setting a field to have a different type of stack than intended, we
  125. # should get an exception.
  126. @pytest.mark.parametrize("definition_container, instance_container", [
  127. (DefinitionContainer(container_id = "TestDefinitionContainer"), InstanceContainer(container_id = "TestInstanceContainer")),
  128. (DefinitionContainerSubClass(), InstanceContainerSubClass())
  129. ])
  130. def test_constrainContainerTypes(definition_container, instance_container, global_stack):
  131. instance_container.addMetaDataEntry("type", "")
  132. with pytest.raises(InvalidContainerError): # Putting a definition container in the user changes is not allowed.
  133. global_stack.userChanges = definition_container
  134. with pytest.raises(InvalidContainerError):
  135. global_stack.userChanges = instance_container # Putting a random instance container in the user changes is not allowed.
  136. instance_container.setMetaDataEntry("type", "user") # After setting the metadata type entry correctly, we are allowed to set the container
  137. global_stack.userChanges = instance_container
  138. with pytest.raises(InvalidContainerError):
  139. global_stack.qualityChanges = definition_container
  140. with pytest.raises(InvalidContainerError):
  141. global_stack.qualityChanges = instance_container
  142. instance_container.setMetaDataEntry("type", "quality_changes")
  143. global_stack.qualityChanges = instance_container
  144. with pytest.raises(InvalidContainerError):
  145. global_stack.quality = definition_container
  146. with pytest.raises(InvalidContainerError):
  147. global_stack.quality = instance_container
  148. instance_container.setMetaDataEntry("type", "quality")
  149. global_stack.quality = instance_container
  150. with pytest.raises(InvalidContainerError):
  151. global_stack.material = definition_container
  152. with pytest.raises(InvalidContainerError):
  153. global_stack.material = instance_container
  154. instance_container.setMetaDataEntry("type", "material")
  155. global_stack.material = instance_container
  156. with pytest.raises(InvalidContainerError):
  157. global_stack.variant = definition_container
  158. with pytest.raises(InvalidContainerError):
  159. global_stack.variant = instance_container
  160. instance_container.setMetaDataEntry("type", "variant")
  161. global_stack.variant = instance_container
  162. with pytest.raises(InvalidContainerError):
  163. global_stack.definitionChanges = definition_container
  164. with pytest.raises(InvalidContainerError):
  165. global_stack.definitionChanges = instance_container
  166. instance_container.setMetaDataEntry("type", "definition_changes")
  167. global_stack.definitionChanges = instance_container
  168. with pytest.raises(InvalidContainerError): #Putting an instance container in the definition is not allowed.
  169. global_stack.definition = instance_container
  170. global_stack.definition = definition_container #Putting a definition container in the definition is allowed.
  171. ## Tests whether the user changes are being read properly from a global stack.
  172. @pytest.mark.parametrize("filename, user_changes_id", [
  173. ("Global.global.cfg", "empty"),
  174. ("Global.stack.cfg", "empty"),
  175. ("MachineLegacy.stack.cfg", "empty"),
  176. ("OnlyUser.global.cfg", "some_instance"), #This one does have a user profile.
  177. ("Complete.global.cfg", "some_user_changes")
  178. ])
  179. def test_deserializeUserChanges(filename, user_changes_id, container_registry, global_stack):
  180. serialized = readStack(filename)
  181. #Mock the loading of the instance containers.
  182. global_stack.findContainer = findSomeContainers
  183. original_container_registry = UM.Settings.ContainerStack._containerRegistry
  184. UM.Settings.ContainerStack._containerRegistry = container_registry #Always has all profiles you ask of.
  185. global_stack.deserialize(serialized)
  186. assert global_stack.userChanges.getId() == user_changes_id
  187. #Restore.
  188. UM.Settings.ContainerStack._containerRegistry = original_container_registry
  189. ## Tests whether the quality changes are being read properly from a global
  190. # stack.
  191. @pytest.mark.parametrize("filename, quality_changes_id", [
  192. ("Global.global.cfg", "empty"),
  193. ("Global.stack.cfg", "empty"),
  194. ("MachineLegacy.stack.cfg", "empty"),
  195. ("OnlyQualityChanges.global.cfg", "some_instance"),
  196. ("Complete.global.cfg", "some_quality_changes")
  197. ])
  198. def test_deserializeQualityChanges(filename, quality_changes_id, container_registry, global_stack):
  199. serialized = readStack(filename)
  200. #Mock the loading of the instance containers.
  201. global_stack.findContainer = findSomeContainers
  202. original_container_registry = UM.Settings.ContainerStack._containerRegistry
  203. UM.Settings.ContainerStack._containerRegistry = container_registry #Always has all the profiles you ask of.
  204. global_stack.deserialize(serialized)
  205. assert global_stack.qualityChanges.getId() == quality_changes_id
  206. #Restore.
  207. UM.Settings.ContainerStack._containerRegistry = original_container_registry
  208. ## Tests whether the quality profile is being read properly from a global
  209. # stack.
  210. @pytest.mark.parametrize("filename, quality_id", [
  211. ("Global.global.cfg", "empty"),
  212. ("Global.stack.cfg", "empty"),
  213. ("MachineLegacy.stack.cfg", "empty"),
  214. ("OnlyQuality.global.cfg", "some_instance"),
  215. ("Complete.global.cfg", "some_quality")
  216. ])
  217. def test_deserializeQuality(filename, quality_id, container_registry, global_stack):
  218. serialized = readStack(filename)
  219. #Mock the loading of the instance containers.
  220. global_stack.findContainer = findSomeContainers
  221. original_container_registry = UM.Settings.ContainerStack._containerRegistry
  222. UM.Settings.ContainerStack._containerRegistry = container_registry #Always has all the profiles you ask of.
  223. global_stack.deserialize(serialized)
  224. assert global_stack.quality.getId() == quality_id
  225. #Restore.
  226. UM.Settings.ContainerStack._containerRegistry = original_container_registry
  227. ## Tests whether the material profile is being read properly from a global
  228. # stack.
  229. @pytest.mark.parametrize("filename, material_id", [
  230. ("Global.global.cfg", "some_instance"),
  231. ("Global.stack.cfg", "some_instance"),
  232. ("MachineLegacy.stack.cfg", "some_instance"),
  233. ("OnlyDefinition.global.cfg", "empty"),
  234. ("OnlyMaterial.global.cfg", "some_instance"),
  235. ("Complete.global.cfg", "some_material")
  236. ])
  237. def test_deserializeMaterial(filename, material_id, container_registry, global_stack):
  238. serialized = readStack(filename)
  239. #Mock the loading of the instance containers.
  240. global_stack.findContainer = findSomeContainers
  241. original_container_registry = UM.Settings.ContainerStack._containerRegistry
  242. UM.Settings.ContainerStack._containerRegistry = container_registry #Always has all the profiles you ask of.
  243. global_stack.deserialize(serialized)
  244. assert global_stack.material.getId() == material_id
  245. #Restore.
  246. UM.Settings.ContainerStack._containerRegistry = original_container_registry
  247. ## Tests whether the variant profile is being read properly from a global
  248. # stack.
  249. @pytest.mark.parametrize("filename, variant_id", [
  250. ("Global.global.cfg", "empty"),
  251. ("Global.stack.cfg", "empty"),
  252. ("MachineLegacy.stack.cfg", "empty"),
  253. ("OnlyVariant.global.cfg", "some_instance"),
  254. ("Complete.global.cfg", "some_variant")
  255. ])
  256. def test_deserializeVariant(filename, variant_id, container_registry, global_stack):
  257. serialized = readStack(filename)
  258. #Mock the loading of the instance containers.
  259. global_stack.findContainer = findSomeContainers
  260. original_container_registry = UM.Settings.ContainerStack._containerRegistry
  261. UM.Settings.ContainerStack._containerRegistry = container_registry #Always has all the profiles you ask of.
  262. global_stack.deserialize(serialized)
  263. assert global_stack.variant.getId() == variant_id
  264. #Restore.
  265. UM.Settings.ContainerStack._containerRegistry = original_container_registry
  266. ## Tests whether the definition changes profile is being read properly from a
  267. # global stack.
  268. @pytest.mark.parametrize("filename, definition_changes_id", [
  269. ("Global.global.cfg", "empty"),
  270. ("Global.stack.cfg", "empty"),
  271. ("MachineLegacy.stack.cfg", "empty"),
  272. ("OnlyDefinitionChanges.global.cfg", "some_instance"),
  273. ("Complete.global.cfg", "some_material")
  274. ])
  275. def test_deserializeDefinitionChanges(filename, definition_changes_id, container_registry, global_stack):
  276. serialized = readStack(filename)
  277. global_stack = cura.Settings.GlobalStack.GlobalStack("TestStack")
  278. #Mock the loading of the instance containers.
  279. global_stack.findContainer = findSomeContainers
  280. original_container_registry = UM.Settings.ContainerStack._containerRegistry
  281. UM.Settings.ContainerStack._containerRegistry = container_registry #Always has all the profiles you ask of.
  282. global_stack.deserialize(serialized)
  283. assert global_stack.definitionChanges.getId() == definition_changes_id
  284. #Restore.
  285. UM.Settings.ContainerStack._containerRegistry = original_container_registry
  286. ## Tests whether the definition is being read properly from a global stack.
  287. @pytest.mark.parametrize("filename, definition_id", [
  288. ("Global.global.cfg", "some_definition"),
  289. ("Global.stack.cfg", "some_definition"),
  290. ("MachineLegacy.stack.cfg", "some_definition"),
  291. ("OnlyDefinition.global.cfg", "some_definition"),
  292. ("Complete.global.cfg", "some_definition")
  293. ])
  294. def test_deserializeDefinition(filename, definition_id, container_registry, global_stack):
  295. serialized = readStack(filename)
  296. #Mock the loading of the instance containers.
  297. global_stack.findContainer = findSomeContainers
  298. original_container_registry = UM.Settings.ContainerStack._containerRegistry
  299. UM.Settings.ContainerStack._containerRegistry = container_registry #Always has all the profiles you ask of.
  300. global_stack.deserialize(serialized)
  301. assert global_stack.definition.getId() == definition_id
  302. #Restore.
  303. UM.Settings.ContainerStack._containerRegistry = original_container_registry
  304. ## Tests that when a global stack is loaded with an unknown instance, it raises
  305. # an exception.
  306. def test_deserializeMissingContainer(global_stack):
  307. serialized = readStack("Global.global.cfg")
  308. with pytest.raises(Exception):
  309. global_stack.deserialize(serialized)
  310. try:
  311. global_stack.deserialize(serialized)
  312. except Exception as e:
  313. #Must be exactly Exception, not one of its subclasses, since that is what gets raised when a stack has an unknown container.
  314. #That's why we can't use pytest.raises.
  315. assert type(e) == Exception
  316. ## Tests whether getProperty properly applies the stack-like behaviour on its
  317. # containers.
  318. def test_getPropertyFallThrough(global_stack):
  319. #A few instance container mocks to put in the stack.
  320. mock_layer_heights = {} #For each container type, a mock container that defines layer height to something unique.
  321. mock_no_settings = {} #For each container type, a mock container that has no settings at all.
  322. for type_id, type_name in cura.Settings.CuraContainerStack._ContainerIndexes.IndexTypeMap.items():
  323. container = unittest.mock.MagicMock()
  324. container.getProperty = lambda key, property, type_id = type_id: type_id if (key == "layer_height" and property == "value") else None #Returns the container type ID as layer height, in order to identify it.
  325. container.hasProperty = lambda key, property: key == "layer_height"
  326. container.getMetaDataEntry = unittest.mock.MagicMock(return_value = type_name)
  327. mock_layer_heights[type_id] = container
  328. container = unittest.mock.MagicMock()
  329. container.getProperty = unittest.mock.MagicMock(return_value = None) #Has no settings at all.
  330. container.hasProperty = unittest.mock.MagicMock(return_value = False)
  331. container.getMetaDataEntry = unittest.mock.MagicMock(return_value = type_name)
  332. mock_no_settings[type_id] = container
  333. global_stack.userChanges = mock_no_settings[cura.Settings.CuraContainerStack._ContainerIndexes.UserChanges]
  334. global_stack.qualityChanges = mock_no_settings[cura.Settings.CuraContainerStack._ContainerIndexes.QualityChanges]
  335. global_stack.quality = mock_no_settings[cura.Settings.CuraContainerStack._ContainerIndexes.Quality]
  336. global_stack.material = mock_no_settings[cura.Settings.CuraContainerStack._ContainerIndexes.Material]
  337. global_stack.variant = mock_no_settings[cura.Settings.CuraContainerStack._ContainerIndexes.Variant]
  338. global_stack.definitionChanges = mock_no_settings[cura.Settings.CuraContainerStack._ContainerIndexes.DefinitionChanges]
  339. with unittest.mock.patch("cura.Settings.CuraContainerStack.DefinitionContainer", unittest.mock.MagicMock): #To guard against the type checking.
  340. global_stack.definition = mock_layer_heights[cura.Settings.CuraContainerStack._ContainerIndexes.Definition] #There's a layer height in here!
  341. assert global_stack.getProperty("layer_height", "value") == cura.Settings.CuraContainerStack._ContainerIndexes.Definition
  342. global_stack.definitionChanges = mock_layer_heights[cura.Settings.CuraContainerStack._ContainerIndexes.DefinitionChanges]
  343. assert global_stack.getProperty("layer_height", "value") == cura.Settings.CuraContainerStack._ContainerIndexes.DefinitionChanges
  344. global_stack.variant = mock_layer_heights[cura.Settings.CuraContainerStack._ContainerIndexes.Variant]
  345. assert global_stack.getProperty("layer_height", "value") == cura.Settings.CuraContainerStack._ContainerIndexes.Variant
  346. global_stack.material = mock_layer_heights[cura.Settings.CuraContainerStack._ContainerIndexes.Material]
  347. assert global_stack.getProperty("layer_height", "value") == cura.Settings.CuraContainerStack._ContainerIndexes.Material
  348. global_stack.quality = mock_layer_heights[cura.Settings.CuraContainerStack._ContainerIndexes.Quality]
  349. assert global_stack.getProperty("layer_height", "value") == cura.Settings.CuraContainerStack._ContainerIndexes.Quality
  350. global_stack.qualityChanges = mock_layer_heights[cura.Settings.CuraContainerStack._ContainerIndexes.QualityChanges]
  351. assert global_stack.getProperty("layer_height", "value") == cura.Settings.CuraContainerStack._ContainerIndexes.QualityChanges
  352. global_stack.userChanges = mock_layer_heights[cura.Settings.CuraContainerStack._ContainerIndexes.UserChanges]
  353. assert global_stack.getProperty("layer_height", "value") == cura.Settings.CuraContainerStack._ContainerIndexes.UserChanges
  354. def test_getPropertyWithResolve(global_stack):
  355. #Define some containers for the stack.
  356. resolve = unittest.mock.MagicMock() #Sets just the resolve for bed temperature.
  357. resolve.getProperty = lambda key, property: 15 if (key == "material_bed_temperature" and property == "resolve") else None
  358. resolve_and_value = unittest.mock.MagicMock() #Sets the resolve and value for bed temperature.
  359. resolve_and_value.getProperty = lambda key, property: (7.5 if property == "resolve" else 5) if (key == "material_bed_temperature") else None #7.5 resolve, 5 value.
  360. value = unittest.mock.MagicMock() #Sets just the value for bed temperature.
  361. value.getProperty = lambda key, property: 10 if (key == "material_bed_temperature" and property == "value") else None
  362. empty = unittest.mock.MagicMock() #Sets no value or resolve.
  363. empty.getProperty = unittest.mock.MagicMock(return_value = None)
  364. global_stack.definition = resolve_and_value
  365. assert global_stack.getProperty("material_bed_temperature", "value") == 7.5 #Resolve wins in the definition.
  366. global_stack.userChanges = resolve_and_value
  367. assert global_stack.getProperty("material_bed_temperature", "value") == 5 #Value wins in other places.
  368. global_stack.userChanges = value
  369. assert global_stack.getProperty("material_bed_temperature", "value") == 10 #Resolve in the definition doesn't influence the value in the user changes.
  370. global_stack.userChanges = resolve
  371. assert global_stack.getProperty("material_bed_temperature", "value") == 15 #Falls through to definition for lack of values, but then asks the start of the stack for the resolve.
  372. global_stack.userChanges = empty
  373. global_stack.qualityChanges = resolve_and_value
  374. assert global_stack.getProperty("material_bed_temperature", "value") == 5 #Value still wins in lower places, except definition.
  375. global_stack.qualityChanges = empty
  376. global_stack.quality = resolve_and_value
  377. assert global_stack.getProperty("material_bed_temperature", "value") == 5
  378. global_stack.quality = empty
  379. global_stack.material = resolve_and_value
  380. assert global_stack.getProperty("material_bed_temperature", "value") == 5
  381. global_stack.material = empty
  382. global_stack.variant = resolve_and_value
  383. assert global_stack.getProperty("material_bed_temperature", "value") == 5
  384. global_stack.variant = empty
  385. global_stack.definitionChanges = resolve_and_value
  386. assert global_stack.getProperty("material_bed_temperature", "value") == 5
  387. ## Tests whether the hasUserValue returns true for settings that are changed in
  388. # the user-changes container.
  389. def test_hasUserValueUserChanges(global_stack):
  390. user_changes = MockContainer("test_user_changes", "user")
  391. def hasProperty(key, property):
  392. return key == "layer_height" and property == "value" # Only have the layer_height property set.
  393. user_changes.hasProperty = hasProperty
  394. global_stack.userChanges = user_changes
  395. assert not global_stack.hasUserValue("infill_sparse_density")
  396. assert global_stack.hasUserValue("layer_height")
  397. assert not global_stack.hasUserValue("")
  398. ## Tests whether the hasUserValue returns true for settings that are changed in
  399. # the quality-changes container.
  400. def test_hasUserValueQualityChanges(global_stack):
  401. quality_changes = MockContainer("test_quality_changes", "quality_changes")
  402. def hasProperty(key, property):
  403. return key == "layer_height" and property == "value" # Only have the layer_height property set.
  404. quality_changes.hasProperty = hasProperty
  405. global_stack.qualityChanges = quality_changes
  406. assert not global_stack.hasUserValue("infill_sparse_density")
  407. assert global_stack.hasUserValue("layer_height")
  408. assert not global_stack.hasUserValue("")
  409. ## Tests whether inserting a container is properly forbidden.
  410. def test_insertContainer(global_stack):
  411. with pytest.raises(InvalidOperationError):
  412. global_stack.insertContainer(0, unittest.mock.MagicMock())
  413. ## Tests whether removing a container is properly forbidden.
  414. def test_removeContainer(global_stack):
  415. with pytest.raises(InvalidOperationError):
  416. global_stack.removeContainer(unittest.mock.MagicMock())
  417. ## Tests setting definitions by specifying an ID of a definition that exists.
  418. def test_setDefinitionByIdExists(global_stack, container_registry):
  419. global_stack.setDefinitionById("some_definition") #The container registry always has a container with the ID.
  420. ## Tests setting definitions by specifying an ID of a definition that doesn't
  421. # exist.
  422. def test_setDefinitionByIdDoesntExist(global_stack):
  423. with pytest.raises(InvalidContainerError):
  424. global_stack.setDefinitionById("some_definition") #Container registry is empty now.
  425. ## Tests setting definition changes by specifying an ID of a container that
  426. # exists.
  427. def test_setDefinitionChangesByIdExists(global_stack, container_registry):
  428. container_registry.typeMetaData = "definition_changes"
  429. global_stack.setDefinitionChangesById("some_definition_changes") #The container registry always has a container with the ID.
  430. ## Tests setting definition changes by specifying an ID of a container that
  431. # doesn't exist.
  432. def test_setDefinitionChangesByIdDoesntExist(global_stack):
  433. with pytest.raises(InvalidContainerError):
  434. global_stack.setDefinitionChangesById("some_definition_changes") #Container registry is empty now.
  435. ## Tests setting materials by specifying an ID of a material that exists.
  436. def test_setMaterialByIdExists(global_stack, container_registry):
  437. container_registry.typeMetaData = "material"
  438. global_stack.setMaterialById("some_material") #The container registry always has a container with the ID.
  439. ## Tests setting materials by specifying an ID of a material that doesn't
  440. # exist.
  441. def test_setMaterialByIdDoesntExist(global_stack):
  442. with pytest.raises(InvalidContainerError):
  443. global_stack.setMaterialById("some_material") #Container registry is empty now.
  444. ## Tests whether changing the next stack is properly forbidden.
  445. def test_setNextStack(global_stack):
  446. with pytest.raises(InvalidOperationError):
  447. global_stack.setNextStack(unittest.mock.MagicMock())
  448. ## Tests setting properties directly on the global stack.
  449. @pytest.mark.parametrize("key, property, value, output_value", [
  450. ("layer_height", "value", 0.1337, 0.1337),
  451. ("foo", "value", 100, 100),
  452. ("support_enabled", "value", True, True),
  453. ("layer_height", "default_value", 0.1337, 0.1337),
  454. ("layer_height", "is_bright_pink", "of course", "of course")
  455. ])
  456. def test_setPropertyUser(key, property, value, output_value, writable_global_stack):
  457. writable_global_stack.setProperty(key, property, value)
  458. assert writable_global_stack.userChanges.getProperty(key, property) == output_value
  459. ## Tests setting properties on specific containers on the global stack.
  460. @pytest.mark.parametrize("target_container", [
  461. "user",
  462. "quality_changes",
  463. "quality",
  464. "material",
  465. "variant",
  466. "definition_changes",
  467. ])
  468. def test_setPropertyOtherContainers(target_container, writable_global_stack):
  469. #Other parameters that don't need to be varied.
  470. key = "layer_height"
  471. property = "value"
  472. value = 0.1337
  473. output_value = 0.1337
  474. writable_global_stack.setProperty(key, property, value, target_container = target_container)
  475. containers = {
  476. "user": writable_global_stack.userChanges,
  477. "quality_changes": writable_global_stack.qualityChanges,
  478. "quality": writable_global_stack.quality,
  479. "material": writable_global_stack.material,
  480. "variant": writable_global_stack.variant,
  481. "definition_changes": writable_global_stack.definitionChanges,
  482. "definition": writable_global_stack.definition
  483. }
  484. assert containers[target_container].getProperty(key, property) == output_value
  485. ## Tests setting qualities by specifying an ID of a quality that exists.
  486. def test_setQualityByIdExists(global_stack, container_registry):
  487. container_registry.typeMetaData = "quality"
  488. global_stack.setQualityById("some_quality") #The container registry always has a container with the ID.
  489. ## Tests setting qualities by specifying an ID of a quality that doesn't exist.
  490. def test_setQualityByIdDoesntExist(global_stack):
  491. with pytest.raises(InvalidContainerError):
  492. global_stack.setQualityById("some_quality") #Container registry is empty now.
  493. ## Tests setting quality changes by specifying an ID of a quality change that
  494. # exists.
  495. def test_setQualityChangesByIdExists(global_stack, container_registry):
  496. container_registry.typeMetaData = "quality_changes"
  497. global_stack.setQualityChangesById("some_quality_changes") #The container registry always has a container with the ID.
  498. ## Tests setting quality changes by specifying an ID of a quality change that
  499. # doesn't exist.
  500. def test_setQualityChangesByIdDoesntExist(global_stack):
  501. with pytest.raises(InvalidContainerError):
  502. global_stack.setQualityChangesById("some_quality_changes") #Container registry is empty now.
  503. ## Tests setting variants by specifying an ID of a variant that exists.
  504. def test_setVariantByIdExists(global_stack, container_registry):
  505. container_registry.typeMetaData = "variant"
  506. global_stack.setVariantById("some_variant") #The container registry always has a container with the ID.
  507. ## Tests setting variants by specifying an ID of a variant that doesn't exist.
  508. def test_setVariantByIdDoesntExist(global_stack):
  509. with pytest.raises(InvalidContainerError):
  510. global_stack.setVariantById("some_variant") #Container registry is empty now.