Starcoin has released version v1.12.3-beta. Version 1.12 focuses on improving the integration-test capability of the (mpm
) Move Package Manager and optimizing the command-line development experience for developers.
As the DApp's Move contract becomes more and more complex, we face some complex test scenarios:
scene one
Project A depends on Starcoin Move Framework, and Project B depends on Project A. At this time, if the Project B needs to test locally, it needs the integration test tool to provide the following capabilities:
Project B needs to be able to test the environment locally and deploy the Move contract of project A to the account address of project A. or
Project B forks a branch from the test network or the main network as a test environment, so that project B can directly test based on the contracts and states that have been deployed on the network.
scene two
The contract of project A relies on the historical state on the chain for some verification, such as obtaining the user's STC balance at a certain historical height. At this time, integration tests need to provide the following capabilities:
Call chain related APIs.
The post-test depends on the output of the pre-test.
The version released this time mainly focuses on these two complex scenarios to improve integration testing and command-line tools, and mainly provide or enhance the following features:
Command output and template variables, support for both integration testing and command line tools.
Use arbitrary addresses in integration tests for testing.
Enhanced integration testing capabilities of
fork
mode, developers can test locally based on a certain high state of the mainnet or testnet.Added
package
anddeploy
integration testing support to facilitate integration testing through two-phase upgrades and DAO upgrades.
Detailed description and usage scenarios
mpm integration-test
1. Command output and template variables
For instructions with output results (such as faucet, call, call-api, etc.), the output results will be saved in the running environment, and subsequent instructions can obtain these results, and use template variables to use some fields in the results as follow-up the input parameters of the instruction.
This feature can meet the requirement that some tests need to rely on the output result of the pre-order command as the input parameter.
Example of use:
//# init -n dev --debug //# faucet --addr creator --amount 12345000000 //# call 0x1::Account::balance --type-args 0x1::STC::STC --args {{$.faucet[0].txn.raw_txn.decoded_payload.ScriptFunction.args[0]}} //# call-api state.get_resource ["{{$.faucet[0].txn.raw_txn.decoded_payload.ScriptFunction.args[0]}}","0x00000000000000000000000000000001::Account::Balance<0x00000000000000000000000000000001::STC::STC>",{"decode":true}] //# run --signers creator --args {{$.call[0]}}u128 --args {{$.call-api[0].json.token.value}}u128 --args {{$.faucet[0].txn.raw_txn.decoded_payload.ScriptFunction.args[0]}} script{ fun main(_sender: signer, balance_from_call: u128, balance_from_api:u128, to: address){ assert!(@creator==to, 101); assert!(balance_from_api == balance_from_call, 102); assert!(balance_from_call == 12345000000, 103); } }
The
--debug
option can display the command output on the command line for easy debugging.$.faucet[0], $.call[0], $.call-api[0]
The array index in the command is the call number of the corresponding command in the entire test file, starting from 0.
Output format of common commands:
faucet
Example output:
{ "output":{ "events":[ ... ], "gas_used":"367377", "status":"Executed", "write_set":[ ... ] }, "txn":{ "authenticator":{ "Ed25519":{ "public_key":"0x4cb5abf6ad79fbf5abbccafcc269d85cd2651ed4b885b5869f241aedf0a5ba29", "signature":"0xd3d8df4f5f4a2faf1bcfacfb40e981d6307543c0ab0a4482b1e3fc27fcdb896fc74dd983620110c14afd558c5d14e7553096d7be4ec3d162628addaf10dc0201" } }, "raw_txn":{ "chain_id":254, "decoded_payload":{ "ScriptFunction":{ "args":[ "0x662ba5a1a1da0f1c70a9762c7eeb7aaf", 12345000000 ], "function":"peer_to_peer_v2", "module":"0x00000000000000000000000000000001::TransferScripts", "ty_args":[ "0x00000000000000000000000000000001::STC::STC" ] } }, "expiration_timestamp_secs":"3610", "gas_token_code":"0x1::STC::STC", "gas_unit_price":"1", "max_gas_amount":"40000000", "payload":"0x02000000000000000000000000000000010f5472616e73666572536372697074730f706565725f746f5f706565725f76320107000000000000000000000000000000010353544303535443000210662ba5a1a1da0f1c70a9762c7eeb7aaf1040c0d1df020000000000000000000000", "sender":"0x0000000000000000000000000a550c18", "sequence_number":"0" }, "transaction_hash":"0xcccd3fcae2b32f699713d63216651c945127b88e99b5befe705b64b48f1a741e" } }
scenes to be used:
Get the address of the faucet target account:
{{$.faucet[0].txn.raw_txn.decoded_payload.ScriptFunction.args[0]}}
Get the amount of faucet: {{$.faucet[0].txn.raw_txn.decoded_payload.ScriptFunction.args[1]}}
call
The output of the call command depends on the output of the called contract function.
scenes to be used:
Get the result of the call command
call-api
The output result of the call-api command depends on the result returned by the called API interface.
scenes to be used:
Get the result of the call-api command
block
Example output:
{ "author":"0x907ce56940b2c38ac54200e1400976a9", "author_auth_key":null, "chain_id":{ "id":251 }, "number":6487001, "parent_gas_used":0, "parent_hash":"0x58d3b6aa35ba1f52c809382b876950b6038c4ce9fa078358c0fcf0b072e5ae3d", "timestamp":1658479121636, "uncles":0 }
scenes to be used:
Get block height:
{{$.block[0].number}}
get block parent_hash:
{{$.block[0].parent_hash}}
package
Example output:
{ "file":"/tmp/.tmpnok0M6/0x3c6b00fadc6b4f37fa6e2c6c0949e97c89b00c07c0d1f1761671e6fe18792676.blob", "hex":"0x662ba5a1a1da0f1c70a9762c7eeb7aaf0146a11ceb0b040000000601000203020505070107080b0813100c2307000000010000000004746573740568656c6c6f662ba5a1a1da0f1c70a9762c7eeb7aaf000100000001020000", "package_hash":"0x3c6b00fadc6b4f37fa6e2c6c0949e97c89b00c07c0d1f1761671e6fe18792676" }
scenes to be used:
Get the package file path:
{{$.package[0].file}}
Get the package hash:
{{$.package[0].package_hash}}
Troubleshooting:
call-api
parameter exception:
Error: Invalid command. Got error error: Invalid value "xxxx" for '<params>': expected `,` or `]` at line 1 column 3
Cause: The input parameter did not match the expected parameter.
Solution:
Check whether the parameters conform to the interface definition;
The call-api data parameter is a json list, and there can be no spaces between list elements
2. Test with arbitrary address
The init
initialization command option adds --addresses named=address
to specify any address
for testing, no longer need to specify public-keys
.
//# init -n dev --addresses alice=0x662ba5a1a1da0f1c70a9762c7eeb7aaf
3. Support call-api calls in fork mode from remote nodes
Version 1.11 can fork from a certain height of a remote node, keep the state before the fork, and update the state based on the state of the fork. However, after updating the state, calling the call-api command will read the state from the remote node, and cannot obtain the locally updated state after fork.
1.12 supports call-api calls in fork mode.
Example of use
//# init --rpc <http://barnard.seed.starcoin.org> --block-number 6487000 //# faucet --addr creator --amount 100000000000 //# block //# call-api chain.get_block_by_number [6487001] //# run --signers creator --args {{$.call-api[0].header.number}}u64 --args {{$.call-api[0].header.block_hash}} script{ use StarcoinFramework::Vector; use StarcoinFramework::Debug; fun main(_sender: signer, block_number: u64, block_hash: vector<u8>){ Debug::print(&block_hash); assert!(block_number == 6487001, 100); assert!(Vector::length(&block_hash) == 32, 101); // 0x2e12...fc8e is the block hash of number 6487001 on barnard network. assert!(x"2e121adfe4bacb96de73e8b1afa5a67b8276bc4319fc3b4c0f346d12751ffc8e" != block_hash, 1002); } }