MrDraw/tests/slicing/test_slicingmanager.py
Gina Häußge 8ff0096eb6 Fix & Docs: Plugins may only have one mixin implementation
Multiple mixins are allowed of course. Allowing multiple implementations lead to too many problems due to plugin names for referring to the APIs of SimpleApiPlugins or the assets of AssetPlugins.

 Hence __plugin_implementations__ has been deprecated in favor of __plugin_implementation__. The plugin subsystem will automatically copy the first implementation from __plugin_implementations__ to __plugin_implementation__ and log a deprecation warning.

 Adjusted documentation accordingly. Also added docs for helpers.
2015-03-30 16:50:06 +02:00

158 lines
5.4 KiB
Python

# coding=utf-8
from __future__ import absolute_import
__author__ = "Gina Häußge <osd@foosel.net>"
__license__ = 'GNU Affero General Public License http://www.gnu.org/licenses/agpl.html'
__copyright__ = "Copyright (C) 2014 The OctoPrint Project - Released under terms of the AGPLv3 License"
import unittest
import mock
import octoprint.slicing
class TestSlicingManager(unittest.TestCase):
def setUp(self):
self.addCleanup(self.cleanUp)
import tempfile
self.profile_path = tempfile.mkdtemp()
self.slicer_plugin = mock.MagicMock()
self.slicer_plugin.get_slicer_properties.return_value = dict(type="mock", name="Mock", same_device=True)
self.slicer_plugin.is_slicer_configured.return_value = True
# mock plugin manager
self.plugin_manager_patcher = mock.patch("octoprint.plugin.plugin_manager")
self.plugin_manager = self.plugin_manager_patcher.start()
self._mock_slicer_plugins(self.slicer_plugin)
# mock profile manager
self.printer_profile_manager = mock.MagicMock(spec=octoprint.printer.profile.PrinterProfileManager)
# mock settings
self.settings_patcher = mock.patch("octoprint.slicing.settings")
settings = self.settings_patcher.start()
self.settings = settings.return_value
self.slicing_manager = octoprint.slicing.SlicingManager(self.profile_path, self.printer_profile_manager)
self.slicing_manager.initialize()
def tearDown(self):
import shutil
shutil.rmtree(self.profile_path)
def cleanUp(self):
self.settings_patcher.stop()
self.plugin_manager_patcher.stop()
def _mock_slicer_plugins(self, *plugins):
def get_implementations(*types):
import octoprint.plugin
if octoprint.plugin.SlicerPlugin in types:
return plugins
return dict()
self.plugin_manager.return_value.get_implementations.side_effect = get_implementations
def test_registered_slicers(self):
self.assertEquals(["mock"], self.slicing_manager.registered_slicers)
def test_slicing_enabled(self):
self.assertTrue(self.slicing_manager.slicing_enabled)
def test_default_slicer(self):
def get(path):
if path == ["slicing", "defaultSlicer"]:
return "mock"
else:
return None
self.settings.get.side_effect = get
self.assertEquals("mock", self.slicing_manager.default_slicer)
def test_default_slicer_unknown(self):
def get(path):
if path == ["slicing", "defaultSlicer"]:
return "unknown"
else:
return None
self.settings.get.side_effect = get
self.assertIsNone(self.slicing_manager.default_slicer)
@mock.patch("threading.Thread")
@mock.patch("tempfile.NamedTemporaryFile")
@mock.patch("os.remove")
def test_slice(self, mocked_os_remove, mocked_tempfile, mocked_thread):
# mock temporary file
temp_file = mock.MagicMock()
temp_file.name = "tmp.file"
mocked_tempfile.return_value = temp_file
# mock retrieval of default profile
def get(path):
return dict()
self.settings.get.side_effect = get
default_profile = octoprint.slicing.SlicingProfile("mock", "default", dict(layer_height=0.2, fill_density=40))
self.slicer_plugin.get_slicer_default_profile.return_value = default_profile
# mock threading
class MockThread(object):
def __init__(self):
self.target = None
self.args = None
self.mock = None
def constructor(self, target=None, args=None):
self.target = target
self.args = args
self.mock = mock.MagicMock()
self.mock.start.side_effect = self.start
return self.mock
def start(self):
self.target(*self.args)
mock_thread = MockThread()
mocked_thread.side_effect = mock_thread.constructor
# mock slicing
self.slicer_plugin.do_slice.return_value = True, None
# mock printer profile manager
printer_profile = dict(_id="mock_printer", _name="Mock Printer Profile")
def get_printer_profile(printer_profile_id):
self.assertEquals("mock_printer", printer_profile_id)
return printer_profile
self.printer_profile_manager.get.side_effect = get_printer_profile
##~~ call tested method
slicer_name = "mock"
source_path = "prefix/source.file"
dest_path = "prefix/dest.file"
profile_name = "dummy_profile"
printer_profile_id = "mock_printer"
position = dict(x=10, y=20)
callback = mock.MagicMock()
callback_args = ("one", "two", "three")
callback_kwargs = dict(foo="bar")
overrides = dict(layer_height=0.5)
self.slicing_manager.slice(slicer_name, source_path, dest_path, profile_name, callback, printer_profile_id=printer_profile_id, position=position, callback_args=callback_args, callback_kwargs=callback_kwargs, overrides=overrides)
# assert that temporary profile was created properly
self.slicer_plugin.save_slicer_profile.assert_called_once_with("tmp.file", default_profile, overrides=overrides)
# assert that slicing thread was created properly
mocked_thread.assert_called_once_with(target=mock.ANY, args=(self.slicer_plugin, source_path, dest_path, profile_name, overrides, printer_profile, position, callback, callback_args, callback_kwargs))
self.assertTrue(mock_thread.mock.daemon)
mock_thread.mock.start.assert_called_once()
# assert that slicer was called correctly
self.slicer_plugin.do_slice.assert_called_once_with(source_path, printer_profile, machinecode_path=dest_path, profile_path="tmp.file", position=position, on_progress=None, on_progress_args=None, on_progress_kwargs=None)
# assert that temporary profile was deleted again
mocked_os_remove.assert_called_once_with("tmp.file")
# assert that callback was called property
callback.assert_called_once_with(*callback_args, **callback_kwargs)