-
Notifications
You must be signed in to change notification settings - Fork 4.5k
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
program-test: Expose bank task to fix fuzzing #14908
Conversation
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 like the direction. We needed a place to hook up a clock/slot manipulation interface and this provides such a location
program-test/src/lib.rs
Outdated
} | ||
|
||
impl ProgramTestState { | ||
pub fn new( |
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 limit scope here
pub fn new( | |
fn new( |
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 call, I was thinking someone might want to hack on it from the outside, but this'll be safer
program-test/src/lib.rs
Outdated
} | ||
} | ||
|
||
pub struct ProgramTestState { |
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.
nit: I think I fancy "context" more:
pub struct ProgramTestState { | |
pub struct ProgramTestContext { |
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.
Works for me!
program-test/src/lib.rs
Outdated
@@ -539,7 +583,7 @@ impl ProgramTest { | |||
/// | |||
/// Returns a `BanksClient` interface into the test environment as well as a payer `Keypair` | |||
/// with SOL for sending transactions | |||
pub async fn start(self) -> (BanksClient, Keypair, Hash) { | |||
pub async fn start(self) -> ProgramTestState { |
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 definitely concerned about changing this signature and blowing up existing users. I think we need to keep it for existing users and future users that just want to keep it simple.
Some ideas for a new method name for this signature:
enter()
-- you enter the ProgramTextContextrun()
-- confusing, do I "start" or "run"start_with_context()
-- maybe my favourite of the three, consistent withstart()
and the Rust norms of adding "with" methods that enhance the functionality of the base method
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.
Ok no problem, I'll add start_with_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.
nice work
program-test/src/lib.rs
Outdated
// are required when sending multiple otherwise identical transactions in series from a | ||
// test | ||
let target_tick_duration = genesis_config.poh_config.target_tick_duration; | ||
let (tx, mut rx) = mpsc::channel(1); |
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.
let (tx, mut rx) = mpsc::channel(1); | |
let (sender, mut receiver) = mpsc::channel(1); |
🙏🏼. Most people unfortunately like to use tx to mean transaction in the code base, except when it means something else like in this case
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.
Ah, right, on it switching to AtomicBool
program-test/src/lib.rs
Outdated
tx, | ||
tokio::spawn(async move { | ||
loop { | ||
if rx.try_recv().is_ok() { |
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.
An AtomicBool is generally used in other parts of the code for this kind of exit pattern. I'm not opposed to a channel if you want to keep it though.
Here's one example of using the atomic bool:
if exit.load(Ordering::Relaxed) { |
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.
That was actually my initial approach, but then I thought a message would be clearer. I'll change it to an AtomicBool to keep things consistent in the codebase
Codecov Report
@@ Coverage Diff @@
## master #14908 +/- ##
=========================================
- Coverage 79.9% 79.8% -0.1%
=========================================
Files 401 401
Lines 100698 100781 +83
=========================================
- Hits 80531 80503 -28
- Misses 20167 20278 +111 |
* program-test: Expose bank task to fix fuzzing * Run cargo fmt and clippy * Remove unnecessary print in test * Review feedback * Transition to AtomicBool (cherry picked from commit 0ce0827)
* program-test: Expose bank task to fix fuzzing * Run cargo fmt and clippy * Remove unnecessary print in test * Review feedback * Transition to AtomicBool (cherry picked from commit 0ce0827) Co-authored-by: Jon Cinque <[email protected]>
Problem
Program-test creates a running task to register ticks on the bank, but does not expose this task. For most cases, this works great, but in a fuzzing environment, not closing the thread properly blows up
/tmp
with all sorts of directories like/tmp/.tmp0000
, perhaps related to rocksdb? I'm not too familiar with that side of it.Summary of Changes
Expose the running task on the bank through a new return type,
ProgramTestState
, and allow it to be stopped ondrop
. This changes the API onProgramTest.start()
, which seems reasonable considering most of these are tests users. If needed, I can spin off a new / old function and mark this as deprecated.One thing to note is that we can't simply destructure this as:
Because the task gets dropped at that point.
The other nice part of this approach is that we can start to support a lot of functions that have been asked for by devs. My next idea is to add a
warp_to_slot
onProgramTestState
. We'll just need to keep track of theBankForks
and useBank::warp_from_parent
.This approach gets much more consistent performance from fuzzing as well. For the test, we can't easily use the
fuzz!
macro because then we need to build withcargo hfuzz build
, so instead it's simulating what a fuzz run would look like with arbitrary&[u8]
data.Fixes #14707