-
Notifications
You must be signed in to change notification settings - Fork 37
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
[CX_HARDENING] Enhance DA Task Test Coverage #3568
base: main
Are you sure you want to change the base?
[CX_HARDENING] Enhance DA Task Test Coverage #3568
Conversation
- Test outdated proposal handling - Verify duplicate vote detection - Validate vote collection and processing - Ensure correct DA vote handling by non-leader nodes Signed-off-by: shamb0 <[email protected]>
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Great first step, and thank you for doing this! Big ticket items are the following:
- Let's just put all the da tests in the existing test file instead of its own module
- Let's avoid spawning a custom handler for this test until, as a team, we're ready to refactor the entire test suite to use a more lean handler. If you want a more lean test handler without forcing a rewrite of the tests themselves, just change the
build_system_handler
helper method to callSystemContext::new
instead ofinit
, and that should get us 90% of what you've done here. If that works without needing to add all this new behavior, that'd be a big win. - Let's try to avoid handling external events since they nearly-always get turned into internal events anyway. A good place to look is
network.rs
or, broadly, the network task.
crates/hotshot/src/lib.rs
Outdated
@@ -639,6 +639,31 @@ impl<TYPES: NodeType, I: NodeImplementation<TYPES>, V: Versions> SystemContext<T | |||
} | |||
} | |||
|
|||
#[cfg(feature = "hotshot-testing")] | |||
impl<TYPES: NodeType, I: NodeImplementation<TYPES>, V: Versions> SystemContext<TYPES, I, V> { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think we can just add this to the existing trait impl and enable the method when testing is enabled instead of doing separate bespoke impl.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think this should actually just go in testing/src/helpers.rs
(ungated), next to build_system_handle
(which is what we use currently in the tests). I'd call it build_inactive_handle
or something (I think "lean" is slightly misleading, because it's just a dummy handle that isn't running anything).
I made an issue a while ago to do something like this for the non-integration tests (all the task-specific tests in tests_1
), so I think this is good to have in general
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Good One @ss-es, I wanted to acknowledge the suggestion to place the test-specific helper function in testing/src/helpers.rs
. During my implementation, I encountered issues due to the private and public(crate) visibility of dependent fields in pub struct SystemContext<> and pub struct SystemContextHandle<>. To avoid modifying the existing visibility of these fields, I opted for an alternative approach.
/// create the [`SystemContextHandle`] from a launcher | ||
/// # Panics | ||
/// if cannot create a [`HotShotInitializer`] | ||
pub async fn build_system_handle_from_launcher< |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'm hesitant to make such a specific change for the tests in this case, especially since you have them working and debugging is not as big of an issue at this point. While it's not ideal to spin up the entire SystemContext for unit tests, this method unfortunately creates a rift in what is the accepted testing framework, and what is done here. If we made this change, we'd want to propagate it to all tests, lest we end up in the situation where specific knowledge of this specific suite rests solely with someone who is not on the team.
I am not opposed to the outright removal of this in theory, though I think for this PR, we should stick to the existing spawner.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@jparr721, I understand your concerns about consistency in our testing framework. To clarify, the existing hotshot-testing::helpers::build_system_handle()
function remains unchanged, and all current test cases continue to work as expected.
The new API, hotshot-testing::helpers::build_system_handle_from_launcher()
, was added to address issue #3160, which requires 'Permute the inputs and verify if the tests still pass.'. While build_system_handle()
uses default test configuration parameters, the new function provides flexibility by allowing modifications to the setup.
I suggest we review its usage in the test scenarios. If it doesn’t add significant value, we can consider removing it. Specifically,
- Validating vote collection and processing.
- Ensuring non-leader nodes correctly handle DA votes.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Why not just use the random!
macro to get permuted inputs in that case? Furthermore, we do handle the vote collection and DA votes within the integration tests (e.g. test_success
), so spinning up additional nodes for those might not be explicitly necessary.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thank you, @jparr721, for your suggestion. I agree that utilizing random!() could be an effective way to introduce fuzziness in test configuration parameters. I will explore this approach and provide an update on the outcome.
crates/testing/src/helpers.rs
Outdated
@@ -393,3 +538,40 @@ pub fn build_fake_view_with_leaf_and_state( | |||
}, | |||
} | |||
} | |||
|
|||
pub async fn check_external_events<TYPES: NodeType, S: StreamExt<Item = Event<TYPES>> + Unpin>( |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Curious as to what this is doing that isn't handled by the testing macro?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@jparr721, I introduced a new function, fn check_external_events()
, to validate events from the external event stream. This function provides additional validation that complements the existing testing macro. I've also created a simplified block diagram to illustrate its role within the TaskState
validation context.
Note:: The dotted boxes labeled 'network layer' and 'external service layer' are not relevant to the 'TaskState' validation context.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
See remark below. This is not necessary since the network task will transform the raw event into a HotShot event, so the checks will be redundant.
@@ -0,0 +1,3 @@ | |||
mod tests_cx_hardening { | |||
automod::dir!("tests/tests_cx_hardening"); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think tests_cx_hardening
would make a task namespace into a first-class feature of the codebase, muddying the circumstances for when we should change them. Instead, let's just add these under the existing da task tests and remove this special file.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
+1 to just throw this into one of the test groups
let external_event_expectations = vec![expect_external_events(vec![ext_event_exact(Event { | ||
view_number: view3.view_number, | ||
event: EventType::DaProposal { | ||
proposal: view3.da_proposal.clone(), | ||
sender: view3.leader_public_key, | ||
}, | ||
})])]; | ||
|
||
// Create DA task state and script for the test | ||
let da_state = DaTaskState::<TestTypes, MemoryImpl>::create_from(&handle).await; | ||
let mut da_script = TaskScript { | ||
timeout: Duration::from_millis(100), | ||
state: da_state, | ||
expectations, | ||
}; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I don't think we need these external event handlers as the DaProposal
event is transformed into DaProposalRecv
in the downstream handlers.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Related to the comment, #3568 (comment)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think I still feel strongly that we don't necessarily need to process the external events. If the event is transformed successfully into a, for example, DaProposalRecv
event, then we know with certainty that the external event was received, so we don't need to handle this stream in that case. To avoid bespoke changes, I'd prefer to remove it since the checks are redundant under this circumstance.
crates/types/src/event.rs
Outdated
impl<TYPES: NodeType> Eq for EventType<TYPES> {} | ||
|
||
impl<TYPES: NodeType> PartialEq for EventType<TYPES> { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This might be a bit overkill if the above external event changes are removed. If we cannot derive Eq and PartialEq here, perhaps we should consider fixing the types within EventType to do so instead, that way we can avoid arduously maintaining this for a yet-unneeded change.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
+1 this should be a #derive
. I think you might need to derive Eq
and/or PartialEq
for a few types, but I don't think that should be an issue
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@jparr721, @ss-es, I agree that it’s not an ideal solution. My initial approach was to add #[derive(Eq, PartialEq)]
annotations to the dependent inner types. However, this would have required modifying a significant number of files, so I considered handling it in a separate PR to reduce the review effort.
Please let me know if you prefer that I include these changes in this PR or if it would be better to address them in a separate PR.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think I'm just strongly opposed to a custom Eq
or PartialEq
implementation.
But after looking over the PR some more, I'm not sure if any of this is really that necessary; I think I agree with @jparr721 that the external event checking could just be removed altogether.
We might have to discuss internally about whether we want to test this (and to what extent), but I think I would just split this off from the PR
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Done @ss-es, I have completed the requested changes. Specifically, I removed the modifications related to 'external event checking' from this pull request.
Signed-off-by: shamb0 <[email protected]>
…DATask-test-coverage
Signed-off-by: shamb0 <[email protected]> [Libp2p] DHT overhaul (EspressoSystems#3548) Update builder marketplace API (EspressoSystems#3573) Fix BuilderDataSource for marketplace builder (EspressoSystems#3576) * Fix BuilderDataSource for marketplace builder Batch dependabot PRs (EspressoSystems#3570) Bump serde_json in the all group across 1 directory (EspressoSystems#3579) Fix upgrade lock in network task (EspressoSystems#3580) Bump the all group with 2 updates (EspressoSystems#3582) merge to upstream main Signed-off-by: shamb0 <[email protected]> Refactor: Address review comments Signed-off-by: shamb0 <[email protected]>
11f1190
to
02a3d4d
Compare
…DATask-test-coverage
This PR:
This PR partially addresses issue #3160 by adding test cases for the following scenarios:
Key Changes
crates/testing/tests/tests_cx_hardening/cxh_da_task.rs
.create_lean_test_handle()
function to create a lightweight system handle for task state testing.build_da_cert<>
function located inHotShot/crates/testing/src/helpers.rs
.output_event_stream
.This PR does not:
Key Areas to Review: