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}