Skip to content

Commit

Permalink
tests: add unit tests
Browse files Browse the repository at this point in the history
  • Loading branch information
hugocaillard committed Sep 24, 2024
1 parent b35e449 commit 4b1499d
Show file tree
Hide file tree
Showing 4 changed files with 207 additions and 53 deletions.
2 changes: 1 addition & 1 deletion Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

24 changes: 16 additions & 8 deletions components/clarity-repl/src/repl/datastore.rs
Original file line number Diff line number Diff line change
Expand Up @@ -504,16 +504,25 @@ impl Datastore {
clarity_datastore
.height_at_chain_tip
.insert(id, self.stacks_chain_height);
clarity_datastore.open_chain_tip = height_to_id(self.stacks_chain_height);
clarity_datastore.current_chain_tip = clarity_datastore.open_chain_tip;
}

clarity_datastore.open_chain_tip = height_to_id(self.stacks_chain_height);
clarity_datastore.current_chain_tip = clarity_datastore.open_chain_tip;
self.stacks_chain_height
}

pub fn set_current_epoch(&mut self, epoch: StacksEpochId) {
pub fn set_current_epoch(
&mut self,
clarity_datastore: &mut ClarityDatastore,
epoch: StacksEpochId,
) {
self.current_epoch = epoch;
self.current_epoch_start_height = self.stacks_chain_height;
if epoch >= StacksEpochId::Epoch30 {
// ideally the burn chain tip should be advanced for each new epoch
// but this would introduce breaking changes to existing 2.x tests
self.advance_burn_chain_tip(clarity_datastore, 1);
}
}
}

Expand All @@ -532,11 +541,9 @@ impl HeadersDB for Datastore {
&self,
id_bhh: &StacksBlockId,
) -> Option<BurnchainHeaderHash> {
let hash = self
.stacks_blocks
self.stacks_blocks
.get(id_bhh)
.map(|block| block.burn_block_header_hash);
hash
.map(|block| block.burn_block_header_hash)
}

fn get_consensus_hash_for_block(
Expand Down Expand Up @@ -761,8 +768,9 @@ mod tests {
#[test]
fn test_set_current_epoch() {
let mut datastore = Datastore::default();
let mut clarity_datastore = ClarityDatastore::new();
let epoch_id = StacksEpochId::Epoch25;
datastore.set_current_epoch(epoch_id);
datastore.set_current_epoch(&mut clarity_datastore, epoch_id);
assert_eq!(datastore.current_epoch, epoch_id);
}

Expand Down
190 changes: 175 additions & 15 deletions components/clarity-repl/src/repl/interpreter.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1092,7 +1092,8 @@ impl ClarityInterpreter {
}

pub fn set_current_epoch(&mut self, epoch: StacksEpochId) {
self.datastore.set_current_epoch(epoch);
self.datastore
.set_current_epoch(&mut self.clarity_datastore, epoch);
}

pub fn advance_burn_chain_tip(&mut self, count: u32) -> u32 {
Expand Down Expand Up @@ -1238,6 +1239,24 @@ mod tests {
assert_eq!(result.result, expected_value);
}

#[track_caller]
fn run_snippet(
interpreter: &mut ClarityInterpreter,
snippet: &str,
clarity_version: ClarityVersion,
) -> Value {
let contract = ClarityContractBuilder::new()
.code_source(snippet.to_string())
.epoch(interpreter.datastore.get_current_epoch())
.clarity_version(clarity_version)
.build();
let deploy_result = deploy_contract(interpreter, &contract);
match deploy_result.unwrap().result {
EvaluationResult::Contract(_) => unreachable!(),
EvaluationResult::Snippet(res) => res.result,
}
}

#[test]
fn test_get_tx_sender() {
let mut interpreter =
Expand Down Expand Up @@ -1277,9 +1296,7 @@ mod tests {
fn test_advance_stacks_chain_tip_pre_epoch_3() {
let mut interpreter =
ClarityInterpreter::new(StandardPrincipalData::transient(), Settings::default());
interpreter
.datastore
.set_current_epoch(StacksEpochId::Epoch2_05);
interpreter.set_current_epoch(StacksEpochId::Epoch2_05);
let count = 5;
let initial_block_height = interpreter.get_burn_block_height();
assert_ne!(interpreter.advance_stacks_chain_tip(count), Ok(count));
Expand All @@ -1296,14 +1313,13 @@ mod tests {
};
let mut interpreter =
ClarityInterpreter::new(StandardPrincipalData::transient(), wasm_settings);
interpreter
.datastore
.set_current_epoch(StacksEpochId::Epoch30);
interpreter.set_current_epoch(StacksEpochId::Epoch30);
interpreter.advance_burn_chain_tip(1);
let count = 5;
let initial_block_height = interpreter.get_burn_block_height();
let initial_block_height = interpreter.get_block_height();

let result = interpreter.advance_stacks_chain_tip(count);
assert_eq!(result, Ok(count));
assert_eq!(result, Ok(initial_block_height + count));

assert_eq!(interpreter.get_burn_block_height(), initial_block_height);
assert_eq!(interpreter.get_block_height(), initial_block_height + count);
Expand All @@ -1313,9 +1329,7 @@ mod tests {
fn test_advance_chain_tip_pre_epoch3() {
let mut interpreter =
ClarityInterpreter::new(StandardPrincipalData::transient(), Settings::default());
interpreter
.datastore
.set_current_epoch(StacksEpochId::Epoch2_05);
interpreter.set_current_epoch(StacksEpochId::Epoch2_05);
let count = 5;
let initial_block_height = interpreter.get_block_height();
interpreter.advance_burn_chain_tip(count);
Expand All @@ -1330,9 +1344,7 @@ mod tests {
fn test_advance_chain_tip() {
let mut interpreter =
ClarityInterpreter::new(StandardPrincipalData::transient(), Settings::default());
interpreter
.datastore
.set_current_epoch(StacksEpochId::Epoch30);
interpreter.set_current_epoch(StacksEpochId::Epoch30);
let count = 5;
let initial_block_height = interpreter.get_block_height();
interpreter.advance_burn_chain_tip(count);
Expand Down Expand Up @@ -1973,6 +1985,154 @@ mod tests {
assert!(interpreter.run(&call_contract, None, false, None).is_ok());
}

#[test]
fn burn_block_time_is_realistic_in_epoch_3_0() {
let mut interpreter =
ClarityInterpreter::new(StandardPrincipalData::transient(), Settings::default());

interpreter.set_current_epoch(StacksEpochId::Epoch30);
interpreter.advance_burn_chain_tip(3);

let snippet_1 = run_snippet(
&mut interpreter,
"(get-tenure-info? time u2)",
ClarityVersion::Clarity3,
);
let time_block_1 = match snippet_1.expect_optional() {
Ok(Some(Value::UInt(time))) => time,
_ => panic!("Unexpected result"),
};

let snippet_2 = run_snippet(
&mut interpreter,
"(get-tenure-info? time u3)",
ClarityVersion::Clarity3,
);
let time_block_2 = match snippet_2.expect_optional() {
Ok(Some(Value::UInt(time))) => time,
_ => panic!("Unexpected result"),
};
assert_eq!(time_block_2 - time_block_1, 600);
}

#[test]
fn first_stacks_block_time_in_a_tenure() {
let mut interpreter =
ClarityInterpreter::new(StandardPrincipalData::transient(), Settings::default());

interpreter.set_current_epoch(StacksEpochId::Epoch30);
let _ = interpreter.advance_burn_chain_tip(2);

let snippet_1 = run_snippet(
&mut interpreter,
"(get-tenure-info? time (- stacks-block-height u1))",
ClarityVersion::Clarity3,
);
let last_tenure_time = match snippet_1.expect_optional() {
Ok(Some(Value::UInt(time))) => time,
_ => panic!("Unexpected result"),
};

let snippet_2 = run_snippet(
&mut interpreter,
"(get-stacks-block-info? time (- stacks-block-height u1))",
ClarityVersion::Clarity3,
);
let last_stacks_block_time = match snippet_2.expect_optional() {
Ok(Some(Value::UInt(time))) => time,
_ => panic!("Unexpected result"),
};
assert_eq!((last_stacks_block_time) - (last_tenure_time), 10);
}

#[test]
fn stacks_block_time_is_realistic_in_epoch_3_0() {
let mut interpreter =
ClarityInterpreter::new(StandardPrincipalData::transient(), Settings::default());

interpreter.set_current_epoch(StacksEpochId::Epoch30);
let _ = interpreter.advance_stacks_chain_tip(3);

let snippet_1 = run_snippet(
&mut interpreter,
"(get-stacks-block-info? time u2)",
ClarityVersion::Clarity3,
);
let time_block_1 = match snippet_1.expect_optional() {
Ok(Some(Value::UInt(time))) => time,
_ => panic!("Unexpected result"),
};

let snippet_2 = run_snippet(
&mut interpreter,
"(get-stacks-block-info? time u3)",
ClarityVersion::Clarity3,
);
let time_block_2 = match snippet_2.expect_optional() {
Ok(Some(Value::UInt(time))) => time,
_ => panic!("Unexpected result"),
};
assert_eq!(time_block_2 - time_block_1, 10);
}

#[test]
fn burn_block_time_after_many_stacks_blocks_is_realistic_in_epoch_3_0() {
let mut interpreter =
ClarityInterpreter::new(StandardPrincipalData::transient(), Settings::default());

interpreter.set_current_epoch(StacksEpochId::Epoch30);
// by advancing stacks_chain_tip by 101, we are getting a tenure of more than 600 seconds
// the next burn block should happen after the last stacks block
let stacks_block_height = interpreter.advance_stacks_chain_tip(101).unwrap();
assert_eq!(stacks_block_height, 102);

let snippet_1 = run_snippet(
&mut interpreter,
"(get-stacks-block-info? time u1)",
ClarityVersion::Clarity3,
);
let stacks_block_time_1 = match snippet_1.expect_optional() {
Ok(Some(Value::UInt(time))) => time,
_ => panic!("Unexpected result"),
};

let snippet_2 = run_snippet(
&mut interpreter,
"(get-stacks-block-info? time u101)",
ClarityVersion::Clarity3,
);
let stacks_block_time_2 = match snippet_2.expect_optional() {
Ok(Some(Value::UInt(time))) => time,
_ => panic!("Unexpected result"),
};
assert_eq!(stacks_block_time_2 - stacks_block_time_1, 1000);

let _ = interpreter.advance_burn_chain_tip(1);
let _ = interpreter.advance_stacks_chain_tip(1);

let snippet_3 = run_snippet(
&mut interpreter,
"(get-tenure-info? time u4)",
ClarityVersion::Clarity3,
);
let tenure_height_1 = match snippet_3.expect_optional() {
Ok(Some(Value::UInt(time))) => time,
_ => panic!("Unexpected result"),
};

let snippet_4 = run_snippet(
&mut interpreter,
"(get-tenure-info? time (- stacks-block-height u1))",
ClarityVersion::Clarity3,
);
let tenure_height_2 = match snippet_4.expect_optional() {
Ok(Some(Value::UInt(time))) => time,
_ => panic!("Unexpected result"),
};

assert_eq!(1030, tenure_height_2 - tenure_height_1);
}

#[test]
fn can_call_a_public_function() {
let mut interpreter =
Expand Down
44 changes: 15 additions & 29 deletions components/clarity-repl/src/repl/session.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1394,7 +1394,7 @@ mod tests {
session.handle_command("::set_epoch 3.0");
let _ = session.handle_command("::advance_stacks_chain_tip 1");
let new_height = session.handle_command("::get_stacks_block_height");
assert_eq!(new_height, "Current height: 1");
assert_eq!(new_height, "Current height: 2");
}

#[test]
Expand Down Expand Up @@ -1426,24 +1426,25 @@ mod tests {
let result = session.handle_command("::advance_burn_chain_tip 1");
assert_eq!(
result,
"new burn height: 1\nnew stacks height: 1"
"new burn height: 2\nnew stacks height: 2"
.to_string()
.green()
.to_string()
);
let new_height = session.handle_command("::get_stacks_block_height");
assert_eq!(new_height, "Current height: 1");
assert_eq!(new_height, "Current height: 2");
// advance_chain_tip will only affect stacks height in epoch 3 or greater
let _ = session.handle_command("::advance_chain_tip 1");
let new_height = session.handle_command("::get_stacks_block_height");
assert_eq!(new_height, "Current height: 2");
assert_eq!(new_height, "Current height: 3");
let new_height = session.handle_command("::get_burn_block_height");
assert_eq!(new_height, "Current height: 1");
assert_eq!(new_height, "Current height: 2");
}

#[test]
fn set_epoch_command() {
let mut session = Session::new(SessionSettings::default());
let initial_block_height = session.interpreter.get_block_height();
let initial_epoch = session.handle_command("::get_epoch");
// initial epoch is 2.05
assert_eq!(initial_epoch, "Current epoch: 2.05");
Expand All @@ -1459,9 +1460,18 @@ mod tests {
let current_epoch = session.handle_command("::get_epoch");
assert_eq!(current_epoch, "Current epoch: 2.4");

// changing epoch in 2.x does not impact the block height
assert_eq!(session.interpreter.get_block_height(), initial_block_height);

session.handle_command("::set_epoch 3.0");
let current_epoch = session.handle_command("::get_epoch");
assert_eq!(current_epoch, "Current epoch: 3.0");

// changing epoch in 3.x increments the block height
assert_eq!(
session.interpreter.get_block_height(),
initial_block_height + 1
);
}

#[test]
Expand Down Expand Up @@ -1764,28 +1774,4 @@ mod tests {

assert!(time_block_2 - time_block_1 == 600);
}

#[test]
fn block_time_is_realistic_in_epoch_3_0() {
let settings = SessionSettings::default();
let mut session = Session::new(settings);
session.start().expect("session could not start");
session.update_epoch(StacksEpochId::Epoch30);

session.advance_burn_chain_tip(4);

let result = run_session_snippet(&mut session, "(get-tenure-info? time u2)");
let time_block_1 = match result.expect_optional() {
Ok(Some(Value::UInt(time))) => time,
_ => panic!("Unexpected result"),
};

let result = run_session_snippet(&mut session, "(get-tenure-info? time u3)");
let time_block_2 = match result.expect_optional() {
Ok(Some(Value::UInt(time))) => time,
_ => panic!("Unexpected result"),
};

assert!(time_block_2 - time_block_1 == 600);
}
}

0 comments on commit 4b1499d

Please sign in to comment.