def test_new_view_combinations(random): # Create pool in some random initial state pool, _ = some_pool(random) quorums = pool.nodes[0]._data.quorums # Get view change votes from all nodes view_change_messages = [] for node in pool.nodes: network = MockNetwork() node._view_changer._network = network node._view_changer._bus.send(NeedViewChange()) view_change_messages.append(network.sent_messages[0][0]) # Check that all committed requests are present in final batches for _ in range(10): num_votes = quorums.strong.value votes = random.sample(view_change_messages, num_votes) cp = pool.nodes[0]._view_changer._new_view_builder.calc_checkpoint(votes) assert cp is not None batches = pool.nodes[0]._view_changer._new_view_builder.calc_batches(cp, votes) committed = calc_committed(votes) committed = [c for c in committed if c.pp_seq_no > cp.seqNoEnd] assert batches is not None assert committed == batches[:len(committed)]
def check_view_change_completes_under_normal_conditions(random: SimRandom): # Create random pool with random initial state pool, committed = some_pool(random) # Schedule view change at different time on all nodes for node in pool.nodes: pool.timer.schedule( random.integer(0, 10000), partial(node._view_changer.process_need_view_change, NeedViewChange())) # Make sure all nodes complete view change pool.timer.wait_for(lambda: all(not node._data.waiting_for_new_view and node._data.view_no > 0 for node in pool.nodes)) # Make sure all nodes end up in same state for node_a, node_b in zip(pool.nodes, pool.nodes[1:]): assert node_a._data.view_no == node_b._data.view_no assert node_a._data.primary_name == node_b._data.primary_name assert node_a._data.stable_checkpoint == node_b._data.stable_checkpoint assert node_a._data.preprepared == node_b._data.preprepared # Make sure that all committed reqs are ordered with the same ppSeqNo in the new view: stable_checkpoint = pool.nodes[0]._data.stable_checkpoint committed = [c for c in committed if c.pp_seq_no > stable_checkpoint] for n in pool.nodes: assert committed == n._data.preprepared[:len(committed)]
def test_view_change_permutations(random_random): # Create pool in some random initial state pool, _ = some_pool(random_random) quorums = pool.nodes[0]._data.quorums # Get view change votes from all nodes view_change_messages = [] for node in pool.nodes: network = MockNetwork() node._view_changer._network = network node._view_changer._bus.send(NeedViewChange()) view_change_messages.append(network.sent_messages[0][0]) # Select random number of view change votes num_view_changes = random_random.integer(quorums.view_change.value, quorums.n) view_change_messages = random_random.sample(view_change_messages, num_view_changes) # Check that all committed requests are present in final batches new_view_builder = pool.nodes[0]._view_changer._new_view_builder cps = { new_view_builder.calc_checkpoint( random_random.shuffle(view_change_messages)) for _ in range(10) } assert len(cps) == 1
def check_view_change_completes_under_normal_conditions( random: SimRandom, min_latency, max_latency, filtered_msg_types, filter_probability): # PREPARE # 1. Create random pool with random initial state pool, committed = some_pool(random) N = pool.size F = (N - 1) // 3 # 2. set latency pool.network.set_latency(min_latency, max_latency) # 3. set filter pool.network.set_filter([getNodeName(pool.nodes[-1].name)], filtered_msg_types, filter_probability) # EXECUTE # Schedule view change at different time on all nodes for node in pool.nodes: pool.timer.schedule( random.integer(0, 10000), partial(node._view_changer.process_need_view_change, NeedViewChange())) # CHECK # 1. Make sure all nodes complete view change pool.timer.wait_for(lambda: all(not node._data.waiting_for_new_view and node._data.view_no > 0 for node in pool.nodes)) # 2. check that equal stable checkpoint is set on at least N-F nodes (F nodes may lag behind and will catchup) stable_checkpoints = [n._data.stable_checkpoint for n in pool.nodes] most_freq_stable_ckeckpoint = Counter(stable_checkpoints).most_common(1) stable_checkpoint = most_freq_stable_ckeckpoint[0][0] assert most_freq_stable_ckeckpoint[0][1] >= N - F # 3. check that equal preprepares is set on all node with the found stable checkpoint preprepares = set() for n in pool.nodes: if n._data.stable_checkpoint >= stable_checkpoint: preprepares.add(tuple(n._data.preprepared)) assert len(preprepares) == 1 # 4. Make sure all nodes end up in same view for node_a, node_b in zip(pool.nodes, pool.nodes[1:]): assert node_a._data.view_no == node_b._data.view_no assert node_a._data.primary_name == node_b._data.primary_name # 5. Make sure that all committed reqs are ordered with the same ppSeqNo in the new view: committed_above_cp = [ c for c in committed if c.pp_seq_no > stable_checkpoint ] for n in pool.nodes: if n._data.stable_checkpoint >= stable_checkpoint: assert committed_above_cp == n._data.preprepared[:len( committed_above_cp)]
def pool_committed(new_random): pool, committed = some_pool(new_random) return pool, committed