예제 #1
0
    def test_random_move(self):
        """
        Test for the move node functionality.
        """

        print("=========================")

        # create tree randomly and recursively
        tree = ClosureTree()
        root_id = tree.add_node("root")
        self._generate_tree(tree, root_id, max_depth=2, branch_size=2)

        print("Stress test for moving nodes. Tree size: {}".format(tree.node_count()))

        # generate 2 random nodes from the children of the root node
        r = tree.get_descendants(root_id)
        r = [x.descendant for x in r]
        max_index = len(r) - 1

        moving_node_id = r[randint(0, max_index)]
        parent_node_id = r[randint(0, max_index)]

        while parent_node_id == moving_node_id:
            parent_node_id = r[randint(0, max_index)]

        print("Moving {} under {}.".format(moving_node_id, parent_node_id))

        # move the node to the new parent and time the execution
        t1_1 = self._timed_move(tree, moving_node_id, parent_node_id)

        # move the node back and time the execution
        t1_2 = self._timed_move(tree, moving_node_id, parent_node_id)

        print("Standard: moved node:\n\t-> {}\n\t<- {}".format(t1_1, t1_2))
예제 #2
0
    def setUp(self):
        """
        Create this structure:
        tree 1:
                  A
              /   |  \
             B    C   F
           /  \       |
          D   E       G

        tree 2:
          X
        """

        self.c_tree = ClosureTree()
        self.c_tree.add_node("A")
        self.c_tree.add_node("B", "A", True)
        self.c_tree.add_node("C", "A", True)
        self.c_tree.add_node("D", "B", True)
        self.c_tree.add_node("E", "B", True)
        self.c_tree.add_node("F", "A", True)
        self.c_tree.add_node("G", "F", True)
        self.c_tree.add_node("X")
        self.c_tree.add_node("Y", "X", True)
        self.c_tree.add_node("Z", "Y", True)
        self.c_tree.add_node("W", "X", True)
예제 #3
0
class ClosureTest(unittest.TestCase):
    def setUp(self):
        """
        Create this structure:
        tree 1:
                  A
              /   |  \
             B    C   F
           /  \       |
          D   E       G

        tree 2:
          X
        """

        self.c_tree = ClosureTree()
        self.c_tree.add_node("A")
        self.c_tree.add_node("B", "A", True)
        self.c_tree.add_node("C", "A", True)
        self.c_tree.add_node("D", "B", True)
        self.c_tree.add_node("E", "B", True)
        self.c_tree.add_node("F", "A", True)
        self.c_tree.add_node("G", "F", True)
        self.c_tree.add_node("X")
        self.c_tree.add_node("Y", "X", True)
        self.c_tree.add_node("Z", "Y", True)
        self.c_tree.add_node("W", "X", True)

    def test_print(self):
        """
        Just prints stuff.
        """

        self.c_tree.print_tables()

        self.c_tree.delete_node(self.c_tree.get_first_id("W"))
        print('Tree after deleting "W"')
        self.c_tree.view_tree()

        print("=========================")
        print("Move B under C.")
        self.c_tree.move_node(self.c_tree.get_first_id("B"), self.c_tree.get_first_id("C"))
        self.c_tree.view_tree()

        print("Path for D:")
        self.c_tree.print_path(self.c_tree.get_first_id("Y"))

    def _generate_tree(self, tree, node_id=None, max_depth=5, depth=0, branch_size=5):

        """
        Create a random tree recursively.
        :param tree: the tree in which the nodes will be added.
        :param node_id: the root node under which all the nodes will be added
        :param max_depth: the maximum absolute depth that will be reached
        :param depth: the current depth
        :param branch_size: the maximum number of children that can be generated for any node
        """

        if not node_id:
            node_id = tree.add_node("root")

        if depth < max_depth:
            for _ in range(randint(2, branch_size)):
                node_pk = tree.add_node("x", node_id)
                self._generate_tree(tree, node_pk, max_depth, depth=depth + 1)

    def _timed_move(self, tree, node_id, parent_id):
        """
        Executes the move node functionality and returns the execution time.
        :param tree: the tree in which the operation will be performed.
        :param node_id: the id of the node that will be moved
        :param parent_id: the id of the new parent to which the node will be attached
        :return: the execution time
        """

        t = Timer(lambda: tree.move_node(node_id, parent_id))
        return t.timeit(1)

    def test_random_move(self):
        """
        Test for the move node functionality.
        """

        print("=========================")

        # create tree randomly and recursively
        tree = ClosureTree()
        root_id = tree.add_node("root")
        self._generate_tree(tree, root_id, max_depth=2, branch_size=2)

        print("Stress test for moving nodes. Tree size: {}".format(tree.node_count()))

        # generate 2 random nodes from the children of the root node
        r = tree.get_descendants(root_id)
        r = [x.descendant for x in r]
        max_index = len(r) - 1

        moving_node_id = r[randint(0, max_index)]
        parent_node_id = r[randint(0, max_index)]

        while parent_node_id == moving_node_id:
            parent_node_id = r[randint(0, max_index)]

        print("Moving {} under {}.".format(moving_node_id, parent_node_id))

        # move the node to the new parent and time the execution
        t1_1 = self._timed_move(tree, moving_node_id, parent_node_id)

        # move the node back and time the execution
        t1_2 = self._timed_move(tree, moving_node_id, parent_node_id)

        print("Standard: moved node:\n\t-> {}\n\t<- {}".format(t1_1, t1_2))