diff --git a/.gitignore b/.gitignore index b4a04b9..a10fce2 100644 --- a/.gitignore +++ b/.gitignore @@ -18,6 +18,7 @@ Cargo.lock # Test outputs /tests/outputs/ *.wasm +!tests/fixtures/wasm/*.wasm # Logs *.log diff --git a/test_snapshots/test_fixture_registration_and_invocation.1.json b/test_snapshots/test_fixture_registration_and_invocation.1.json new file mode 100644 index 0000000..7dc2b31 --- /dev/null +++ b/test_snapshots/test_fixture_registration_and_invocation.1.json @@ -0,0 +1,135 @@ +{ + "generators": { + "address": 1, + "nonce": 0 + }, + "auth": [ + [], + [] + ], + "ledger": { + "protocol_version": 22, + "sequence_number": 0, + "timestamp": 0, + "network_id": "0000000000000000000000000000000000000000000000000000000000000000", + "base_reserve": 0, + "min_persistent_entry_ttl": 4096, + "min_temp_entry_ttl": 16, + "max_entry_ttl": 6312000, + "ledger_entries": [ + [ + { + "contract_data": { + "contract": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD2KM", + "key": { + "ledger_key_nonce": { + "nonce": 801925984706572462 + } + }, + "durability": "temporary" + } + }, + [ + { + "last_modified_ledger_seq": 0, + "data": { + "contract_data": { + "ext": "v0", + "contract": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD2KM", + "key": { + "ledger_key_nonce": { + "nonce": 801925984706572462 + } + }, + "durability": "temporary", + "val": "void" + } + }, + "ext": "v0" + }, + 6311999 + ] + ], + [ + { + "contract_data": { + "contract": "CBKMUZNFQIAL775XBB2W2GP5CNHBM5YGH6C3XB7AY6SUVO2IBU3VYK2V", + "key": "ledger_key_contract_instance", + "durability": "persistent" + } + }, + [ + { + "last_modified_ledger_seq": 0, + "data": { + "contract_data": { + "ext": "v0", + "contract": "CBKMUZNFQIAL775XBB2W2GP5CNHBM5YGH6C3XB7AY6SUVO2IBU3VYK2V", + "key": "ledger_key_contract_instance", + "durability": "persistent", + "val": { + "contract_instance": { + "executable": { + "wasm": "626e043a6d5a8dcf3478766a72fcf3a01b5ec28abebdade8759dbc23cd1aacab" + }, + "storage": [ + { + "key": { + "symbol": "c" + }, + "val": { + "i64": 2 + } + } + ] + } + } + } + }, + "ext": "v0" + }, + 4095 + ] + ], + [ + { + "contract_code": { + "hash": "626e043a6d5a8dcf3478766a72fcf3a01b5ec28abebdade8759dbc23cd1aacab" + } + }, + [ + { + "last_modified_ledger_seq": 0, + "data": { + "contract_code": { + "ext": { + "v1": { + "ext": "v0", + "cost_inputs": { + "ext": "v0", + "n_instructions": 243, + "n_functions": 13, + "n_globals": 3, + "n_table_entries": 1, + "n_types": 9, + "n_data_segments": 0, + "n_elem_segments": 0, + "n_imports": 5, + "n_exports": 6, + "n_data_segment_bytes": 0 + } + } + }, + "hash": "626e043a6d5a8dcf3478766a72fcf3a01b5ec28abebdade8759dbc23cd1aacab", + "code": "0061736d0100000001360960017e017e60027e7e017e60037e7e7e017e6000017e60037f7e7e017e60037f7e7e017f60000060027f7e017e60047f7e7e7e017e021f05016901320000016901310000016c01310001016c01300001016c015f0002030e0d030304050607070807070404080405017001010105030100100619037f01418080c0000b7f00418080c0000b7f00418080c0000b073b06066d656d6f7279020003676574000509696e6372656d656e740006015f00090a5f5f646174615f656e6403010b5f5f686561705f6261736503020af3040dc60103017f017e017f23808080800041106b22002480808080000240024002402000410f6a428ed00042021088808080000d00420021010c010b024002402000410f6a428ed00042021087808080002201a741ff0171220241c100460d00024020024107470d00200142088721010c020b000b2000410f6a2001108a8080800021010b20014280808080808080c0007c42808080808080808001540d002000410f6a2001108b8080800021010c010b200142088642078421010b200041106a24808080800020010b9a0204017f017e017f017e23808080800041106b220024808080800042012101024002402000410f6a428ed0004202108880808000450d00024002402000410f6a428ed00042021087808080002201a741ff0171220241c100460d00024020024107470d00200142088721030c020b000b2000410f6a2001108a8080800021030b200342017c210120034281808080808080c0007c42808080808080808001540d002000410f6a2001108b8080800021030c010b200142088642078421030b2000410f6a428ed00020034202108c808080001a0240024020014280808080808080c0007c42808080808080808001540d002000410f6a2001108b8080800021010c010b200142088642078421010b200041106a24808080800020010b0e00200020012002108f808080000b11002000200120021090808080004201510b02000b0c0020002001108d808080000b0c0020002001108e808080000b100020002001200220031091808080000b0a0020011080808080000b0a0020011081808080000b0c00200120021082808080000b0c00200120021083808080000b0e002001200220031084808080000b004f0e636f6e747261637473706563763000000000000000000000000367657400000000000000000100000007000000000000000000000009696e6372656d656e74000000000000000000000100000007001e11636f6e7472616374656e766d6574617630000000000000001600000000006f0e636f6e74726163746d65746176300000000000000005727376657200000000000006312e39332e3100000000000000000008727373646b7665720000003032322e302e3130233961316237356235303961353035336236373662303966646264323234666538633566326663643500f30b046e616d65001514636f756e7465725f666978747572652e7761736d01c00b1200405f5a4e3137736f726f62616e5f656e765f677565737435677565737433696e7431306f626a5f746f5f693634313768383665316531663538643834346237384501425f5a4e3137736f726f62616e5f656e765f677565737435677565737433696e7431326f626a5f66726f6d5f6936343137683064393630393634626533373839396445024a5f5a4e3137736f726f62616e5f656e765f6775657374356775657374366c656467657231376765745f636f6e74726163745f646174613137686234663737313039666434663062323645034a5f5a4e3137736f726f62616e5f656e765f6775657374356775657374366c656467657231376861735f636f6e74726163745f646174613137686334656531343033306334333337326245044a5f5a4e3137736f726f62616e5f656e765f6775657374356775657374366c656467657231377075745f636f6e74726163745f64617461313768363336343339613761316530393536304505036765740609696e6372656d656e7407425f5a4e3131736f726f62616e5f73646b3773746f726167653753746f7261676531326765745f696e7465726e616c313768643563613862346130383965333833304508425f5a4e3131736f726f62616e5f73646b3773746f726167653753746f7261676531326861735f696e7465726e616c313768313362656564633430666162613463634509015f0a6b5f5a4e37305f244c5424736f726f62616e5f73646b2e2e656e762e2e456e76247532302461732475323024736f726f62616e5f656e765f636f6d6d6f6e2e2e656e762e2e456e762447542431306f626a5f746f5f69363431376834623166313764363834313362623632450b6d5f5a4e37305f244c5424736f726f62616e5f73646b2e2e656e762e2e456e76247532302461732475323024736f726f62616e5f656e765f636f6d6d6f6e2e2e656e762e2e456e762447542431326f626a5f66726f6d5f69363431376833333434353331636234616663323339450c725f5a4e37305f244c5424736f726f62616e5f73646b2e2e656e762e2e456e76247532302461732475323024736f726f62616e5f656e765f636f6d6d6f6e2e2e656e762e2e456e762447542431377075745f636f6e74726163745f6461746131376836386261636563393935663364323039450d755f5a4e38305f244c5424736f726f62616e5f656e765f67756573742e2e67756573742e2e4775657374247532302461732475323024736f726f62616e5f656e765f636f6d6d6f6e2e2e656e762e2e456e762447542431306f626a5f746f5f69363431376838633334663161646233373437336437450e775f5a4e38305f244c5424736f726f62616e5f656e765f67756573742e2e67756573742e2e4775657374247532302461732475323024736f726f62616e5f656e765f636f6d6d6f6e2e2e656e762e2e456e762447542431326f626a5f66726f6d5f69363431376866393633376331653333303261316262450f7c5f5a4e38305f244c5424736f726f62616e5f656e765f67756573742e2e67756573742e2e4775657374247532302461732475323024736f726f62616e5f656e765f636f6d6d6f6e2e2e656e762e2e456e762447542431376765745f636f6e74726163745f646174613137686538666538653935646334666661373945107c5f5a4e38305f244c5424736f726f62616e5f656e765f67756573742e2e67756573742e2e4775657374247532302461732475323024736f726f62616e5f656e765f636f6d6d6f6e2e2e656e762e2e456e762447542431376861735f636f6e74726163745f646174613137686639386664623934303931656665663045117c5f5a4e38305f244c5424736f726f62616e5f656e765f67756573742e2e67756573742e2e4775657374247532302461732475323024736f726f62616e5f656e765f636f6d6d6f6e2e2e656e762e2e456e762447542431377075745f636f6e74726163745f646174613137686362373061366564353466663364343745071201000f5f5f737461636b5f706f696e746572004d0970726f64756365727302086c616e6775616765010452757374000c70726f6365737365642d6279010572757374631d312e39332e31202830316636646466373520323032362d30322d3131290094010f7461726765745f6665617475726573082b0b62756c6b2d6d656d6f72792b0f62756c6b2d6d656d6f72792d6f70742b1663616c6c2d696e6469726563742d6f7665726c6f6e672b0a6d756c746976616c75652b0f6d757461626c652d676c6f62616c732b136e6f6e7472617070696e672d6670746f696e742b0f7265666572656e63652d74797065732b087369676e2d657874" + } + }, + "ext": "v0" + }, + 4095 + ] + ] + ] + }, + "events": [] +} \ No newline at end of file diff --git a/tests/fixture_tests.rs b/tests/fixture_tests.rs index c5d2f0d..6cacdf5 100644 --- a/tests/fixture_tests.rs +++ b/tests/fixture_tests.rs @@ -126,5 +126,34 @@ fn test_fixture_inspect_command() { // Should succeed and show functions cmd.assert() .success() - .stdout(predicates::str::contains("Exported Functions")); + .stderr(predicates::str::contains("Exported Functions")); +} + +#[test] +fn test_fixture_registration_and_invocation() { + use soroban_sdk::{Env, Symbol}; + + let fixture_path = get_fixture_path("counter"); + if !fixture_path.exists() { + return; + } + + let wasm_bytes = fs::read(fixture_path).unwrap(); + let env = Env::default(); + let contract_id = env.register(&*wasm_bytes, ()); + + // Call increment + let first: i64 = env.invoke_contract( + &contract_id, + &Symbol::new(&env, "increment"), + soroban_sdk::vec![&env], + ); + assert_eq!(first, 1); + + let second: i64 = env.invoke_contract( + &contract_id, + &Symbol::new(&env, "increment"), + soroban_sdk::vec![&env], + ); + assert_eq!(second, 2); } diff --git a/tests/fixtures/build_fixtures.sh b/tests/fixtures/build_fixtures.sh new file mode 100644 index 0000000..46f25d8 --- /dev/null +++ b/tests/fixtures/build_fixtures.sh @@ -0,0 +1,11 @@ +#!/bin/bash +set -e +WASM_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)/wasm" +mkdir -p "$WASM_DIR" +for dir in "$(dirname "${BASH_SOURCE[0]}")"/contracts/*/; do + if [ -f "${dir}Cargo.toml" ]; then + name=$(basename "$dir") + (cd "$dir" && cargo build --release --target wasm32-unknown-unknown) + cp "${dir}target/wasm32-unknown-unknown/release/${name//-/_}.wasm" "$WASM_DIR/${name}.wasm" + fi +done diff --git a/tests/fixtures/contracts/Cargo.toml b/tests/fixtures/contracts/Cargo.toml index a9ccd75..b08d6e6 100644 --- a/tests/fixtures/contracts/Cargo.toml +++ b/tests/fixtures/contracts/Cargo.toml @@ -2,7 +2,7 @@ members = [ "counter", "echo", - "panic", + "always_panic", "budget_heavy", "cross_contract", ] diff --git a/tests/fixtures/contracts/panic/Cargo.toml b/tests/fixtures/contracts/always_panic/Cargo.toml similarity index 71% rename from tests/fixtures/contracts/panic/Cargo.toml rename to tests/fixtures/contracts/always_panic/Cargo.toml index 945ae78..47277bc 100644 --- a/tests/fixtures/contracts/panic/Cargo.toml +++ b/tests/fixtures/contracts/always_panic/Cargo.toml @@ -1,19 +1,15 @@ [package] -name = "panic-fixture" +name = "always-panic-fixture" version = "0.1.0" edition = "2021" publish = false [lib] crate-type = ["cdylib"] -doctest = false [dependencies] soroban-sdk = { version = "22.0.0" } -[dev-dependencies] -soroban-sdk = { version = "22.0.0", features = ["testutils"] } - [profile.release] opt-level = "z" overflow-checks = true diff --git a/tests/fixtures/contracts/always_panic/src/lib.rs b/tests/fixtures/contracts/always_panic/src/lib.rs new file mode 100644 index 0000000..060dd66 --- /dev/null +++ b/tests/fixtures/contracts/always_panic/src/lib.rs @@ -0,0 +1,12 @@ +#![no_std] +use soroban_sdk::{contract, contractimpl, Env}; + +#[contract] +pub struct AlwaysPanic; + +#[contractimpl] +impl AlwaysPanic { + pub fn panic(_env: Env) { + panic!("p") + } +} diff --git a/tests/fixtures/contracts/panic/src/test.rs b/tests/fixtures/contracts/always_panic/src/test.rs similarity index 100% rename from tests/fixtures/contracts/panic/src/test.rs rename to tests/fixtures/contracts/always_panic/src/test.rs diff --git a/tests/fixtures/contracts/budget_heavy/src/lib.rs b/tests/fixtures/contracts/budget_heavy/src/lib.rs index 1184736..85d57ea 100644 --- a/tests/fixtures/contracts/budget_heavy/src/lib.rs +++ b/tests/fixtures/contracts/budget_heavy/src/lib.rs @@ -1,5 +1,4 @@ #![no_std] - use soroban_sdk::{contract, contractimpl, symbol_short, Env, Vec}; #[contract] @@ -7,41 +6,12 @@ pub struct BudgetHeavy; #[contractimpl] impl BudgetHeavy { - /// Perform a budget-heavy operation with many iterations - pub fn heavy_computation(env: Env, iterations: u32) -> u32 { - let mut result = 0u32; - for i in 0..iterations { - // Perform some computation - result = result.wrapping_add(i); - - // Store intermediate results (costs budget) - env.storage() - .instance() - .set(&symbol_short!("iter"), &i); - } - result - } - - /// Allocate and manipulate large vectors - pub fn heavy_memory(env: Env, size: u32) -> u32 { - let mut vec = Vec::::new(&env); - for i in 0..size { - vec.push_back(i); - } - vec.len() - } - - /// Nested loops for CPU-intensive operations - pub fn nested_loops(env: Env, n: u32) -> u32 { - let mut sum = 0u32; + pub fn heavy(env: Env, n: u32) -> u32 { + let mut v = Vec::::new(&env); for i in 0..n { - for j in 0..n { - sum = sum.wrapping_add(i.wrapping_mul(j)); - } + v.push_back(i); + env.storage().instance().set(&symbol_short!("i"), &i); } - sum + v.len() } } - -#[cfg(test)] -mod test; diff --git a/tests/fixtures/contracts/counter/src/lib.rs b/tests/fixtures/contracts/counter/src/lib.rs index a29b7f3..9e5bce2 100644 --- a/tests/fixtures/contracts/counter/src/lib.rs +++ b/tests/fixtures/contracts/counter/src/lib.rs @@ -1,5 +1,4 @@ #![no_std] - use soroban_sdk::{contract, contractimpl, symbol_short, Env}; #[contract] @@ -7,43 +6,20 @@ pub struct Counter; #[contractimpl] impl Counter { - /// Initialize the counter with a starting value - pub fn init(env: Env, value: i64) { - env.storage().instance().set(&symbol_short!("count"), &value); - } - - /// Increment the counter by 1 pub fn increment(env: Env) -> i64 { - let current: i64 = env - .storage() - .instance() - .get(&symbol_short!("count")) - .unwrap_or(0); - let new_value = current + 1; - env.storage().instance().set(&symbol_short!("count"), &new_value); - new_value - } - - /// Decrement the counter by 1 - pub fn decrement(env: Env) -> i64 { - let current: i64 = env + let val: i64 = env .storage() .instance() - .get(&symbol_short!("count")) - .unwrap_or(0); - let new_value = current - 1; - env.storage().instance().set(&symbol_short!("count"), &new_value); - new_value + .get(&symbol_short!("c")) + .unwrap_or(0) + + 1; + env.storage().instance().set(&symbol_short!("c"), &val); + val } - - /// Get the current counter value pub fn get(env: Env) -> i64 { env.storage() .instance() - .get(&symbol_short!("count")) + .get(&symbol_short!("c")) .unwrap_or(0) } } - -#[cfg(test)] -mod test; diff --git a/tests/fixtures/contracts/cross_contract/src/lib.rs b/tests/fixtures/contracts/cross_contract/src/lib.rs index 7ccd126..7896489 100644 --- a/tests/fixtures/contracts/cross_contract/src/lib.rs +++ b/tests/fixtures/contracts/cross_contract/src/lib.rs @@ -1,55 +1,12 @@ #![no_std] - -use soroban_sdk::{contract, contractimpl, symbol_short, Address, Env, Val}; +use soroban_sdk::{contract, contractimpl, Address, Env, Symbol, Val, Vec}; #[contract] -pub struct CrossContractCaller; +pub struct Caller; #[contractimpl] -impl CrossContractCaller { - /// Call another contract's function - /// - /// # Arguments - /// * `callee` - Address of the contract to call - /// * `function` - Function name to call (as symbol) - /// * `args` - Arguments to pass to the function - pub fn call_contract( - env: Env, - callee: Address, - function: soroban_sdk::Symbol, - args: Vec, - ) -> Val { - env.invoke_contract(&callee, &function, &args) - } - - /// Call another contract's echo function with a value - pub fn call_echo(env: Env, callee: Address, value: Val) -> Val { - let args = soroban_sdk::vec![&env, value]; - env.invoke_contract(&callee, &symbol_short!("echo"), &args) - } - - /// Chain call: call a contract that calls another contract - pub fn chain_call( - env: Env, - first: Address, - second: Address, - value: Val, - ) -> Val { - // Call first contract - let first_result = env.invoke_contract( - &first, - &symbol_short!("echo"), - &soroban_sdk::vec![&env, value], - ); - - // Call second contract with first result - env.invoke_contract( - &second, - &symbol_short!("echo"), - &soroban_sdk::vec![&env, first_result], - ) +impl Caller { + pub fn call(env: Env, c: Address, f: Symbol, a: Vec) -> Val { + env.invoke_contract(&c, &f, a) } } - -#[cfg(test)] -mod test; diff --git a/tests/fixtures/contracts/echo/src/lib.rs b/tests/fixtures/contracts/echo/src/lib.rs index 688e42f..9ac0073 100644 --- a/tests/fixtures/contracts/echo/src/lib.rs +++ b/tests/fixtures/contracts/echo/src/lib.rs @@ -1,5 +1,4 @@ #![no_std] - use soroban_sdk::{contract, contractimpl, Env, Val}; #[contract] @@ -7,26 +6,7 @@ pub struct Echo; #[contractimpl] impl Echo { - /// Echo function that returns its input unchanged - pub fn echo(_env: Env, value: Val) -> Val { - value - } - - /// Echo a string - pub fn echo_string(_env: Env, value: soroban_sdk::String) -> soroban_sdk::String { - value - } - - /// Echo an integer - pub fn echo_i64(_env: Env, value: i64) -> i64 { - value - } - - /// Echo a boolean - pub fn echo_bool(_env: Env, value: bool) -> bool { - value + pub fn echo(_env: Env, v: Val) -> Val { + v } } - -#[cfg(test)] -mod test; diff --git a/tests/fixtures/contracts/panic/src/lib.rs b/tests/fixtures/contracts/panic/src/lib.rs deleted file mode 100644 index 42bbc25..0000000 --- a/tests/fixtures/contracts/panic/src/lib.rs +++ /dev/null @@ -1,29 +0,0 @@ -#![no_std] - -use soroban_sdk::{contract, contractimpl, Env}; - -#[contract] -pub struct PanicContract; - -#[contractimpl] -impl PanicContract { - /// Always panics - useful for error testing - pub fn panic(_env: Env) { - panic!("This contract always panics"); - } - - /// Panics with a custom message - pub fn panic_with_message(_env: Env, message: soroban_sdk::String) { - panic!("{}", message); - } - - /// Panics when called with a specific value - pub fn panic_if_true(_env: Env, should_panic: bool) { - if should_panic { - panic!("Panic triggered by condition"); - } - } -} - -#[cfg(test)] -mod test; diff --git a/tests/fixtures/wasm/always_panic.wasm b/tests/fixtures/wasm/always_panic.wasm new file mode 100644 index 0000000..3346bb7 Binary files /dev/null and b/tests/fixtures/wasm/always_panic.wasm differ diff --git a/tests/fixtures/wasm/budget_heavy.wasm b/tests/fixtures/wasm/budget_heavy.wasm new file mode 100644 index 0000000..9d729d1 Binary files /dev/null and b/tests/fixtures/wasm/budget_heavy.wasm differ diff --git a/tests/fixtures/wasm/counter.wasm b/tests/fixtures/wasm/counter.wasm new file mode 100644 index 0000000..8555359 Binary files /dev/null and b/tests/fixtures/wasm/counter.wasm differ diff --git a/tests/fixtures/wasm/cross_contract.wasm b/tests/fixtures/wasm/cross_contract.wasm new file mode 100644 index 0000000..439cc4c Binary files /dev/null and b/tests/fixtures/wasm/cross_contract.wasm differ diff --git a/tests/fixtures/wasm/echo.wasm b/tests/fixtures/wasm/echo.wasm new file mode 100644 index 0000000..b371af8 Binary files /dev/null and b/tests/fixtures/wasm/echo.wasm differ