Example #1
0
def test():
    '''Test tutorial-1.'''
    life_board_pattern = re.compile('^(([ #]{45}\n){24})([ #]{45})$')
    import garlicsim
    from garlicsim_lib.simpacks import life
    state = life.State.create_messy_root()
    assert life_board_pattern.match(repr(state))
    assert repr(type(state)) == \
        "<class 'garlicsim_lib.simpacks.life.state.State'>"
    new_state = garlicsim.simulate(state)
    assert life_board_pattern.match(repr(new_state))
    new_state = garlicsim.simulate(state, 20)
    assert life_board_pattern.match(repr(new_state))
    result = garlicsim.list_simulate(state, 20)
    assert repr(type(result)) == "<type 'list'>"
    assert len(result) == 21
    assert life_board_pattern.match(repr(result[0]))
    assert result[0] == state
    assert life_board_pattern.match(repr(result[-1]))
    assert life_board_pattern.match(repr(result[7]))
    repr(garlicsim.iter_simulate(state, 5)) # Not testing cause of pypy et al.
    assert (list(garlicsim.iter_simulate(state, 5)) == \
            garlicsim.list_simulate(state, 5))
    
    project = garlicsim.Project(life)
    state = life.State.create_diehard()
    assert life_board_pattern.match(repr(state))
    assert repr(state).count('#') == 7
    root = project.root_this_state(state)
    assert repr(root) == \
        ('<garlicsim.data_structures.Node with clock 0, '
         'root, leaf, touched, blockless, at %s>' % hex(id(root)))
    project.begin_crunching(root, 50)
    _result = project.sync_crunchers()
    assert repr(_result) == '<0 nodes were added to the tree>'
    (cruncher,) = project.crunching_manager.crunchers.values()
    while cruncher.is_alive():
        time.sleep(0.1)
    _result = project.sync_crunchers()
    assert repr(_result) == '<50 nodes were added to the tree>'
    assert repr(project.tree) == (
        '<garlicsim.data_structures.Tree with 1 roots, '
        '51 nodes and 1 possible paths at %s>' % hex(id(project.tree))
    )
    (path,) = project.tree.all_possible_paths()
    assert repr(path) == (
        '<garlicsim.data_structures.Path of length 51 '
        'at %s>' % hex(id(path))
    )    
    assert repr(path[-1]) == (
        '<garlicsim.data_structures.Node with clock 50, leaf, untouched, '
        'blockful, crunched with life.State.step_generator(<state>), at '
        '%s>' % hex(id(path[-1])))
    _state = path[-1].state
    assert repr(_state).count('#') == 24
    assert life_board_pattern.match(repr(_state))
    node = path[27]
    assert repr(node.state).count('#') == 20
    assert life_board_pattern.match(repr(node.state))
    new_node = project.fork_to_edit(node)
    new_node.state.board.set(28, 13, True)
    assert repr(new_node.state).count('#') == 21
    assert life_board_pattern.match(repr(new_node.state))
    new_node.finalize()
    assert repr(project.tree) == (
        '<garlicsim.data_structures.Tree with 1 roots, '
        '52 nodes and 2 possible paths at %s>' % hex(id(project.tree))
    )
    project.ensure_buffer(root, 50)
    _result = project.sync_crunchers()
    assert repr(_result) == '<0 nodes were added to the tree>'
    (cruncher,) = project.crunching_manager.crunchers.values()
    while cruncher.is_alive():
        time.sleep(0.1)
    _result = project.sync_crunchers()
    assert repr(_result) == '<23 nodes were added to the tree>'
    new_path = new_node.make_containing_path()
    assert repr(new_path[-1].state).count('#') == 49
    assert life_board_pattern.match(repr(new_path[-1].state))
Example #2
0
def check(simpack, cruncher_type):
    
    my_simpack_grokker = garlicsim.misc.SimpackGrokker(simpack)
    
    assert my_simpack_grokker is garlicsim.misc.SimpackGrokker(simpack)
    # Ensuring caching works.
    
    assert not simpack._test_settings.ENDABLE
    
    assert garlicsim.misc.simpack_grokker.step_type.StepType.get_step_type(
        my_simpack_grokker.default_step_function
    ) == simpack._test_settings.DEFAULT_STEP_FUNCTION_TYPE
    
    step_profile = my_simpack_grokker.build_step_profile()
    deterministic = \
        my_simpack_grokker.settings.DETERMINISM_FUNCTION(step_profile)
    
    
    state = simpack.State.create_root()
    
    
    prev_state = state
    for i in [1, 2, 3, 4]:
        new_state = garlicsim.simulate(state, i)
        assert new_state.clock >= getattr(prev_state, 'clock', 0)
        prev_state = new_state
    
    result = garlicsim.list_simulate(state, 4)
    for item in result:
        assert isinstance(item, garlicsim.data_structures.State)
        assert isinstance(item, simpack.State)
    
    assert isinstance(result, list)
    assert len(result) == 5
        
    
    iter_result = garlicsim.iter_simulate(state, 4)
        
    assert not hasattr(iter_result, '__getitem__')
    assert hasattr(iter_result, '__iter__')
    iter_result_in_list = list(iter_result)
    del iter_result
    assert len(iter_result_in_list) == len(result) == 5

    
    ### Setting up a project to run asynchronous tests:
    
    project = garlicsim.Project(simpack)
        
    project.crunching_manager.cruncher_type = cruncher_type
    
    assert project.tree.lock._ReadWriteLock__writer is None
    
    root = project.root_this_state(state)
    
    
    project.begin_crunching(root, 4)

    total_nodes_added = 0    
    while project.crunching_manager.jobs:
        time.sleep(0.1)
        total_nodes_added += project.sync_crunchers()
        
    assert total_nodes_added == 4
    
    assert len(project.tree.nodes) == 5
    assert len(project.tree.roots) == 1
    
    paths = project.tree.all_possible_paths()
    
    assert len(paths) == 1
    
    (my_path,) = paths
        
    assert len(my_path) == 5
    
    node_1 = my_path[1]
    assert node_1.state.clock == 1
    
    node_2 = project.simulate(node_1, 3)
    
    assert len(project.tree.nodes) == 8
    assert len(project.tree.roots) == 1
    
    assert len(project.tree.all_possible_paths()) == 2

    block_1, block_2 = [node.block for node in node_1.children]
    assert isinstance(block_1, garlicsim.data_structures.Block)
    assert isinstance(block_2, garlicsim.data_structures.Block)
    assert block_1.soft_get_block() is block_1
    assert block_2.soft_get_block() is block_2
    assert block_1.is_overlapping(block_1)
    assert block_2.is_overlapping(block_2)
    assert not block_1.is_overlapping(block_2)
    assert not block_2.is_overlapping(block_1)
    block_path_1 = block_1.make_containing_path()
    block_path_2 = block_2.make_containing_path()
    assert block_path_1 == block_path_1
    assert block_path_1 != block_path_2
    assert (block_1[0] in block_path_1) and (block_1[-1] in block_path_1)
    assert (block_2[0] in block_path_2) and (block_2[-1] in block_path_2)
    assert block_1.get_root() is block_2.get_root()
    
        
 
    tree_members_iterator = \
        project.tree.iterate_tree_members(include_blockful_nodes=False)
    assert tree_members_iterator.__iter__() is tree_members_iterator
    tree_members = list(tree_members_iterator)
    assert (block_1 in tree_members) and (block_2 in tree_members)
    for tree_member in tree_members:
        if isinstance(tree_member, garlicsim.data_structures.Node):
            assert tree_member.block is None
    
    tree_members_iterator_including_blockful_nodes = \
        project.tree.iterate_tree_members(include_blockful_nodes=True)
    assert tree_members_iterator_including_blockful_nodes.__iter__() is \
        tree_members_iterator_including_blockful_nodes
    tree_members_including_blockful_nodes = \
        list(tree_members_iterator_including_blockful_nodes)
    
    blockful_nodes = \
        [member for member in tree_members_including_blockful_nodes if 
         member not in tree_members]
    for blockful_node in blockful_nodes:
        assert isinstance(blockful_node, garlicsim.data_structures.Node)
        assert isinstance(blockful_node.block, garlicsim.data_structures.Block)
        assert blockful_node.block is blockful_node.soft_get_block()
    assert set(tree_members).\
        issubset(set(tree_members_including_blockful_nodes))
    
    tree_step_profiles = project.tree.get_step_profiles()
    assert isinstance(tree_step_profiles, OrderedSet)
    assert tree_step_profiles == [step_profile]
    
Example #3
0
def simpack_check(simpack, cruncher):
    
    my_simpack_grokker = garlicsim.misc.SimpackGrokker(simpack)
    
    state = simpack.State.create_messy_root() if \
          simpack.State.create_messy_root else \
          simpack.State.create_root()
    
    new_state = garlicsim.simulate(state, 5)
    
    result = garlicsim.list_simulate(state, 5)
    
    iter_result = garlicsim.iter_simulate(state, 5)
    
    
    assert not hasattr(iter_result, '__getitem__')
    assert hasattr(iter_result, '__iter__')
    iter_result_in_list = list(iter_result)
    del iter_result
    assert len(iter_result_in_list) == len(result) == 6
    if _is_deterministic(simpack):
        assert iter_result_in_list == result
    
    
    empty_step_profile = garlicsim.misc.StepProfile()
    
    assert len(result) == 6
    
    for item in result:
        assert isinstance(item, garlicsim.data_structures.State)
        if hasattr(simpack, 'State'): # Later make mandatory
            assert isinstance(item, simpack.State)
    
    if _is_deterministic(simpack):
        
        assert result[-1] == new_state
        
        for old, new in cute_iter_tools.consecutive_pairs(result):
            assert new == my_simpack_grokker.step(old, empty_step_profile)
    
    project = garlicsim.Project(simpack)
    
    project.crunching_manager.Cruncher = cruncher
    
    assert project.tree.lock._ReadWriteLock__writer is None
    
    root = project.root_this_state(state)
    
    project.begin_crunching(root, 20)

    total_nodes_added = 0    
    while project.crunching_manager.jobs:
        time.sleep(0.1)
        total_nodes_added += project.sync_crunchers()
        
    x = total_nodes_added
    assert len(project.tree.nodes) == x + 1
    assert len(project.tree.roots) == 1
    
    paths = project.tree.all_possible_paths()
    
    assert len(paths) == 1
    
    (my_path,) = paths
    
    if _is_deterministic(simpack):
        assert my_path[5].state == new_state
        
    assert len(my_path) == x + 1
    
    node_1 = my_path[-3]
    
    node_2 = project.simulate(node_1, 5)
    
    assert len(project.tree.nodes) == x + 6
    assert len(project.tree.roots) == 1
    
    assert len(project.tree.all_possible_paths()) == 2
    
    node_3 = my_path.next_node(node_1)
    
    project.begin_crunching(node_3, 5)
    
    total_nodes_added = 0
    while project.crunching_manager.jobs:
        time.sleep(0.1)
        total_nodes_added += project.sync_crunchers()
    
    y = total_nodes_added
    assert len(project.tree.nodes) == x + y + 6
    
    paths = project.tree.all_possible_paths()
    assert len(paths) == 3
    
    assert set(len(p) for p in paths) == set([x + 1, x + 4, x + y])
    
    
    project.ensure_buffer(node_3, 3)

    total_nodes_added = 0
    while project.crunching_manager.jobs:
        time.sleep(0.1)
        total_nodes_added += project.sync_crunchers()
    
    assert len(project.tree.nodes) == x + y + 6 + total_nodes_added
    assert len(project.tree.all_possible_paths()) == 3
    
    assert project.tree.lock._ReadWriteLock__writer is None
    
    two_paths = node_3.all_possible_paths()
    
    assert len(two_paths) == 2
    (path_1, path_2) = two_paths
    get_clock_buffer = lambda path: (path[-1].state.clock - node_3.state.clock)
    (clock_buffer_1, clock_buffer_2) = [get_clock_buffer(p) for p in two_paths]
    
    project.ensure_buffer_on_path(node_3, path_1, get_clock_buffer(path_1) * 1.2)
    
    total_nodes_added = 0
    while project.crunching_manager.jobs:
        time.sleep(0.1)
        total_nodes_added += project.sync_crunchers()
    
    (old_clock_buffer_1, old_clock_buffer_2) = (clock_buffer_1, clock_buffer_2)
    (clock_buffer_1, clock_buffer_2) = [get_clock_buffer(p) for p in two_paths]
    
    assert clock_buffer_1 / old_clock_buffer_1 >= 1.2
    assert clock_buffer_2 == old_clock_buffer_2
    
    project.ensure_buffer_on_path(node_3, path_2, get_clock_buffer(path_2) * 1.3)
    
    total_nodes_added = 0
    while project.crunching_manager.jobs:
        time.sleep(0.1)
        total_nodes_added += project.sync_crunchers()
    
    (old_clock_buffer_1, old_clock_buffer_2) = (clock_buffer_1, clock_buffer_2)
    (clock_buffer_1, clock_buffer_2) = [get_clock_buffer(p) for p in two_paths]
    
    assert clock_buffer_1 == old_clock_buffer_1
    assert clock_buffer_2 / old_clock_buffer_2 >= 1.3
    
    
    
    plain_root = project.create_root()
    
    assert len(project.tree.roots) == 2
    
    assert len(project.tree.all_possible_paths()) == 4
    
    
    
    assert project.tree.lock._ReadWriteLock__writer is None
    
    number_of_nodes = len(project.tree.nodes)
    iterator = project.iter_simulate(node_1, 10)
    
    assert project.tree.lock._ReadWriteLock__writer is None
    
    new_node = iterator.next()
    assert new_node is node_1
    assert len(project.tree.nodes) == number_of_nodes
    
    assert project.tree.lock._ReadWriteLock__writer is None
    
    new_node = iterator.next()
    assert new_node is not node_1
    assert new_node.parent is node_1
    assert len(project.tree.nodes) == number_of_nodes + 1
    
    bunch_of_new_nodes = tuple(iterator)
    for parent_node, kid_node in cute_iter_tools.consecutive_pairs(bunch_of_new_nodes):
        assert project.tree.lock._ReadWriteLock__writer is None
        assert isinstance(parent_node, garlicsim.data_structures.Node)
        assert isinstance(kid_node, garlicsim.data_structures.Node)
        assert parent_node.children == [kid_node]
        assert kid_node.parent is parent_node
        
    assert len(project.tree.nodes) == number_of_nodes + 10
        
    
    
    
Example #4
0
def check(simpack, cruncher_type):

    assert simpack._test_settings.ENDABLE is True
    assert simpack._test_settings.CONSTANT_CLOCK_INTERVAL == 1

    my_simpack_grokker = garlicsim.misc.SimpackGrokker(simpack)

    assert my_simpack_grokker is garlicsim.misc.SimpackGrokker(simpack)
    # Ensuring caching works.

    assert garlicsim.misc.simpack_grokker.step_type.StepType.get_step_type(
        my_simpack_grokker.default_step_function
    ) == simpack._test_settings.DEFAULT_STEP_FUNCTION_TYPE

    step_profile = my_simpack_grokker.build_step_profile()
    deterministic = \
        my_simpack_grokker.settings.DETERMINISM_FUNCTION(step_profile)

    state = simpack.State.create_root()

    ### Running for short periods synchronically so it doesn't end: ###########
    #                                                                         #

    # Whether we run the simulation for one, two, three, or four iterations,
    # the simulation doesn't end.
    prev_state = state
    for i in [1, 2, 3, 4]:
        new_state = garlicsim.simulate(state, i)
        assert new_state.clock >= getattr(prev_state, 'clock', 0)
        prev_state = new_state

    result = garlicsim.list_simulate(state, 4)
    for item in result:
        assert isinstance(item, garlicsim.data_structures.State)
        assert isinstance(item, simpack.State)

    assert isinstance(result, list)
    assert len(result) == 5

    iter_result = garlicsim.iter_simulate(state, 4)

    assert not hasattr(iter_result, '__getitem__')
    assert hasattr(iter_result, '__iter__')
    iter_result_in_list = list(iter_result)
    del iter_result
    assert len(iter_result_in_list) == len(result) == 5

    #                                                                         #
    ### Done running for short periods synchronically so it doesn't end. ######

    ### Now, let's run it for longer periods synchronically to make it end: ###
    #                                                                         #

    for i in [5, 6, 7]:
        new_state = garlicsim.simulate(state, i)
        assert new_state.clock == 4

    result = garlicsim.list_simulate(state, 7)

    assert isinstance(result, list)
    assert len(result) == 5

    iter_result = garlicsim.iter_simulate(state, 7)

    assert not hasattr(iter_result, '__getitem__')
    assert hasattr(iter_result, '__iter__')
    iter_result_in_list = list(iter_result)
    del iter_result
    assert len(iter_result_in_list) == len(result) == 5

    #                                                                         #
    ### Done running for longer periods synchronically to make it end. ########

    ### Setting up a project to run asynchronous tests:

    project = garlicsim.Project(simpack)

    project.crunching_manager.cruncher_type = cruncher_type

    assert project.tree.lock._ReadWriteLock__writer is None

    root = project.root_this_state(state)

    def get_all_ends():
        return [
            member for member in project.tree.iterate_tree_members()
            if isinstance(member, garlicsim.data_structures.End)
        ]

    assert len(get_all_ends()) == 0

    ### Running for short periods asynchronically so it doesn't end: ##########
    #                                                                         #

    project.begin_crunching(root, 4)

    total_nodes_added = 0
    while project.crunching_manager.jobs:
        time.sleep(0.1)
        total_nodes_added += project.sync_crunchers()

    assert total_nodes_added == 4

    assert len(project.tree.nodes) == 5
    assert len(project.tree.roots) == 1

    paths = project.tree.all_possible_paths()

    assert len(paths) == 1

    (my_path, ) = paths

    assert len(my_path) == 5

    node_1 = my_path[1]
    assert node_1.state.clock == 1

    node_2 = project.simulate(node_1, 3)

    assert len(project.tree.nodes) == 8
    assert len(project.tree.roots) == 1

    assert len(project.tree.all_possible_paths()) == 2

    assert len(get_all_ends()) == 0

    #                                                                         #
    ### Done running for short periods asynchronically so it doesn't end. #####

    ### Now, let's run it for longer periods asynchronically to make it end: ##
    #                                                                         #

    node_3 = my_path.next_node(node_1)
    assert node_3.state.clock == 2
    project.begin_crunching(node_3, 3)

    total_nodes_added = 0
    while project.crunching_manager.jobs:
        time.sleep(0.1)
        total_nodes_added += project.sync_crunchers()
    assert total_nodes_added == 2  # Would have been 3 without the end!

    assert len(get_all_ends()) == 1

    # So now `node_3`'s newer path has an end:
    ended_path = node_3.all_possible_paths()[1]
    isinstance(ended_path, garlicsim.data_structures.Path)
    (end,
     ) = ended_path.get_ends_of_last_node()  # (Asserting there's one end.)
    assert isinstance(end, garlicsim.data_structures.End)

    assert len(project.tree.nodes) == 10

    paths = project.tree.all_possible_paths()
    assert len(paths) == 3

    assert [len(p) for p in paths] == [5, 5, 5]

    # Ensuring buffer on `ended_path` from `node_3` won't cause a new job to be
    # created since we have a path to an existing end:
    project.ensure_buffer_on_path(node_3, ended_path, 10)
    project.ensure_buffer_on_path(node_3, ended_path, 1000)
    project.ensure_buffer_on_path(node_3, ended_path, infinity)
    total_nodes_added = 0
    assert not project.crunching_manager.jobs
    assert len(project.tree.nodes) == 10

    # These `ensure_buffer_on_path` calls shouldn't have added any ends:
    assert len(get_all_ends()) == 1

    # But `node_3` has the older path coming out of it which goes all the way to
    # clock 4 but doesn't terminate in an `End`:
    other_path = node_3.all_possible_paths()[0]
    assert other_path.get_ends_of_last_node() == []

    # And when we `ensure_buffer` from `node_3`, it will ensure a buffer on that
    # path also, and cause an `End` to be created there:
    project.ensure_buffer(node_3, 1000)
    total_nodes_added = 0
    while project.crunching_manager.jobs:
        time.sleep(0.1)
        total_nodes_added += project.sync_crunchers()
    assert len(project.tree.nodes) == 10
    assert len(get_all_ends()) == 2

    plain_root = project.create_root()

    assert len(project.tree.roots) == 2
    assert len(project.tree.all_possible_paths()) == 4
    assert len(project.tree.nodes) == 11

    iterator = project.iter_simulate(node_1, 10)
    new_node = iterator.next()
    assert new_node is node_1
    assert len(project.tree.nodes) == 11

    assert project.tree.lock._ReadWriteLock__writer is None

    new_node = iterator.next()
    assert new_node is not node_1
    assert new_node.parent is node_1
    assert len(project.tree.nodes) == 12

    bunch_of_new_nodes = tuple(iterator)
    consecutive_pairs = cute_iter_tools.consecutive_pairs(bunch_of_new_nodes)
    for parent_node, kid_node in consecutive_pairs:
        assert project.tree.lock._ReadWriteLock__writer is None
        assert isinstance(parent_node, garlicsim.data_structures.Node)
        assert isinstance(kid_node, garlicsim.data_structures.Node)
        assert parent_node.children == [kid_node]
        assert kid_node.parent is parent_node

    assert len(project.tree.nodes) == 14

    assert len(get_all_ends()) == 3


    tree_members_iterator = \
        project.tree.iterate_tree_members(include_blockful_nodes=False)
    assert tree_members_iterator.__iter__() is tree_members_iterator
    tree_members = list(tree_members_iterator)
    for tree_member in tree_members:
        if isinstance(tree_member, garlicsim.data_structures.Node):
            assert tree_member.block is None

    tree_members_iterator_including_blockful_nodes = \
        project.tree.iterate_tree_members()
    assert tree_members_iterator_including_blockful_nodes.__iter__() is \
        tree_members_iterator_including_blockful_nodes
    tree_members_including_blockful_nodes = \
        list(tree_members_iterator_including_blockful_nodes)


    blockful_nodes = \
        [member for member in tree_members_including_blockful_nodes if
         member not in tree_members]
    assert len(blockful_nodes) >= 1
    for blockful_node in blockful_nodes:
        assert isinstance(blockful_node, garlicsim.data_structures.Node)
        assert isinstance(blockful_node.block, garlicsim.data_structures.Block)
        assert blockful_node.block is blockful_node.soft_get_block()
    assert set(tree_members).\
        issubset(set(tree_members_including_blockful_nodes))

    tree_step_profiles = project.tree.get_step_profiles()
    assert isinstance(tree_step_profiles, OrderedSet)
    assert tree_step_profiles == [step_profile]

    ends = [
        member for member in tree_members
        if isinstance(member, garlicsim.data_structures.End)
    ]
    assert len(ends) == 3
    for end in ends:
        assert end in tree_members_including_blockful_nodes

    ### Testing `Project.simulate`: ###########################################
    #                                                                         #

    project.simulate(root, 4)
    assert len(get_all_ends()) == 3

    project.simulate(root, 5)
    assert len(get_all_ends()) == 4

    #                                                                         #
    ### Finished testing `Project.simulate`. ##################################

    ### Testing end creation in middle of block: ##############################
    #                                                                         #

    my_non_ending_step = non_ending_history_step if \
        my_simpack_grokker.history_dependent else non_ending_inplace_step

    nodes_in_tree = len(project.tree.nodes)
    nodes = list(project.iter_simulate(root, 8, my_non_ending_step))
    assert len(project.tree.nodes) == nodes_in_tree + 8

    middle_node = nodes[-4]
    assert middle_node.state.clock == 5
    assert nodes[1].block == middle_node.block == nodes[-1].block
    assert len(middle_node.block) == 8

    project.begin_crunching(middle_node, infinity, step_profile)
    total_nodes_added = 0
    assert project.crunching_manager.jobs
    while project.crunching_manager.jobs:
        time.sleep(0.1)
        total_nodes_added += project.sync_crunchers()
    assert total_nodes_added == 0

    assert len(middle_node.ends) == 1
    assert middle_node.block is not nodes[-1].block
    assert len(middle_node.block) == 5
    assert len(nodes[-1].block) == 3
Example #5
0
def check(simpack, cruncher_type):

    my_simpack_grokker = garlicsim.misc.SimpackGrokker(simpack)

    assert my_simpack_grokker is garlicsim.misc.SimpackGrokker(simpack)
    # Ensuring caching works.

    assert not simpack._test_settings.ENDABLE

    assert garlicsim.misc.simpack_grokker.step_type.StepType.get_step_type(
        my_simpack_grokker.default_step_function
    ) == simpack._test_settings.DEFAULT_STEP_FUNCTION_TYPE

    step_profile = my_simpack_grokker.build_step_profile()
    deterministic = \
        my_simpack_grokker.settings.DETERMINISM_FUNCTION(step_profile)

    state = simpack.State.create_root()

    prev_state = state
    for i in [1, 2, 3, 4]:
        new_state = garlicsim.simulate(state, i)
        assert new_state.clock >= getattr(prev_state, 'clock', 0)
        prev_state = new_state

    result = garlicsim.list_simulate(state, 4)
    for item in result:
        assert isinstance(item, garlicsim.data_structures.State)
        assert isinstance(item, simpack.State)

    assert isinstance(result, list)
    assert len(result) == 5

    iter_result = garlicsim.iter_simulate(state, 4)

    assert not hasattr(iter_result, '__getitem__')
    assert hasattr(iter_result, '__iter__')
    iter_result_in_list = list(iter_result)
    del iter_result
    assert len(iter_result_in_list) == len(result) == 5

    ### Setting up a project to run asynchronous tests:

    project = garlicsim.Project(simpack)

    project.crunching_manager.cruncher_type = cruncher_type

    assert project.tree.lock._ReadWriteLock__writer is None

    root = project.root_this_state(state)

    project.begin_crunching(root, 4)

    total_nodes_added = 0
    while project.crunching_manager.jobs:
        time.sleep(0.1)
        total_nodes_added += project.sync_crunchers()

    assert total_nodes_added == 4

    assert len(project.tree.nodes) == 5
    assert len(project.tree.roots) == 1

    paths = project.tree.all_possible_paths()

    assert len(paths) == 1

    (my_path, ) = paths

    assert len(my_path) == 5

    node_1 = my_path[1]
    assert node_1.state.clock == 1

    node_2 = project.simulate(node_1, 3)

    assert len(project.tree.nodes) == 8
    assert len(project.tree.roots) == 1

    assert len(project.tree.all_possible_paths()) == 2

    block_1, block_2 = [node.block for node in node_1.children]
    assert isinstance(block_1, garlicsim.data_structures.Block)
    assert isinstance(block_2, garlicsim.data_structures.Block)
    assert block_1.soft_get_block() is block_1
    assert block_2.soft_get_block() is block_2
    assert block_1.is_overlapping(block_1)
    assert block_2.is_overlapping(block_2)
    assert not block_1.is_overlapping(block_2)
    assert not block_2.is_overlapping(block_1)
    block_path_1 = block_1.make_containing_path()
    block_path_2 = block_2.make_containing_path()
    assert block_path_1 == block_path_1
    assert block_path_1 != block_path_2
    assert (block_1[0] in block_path_1) and (block_1[-1] in block_path_1)
    assert (block_2[0] in block_path_2) and (block_2[-1] in block_path_2)
    assert block_1.get_root() is block_2.get_root()



    tree_members_iterator = \
        project.tree.iterate_tree_members(include_blockful_nodes=False)
    assert tree_members_iterator.__iter__() is tree_members_iterator
    tree_members = list(tree_members_iterator)
    assert (block_1 in tree_members) and (block_2 in tree_members)
    for tree_member in tree_members:
        if isinstance(tree_member, garlicsim.data_structures.Node):
            assert tree_member.block is None

    tree_members_iterator_including_blockful_nodes = \
        project.tree.iterate_tree_members(include_blockful_nodes=True)
    assert tree_members_iterator_including_blockful_nodes.__iter__() is \
        tree_members_iterator_including_blockful_nodes
    tree_members_including_blockful_nodes = \
        list(tree_members_iterator_including_blockful_nodes)

    blockful_nodes = \
        [member for member in tree_members_including_blockful_nodes if
         member not in tree_members]
    for blockful_node in blockful_nodes:
        assert isinstance(blockful_node, garlicsim.data_structures.Node)
        assert isinstance(blockful_node.block, garlicsim.data_structures.Block)
        assert blockful_node.block is blockful_node.soft_get_block()
    assert set(tree_members).\
        issubset(set(tree_members_including_blockful_nodes))

    tree_step_profiles = project.tree.get_step_profiles()
    assert isinstance(tree_step_profiles, OrderedSet)
    assert tree_step_profiles == [step_profile]
def check(simpack, cruncher_type):
    
    my_simpack_grokker = garlicsim.misc.SimpackGrokker(simpack)
    
    assert my_simpack_grokker is garlicsim.misc.SimpackGrokker(simpack)
    # Ensuring caching works.
    
    empty_step_profile = garlicsim.misc.StepProfile(
        my_simpack_grokker.default_step_function
    )
    
    state = simpack.State.create_messy_root() if \
          simpack.State.create_messy_root else \
          simpack.State.create_root()
    
    new_state = garlicsim.simulate(state, 3)
    
    result = garlicsim.list_simulate(state, 3)
    for item in result:
        assert isinstance(item, garlicsim.data_structures.State)
        assert isinstance(item, simpack.State)
    
    assert isinstance(result, list)
    assert len(result) == 4
    
    if _is_deterministic(simpack):    
        for old, new in cute_iter_tools.consecutive_pairs(result):
            assert new == my_simpack_grokker.step(old, empty_step_profile)
            
    
    iter_result = garlicsim.iter_simulate(state, 3)
    
    
    assert not hasattr(iter_result, '__getitem__')
    assert hasattr(iter_result, '__iter__')
    iter_result_in_list = list(iter_result)
    del iter_result
    assert len(iter_result_in_list) == len(result) == 4
    if _is_deterministic(simpack):
        assert iter_result_in_list == result
        assert iter_result_in_list[-1] == new_state == result[-1]
        
    
    
    project = garlicsim.Project(simpack)
    
    # Ensure that `Project.__init__` can take simpack grokker:
    alterante_project = garlicsim.Project(my_simpack_grokker)
    project.simpack is alterante_project.simpack
    project.simpack_grokker is alterante_project.simpack_grokker
    
    
    project.crunching_manager.cruncher_type = cruncher_type
    
    assert project.tree.lock._ReadWriteLock__writer is None
    
    root = project.root_this_state(state)
    
    project.begin_crunching(root, 4)

    total_nodes_added = 0    
    while project.crunching_manager.jobs:
        time.sleep(0.1)
        total_nodes_added += project.sync_crunchers()
        
    x = total_nodes_added
    
    if x < 4:
        # For simpacks with long time intervals, we make sure at least 4 nodes
        # were created.
        path = root.make_containing_path()
        leaf = path[-1]
        project.simulate(
            leaf,
            math_tools.round_to_int(4 - x, up=True)
        )
        x += path.__len__(head=path.next_node(leaf))
            
    assert len(project.tree.nodes) == x + 1
    assert len(project.tree.roots) == 1
    
    paths = project.tree.all_possible_paths()
    
    assert len(paths) == 1
    
    (my_path,) = paths
        
    assert len(my_path) == x + 1
    
    node_1 = my_path[1]
    
    node_2 = project.simulate(node_1, 3)
    
    assert len(project.tree.nodes) == x + 1 + 3
    assert len(project.tree.roots) == 1
    
    assert len(project.tree.all_possible_paths()) == 2
    
    
    ### Testing project pickling and unpickling: ##############################
    #                                                                         #
    pickled_project = pickle.dumps(project, protocol=2)
    
    unpickled_project = cPickle.loads(pickled_project)
    path_pairs = itertools.izip(project.tree.all_possible_paths(),
                                unpickled_project.tree.all_possible_paths())
    
    if simpack.State.__eq__ != garlicsim.data_structures.State.__eq__:
        
        for path_of_original, path_of_duplicate in path_pairs:
            
            state_pairs = itertools.izip(path_of_original.states(),
                                         path_of_duplicate.states())
            for state_of_original, state_of_duplicate in state_pairs:
                
                assert state_of_original == state_of_duplicate
    #                                                                         #
    ### Finished testing project pickling and unpickling. #####################
            
    
    
    node_3 = my_path.next_node(node_1)
    
    project.begin_crunching(node_3, 3)
    
    total_nodes_added = 0
    while project.crunching_manager.jobs:
        time.sleep(0.1)
        total_nodes_added += project.sync_crunchers()
    y = total_nodes_added
        
    if y < 3:
        # For simpacks with long time intervals, we make sure at least 3 nodes
        # were created.
        path = node_3.children[1].make_containing_path()
        leaf = path[-1]
        project.simulate(
            leaf,
            math_tools.round_to_int(3 - y, up=True)
        )
        y += path.__len__(head=path.next_node(leaf))
    
    
    assert len(project.tree.nodes) == x + y + 4
    
    paths = project.tree.all_possible_paths()
    assert len(paths) == 3
    
    assert [len(p) for p in paths] == [x + 1, 3 + y, 5]
    
    for (_path_1, _path_2) in cute_iter_tools.consecutive_pairs(paths):
        assert _path_1._get_higher_path(node=root) == _path_2
        
    for _path in paths:
        assert _path.copy() == _path
    
    
    project.ensure_buffer(node_3, 3)

    total_nodes_added = 0
    while project.crunching_manager.jobs:
        time.sleep(0.1)
        total_nodes_added += project.sync_crunchers()
    
    assert len(project.tree.nodes) == x + y + 4 + total_nodes_added
    assert len(project.tree.all_possible_paths()) == 3
    
    assert project.tree.lock._ReadWriteLock__writer is None
    
    two_paths = node_3.all_possible_paths()
    
    assert len(two_paths) == 2
    (path_1, path_2) = two_paths
    get_clock_buffer = lambda path: (path[-1].state.clock - node_3.state.clock)
    (clock_buffer_1, clock_buffer_2) = [get_clock_buffer(p) for p in two_paths]
    
    project.ensure_buffer_on_path(node_3, path_1, get_clock_buffer(path_1) * 1.2)
    
    total_nodes_added = 0
    while project.crunching_manager.jobs:
        time.sleep(0.1)
        total_nodes_added += project.sync_crunchers()
    
    (old_clock_buffer_1, old_clock_buffer_2) = (clock_buffer_1, clock_buffer_2)
    (clock_buffer_1, clock_buffer_2) = [get_clock_buffer(p) for p in two_paths]
    
    assert clock_buffer_1 / old_clock_buffer_1 >= 1.2 - FUZZ
    assert clock_buffer_2 == old_clock_buffer_2
    
    project.ensure_buffer_on_path(node_3, path_2, get_clock_buffer(path_2) * 1.3)
    
    total_nodes_added = 0
    while project.crunching_manager.jobs:
        time.sleep(0.1)
        total_nodes_added += project.sync_crunchers()
    
    (old_clock_buffer_1, old_clock_buffer_2) = (clock_buffer_1, clock_buffer_2)
    (clock_buffer_1, clock_buffer_2) = [get_clock_buffer(p) for p in two_paths]
    
    assert clock_buffer_1 == old_clock_buffer_1
    assert clock_buffer_2 / old_clock_buffer_2 >= 1.3 - FUZZ
    
    
    
    plain_root = project.create_root()
    
    assert len(project.tree.roots) == 2
    
    assert len(project.tree.all_possible_paths()) == 4
    
    
    
    assert project.tree.lock._ReadWriteLock__writer is None
    
    number_of_nodes = len(project.tree.nodes)
    iterator = project.iter_simulate(plain_root, 5)
    
    assert project.tree.lock._ReadWriteLock__writer is None
    
    new_node = iterator.next()
    assert new_node is plain_root
    assert len(project.tree.nodes) == number_of_nodes
    
    assert project.tree.lock._ReadWriteLock__writer is None
    
    new_node = iterator.next()
    assert new_node is not plain_root
    assert new_node.parent is plain_root
    assert len(project.tree.nodes) == number_of_nodes + 1
    
    bunch_of_new_nodes = tuple(iterator)
    consecutive_nodes = cute_iter_tools.consecutive_pairs(bunch_of_new_nodes)
    for parent_node, kid_node in consecutive_nodes:
        assert project.tree.lock._ReadWriteLock__writer is None
        assert isinstance(parent_node, garlicsim.data_structures.Node)
        assert isinstance(kid_node, garlicsim.data_structures.Node)
        assert parent_node.children == [kid_node]
        assert kid_node.parent is parent_node
        
    assert len(project.tree.nodes) == number_of_nodes + 5
    
    (alternate_path,) = plain_root.all_possible_paths()
    assert isinstance(alternate_path, garlicsim.data_structures.Path)
    assert alternate_path == plain_root.make_containing_path()
    assert len(alternate_path) == 6
    all_except_root = list(alternate_path)[1:]
    
    ((_key, _value),) = plain_root.get_all_leaves().items()
    assert _key is alternate_path[-1]
    assert _value['nodes_distance'] == 5
    assert 'clock_distance' in _value # Can't know the value of that.
    
    block = all_except_root[0].block
    assert isinstance(block, garlicsim.data_structures.Block)
    for node in all_except_root:
        assert isinstance(node, garlicsim.data_structures.Node)
        assert node.block is node.soft_get_block() is block
        nose.tools.assert_raises(garlicsim.data_structures.NodeError,
                                 node.finalize)
        assert node.get_root() is plain_root
        assert node.get_ancestor(generations=0) is node
        assert node.get_ancestor(generations=infinity, round=True) is \
            plain_root
        nose.tools.assert_raises(
            garlicsim.data_structures.node.NodeLookupError,
            lambda: node.get_ancestor(generations=infinity, round=False)
        )
        nose.tools.assert_raises(
            garlicsim.data_structures.node.NodeLookupError,
            lambda: node.get_ancestor(generations=100, round=False)
        )
        if node.is_last_on_block():
            assert block[-1] is node
            assert node.get_ancestor(generations=2, round=False) is \
                block[-3]
            assert node.get_ancestor(generations=1, round=True) is \
                block[-2] is node.parent
        if node.is_first_on_block():
            assert block[0] is node
        
    assert set(all_except_root) == set(block)
    
    second_on_block = block[1]
    second_to_last_on_block = block[-2]
    assert second_to_last_on_block.state.clock > second_on_block.state.clock
    assert list(
        alternate_path.iterate_blockwise(
            second_on_block,
            second_to_last_on_block
        )
    ) == list(block[1:-1])
    assert list(
        alternate_path.iterate_blockwise_reversed(
            second_on_block,
            second_to_last_on_block
        )
    ) == list(block[-2:0:-1])
    
    ### Testing path methods: #################################################
    #                                                                         #

    empty_path = garlicsim.data_structures.Path(project.tree)
    assert len(empty_path) == 0
    assert list(empty_path) == []
    assert list(reversed(empty_path)) == []
    assert list(empty_path.iterate_blockwise()) == []
    assert list(empty_path.iterate_blockwise_reversed()) == []
    
    
    for (path, other_path) in [(path_1, path_2), (path_2, path_1)]:
        assert isinstance(path, garlicsim.data_structures.Path)
        assert path[-1] is path.get_last_node()
        node_list = list(path)
        reversed_node_list = list(reversed(path))
        assert node_list == list(reversed(reversed_node_list))
        assert list(path.iterate_blockwise()) == \
            list(reversed(list(path.iterate_blockwise_reversed(tail=path[-1]))))
        stranger_node = other_path[-1] 
        assert stranger_node not in path
        nose.tools.assert_raises(
            garlicsim.data_structures.path.TailNotReached,
            lambda: list(path.__iter__(tail=stranger_node))
        )
        
    
    #                                                                         #
    ### Finished testing path methods. ########################################
    
    
    if simpack.State.create_messy_root is not None:
        messy_root = project.create_messy_root()
        assert len(project.tree.roots) == 3
        assert messy_root is project.tree.roots[-1]
        assert isinstance(messy_root.state, simpack.State)
Example #7
0
def check(simpack, cruncher_type):
    '''
    Run checks on a simpack that uses inplace step functions.
    '''
    my_simpack_grokker = garlicsim.misc.SimpackGrokker(simpack)
    
    assert simpack._test_settings.DEFAULT_STEP_FUNCTION_TYPE in \
           [garlicsim.misc.simpack_grokker.step_types.InplaceStep,
            garlicsim.misc.simpack_grokker.step_types.InplaceStepGenerator]
    
    assert garlicsim.misc.simpack_grokker.step_type.StepType.get_step_type(
        my_simpack_grokker.default_step_function
    ) == simpack._test_settings.DEFAULT_STEP_FUNCTION_TYPE
    
    assert simpack._test_settings.CONSTANT_CLOCK_INTERVAL == 1
    
    step_profile = my_simpack_grokker.build_step_profile()
    
    state = simpack.State.create_root()
    assert state.clock == 0
    
    
    with StateDeepcopyCounter() as state_deepcopy_counter:
        state_1 = garlicsim.simulate(state)
    assert state.clock == 0
    assert state_1.clock == 1
    assert state_1 is not state
    assert state_1.list is not state.list
    assert state_1.cross_process_persistent is state.cross_process_persistent
    n_state_deepcopy_operations = state_deepcopy_counter.call_count
    assert 1 <= n_state_deepcopy_operations <= 2
    
    
    with StateDeepcopyCounter() as state_deepcopy_counter:
        state_2 = garlicsim.simulate(state, 2)
    assert state.clock == 0
    assert state_1.clock == 1
    assert state_2.clock == 2
    assert state_2 is not state
    assert state_2.list is not state.list
    assert state_2.cross_process_persistent is state.cross_process_persistent
    assert n_state_deepcopy_operations == state_deepcopy_counter.call_count

    
    with StateDeepcopyCounter() as state_deepcopy_counter:
        state_10 = garlicsim.simulate(state, 10)
    assert state.clock == 0
    assert state_1.clock == 1
    assert state_2.clock == 2
    assert state_10.clock == 10
    assert state_10 is not state
    assert state_10 is not state_2
    assert state_10.list is not state.list
    assert state_10.list is not state_2.list
    assert state_10.cross_process_persistent is state.cross_process_persistent
    assert n_state_deepcopy_operations == state_deepcopy_counter.call_count
    

    ###########################################################################
    #                                                                         #
    
    with StateDeepcopyCounter() as state_deepcopy_counter:
        garlicsim.list_simulate(state, 3)
    n_state_deepcopy_operations_for_3_in_list = \
        state_deepcopy_counter.call_count
    
    with StateDeepcopyCounter() as state_deepcopy_counter:
        garlicsim.list_simulate(state, 4)
    n_state_deepcopy_operations_for_4_in_list = \
        state_deepcopy_counter.call_count
    
    assert n_state_deepcopy_operations_for_4_in_list > \
           n_state_deepcopy_operations_for_3_in_list
    
    #                                                                         #
    ###########################################################################
        
        
    prev_state = state
    for i in [1, 2, 3, 4]:
        new_state = garlicsim.simulate(state, i)
        assert new_state.clock >= getattr(prev_state, 'clock', 0)
        assert new_state is not prev_state
        assert new_state.list is not prev_state.list
        assert new_state.cross_process_persistent is \
               prev_state.cross_process_persistent
        prev_state = new_state
    
    result = garlicsim.list_simulate(state, 4)
    for item in result:
        assert isinstance(item, garlicsim.data_structures.State)
        assert isinstance(item, simpack.State)
    
    assert isinstance(result, list)
    assert len(result) == 5
        
    
    iter_result = garlicsim.iter_simulate(state, 4)
        
    assert not hasattr(iter_result, '__getitem__')
    assert hasattr(iter_result, '__iter__')
    iter_result_in_list = list(iter_result)
    del iter_result
    assert len(iter_result_in_list) == len(result) == 5

    
    ### Setting up a project to run asynchronous tests:
    
    project = garlicsim.Project(simpack)
        
    project.crunching_manager.cruncher_type = cruncher_type
    
    assert project.tree.lock._ReadWriteLock__writer is None
    
    root = project.root_this_state(state)
    
    
    project.begin_crunching(root, 4)

    total_nodes_added = 0    
    while project.crunching_manager.jobs:
        time.sleep(0.1)
        total_nodes_added += project.sync_crunchers()
        
    assert total_nodes_added == 4
    
    assert len(project.tree.nodes) == 5
    assert len(project.tree.roots) == 1
    
    paths = project.tree.all_possible_paths()
    
    assert len(paths) == 1
    
    (my_path,) = paths
        
    assert len(my_path) == 5
    
    node_1 = my_path[1]
    assert node_1.state.clock == 1
    
    node_2 = project.simulate(node_1, 3)
    
    assert len(project.tree.nodes) == 8
    assert len(project.tree.roots) == 1
    
    assert len(project.tree.all_possible_paths()) == 2

    block_1, block_2 = [node.block for node in node_1.children]
    assert isinstance(block_1, garlicsim.data_structures.Block)
    assert isinstance(block_2, garlicsim.data_structures.Block)
    assert block_1.soft_get_block() is block_1
    assert block_2.soft_get_block() is block_2
    assert block_1.is_overlapping(block_1)
    assert block_2.is_overlapping(block_2)
    assert not block_1.is_overlapping(block_2)
    assert not block_2.is_overlapping(block_1)
    block_path_1 = block_1.make_containing_path()
    block_path_2 = block_2.make_containing_path()
    assert block_path_1 == block_path_1
    assert block_path_1 != block_path_2
    assert (block_1[0] in block_path_1) and (block_1[-1] in block_path_1)
    assert (block_2[0] in block_path_2) and (block_2[-1] in block_path_2)
    assert block_1.get_root() is block_2.get_root()
    
        
 
    tree_members_iterator = \
        project.tree.iterate_tree_members(include_blockful_nodes=False)
    assert tree_members_iterator.__iter__() is tree_members_iterator
    tree_members = list(tree_members_iterator)
    assert (block_1 in tree_members) and (block_2 in tree_members)
    for tree_member in tree_members:
        if isinstance(tree_member, garlicsim.data_structures.Node):
            assert tree_member.block is None
    
    tree_members_iterator_including_blockful_nodes = \
        project.tree.iterate_tree_members(include_blockful_nodes=True)
    assert tree_members_iterator_including_blockful_nodes.__iter__() is \
        tree_members_iterator_including_blockful_nodes
    tree_members_including_blockful_nodes = \
        list(tree_members_iterator_including_blockful_nodes)
    
    blockful_nodes = \
        [member for member in tree_members_including_blockful_nodes if 
         member not in tree_members]
    for blockful_node in blockful_nodes:
        assert isinstance(blockful_node, garlicsim.data_structures.Node)
        assert isinstance(blockful_node.block, garlicsim.data_structures.Block)
        assert blockful_node.block is blockful_node.soft_get_block()
    assert set(tree_members).\
        issubset(set(tree_members_including_blockful_nodes))
    
    tree_step_profiles = project.tree.get_step_profiles()
    assert isinstance(tree_step_profiles, OrderedSet)
    assert tree_step_profiles == [step_profile]
    
Example #8
0
def test():
    '''Test tutorial-1.'''
    life_board_pattern = re.compile('^(([ #]{45}\n){24})([ #]{45})$')
    import garlicsim
    from garlicsim_lib.simpacks import life
    state = life.State.create_messy_root()
    assert life_board_pattern.match(repr(state))
    assert repr(type(state)) == \
        "<class 'garlicsim_lib.simpacks.life.state.State'>"
    new_state = garlicsim.simulate(state)
    assert life_board_pattern.match(repr(new_state))
    new_state = garlicsim.simulate(state, 20)
    assert life_board_pattern.match(repr(new_state))
    result = garlicsim.list_simulate(state, 20)
    assert repr(type(result)) == "<type 'list'>"
    assert len(result) == 21
    assert life_board_pattern.match(repr(result[0]))
    assert result[0] == state
    assert life_board_pattern.match(repr(result[-1]))
    assert life_board_pattern.match(repr(result[7]))
    repr(garlicsim.iter_simulate(state, 5))  # Not testing cause of pypy et al.
    assert (list(garlicsim.iter_simulate(state, 5)) == \
            garlicsim.list_simulate(state, 5))

    project = garlicsim.Project(life)
    state = life.State.create_diehard()
    assert life_board_pattern.match(repr(state))
    assert repr(state).count('#') == 7
    root = project.root_this_state(state)
    assert repr(root) == \
        ('<garlicsim.data_structures.Node with clock 0, '
         'root, leaf, touched, blockless, at %s>' % hex(id(root)))
    project.begin_crunching(root, 50)
    _result = project.sync_crunchers()
    assert repr(_result) == '<0 nodes were added to the tree>'
    (cruncher, ) = project.crunching_manager.crunchers.values()
    while cruncher.is_alive():
        time.sleep(0.1)
    _result = project.sync_crunchers()
    assert repr(_result) == '<50 nodes were added to the tree>'
    assert repr(
        project.tree) == ('<garlicsim.data_structures.Tree with 1 roots, '
                          '51 nodes and 1 possible paths at %s>' %
                          hex(id(project.tree)))
    (path, ) = project.tree.all_possible_paths()
    assert repr(path) == ('<garlicsim.data_structures.Path of length 51 '
                          'at %s>' % hex(id(path)))
    assert repr(path[-1]) == (
        '<garlicsim.data_structures.Node with clock 50, leaf, untouched, '
        'blockful, crunched with life.State.step_generator(<state>), at '
        '%s>' % hex(id(path[-1])))
    _state = path[-1].state
    assert repr(_state).count('#') == 24
    assert life_board_pattern.match(repr(_state))
    node = path[27]
    assert repr(node.state).count('#') == 20
    assert life_board_pattern.match(repr(node.state))
    new_node = project.fork_to_edit(node)
    new_node.state.board.set(28, 13, True)
    assert repr(new_node.state).count('#') == 21
    assert life_board_pattern.match(repr(new_node.state))
    new_node.finalize()
    assert repr(
        project.tree) == ('<garlicsim.data_structures.Tree with 1 roots, '
                          '52 nodes and 2 possible paths at %s>' %
                          hex(id(project.tree)))
    project.ensure_buffer(root, 50)
    _result = project.sync_crunchers()
    assert repr(_result) == '<0 nodes were added to the tree>'
    (cruncher, ) = project.crunching_manager.crunchers.values()
    while cruncher.is_alive():
        time.sleep(0.1)
    _result = project.sync_crunchers()
    assert repr(_result) == '<23 nodes were added to the tree>'
    new_path = new_node.make_containing_path()
    assert repr(new_path[-1].state).count('#') == 49
    assert life_board_pattern.match(repr(new_path[-1].state))
Example #9
0
def check(simpack, cruncher_type):
    
    assert simpack._test_settings.ENDABLE is True
    assert simpack._test_settings.CONSTANT_CLOCK_INTERVAL == 1
    
    my_simpack_grokker = garlicsim.misc.SimpackGrokker(simpack)
    
    assert my_simpack_grokker is garlicsim.misc.SimpackGrokker(simpack)
    # Ensuring caching works.
    
    assert garlicsim.misc.simpack_grokker.step_type.StepType.get_step_type(
        my_simpack_grokker.default_step_function
    ) == simpack._test_settings.DEFAULT_STEP_FUNCTION_TYPE
    
    step_profile = my_simpack_grokker.build_step_profile()
    deterministic = \
        my_simpack_grokker.settings.DETERMINISM_FUNCTION(step_profile)
    
    state = simpack.State.create_root()
    
    ### Running for short periods synchronically so it doesn't end: ###########
    #                                                                         #
    
    # Whether we run the simulation for one, two, three, or four iterations,
    # the simulation doesn't end.
    prev_state = state
    for i in [1, 2, 3, 4]:
        new_state = garlicsim.simulate(state, i)
        assert new_state.clock >= getattr(prev_state, 'clock', 0)
        prev_state = new_state
    
    result = garlicsim.list_simulate(state, 4)
    for item in result:
        assert isinstance(item, garlicsim.data_structures.State)
        assert isinstance(item, simpack.State)
    
    assert isinstance(result, list)
    assert len(result) == 5
        
    
    iter_result = garlicsim.iter_simulate(state, 4)
        
    assert not hasattr(iter_result, '__getitem__')
    assert hasattr(iter_result, '__iter__')
    iter_result_in_list = list(iter_result)
    del iter_result
    assert len(iter_result_in_list) == len(result) == 5
    
    #                                                                         #
    ### Done running for short periods synchronically so it doesn't end. ######
    
    ### Now, let's run it for longer periods synchronically to make it end: ###
    #                                                                         #
    
    for i in [5, 6, 7]:
        new_state = garlicsim.simulate(state, i)
        assert new_state.clock == 4
    
    result = garlicsim.list_simulate(state, 7)
    
    assert isinstance(result, list)
    assert len(result) == 5
        
    
    iter_result = garlicsim.iter_simulate(state, 7)
        
    assert not hasattr(iter_result, '__getitem__')
    assert hasattr(iter_result, '__iter__')
    iter_result_in_list = list(iter_result)
    del iter_result
    assert len(iter_result_in_list) == len(result) == 5
        
    #                                                                         #
    ### Done running for longer periods synchronically to make it end. ########
    
    ### Setting up a project to run asynchronous tests:
    
    project = garlicsim.Project(simpack) 
        
    project.crunching_manager.cruncher_type = cruncher_type
    
    assert project.tree.lock._ReadWriteLock__writer is None
    
    root = project.root_this_state(state)
    
    def get_all_ends():
        return [member for member in project.tree.iterate_tree_members() if 
                isinstance(member, garlicsim.data_structures.End)]
    
    assert len(get_all_ends()) == 0
    
    ### Running for short periods asynchronically so it doesn't end: ##########
    #                                                                         #
    
    project.begin_crunching(root, 4)

    total_nodes_added = 0    
    while project.crunching_manager.jobs:
        time.sleep(0.1)
        total_nodes_added += project.sync_crunchers()
        
    assert total_nodes_added == 4
    
    assert len(project.tree.nodes) == 5
    assert len(project.tree.roots) == 1
    
    paths = project.tree.all_possible_paths()
    
    assert len(paths) == 1
    
    (my_path,) = paths
        
    assert len(my_path) == 5
    
    node_1 = my_path[1]
    assert node_1.state.clock == 1
    
    node_2 = project.simulate(node_1, 3)
    
    assert len(project.tree.nodes) == 8
    assert len(project.tree.roots) == 1
    
    assert len(project.tree.all_possible_paths()) == 2
    
    assert len(get_all_ends()) == 0
    
    #                                                                         #
    ### Done running for short periods asynchronically so it doesn't end. #####
    
    ### Now, let's run it for longer periods asynchronically to make it end: ##
    #                                                                         #
    
    node_3 = my_path.next_node(node_1)
    assert node_3.state.clock == 2
    project.begin_crunching(node_3, 3)
    
    total_nodes_added = 0
    while project.crunching_manager.jobs:
        time.sleep(0.1)
        total_nodes_added += project.sync_crunchers()
    assert total_nodes_added == 2 # Would have been 3 without the end!
    
    assert len(get_all_ends()) == 1
    
    # So now `node_3`'s newer path has an end:
    ended_path = node_3.all_possible_paths()[1]
    isinstance(ended_path, garlicsim.data_structures.Path)
    (end,) = ended_path.get_ends_of_last_node() # (Asserting there's one end.)
    assert isinstance(end, garlicsim.data_structures.End)
    
    assert len(project.tree.nodes) == 10
    
    paths = project.tree.all_possible_paths()
    assert len(paths) == 3
    
    assert [len(p) for p in paths] == [5, 5, 5]
    
    
    # Ensuring buffer on `ended_path` from `node_3` won't cause a new job to be
    # created since we have a path to an existing end:
    project.ensure_buffer_on_path(node_3, ended_path, 10)
    project.ensure_buffer_on_path(node_3, ended_path, 1000)
    project.ensure_buffer_on_path(node_3, ended_path, infinity)
    total_nodes_added = 0    
    assert not project.crunching_manager.jobs
    assert len(project.tree.nodes) == 10
    
    # These `ensure_buffer_on_path` calls shouldn't have added any ends:
    assert len(get_all_ends()) == 1
    
    # But `node_3` has the older path coming out of it which goes all the way to
    # clock 4 but doesn't terminate in an `End`:
    other_path = node_3.all_possible_paths()[0]
    assert other_path.get_ends_of_last_node() == []
    
    # And when we `ensure_buffer` from `node_3`, it will ensure a buffer on that
    # path also, and cause an `End` to be created there:
    project.ensure_buffer(node_3, 1000)
    total_nodes_added = 0    
    while project.crunching_manager.jobs:
        time.sleep(0.1)
        total_nodes_added += project.sync_crunchers()
    assert len(project.tree.nodes) == 10
    assert len(get_all_ends()) == 2
    
    
    plain_root = project.create_root()
    
    assert len(project.tree.roots) == 2
    assert len(project.tree.all_possible_paths()) == 4
    assert len(project.tree.nodes) == 11
    
    iterator = project.iter_simulate(node_1, 10)
    new_node = iterator.next()
    assert new_node is node_1
    assert len(project.tree.nodes) == 11
    
    assert project.tree.lock._ReadWriteLock__writer is None
    
    new_node = iterator.next()
    assert new_node is not node_1
    assert new_node.parent is node_1
    assert len(project.tree.nodes) == 12
    
    bunch_of_new_nodes = tuple(iterator)
    consecutive_pairs = cute_iter_tools.consecutive_pairs(bunch_of_new_nodes)
    for parent_node, kid_node in consecutive_pairs:
        assert project.tree.lock._ReadWriteLock__writer is None
        assert isinstance(parent_node, garlicsim.data_structures.Node)
        assert isinstance(kid_node, garlicsim.data_structures.Node)
        assert parent_node.children == [kid_node]
        assert kid_node.parent is parent_node
        
    assert len(project.tree.nodes) == 14

    assert len(get_all_ends()) == 3
    
        
    tree_members_iterator = \
        project.tree.iterate_tree_members(include_blockful_nodes=False)
    assert tree_members_iterator.__iter__() is tree_members_iterator
    tree_members = list(tree_members_iterator)
    for tree_member in tree_members:
        if isinstance(tree_member, garlicsim.data_structures.Node):
            assert tree_member.block is None
            
    tree_members_iterator_including_blockful_nodes = \
        project.tree.iterate_tree_members()
    assert tree_members_iterator_including_blockful_nodes.__iter__() is \
        tree_members_iterator_including_blockful_nodes
    tree_members_including_blockful_nodes = \
        list(tree_members_iterator_including_blockful_nodes)
    
    
    blockful_nodes = \
        [member for member in tree_members_including_blockful_nodes if 
         member not in tree_members]
    assert len(blockful_nodes) >= 1
    for blockful_node in blockful_nodes:
        assert isinstance(blockful_node, garlicsim.data_structures.Node)
        assert isinstance(blockful_node.block, garlicsim.data_structures.Block)
        assert blockful_node.block is blockful_node.soft_get_block()
    assert set(tree_members).\
        issubset(set(tree_members_including_blockful_nodes))
    
    tree_step_profiles = project.tree.get_step_profiles()
    assert isinstance(tree_step_profiles, OrderedSet)
    assert tree_step_profiles == [step_profile]
    
    ends = [member for member in tree_members if 
            isinstance(member, garlicsim.data_structures.End)]
    assert len(ends) == 3
    for end in ends:
        assert end in tree_members_including_blockful_nodes
        
    ### Testing `Project.simulate`: ###########################################
    #                                                                         #
    
    project.simulate(root, 4)
    assert len(get_all_ends()) == 3
    
    project.simulate(root, 5)
    assert len(get_all_ends()) == 4
    
    #                                                                         #
    ### Finished testing `Project.simulate`. ##################################
    
    ### Testing end creation in middle of block: ##############################
    #                                                                         #
    
    my_non_ending_step = non_ending_history_step if \
        my_simpack_grokker.history_dependent else non_ending_inplace_step
    
    nodes_in_tree = len(project.tree.nodes)
    nodes = list(project.iter_simulate(root, 8, my_non_ending_step))
    assert len(project.tree.nodes) == nodes_in_tree + 8
    
    middle_node = nodes[-4]
    assert middle_node.state.clock == 5
    assert nodes[1].block == middle_node.block == nodes[-1].block
    assert len(middle_node.block) == 8
    

    project.begin_crunching(middle_node, infinity, step_profile)
    total_nodes_added = 0
    assert project.crunching_manager.jobs
    while project.crunching_manager.jobs:
        time.sleep(0.1)
        total_nodes_added += project.sync_crunchers()
    assert total_nodes_added == 0
    
    assert len(middle_node.ends) == 1
    assert middle_node.block is not nodes[-1].block
    assert len(middle_node.block) == 5
    assert len(nodes[-1].block) == 3
        
    #                                                                         #
    ### Finished testing end creation in middle of block. #####################
    
    
    
Example #10
0
def check(simpack, cruncher_type):
    '''
    Run checks on a simpack that uses inplace step functions.
    '''
    my_simpack_grokker = garlicsim.misc.SimpackGrokker(simpack)

    assert simpack._test_settings.DEFAULT_STEP_FUNCTION_TYPE in \
           [garlicsim.misc.simpack_grokker.step_types.InplaceStep,
            garlicsim.misc.simpack_grokker.step_types.InplaceStepGenerator]

    assert garlicsim.misc.simpack_grokker.step_type.StepType.get_step_type(
        my_simpack_grokker.default_step_function
    ) == simpack._test_settings.DEFAULT_STEP_FUNCTION_TYPE

    assert simpack._test_settings.CONSTANT_CLOCK_INTERVAL == 1

    step_profile = my_simpack_grokker.build_step_profile()

    state = simpack.State.create_root()
    assert state.clock == 0

    with StateDeepcopyCounter() as state_deepcopy_counter:
        state_1 = garlicsim.simulate(state)
    assert state.clock == 0
    assert state_1.clock == 1
    assert state_1 is not state
    assert state_1.list is not state.list
    assert state_1.cross_process_persistent is state.cross_process_persistent
    n_state_deepcopy_operations = state_deepcopy_counter.call_count
    assert 1 <= n_state_deepcopy_operations <= 2

    with StateDeepcopyCounter() as state_deepcopy_counter:
        state_2 = garlicsim.simulate(state, 2)
    assert state.clock == 0
    assert state_1.clock == 1
    assert state_2.clock == 2
    assert state_2 is not state
    assert state_2.list is not state.list
    assert state_2.cross_process_persistent is state.cross_process_persistent
    assert n_state_deepcopy_operations == state_deepcopy_counter.call_count

    with StateDeepcopyCounter() as state_deepcopy_counter:
        state_10 = garlicsim.simulate(state, 10)
    assert state.clock == 0
    assert state_1.clock == 1
    assert state_2.clock == 2
    assert state_10.clock == 10
    assert state_10 is not state
    assert state_10 is not state_2
    assert state_10.list is not state.list
    assert state_10.list is not state_2.list
    assert state_10.cross_process_persistent is state.cross_process_persistent
    assert n_state_deepcopy_operations == state_deepcopy_counter.call_count

    ###########################################################################
    #                                                                         #

    with StateDeepcopyCounter() as state_deepcopy_counter:
        garlicsim.list_simulate(state, 3)
    n_state_deepcopy_operations_for_3_in_list = \
        state_deepcopy_counter.call_count

    with StateDeepcopyCounter() as state_deepcopy_counter:
        garlicsim.list_simulate(state, 4)
    n_state_deepcopy_operations_for_4_in_list = \
        state_deepcopy_counter.call_count

    assert n_state_deepcopy_operations_for_4_in_list > \
           n_state_deepcopy_operations_for_3_in_list

    #                                                                         #
    ###########################################################################

    prev_state = state
    for i in [1, 2, 3, 4]:
        new_state = garlicsim.simulate(state, i)
        assert new_state.clock >= getattr(prev_state, 'clock', 0)
        assert new_state is not prev_state
        assert new_state.list is not prev_state.list
        assert new_state.cross_process_persistent is \
               prev_state.cross_process_persistent
        prev_state = new_state

    result = garlicsim.list_simulate(state, 4)
    for item in result:
        assert isinstance(item, garlicsim.data_structures.State)
        assert isinstance(item, simpack.State)

    assert isinstance(result, list)
    assert len(result) == 5

    iter_result = garlicsim.iter_simulate(state, 4)

    assert not hasattr(iter_result, '__getitem__')
    assert hasattr(iter_result, '__iter__')
    iter_result_in_list = list(iter_result)
    del iter_result
    assert len(iter_result_in_list) == len(result) == 5

    ### Setting up a project to run asynchronous tests:

    project = garlicsim.Project(simpack)

    project.crunching_manager.cruncher_type = cruncher_type

    assert project.tree.lock._ReadWriteLock__writer is None

    root = project.root_this_state(state)

    project.begin_crunching(root, 4)

    total_nodes_added = 0
    while project.crunching_manager.jobs:
        time.sleep(0.1)
        total_nodes_added += project.sync_crunchers()

    assert total_nodes_added == 4

    assert len(project.tree.nodes) == 5
    assert len(project.tree.roots) == 1

    paths = project.tree.all_possible_paths()

    assert len(paths) == 1

    (my_path, ) = paths

    assert len(my_path) == 5

    node_1 = my_path[1]
    assert node_1.state.clock == 1

    node_2 = project.simulate(node_1, 3)

    assert len(project.tree.nodes) == 8
    assert len(project.tree.roots) == 1

    assert len(project.tree.all_possible_paths()) == 2

    block_1, block_2 = [node.block for node in node_1.children]
    assert isinstance(block_1, garlicsim.data_structures.Block)
    assert isinstance(block_2, garlicsim.data_structures.Block)
    assert block_1.soft_get_block() is block_1
    assert block_2.soft_get_block() is block_2
    assert block_1.is_overlapping(block_1)
    assert block_2.is_overlapping(block_2)
    assert not block_1.is_overlapping(block_2)
    assert not block_2.is_overlapping(block_1)
    block_path_1 = block_1.make_containing_path()
    block_path_2 = block_2.make_containing_path()
    assert block_path_1 == block_path_1
    assert block_path_1 != block_path_2
    assert (block_1[0] in block_path_1) and (block_1[-1] in block_path_1)
    assert (block_2[0] in block_path_2) and (block_2[-1] in block_path_2)
    assert block_1.get_root() is block_2.get_root()



    tree_members_iterator = \
        project.tree.iterate_tree_members(include_blockful_nodes=False)
    assert tree_members_iterator.__iter__() is tree_members_iterator
    tree_members = list(tree_members_iterator)
    assert (block_1 in tree_members) and (block_2 in tree_members)
    for tree_member in tree_members:
        if isinstance(tree_member, garlicsim.data_structures.Node):
            assert tree_member.block is None

    tree_members_iterator_including_blockful_nodes = \
        project.tree.iterate_tree_members(include_blockful_nodes=True)
    assert tree_members_iterator_including_blockful_nodes.__iter__() is \
        tree_members_iterator_including_blockful_nodes
    tree_members_including_blockful_nodes = \
        list(tree_members_iterator_including_blockful_nodes)

    blockful_nodes = \
        [member for member in tree_members_including_blockful_nodes if
         member not in tree_members]
    for blockful_node in blockful_nodes:
        assert isinstance(blockful_node, garlicsim.data_structures.Node)
        assert isinstance(blockful_node.block, garlicsim.data_structures.Block)
        assert blockful_node.block is blockful_node.soft_get_block()
    assert set(tree_members).\
        issubset(set(tree_members_including_blockful_nodes))

    tree_step_profiles = project.tree.get_step_profiles()
    assert isinstance(tree_step_profiles, OrderedSet)
    assert tree_step_profiles == [step_profile]
Example #11
0
def check(simpack, cruncher_type):

    my_simpack_grokker = garlicsim.misc.SimpackGrokker(simpack)

    assert my_simpack_grokker is garlicsim.misc.SimpackGrokker(simpack)
    # Ensuring caching works.

    empty_step_profile = garlicsim.misc.StepProfile(
        my_simpack_grokker.default_step_function)

    state = simpack.State.create_messy_root() if \
          simpack.State.create_messy_root else \
          simpack.State.create_root()

    new_state = garlicsim.simulate(state, 3)

    result = garlicsim.list_simulate(state, 3)
    for item in result:
        assert isinstance(item, garlicsim.data_structures.State)
        assert isinstance(item, simpack.State)

    assert isinstance(result, list)
    assert len(result) == 4

    if _is_deterministic(simpack):
        for old, new in cute_iter_tools.consecutive_pairs(result):
            assert new == my_simpack_grokker.step(old, empty_step_profile)

    iter_result = garlicsim.iter_simulate(state, 3)

    assert not hasattr(iter_result, '__getitem__')
    assert hasattr(iter_result, '__iter__')
    iter_result_in_list = list(iter_result)
    del iter_result
    assert len(iter_result_in_list) == len(result) == 4
    if _is_deterministic(simpack):
        assert iter_result_in_list == result
        assert iter_result_in_list[-1] == new_state == result[-1]

    project = garlicsim.Project(simpack)

    # Ensure that `Project.__init__` can take simpack grokker:
    alterante_project = garlicsim.Project(my_simpack_grokker)
    project.simpack is alterante_project.simpack
    project.simpack_grokker is alterante_project.simpack_grokker

    project.crunching_manager.cruncher_type = cruncher_type

    assert project.tree.lock._ReadWriteLock__writer is None

    root = project.root_this_state(state)

    project.begin_crunching(root, 4)

    total_nodes_added = 0
    while project.crunching_manager.jobs:
        time.sleep(0.1)
        total_nodes_added += project.sync_crunchers()

    x = total_nodes_added

    if x < 4:
        # For simpacks with long time intervals, we make sure at least 4 nodes
        # were created.
        path = root.make_containing_path()
        leaf = path[-1]
        project.simulate(leaf, math_tools.round_to_int(4 - x, up=True))
        x += path.__len__(head=path.next_node(leaf))

    assert len(project.tree.nodes) == x + 1
    assert len(project.tree.roots) == 1

    paths = project.tree.all_possible_paths()

    assert len(paths) == 1

    (my_path, ) = paths

    assert len(my_path) == x + 1

    node_1 = my_path[1]

    node_2 = project.simulate(node_1, 3)

    assert len(project.tree.nodes) == x + 1 + 3
    assert len(project.tree.roots) == 1

    assert len(project.tree.all_possible_paths()) == 2

    ### Testing project pickling and unpickling: ##############################
    #                                                                         #
    pickled_project = pickle.dumps(project, protocol=2)

    unpickled_project = cPickle.loads(pickled_project)
    path_pairs = itertools.izip(project.tree.all_possible_paths(),
                                unpickled_project.tree.all_possible_paths())

    if simpack.State.__eq__ != garlicsim.data_structures.State.__eq__:

        for path_of_original, path_of_duplicate in path_pairs:

            state_pairs = itertools.izip(path_of_original.states(),
                                         path_of_duplicate.states())
            for state_of_original, state_of_duplicate in state_pairs:

                assert state_of_original == state_of_duplicate
    #                                                                         #
    ### Finished testing project pickling and unpickling. #####################

    node_3 = my_path.next_node(node_1)

    project.begin_crunching(node_3, 3)

    total_nodes_added = 0
    while project.crunching_manager.jobs:
        time.sleep(0.1)
        total_nodes_added += project.sync_crunchers()
    y = total_nodes_added

    if y < 3:
        # For simpacks with long time intervals, we make sure at least 3 nodes
        # were created.
        path = node_3.children[1].make_containing_path()
        leaf = path[-1]
        project.simulate(leaf, math_tools.round_to_int(3 - y, up=True))
        y += path.__len__(head=path.next_node(leaf))

    assert len(project.tree.nodes) == x + y + 4

    paths = project.tree.all_possible_paths()
    assert len(paths) == 3

    assert [len(p) for p in paths] == [x + 1, 3 + y, 5]

    for (_path_1, _path_2) in cute_iter_tools.consecutive_pairs(paths):
        assert _path_1._get_higher_path(node=root) == _path_2

    for _path in paths:
        assert _path.copy() == _path

    project.ensure_buffer(node_3, 3)

    total_nodes_added = 0
    while project.crunching_manager.jobs:
        time.sleep(0.1)
        total_nodes_added += project.sync_crunchers()

    assert len(project.tree.nodes) == x + y + 4 + total_nodes_added
    assert len(project.tree.all_possible_paths()) == 3

    assert project.tree.lock._ReadWriteLock__writer is None

    two_paths = node_3.all_possible_paths()

    assert len(two_paths) == 2
    (path_1, path_2) = two_paths
    get_clock_buffer = lambda path: (path[-1].state.clock - node_3.state.clock)
    (clock_buffer_1, clock_buffer_2) = [get_clock_buffer(p) for p in two_paths]

    project.ensure_buffer_on_path(node_3, path_1,
                                  get_clock_buffer(path_1) * 1.2)

    total_nodes_added = 0
    while project.crunching_manager.jobs:
        time.sleep(0.1)
        total_nodes_added += project.sync_crunchers()

    (old_clock_buffer_1, old_clock_buffer_2) = (clock_buffer_1, clock_buffer_2)
    (clock_buffer_1, clock_buffer_2) = [get_clock_buffer(p) for p in two_paths]

    assert clock_buffer_1 / old_clock_buffer_1 >= 1.2 - FUZZ
    assert clock_buffer_2 == old_clock_buffer_2

    project.ensure_buffer_on_path(node_3, path_2,
                                  get_clock_buffer(path_2) * 1.3)

    total_nodes_added = 0
    while project.crunching_manager.jobs:
        time.sleep(0.1)
        total_nodes_added += project.sync_crunchers()

    (old_clock_buffer_1, old_clock_buffer_2) = (clock_buffer_1, clock_buffer_2)
    (clock_buffer_1, clock_buffer_2) = [get_clock_buffer(p) for p in two_paths]

    assert clock_buffer_1 == old_clock_buffer_1
    assert clock_buffer_2 / old_clock_buffer_2 >= 1.3 - FUZZ

    plain_root = project.create_root()

    assert len(project.tree.roots) == 2

    assert len(project.tree.all_possible_paths()) == 4

    assert project.tree.lock._ReadWriteLock__writer is None

    number_of_nodes = len(project.tree.nodes)
    iterator = project.iter_simulate(plain_root, 5)

    assert project.tree.lock._ReadWriteLock__writer is None

    new_node = iterator.next()
    assert new_node is plain_root
    assert len(project.tree.nodes) == number_of_nodes

    assert project.tree.lock._ReadWriteLock__writer is None

    new_node = iterator.next()
    assert new_node is not plain_root
    assert new_node.parent is plain_root
    assert len(project.tree.nodes) == number_of_nodes + 1

    bunch_of_new_nodes = tuple(iterator)
    consecutive_nodes = cute_iter_tools.consecutive_pairs(bunch_of_new_nodes)
    for parent_node, kid_node in consecutive_nodes:
        assert project.tree.lock._ReadWriteLock__writer is None
        assert isinstance(parent_node, garlicsim.data_structures.Node)
        assert isinstance(kid_node, garlicsim.data_structures.Node)
        assert parent_node.children == [kid_node]
        assert kid_node.parent is parent_node

    assert len(project.tree.nodes) == number_of_nodes + 5

    (alternate_path, ) = plain_root.all_possible_paths()
    assert isinstance(alternate_path, garlicsim.data_structures.Path)
    assert alternate_path == plain_root.make_containing_path()
    assert len(alternate_path) == 6
    all_except_root = list(alternate_path)[1:]

    ((_key, _value), ) = plain_root.get_all_leaves().items()
    assert _key is alternate_path[-1]
    assert _value['nodes_distance'] == 5
    assert 'clock_distance' in _value  # Can't know the value of that.

    block = all_except_root[0].block
    assert isinstance(block, garlicsim.data_structures.Block)
    for node in all_except_root:
        assert isinstance(node, garlicsim.data_structures.Node)
        assert node.block is node.soft_get_block() is block
        nose.tools.assert_raises(garlicsim.data_structures.NodeError,
                                 node.finalize)
        assert node.get_root() is plain_root
        assert node.get_ancestor(generations=0) is node
        assert node.get_ancestor(generations=infinity, round=True) is \
            plain_root
        nose.tools.assert_raises(
            garlicsim.data_structures.node.NodeLookupError,
            lambda: node.get_ancestor(generations=infinity, round=False))
        nose.tools.assert_raises(
            garlicsim.data_structures.node.NodeLookupError,
            lambda: node.get_ancestor(generations=100, round=False))
        if node.is_last_on_block():
            assert block[-1] is node
            assert node.get_ancestor(generations=2, round=False) is \
                block[-3]
            assert node.get_ancestor(generations=1, round=True) is \
                block[-2] is node.parent
        if node.is_first_on_block():
            assert block[0] is node

    assert set(all_except_root) == set(block)

    second_on_block = block[1]
    second_to_last_on_block = block[-2]
    assert second_to_last_on_block.state.clock > second_on_block.state.clock
    assert list(
        alternate_path.iterate_blockwise(
            second_on_block, second_to_last_on_block)) == list(block[1:-1])
    assert list(
        alternate_path.iterate_blockwise_reversed(
            second_on_block, second_to_last_on_block)) == list(block[-2:0:-1])

    ### Testing path methods: #################################################
    #                                                                         #

    empty_path = garlicsim.data_structures.Path(project.tree)
    assert len(empty_path) == 0
    assert list(empty_path) == []
    assert list(reversed(empty_path)) == []
    assert list(empty_path.iterate_blockwise()) == []
    assert list(empty_path.iterate_blockwise_reversed()) == []

    for (path, other_path) in [(path_1, path_2), (path_2, path_1)]:
        assert isinstance(path, garlicsim.data_structures.Path)
        assert path[-1] is path.get_last_node()
        node_list = list(path)
        reversed_node_list = list(reversed(path))
        assert node_list == list(reversed(reversed_node_list))
        assert list(path.iterate_blockwise()) == \
            list(reversed(list(path.iterate_blockwise_reversed(tail=path[-1]))))
        stranger_node = other_path[-1]
        assert stranger_node not in path
        nose.tools.assert_raises(
            garlicsim.data_structures.path.TailNotReached,
            lambda: list(path.__iter__(tail=stranger_node)))

    #                                                                         #
    ### Finished testing path methods. ########################################

    if simpack.State.create_messy_root is not None:
        messy_root = project.create_messy_root()
        assert len(project.tree.roots) == 3
        assert messy_root is project.tree.roots[-1]
        assert isinstance(messy_root.state, simpack.State)