Skip to content

Commit a43d7a8

Browse files
committed
add tests for loading a project
1 parent faab690 commit a43d7a8

5 files changed

Lines changed: 295 additions & 7 deletions

File tree

bin/icp-cli/tests/project_tests.rs

Lines changed: 288 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,288 @@
1+
use icp_adapter::script::{CommandField, ScriptAdapter};
2+
use icp_canister::model::{Adapter, Build, CanisterManifest};
3+
use icp_project::{
4+
model::{LoadProjectManifestError, ProjectManifest},
5+
structure::ProjectDirectoryStructure,
6+
};
7+
mod common;
8+
use common::TestEnv;
9+
10+
#[test]
11+
fn empty_project() {
12+
// Setup
13+
let env = TestEnv::new();
14+
let project_dir = env.home_path();
15+
16+
// Write project-manifest
17+
std::fs::write(
18+
project_dir.join("icp.yaml"), // path
19+
"", // contents
20+
)
21+
.expect("failed to write project manifest");
22+
23+
// Load Project
24+
let pds = ProjectDirectoryStructure::new(project_dir);
25+
let pm = ProjectManifest::load(&pds).expect("failed to load project manifest");
26+
27+
// Verify no canisters were found
28+
assert!(pm.canisters.is_empty());
29+
}
30+
31+
#[test]
32+
fn single_canister_project() {
33+
// Setup
34+
let env = TestEnv::new();
35+
let project_dir = env.home_path();
36+
37+
// Write project-manifest
38+
let pm = r#"
39+
canister:
40+
name: canister-1
41+
build:
42+
adapter:
43+
type: script
44+
command: echo test
45+
"#;
46+
47+
std::fs::write(
48+
project_dir.join("icp.yaml"), // path
49+
pm, // contents
50+
)
51+
.expect("failed to write project manifest");
52+
53+
// Load Project
54+
let pds = ProjectDirectoryStructure::new(project_dir);
55+
let pm = ProjectManifest::load(&pds).expect("failed to load project manifest");
56+
57+
// Verify canister was loaded
58+
let canisters = vec![(
59+
project_dir.to_owned(),
60+
CanisterManifest {
61+
name: "canister-1".into(),
62+
build: Build {
63+
adapter: Adapter::Script(ScriptAdapter {
64+
command: CommandField::Command("echo test".into()),
65+
}),
66+
},
67+
},
68+
)];
69+
70+
assert_eq!(pm.canisters, canisters);
71+
}
72+
73+
#[test]
74+
fn multi_canister_project() {
75+
// Setup
76+
let env = TestEnv::new();
77+
let project_dir = env.home_path();
78+
79+
// Create canister directory
80+
std::fs::create_dir(project_dir.join("canister-1"))
81+
.expect("failed to create canister directory");
82+
83+
// Write canister-manifest
84+
let cm = r#"
85+
name: canister-1
86+
build:
87+
adapter:
88+
type: script
89+
command: echo test
90+
"#;
91+
92+
std::fs::write(
93+
project_dir.join("canister-1/canister.yaml"), // path
94+
cm, // contents
95+
)
96+
.expect("failed to write canister manifest");
97+
98+
// Write project-manifest
99+
let pm = r#"
100+
canisters:
101+
- canister-1
102+
"#;
103+
104+
std::fs::write(
105+
project_dir.join("icp.yaml"), // path
106+
pm, // contents
107+
)
108+
.expect("failed to write project manifest");
109+
110+
// Load Project
111+
let pds = ProjectDirectoryStructure::new(project_dir);
112+
let pm = ProjectManifest::load(&pds).expect("failed to load project manifest");
113+
114+
// Verify canister was loaded
115+
let canisters = vec![(
116+
project_dir.join("canister-1"),
117+
CanisterManifest {
118+
name: "canister-1".into(),
119+
build: Build {
120+
adapter: Adapter::Script(ScriptAdapter {
121+
command: CommandField::Command("echo test".into()),
122+
}),
123+
},
124+
},
125+
)];
126+
127+
assert_eq!(pm.canisters, canisters);
128+
}
129+
130+
#[test]
131+
fn invalid_project_manifest() {
132+
// Setup
133+
let env = TestEnv::new();
134+
let project_dir = env.home_path();
135+
136+
// Write project-manifest
137+
std::fs::write(
138+
project_dir.join("icp.yaml"), // path
139+
"invalid-content", // contents
140+
)
141+
.expect("failed to write project manifest");
142+
143+
// Load Project
144+
let pds = ProjectDirectoryStructure::new(project_dir);
145+
let pm = ProjectManifest::load(&pds);
146+
147+
// Assert failure
148+
assert!(matches!(pm, Err(LoadProjectManifestError::Parse { .. })));
149+
}
150+
151+
#[test]
152+
fn invalid_canister_manifest() {
153+
// Setup
154+
let env = TestEnv::new();
155+
let project_dir = env.home_path();
156+
157+
// Create canister directory
158+
std::fs::create_dir(project_dir.join("canister-1"))
159+
.expect("failed to create canister directory");
160+
161+
// Write canister-manifest
162+
std::fs::write(
163+
project_dir.join("canister-1/canister.yaml"), // path
164+
"invalid-content", // contents
165+
)
166+
.expect("failed to write canister manifest");
167+
168+
// Write project-manifest
169+
let pm = r#"
170+
canisters:
171+
- canister-1
172+
"#;
173+
174+
std::fs::write(
175+
project_dir.join("icp.yaml"), // path
176+
pm, // contents
177+
)
178+
.expect("failed to write project manifest");
179+
180+
// Load Project
181+
let pds = ProjectDirectoryStructure::new(project_dir);
182+
let pm = ProjectManifest::load(&pds);
183+
184+
// Assert failure
185+
assert!(matches!(
186+
pm,
187+
Err(LoadProjectManifestError::CanisterLoad { .. })
188+
));
189+
}
190+
191+
#[test]
192+
fn glob_path_non_canister() {
193+
// Setup
194+
let env = TestEnv::new();
195+
let project_dir = env.home_path();
196+
197+
// Create canister directory
198+
std::fs::create_dir_all(project_dir.join("canisters/canister-1"))
199+
.expect("failed to create canister directory");
200+
201+
// Skip writing canister-manifest
202+
//
203+
204+
// Write project-manifest
205+
let pm = r#"
206+
canisters:
207+
- canisters/*
208+
"#;
209+
210+
std::fs::write(
211+
project_dir.join("icp.yaml"), // path
212+
pm, // contents
213+
)
214+
.expect("failed to write project manifest");
215+
216+
// Load Project
217+
let pds = ProjectDirectoryStructure::new(project_dir);
218+
let pm = ProjectManifest::load(&pds).expect("failed to load project manifest");
219+
220+
// Verify no canisters were found
221+
assert!(pm.canisters.is_empty());
222+
}
223+
224+
#[test]
225+
fn explicit_path_non_canister() {
226+
// Setup
227+
let env = TestEnv::new();
228+
let project_dir = env.home_path();
229+
230+
// Create canister directory
231+
std::fs::create_dir(project_dir.join("canister-1"))
232+
.expect("failed to create canister directory");
233+
234+
// Skip writing canister-manifest
235+
//
236+
237+
// Write project-manifest
238+
let pm = r#"
239+
canisters:
240+
- canister-1
241+
"#;
242+
243+
std::fs::write(
244+
project_dir.join("icp.yaml"), // path
245+
pm, // contents
246+
)
247+
.expect("failed to write project manifest");
248+
249+
// Load Project
250+
let pds = ProjectDirectoryStructure::new(project_dir);
251+
let pm = ProjectManifest::load(&pds);
252+
253+
// Assert failure
254+
assert!(matches!(
255+
pm,
256+
Err(LoadProjectManifestError::NoManifest { .. })
257+
));
258+
}
259+
260+
#[test]
261+
fn invalid_glob_pattern() {
262+
// Setup
263+
let env = TestEnv::new();
264+
let project_dir = env.home_path();
265+
266+
// Write project-manifest
267+
let pm = r#"
268+
canisters:
269+
- canisters/***
270+
"#;
271+
272+
std::fs::write(
273+
project_dir.join("icp.yaml"), // path
274+
pm, // contents
275+
)
276+
.expect("failed to write project manifest");
277+
278+
// Load Project
279+
let pds = ProjectDirectoryStructure::new(project_dir);
280+
let pm = ProjectManifest::load(&pds);
281+
282+
// Verify no canisters were found
283+
// Assert failure
284+
assert!(matches!(
285+
pm,
286+
Err(LoadProjectManifestError::GlobPattern { .. })
287+
));
288+
}

lib/icp-adapter/src/motoko.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ use serde::Deserialize;
55
use snafu::Snafu;
66

77
/// Configuration for a Motoko-based canister build adapter.
8-
#[derive(Debug, Deserialize)]
8+
#[derive(Debug, Deserialize, PartialEq)]
99
pub struct MotokoAdapter {
1010
/// Optional path to the main Motoko source file.
1111
/// If omitted, a default like `main.mo` may be assumed.

lib/icp-adapter/src/rust.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ use serde::Deserialize;
55
use snafu::Snafu;
66

77
/// Configuration for a Rust-based canister build adapter.
8-
#[derive(Debug, Deserialize)]
8+
#[derive(Debug, Deserialize, PartialEq)]
99
pub struct RustAdapter {
1010
/// The name of the Cargo package to build.
1111
pub package: String,

lib/icp-adapter/src/script.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ use serde::Deserialize;
55
use snafu::{OptionExt, ResultExt, Snafu};
66
use std::process::{Command, Stdio};
77

8-
#[derive(Debug, Deserialize)]
8+
#[derive(Debug, Deserialize, PartialEq)]
99
#[serde(rename_all = "lowercase")]
1010
pub enum CommandField {
1111
/// Command used to build a canister
@@ -16,7 +16,7 @@ pub enum CommandField {
1616
}
1717

1818
/// Configuration for a custom canister build adapter.
19-
#[derive(Debug, Deserialize)]
19+
#[derive(Debug, Deserialize, PartialEq)]
2020
pub struct ScriptAdapter {
2121
/// Command used to build a canister
2222
#[serde(flatten)]

lib/icp-canister/src/model.rs

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@ use snafu::Snafu;
1414
/// type: rust
1515
/// package: my_canister
1616
/// ```
17-
#[derive(Debug, Deserialize)]
17+
#[derive(Debug, Deserialize, PartialEq)]
1818
#[serde(tag = "type", rename_all = "lowercase")]
1919
pub enum Adapter {
2020
/// Represents a canister built using the Rust programming language.
@@ -32,15 +32,15 @@ pub enum Adapter {
3232

3333
/// Describes how the canister should be built into WebAssembly,
3434
/// including the adapter responsible for the build.
35-
#[derive(Debug, Deserialize)]
35+
#[derive(Debug, Deserialize, PartialEq)]
3636
pub struct Build {
3737
pub adapter: Adapter,
3838
}
3939

4040
/// Represents the manifest describing a single canister.
4141
/// This struct is typically loaded from a `canister.yaml` file and defines
4242
/// the canister's name and how it should be built into WebAssembly.
43-
#[derive(Debug, Deserialize)]
43+
#[derive(Debug, Deserialize, PartialEq)]
4444
pub struct CanisterManifest {
4545
/// The unique name of the canister as defined in this manifest.
4646
pub name: String,

0 commit comments

Comments
 (0)