Unhappy path base test assertions (#14)

* Unhappy path tests replacing timeout msgs with NewView. Also revising the conditions to enter into the unhappy path.

* Unhappy path tests assertions.

* Fix assertions on test

* Cleanup

---------

Co-authored-by: mjalalzai <33738574+MForensic@users.noreply.github.com>
This commit is contained in:
Daniel Sanchez 2023-04-11 11:57:31 +02:00 committed by GitHub
parent 3a598b23eb
commit caea1b4116
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
4 changed files with 34 additions and 29 deletions

View File

View File

@ -448,9 +448,10 @@ class Carnot:
necessary to reconstruct the new overlay
"""
assert len(msgs) == self.overlay.leader_super_majority_threshold(self.id)
assert all(msg.view >= self.current_view for msg in msgs)
# The checks below are performed in is_safe_to_timeout().
# assert all(msg.view >= self.current_view for msg in msgs)
# assert self.current_view > max(self.highest_voted_view - 1, self.local_high_qc.view)
assert len(set(msg.view for msg in msgs)) == 1
assert self.current_view > max(self.highest_voted_view - 1, self.local_high_qc.view)
assert self.overlay.is_member_of_root_committee(self.id)
timeout_qc = self.build_timeout_qc(msgs, self.id)
@ -465,16 +466,19 @@ class Carnot:
self.rebuild_overlay_from_timeout_qc(timeout_qc)
self.broadcast(timeout_qc) # we broadcast so all nodes can get ready for voting on a new view
def approve_new_view(self, timeouts: Set[NewView]):
def approve_new_view(self, new_views: Set[NewView]):
assert not self.overlay.is_member_of_leaf_committee(self.id)
assert len(set(timeout.view for timeout in timeouts)) == 1
assert all(timeout.view >= self.current_view for timeout in timeouts)
assert all(timeout.view == timeout.timeout_qc.view for timeout in timeouts)
assert len(timeouts) == self.overlay.super_majority_threshold(self.id)
assert all(self.overlay.is_member_of_child_committee(self.id, timeout.sender) for timeout in timeouts)
assert len(set(new_view.view for new_view in new_views)) == 1
# newView.view == self.last_timeout_view_qc.view for member of root committee and its children because
# they have already created the timeout_qc. For other nodes newView.view > self.last_timeout_view_qc.view.
if self.last_timeout_view_qc is not None:
assert all(new_view.view >= self.last_timeout_view_qc.view for new_view in new_views)
assert all(new_view.view == new_view.timeout_qc.view for new_view in new_views)
assert len(new_views) == self.overlay.super_majority_threshold(self.id)
assert all(self.overlay.is_member_of_child_committee(self.id, new_view.sender) for new_view in new_views)
timeouts = list(timeouts)
timeout_qc = timeouts[0].timeout_qc
new_views = list(new_views)
timeout_qc = new_views[0].timeout_qc
new_high_qc = timeout_qc.high_qc
self.rebuild_overlay_from_timeout_qc(timeout_qc)
@ -513,16 +517,17 @@ class Carnot:
if self.highest_voted_view < self.current_view:
self.increment_voted_view(timeout_qc.view)
# Just a suggestion that received_timeout_qc can be reused by each node when the process timeout_qc of the NewView msg.
def received_timeout_qc(self, timeout_qc: TimeoutQc):
assert timeout_qc.view >= self.current_view
# assert timeout_qc.view >= self.current_view
new_high_qc = timeout_qc.high_qc
if new_high_qc.view > self.local_high_qc.view:
self.update_high_qc(new_high_qc)
self.update_timeout_qc(timeout_qc)
if not self.is_safe_to_timeout():
return
self.rebuild_overlay_from_timeout_qc(timeout_qc)
if self.overlay.is_member_of_leaf_committee(self.id):
new_high_qc = timeout_qc.high_qc
if new_high_qc.view >= self.local_high_qc.view:
self.update_high_qc(new_high_qc)
self.update_timeout_qc(timeout_qc)
timeout_msg = NewView(
view=self.current_view,
high_qc=self.local_high_qc,
@ -539,7 +544,8 @@ class Carnot:
assert timeout_qc.view >= self.current_view
self.overlay = Overlay()
def build_timeout_qc(self, msgs: Set[Timeout], sender: Id) -> TimeoutQc:
@staticmethod
def build_timeout_qc(msgs: Set[Timeout], sender: Id) -> TimeoutQc:
msgs = list(msgs)
return TimeoutQc(
view=msgs[0].view,
@ -602,5 +608,3 @@ class Carnot:
if __name__ == "__main__":
pass

View File

@ -1,4 +1,4 @@
from .carnot import *
from carnot import *
from unittest import TestCase

View File

@ -1,5 +1,6 @@
from unittest import TestCase
from .carnot import *
from unittest import TestCase
# Unhappy path tests
@ -67,6 +68,7 @@ class TestCarnotHappyPath(TestCase):
34
"""
def __init__(self):
self.parents = {
int_to_id(1): int_to_id(0),
@ -126,7 +128,6 @@ class TestCarnotHappyPath(TestCase):
}
return thresholds.get(_id, 0)
nodes = {int_to_id(i): MockCarnot(int_to_id(i)) for i in range(5)}
overlay = MockOverlay()
# add overlay
@ -183,9 +184,9 @@ class TestCarnotHappyPath(TestCase):
leader.propose_block(2, [root_new_view, new_view_1, new_view_leaf_2])
# Add final assertions on nodes
new_block_1 = leader.latest_event
self.assertEqual(new_block_1.view, 2)
self.assertEqual(new_block_1.qc.view, 1)
self.assertEqual(leader.last_timeout_view_qc.view, 1)
self.assertEqual(leader.local_high_qc.view, 0)
self.assertEqual(leader.highest_voted_view, 1)