def test_join_a_joined_path(self):
        # p1 p1i1   p1i2
        # p2 p2i1 /
        # p3 p3i1 /
        # or
        # p2.join(p3)
        # p1.join(p2)
        p1i1 = m.Instruction()
        p1i2 = m.Instruction()
        p2i1 = m.Instruction()
        p3i1 = m.Instruction()

        path1 = m.Path()
        path1.append(p1i1)
        path2 = m.Path()
        path2.append(p2i1)
        path3 = m.Path()
        path3.append(p3i1)

        path2.join(path3)
        path1.join(path2)

        path1.append(p1i2)

        self.assertEqual(p1i2, next_instruction(p1i1))
        self.assertEqual(p1i2, next_instruction(p2i1))
        self.assertEqual(p1i2, next_instruction(p3i1))
    def test_join(self):
        # p1 p1i1   p1i2
        # p2 p2i1 /
        p1i1 = m.Instruction()
        p1i2 = m.Instruction()
        p2i1 = m.Instruction()

        path1 = m.Path()
        path1.append(p1i1)
        path2 = m.Path()
        path2.append(p2i1)

        path1.join(path2)

        path1.append(p1i2)

        self.assertEqual(p1i2, next_instruction(p1i1))
        self.assertEqual(p1i2, next_instruction(p2i1))
    def test_FalseBranchAppender(self):
        bi = m.BranchingInstruction()
        i1 = m.Instruction()

        path = m.Path()
        path.set_appender(m.FalseBranchAppender(path, bi))
        path.append(i1)

        self.assertEqual(i1, bi.instruction_on_no)
    def test_NewPathAppender(self):
        # append
        i1 = m.Instruction()
        i2 = m.Instruction()

        path = m.Path()
        path.append(i1)
        path.append(i2)

        self.assertEqual(i2, next_instruction(i1))
    def test_join_to_a_closed_path(self):
        # p1 RETURN   p1i2
        # p2 p2i1 /
        p2i1 = m.Instruction()
        p1i2 = m.Instruction()

        path1 = m.Path()
        path1.append(m.Return())
        path1.close()
        self.assertTrue(path1.is_closed)
        path2 = m.Path()
        path2.append(p2i1)

        path1.join(path2)
        self.assertFalse(path1.is_closed)

        path1.append(p1i2)

        self.assertEqual(p1i2, next_instruction(p2i1))
    def test_InstructionAppender(self):
        # append
        i0 = m.Instruction()
        i1 = m.Instruction()
        i2 = m.Instruction()

        path = m.Path(m.InstructionAppender(i0))
        path.append(i1)
        path.append(i2)

        self.assertEqual(i1, next_instruction(i0))
    def test_TrueBranchAppender_resets_appender(self):
        bi = m.BranchingInstruction()
        i1 = m.Instruction()
        i2 = m.Instruction()

        path = m.Path()
        path.set_appender(m.TrueBranchAppender(path, bi))
        path.append(i1)
        path.append(i2)

        self.assertEqual(i1, bi.instruction_on_yes)
        self.assertEqual(i2, next_instruction(i1))
    def test_FalseBranchAppender_does_not_touch_yes_path(self):
        sentinel = object()
        bi = m.BranchingInstruction()
        bi.instruction_on_yes = sentinel
        i1 = m.Instruction()
        i2 = m.Instruction()

        path = m.Path()
        path.set_appender(m.FalseBranchAppender(path, bi))
        path.append(i1)
        path.append(i2)

        self.assertEqual(sentinel, bi.instruction_on_yes)