|
4 | 4 | import pytest |
5 | 5 |
|
6 | 6 | from cryosparc.dataset import Dataset |
7 | | -from cryosparc.job import Job |
| 7 | +from cryosparc.job import ExternalJob, Job |
8 | 8 | from cryosparc.project import Project |
| 9 | +from cryosparc.tools import CryoSPARC |
| 10 | + |
| 11 | +from .conftest import T20S_PARTICLES |
9 | 12 |
|
10 | 13 |
|
11 | 14 | @pytest.fixture |
12 | 15 | def job(cs, project: Project): |
13 | 16 | return project.find_job("J1") |
14 | 17 |
|
15 | 18 |
|
| 19 | +@pytest.fixture |
| 20 | +def mock_external_job_doc(): |
| 21 | + return { |
| 22 | + "_id": "67292e95282b26b45d0e8fee", |
| 23 | + "uid": "J2", |
| 24 | + "uid_num": 2, |
| 25 | + "project_uid": "P1", |
| 26 | + "project_uid_num": 1, |
| 27 | + "type": "snowflake", |
| 28 | + "job_type": "snowflake", |
| 29 | + "title": "Recenter Particles", |
| 30 | + "description": "Enter a description.", |
| 31 | + "status": "building", |
| 32 | + "created_at": "Mon, 04 Nov 2024 20:29:09 GMT", |
| 33 | + "created_by_user_id": "61f0383552d791f286b796ef", |
| 34 | + "parents": [], |
| 35 | + "children": [], |
| 36 | + "input_slot_groups": [], |
| 37 | + "output_result_groups": [], |
| 38 | + "output_results": [], |
| 39 | + "params_base": {}, |
| 40 | + "params_spec": {}, |
| 41 | + "params_secs": {}, |
| 42 | + "workspace_uids": ["W1"], |
| 43 | + } |
| 44 | + |
| 45 | + |
| 46 | +@pytest.fixture |
| 47 | +def external_job( |
| 48 | + mock_jsonrpc_procs_vis, |
| 49 | + mock_jsonrpc_procs_core, |
| 50 | + mock_external_job_doc, |
| 51 | + cs: CryoSPARC, |
| 52 | + project: Project, |
| 53 | +): |
| 54 | + mock_jsonrpc_procs_vis["create_external_job"] = "J2" |
| 55 | + mock_jsonrpc_procs_core["get_job"] = mock_external_job_doc |
| 56 | + cs.cli() |
| 57 | + cs.vis() |
| 58 | + return project.create_external_job("W1", title="Recenter Particles") |
| 59 | + |
| 60 | + |
16 | 61 | def test_queue(job: Job): |
17 | 62 | job.queue() |
18 | 63 | queue_request = httpretty.latest_requests()[-3] |
@@ -104,3 +149,108 @@ def test_job_subprocess_io(job: Job): |
104 | 149 | opt1 = {"project_uid": "P1", "job_uid": "J1", "message": "error", "error": False} |
105 | 150 | opt2 = {"project_uid": "P1", "job_uid": "J1", "message": "world", "error": False} |
106 | 151 | assert params == opt1 or params == opt2 |
| 152 | + |
| 153 | + |
| 154 | +def test_create_external_job(cs: CryoSPARC, external_job: ExternalJob): |
| 155 | + requests = httpretty.latest_requests() |
| 156 | + create_external_job_request = requests[-3] |
| 157 | + create_external_job_body = create_external_job_request.parsed_body |
| 158 | + find_external_job_request = requests[-1] |
| 159 | + find_external_job_body = find_external_job_request.parsed_body |
| 160 | + |
| 161 | + assert create_external_job_body["method"] == "create_external_job" |
| 162 | + assert create_external_job_body["params"] == { |
| 163 | + "project_uid": "P1", |
| 164 | + "workspace_uid": "W1", |
| 165 | + "user": cs.user_id, |
| 166 | + "title": "Recenter Particles", |
| 167 | + "desc": None, |
| 168 | + } |
| 169 | + assert find_external_job_body["method"] == "get_job" |
| 170 | + assert find_external_job_body["params"] == ["P1", "J2"] |
| 171 | + |
| 172 | + |
| 173 | +@pytest.fixture |
| 174 | +def external_job_output(mock_jsonrpc_procs_vis, mock_external_job_doc, cs: CryoSPARC, external_job: ExternalJob): |
| 175 | + mock_external_job_doc["output_result_groups"] = [ |
| 176 | + { |
| 177 | + "uid": "J2-G1", |
| 178 | + "type": "particle", |
| 179 | + "name": "particles", |
| 180 | + "title": "Particles", |
| 181 | + "description": "", |
| 182 | + "contains": [ |
| 183 | + { |
| 184 | + "uid": "J2-R1", |
| 185 | + "type": "particle.blob", |
| 186 | + "group_name": "particles", |
| 187 | + "name": "blob", |
| 188 | + "passthrough": False, |
| 189 | + }, |
| 190 | + { |
| 191 | + "uid": "J2-R2", |
| 192 | + "type": "particle.ctf", |
| 193 | + "group_name": "particles", |
| 194 | + "name": "ctf", |
| 195 | + "passthrough": False, |
| 196 | + }, |
| 197 | + ], |
| 198 | + "passthrough": False, |
| 199 | + } |
| 200 | + ] |
| 201 | + mock_external_job_doc["output_results"] = [ |
| 202 | + { |
| 203 | + "uid": "J2-R1", |
| 204 | + "type": "particle.blob", |
| 205 | + "group_name": "particles", |
| 206 | + "name": "blob", |
| 207 | + "title": "", |
| 208 | + "description": "", |
| 209 | + "min_fields": [["path", "O"], ["idx", "u4"], ["shape", "2u4"], ["psize_A", "f4"], ["sign", "f4"]], |
| 210 | + "versions": [0], |
| 211 | + "metafiles": ["J2/particles.cs"], |
| 212 | + "num_items": [10], |
| 213 | + "passthrough": False, |
| 214 | + }, |
| 215 | + { |
| 216 | + "uid": "J2-R2", |
| 217 | + "type": "particle.ctf", |
| 218 | + "group_name": "particles", |
| 219 | + "name": "ctf", |
| 220 | + "title": "", |
| 221 | + "description": "", |
| 222 | + "min_fields": [["type", "O"], ["exp_group_id", "u4"], ["accel_kv", "f4"], ["cs_mm", "f4"]], |
| 223 | + "versions": [0], |
| 224 | + "metafiles": ["J2/particles.cs"], |
| 225 | + "num_items": [10], |
| 226 | + "passthrough": False, |
| 227 | + }, |
| 228 | + ] |
| 229 | + mock_jsonrpc_procs_vis["add_external_job_output"] = "particles" |
| 230 | + httpretty.register_uri( |
| 231 | + httpretty.POST, |
| 232 | + "http://localhost:39003/external/projects/P1/jobs/J2/outputs/particles/dataset", |
| 233 | + body='"particles"', |
| 234 | + ) |
| 235 | + |
| 236 | + cs.vis() |
| 237 | + external_job.add_output("particle", name="particles", slots=["blob", "ctf"]) |
| 238 | + external_job.save_output("particles", T20S_PARTICLES) |
| 239 | + return T20S_PARTICLES |
| 240 | + |
| 241 | + |
| 242 | +def test_external_job_output(external_job_output): |
| 243 | + requests = httpretty.latest_requests() |
| 244 | + create_output_request = requests[-3] |
| 245 | + find_external_job_request = requests[-1] |
| 246 | + find_external_job_body = find_external_job_request.parsed_body |
| 247 | + |
| 248 | + assert len(external_job_output) > 0 |
| 249 | + assert create_output_request.url == "http://localhost:39003/external/projects/P1/jobs/J2/outputs/particles/dataset" |
| 250 | + assert find_external_job_body["method"] == "get_job" |
| 251 | + assert find_external_job_body["params"] == ["P1", "J2"] |
| 252 | + |
| 253 | + |
| 254 | +def test_invalid_external_job_output(external_job): |
| 255 | + with pytest.raises(ValueError, match="Invalid output name"): |
| 256 | + external_job.add_output("particle", name="particles/1", slots=["blob", "ctf"]) |
0 commit comments