Skip to content

Commit

Permalink
Add tests
Browse files Browse the repository at this point in the history
  • Loading branch information
lxfind committed Apr 5, 2022
1 parent c753e04 commit f9ef178
Show file tree
Hide file tree
Showing 7 changed files with 586 additions and 215 deletions.
84 changes: 84 additions & 0 deletions sui/src/rest_server.rs
Original file line number Diff line number Diff line change
Expand Up @@ -376,7 +376,91 @@ async fn merge_coin(
.await
}
.await
.map_err(|error| custom_http_error(StatusCode::BAD_REQUEST, error.to_string()))?;
Ok(HttpResponseOk(TransactionBytes::new(tx_data)))
}

/// Publish move module. It will perform proper verification and linking to make
/// sure the package is valid. If some modules have initializers, these initializers
/// will also be executed in Move (which means new Move objects can be created in
/// the process of publishing a Move package). Gas budget is required because of the
/// need to execute module initializers.
#[endpoint {
method = POST,
path = "/api/publish",
tags = [ "API" ],
}]
#[allow(unused_variables)]
async fn publish(
ctx: Arc<RequestContext<ServerContext>>,
request: TypedBody<PublishRequest>,
) -> Result<HttpResponseOk<TransactionBytes>, HttpError> {
let mut gateway = ctx.context().gateway.lock().await;
let publish_params = request.into_inner();
let data = handle_publish(publish_params, &mut gateway)
.await
.map_err(|err| custom_http_error(StatusCode::BAD_REQUEST, format!("{:#}", err)))?;
Ok(HttpResponseOk(TransactionBytes::new(data)))
}

/// Execute a Move call transaction by calling the specified function in the
/// module of the given package. Arguments are passed in and type will be
/// inferred from function signature. Gas usage is capped by the gas_budget.
///
/// Example CallRequest
/// {
/// "sender": "b378b8d26c4daa95c5f6a2e2295e6e5f34371c1659e95f572788ffa55c265363",
/// "package_object_id": "0x2",
/// "module": "ObjectBasics",
/// "function": "create",
/// "args": [
/// 200,
/// "b378b8d26c4daa95c5f6a2e2295e6e5f34371c1659e95f572788ffa55c265363"
/// ],
/// "gas_object_id": "1AC945CA31E77991654C0A0FCA8B0FD9C469B5C6",
/// "gas_budget": 2000
/// }
#[endpoint {
method = POST,
path = "/api/move_call",
tags = [ "API" ],
}]
async fn move_call(
ctx: Arc<RequestContext<ServerContext>>,
request: TypedBody<CallRequest>,
) -> Result<HttpResponseOk<TransactionBytes>, HttpError> {
let mut gateway = ctx.context().gateway.lock().await;

let call_params = request.into_inner();
let data = handle_move_call(call_params, &mut gateway)
.await
.map_err(|err| custom_http_error(StatusCode::BAD_REQUEST, format!("{:#}", err)))?;

Ok(HttpResponseOk(TransactionBytes::new(data)))
}

/// Synchronize client state with authorities. This will fetch the latest information
/// on all objects owned by each address that is managed by this client state.
#[endpoint {
method = POST,
path = "/api/sync_account_state",
tags = [ "API" ],
}]
async fn sync_account_state(
ctx: Arc<RequestContext<ServerContext>>,
request: TypedBody<SyncRequest>,
) -> Result<HttpResponseUpdatedNoContent, HttpError> {
let sync_params = request.into_inner();
let gateway = ctx.context().gateway.lock().await;

let address = decode_bytes_hex(sync_params.address.as_str()).map_err(|error| {
custom_http_error(
StatusCode::FAILED_DEPENDENCY,
format!("Could not decode to address from hex {error}"),
)
})?;

gateway.sync_account_state(address).await.map_err(|err| {
custom_http_error(
StatusCode::BAD_REQUEST,
format!("Can't create client state: {err}"),
Expand Down
160 changes: 1 addition & 159 deletions sui_core/src/unit_tests/authority_tests.rs
Original file line number Diff line number Diff line change
Expand Up @@ -329,42 +329,6 @@ async fn test_immutable_gas() {
));
}

#[tokio::test]
async fn test_handle_transfer_zero_balance() {
let (sender, sender_key) = get_key_pair();
let recipient = dbg_addr(2);
let object_id = ObjectID::random();
let authority_state = init_state_with_ids(vec![(sender, object_id)]).await;
let object = authority_state
.get_object(&object_id)
.await
.unwrap()
.unwrap();

// Create a gas object with 0 balance.
let gas_object_id = ObjectID::random();
let gas_object =
Object::with_id_owner_gas_for_testing(gas_object_id, SequenceNumber::new(), sender, 0);
let gas_object_ref = gas_object.compute_object_reference();
authority_state.insert_genesis_object(gas_object).await;

let transfer_transaction = init_transfer_transaction(
sender,
&sender_key,
recipient,
object.compute_object_reference(),
gas_object_ref,
);

let result = authority_state
.handle_transaction(transfer_transaction.clone())
.await;
assert!(matches!(
result.unwrap_err(),
SuiError::InsufficientGas { .. }
));
}

pub async fn send_and_confirm_transaction(
authority: &AuthorityState,
transaction: Transaction,
Expand Down Expand Up @@ -538,37 +502,6 @@ async fn test_publish_non_existing_dependent_module() {
);
}

// Test the case when the gas provided is less than minimum requirement during module publish.
// Note that the case where gas is insufficient to publish the module is tested
// separately in the adapter tests.
#[tokio::test]
async fn test_publish_module_insufficient_gas() {
let (sender, sender_key) = get_key_pair();
let gas_payment_object_id = ObjectID::random();
let gas_balance = 9;
let gas_payment_object = Object::with_id_owner_gas_for_testing(
gas_payment_object_id,
SequenceNumber::new(),
sender,
gas_balance,
);
let gas_payment_object_ref = gas_payment_object.compute_object_reference();
let authority = init_state_with_objects(vec![gas_payment_object]).await;

let module = file_format::empty_module();
let mut module_bytes = Vec::new();
module.serialize(&mut module_bytes).unwrap();
let module_bytes = vec![module_bytes];
let data = TransactionData::new_module(sender, gas_payment_object_ref, module_bytes, 10);
let signature = Signature::new(&data, &sender_key);
let transaction = Transaction::new(data, signature);
let response = authority
.handle_transaction(transaction.clone())
.await
.unwrap_err();
assert!(matches!(response, SuiError::InsufficientGas { .. }));
}

#[tokio::test]
async fn test_handle_move_transaction() {
let (sender, sender_key) = get_key_pair();
Expand Down Expand Up @@ -601,47 +534,6 @@ async fn test_handle_move_transaction() {
assert_eq!(created_obj.version(), OBJECT_START_VERSION);
}

// Test the case when the gas budget provided is less than minimum requirement during move call.
// Note that the case where gas is insufficient to execute move bytecode is tested
// separately in the adapter tests.
#[tokio::test]
async fn test_handle_move_transaction_insufficient_budget() {
let (sender, sender_key) = get_key_pair();
let gas_payment_object_id = ObjectID::random();
let gas_payment_object = Object::with_id_owner_for_testing(gas_payment_object_id, sender);
let gas_payment_object_ref = gas_payment_object.compute_object_reference();
// find the function Object::create and call it to create a new object
let genesis_package_objects = genesis::clone_genesis_packages();
let package_object_ref =
get_genesis_package_by_module(&genesis_package_objects, "ObjectBasics");

let authority_state = init_state_with_objects(vec![gas_payment_object]).await;

let function = ident_str!("create").to_owned();
let data = TransactionData::new_move_call(
sender,
package_object_ref,
ident_str!("ObjectBasics").to_owned(),
function,
Vec::new(),
gas_payment_object_ref,
Vec::new(),
vec![],
vec![
16u64.to_le_bytes().to_vec(),
bcs::to_bytes(&AccountAddress::from(sender)).unwrap(),
],
4,
);
let signature = Signature::new(&data, &sender_key);
let transaction = Transaction::new(data, signature);
let response = authority_state
.handle_transaction(transaction.clone())
.await
.unwrap_err();
assert!(matches!(response, SuiError::InsufficientGas { .. }));
}

#[tokio::test]
async fn test_handle_transfer_transaction_double_spend() {
let (sender, sender_key) = get_key_pair();
Expand Down Expand Up @@ -840,56 +732,6 @@ async fn test_handle_confirmation_transaction_receiver_equal_sender() {
.is_some());
}

#[tokio::test]
async fn test_handle_confirmation_transaction_gas() {
let run_test_with_gas = |gas: u64| async move {
let (sender, sender_key) = get_key_pair();
let recipient = dbg_addr(2);
let object_id = ObjectID::random();
let authority_state = init_state_with_ids(vec![(sender, object_id)]).await;
let object = authority_state
.get_object(&object_id)
.await
.unwrap()
.unwrap();

// Create a gas object with balance.
let gas_object_id = ObjectID::random();
let gas_object = Object::with_id_owner_gas_for_testing(
gas_object_id,
SequenceNumber::new(),
sender,
gas,
);

let gas_object_ref = gas_object.compute_object_reference();
authority_state.insert_genesis_object(gas_object).await;

let certified_transfer_transaction = init_certified_transfer_transaction(
sender,
&sender_key,
recipient,
object.compute_object_reference(),
gas_object_ref,
&authority_state,
);

authority_state
.handle_confirmation_transaction(ConfirmationTransaction::new(
certified_transfer_transaction.clone(),
))
.await
};
let result = run_test_with_gas(1000).await;
assert!(matches!(
result.unwrap_err(),
SuiError::InsufficientGas { .. }
));
// This will execute sufccessfully.
let result = run_test_with_gas(10000).await;
result.unwrap();
}

#[tokio::test]
async fn test_handle_confirmation_transaction_ok() {
let (sender, sender_key) = get_key_pair();
Expand Down Expand Up @@ -1406,7 +1248,7 @@ pub async fn init_state_with_object_id(address: SuiAddress, object: ObjectID) ->
}

#[cfg(test)]
fn init_transfer_transaction(
pub fn init_transfer_transaction(
sender: SuiAddress,
secret: &KeyPair,
recipient: SuiAddress,
Expand Down
Loading

1 comment on commit f9ef178

@github-actions
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Bench results

�[0m�[0m�[1m�[32m Finished�[0m release [optimized] target(s) in 0.32s
�[0m�[0m�[1m�[32m Running�[0m target/release/microbench
�[2m2022-04-05T17:53:27.789885Z�[0m �[32m INFO�[0m �[2mmicrobench�[0m�[2m:�[0m Starting benchmark: TransactionsAndCerts
�[2m2022-04-05T17:53:27.789924Z�[0m �[32m INFO�[0m �[2mmicrobench�[0m�[2m:�[0m Preparing accounts.
�[2m2022-04-05T17:53:27.790301Z�[0m �[32m INFO�[0m �[2mmicrobench�[0m�[2m:�[0m Init Authority.
�[2m2022-04-05T17:53:27.790377Z�[0m �[32m INFO�[0m �[2mmicrobench�[0m�[2m:�[0m Open database on path: "/tmp/DB_1715A7B09C5CF304ABC2018A83E597A1A5C92831"
�[2m2022-04-05T17:53:28.060897Z�[0m �[32m INFO�[0m �[2mmicrobench�[0m�[2m:�[0m Generate empty store with Genesis.
�[2m2022-04-05T17:53:28.991148Z�[0m �[32m INFO�[0m �[2mmicrobench�[0m�[2m:�[0m Preparing transactions.
�[2m2022-04-05T17:53:29.564383Z�[0m �[32m INFO�[0m �[2msui_network::transport�[0m�[2m:�[0m Listening to TCP traffic on 127.0.0.1:9555
�[2m2022-04-05T17:53:29.564466Z�[0m �[32m INFO�[0m �[2mmicrobench�[0m�[2m:�[0m Sending requests.
�[2m2022-04-05T17:53:29.565233Z�[0m �[32m INFO�[0m �[2mmicrobench�[0m�[2m:�[0m Start batch listener at sequence: 0.
�[2m2022-04-05T17:53:29.565253Z�[0m �[32m INFO�[0m �[2mmicrobench�[0m�[2m:�[0m Client received batch up to sequence 0
�[2m2022-04-05T17:53:29.564515Z�[0m �[32m INFO�[0m �[2mmicrobench�[0m�[2m:�[0m Number of TCP connections: 2
�[2m2022-04-05T17:53:29.875110Z�[0m �[31mERROR�[0m �[2msui_core::authority_server�[0m�[2m:�[0m Failed to send query response: frame size too big
�[2m2022-04-05T17:53:29.893072Z�[0m �[31mERROR�[0m �[2msui_core::authority_server�[0m�[2m:�[0m Failed to send query response: frame size too big
�[2m2022-04-05T17:53:29.961005Z�[0m �[31mERROR�[0m �[2msui_core::authority_server�[0m�[2m:�[0m Failed to send query response: frame size too big
�[2m2022-04-05T17:53:29.988643Z�[0m �[31mERROR�[0m �[2msui_core::authority_server�[0m�[2m:�[0m Failed to send query response: frame size too big
�[2m2022-04-05T17:53:30.051799Z�[0m �[31mERROR�[0m �[2msui_core::authority_server�[0m�[2m:�[0m Failed to send query response: frame size too big
�[2m2022-04-05T17:53:30.085710Z�[0m �[31mERROR�[0m �[2msui_core::authority_server�[0m�[2m:�[0m Failed to send query response: frame size too big
�[2m2022-04-05T17:53:30.148692Z�[0m �[31mERROR�[0m �[2msui_core::authority_server�[0m�[2m:�[0m Failed to send query response: frame size too big
�[2m2022-04-05T17:53:30.184722Z�[0m �[31mERROR�[0m �[2msui_core::authority_server�[0m�[2m:�[0m Failed to send query response: frame size too big
�[2m2022-04-05T17:53:30.250528Z�[0m �[31mERROR�[0m �[2msui_core::authority_server�[0m�[2m:�[0m Failed to send query response: frame size too big
�[2m2022-04-05T17:53:30.281300Z�[0m �[31mERROR�[0m �[2msui_core::authority_server�[0m�[2m:�[0m Failed to send query response: frame size too big
�[2m2022-04-05T17:53:30.343577Z�[0m �[31mERROR�[0m �[2msui_core::authority_server�[0m�[2m:�[0m Failed to send query response: frame size too big
�[2m2022-04-05T17:53:30.379337Z�[0m �[31mERROR�[0m �[2msui_core::authority_server�[0m�[2m:�[0m Failed to send query response: frame size too big
�[2m2022-04-05T17:53:30.441509Z�[0m �[31mERROR�[0m �[2msui_core::authority_server�[0m�[2m:�[0m Failed to send query response: frame size too big
�[2m2022-04-05T17:53:30.479284Z�[0m �[31mERROR�[0m �[2msui_core::authority_server�[0m�[2m:�[0m Failed to send query response: frame size too big
�[2m2022-04-05T17:53:30.541092Z�[0m �[31mERROR�[0m �[2msui_core::authority_server�[0m�[2m:�[0m Failed to send query response: frame size too big
�[2m2022-04-05T17:53:30.578830Z�[0m �[31mERROR�[0m �[2msui_core::authority_server�[0m�[2m:�[0m Failed to send query response: frame size too big
�[2m2022-04-05T17:53:30.642068Z�[0m �[31mERROR�[0m �[2msui_core::authority_server�[0m�[2m:�[0m Failed to send query response: frame size too big
�[2m2022-04-05T17:53:30.680550Z�[0m �[31mERROR�[0m �[2msui_core::authority_server�[0m�[2m:�[0m Failed to send query response: frame size too big
�[2m2022-04-05T17:53:30.744294Z�[0m �[31mERROR�[0m �[2msui_core::authority_server�[0m�[2m:�[0m Failed to send query response: frame size too big
�[2m2022-04-05T17:53:30.778611Z�[0m �[31mERROR�[0m �[2msui_core::authority_server�[0m�[2m:�[0m Failed to send query response: frame size too big
�[2m2022-04-05T17:53:30.841277Z�[0m �[31mERROR�[0m �[2msui_core::authority_server�[0m�[2m:�[0m Failed to send query response: frame size too big
�[2m2022-04-05T17:53:30.876894Z�[0m �[31mERROR�[0m �[2msui_core::authority_server�[0m�[2m:�[0m Failed to send query response: frame size too big
�[2m2022-04-05T17:53:30.939144Z�[0m �[31mERROR�[0m �[2msui_core::authority_server�[0m�[2m:�[0m Failed to send query response: frame size too big
�[2m2022-04-05T17:53:30.976416Z�[0m �[31mERROR�[0m �[2msui_core::authority_server�[0m�[2m:�[0m Failed to send query response: frame size too big
�[2m2022-04-05T17:53:31.040072Z�[0m �[31mERROR�[0m �[2msui_core::authority_server�[0m�[2m:�[0m Failed to send query response: frame size too big
�[2m2022-04-05T17:53:31.074459Z�[0m �[31mERROR�[0m �[2msui_core::authority_server�[0m�[2m:�[0m Failed to send query response: frame size too big
�[2m2022-04-05T17:53:31.137135Z�[0m �[31mERROR�[0m �[2msui_core::authority_server�[0m�[2m:�[0m Failed to send query response: frame size too big
�[2m2022-04-05T17:53:31.173524Z�[0m �[31mERROR�[0m �[2msui_core::authority_server�[0m�[2m:�[0m Failed to send query response: frame size too big
�[2m2022-04-05T17:53:31.236746Z�[0m �[31mERROR�[0m �[2msui_core::authority_server�[0m�[2m:�[0m Failed to send query response: frame size too big
�[2m2022-04-05T17:53:31.270707Z�[0m �[31mERROR�[0m �[2msui_core::authority_server�[0m�[2m:�[0m Failed to send query response: frame size too big
�[2m2022-04-05T17:53:31.332564Z�[0m �[31mERROR�[0m �[2msui_core::authority_server�[0m�[2m:�[0m Failed to send query response: frame size too big
�[2m2022-04-05T17:53:31.367890Z�[0m �[31mERROR�[0m �[2msui_core::authority_server�[0m�[2m:�[0m Failed to send query response: frame size too big
�[2m2022-04-05T17:53:31.429710Z�[0m �[31mERROR�[0m �[2msui_core::authority_server�[0m�[2m:�[0m Failed to send query response: frame size too big
�[2m2022-04-05T17:53:31.469300Z�[0m �[31mERROR�[0m �[2msui_core::authority_server�[0m�[2m:�[0m Failed to send query response: frame size too big
�[2m2022-04-05T17:53:31.531276Z�[0m �[31mERROR�[0m �[2msui_core::authority_server�[0m�[2m:�[0m Failed to send query response: frame size too big
�[2m2022-04-05T17:53:31.570725Z�[0m �[31mERROR�[0m �[2msui_core::authority_server�[0m�[2m:�[0m Failed to send query response: frame size too big
�[2m2022-04-05T17:53:31.704615Z�[0m �[31mERROR�[0m �[2msui_core::authority_server�[0m�[2m:�[0m Failed to send query response: frame size too big
�[2m2022-04-05T17:53:31.751000Z�[0m �[31mERROR�[0m �[2msui_core::authority_server�[0m�[2m:�[0m Failed to send query response: frame size too big
�[2m2022-04-05T17:53:31.814204Z�[0m �[31mERROR�[0m �[2msui_core::authority_server�[0m�[2m:�[0m Failed to send query response: frame size too big
�[2m2022-04-05T17:53:31.850133Z�[0m �[31mERROR�[0m �[2msui_core::authority_server�[0m�[2m:�[0m Failed to send query response: frame size too big
�[2m2022-04-05T17:53:31.912539Z�[0m �[31mERROR�[0m �[2msui_core::authority_server�[0m�[2m:�[0m Failed to send query response: frame size too big
�[2m2022-04-05T17:53:31.947891Z�[0m �[31mERROR�[0m �[2msui_core::authority_server�[0m�[2m:�[0m Failed to send query response: frame size too big
�[2m2022-04-05T17:53:32.010041Z�[0m �[31mERROR�[0m �[2msui_core::authority_server�[0m�[2m:�[0m Failed to send query response: frame size too big
�[2m2022-04-05T17:53:32.046656Z�[0m �[31mERROR�[0m �[2msui_core::authority_server�[0m�[2m:�[0m Failed to send query response: frame size too big
�[2m2022-04-05T17:53:32.110646Z�[0m �[31mERROR�[0m �[2msui_core::authority_server�[0m�[2m:�[0m Failed to send query response: frame size too big
�[2m2022-04-05T17:53:32.145246Z�[0m �[31mERROR�[0m �[2msui_core::authority_server�[0m�[2m:�[0m Failed to send query response: frame size too big
�[2m2022-04-05T17:53:32.208255Z�[0m �[31mERROR�[0m �[2msui_core::authority_server�[0m�[2m:�[0m Failed to send query response: frame size too big
�[2m2022-04-05T17:53:32.245502Z�[0m �[31mERROR�[0m �[2msui_core::authority_server�[0m�[2m:�[0m Failed to send query response: frame size too big
�[2m2022-04-05T17:53:32.308238Z�[0m �[31mERROR�[0m �[2msui_core::authority_server�[0m�[2m:�[0m Failed to send query response: frame size too big
�[2m2022-04-05T17:53:32.347491Z�[0m �[31mERROR�[0m �[2msui_core::authority_server�[0m�[2m:�[0m Failed to send query response: frame size too big
�[2m2022-04-05T17:53:32.347798Z�[0m �[32m INFO�[0m �[2mmicrobench�[0m�[2m:�[0m Received 50 responses.
�[2m2022-04-05T17:53:32.415702Z�[0m �[33m WARN�[0m �[2mmicrobench�[0m�[2m:�[0m Completed benchmark for TransactionsAndCerts
Total time: 2782520us, items: 100000, tx/sec: 35938.645544326726

Please sign in to comment.