Refactor project loading for testability.
Change-Id: Ib0be12b67b2f32c809610248013b8610f234d2b7
Reviewed-on: https://pigweed-review.googlesource.com/c/pigweed/qg/+/125530
Reviewed-by: Alexei Frolov <frolv@google.com>
Commit-Queue: Erik Gilling <konkers@google.com>
diff --git a/qg/src/project/mod.rs b/qg/src/project/mod.rs
index 8d76556..8fe7bb9 100644
--- a/qg/src/project/mod.rs
+++ b/qg/src/project/mod.rs
@@ -62,18 +62,40 @@
/// - [`Error::ProjectNotFound`]: No project could be located.
pub fn locate() -> Result<Self> {
let cwd = std::env::current_dir()?;
- let mut cwd = cwd.as_path();
+ let cwd = cwd.as_path();
+ Self::locate_from_path(cwd)
+ }
- let project_root = loop {
- if cwd.join(Self::MANIFEST_FILE).exists() {
- break cwd;
+ // Implementation details of `locate()` without looking up the
+ // current working directory. This allows testing of the core
+ // logic without dependence on the environment and makes it
+ // friendlier to parallel test execution.
+ fn locate_from_path<P: AsRef<Path>>(cwd: P) -> Result<Self> {
+ let mut cwd = cwd.as_ref();
+
+ loop {
+ if let Ok(project) = Self::load(cwd) {
+ return Ok(project);
}
cwd = match cwd.parent() {
Some(p) => p,
None => return Err(Error::ProjectNotFound),
}
- };
+ }
+ }
+
+ /// Load a qg project from an specific path.
+ ///
+ /// # Errors
+ /// May return one of the following errors:
+ /// - [`Error::File`]: Failed to access the filesystem.
+ /// - [`Error::ProjectNotFound`]: No project manifest found in `project_root`.
+ pub fn load<P: AsRef<Path>>(project_root: P) -> Result<Self> {
+ let project_root = project_root.as_ref();
+ if !project_root.join(Self::MANIFEST_FILE).exists() {
+ return Err(Error::ProjectNotFound);
+ }
let manifest = self::File::new(project_root.join(Self::MANIFEST_FILE))
.deserialize_toml::<Manifest>()?;
@@ -314,4 +336,22 @@
Error::InvalidPath,
));
}
+
+ #[test]
+ fn locate_test_project() {
+ // Test that `locate()` and find a manifest from a parent directory.
+ let project =
+ Project::locate_from_path("./src/test_projects/simple/subdir/subsubdir").unwrap();
+ assert_eq!(project.name, "test-qg-project");
+ }
+
+ #[test]
+ fn load_test_project() {
+ // Loads from the project root succeed.
+ let project = Project::load("./src/test_projects/simple").unwrap();
+ assert_eq!(project.name, "test-qg-project");
+
+ // Loads from a project subdirectory fail.
+ assert!(Project::load("./src/test_projects/simple/subdir/subsubdir").is_err());
+ }
}
diff --git a/qg/src/test_projects/simple/qg.toml b/qg/src/test_projects/simple/qg.toml
new file mode 100644
index 0000000..23405e2
--- /dev/null
+++ b/qg/src/test_projects/simple/qg.toml
@@ -0,0 +1,2 @@
+[project]
+name = "test-qg-project"
diff --git a/qg/src/test_projects/simple/subdir/subsubdir/keepdir b/qg/src/test_projects/simple/subdir/subsubdir/keepdir
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/qg/src/test_projects/simple/subdir/subsubdir/keepdir