Skip to content

Commit bab5c3e

Browse files
emmazzzclaude
andcommitted
Split write API tests into dedicated test file with correctness checks
Move executeTransactionBlock and dryRunTransactionBlock tests from jsonrpc_fn_delegation_tests.rs into a new jsonrpc_write_api_tests.rs. The delegation test file now only tests governance APIs (getStakes, getStakesByIds, getValidatorsApy) and no longer needs a gRPC URL. The new write tests verify conversion correctness: sender identity in transaction input, exact balance change amounts for sender/recipient, effects status and gas costs, object change types, and consistency between dry run and execute results. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
1 parent 2becc9a commit bab5c3e

File tree

3 files changed

+469
-257
lines changed

3 files changed

+469
-257
lines changed

crates/sui-indexer-alt-e2e-tests/tests/jsonrpc_fn_delegation_tests.rs

Lines changed: 2 additions & 256 deletions
Original file line numberDiff line numberDiff line change
@@ -40,7 +40,7 @@ struct FnDelegationTestCluster {
4040
}
4141

4242
impl FnDelegationTestCluster {
43-
/// Creates a new test cluster with an RPC with transaction execution enabled.
43+
/// Creates a new test cluster with an RPC with delegation governance enabled.
4444
async fn new() -> anyhow::Result<Self> {
4545
let onchain_cluster = TestClusterBuilder::new()
4646
.with_num_validators(1)
@@ -56,7 +56,6 @@ impl FnDelegationTestCluster {
5656
.await;
5757

5858
let fullnode_rpc_url = Url::parse(onchain_cluster.rpc_url())?;
59-
let fullnode_grpc_url = onchain_cluster.rpc_url().to_string();
6059

6160
let rpc_listen_address =
6261
SocketAddr::new(IpAddr::V4(Ipv4Addr::LOCALHOST), get_available_port());
@@ -80,7 +79,7 @@ impl FnDelegationTestCluster {
8079
rpc_args,
8180
NodeArgs {
8281
fullnode_rpc_url: Some(fullnode_rpc_url),
83-
fullnode_grpc_url: Some(fullnode_grpc_url),
82+
fullnode_grpc_url: None,
8483
},
8584
SystemPackageTaskArgs::default(),
8685
RpcConfig::default(),
@@ -97,43 +96,6 @@ impl FnDelegationTestCluster {
9796
})
9897
}
9998

100-
/// Builds a simple transaction and returns the digest, tx bytes, and sigs to be used for testing.
101-
async fn transfer_transaction(&self) -> anyhow::Result<(String, String, Vec<String>)> {
102-
let addresses = self.onchain_cluster.wallet.get_addresses();
103-
104-
let recipient = addresses[1];
105-
let tx = self
106-
.onchain_cluster
107-
.test_transaction_builder()
108-
.await
109-
.transfer_sui(Some(1_000), recipient)
110-
.build();
111-
let tx_digest = tx.digest().to_string();
112-
let signed_tx = self.onchain_cluster.wallet.sign_transaction(&tx).await;
113-
let (tx_bytes, sigs) = signed_tx.to_tx_bytes_and_signatures();
114-
let tx_bytes = tx_bytes.encoded();
115-
let sigs: Vec<_> = sigs.iter().map(|sig| sig.encoded()).collect();
116-
117-
Ok((tx_digest, tx_bytes, sigs))
118-
}
119-
120-
/// Builds a transaction that would abort if called by a normal user.
121-
async fn privileged_transaction(&self) -> anyhow::Result<(String, String, Vec<String>)> {
122-
let tx: sui_types::transaction::TransactionData = self
123-
.onchain_cluster
124-
.test_transaction_builder()
125-
.await
126-
.call_request_remove_validator()
127-
.build();
128-
let tx_digest = tx.digest().to_string();
129-
let signed_tx = self.onchain_cluster.wallet.sign_transaction(&tx).await;
130-
let (tx_bytes, sigs) = signed_tx.to_tx_bytes_and_signatures();
131-
let tx_bytes = tx_bytes.encoded();
132-
let sigs: Vec<_> = sigs.iter().map(|sig| sig.encoded()).collect();
133-
134-
Ok((tx_digest, tx_bytes, sigs))
135-
}
136-
13799
async fn get_validator_address(&self) -> SuiAddress {
138100
self.onchain_cluster
139101
.grpc_client()
@@ -171,222 +133,6 @@ impl FnDelegationTestCluster {
171133
}
172134
}
173135

174-
#[sim_test]
175-
async fn test_execution() {
176-
telemetry_subscribers::init_for_testing();
177-
let test_cluster = FnDelegationTestCluster::new()
178-
.await
179-
.expect("Failed to create test cluster");
180-
181-
let (tx_digest, tx_bytes, sigs) = test_cluster.transfer_transaction().await.unwrap();
182-
183-
// Call the executeTransactionBlock method and check that the response is valid.
184-
let response = test_cluster
185-
.execute_jsonrpc(
186-
"sui_executeTransactionBlock".to_string(),
187-
json!({
188-
"tx_bytes": tx_bytes,
189-
"signatures": sigs,
190-
"options": {
191-
"showInput": true,
192-
"showRawInput": true,
193-
"showEffects": true,
194-
"showRawEffects": true,
195-
"showEvents": true,
196-
"showObjectChanges": true,
197-
"showBalanceChanges": true,
198-
},
199-
}),
200-
)
201-
.await
202-
.unwrap();
203-
204-
tracing::info!("execution rpc response is {:?}", response);
205-
206-
// Checking that all the requested fields are present in the response.
207-
assert_eq!(response["result"]["digest"], tx_digest);
208-
assert!(response["result"]["transaction"].is_object());
209-
assert!(response["result"]["rawTransaction"].is_string());
210-
assert!(response["result"]["effects"].is_object());
211-
assert!(response["result"]["rawEffects"].is_array());
212-
assert!(response["result"]["events"].is_array());
213-
assert!(response["result"]["objectChanges"].is_array());
214-
assert!(response["result"]["balanceChanges"].is_array());
215-
}
216-
217-
#[sim_test]
218-
async fn test_execution_with_deprecated_mode() {
219-
telemetry_subscribers::init_for_testing();
220-
221-
let test_cluster = FnDelegationTestCluster::new()
222-
.await
223-
.expect("Failed to create test cluster");
224-
225-
let (_, tx_bytes, sigs) = test_cluster.transfer_transaction().await.unwrap();
226-
227-
// Call the executeTransactionBlock method and check that the response is valid.
228-
let response = test_cluster
229-
.execute_jsonrpc(
230-
"sui_executeTransactionBlock".to_string(),
231-
json!({
232-
"tx_bytes": tx_bytes,
233-
"signatures": sigs,
234-
"request_type": "WaitForLocalExecution",
235-
}),
236-
)
237-
.await
238-
.unwrap();
239-
240-
tracing::info!("execution rpc response is {:?}", response);
241-
242-
assert_eq!(response["error"]["code"], -32602);
243-
assert_eq!(
244-
response["error"]["message"],
245-
"Invalid Params: WaitForLocalExecution mode is deprecated"
246-
);
247-
}
248-
249-
#[sim_test]
250-
async fn test_execution_with_no_sigs() {
251-
telemetry_subscribers::init_for_testing();
252-
253-
let test_cluster = FnDelegationTestCluster::new()
254-
.await
255-
.expect("Failed to create test cluster");
256-
257-
let (_, tx_bytes, _) = test_cluster.transfer_transaction().await.unwrap();
258-
259-
// Call the executeTransactionBlock method and check that the response is valid.
260-
let response = test_cluster
261-
.execute_jsonrpc(
262-
"sui_executeTransactionBlock".to_string(),
263-
json!({
264-
"tx_bytes": tx_bytes,
265-
}),
266-
)
267-
.await
268-
.unwrap();
269-
270-
tracing::info!("execution rpc response is {:?}", response);
271-
272-
assert_eq!(response["error"]["code"], -32602);
273-
assert_eq!(response["error"]["message"], "Invalid params");
274-
assert!(
275-
response["error"]["data"]
276-
.as_str()
277-
.unwrap()
278-
.starts_with("missing field `signatures`")
279-
);
280-
}
281-
282-
#[sim_test]
283-
async fn test_execution_with_empty_sigs() {
284-
telemetry_subscribers::init_for_testing();
285-
286-
let test_cluster = FnDelegationTestCluster::new()
287-
.await
288-
.expect("Failed to create test cluster");
289-
290-
let (_, tx_bytes, _) = test_cluster.transfer_transaction().await.unwrap();
291-
292-
// Call the executeTransactionBlock method and check that the response is valid.
293-
let response = test_cluster
294-
.execute_jsonrpc(
295-
"sui_executeTransactionBlock".to_string(),
296-
json!({
297-
"tx_bytes": tx_bytes,
298-
"signatures": [],
299-
}),
300-
)
301-
.await
302-
.unwrap();
303-
304-
tracing::info!("execution rpc response is {:?}", response);
305-
306-
assert_eq!(response["error"]["code"], -32002);
307-
assert_eq!(
308-
response["error"]["message"],
309-
"Invalid user signature: Expect 1 signer signatures but got 0"
310-
);
311-
}
312-
313-
#[sim_test]
314-
async fn test_execution_with_aborted_tx() {
315-
telemetry_subscribers::init_for_testing();
316-
317-
let test_cluster = FnDelegationTestCluster::new()
318-
.await
319-
.expect("Failed to create test cluster");
320-
321-
let (_, tx_bytes, sigs) = test_cluster.privileged_transaction().await.unwrap();
322-
323-
// Call the executeTransactionBlock method and check that the response is valid.
324-
let response = test_cluster
325-
.execute_jsonrpc(
326-
"sui_executeTransactionBlock".to_string(),
327-
json!({
328-
"tx_bytes": tx_bytes,
329-
"signatures": sigs,
330-
"options": {
331-
"showEffects": true,
332-
},
333-
}),
334-
)
335-
.await
336-
.unwrap();
337-
338-
tracing::info!("execution rpc response is {:?}", response);
339-
340-
assert_eq!(response["result"]["effects"]["status"]["status"], "failure");
341-
}
342-
343-
#[sim_test]
344-
async fn test_dry_run() {
345-
let test_cluster = FnDelegationTestCluster::new()
346-
.await
347-
.expect("Failed to create test cluster");
348-
349-
let (_, tx_bytes, _) = test_cluster.transfer_transaction().await.unwrap();
350-
351-
let response = test_cluster
352-
.execute_jsonrpc(
353-
"sui_dryRunTransactionBlock".to_string(),
354-
json!({
355-
"tx_bytes": tx_bytes,
356-
}),
357-
)
358-
.await
359-
.unwrap();
360-
361-
assert_eq!(response["result"]["effects"]["status"]["status"], "success");
362-
}
363-
364-
#[sim_test]
365-
async fn test_dry_run_with_invalid_tx() {
366-
let test_cluster = FnDelegationTestCluster::new()
367-
.await
368-
.expect("Failed to create test cluster");
369-
370-
let response = test_cluster
371-
.execute_jsonrpc(
372-
"sui_dryRunTransactionBlock".to_string(),
373-
json!({
374-
"tx_bytes": "invalid_tx_bytes",
375-
}),
376-
)
377-
.await
378-
.unwrap();
379-
380-
assert_eq!(response["error"]["code"], -32602);
381-
assert_eq!(response["error"]["message"], "Invalid params");
382-
assert!(
383-
response["error"]["data"]
384-
.as_str()
385-
.unwrap()
386-
.starts_with("Invalid value was given to the function")
387-
);
388-
}
389-
390136
#[sim_test]
391137
async fn test_get_stakes_and_by_ids() {
392138
let test_cluster = FnDelegationTestCluster::new()

0 commit comments

Comments
 (0)