litcheck_lit/test/registry/
default.rs1use std::{path::Path, sync::Arc};
2
3use litcheck::{
4 diagnostics::{DiagResult, IntoDiagnostic},
5 fs,
6};
7
8use crate::test::{Test, TestConfig, TestList, TestSuite};
9
10use super::TestRegistry;
11
12pub struct DefaultTestRegistry;
23impl TestRegistry for DefaultTestRegistry {
24 fn all(&self, suite: Arc<TestSuite>) -> DiagResult<TestList> {
25 let source_dir = suite.source_dir();
26 get_file_based_tests(source_dir, suite.clone(), suite.config.clone())
27 }
28
29 fn find(
30 &self,
31 path_in_suite: &Path,
32 suite: Arc<TestSuite>,
33 config: Arc<TestConfig>,
34 ) -> DiagResult<TestList> {
35 let source_dir = suite.source_dir();
36 let absolute_path = source_dir.join(path_in_suite);
37 if absolute_path.is_dir() {
38 return get_file_based_tests(&absolute_path, suite, config);
39 }
40 log::debug!(
41 "checking if {} is a valid test file using default registry",
42 absolute_path.display()
43 );
44
45 let mut tests = TestList::default();
46 if is_file_based_test(&absolute_path, &suite, &config) {
47 log::debug!(
48 "{} is a valid test, adding it to registry",
49 absolute_path.display()
50 );
51 tests.push_back(Arc::new(Test::new(
52 path_in_suite.to_path_buf(),
53 suite,
54 config,
55 )));
56 }
57 Ok(tests)
58 }
59}
60
61fn get_file_based_tests(
63 search_path: &Path,
64 suite: Arc<TestSuite>,
65 config: Arc<TestConfig>,
66) -> DiagResult<TestList> {
67 debug_assert!(search_path.is_absolute());
68
69 log::debug!(
70 "searching for tests in {} using default registry",
71 search_path.display()
72 );
73 let results = fs::search_directory(search_path, true, |entry| {
74 let path = entry.path();
75 log::trace!("checking if file is valid test: {}", path.display());
76 is_file_based_test(path, &suite, &config)
77 });
78
79 let mut tests = TestList::default();
80 for result in results {
81 let test_path = result.into_diagnostic()?.into_path();
82 log::trace!("found test file: {}", test_path.display());
83 let relative_path = test_path
84 .strip_prefix(search_path)
85 .expect("expected path relative to search_path");
86 tests.push_back(Arc::new(Test::new(
87 relative_path.to_path_buf(),
88 suite.clone(),
89 config.clone(),
90 )));
91 }
92
93 Ok(tests)
94}
95
96fn is_file_based_test(path: &Path, suite: &TestSuite, config: &TestConfig) -> bool {
98 let is_hidden = path
99 .file_name()
100 .map(|name| name.as_encoded_bytes().starts_with(b"."))
101 .unwrap_or(false);
102
103 if is_hidden || !path.is_file() {
104 return false;
105 }
106
107 let path_in_suite = path.strip_prefix(suite.source_dir()).unwrap_or(path);
108 config
109 .patterns
110 .iter()
111 .any(|p| p.matches_path(path_in_suite))
112}