def test_free_triad(self):
        a = Allocator(2, 1, seconds_before_free=0.1)

        id0, _0, _1, _2 = a._alloc_triads(1, 1)
        id1, _0, _1, _2 = a._alloc_triads(1, 1)

        # The pack tree should be full
        assert a.pack_tree.allocated is False
        assert a.pack_tree.children is not None
        assert a.pack_tree.children[0].allocated is True
        assert a.pack_tree.children[1].allocated is True

        # Triad should be freed after timeout and allocation
        a.free(id1)
        assert a.pack_tree.allocated is False
        assert a.pack_tree.children is not None
        assert a.pack_tree.children[0].allocated is True
        assert a.pack_tree.children[1].allocated is True
        time.sleep(a.seconds_before_free)
        a.check_free()
        assert a.pack_tree.allocated is False
        assert a.pack_tree.children is not None
        assert a.pack_tree.children[0].allocated is True
        assert a.pack_tree.children[1].allocated is False

        # Full tree should be freed too
        a.free(id0)
        time.sleep(a.seconds_before_free)
        a.check_free()
        assert a.pack_tree.allocated is False
        assert a.pack_tree.children is None
    def test_free_board(self):
        a = Allocator(2,
                      1,
                      dead_boards=set([(0, 0, 1)]),
                      seconds_before_free=0.1)

        # Allocate the two boards on triad 0, 0
        id00, _1, _2, _3 = a._alloc_board(0, 0, 0)
        id02, _1, _2, _3 = a._alloc_board(0, 0, 2)

        # Allocate the three boards on triad 1, 0
        id10, _1, _2, _3 = a._alloc_board(1, 0, 0)
        id11, _1, _2, _3 = a._alloc_board(1, 0, 1)
        id12, _1, _2, _3 = a._alloc_board(1, 0, 2)

        # No board triads should be available
        assert len(a.single_board_triads) == 0
        assert a.full_single_board_triads == set([(0, 0), (1, 0)])

        # The pack tree should be full
        assert a.pack_tree.allocated is False
        assert a.pack_tree.children is not None
        assert a.pack_tree.children[0].allocated is True
        assert a.pack_tree.children[1].allocated is True

        # Freeing a board should bring it back into the single boards triads
        # dictionary, but only after timeout
        a.free(id00)
        assert len(a.single_board_triads) == 0
        assert a.full_single_board_triads == set([(0, 0), (1, 0)])
        assert a.pack_tree.allocated is False
        assert a.pack_tree.children is not None
        assert a.pack_tree.children[0].allocated is True
        assert a.pack_tree.children[1].allocated is True
        time.sleep(a.seconds_before_free)
        a.check_free()
        assert a.single_board_triads == {(0, 0): set([0])}
        assert a.full_single_board_triads == set([(1, 0)])

        # The pack tree should still be full
        assert a.pack_tree.allocated is False
        assert a.pack_tree.children is not None
        assert a.pack_tree.children[0].allocated is True
        assert a.pack_tree.children[1].allocated is True

        # Freeing the only other working board in a triad should remove the
        # triad entirely
        a.free(id02)
        assert a.single_board_triads == {(0, 0): set([0])}
        assert a.full_single_board_triads == set([(1, 0)])
        assert a.pack_tree.allocated is False
        assert a.pack_tree.children is not None
        assert a.pack_tree.children[0].allocated is True
        assert a.pack_tree.children[1].allocated is True
        time.sleep(a.seconds_before_free)
        a.check_free()
        assert a.single_board_triads == {}
        assert a.full_single_board_triads == set([(1, 0)])

        # ...and the corresponding part of the pack_tree should be free too
        assert a.pack_tree.allocated is False
        assert a.pack_tree.children is not None
        assert a.pack_tree.children[0].allocated is False
        assert a.pack_tree.children[1].allocated is True

        # Freeing should move into the single boards dictionary
        a.free(id10)
        assert a.single_board_triads == {}
        assert a.full_single_board_triads == set([(1, 0)])
        assert a.pack_tree.allocated is False
        assert a.pack_tree.children is not None
        assert a.pack_tree.children[0].allocated is False
        assert a.pack_tree.children[1].allocated is True
        time.sleep(a.seconds_before_free)
        a.check_free()
        assert a.single_board_triads == {(1, 0): set([0])}
        assert a.full_single_board_triads == set()

        # The pack_tree should be unchanged.
        assert a.pack_tree.allocated is False
        assert a.pack_tree.children is not None
        assert a.pack_tree.children[0].allocated is False
        assert a.pack_tree.children[1].allocated is True

        # Freeing another board in the same triad (but not the last) should
        # just update the dictionary.
        a.free(id11)
        assert a.single_board_triads == {(1, 0): set([0])}
        assert a.full_single_board_triads == set()
        assert a.pack_tree.allocated is False
        assert a.pack_tree.children is not None
        assert a.pack_tree.children[0].allocated is False
        assert a.pack_tree.children[1].allocated is True
        time.sleep(a.seconds_before_free)
        a.check_free()
        assert a.single_board_triads == {(1, 0): set([0, 1])}
        assert a.full_single_board_triads == set()

        # The pack_tree should be unchanged.
        assert a.pack_tree.allocated is False
        assert a.pack_tree.children is not None
        assert a.pack_tree.children[0].allocated is False
        assert a.pack_tree.children[1].allocated is True

        # Freeing the last board should remove it as before...
        a.free(id12)
        assert a.single_board_triads == {(1, 0): set([0, 1])}
        assert a.full_single_board_triads == set()
        assert a.pack_tree.allocated is False
        assert a.pack_tree.children is not None
        assert a.pack_tree.children[0].allocated is False
        assert a.pack_tree.children[1].allocated is True
        time.sleep(a.seconds_before_free)
        a.check_free()
        assert a.single_board_triads == {}
        assert a.full_single_board_triads == set()

        # The pack tree should now be empty
        assert a.pack_tree.allocated is False
        assert a.pack_tree.children is None