From 61e3207740cd0b4fa58feaad7562452089a9057f Mon Sep 17 00:00:00 2001 From: mraszyk <31483726+mraszyk@users.noreply.github.com> Date: Mon, 18 Nov 2024 19:26:19 +0100 Subject: [PATCH] feat: make ic-repl work against PocketIC (#99) * feat: make ic-repl work against PocketIC * lazy * dfx stop * clean * use fn get_default_effective_canister_id * simplify deps * bump dfx * dfx version * Revert "dfx version" This reverts commit ab157dd89ffb36d28378b0f76067ea3a65cabed2. * deps * dfx * avoid pocket-ic crate (#101) * avoid pocket-ic crate * . * trim_end_matches --- .github/workflows/ci.yml | 15 +- Cargo.lock | 363 ++++++++++++++++++++++++++++++++++++++- Cargo.toml | 3 +- src/exp.rs | 6 +- src/helper.rs | 29 ++++ src/utils.rs | 10 +- 6 files changed, 412 insertions(+), 14 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index e3e578a..72df0a2 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -8,7 +8,7 @@ jobs: test: runs-on: ubuntu-latest env: - DFX_VERSION: 0.24.0 + DFX_VERSION: 0.24.2 steps: - uses: actions/checkout@v4 - name: Install stable Rust toolchain @@ -38,12 +38,19 @@ jobs: uses: dfinity/setup-dfx@main with: dfx-version: "${{ env.DFX_VERSION }}" - - name: Start replica using dfx + - name: Run e2e tests against replica run: | echo '{}' > dfx.json - dfx start --background - - name: e2e tests + dfx start --background --clean + set -ex + target/debug/ic-repl examples/install.sh + target/debug/ic-repl examples/func.sh + dfx stop + - name: Run e2e tests against PocketIC run: | + echo '{}' > dfx.json + dfx start --background --clean --pocketic set -ex target/debug/ic-repl examples/install.sh target/debug/ic-repl examples/func.sh + dfx stop diff --git a/Cargo.lock b/Cargo.lock index 000ba14..7b38eac 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -51,6 +51,21 @@ version = "0.2.18" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "5c6cb57a04249c6480766f7f7cef5467412af1490f8d1e243141daddada3264f" +[[package]] +name = "android-tzdata" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e999941b234f3131b00bc13c22d06e8c5ff726d1b6318ac7eb276997bbb4fef0" + +[[package]] +name = "android_system_properties" +version = "0.1.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "819e7219dbd41043ac279b19830f2efc897156490d7fd6ea916720117ee66311" +dependencies = [ + "libc", +] + [[package]] name = "anstream" version = "0.6.17" @@ -155,6 +170,12 @@ dependencies = [ "syn 2.0.85", ] +[[package]] +name = "atomic-waker" +version = "1.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1505bd5d3d116872e7271a6d4e16d81d0c8570876c8de68093a09ac269d8aac0" + [[package]] name = "autocfg" version = "1.4.0" @@ -413,6 +434,19 @@ version = "0.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "613afe47fcd5fac7ccf1db93babcb082c5994d996f20b8b159f2ad1658eb5724" +[[package]] +name = "chrono" +version = "0.4.38" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a21f936df1771bf62b77f047b726c4625ff2e8aa607c01ec06e5a05bd8463401" +dependencies = [ + "android-tzdata", + "iana-time-zone", + "num-traits", + "serde", + "windows-targets 0.52.6", +] + [[package]] name = "clap" version = "4.5.20" @@ -521,6 +555,22 @@ dependencies = [ "unicode-segmentation", ] +[[package]] +name = "core-foundation" +version = "0.9.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "91e195e091a93c46f7102ec7818a2aa394e1e1771c3ab4825963fa03e45afb8f" +dependencies = [ + "core-foundation-sys", + "libc", +] + +[[package]] +name = "core-foundation-sys" +version = "0.8.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "773648b94d0e5d620f64f280777445740e61fe701025087ec8b57f45c791888b" + [[package]] name = "core2" version = "0.4.0" @@ -614,6 +664,41 @@ dependencies = [ "zeroize", ] +[[package]] +name = "darling" +version = "0.20.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6f63b86c8a8826a49b8c21f08a2d07338eec8d900540f8630dc76284be802989" +dependencies = [ + "darling_core", + "darling_macro", +] + +[[package]] +name = "darling_core" +version = "0.20.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "95133861a8032aaea082871032f5815eb9e98cef03fa916ab4500513994df9e5" +dependencies = [ + "fnv", + "ident_case", + "proc-macro2", + "quote", + "strsim", + "syn 2.0.85", +] + +[[package]] +name = "darling_macro" +version = "0.20.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d336a2a514f6ccccaa3e09b02d41d35330c07ddf03a62165fcec10bb561c7806" +dependencies = [ + "darling_core", + "quote", + "syn 2.0.85", +] + [[package]] name = "dary_heap" version = "0.3.7" @@ -658,6 +743,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b42b6fa04a440b495c8b04d0e71b707c585f83cb9cb28cf8cd0d976c315e31b4" dependencies = [ "powerfmt", + "serde", ] [[package]] @@ -817,6 +903,15 @@ version = "0.3.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a357d28ed41a50f9c765dbfe56cbc04a64e53e5fc58ba79fbc34c10ef3df831f" +[[package]] +name = "encoding_rs" +version = "0.8.35" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "75030f3c4f45dafd7586dd6780965a8c7e8e285a5ecb86713e63a79c5b2766f3" +dependencies = [ + "cfg-if", +] + [[package]] name = "endian-type" version = "0.1.2" @@ -940,6 +1035,21 @@ version = "1.0.7" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3f9eec918d3f24069decb9af1554cad7c880e2da24a9afd88aca000531ab82c1" +[[package]] +name = "foreign-types" +version = "0.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f6f339eb8adc052cd2ca78910fda869aefa38d22d5cb648e6485e4d3fc06f3b1" +dependencies = [ + "foreign-types-shared", +] + +[[package]] +name = "foreign-types-shared" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "00b0228411908ca8685dba7fc2cdd70ec9990a6e753e89b6ac91a84c40fbaf4b" + [[package]] name = "form_urlencoded" version = "1.2.1" @@ -1088,6 +1198,25 @@ dependencies = [ "subtle", ] +[[package]] +name = "h2" +version = "0.4.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "524e8ac6999421f49a846c2d4411f337e53497d8ec55d67753beffa43c5d9205" +dependencies = [ + "atomic-waker", + "bytes", + "fnv", + "futures-core", + "futures-sink", + "http", + "indexmap 2.6.0", + "slab", + "tokio", + "tokio-util", + "tracing", +] + [[package]] name = "half" version = "1.8.3" @@ -1225,6 +1354,7 @@ dependencies = [ "bytes", "futures-channel", "futures-util", + "h2", "http", "http-body", "httparse", @@ -1253,6 +1383,22 @@ dependencies = [ "webpki-roots", ] +[[package]] +name = "hyper-tls" +version = "0.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "70206fc6890eaca9fde8a0bf71caa2ddfc9fe045ac9e5c70df101a7dbde866e0" +dependencies = [ + "bytes", + "http-body-util", + "hyper", + "hyper-util", + "native-tls", + "tokio", + "tokio-native-tls", + "tower-service", +] + [[package]] name = "hyper-util" version = "0.1.9" @@ -1272,6 +1418,29 @@ dependencies = [ "tracing", ] +[[package]] +name = "iana-time-zone" +version = "0.1.61" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "235e081f3925a06703c2d0117ea8b91f042756fd6e7a6e5d901e8ca1a996b220" +dependencies = [ + "android_system_properties", + "core-foundation-sys", + "iana-time-zone-haiku", + "js-sys", + "wasm-bindgen", + "windows-core", +] + +[[package]] +name = "iana-time-zone-haiku" +version = "0.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f31827a206f56af32e590ba56d5d2d085f558508192593743f16b2306495269f" +dependencies = [ + "cc", +] + [[package]] name = "ic-agent" version = "0.39.1" @@ -1372,12 +1541,14 @@ dependencies = [ "pretty_assertions", "qrcode", "rand", + "reqwest", "rpassword", "rustyline", "rustyline-derive", "serde", "serde_cbor", "serde_json", + "serde_with", "sha2 0.10.8", "shellexpand", "tokio", @@ -1462,6 +1633,12 @@ version = "2.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "25a2bc672d1148e28034f176e01fffebb08b35768468cc954630da77a1449005" +[[package]] +name = "ident_case" +version = "1.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b9e0384b61958566e926dc50660321d12159025e767c18e043daf26b70104c39" + [[package]] name = "idna" version = "0.5.0" @@ -1493,6 +1670,7 @@ checksum = "bd070e393353796e801d209ad339e89596eb4c8d430d18ede6a1cced8fafbd99" dependencies = [ "autocfg", "hashbrown 0.12.3", + "serde", ] [[package]] @@ -1779,6 +1957,23 @@ dependencies = [ "windows-sys 0.52.0", ] +[[package]] +name = "native-tls" +version = "0.2.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a8614eb2c83d59d1c8cc974dd3f920198647674a0a035e1af1fa58707e317466" +dependencies = [ + "libc", + "log", + "openssl", + "openssl-probe", + "openssl-sys", + "schannel", + "security-framework", + "security-framework-sys", + "tempfile", +] + [[package]] name = "new_debug_unreachable" version = "1.0.6" @@ -1895,6 +2090,50 @@ version = "0.3.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c08d65885ee38876c4f86fa503fb49d7b507c2b62552df7c70b2fce627e06381" +[[package]] +name = "openssl" +version = "0.10.68" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6174bc48f102d208783c2c84bf931bb75927a617866870de8a4ea85597f871f5" +dependencies = [ + "bitflags 2.6.0", + "cfg-if", + "foreign-types", + "libc", + "once_cell", + "openssl-macros", + "openssl-sys", +] + +[[package]] +name = "openssl-macros" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a948666b637a0f465e8564c73e89d4dde00d72d4d473cc972f390fc3dcee7d9c" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.85", +] + +[[package]] +name = "openssl-probe" +version = "0.1.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ff011a302c396a5197692431fc1948019154afc178baf7d8e37367442a4601cf" + +[[package]] +name = "openssl-sys" +version = "0.9.104" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "45abf306cbf99debc8195b66b7346498d7b10c210de50418b5ccd7ceba08c741" +dependencies = [ + "cc", + "libc", + "pkg-config", + "vcpkg", +] + [[package]] name = "option-ext" version = "0.2.0" @@ -2084,6 +2323,12 @@ dependencies = [ "spki", ] +[[package]] +name = "pkg-config" +version = "0.3.31" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "953ec861398dccce10c670dfeaf3ec4911ca479e9c02154b3a215178c5f566f2" + [[package]] name = "png" version = "0.17.14" @@ -2338,25 +2583,29 @@ checksum = "2b15c43186be67a4fd63bee50d0303afffcef381492ebe2c5d87f324e1b8815c" [[package]] name = "reqwest" -version = "0.12.8" +version = "0.12.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f713147fbe92361e52392c73b8c9e48c04c6625bce969ef54dc901e58e042a7b" +checksum = "a77c62af46e79de0a562e1a9849205ffcb7fc1238876e9bd743357570e04046f" dependencies = [ "base64 0.22.1", "bytes", + "encoding_rs", "futures-channel", "futures-core", "futures-util", + "h2", "http", "http-body", "http-body-util", "hyper", "hyper-rustls", + "hyper-tls", "hyper-util", "ipnet", "js-sys", "log", "mime", + "native-tls", "once_cell", "percent-encoding", "pin-project-lite", @@ -2368,7 +2617,9 @@ dependencies = [ "serde_json", "serde_urlencoded", "sync_wrapper", + "system-configuration", "tokio", + "tokio-native-tls", "tokio-rustls", "tokio-util", "tower-service", @@ -2561,6 +2812,15 @@ dependencies = [ "winapi-util", ] +[[package]] +name = "schannel" +version = "0.1.26" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "01227be5826fa0690321a2ba6c5cd57a19cf3f6a09e76973b58e61de6ab9d1c1" +dependencies = [ + "windows-sys 0.59.0", +] + [[package]] name = "scopeguard" version = "1.2.0" @@ -2581,6 +2841,29 @@ dependencies = [ "zeroize", ] +[[package]] +name = "security-framework" +version = "2.11.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "897b2245f0b511c87893af39b033e5ca9cce68824c4d7e7630b5a1d339658d02" +dependencies = [ + "bitflags 2.6.0", + "core-foundation", + "core-foundation-sys", + "libc", + "security-framework-sys", +] + +[[package]] +name = "security-framework-sys" +version = "2.12.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fa39c7303dc58b5543c94d22c1766b0d31f2ee58306363ea622b10bbc075eaa2" +dependencies = [ + "core-foundation-sys", + "libc", +] + [[package]] name = "semver" version = "1.0.23" @@ -2670,6 +2953,36 @@ dependencies = [ "serde", ] +[[package]] +name = "serde_with" +version = "3.11.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8e28bdad6db2b8340e449f7108f020b3b092e8583a9e3fb82713e1d4e71fe817" +dependencies = [ + "base64 0.22.1", + "chrono", + "hex", + "indexmap 1.9.3", + "indexmap 2.6.0", + "serde", + "serde_derive", + "serde_json", + "serde_with_macros", + "time", +] + +[[package]] +name = "serde_with_macros" +version = "3.11.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9d846214a9854ef724f3da161b426242d8de7c1fc7de2f89bb1efcb154dca79d" +dependencies = [ + "darling", + "proc-macro2", + "quote", + "syn 2.0.85", +] + [[package]] name = "sha2" version = "0.9.9" @@ -2886,6 +3199,27 @@ dependencies = [ "futures-core", ] +[[package]] +name = "system-configuration" +version = "0.6.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3c879d448e9d986b661742763247d3693ed13609438cf3d006f51f5368a5ba6b" +dependencies = [ + "bitflags 2.6.0", + "core-foundation", + "system-configuration-sys", +] + +[[package]] +name = "system-configuration-sys" +version = "0.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8e1d1b10ced5ca923a1fcb8d03e96b8d3268065d724548c0211415ff6ac6bac4" +dependencies = [ + "core-foundation-sys", + "libc", +] + [[package]] name = "tempfile" version = "3.13.0" @@ -3023,6 +3357,16 @@ dependencies = [ "syn 2.0.85", ] +[[package]] +name = "tokio-native-tls" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bbae76ab933c85776efabc971569dd6119c580d8f5d448769dec1764bf796ef2" +dependencies = [ + "native-tls", + "tokio", +] + [[package]] name = "tokio-rustls" version = "0.26.0" @@ -3192,6 +3536,12 @@ version = "0.2.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "06abde3611657adf66d383f00b093d7faecc7fa57071cce2578660c9f1010821" +[[package]] +name = "vcpkg" +version = "0.2.15" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "accd4ea62f7bb7a82fe23066fb0957d48ef677f6eeb8215f372f52e48bb32426" + [[package]] name = "version_check" version = "0.9.5" @@ -3404,6 +3754,15 @@ version = "0.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f" +[[package]] +name = "windows-core" +version = "0.52.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "33ab640c8d7e35bf8ba19b884ba838ceb4fba93a4e8c65a9059d08afcfc683d9" +dependencies = [ + "windows-targets 0.52.6", +] + [[package]] name = "windows-registry" version = "0.2.0" diff --git a/Cargo.toml b/Cargo.toml index 85439a8..fd2537b 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -48,4 +48,5 @@ image = { version = "0.24", default-features = false, features = ["png"] } libflate = "2.0" base64 = "0.21" futures = "0.3.30" - +reqwest = "0.12.9" +serde_with = { version = "3.11.0", features = ["base64"] } diff --git a/src/exp.rs b/src/exp.rs index 8440985..175ddcb 100644 --- a/src/exp.rs +++ b/src/exp.rs @@ -594,7 +594,8 @@ impl Exp { args.to_bytes()? }; let method = &call.method.method; - let effective_id = get_effective_canister_id(info.canister_id, method, &bytes)?; + let effective_id = get_effective_canister_id(info.canister_id, method, &bytes)? + .unwrap_or(helper.default_effective_canister_id); let mut builder = helper.agent.update(&info.canister_id, method); builder = builder .with_arg(bytes) @@ -931,7 +932,8 @@ async fn call( ) -> anyhow::Result { use crate::offline::*; let agent = &helper.agent; - let effective_id = get_effective_canister_id(*canister_id, method, args)?; + let effective_id = get_effective_canister_id(*canister_id, method, args)? + .unwrap_or(helper.default_effective_canister_id); let is_query = opt_func .as_ref() .map(|(_, f)| f.is_query()) diff --git a/src/helper.rs b/src/helper.rs index e524622..a21486d 100644 --- a/src/helper.rs +++ b/src/helper.rs @@ -91,6 +91,7 @@ pub struct MyHelper { pub base_path: std::path::PathBuf, pub messages: RefCell>, pub verbose: bool, + pub default_effective_canister_id: Principal, } impl MyHelper { @@ -113,6 +114,7 @@ impl MyHelper { offline: self.offline.clone(), messages: self.messages.clone(), verbose: self.verbose, + default_effective_canister_id: self.default_effective_canister_id, } } pub fn new( @@ -121,6 +123,32 @@ impl MyHelper { offline: Option, verbose: bool, ) -> Self { + let runtime = Runtime::new().expect("Unable to create a runtime"); + let default_effective_canister_id = runtime + .block_on(async { + use serde_with::base64::Base64; + #[serde_with::serde_as] + #[derive(serde::Deserialize)] + pub struct RawCanisterId { + #[serde_as(as = "Base64")] + pub canister_id: Vec, + } + #[derive(serde::Deserialize)] + struct Topology { + pub default_effective_canister_id: RawCanisterId, + } + let resp = reqwest::get(format!("{}/_/topology", agent_url.trim_end_matches('/'))) + .await + .ok()?; + if resp.status().is_success() { + resp.json::().await.ok().map(|topology| { + Principal::from_slice(&topology.default_effective_canister_id.canister_id) + }) + } else { + None + } + }) + .unwrap_or(Principal::management_canister()); let mut res = MyHelper { completer: FilenameCompleter::new(), highlighter: MatchingBracketHighlighter::new(), @@ -139,6 +167,7 @@ impl MyHelper { agent_url, offline, verbose, + default_effective_canister_id, }; res.fetch_root_key_if_needed().unwrap(); res.load_prelude().unwrap(); diff --git a/src/utils.rs b/src/utils.rs index 241dce7..76236e1 100644 --- a/src/utils.rs +++ b/src/utils.rs @@ -162,7 +162,7 @@ pub fn get_effective_canister_id( canister_id: Principal, method: &str, args: &[u8], -) -> anyhow::Result { +) -> anyhow::Result> { use candid::{CandidType, Decode, Deserialize}; if canister_id == Principal::management_canister() { match method { @@ -170,7 +170,7 @@ pub fn get_effective_canister_id( "{} can only be called via inter-canister call.", method )), - "provisional_create_canister_with_cycles" => Ok(canister_id), + "provisional_create_canister_with_cycles" => Ok(None), "install_chunked_code" => { #[derive(CandidType, Deserialize)] struct Arg { @@ -179,7 +179,7 @@ pub fn get_effective_canister_id( let args = Decode!(args, Arg).map_err(|_| { anyhow!("{} can only be called via inter-canister call.", method) })?; - Ok(args.target_canister) + Ok(Some(args.target_canister)) } _ => { #[derive(CandidType, Deserialize)] @@ -189,11 +189,11 @@ pub fn get_effective_canister_id( let args = Decode!(args, Arg).map_err(|_| { anyhow!("{} can only be called via inter-canister call.", method) })?; - Ok(args.canister_id) + Ok(Some(args.canister_id)) } } } else { - Ok(canister_id) + Ok(Some(canister_id)) } }