def test_handleAtCommand_multipleHandlers_match(self):
        """Test handleAtCommand when multiple command handlers are defined and match."""
        mockLogger = mock.Mock()
        mockState = mock.Mock()
        mockCommInstance = mock.Mock()
        mockCommInstance.isStreaming.return_value = False

        mockEntry1 = mock.Mock()
        mockEntry1.action = ENABLE_EXCLUSION
        mockEntry1.matches.return_value = True

        mockEntry2 = mock.Mock()
        mockEntry2.action = ENABLE_EXCLUSION
        mockEntry2.matches.return_value = True

        mockState.atCommandActions = mock.Mock(
            wraps={"DefinedCommand": [mockEntry1, mockEntry2]})

        unit = GcodeHandlers(mockState, mockLogger)

        result = unit.handleAtCommand(mockCommInstance, "DefinedCommand",
                                      "params")

        mockState.atCommandActions.get.assert_called_with("DefinedCommand")
        mockEntry1.matches.assert_called_with("DefinedCommand", "params")
        mockEntry2.matches.assert_called_with("DefinedCommand", "params")
        self.assertEqual(mockState.enableExclusion.call_count, 2,
                         "enableExclusion should be called twice")
        mockState.disableExclusion.assert_not_called()
        mockCommInstance.sendCommand.assert_not_called()

        self.assertTrue(result, "The result should be True")
    def test_handleAtCommand_oneHandler_match_DISABLE_EXCLUSION(self):
        """Test handleAtCommand with one matching handler that disables exclusion."""
        mockLogger = mock.Mock()

        mockState = mock.Mock()
        mockState.disableExclusion.return_value = ["Command1", "Command2"]

        mockCommInstance = mock.Mock()
        mockCommInstance.isStreaming.return_value = False

        mockEntry = mock.Mock()
        mockEntry.action = DISABLE_EXCLUSION
        mockEntry.matches.return_value = True

        mockState.atCommandActions = mock.Mock(
            wraps={"DefinedCommand": [mockEntry]})

        unit = GcodeHandlers(mockState, mockLogger)

        result = unit.handleAtCommand(mockCommInstance, "DefinedCommand",
                                      "params")

        mockState.atCommandActions.get.assert_called_with("DefinedCommand")
        mockEntry.matches.assert_called_with("DefinedCommand", "params")
        mockState.enableExclusion.assert_not_called()
        mockState.disableExclusion.assert_called_once()
        mockCommInstance.sendCommand.assert_has_calls(
            [mock.call("Command1"),
             mock.call("Command2")])

        self.assertTrue(result, "The result should be True")
    def test_handleAtCommand_multipleHandlers_noParamMatch(self):
        """Test handleAtCommand when multiple command handlers defined, but no param matches."""
        mockLogger = mock.Mock()
        mockState = mock.Mock()
        mockCommInstance = mock.Mock()
        mockCommInstance.isStreaming.return_value = False

        mockEntry1 = mock.Mock()
        mockEntry1.matches.return_value = None

        mockEntry2 = mock.Mock()
        mockEntry2.matches.return_value = None

        mockState.atCommandActions = mock.Mock(
            wraps={"DefinedCommand": [mockEntry1, mockEntry2]})

        unit = GcodeHandlers(mockState, mockLogger)

        result = unit.handleAtCommand(mockCommInstance, "DefinedCommand",
                                      "params")

        mockState.atCommandActions.get.assert_called_with("DefinedCommand")
        mockEntry1.matches.assert_called_with("DefinedCommand", "params")
        mockEntry2.matches.assert_called_with("DefinedCommand", "params")
        mockState.enableExclusion.assert_not_called()
        mockState.disableExclusion.assert_not_called()
        mockCommInstance.sendCommand.assert_not_called()

        self.assertFalse(result, "The result should be False")
    def test_handleAtCommand_oneHandler_match_unsupported_action(self):
        """Test handleAtCommand with one matching handler that specifies an unsupported action."""
        mockLogger = mock.Mock()
        mockState = mock.Mock()
        mockCommInstance = mock.Mock()
        mockCommInstance.isStreaming.return_value = False
        mockEntry = mock.Mock()
        mockEntry.action = "unsupported"
        mockEntry.matches.return_value = True

        mockState.atCommandActions = mock.Mock(
            wraps={"DefinedCommand": [mockEntry]})

        unit = GcodeHandlers(mockState, mockLogger)

        result = unit.handleAtCommand(mockCommInstance, "DefinedCommand",
                                      "params")

        mockState.atCommandActions.get.assert_called_with("DefinedCommand")
        mockEntry.matches.assert_called_with("DefinedCommand", "params")
        mockState.enableExclusion.assert_not_called()
        mockState.disableExclusion.assert_not_called()
        mockCommInstance.sendCommand.assert_not_called()

        mockLogger.warn.assert_called()

        self.assertTrue(result, "The result should be True")
    def test_handleAtCommand_isSdStreaming(self):
        """Test handleAtCommand when the commInstance indicates SD streaming."""
        mockLogger = mock.Mock()
        mockState = mock.Mock()
        mockCommInstance = mock.Mock()
        mockCommInstance.isStreaming.return_value = True

        # Mock a matching entry, which should not be invoked
        mockEntry = mock.Mock()
        mockEntry.action = ENABLE_EXCLUSION
        mockEntry.matches.return_value = True
        mockState.atCommandActions = mock.Mock(
            wraps={"DefinedCommand": [mockEntry]})

        unit = GcodeHandlers(mockState, mockLogger)

        result = unit.handleAtCommand(mockCommInstance, "DefinedCommand",
                                      "params")

        mockState.atCommandActions.get.assert_not_called()
        mockEntry.matches.assert_not_called()
        mockState.enableExclusion.assert_not_called()
        mockState.disableExclusion.assert_not_called()
        mockCommInstance.sendCommand.assert_not_called()

        self.assertFalse(result, "The result should be False")
    def test_computeArcCenterOffsets_zeroRadius(self):
        """Test the computeArcCenterOffsets method with a radius of zero."""
        mockLogger = mock.Mock()

        mockState = mock.Mock()
        mockState.position.X_AXIS.nativeToLogical.return_value = 0
        mockState.position.Y_AXIS.nativeToLogical.return_value = 0

        unit = GcodeHandlers(mockState, mockLogger)

        result = unit.computeArcCenterOffsets(10, 10, 0, True)

        self.assertEqual(result, (0, 0),
                         "No offset should be computed when the radius is 0")
    def test_computeArcCenterOffsets_counterClockwise_semicircle(self):
        """Test the computeArcCenterOffsets method with a CCW semicircular 100 unit arc."""
        arcRadius = 50

        mockLogger = mock.Mock()

        mockState = mock.Mock()
        mockState.position.X_AXIS.nativeToLogical.return_value = arcRadius
        mockState.position.Y_AXIS.nativeToLogical.return_value = 0

        unit = GcodeHandlers(mockState, mockLogger)

        result = unit.computeArcCenterOffsets(-arcRadius, 0, arcRadius, False)

        self.assertEqual(
            result, (-arcRadius, 0),
            "The computed center offset should be (%s, %s)" % (-arcRadius, 0))
    def test_computeArcCenterOffsets_circle(self):
        """Test the computeArcCenterOffsets method when the start and end points are identical."""
        arcRadius = 50
        mockLogger = mock.Mock()

        mockState = mock.Mock()
        mockState.position.X_AXIS.nativeToLogical.return_value = 0
        mockState.position.Y_AXIS.nativeToLogical.return_value = 0

        unit = GcodeHandlers(mockState, mockLogger)

        result = unit.computeArcCenterOffsets(0, 0, arcRadius, True)

        self.assertEqual(
            result, (0, 0),
            "No offset should be computed when the start and end points are the same"
        )
    def test_computeArcCenterOffsets_radiusTooSmall(self):
        """Test computeArcCenterOffsets when the radius is less than half the chord length."""
        mockLogger = mock.Mock()

        mockState = mock.Mock()
        mockState.position.X_AXIS.nativeToLogical.return_value = 0
        mockState.position.Y_AXIS.nativeToLogical.return_value = 0

        unit = GcodeHandlers(mockState, mockLogger)

        # Try chord length 10, radius 4
        result = unit.computeArcCenterOffsets(10, 0, 4, True)

        self.assertEqual(
            result, (0, 0),
            "No offset should be computed if the radius is less than half the chord length."
        )
    def test_handleAtCommand_noHandler(self):
        """Test handleAtCommand when no matching command handler is defined."""
        mockLogger = mock.Mock()
        mockState = mock.Mock()
        mockCommInstance = mock.Mock()
        mockCommInstance.isStreaming.return_value = False
        mockEntry = mock.Mock()

        mockState.atCommandActions = mock.Mock(wraps={"NoMatch": [mockEntry]})

        unit = GcodeHandlers(mockState, mockLogger)

        result = unit.handleAtCommand(mockCommInstance, "NotDefined", "params")

        mockState.atCommandActions.get.assert_called_with("NotDefined")
        mockEntry.matches.assert_not_called()
        mockState.enableExclusion.assert_not_called()
        mockState.disableExclusion.assert_not_called()
        mockCommInstance.sendCommand.assert_not_called()

        self.assertFalse(result, "The result should be False")
    def test_planArc_counterClockwise_semicircle(self):
        """Tests the planArc method with a CCW semicircular 100 unit arc centered at (0,0)."""
        arcRadius = 50

        mockLogger = mock.Mock()

        mockState = mock.Mock()
        mockState.position.X_AXIS.nativeToLogical.return_value = -arcRadius
        mockState.position.Y_AXIS.nativeToLogical.return_value = 0

        unit = GcodeHandlers(mockState, mockLogger)

        result = unit.planArc(arcRadius, 0, arcRadius, 0, False)

        self._assert_planArc_commonResultProperties(start=(-arcRadius, 0),
                                                    end=(arcRadius, 0),
                                                    center=(0, 0),
                                                    radius=arcRadius,
                                                    items=result)

        # y value comparisons
        # - the y component of each point should be below or equal to the y axis
        # - the y component direction must change one time
        self._assert_planArc_axisProperties(
            coordinateOffset=1,
            initialValue=0,
            initialDirection=-1,
            expectedReversals=1,
            items=result,
            filterFunc=lambda x, y, direction, index: (self.assertTrue(
                y <= 0, "Each y coordinate should be on or below the Y axis" +
                ": pt=(%s, %s) index=%s" % (x, y, index))))

        # x value comparisons
        # - the x component of each point should increase for each point
        self._assert_planArc_axisProperties(coordinateOffset=0,
                                            initialValue=-arcRadius,
                                            initialDirection=1,
                                            expectedReversals=0,
                                            items=result)
示例#12
0
    def test_constructor(self):
        """Test the constructor when passed logger and state instances."""
        # pylint: disable=protected-access
        mockState = mock.Mock(name="state")
        mockLogger = mock.Mock(name="_logger")

        unit = GcodeHandlers(mockState, mockLogger)

        self.assertIsInstance(unit, GcodeHandlers)
        self.assertProperties(unit, GcodeHandlersTests.expectedProperties)
        self.assertIs(unit._logger, mockLogger,
                      "The logger should match the instance passed in")
        self.assertIs(unit.state, mockState,
                      "The state should match the instance passed in")
    def test_computeArcCenterOffsets_negativeRadius(self):
        """Test computeArcCenterOffsets method with a negative radius value."""
        # Tests an arc with a chord length of 8 (half-width of 4) and a height (from chord to
        # center point on arc) of 3

        arcRadius = -(4.0 + 1.0 / 6.0)

        mockLogger = mock.Mock()

        mockState = mock.Mock()
        mockState.position.X_AXIS.nativeToLogical.return_value = 0
        mockState.position.Y_AXIS.nativeToLogical.return_value = 0

        unit = GcodeHandlers(mockState, mockLogger)

        result = unit.computeArcCenterOffsets(8, 0, arcRadius, True)

        self.assertEqual(
            result[0], 4,
            "The returned I value should match the expected value")
        self.assertAlmostEqual(
            result[1],
            arcRadius + 3,  # Note addition here when radius is negative
            msg="The returned J value should match the expected value")
示例#14
0
    def test_constructor_missingLogger(self):
        """Test the constructor when passed a state, but no logger."""
        mockState = mock.Mock(name="state")

        with self.assertRaises(AssertionError):
            GcodeHandlers(mockState, None)
示例#15
0
    def test_constructor_missingState(self):
        """Test the constructor when passed a logger, but no state."""
        mockLogger = mock.Mock(name="_logger")

        with self.assertRaises(AssertionError):
            GcodeHandlers(None, mockLogger)
示例#16
0
 def _createInstance():
     return GcodeHandlers(mock.Mock(name="state"),
                          mock.Mock(name="_logger"))
    def test_planArc_counterClockwise_circle(self):
        """Tests the planArc method with a CCW circular 100 unit arc centered at (0,0)."""
        arcRadius = 50

        mockLogger = mock.Mock()

        mockState = mock.Mock()
        mockState.position.X_AXIS.nativeToLogical.return_value = -arcRadius
        mockState.position.Y_AXIS.nativeToLogical.return_value = 0

        unit = GcodeHandlers(mockState, mockLogger)

        result = unit.planArc(-arcRadius, 0, arcRadius, 0, False)

        self._assert_planArc_commonResultProperties(start=(-arcRadius, 0),
                                                    end=(-arcRadius, 0),
                                                    center=(0, 0),
                                                    radius=arcRadius,
                                                    items=result)

        # y value comparisons
        # - the y component of each point to the left of x axis should have a negative direction
        # - the y component of each point to the right of x axis should have a positive direction
        # - the y component direction must change two times
        ignoredY = {"first": False}

        def filter_y(x, y, direction, index):
            if (x < 0):
                self.assertEqual(
                    direction, -1,
                    "The y direction should be negative for points to the left of the x axis"
                    + ": pt=(%s, %s) index=%s" % (x, y, index))
            elif (ignoredY["first"]):
                self.assertEqual(
                    direction, 1,
                    "The y direction should be positive for points to the right of the x axis"
                    + ": pt=(%s, %s) index=%s" % (x, y, index))
            else:
                # Ignore the first one, since it _could_ have the opposite direction at the boundary
                ignoredY["first"] = True

        self._assert_planArc_axisProperties(coordinateOffset=1,
                                            initialValue=0,
                                            initialDirection=-1,
                                            expectedReversals=2,
                                            items=result,
                                            filterFunc=filter_y)

        # x value comparisons
        # - the x component of each point above the y axis should have a negative direction
        # - the x component of each point below the y axis should have a positive direction
        # - the x component direction must change one time
        ignoredX = {"first": False}

        def filter_x(x, y, direction, index):
            if (y < 0):
                self.assertEqual(
                    direction, 1,
                    "The x direction should be positive for points below the y axis"
                    + ": pt=(%s, %s) index=%s" % (x, y, index))
            elif (ignoredX["first"]):
                self.assertEqual(
                    direction, -1,
                    "The x direction should be negative for points above the y axis"
                    + ": pt=(%s, %s) index=%s" % (x, y, index))
            else:
                # Ignore the first one, since it _could_ have the opposite direction at the boundary
                ignoredX["first"] = True

        self._assert_planArc_axisProperties(coordinateOffset=0,
                                            initialValue=-arcRadius,
                                            initialDirection=1,
                                            expectedReversals=1,
                                            items=result,
                                            filterFunc=filter_x)