Skip to content

Commit

Permalink
test: run e2e/integration tests vs replica rather than ic-ref (#474)
Browse files Browse the repository at this point in the history
* test: run e2e tests vs replica rather than ic-ref

* expected error message

* expected errors

* error-messages

* errors

* error results

* .

* creation fee

* replica burns some cycles

* more cycles

* wow

* .

* start clean

* .

* format
  • Loading branch information
ericswanson-dfinity authored Sep 28, 2023
1 parent 4debbb7 commit 1fef402
Show file tree
Hide file tree
Showing 3 changed files with 127 additions and 71 deletions.
30 changes: 15 additions & 15 deletions .github/workflows/ic-ref.yml
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,11 @@ jobs:
with:
path: main

- name: Install dfx
uses: dfinity/setup-dfx@main
with:
dfx-version: "0.15.0"

- name: Cargo cache
uses: actions/cache@v2
with:
Expand All @@ -48,28 +53,23 @@ jobs:
wget https://github.com/dfinity/cycles-wallet/releases/download/${{ matrix.wallet-tag }}/wallet.wasm
mv wallet.wasm $HOME/wallet.wasm
- name: Download ic-ref and universal-canister
- name: Download universal-canister
run: |
wget https://download.dfinity.systems/ic-ref/ic-ref-0.0.1-${{ matrix.ic-hs-ref }}-x86_64-linux.tar.gz
tar -xvf ic-ref-0.0.1-${{ matrix.ic-hs-ref }}-x86_64-linux.tar.gz ic-ref
mkdir -p $HOME/bin
mv ic-ref $HOME/bin/ic-ref
wget https://download.dfinity.systems/ic-ref/ic-ref-test-0.0.1-${{ matrix.ic-hs-ref }}-x86_64-linux.tar.gz
tar -xvf ic-ref-test-0.0.1-${{ matrix.ic-hs-ref }}-x86_64-linux.tar.gz test-data/universal-canister.wasm
mv test-data/universal-canister.wasm $HOME/canister.wasm
- name: Run Integration Tests
run: |
set -ex
$HOME/bin/ic-ref --pick-port --write-port-to $HOME/ic_ref_port &
dfx start --background --clean
sleep 1
export IC_REF_PORT=$(cat $HOME/ic_ref_port)
export IC_REF_PORT=$(dfx info replica-port)
export IC_UNIVERSAL_CANISTER_PATH=$HOME/canister.wasm
export IC_WALLET_CANISTER_PATH=$HOME/wallet.wasm
cd main
cargo test --all-features -- --ignored
killall ic-ref
dfx stop
env:
RUST_BACKTRACE: 1

Expand All @@ -89,14 +89,14 @@ jobs:
# create key:
pkcs11-tool -k --module $HSM_PKCS11_LIBRARY_PATH --login --slot-index $HSM_SLOT_INDEX -d $HSM_KEY_ID --key-type EC:prime256v1 --pin $HSM_PIN
$HOME/bin/ic-ref --pick-port --write-port-to $HOME/ic_ref_port &
dfx start --background --clean
sleep 1
export IC_REF_PORT=$(cat $HOME/ic_ref_port)
export IC_REF_PORT=$(dfx info replica-port)
export IC_UNIVERSAL_CANISTER_PATH=$HOME/canister.wasm
export IC_WALLET_CANISTER_PATH=$HOME/wallet.wasm
cd main/ref-tests
cargo test --all-features -- --ignored --nocapture --test-threads=1
killall ic-ref
dfx stop
env:
RUST_BACKTRACE: 1
HSM_PKCS11_LIBRARY_PATH: /usr/lib/softhsm/libsofthsm2.so
Expand All @@ -108,12 +108,12 @@ jobs:
- name: Run Doc Tests
run: |
set -ex
$HOME/bin/ic-ref --pick-port --write-port-to $HOME/ic_ref_port &
dfx start --background --clean
sleep 1
export IC_REF_PORT=$(cat $HOME/ic_ref_port)
export IC_REF_PORT=$(dfx info replica-port)
cd main
cargo test --all-features --doc -- --ignored
killall ic-ref
dfx stop
env:
RUST_BACKTRACE: 1

Expand Down
161 changes: 107 additions & 54 deletions ref-tests/tests/ic-ref.rs
Original file line number Diff line number Diff line change
Expand Up @@ -62,10 +62,16 @@ mod management_canister {
};
use sha2::{Digest, Sha256};
use std::collections::HashSet;
use std::convert::TryInto;

mod create_canister {
use super::with_agent;
use ic_agent::{export::Principal, AgentError};
use ic_agent::{
agent::{RejectCode, RejectResponse},
export::Principal,
AgentError,
};

use ic_utils::interfaces::ManagementCanister;
use ref_tests::get_effective_canister_id;
use std::str::FromStr;
Expand Down Expand Up @@ -103,13 +109,14 @@ mod management_canister {
.call_and_wait()
.await;

let payload_content =
"canister does not exist: 75hes-oqbaa-aaaaa-aaaaa-aaaaa-aaaaa-aaaaa-q"
.to_string();

assert!(matches!(result,
Err(AgentError::HttpError(payload))
if String::from_utf8(payload.content.clone()).expect("Expected utf8") == payload_content));
Err(AgentError::ReplicaError(RejectResponse {
reject_code: RejectCode::DestinationInvalid,
reject_message,
error_code: Some(ref error_code)
})) if reject_message == "Canister 75hes-oqbaa-aaaaa-aaaaa-aaaaa-aaaaa-aaaaa-q not found" &&
error_code == "IC0301"));

Ok(())
})
}
Expand Down Expand Up @@ -164,7 +171,7 @@ mod management_canister {
.with_mode(InstallMode::Reinstall)
.call_and_wait()
.await;
assert!(matches!(result, Err(AgentError::HttpError(..))));
assert!(matches!(result, Err(AgentError::ReplicaError(..))));

// Upgrade should succeed.
ic00.install_code(&canister_id, &canister_wasm)
Expand All @@ -178,7 +185,7 @@ mod management_canister {
.with_mode(InstallMode::Upgrade)
.call_and_wait()
.await;
assert!(matches!(result, Err(AgentError::HttpError(..))));
assert!(matches!(result, Err(AgentError::ReplicaError(..))));

// Change controller.
ic00.update_settings(&canister_id)
Expand All @@ -192,9 +199,14 @@ mod management_canister {
.with_controller(other_agent_principal)
.call_and_wait()
.await;
assert!(matches!(result, Err(AgentError::HttpError(payload))
if String::from_utf8(payload.content.clone()).expect("Expected utf8")
== *"Wrong sender"));
assert!(
matches!(result, Err(AgentError::ReplicaError(RejectResponse{
reject_code: RejectCode::CanisterError,
reject_message,
error_code: Some(ref error_code),
})) if reject_message == format!("Only controllers of canister {} can call ic00 method update_settings", canister_id) &&
error_code == "IC0512")
);

// Reinstall as new controller
other_ic00
Expand Down Expand Up @@ -411,8 +423,8 @@ mod management_canister {
matches!(result, Err(AgentError::ReplicaError(RejectResponse{
reject_code: RejectCode::CanisterError,
reject_message,
..
})) if reject_message == "canister is not running")
error_code: None,
})) if reject_message == format!("Canister {} is stopped", canister_id))
);

// Can't call query on a stopped canister
Expand All @@ -421,8 +433,9 @@ mod management_canister {
matches!(result, Err(AgentError::ReplicaError(RejectResponse{
reject_code: RejectCode::CanisterError,
reject_message,
..
})) if reject_message == "canister is stopped")
error_code: Some(ref error_code),
})) if reject_message == format!("IC0508: Canister {} is stopped and therefore does not have a CallContextManager", canister_id) &&
error_code == "IC0508")
);

// Upgrade should succeed
Expand All @@ -444,8 +457,8 @@ mod management_canister {
matches!(result, Err(AgentError::ReplicaError(RejectResponse{
reject_code: RejectCode::DestinationInvalid,
reject_message,
..
})) if reject_message == "method does not exist: update")
error_code: None,
})) if reject_message == format!("Canister {} has no update method 'update'", canister_id))
);

// Can call query
Expand All @@ -454,17 +467,14 @@ mod management_canister {
matches!(result, Err(AgentError::ReplicaError(RejectResponse{
reject_code: RejectCode::DestinationInvalid,
reject_message,
..
})) if reject_message == "query method does not exist")
error_code: Some(ref error_code),
})) if reject_message == format!("IC0302: Canister {} has no query method 'query'", canister_id) &&
error_code == "IC0302")
);

// Another start is a noop
ic00.start_canister(&canister_id).call_and_wait().await?;

// Delete a running canister should fail.
let result = ic00.delete_canister(&canister_id).call_and_wait().await;
assert!(matches!(result, Err(AgentError::ReplicaError { .. })));

// Stop should succeed.
ic00.stop_canister(&canister_id).call_and_wait().await?;

Expand All @@ -473,37 +483,51 @@ mod management_canister {

// Cannot call update
let result = agent.update(&canister_id, "update").call_and_wait().await;
assert!(matches!(result, Err(AgentError::HttpError(payload))
if String::from_utf8(payload.content.clone()).expect("Expected utf8")
== format!("canister no longer exists: {}", canister_id.to_text())));
assert!(
matches!(result, Err(AgentError::ReplicaError(RejectResponse{
reject_code: RejectCode::DestinationInvalid,
reject_message,
error_code: Some(ref error_code),
})) if reject_message == format!("Canister {} not found", canister_id) &&
error_code == "IC0301")
);

// Cannot call query
let result = agent.query(&canister_id, "query").with_arg([]).call().await;
assert!(
matches!(result, Err(AgentError::ReplicaError(RejectResponse{
reject_code: RejectCode::DestinationInvalid,
reject_message,
..
})) if reject_message
== format!("canister no longer exists: {}", canister_id.to_text()))
error_code: Some(ref error_code)
})) if reject_message == format!("IC0301: Canister {} not found", canister_id) &&
error_code == "IC0301")
);

// Cannot query canister status
let result = ic00.canister_status(&canister_id).call_and_wait().await;
assert!(match result {
Err(AgentError::HttpError(payload))
if String::from_utf8(payload.content.clone()).expect("Expected utf8")
== format!("canister no longer exists: {}", canister_id.to_text()) =>
Err(AgentError::ReplicaError(RejectResponse{
reject_code: RejectCode::DestinationInvalid,
reject_message,
error_code: Some(ref error_code)
}))
if reject_message == format!("Canister {} not found", canister_id) &&
error_code == "IC0301" =>
true,
Ok((_status_call_result,)) => false,
_ => false,
});

// Delete a deleted canister should fail.
let result = ic00.delete_canister(&canister_id).call_and_wait().await;
assert!(matches!(result, Err(AgentError::HttpError(payload))
if String::from_utf8(payload.content.clone()).expect("Expected utf8")
== format!("canister no longer exists: {}", canister_id.to_text())));
assert!(
matches!(result, Err(AgentError::ReplicaError(RejectResponse{
reject_code: RejectCode::DestinationInvalid,
reject_message,
error_code: Some(ref error_code)
})) if reject_message == format!("Canister {} not found", canister_id) &&
error_code == "IC0301")
);
Ok(())
})
}
Expand Down Expand Up @@ -538,33 +562,51 @@ mod management_canister {
.start_canister(&canister_id)
.call_and_wait()
.await;
assert!(matches!(result, Err(AgentError::HttpError(payload))
if String::from_utf8(payload.content.clone()).expect("Expected utf8")
== *"Wrong sender"));
assert!(matches!(result,
Err(AgentError::ReplicaError(RejectResponse {
reject_code: RejectCode::CanisterError,
reject_message,
error_code: Some(ref error_code)
})) if reject_message == format!("Only controllers of canister {} can call ic00 method start_canister", canister_id) &&
error_code == "IC0512"));

// Stop as a wrong controller should fail.
let result = other_ic00.stop_canister(&canister_id).call_and_wait().await;
assert!(matches!(result, Err(AgentError::HttpError(payload))
if String::from_utf8(payload.content.clone()).expect("Expected utf8")
== *"Wrong sender"));
assert!(
matches!(result,
Err(AgentError::ReplicaError(RejectResponse {
reject_code: RejectCode::CanisterError,
reject_message,
error_code: Some(ref error_code)
})) if reject_message == format!("Only controllers of canister {} can call ic00 method stop_canister", canister_id) &&
error_code == "IC0512")
);

// Get canister status as a wrong controller should fail.
let result = other_ic00
.canister_status(&canister_id)
.call_and_wait()
.await;
assert!(matches!(result, Err(AgentError::HttpError(payload))
if String::from_utf8(payload.content.clone()).expect("Expected utf8")
== *"Wrong sender"));
assert!(matches!(result,
Err(AgentError::ReplicaError(RejectResponse {
reject_code: RejectCode::CanisterError,
reject_message,
error_code: Some(ref error_code)
})) if reject_message == format!("Only controllers of canister {} can call ic00 method canister_status", canister_id) &&
error_code == "IC0512"));

// Delete as a wrong controller should fail.
let result = other_ic00
.delete_canister(&canister_id)
.call_and_wait()
.await;
assert!(matches!(result, Err(AgentError::HttpError(payload))
if String::from_utf8(payload.content.clone()).expect("Expected utf8")
== *"Wrong sender"));
assert!(matches!(result,
Err(AgentError::ReplicaError(RejectResponse {
reject_code: RejectCode::CanisterError,
reject_message,
error_code: Some(ref error_code)
})) if reject_message == format!("Only controllers of canister {} can call ic00 method delete_canister", canister_id) &&
error_code == "IC0512"));

Ok(())
})
Expand Down Expand Up @@ -596,8 +638,14 @@ mod management_canister {

let args = Argument::from_candid((create_args,));

let creation_fee = 8000000000;
let (create_result,): (CreateResult,) = wallet
.call(Principal::management_canister(), "create_canister", args, 0)
.call(
Principal::management_canister(),
"create_canister",
args,
creation_fee,
)
.call_and_wait()
.await?;
let canister_id = create_result.canister_id;
Expand All @@ -614,7 +662,7 @@ mod management_canister {
.call_and_wait()
.await?;

assert_eq!(result.cycles, 0_u64);
assert!(result.cycles > 0_u64 && result.cycles < creation_fee);

let ic00 = ManagementCanister::create(&agent);
// cycle balance is default_canister_balance when creating with
Expand All @@ -626,7 +674,10 @@ mod management_canister {
.call_and_wait()
.await?;
let result = ic00.canister_status(&canister_id_1).call_and_wait().await?;
assert_eq!(result.0.cycles, default_canister_balance);
// assume some cycles are already burned
let cycles: i128 = result.0.cycles.0.try_into().unwrap();
let burned = default_canister_balance as i128 - cycles;
assert!(burned > 0 && burned < 100_000_000);

// cycle balance should be amount specified to
// provisional_create_canister_with_cycles call
Expand All @@ -638,7 +689,9 @@ mod management_canister {
.call_and_wait()
.await?;
let result = ic00.canister_status(&canister_id_2).call_and_wait().await?;
assert_eq!(result.0.cycles, amount);
let cycles: i128 = result.0.cycles.0.try_into().unwrap();
let burned = amount as i128 - cycles;
assert!(burned > 0 && burned < 100_000_000);

Ok(())
})
Expand Down Expand Up @@ -928,8 +981,8 @@ mod extras {
Err(AgentError::ReplicaError(RejectResponse {
reject_code: RejectCode::DestinationInvalid,
reject_message,
..
})) if reject_message == "The specified_id of the created canister is already in use."));
error_code: None,
})) if reject_message == "Canister iimsn-6yaaa-aaaaa-afiaa-cai is already installed"));

Ok(())
})
Expand Down
Loading

0 comments on commit 1fef402

Please sign in to comment.