nautilus_core/paths.rs
1// -------------------------------------------------------------------------------------------------
2// Copyright (C) 2015-2026 Nautech Systems Pty Ltd. All rights reserved.
3// https://nautechsystems.io
4//
5// Licensed under the GNU Lesser General Public License Version 3.0 (the "License");
6// You may not use this file except in compliance with the License.
7// You may obtain a copy of the License at https://www.gnu.org/licenses/lgpl-3.0.en.html
8//
9// Unless required by applicable law or agreed to in writing, software
10// distributed under the License is distributed on an "AS IS" BASIS,
11// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12// See the License for the specific language governing permissions and
13// limitations under the License.
14// -------------------------------------------------------------------------------------------------
15
16//! Utility functions for resolving project and workspace directory paths.
17
18use std::path::PathBuf;
19
20/// Returns the workspace root directory path.
21///
22/// This is the directory containing the top-level `Cargo.toml` with the
23/// `[workspace]` section, typically where `pyproject.toml` and `docs/` are located.
24///
25/// # Panics
26///
27/// Panics if the `CARGO_MANIFEST_DIR` environment variable is not set or
28/// the parent directories cannot be determined.
29#[must_use]
30pub fn get_workspace_root_path() -> PathBuf {
31 PathBuf::from(env!("CARGO_MANIFEST_DIR"))
32 .parent() // crates/core -> crates/
33 .and_then(|p| p.parent()) // crates/ -> nautilus_trader/
34 .expect("Failed to get workspace root")
35 .to_path_buf()
36}
37
38/// Returns the project root directory path.
39///
40/// For this monorepo, the project root is the same as the workspace root.
41///
42/// # Panics
43///
44/// Panics if the workspace root path cannot be determined.
45#[must_use]
46pub fn get_project_root_path() -> PathBuf {
47 get_workspace_root_path()
48}
49
50/// Returns the tests root directory path.
51#[must_use]
52pub fn get_tests_root_path() -> PathBuf {
53 get_project_root_path().join("tests")
54}
55
56/// Returns the test data directory path.
57#[must_use]
58pub fn get_test_data_path() -> PathBuf {
59 if let Ok(test_data_root_path) = std::env::var("TEST_DATA_ROOT_PATH") {
60 get_project_root_path()
61 .join(test_data_root_path)
62 .join("test_data")
63 } else {
64 get_project_root_path().join("tests").join("test_data")
65 }
66}
67
68#[cfg(test)]
69mod tests {
70 use rstest::rstest;
71
72 use super::*;
73
74 #[rstest]
75 fn test_workspace_root_contains_pyproject() {
76 let root = get_workspace_root_path();
77 assert!(
78 root.join("pyproject.toml").exists(),
79 "Workspace root should contain pyproject.toml, got: {root:?}"
80 );
81 }
82
83 #[rstest]
84 fn test_workspace_root_contains_crates_dir() {
85 let root = get_workspace_root_path();
86 assert!(
87 root.join("crates").is_dir(),
88 "Workspace root should contain crates/ directory, got: {root:?}"
89 );
90 }
91
92 #[rstest]
93 fn test_project_root_equals_workspace_root() {
94 assert_eq!(get_project_root_path(), get_workspace_root_path());
95 }
96
97 #[rstest]
98 fn test_tests_root_path() {
99 let tests_root = get_tests_root_path();
100 assert!(
101 tests_root.ends_with("tests"),
102 "Tests root should end with 'tests', got: {tests_root:?}"
103 );
104 }
105}