TestStartEndGCode.py 5.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310
  1. # Copyright (c) 2024 Ultimaker B.V.
  2. # Cura is released under the terms of the LGPLv3 or higher.
  3. import pytest
  4. from unittest.mock import MagicMock
  5. from plugins.CuraEngineBackend.StartSliceJob import GcodeStartEndFormatter
  6. # def createMockedInstanceContainer(container_id):
  7. # result = MagicMock()
  8. # result.getId = MagicMock(return_value=container_id)
  9. # result.getMetaDataEntry = MagicMock(side_effect=getMetadataEntrySideEffect)
  10. # return result
  11. class MockValueProvider:
  12. ## Creates a mock value provider.
  13. #
  14. # This initialises a dictionary with key-value pairs.
  15. def __init__(self, values):
  16. self._values = values
  17. ## Provides a value.
  18. #
  19. # \param name The key of the value to provide.
  20. def getProperty(self, key, property_name, context = None):
  21. if not (key in self._values):
  22. return None
  23. return self._values[key]
  24. extruder_0_values = {
  25. "material_temperature": 190.0
  26. }
  27. extruder_1_values = {
  28. "material_temperature": 210.0
  29. }
  30. global_values = {
  31. "bed_temperature": 50.0,
  32. "initial_extruder": 0
  33. }
  34. extruder_0_provider = MockValueProvider(extruder_0_values)
  35. extruder_1_provider = MockValueProvider(extruder_1_values)
  36. all_extruder_settings = {"-1": global_values, "0": extruder_0_values, "1": extruder_1_values}
  37. test_cases = [
  38. ('Static code', None, 'G0', 'G0'),
  39. ('Basic replacement', None, 'M128 {bed_temperature}', 'M128 50.0'),
  40. (
  41. 'Conditional expression with global setting',
  42. None,
  43. '''{if bed_temperature > 30}
  44. G123
  45. {else}
  46. G456
  47. {endif}''',
  48. '''G123
  49. '''
  50. ),
  51. (
  52. 'Conditional expression with extruder setting directly specified by index 0',
  53. None,
  54. '''{if material_temperature > 200, 0}
  55. G10
  56. {else}
  57. G20
  58. {endif}''',
  59. '''G20
  60. '''
  61. ),
  62. (
  63. 'Conditional expression with extruder setting directly specified by index 1',
  64. None,
  65. '''{if material_temperature > 200, 1}
  66. G100
  67. {else}
  68. G200
  69. {endif}''',
  70. '''G100
  71. '''
  72. ),
  73. (
  74. 'Conditional expression with extruder index specified by setting',
  75. None,
  76. '''{if material_temperature > 200, initial_extruder}
  77. G1000
  78. {else}
  79. G2000
  80. {endif}''',
  81. '''G2000
  82. '''
  83. ),
  84. (
  85. 'Conditional expression with extruder index specified by formula',
  86. None,
  87. '''{if material_temperature > 200, (initial_extruder + 1) % 2}
  88. X1000
  89. {else}
  90. X2000
  91. {endif}''',
  92. '''X1000
  93. '''
  94. ),
  95. (
  96. 'Conditional expression with elsif',
  97. None,
  98. '''{if bed_temperature < 30}
  99. T30
  100. {elif bed_temperature >= 30 and bed_temperature < 40}
  101. T40
  102. {elif bed_temperature >= 40 and bed_temperature < 50}
  103. T50
  104. {elif bed_temperature >= 50 and bed_temperature < 60}
  105. T60
  106. {elif bed_temperature >= 60 and bed_temperature < 70}
  107. T70
  108. {else}
  109. T-800
  110. {endif}''',
  111. '''T60
  112. '''
  113. ),
  114. (
  115. 'Formula inside a conditional expression',
  116. None,
  117. '''{if bed_temperature < 30}
  118. Z000
  119. {else}
  120. Z{bed_temperature + 10}
  121. {endif}''',
  122. '''Z60.0
  123. '''
  124. ),
  125. (
  126. 'Other commands around conditional expression',
  127. None,
  128. '''
  129. R000
  130. # My super initial command
  131. R111 X123 Y456 Z789
  132. {if bed_temperature > 30}
  133. R987
  134. R654 X321
  135. {else}
  136. R963 X852 Y741
  137. R321 X654 Y987
  138. {endif}
  139. # And finally, the end of the start at the beginning of the header
  140. R369
  141. R357 X951 Y843''',
  142. '''
  143. R000
  144. # My super initial command
  145. R111 X123 Y456 Z789
  146. R987
  147. R654 X321
  148. # And finally, the end of the start at the beginning of the header
  149. R369
  150. R357 X951 Y843'''
  151. ),
  152. (
  153. 'Multiple conditional expressions',
  154. None,
  155. '''
  156. A999
  157. {if bed_temperature > 30}
  158. A000
  159. {else}
  160. A100
  161. {endif}
  162. A888
  163. {if material_temperature > 200, 0}
  164. A200
  165. {else}
  166. A300
  167. {endif}
  168. A777
  169. ''',
  170. '''
  171. A999
  172. A000
  173. A888
  174. A300
  175. A777
  176. '''
  177. ),
  178. (
  179. 'Nested condition expression',
  180. SyntaxError,
  181. '''{if bed_temperature < 30}
  182. {if material_temperature < 30, 0}
  183. M000
  184. {else}
  185. M888
  186. {endif}
  187. {else}
  188. M{bed_temperature + 10}
  189. {endif}''',
  190. ''
  191. ),
  192. (
  193. 'Wrong condition expression',
  194. SyntaxError,
  195. '''{of material_temperature > 200, 1}
  196. G100
  197. {else}
  198. G200
  199. {endif}''',
  200. ''
  201. ),
  202. (
  203. 'Condition expression without start',
  204. SyntaxError,
  205. '''
  206. W100
  207. {else}
  208. W200
  209. {endif}''',
  210. ''
  211. ),
  212. (
  213. 'Formula with non-existing variable',
  214. None,
  215. '{material_storage_temperature}',
  216. '0'
  217. ),
  218. (
  219. 'Missing formula end character',
  220. None,
  221. '{material_temperature, 0',
  222. '{material_temperature, 0'
  223. ),
  224. (
  225. 'Conditional expression with missing end character',
  226. SyntaxError,
  227. '''{if material_temperature > 200, 0
  228. Q1000
  229. {else}
  230. Q2000
  231. {endif}''',
  232. ''
  233. ),
  234. (
  235. 'Unexpected end character',
  236. None,
  237. '''{if material_temperature > 200, 0}}
  238. S1000
  239. {else}
  240. S2000
  241. {endif}''',
  242. '''S2000
  243. '''
  244. ),
  245. ]
  246. def pytest_generate_tests(metafunc):
  247. if "original_gcode" in metafunc.fixturenames:
  248. tests_ids = [test[0] for test in test_cases]
  249. tests_data = [test[1:] for test in test_cases]
  250. metafunc.parametrize("exception_type, original_gcode, expected_gcode", tests_data, ids = tests_ids)
  251. @pytest.fixture
  252. def cura_application():
  253. result = MagicMock()
  254. result.getGlobalContainerStack = MagicMock(return_value = MockValueProvider(global_values))
  255. return result
  256. @pytest.fixture
  257. def extruder_manager():
  258. def get_extruder(extruder_nr: str):
  259. if extruder_nr == "0":
  260. return extruder_0_provider
  261. elif extruder_nr == "1":
  262. return extruder_1_provider
  263. else:
  264. return None
  265. result = MagicMock()
  266. result.getExtruderStack = MagicMock(side_effect = get_extruder)
  267. return result
  268. def test_startEndGCode_replace(cura_application, extruder_manager, exception_type, original_gcode, expected_gcode):
  269. formatter = GcodeStartEndFormatter(all_extruder_settings, -1)
  270. formatter._cura_application = cura_application
  271. formatter._extruder_manager = extruder_manager
  272. if exception_type is not None:
  273. with pytest.raises(exception_type):
  274. formatter.format(original_gcode)
  275. else:
  276. assert formatter.format(original_gcode) == expected_gcode