Skip to content

Commit 02ece9e

Browse files
committed
rimport: Add system tests (call from cmdline).
1 parent 63df153 commit 02ece9e

2 files changed

Lines changed: 312 additions & 2 deletions

File tree

rimport

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -180,8 +180,10 @@ def main(argv: List[str] | None = None) -> int:
180180
args = parser.parse_args(argv)
181181

182182
# Ensure we are running as the cesmdata account before touching the tree
183-
# Comment out the next line if you prefer to run `sudox -u cesmdata rimport …` explicitly.
184-
ensure_running_as("cesmdata", sys.argv)
183+
# Set env var RIMPORT_SKIP_USER_CHECK=1 if you prefer to run `sudox -u cesmdata rimport …`
184+
# explicitly (or for testing).
185+
if os.getenv("RIMPORT_SKIP_USER_CHECK") != "1":
186+
ensure_running_as("cesmdata", sys.argv)
185187

186188
root = Path(args.inputdata).expanduser().resolve()
187189
if not root.exists():

tests/rimport/test_cmdline.py

Lines changed: 308 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,308 @@
1+
"""
2+
System tests for rimport script executed from command line.
3+
"""
4+
5+
import os
6+
import sys
7+
import subprocess
8+
9+
import pytest
10+
11+
12+
@pytest.fixture(name="rimport_script")
13+
def fixture_rimport_script():
14+
"""Return the path to the rimport script."""
15+
return os.path.join(
16+
os.path.dirname(os.path.dirname(os.path.dirname(os.path.abspath(__file__)))),
17+
"rimport",
18+
)
19+
20+
21+
@pytest.fixture(name="test_env")
22+
def fixture_test_env(tmp_path):
23+
"""Create test environment with inputdata and staging directories."""
24+
inputdata_root = tmp_path / "inputdata"
25+
staging_root = tmp_path / "staging"
26+
inputdata_root.mkdir()
27+
staging_root.mkdir()
28+
29+
return {
30+
"inputdata_root": inputdata_root,
31+
"staging_root": staging_root,
32+
"tmp_path": tmp_path,
33+
}
34+
35+
36+
@pytest.fixture(name="rimport_env")
37+
def fixture_rimport_env(test_env):
38+
"""Create environment dict for running rimport with test settings."""
39+
env = os.environ.copy()
40+
env["RIMPORT_STAGING"] = str(test_env["staging_root"])
41+
env["RIMPORT_SKIP_USER_CHECK"] = "1"
42+
return env
43+
44+
45+
class TestRimportCommandLine:
46+
"""System tests for rimport command-line execution."""
47+
48+
def test_file_option_stages_single_file(
49+
self, rimport_script, test_env, rimport_env
50+
):
51+
"""Test that -file option stages a single file."""
52+
inputdata_root = test_env["inputdata_root"]
53+
staging_root = test_env["staging_root"]
54+
55+
# Create a file in inputdata
56+
test_file = inputdata_root / "test.nc"
57+
test_file.write_text("test data")
58+
59+
# Run rimport with -file option
60+
command = [
61+
sys.executable,
62+
rimport_script,
63+
"-file",
64+
"test.nc",
65+
"-inputdata",
66+
str(inputdata_root),
67+
]
68+
69+
result = subprocess.run(
70+
command,
71+
capture_output=True,
72+
text=True,
73+
check=False,
74+
env=rimport_env,
75+
)
76+
77+
# Verify success
78+
assert result.returncode == 0, f"Command failed: {result.stderr}"
79+
80+
# Verify file was staged
81+
staged_file = staging_root / "test.nc"
82+
assert staged_file.exists()
83+
assert staged_file.read_text() == "test data"
84+
85+
def test_list_option_stages_multiple_files(
86+
self, rimport_script, test_env, rimport_env
87+
):
88+
"""Test that -list option stages multiple files."""
89+
inputdata_root = test_env["inputdata_root"]
90+
staging_root = test_env["staging_root"]
91+
tmp_path = test_env["tmp_path"]
92+
93+
# Create files in inputdata
94+
file1 = inputdata_root / "file1.nc"
95+
file2 = inputdata_root / "file2.nc"
96+
file1.write_text("data1")
97+
file2.write_text("data2")
98+
99+
# Create filelist
100+
filelist = tmp_path / "filelist.txt"
101+
filelist.write_text("file1.nc\nfile2.nc\n")
102+
103+
# Run rimport with -list option
104+
command = [
105+
sys.executable,
106+
rimport_script,
107+
"-list",
108+
str(filelist),
109+
"-inputdata",
110+
str(inputdata_root),
111+
]
112+
113+
result = subprocess.run(
114+
command,
115+
capture_output=True,
116+
text=True,
117+
check=False,
118+
env=rimport_env,
119+
)
120+
121+
# Verify success
122+
assert result.returncode == 0, f"Command failed: {result.stderr}"
123+
124+
# Verify both files were staged
125+
assert (staging_root / "file1.nc").exists()
126+
assert (staging_root / "file2.nc").exists()
127+
assert (staging_root / "file1.nc").read_text() == "data1"
128+
assert (staging_root / "file2.nc").read_text() == "data2"
129+
130+
def test_preserves_directory_structure(self, rimport_script, test_env, rimport_env):
131+
"""Test that directory structure is preserved in staging."""
132+
inputdata_root = test_env["inputdata_root"]
133+
staging_root = test_env["staging_root"]
134+
135+
# Create nested file
136+
nested_file = inputdata_root / "dir1" / "dir2" / "file.nc"
137+
nested_file.parent.mkdir(parents=True)
138+
nested_file.write_text("nested data")
139+
140+
# Run rimport
141+
command = [
142+
sys.executable,
143+
rimport_script,
144+
"-file",
145+
"dir1/dir2/file.nc",
146+
"-inputdata",
147+
str(inputdata_root),
148+
]
149+
150+
result = subprocess.run(
151+
command,
152+
capture_output=True,
153+
text=True,
154+
check=False,
155+
env=rimport_env,
156+
)
157+
158+
# Verify success
159+
assert result.returncode == 0, f"Command failed: {result.stderr}"
160+
161+
# Verify directory structure is preserved
162+
staged_file = staging_root / "dir1" / "dir2" / "file.nc"
163+
assert staged_file.exists()
164+
assert staged_file.read_text() == "nested data"
165+
166+
def test_error_for_nonexistent_file(self, rimport_script, test_env, rimport_env):
167+
"""Test that error is reported for nonexistent file."""
168+
inputdata_root = test_env["inputdata_root"]
169+
170+
# Run rimport with nonexistent file
171+
command = [
172+
sys.executable,
173+
rimport_script,
174+
"-file",
175+
"nonexistent.nc",
176+
"-inputdata",
177+
str(inputdata_root),
178+
]
179+
180+
result = subprocess.run(
181+
command,
182+
capture_output=True,
183+
text=True,
184+
check=False,
185+
env=rimport_env,
186+
)
187+
188+
# Verify error
189+
assert result.returncode != 0
190+
assert "error" in result.stderr.lower()
191+
192+
def test_error_for_nonexistent_list_file(
193+
self, rimport_script, test_env, rimport_env
194+
):
195+
"""Test that error is reported when list file doesn't exist."""
196+
inputdata_root = test_env["inputdata_root"]
197+
tmp_path = test_env["tmp_path"]
198+
199+
# Run rimport with nonexistent list file
200+
command = [
201+
sys.executable,
202+
rimport_script,
203+
"-list",
204+
str(tmp_path / "nonexistent.txt"),
205+
"-inputdata",
206+
str(inputdata_root),
207+
]
208+
209+
result = subprocess.run(
210+
command,
211+
capture_output=True,
212+
text=True,
213+
check=False,
214+
env=rimport_env,
215+
)
216+
217+
# Verify error
218+
assert result.returncode == 2
219+
assert "list file not found" in result.stderr
220+
221+
def test_error_for_empty_list_file(self, rimport_script, test_env, rimport_env):
222+
"""Test that error is reported when list file is empty."""
223+
inputdata_root = test_env["inputdata_root"]
224+
tmp_path = test_env["tmp_path"]
225+
226+
# Create empty list file
227+
filelist = tmp_path / "empty.txt"
228+
filelist.write_text("")
229+
230+
# Run rimport
231+
command = [
232+
sys.executable,
233+
rimport_script,
234+
"-list",
235+
str(filelist),
236+
"-inputdata",
237+
str(inputdata_root),
238+
]
239+
240+
result = subprocess.run(
241+
command,
242+
capture_output=True,
243+
text=True,
244+
check=False,
245+
env=rimport_env,
246+
)
247+
248+
# Verify error
249+
assert result.returncode == 2
250+
assert "no filenames found" in result.stderr
251+
252+
@pytest.mark.parametrize("help_flag", ["-help", "-h"])
253+
def test_help_flag_shows_help(self, rimport_script, help_flag):
254+
"""Test that help flags show help message."""
255+
command = [sys.executable, rimport_script, help_flag]
256+
257+
result = subprocess.run(
258+
command,
259+
capture_output=True,
260+
text=True,
261+
check=False,
262+
)
263+
264+
# Help should exit with code 0
265+
assert result.returncode == 0
266+
assert "SYNOPSIS" in result.stdout
267+
assert "OPTIONS" in result.stdout
268+
269+
def test_list_with_comments_and_blanks(self, rimport_script, test_env, rimport_env):
270+
"""Test that list file with comments and blank lines works correctly."""
271+
inputdata_root = test_env["inputdata_root"]
272+
staging_root = test_env["staging_root"]
273+
tmp_path = test_env["tmp_path"]
274+
275+
# Create files
276+
file1 = inputdata_root / "file1.nc"
277+
file2 = inputdata_root / "file2.nc"
278+
file1.write_text("data1")
279+
file2.write_text("data2")
280+
281+
# Create filelist with comments and blanks
282+
filelist = tmp_path / "filelist.txt"
283+
filelist.write_text("# Comment\nfile1.nc\n\n# Another comment\nfile2.nc\n")
284+
285+
# Run rimport
286+
command = [
287+
sys.executable,
288+
rimport_script,
289+
"-list",
290+
str(filelist),
291+
"-inputdata",
292+
str(inputdata_root),
293+
]
294+
295+
result = subprocess.run(
296+
command,
297+
capture_output=True,
298+
text=True,
299+
check=False,
300+
env=rimport_env,
301+
)
302+
303+
# Verify success
304+
assert result.returncode == 0, f"Command failed: {result.stderr}"
305+
306+
# Verify both files were staged
307+
assert (staging_root / "file1.nc").exists()
308+
assert (staging_root / "file2.nc").exists()

0 commit comments

Comments
 (0)