Skip to content

Commit 6a2da47

Browse files
Merge branch 'abk/run-641-stable-memory-integrity-test' into 'master'
RUN-641: Stable memory integrity test Introduce a property test that applies a random sequence of stable memory operations to a canister and verifies the final stable memory state. See merge request dfinity-lab/public/ic!12573
2 parents 857c6b7 + 8220223 commit 6a2da47

File tree

8 files changed

+746
-0
lines changed

8 files changed

+746
-0
lines changed

.gitlab/CODEOWNERS

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -209,6 +209,7 @@ go_deps.bzl @dfinity-lab/teams/idx
209209
/rs/rust_canisters/proxy_canister/ @dfinity-lab/teams/networking-team
210210
/rs/rust_canisters/response_payload_test/ @dfinity-lab/teams/runtime-owners
211211
/rs/rust_canisters/stable_structures/ @dfinity-lab/teams/runtime-owners
212+
/rs/rust_canisters/stable_memory_integrity @dfinity-lab/teams/runtime-owners
212213
/rs/rust_canisters/xnet_test/ @dfinity-lab/teams/message-routing-owners
213214
/rs/scenario_tests/ @dfinity-lab/teams/ic-testing-verification
214215
/rs/sns/ @dfinity-lab/teams/nns-team
Lines changed: 54 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,54 @@
1+
load("//bazel:canisters.bzl", "rust_canister")
2+
load("@rules_rust//rust:defs.bzl", "rust_library", "rust_test")
3+
4+
package(default_visibility = ["//visibility:public"])
5+
6+
rust_library(
7+
name = "stable_memory_integrity",
8+
srcs = glob(["src/**/*.rs"]),
9+
aliases = {},
10+
crate_name = "ic_stable_memory_integrity",
11+
proc_macro_deps = [],
12+
version = "0.8.0",
13+
deps = [
14+
"@crate_index//:candid",
15+
"@crate_index//:ic-cdk",
16+
"@crate_index//:serde",
17+
],
18+
)
19+
20+
rust_canister(
21+
name = "stable_memory_integrity_canister",
22+
srcs = ["bin/main.rs"],
23+
proc_macro_deps = ["@crate_index//:ic-cdk-macros"],
24+
service_file = ":stable_memory_integrity.did",
25+
deps = [
26+
"//rs/rust_canisters/stable_memory_integrity",
27+
"@crate_index//:candid",
28+
"@crate_index//:ic-cdk",
29+
],
30+
)
31+
32+
rust_test(
33+
name = "tests",
34+
srcs = ["tests/stable_memory_integrity.rs"],
35+
aliases = {},
36+
crate_root = "tests/stable_memory_integrity.rs",
37+
data = [
38+
":stable_memory_integrity_canister.wasm",
39+
],
40+
env = {
41+
"STABLE_MEMORY_INTEGRITY_CANISTER_WASM_PATH": "$(rootpath :stable_memory_integrity_canister.wasm)",
42+
},
43+
proc_macro_deps = [],
44+
deps = [
45+
"//rs/rust_canisters/canister_test",
46+
"//rs/rust_canisters/stable_memory_integrity",
47+
"//rs/state_machine_tests",
48+
"//rs/types/types",
49+
"@crate_index//:assert_matches",
50+
"@crate_index//:candid",
51+
"@crate_index//:lazy_static",
52+
"@crate_index//:proptest",
53+
],
54+
)
Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
[package]
2+
name = "stable_memory_integrity"
3+
version = "0.1.0"
4+
edition = "2021"
5+
6+
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
7+
8+
[dependencies]
9+
assert_matches = "1.5.0"
10+
candid = "0.8.1"
11+
canister-test = { path = "../canister_test" }
12+
ic-cdk = "0.6.0"
13+
ic-cdk-macros = "0.6.0"
14+
ic-state-machine-tests = { path = "../../state_machine_tests" }
15+
ic-types = { path = "../../types/types" }
16+
lazy-static = "1.4.0"
17+
serde = "1.0.136"
18+
proptest = "1.2.0"
19+
20+
[[bin]]
21+
name = "stable_memory_integrity"
22+
path = "bin/main.rs"
Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
# Stable Memory Integrity Canister
2+
3+
This canister can perform arbitrary operations on stable memory. It's purpose is
4+
to used when testing the correctness of the stable memory implementation in the
5+
replica.
Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
use ic_cdk::api::stable::{stable64_read, stable64_size};
2+
use ic_cdk_macros::{query, update};
3+
4+
use ic_stable_memory_integrity::StableOperationResult;
5+
6+
#[update]
7+
fn perform_and_check_ops(ops: Vec<StableOperationResult>) {
8+
for op in ops {
9+
op.perform_and_check()
10+
}
11+
}
12+
13+
#[query]
14+
fn final_size() -> u64 {
15+
stable64_size()
16+
}
17+
18+
#[query]
19+
fn read(start: u64, length: u64) -> Vec<u8> {
20+
let mut result = vec![0; length as usize];
21+
stable64_read(start, &mut result);
22+
result
23+
}
24+
25+
fn main() {}
Lines changed: 74 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,74 @@
1+
use candid::CandidType;
2+
use ic_cdk::api::stable::{
3+
stable64_grow, stable64_read, stable64_size, stable64_write, stable_read, stable_write,
4+
};
5+
use serde::{Deserialize, Serialize};
6+
7+
#[derive(Clone, Debug, Serialize, Deserialize, CandidType, PartialEq)]
8+
pub enum StableOperationResult {
9+
Size(u64),
10+
Grow {
11+
new_pages: u64,
12+
result: Result<u64, ()>,
13+
},
14+
Read {
15+
start: u64,
16+
result: Vec<u8>,
17+
},
18+
Write {
19+
start: u64,
20+
contents: Vec<u8>,
21+
},
22+
Read32 {
23+
start: u32,
24+
result: Vec<u8>,
25+
},
26+
Write32 {
27+
start: u32,
28+
contents: Vec<u8>,
29+
},
30+
}
31+
32+
impl StableOperationResult {
33+
pub fn perform_and_check(self) {
34+
match self {
35+
StableOperationResult::Size(expected_size) => {
36+
let result = stable64_size();
37+
assert_eq!(expected_size, result);
38+
}
39+
StableOperationResult::Grow { new_pages, result } => {
40+
let initial_size = stable64_size();
41+
let actual_result = stable64_grow(new_pages).map_err(|_| ());
42+
assert_eq!(result, actual_result);
43+
let new_size = stable64_size();
44+
if actual_result.is_ok() {
45+
assert_eq!(new_size, initial_size + new_pages);
46+
} else {
47+
assert_eq!(new_size, initial_size);
48+
}
49+
}
50+
StableOperationResult::Read { start, result } => {
51+
let mut actual_result = vec![0; result.len()];
52+
stable64_read(start, &mut actual_result);
53+
assert_eq!(result, actual_result);
54+
}
55+
StableOperationResult::Write { start, contents } => {
56+
stable64_write(start, &contents);
57+
let mut result = vec![0; contents.len()];
58+
stable64_read(start, &mut result);
59+
assert_eq!(contents, result);
60+
}
61+
StableOperationResult::Read32 { start, result } => {
62+
let mut actual_result = vec![0; result.len()];
63+
stable_read(start, &mut actual_result);
64+
assert_eq!(result, actual_result);
65+
}
66+
StableOperationResult::Write32 { start, contents } => {
67+
stable_write(start, &contents);
68+
let mut result = vec![0; contents.len()];
69+
stable_read(start, &mut result);
70+
assert_eq!(contents, result);
71+
}
72+
}
73+
}
74+
}
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
service : {}

0 commit comments

Comments
 (0)