Skip to content

Commit

Permalink
More WASM reference-types tests
Browse files Browse the repository at this point in the history
  • Loading branch information
lrubasze committed Jan 24, 2025
1 parent 69a5893 commit 1405636
Show file tree
Hide file tree
Showing 3 changed files with 234 additions and 0 deletions.
59 changes: 59 additions & 0 deletions radix-engine-tests/assets/wasm/reference_types_ref_func.wat
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
(module
;; Define a function table with an initial size of 3 and a maximum size of 4
(table $t 3 4 funcref)
(type $func_type (func (param i32 i32) (result i32)))

;; Initialize the table with the 3 functions
(elem (i32.const 0) $add $multiply $subtract)

;; Function 0: Adds two numbers
(func $add (type $func_type)
(local.get 0)
(local.get 1)
(i32.add)
)

;; Function 1: Multiplies two numbers
(func $multiply (type $func_type)
(local.get 0)
(local.get 1)
(i32.mul)
)

;; Function 2: Subtracts two numbers
(func $subtract (type $func_type)
(local.get 0)
(local.get 1)
(i32.sub)
)

;; Function that overwrites entry at given index in function table
(func $Test_f (param $0 i64) (result i64)
(local $result i32)

;; Overwrite function at given index
(table.set $t
(i32.const ${index}) ;; Index
(ref.func $add) ;; Reference to $add function
)

;; Encode () in SBOR at address 0x0
(i32.const 0)
(i32.const 92) ;; prefix
(i32.store8)
(i32.const 1)
(i32.const 4) ;; i32 value kind
(i32.store8)
(i32.const 2)
(i32.const 0) ;; value
(i32.store)

;; Return slice (ptr = 0, len = 6)
(i64.const 6)
)

;; Define memory with an initial size of 1 page (64 KiB)
(memory $0 1)
(export "memory" (memory $0))
(export "Test_f" (func $Test_f))
)
86 changes: 86 additions & 0 deletions radix-engine-tests/assets/wasm/reference_types_tables.wat
Original file line number Diff line number Diff line change
@@ -0,0 +1,86 @@
(module
;; Define a function table with an initial size of 3 and a maximum size of 4
(table $t 3 4 funcref)
(type $func_type (func (param i32 i32) (result i32)))

;; Initialize the table with the 3 functions
(elem (i32.const 0) $add $multiply $subtract)

;; Function 0: Adds two numbers
(func $add (type $func_type)
(local.get 0)
(local.get 1)
(i32.add)
)

;; Function 1: Multiplies two numbers
(func $multiply (type $func_type)
(local.get 0)
(local.get 1)
(i32.mul)
)

;; Function 2: Subtracts two numbers
(func $subtract (type $func_type)
(local.get 0)
(local.get 1)
(i32.sub)
)

;; Function to grow the table and add a new element
(func $grow_table
(local $ref_func funcref)
;; ref.func not yet supported in 'wasm-instrument'
;; see https://github.com/radixdlt/wasm-instrument/blob/405166c526aa60fa2af4e4b1122b156dbcc1bb15/src/stack_limiter/max_height.rs#L455
;; (local.set $ref_func
;; (ref.func $add)
;; )
;; use table.get instead to get funcref
(local.set $ref_func
(table.get $t
;; Get $add function at the index 0
(i32.const 0)
)
)
(table.grow $t
(local.get $ref_func) ;; Initial value of the new entries
(i32.const 1) ;; Number of entries to grow
)
;; table.grow returns previous size, drop it
(drop)
)

;; Function that grows table and calls some function in the table
(func $Test_f (param $0 i64) (result i64)
(local $result i32)

(call $grow_table)

(i32.const ${a})
(i32.const ${b})
(call_indirect
(type $func_type)
(i32.const ${index}) ;; Call function at given index
)
(local.set $result) ;; value

;; Encode () in SBOR at address 0x0
(i32.const 0)
(i32.const 92) ;; prefix
(i32.store8)
(i32.const 1)
(i32.const 4) ;; i32 value kind
(i32.store8)
(i32.const 2)
(local.get $result) ;; value
(i32.store)

;; Return slice (ptr = 0, len = 6)
(i64.const 6)
)

;; Define memory with an initial size of 1 page (64 KiB)
(memory $0 1)
(export "memory" (memory $0))
(export "Test_f" (func $Test_f))
)
89 changes: 89 additions & 0 deletions radix-engine-tests/tests/vm/wasm_non_mvp.rs
Original file line number Diff line number Diff line change
Expand Up @@ -367,4 +367,93 @@ mod reference_types {
// Assert
receipt.expect_commit(true);
}

#[test]
fn test_wasm_non_mvp_reference_types_tables_cuttlefish_failure() {
// Arrange
let code = wat2wasm(
&include_local_wasm_str!("reference_types_tables.wat")
.replace("${index}", "0")
.replace("${a}", "20")
.replace("${b}", "10"),
);

// Act
let mut ledger = get_ledger!(ProtocolVersion::Cuttlefish);

let receipt =
ledger.try_publish_package((code, single_function_package_definition("Test", "f")));

// Assert
receipt.expect_specific_failure(|error| match error {
RuntimeError::ApplicationError(ApplicationError::PackageError(
PackageError::InvalidWasm(PrepareError::ValidationError(message)),
)) => message.contains("reference types support is not enabled"),
_ => false,
});
}

#[test]
fn test_wasm_non_mvp_reference_types_tables_dugong_success() {
for (index, result) in [
("0", 30), // Add
("1", 200), // Multiply
("2", 10), // Subtract
] {
// Arrange
let code = wat2wasm(
&include_local_wasm_str!("reference_types_tables.wat")
.replace("${index}", index)
.replace("${a}", "20")
.replace("${b}", "10"),
);

// Act
let mut ledger = get_ledger!(ProtocolVersion::Dugong);

let receipt =
ledger.try_publish_package((code, single_function_package_definition("Test", "f")));
// Assert
let package_address = receipt.expect_commit(true).new_package_addresses()[0];

// Act
let receipt = manifest_execute_test_function!(ledger, package_address);

// Assert
let outcome: i32 = receipt.expect_commit(true).output(1);
assert_eq!(outcome, result);
}
}

#[test]
fn test_wasm_non_mvp_reference_types_ref_func_failure() {
// TODO WASM this test demonstrates that RefFunc (and some other instructions enabled in
// reference-types) are not supported in 'wasm-instrument'
// see https://github.com/radixdlt/wasm-instrument/blob/405166c526aa60fa2af4e4b1122b156dbcc1bb15/src/stack_limiter/max_height.rs#L455
// It would be perfect to update the 'wasm-instrument' crate.
// If not it shall be carefully investigated if it is safe to enable 'reference-types'
// (all WASM-related tests are running fine when 'reference-types' are enabled,
// as if the Rust compiler (LLVM) was not using those instructions)

// Arrange
let code = wat2wasm(
&include_local_wasm_str!("reference_types_ref_func.wat").replace("${index}", "0"),
);

// Act
let mut ledger = get_ledger!(ProtocolVersion::Dugong);

let receipt =
ledger.try_publish_package((code, single_function_package_definition("Test", "f")));
// Assert
receipt.expect_specific_failure(|error| match error {
RuntimeError::VmError(VmError::Native(NativeRuntimeError::Trap {
export_name,
error,
..
})) if export_name.eq("publish_wasm_advanced") => error
.contains("not yet implemented: some reference types proposal are not supported"),
_ => false,
});
}
}

0 comments on commit 1405636

Please sign in to comment.