Skip to content

Commit

Permalink
Merge branch 'elias/pocket-ic-api-tests' into 'master'
Browse files Browse the repository at this point in the history
feat(VER-2485): Write some more API tests for PocketIC

Use assert statements and add more tests 

See merge request dfinity-lab/public/ic!14761
  • Loading branch information
fxgst committed Sep 13, 2023
2 parents dddd3bc + 425b40c commit efe4ff6
Show file tree
Hide file tree
Showing 4 changed files with 242 additions and 103 deletions.
25 changes: 15 additions & 10 deletions packages/pocket-ic/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,8 +8,6 @@ use reqwest::Url;
use serde::de::DeserializeOwned;
use serde::{Deserialize, Serialize};
use serde_bytes::ByteBuf;
use serde_json::json;
use std::collections::HashMap;
use std::fmt;
use std::path::PathBuf;
use std::process::Command;
Expand Down Expand Up @@ -57,16 +55,17 @@ impl PocketIc {
) -> Result<Self, String> {
let server_url = Self::start_or_reuse_server();
let reqwest_client = reqwest::blocking::Client::new();
let mut map = HashMap::new();
map.insert("checkpoint_name", name);
let cp = Checkpoint {
checkpoint_name: name.to_string(),
};
let response = reqwest_client
.post(server_url.join("instances/").unwrap())
.json(&json!(map))
.json(&cp)
.send()
.expect("Failed to get result");
let status = response.status();
match status {
reqwest::StatusCode::OK => {
reqwest::StatusCode::CREATED => {
let instance_id = response.text().expect("Failed to get text");
let instance_url = server_url
.join("instances/")
Expand All @@ -80,7 +79,7 @@ impl PocketIc {
reqwest_client,
})
}
reqwest::StatusCode::NOT_FOUND => {
reqwest::StatusCode::BAD_REQUEST => {
Err(format!("Could not find snapshot named '{name}'."))
}
_ => Err(format!(
Expand Down Expand Up @@ -148,11 +147,12 @@ impl PocketIc {
.instance_url
.join("tick_and_create_checkpoint/")
.unwrap();
let mut map = HashMap::new();
map.insert("checkpoint_name", name);
let cp = Checkpoint {
checkpoint_name: name.to_string(),
};
self.reqwest_client
.post(url)
.json(&json!(map))
.json(&cp)
.send()
.expect("Failed to get result")
.text()
Expand Down Expand Up @@ -495,6 +495,11 @@ pub struct CanisterCall {
pub arg: Vec<u8>,
}

#[derive(Clone, Serialize, Deserialize, Debug)]
pub struct Checkpoint {
pub checkpoint_name: String,
}

/// Call a canister candid query method, anonymous.
pub fn query_candid<Input, Output>(
env: &PocketIc,
Expand Down
10 changes: 8 additions & 2 deletions packages/pocket-ic/tests/tests.rs
Original file line number Diff line number Diff line change
Expand Up @@ -35,9 +35,15 @@ fn test_snapshot() {

let reply = call_counter_can(&pic, can_id, "write");
assert_eq!(reply, WasmResult::Reply(vec![1, 0, 0, 0]));
pic.tick_and_create_checkpoint("my_ckpnt");
pic.tick_and_create_checkpoint("my_cp");

let other_ic = PocketIc::new_from_snapshot("my_ckpnt").unwrap();
let fail = PocketIc::new_from_snapshot("does not exist").err().unwrap();
assert!(fail
.to_string()
.to_lowercase()
.contains("could not find snapshot"));

let other_ic = PocketIc::new_from_snapshot("my_cp").unwrap();
let reply = call_counter_can(&other_ic, can_id, "write");
assert_eq!(reply, WasmResult::Reply(vec![2, 0, 0, 0]));
}
Expand Down
32 changes: 14 additions & 18 deletions rs/pocket_ic_server/src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ use ic_registry_subnet_type::SubnetType;
use ic_state_machine_tests::{StateMachine, StateMachineBuilder, StateMachineConfig};
use ic_types::{CanisterId, Cycles, PrincipalId};
use itertools::Itertools;
use pocket_ic::{CanisterCall, RawCanisterId, Request, Request::*};
use pocket_ic::{CanisterCall, Checkpoint, RawCanisterId, Request, Request::*};
use serde::Serialize;
use std::collections::HashMap;
use std::fs::File;
Expand Down Expand Up @@ -285,19 +285,18 @@ async fn create_instance(
instances_sequence_counter: counter,
runtime,
}): State<AppState>,
body: Option<axum::extract::Json<HashMap<String, String>>>,
body: Option<axum::extract::Json<Checkpoint>>,
) -> (StatusCode, String) {
match body {
Some(body) => {
let checkpoint_name = body.get("checkpoint_name").unwrap().clone();
let checkpoints = checkpoints.read().await;
if !checkpoints.contains_key(&checkpoint_name) {
if !checkpoints.contains_key(&body.checkpoint_name) {
return (
StatusCode::NOT_FOUND,
format!("Checkpoint {} does not exist.", checkpoint_name),
StatusCode::BAD_REQUEST,
format!("Checkpoint '{}' does not exist.", body.checkpoint_name),
);
}
let proto_dir = checkpoints.get(&checkpoint_name).unwrap();
let proto_dir = checkpoints.get(&body.checkpoint_name).unwrap();
let new_instance_dir = TempDir::new().expect("Failed to create tempdir");
copy_dir(proto_dir.path(), new_instance_dir.path())
.expect("Failed to copy state directory");
Expand All @@ -311,7 +310,7 @@ async fn create_instance(
let mut instance_map = instance_map.write().await;
let instance_id = counter.fetch_add(1, Ordering::Relaxed).to_string();
instance_map.insert(instance_id.clone(), RwLock::new(sm));
(StatusCode::OK, instance_id)
(StatusCode::CREATED, instance_id)
}
None => {
let sm = tokio::task::spawn_blocking(|| create_state_machine(None, runtime))
Expand All @@ -320,7 +319,7 @@ async fn create_instance(
let mut guard = instance_map.write().await;
let instance_id = counter.fetch_add(1, Ordering::Relaxed).to_string();
guard.insert(instance_id.clone(), RwLock::new(sm));
(StatusCode::OK, instance_id)
(StatusCode::CREATED, instance_id)
}
}
}
Expand Down Expand Up @@ -365,16 +364,13 @@ async fn tick_and_create_checkpoint(
..
}): State<AppState>,
Path(id): Path<InstanceId>,
axum::extract::Json(payload): axum::extract::Json<HashMap<String, String>>,
axum::extract::Json(payload): axum::extract::Json<Checkpoint>,
) -> (StatusCode, String) {
let checkpoint_name = payload
.get("checkpoint_name")
.expect("Missing checkpoint_name field");
let mut checkpoints = checkpoints.write().await;
if checkpoints.contains_key(checkpoint_name) {
if checkpoints.contains_key(&payload.checkpoint_name) {
return (
StatusCode::CONFLICT,
format!("Checkpoint {} already exists.", checkpoint_name),
format!("Checkpoint {} already exists.", payload.checkpoint_name),
);
}
let guard_map = instance_map.read().await;
Expand All @@ -384,12 +380,12 @@ async fn tick_and_create_checkpoint(
guard_sm.set_checkpoints_enabled(true);
guard_sm.tick();
guard_sm.set_checkpoints_enabled(false);
// copy state directory to named location
// Copy state directory to named location.
let checkpoint_dir = TempDir::new().expect("Failed to create tempdir");
copy_dir(guard_sm.state_dir.path(), checkpoint_dir.path())
.expect("Failed to copy state directory");
checkpoints.insert(checkpoint_name.clone(), Arc::new(checkpoint_dir));
(StatusCode::OK, "Success".to_string())
checkpoints.insert(payload.checkpoint_name, Arc::new(checkpoint_dir));
(StatusCode::CREATED, "Checkpoint created.".to_string())
} else {
// id not found in map; return error
// TODO: Result Type for this call
Expand Down
Loading

0 comments on commit efe4ff6

Please sign in to comment.