Skip to content

Commit fde714f

Browse files
Add unit tests for iRODS file source functionality
1 parent 54ca917 commit fde714f

1 file changed

Lines changed: 204 additions & 0 deletions

File tree

test/unit/files/test_irods.py

Lines changed: 204 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,204 @@
1+
import os
2+
import socket
3+
import pytest
4+
5+
from galaxy.files.models import (
6+
FileSourcePluginsConfig,
7+
FilesSourceRuntimeContext,
8+
UserData,
9+
)
10+
from galaxy.files.plugins import FileSourcePluginLoader
11+
from galaxy.files.sources.irods import IrodsFilesSource
12+
from ._util import (
13+
assert_realizes_contains,
14+
configured_file_sources,
15+
write_from,
16+
)
17+
18+
try:
19+
from irods.session import iRODSSession
20+
except ImportError:
21+
iRODSSession = None
22+
23+
24+
ROUNDTRIP_TEST_FILENAME = "numerical_sort_and_write_back_to_irods_v2.tab"
25+
26+
27+
class _FakeSession:
28+
init_kwargs = None
29+
30+
def __init__(self, **kwargs):
31+
type(self).init_kwargs = kwargs
32+
self.connection_timeout = None
33+
self.default_resource = None
34+
35+
36+
class _FakeIrodsFs:
37+
def __init__(self, session, root=None):
38+
self.session = session
39+
self.root = root
40+
41+
42+
def _irods_live_settings() -> dict:
43+
host = os.environ.get("GALAXY_TEST_IRODS_HOST", "127.0.0.1")
44+
port = int(os.environ.get("GALAXY_TEST_IRODS_PORT", "1247"))
45+
username = os.environ.get("GALAXY_TEST_IRODS_USER", "rods")
46+
password = os.environ.get("GALAXY_TEST_IRODS_PASSWORD", "rods")
47+
zone = os.environ.get("GALAXY_TEST_IRODS_ZONE", "tempZone")
48+
root = os.environ.get("GALAXY_TEST_IRODS_ROOT", f"/{zone}/home/{username}")
49+
timeout = int(os.environ.get("GALAXY_TEST_IRODS_TIMEOUT", "30"))
50+
refresh_time = int(os.environ.get("GALAXY_TEST_IRODS_REFRESH_TIME", "300"))
51+
return {
52+
"host": host,
53+
"port": port,
54+
"username": username,
55+
"password": password,
56+
"zone": zone,
57+
"root": root,
58+
"timeout": timeout,
59+
"refresh_time": refresh_time,
60+
}
61+
62+
63+
def _skip_if_irods_unreachable(host: str, port: int):
64+
try:
65+
with socket.create_connection((host, port), timeout=1):
66+
return
67+
except OSError:
68+
pytest.skip(
69+
f"No reachable iRODS service at {host}:{port}. "
70+
"Start your local iRODS Docker stack or override GALAXY_TEST_IRODS_* settings."
71+
)
72+
73+
74+
def _live_file_source_config(settings: dict, writable: bool = False) -> list[dict]:
75+
return [
76+
{
77+
"type": "irods",
78+
"id": "test1",
79+
"label": "iRODS Live Test",
80+
"doc": "Live iRODS connectivity smoke test",
81+
"host": settings["host"],
82+
"port": settings["port"],
83+
"username": settings["username"],
84+
"password": settings["password"],
85+
"zone": settings["zone"],
86+
"root": settings["root"],
87+
"timeout": settings["timeout"],
88+
"refresh_time": settings["refresh_time"],
89+
"writable": writable,
90+
}
91+
]
92+
93+
94+
def _cleanup_live_test_artifacts(settings: dict):
95+
root = settings["root"].rstrip("/")
96+
logical_path = f"{root}/{ROUNDTRIP_TEST_FILENAME}"
97+
98+
session = iRODSSession(
99+
host=settings["host"],
100+
port=settings["port"],
101+
user=settings["username"],
102+
password=settings["password"],
103+
zone=settings["zone"],
104+
refresh_time=settings["refresh_time"],
105+
)
106+
session.connection_timeout = settings["timeout"]
107+
108+
try:
109+
if session.data_objects.exists(logical_path):
110+
session.data_objects.unlink(logical_path)
111+
finally:
112+
session.cleanup()
113+
114+
115+
def test_irods_plugin_registered():
116+
plugin_loader = FileSourcePluginLoader()
117+
plugin_class = plugin_loader.get_plugin_type_class("irods")
118+
assert plugin_class is IrodsFilesSource
119+
120+
121+
def test_irods_open_fs_builds_session(monkeypatch):
122+
monkeypatch.setattr("galaxy.files.sources.irods.iRODSSession", _FakeSession)
123+
monkeypatch.setattr("galaxy.files.sources.irods.iRODSFS", _FakeIrodsFs)
124+
monkeypatch.setattr(IrodsFilesSource, "required_module", _FakeIrodsFs)
125+
126+
file_source = IrodsFilesSource(
127+
IrodsFilesSource.build_template_config(
128+
type="irods",
129+
id="test_irods",
130+
file_sources_config=FileSourcePluginsConfig(),
131+
host="irods.example.org",
132+
port=1247,
133+
username="rods",
134+
password="secret",
135+
zone="tempZone",
136+
root="/tempZone/home/rods",
137+
timeout=42,
138+
refresh_time=120,
139+
resource="demoResc",
140+
writable=True,
141+
)
142+
)
143+
144+
resolved_config = file_source._evaluate_template_config(UserData())
145+
context = FilesSourceRuntimeContext(user_data=UserData(), config=resolved_config)
146+
147+
fs = file_source._open_fs(context)
148+
init_kwargs = _FakeSession.init_kwargs
149+
150+
assert isinstance(fs, _FakeIrodsFs)
151+
assert fs.root == "/tempZone/home/rods"
152+
assert init_kwargs is not None
153+
assert init_kwargs["host"] == "irods.example.org"
154+
assert init_kwargs["port"] == 1247
155+
assert init_kwargs["user"] == "rods"
156+
assert init_kwargs["password"] == "secret"
157+
assert init_kwargs["zone"] == "tempZone"
158+
assert init_kwargs["refresh_time"] == 120
159+
assert fs.session.connection_timeout == 42
160+
assert fs.session.default_resource == "demoResc"
161+
162+
163+
def test_irods_live_touch():
164+
settings = _irods_live_settings()
165+
_skip_if_irods_unreachable(settings["host"], settings["port"])
166+
_cleanup_live_test_artifacts(settings)
167+
168+
file_sources = configured_file_sources(_live_file_source_config(settings, writable=False))
169+
file_source_pair = file_sources.get_file_source_path("gxfiles://test1")
170+
171+
assert file_source_pair.path == "/"
172+
entries, count = file_source_pair.file_source.list("/", recursive=False)
173+
assert isinstance(entries, list)
174+
assert count >= 0
175+
_cleanup_live_test_artifacts(settings)
176+
177+
178+
def test_irods_live_recursive_list():
179+
settings = _irods_live_settings()
180+
_skip_if_irods_unreachable(settings["host"], settings["port"])
181+
_cleanup_live_test_artifacts(settings)
182+
183+
file_sources = configured_file_sources(_live_file_source_config(settings, writable=False))
184+
file_source_pair = file_sources.get_file_source_path("gxfiles://test1")
185+
186+
entries, count = file_source_pair.file_source.list("/", recursive=True)
187+
assert isinstance(entries, list)
188+
assert count >= 0
189+
_cleanup_live_test_artifacts(settings)
190+
191+
192+
def test_irods_live_write_and_read_roundtrip():
193+
settings = _irods_live_settings()
194+
_skip_if_irods_unreachable(settings["host"], settings["port"])
195+
_cleanup_live_test_artifacts(settings)
196+
197+
test_contents = "1\t2\t999\n666\t6\t555\n3\t4\t5\n"
198+
target_uri = f"gxfiles://test1/{ROUNDTRIP_TEST_FILENAME}"
199+
200+
file_sources = configured_file_sources(_live_file_source_config(settings, writable=True))
201+
_ = write_from(file_sources, target_uri, test_contents)
202+
assert_realizes_contains(file_sources, target_uri, test_contents)
203+
204+
_cleanup_live_test_artifacts(settings)

0 commit comments

Comments
 (0)