[docs] 1# @Test suite for source code analysis and marker extraction, TEST_ANA_1, test, [IMPL_LNK_1, IMPL_ONE_1, IMPL_MRST_1]
2import json
3from pathlib import Path
4
5import pytest
6
7from sphinx_codelinks.analyse.analyse import SourceAnalyse
8from sphinx_codelinks.config import SourceAnalyseConfig
9from tests.conftest import (
10 ONELINE_COMMENT_STYLE,
11 ONELINE_COMMENT_STYLE_DEFAULT,
12 TEST_DIR,
13)
14
15TEST_DATA_DIR = Path(__file__).parent.parent / "tests" / "data"
16
17
18@pytest.mark.parametrize(
19 ("src_dir", "src_paths"),
20 [
21 (
22 TEST_DATA_DIR,
23 [
24 TEST_DATA_DIR / "oneline_comment_default" / "default_oneliners.c",
25 TEST_DATA_DIR / "need_id_refs" / "dummy_1.cpp",
26 TEST_DATA_DIR / "marked_rst" / "dummy_1.cpp",
27 ],
28 )
29 ],
30)
31def test_analyse(src_dir, src_paths, tmp_path, snapshot_marks):
32 src_analyse_config = SourceAnalyseConfig(
33 src_files=src_paths,
34 src_dir=src_dir,
35 get_need_id_refs=True,
36 get_oneline_needs=True,
37 get_rst=True,
38 )
39
40 analyse = SourceAnalyse(src_analyse_config)
41 analyse.git_remote_url = None
42 analyse.git_commit_rev = None
43 analyse.run()
44 analyse.dump_marked_content(tmp_path)
45
46 dumped_content = tmp_path / "marked_content.json"
47 with dumped_content.open("r") as f:
48 marked_content = json.load(f)
49 # normalize filepath
50 for obj in marked_content:
51 obj["filepath"] = (
52 Path(obj["filepath"]).relative_to(src_analyse_config.src_dir)
53 ).as_posix()
54 assert marked_content == snapshot_marks
55
56
57@pytest.mark.parametrize(
58 "src_dir, src_paths , oneline_comment_style, result",
59 [
60 (
61 TEST_DIR / "data" / "dcdc",
62 [
63 TEST_DIR / "data" / "dcdc" / "charge" / "demo_1.cpp",
64 TEST_DIR / "data" / "dcdc" / "charge" / "demo_2.cpp",
65 TEST_DIR / "data" / "dcdc" / "discharge" / "demo_3.cpp",
66 TEST_DIR / "data" / "dcdc" / "supercharge.cpp",
67 ],
68 ONELINE_COMMENT_STYLE,
69 {
70 "num_src_files": 4,
71 "num_uncached_files": 4,
72 "num_cached_files": 0,
73 "num_comments": 29,
74 "num_oneline_warnings": 0,
75 },
76 ),
77 (
78 TEST_DIR / "data" / "oneline_comment_basic",
79 [
80 TEST_DIR / "data" / "oneline_comment_basic" / "basic_oneliners.c",
81 ],
82 ONELINE_COMMENT_STYLE,
83 {
84 "num_src_files": 1,
85 "num_uncached_files": 1,
86 "num_cached_files": 0,
87 "num_comments": 14,
88 "num_oneline_warnings": 0,
89 "warnings_path_exists": True,
90 },
91 ),
92 (
93 TEST_DIR / "data" / "oneline_comment_default",
94 [
95 TEST_DIR / "data" / "oneline_comment_default" / "default_oneliners.c",
96 ],
97 ONELINE_COMMENT_STYLE_DEFAULT,
98 {
99 "num_src_files": 1,
100 "num_uncached_files": 1,
101 "num_cached_files": 0,
102 "num_comments": 5,
103 "num_oneline_warnings": 1,
104 "warnings_path_exists": True,
105 },
106 ),
107 (
108 TEST_DIR / "data" / "rust",
109 [
110 TEST_DIR / "data" / "rust" / "demo.rs",
111 ],
112 ONELINE_COMMENT_STYLE_DEFAULT,
113 {
114 "num_src_files": 1,
115 "num_uncached_files": 1,
116 "num_cached_files": 0,
117 "num_comments": 6,
118 "num_oneline_warnings": 0,
119 },
120 ),
121 ],
122)
123def test_analyse_oneline_needs(
124 tmp_path, src_dir, src_paths, oneline_comment_style, result
125):
126 src_analyse_config = SourceAnalyseConfig(
127 src_files=src_paths,
128 src_dir=src_dir,
129 get_need_id_refs=False,
130 get_oneline_needs=True,
131 get_rst=False,
132 oneline_comment_style=oneline_comment_style,
133 )
134 src_analyse = SourceAnalyse(src_analyse_config)
135 src_analyse.run()
136
137 assert len(src_analyse.src_files) == result["num_src_files"]
138 assert len(src_analyse.oneline_warnings) == result["num_oneline_warnings"]
139
140 cnt_comments = 0
141 for src_file in src_analyse.src_files:
142 cnt_comments += len(src_file.src_comments)
143 assert cnt_comments == result["num_comments"]
144
145
146def test_explicit_git_root_configuration(tmp_path):
147 """Test that explicit git_root configuration is used instead of auto-detection."""
148 # Create a fake git repo structure in tmp_path
149 fake_git_root = tmp_path / "fake_repo"
150 fake_git_root.mkdir()
151 (fake_git_root / ".git").mkdir()
152
153 # Create a minimal .git/config with remote URL
154 git_config = fake_git_root / ".git" / "config"
155 git_config.write_text(
156 '[remote "origin"]\n url = https://github.com/test/repo.git\n'
157 )
158
159 # Create HEAD file pointing to a branch ref
160 git_head = fake_git_root / ".git" / "HEAD"
161 git_head.write_text("ref: refs/heads/main\n")
162
163 # Create the refs/heads/main file with the commit hash
164 refs_dir = fake_git_root / ".git" / "refs" / "heads"
165 refs_dir.mkdir(parents=True)
166 (refs_dir / "main").write_text("abc123def456\n")
167
168 # Create source file in a deeply nested location
169 src_dir = tmp_path / "deeply" / "nested" / "src"
170 src_dir.mkdir(parents=True)
171 src_file = src_dir / "test.c"
172 src_file.write_text("// @Test, TEST_1\nvoid test() {}\n")
173
174 # Configure with explicit git_root
175 src_analyse_config = SourceAnalyseConfig(
176 src_files=[src_file],
177 src_dir=src_dir,
178 get_need_id_refs=False,
179 get_oneline_needs=True,
180 get_rst=False,
181 git_root=fake_git_root,
182 )
183
184 src_analyse = SourceAnalyse(src_analyse_config)
185
186 # Verify the explicit git_root was used
187 assert src_analyse.git_root == fake_git_root.resolve()
188 assert src_analyse.git_remote_url == "https://github.com/test/repo.git"
189 assert src_analyse.git_commit_rev == "abc123def456"
190
191
192def test_git_root_auto_detection_when_not_configured(tmp_path):
193 """Test that git_root is auto-detected when not explicitly configured."""
194 src_dir = TEST_DIR / "data" / "dcdc"
195 src_paths = [src_dir / "charge" / "demo_1.cpp"]
196
197 # Don't set git_root - it should auto-detect
198 src_analyse_config = SourceAnalyseConfig(
199 src_files=src_paths,
200 src_dir=src_dir,
201 get_need_id_refs=False,
202 get_oneline_needs=True,
203 get_rst=False,
204 # git_root is not set, so auto-detection should be used
205 )
206
207 src_analyse = SourceAnalyse(src_analyse_config)
208
209 # The test is running inside a git repo, so git_root should be detected
210 # We just verify it's not None (since this test runs in the sphinx-codelinks repo)
211 assert src_analyse.git_root is not None
212 assert (src_analyse.git_root / ".git").exists()
213
214
215def test_oneline_parser_warnings_are_collected(tmp_path):
216 """Test that oneline parser warnings are collected for later output."""
217 src_dir = TEST_DIR / "data" / "oneline_comment_default"
218 src_paths = [src_dir / "default_oneliners.c"]
219 src_analyse_config = SourceAnalyseConfig(
220 src_files=src_paths,
221 src_dir=src_dir,
222 get_need_id_refs=False,
223 get_oneline_needs=True,
224 get_rst=False,
225 oneline_comment_style=ONELINE_COMMENT_STYLE_DEFAULT,
226 )
227 src_analyse = SourceAnalyse(src_analyse_config)
228 src_analyse.run()
229
230 # Verify that warnings were collected
231 assert len(src_analyse.oneline_warnings) == 1
232 warning = src_analyse.oneline_warnings[0]
233 assert "too_many_fields" in warning.sub_type
234 assert warning.lineno == 17