Skip to content

Commit 92d0e65

Browse files
authored
test(spice): enable 4 yield-related tests under spice (#15631)
Test-only changes to handle spice's async execution: - Use `execute_tx` in `test_yield_then_resume_two_actions` to wait for the tx outcome instead of a fixed block count. - Replace `run_until_head_height(N)` with `run_until_executed_height(N)` where the assertion depends on execution. - Switch yield state/receipt helpers to read `node.last_executed()` instead of `client.chain.head()`, so they always inspect an executed block even if consensus has raced ahead. No production code changes.
1 parent 6ae23e8 commit 92d0e65

2 files changed

Lines changed: 37 additions & 58 deletions

File tree

test-loop-tests/src/tests/yield_resume.rs

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -327,8 +327,6 @@ fn test_yield_then_resume_same_block() {
327327
/// With the feature everything should work fine.
328328
/// See https://github.com/near/nearcore/issues/14904, this test reproduces case 4)
329329
#[test]
330-
// TODO(spice-test): Assess if this test is relevant for spice and if yes fix it.
331-
#[cfg_attr(feature = "protocol_feature_spice", ignore)]
332330
fn test_yield_then_resume_two_actions() {
333331
let mut env = prepare_env();
334332
let signer = create_user_test_signer(&AccountId::from_str("test0").unwrap());
@@ -356,8 +354,9 @@ fn test_yield_then_resume_two_actions() {
356354
],
357355
*genesis_block.hash(),
358356
);
359-
env.validator().submit_tx(yield_resume_transaction.clone());
360-
env.validator_runner().run_for_number_of_blocks(3);
357+
env.validator_runner()
358+
.execute_tx(yield_resume_transaction.clone(), Duration::seconds(5))
359+
.unwrap();
361360

362361
{
363362
let node = env.validator();

test-loop-tests/src/tests/yield_timeouts.rs

Lines changed: 34 additions & 54 deletions
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,7 @@ const NEXT_BLOCK_HEIGHT_AFTER_SETUP: u64 = 5;
3131
// producing a YieldResume receipt.
3232
const YIELD_TIMEOUT_HEIGHT: u64 = YIELD_CREATE_HEIGHT + TEST_CONFIG_YIELD_TIMEOUT_LENGTH;
3333

34-
/// Helper function which checks the outgoing receipts from the latest block.
34+
/// Helper function which checks the outgoing receipts from the latest executed block.
3535
/// Returns yield data ids for all PromiseYield and PromiseResume receipts.
3636
fn find_yield_data_ids_from_latest_block(env: &TestLoopEnv) -> Vec<CryptoHash> {
3737
let node = env.validator();
@@ -40,8 +40,9 @@ fn find_yield_data_ids_from_latest_block(env: &TestLoopEnv) -> Vec<CryptoHash> {
4040
let epoch_id = *genesis_block.header().epoch_id();
4141
let shard_layout = client.epoch_manager.get_shard_layout(&epoch_id).unwrap();
4242
let shard_id = shard_layout.account_id_to_shard_id(&"test0".parse::<AccountId>().unwrap());
43-
let last_block_hash = client.chain.head().unwrap().last_block_hash;
44-
let last_block_height = client.chain.head().unwrap().height;
43+
let last_executed = node.last_executed();
44+
let last_block_hash = last_executed.last_block_hash;
45+
let last_block_height = last_executed.height;
4546

4647
let mut result = vec![];
4748

@@ -65,9 +66,9 @@ fn find_yield_data_ids_from_latest_block(env: &TestLoopEnv) -> Vec<CryptoHash> {
6566
pub(crate) fn get_yield_data_ids_in_latest_state(env: &TestLoopEnv) -> Vec<CryptoHash> {
6667
let node = env.validator();
6768
let client = node.client();
68-
let head = client.chain.head().unwrap();
69-
let block_hash = head.last_block_hash;
70-
let epoch_id = head.epoch_id;
69+
let last_executed = node.last_executed();
70+
let block_hash = last_executed.last_block_hash;
71+
let epoch_id = last_executed.epoch_id;
7172
let shard_layout = client.epoch_manager.get_shard_layout(&epoch_id).unwrap();
7273
let shard_uid = shard_layout.account_id_to_shard_uid(&"test0".parse::<AccountId>().unwrap());
7374

@@ -156,12 +157,12 @@ fn get_promise_yield_statuses_in_state(
156157
pub(crate) fn assert_no_promise_yield_status_in_state(env: &TestLoopEnv) {
157158
let node = env.validator();
158159
let client = node.client();
159-
let head = client.chain.head().unwrap();
160-
let epoch_id = head.epoch_id;
160+
let last_executed = node.last_executed();
161+
let epoch_id = last_executed.epoch_id;
161162
let shard_layout = client.epoch_manager.get_shard_layout(&epoch_id).unwrap();
162163
let shard_uid = shard_layout.account_id_to_shard_uid(&"test0".parse::<AccountId>().unwrap());
163164

164-
let state_root = get_latest_state_state_root(client, head.last_block_hash, shard_uid);
165+
let state_root = get_latest_state_state_root(client, last_executed.last_block_hash, shard_uid);
165166
let promise_yield_statuses = get_promise_yield_statuses_in_state(client, state_root, shard_uid);
166167
assert_eq!(promise_yield_statuses, Vec::new());
167168
}
@@ -208,13 +209,8 @@ fn prepare_env_with_yield(
208209
);
209210
env.validator().submit_tx(deploy_contract_tx.clone());
210211

211-
// Allow two blocks for the contract to be deployed.
212-
// With spice, execution is async so we must wait for execution, not just consensus.
213-
if ProtocolFeature::Spice.enabled(PROTOCOL_VERSION) {
214-
env.validator_runner().run_until_executed_height(2);
215-
} else {
216-
env.validator_runner().run_until_head_height(2);
217-
}
212+
// Allow two blocks to execute for the contract to be deployed.
213+
env.validator_runner().run_until_executed_height(2);
218214
assert!(matches!(
219215
env.validator()
220216
.client()
@@ -241,11 +237,7 @@ fn prepare_env_with_yield(
241237
);
242238
let yield_tx_hash = yield_transaction.get_hash();
243239
env.validator().submit_tx(yield_transaction);
244-
if ProtocolFeature::Spice.enabled(PROTOCOL_VERSION) {
245-
env.validator_runner().run_until_executed_height(4);
246-
} else {
247-
env.validator_runner().run_until_head_height(4);
248-
}
240+
env.validator_runner().run_until_executed_height(4);
249241
assert!(matches!(
250242
env.validator()
251243
.client()
@@ -265,7 +257,7 @@ fn prepare_env_with_yield(
265257
};
266258
assert_eq!(yield_data_ids.len(), 1);
267259

268-
let last_block_height = env.validator().head().height;
260+
let last_block_height = env.validator().last_executed().height;
269261
assert_eq!(NEXT_BLOCK_HEIGHT_AFTER_SETUP, last_block_height + 1);
270262

271263
(env, yield_tx_hash, yield_data_ids[0])
@@ -326,8 +318,6 @@ fn create_congestion(env: &TestLoopEnv) {
326318
/// Simple test of timeout execution.
327319
/// Advances sufficiently many blocks, then verifies that the callback was executed.
328320
#[test]
329-
// TODO(spice-test): Assess if this test is relevant for spice and if yes fix it.
330-
#[cfg_attr(feature = "protocol_feature_spice", ignore)]
331321
fn test_simple_yield_timeout() {
332322
let (mut env, yield_tx_hash, data_id) = prepare_env_with_yield(vec![], None);
333323
assert!(NEXT_BLOCK_HEIGHT_AFTER_SETUP < YIELD_TIMEOUT_HEIGHT);
@@ -348,8 +338,8 @@ fn test_simple_yield_timeout() {
348338
);
349339
}
350340

351-
// In this block the timeout is processed, producing a YieldResume receipt.
352-
env.validator_runner().run_until_head_height(YIELD_TIMEOUT_HEIGHT);
341+
// When this block executes, the timeout is processed, producing a YieldResume receipt.
342+
env.validator_runner().run_until_executed_height(YIELD_TIMEOUT_HEIGHT);
353343
// Checks that the anticipated YieldResume receipt was produced.
354344
assert_eq!(find_yield_data_ids_from_latest_block(&env), vec![data_id]);
355345
assert_eq!(
@@ -362,8 +352,8 @@ fn test_simple_yield_timeout() {
362352
FinalExecutionStatus::Started
363353
);
364354

365-
// In this block the resume receipt is applied and the callback will execute.
366-
env.validator_runner().run_until_head_height(YIELD_TIMEOUT_HEIGHT + 1);
355+
// When this block executes, the resume receipt is applied and the callback will execute.
356+
env.validator_runner().run_until_executed_height(YIELD_TIMEOUT_HEIGHT + 1);
367357
assert_eq!(
368358
env.validator()
369359
.client()
@@ -429,8 +419,6 @@ fn test_yield_timeout_under_congestion() {
429419

430420
/// In this case we invoke yield_resume at the last block possible.
431421
#[test]
432-
// TODO(spice-test): Assess if this test is relevant for spice and if yes fix it.
433-
#[cfg_attr(feature = "protocol_feature_spice", ignore)]
434422
fn test_yield_resume_just_before_timeout() {
435423
let yield_payload = vec![6u8; 16];
436424
let (mut env, yield_tx_hash, data_id) = prepare_env_with_yield(yield_payload.clone(), None);
@@ -456,8 +444,8 @@ fn test_yield_resume_just_before_timeout() {
456444
);
457445
}
458446

459-
// In this block the `yield_resume` host function is invoked, producing a YieldResume receipt.
460-
env.validator_runner().run_until_head_height(YIELD_TIMEOUT_HEIGHT);
447+
// When this block executes `yield_resume` host function is invoked, producing a YieldResume receipt.
448+
env.validator_runner().run_until_executed_height(YIELD_TIMEOUT_HEIGHT);
461449
assert_eq!(
462450
env.validator()
463451
.client()
@@ -470,8 +458,8 @@ fn test_yield_resume_just_before_timeout() {
470458
// Here we expect two receipts to be produced; one from yield_resume and one from timeout.
471459
assert_eq!(find_yield_data_ids_from_latest_block(&env), vec![data_id, data_id]);
472460

473-
// In this block the resume receipt is applied and the callback is executed with the resume payload.
474-
env.validator_runner().run_until_head_height(YIELD_TIMEOUT_HEIGHT + 1);
461+
// When this block executes, the resume receipt is applied and the callback is executed with the resume payload.
462+
env.validator_runner().run_until_executed_height(YIELD_TIMEOUT_HEIGHT + 1);
475463
assert_eq!(
476464
env.validator()
477465
.client()
@@ -540,9 +528,7 @@ fn test_yield_resume_after_timeout_height() {
540528

541529
/// In this test there is no block produced at height YIELD_TIMEOUT_HEIGHT.
542530
#[test]
543-
// TODO(spice-test): Assess if this test is relevant for spice and if yes fix it.
544531
#[cfg(feature = "test_features")]
545-
#[cfg_attr(feature = "protocol_feature_spice", ignore)]
546532
fn test_skip_timeout_height() {
547533
use assert_matches::assert_matches;
548534
use near_chain::Error;
@@ -580,6 +566,8 @@ fn test_skip_timeout_height() {
580566
env.validator_runner()
581567
.run_until_head_height_with_timeout(YIELD_TIMEOUT_HEIGHT + 1, Duration::seconds(3));
582568
assert_eq!(env.validator().head().height, YIELD_TIMEOUT_HEIGHT + 1);
569+
// In spice, this waits for the specified block to execute.
570+
env.validator_runner().run_until_executed_height(YIELD_TIMEOUT_HEIGHT + 1);
583571
// The block at YIELD_TIMEOUT_HEIGHT should be missing.
584572
assert_matches!(
585573
env.validator().client().chain.get_block_by_height(YIELD_TIMEOUT_HEIGHT),
@@ -598,8 +586,8 @@ fn test_skip_timeout_height() {
598586
FinalExecutionStatus::Started
599587
);
600588

601-
// In this block the resume receipt is applied and the callback will execute.
602-
env.validator_runner().run_until_head_height(YIELD_TIMEOUT_HEIGHT + 2);
589+
// When this block executes, the resume receipt is applied and the callback will execute.
590+
env.validator_runner().run_until_executed_height(YIELD_TIMEOUT_HEIGHT + 2);
603591
assert_eq!(
604592
env.validator()
605593
.client()
@@ -613,16 +601,17 @@ fn test_skip_timeout_height() {
613601
assert_no_promise_yield_status_in_state(&env);
614602
}
615603

616-
/// Helper: finds PromiseResume receipt IDs from the outgoing receipts at the latest block.
604+
/// Helper: finds PromiseResume receipt IDs from the outgoing receipts at the latest executed block.
617605
fn find_promise_resume_receipt_ids_from_latest_block(env: &TestLoopEnv) -> Vec<CryptoHash> {
618606
let node = env.validator();
619607
let client = node.client();
620608
let genesis_block = client.chain.get_block_by_height(0).unwrap();
621609
let epoch_id = *genesis_block.header().epoch_id();
622610
let shard_layout = client.epoch_manager.get_shard_layout(&epoch_id).unwrap();
623611
let shard_id = shard_layout.account_id_to_shard_id(&"test0".parse::<AccountId>().unwrap());
624-
let last_block_hash = client.chain.head().unwrap().last_block_hash;
625-
let last_block_height = client.chain.head().unwrap().height;
612+
let last_executed = node.last_executed();
613+
let last_block_hash = last_executed.last_block_hash;
614+
let last_block_height = last_executed.height;
626615

627616
let mut result = vec![];
628617
for receipt in client
@@ -648,23 +637,14 @@ fn test_yield_timeout_resume_receipt_has_receipt_to_tx() {
648637
env.validator_runner().run_until_head_height(block_height);
649638
}
650639

651-
// In this block the timeout fires, producing a PromiseResume receipt.
652-
// With spice, we must wait for execution to complete before querying results.
653-
if ProtocolFeature::Spice.enabled(PROTOCOL_VERSION) {
654-
env.validator_runner().run_until_executed_height(YIELD_TIMEOUT_HEIGHT);
655-
} else {
656-
env.validator_runner().run_until_head_height(YIELD_TIMEOUT_HEIGHT);
657-
}
640+
// When this block executes, the timeout fires, producing a PromiseResume receipt.
641+
env.validator_runner().run_until_executed_height(YIELD_TIMEOUT_HEIGHT);
658642
let resume_receipt_ids = find_promise_resume_receipt_ids_from_latest_block(&env);
659643
assert_eq!(resume_receipt_ids.len(), 1, "expected exactly one PromiseResume receipt");
660644
let resume_receipt_id = resume_receipt_ids[0];
661645

662-
// In this block the resume receipt is applied and the callback executes.
663-
if ProtocolFeature::Spice.enabled(PROTOCOL_VERSION) {
664-
env.validator_runner().run_until_executed_height(YIELD_TIMEOUT_HEIGHT + 1);
665-
} else {
666-
env.validator_runner().run_until_head_height(YIELD_TIMEOUT_HEIGHT + 1);
667-
}
646+
// When this block executes, the resume receipt is applied and the callback executes.
647+
env.validator_runner().run_until_executed_height(YIELD_TIMEOUT_HEIGHT + 1);
668648
assert_eq!(
669649
env.validator()
670650
.client()

0 commit comments

Comments
 (0)