canic_testkit/artifacts/
wasm.rs1use std::{
2 fs,
3 path::{Path, PathBuf},
4 process::Command,
5};
6
7pub const INTERNAL_TEST_ENDPOINTS_ENV: (&str, &str) = ("CANIC_INTERNAL_TEST_ENDPOINTS", "1");
8
9#[derive(Clone, Copy, Debug, Eq, PartialEq)]
14pub enum WasmBuildProfile {
15 Debug,
16 Fast,
17 Release,
18}
19
20impl WasmBuildProfile {
21 #[must_use]
23 pub const fn cargo_args(self) -> &'static [&'static str] {
24 match self {
25 Self::Debug => &[],
26 Self::Fast => &["--profile", "fast"],
27 Self::Release => &["--release"],
28 }
29 }
30
31 #[must_use]
33 pub const fn target_dir_name(self) -> &'static str {
34 match self {
35 Self::Debug => "debug",
36 Self::Fast => "fast",
37 Self::Release => "release",
38 }
39 }
40
41 #[must_use]
43 pub const fn canic_wasm_profile_value(self) -> &'static str {
44 match self {
45 Self::Debug => "debug",
46 Self::Fast => "fast",
47 Self::Release => "release",
48 }
49 }
50}
51
52#[must_use]
54pub fn wasm_path(target_dir: &Path, crate_name: &str, profile: WasmBuildProfile) -> PathBuf {
55 target_dir
56 .join("wasm32-unknown-unknown")
57 .join(profile.target_dir_name())
58 .join(format!("{crate_name}.wasm"))
59}
60
61#[must_use]
63pub fn wasm_artifacts_ready(
64 target_dir: &Path,
65 canisters: &[&str],
66 profile: WasmBuildProfile,
67) -> bool {
68 canisters
69 .iter()
70 .all(|name| wasm_path(target_dir, name, profile).is_file())
71}
72
73#[must_use]
75pub fn read_wasm(target_dir: &Path, crate_name: &str, profile: WasmBuildProfile) -> Vec<u8> {
76 let path = wasm_path(target_dir, crate_name, profile);
77 fs::read(&path).unwrap_or_else(|err| panic!("failed to read {crate_name} wasm: {err}"))
78}
79
80pub fn build_wasm_canisters(
82 workspace_root: &Path,
83 target_dir: &Path,
84 packages: &[&str],
85 profile: WasmBuildProfile,
86 extra_env: &[(&str, &str)],
87) {
88 let mut cmd = Command::new("cargo");
89 cmd.current_dir(workspace_root);
90 cmd.env("CARGO_TARGET_DIR", target_dir);
91 cmd.env("DFX_NETWORK", "local");
92 cmd.args(["build", "--target", "wasm32-unknown-unknown"]);
93 cmd.args(profile.cargo_args());
94
95 for (key, value) in extra_env {
96 cmd.env(key, value);
97 }
98
99 for name in packages {
100 cmd.args(["-p", name]);
101 }
102
103 let output = cmd.output().expect("failed to run cargo build");
104 assert!(
105 output.status.success(),
106 "cargo build failed: {}",
107 String::from_utf8_lossy(&output.stderr)
108 );
109}
110
111pub fn build_internal_test_wasm_canisters(
113 workspace_root: &Path,
114 target_dir: &Path,
115 packages: &[&str],
116 profile: WasmBuildProfile,
117) {
118 build_wasm_canisters(
119 workspace_root,
120 target_dir,
121 packages,
122 profile,
123 &[INTERNAL_TEST_ENDPOINTS_ENV],
124 );
125}
126
127pub fn build_internal_test_wasm_canisters_with_env<'a>(
130 workspace_root: &Path,
131 target_dir: &Path,
132 packages: &[&str],
133 profile: WasmBuildProfile,
134 extra_env: &[(&'a str, &'a str)],
135) {
136 let mut build_env = Vec::with_capacity(extra_env.len() + 1);
137 build_env.push(INTERNAL_TEST_ENDPOINTS_ENV);
138 build_env.extend_from_slice(extra_env);
139 build_wasm_canisters(workspace_root, target_dir, packages, profile, &build_env);
140}