Coverage for tests/test_drivers.py: 100%
323 statements
« prev ^ index » next coverage.py v7.16.0, created at 2026-09-15 09:03 +0000
« prev ^ index » next coverage.py v7.16.0, created at 2026-09-15 09:03 +0000
1# This file is part of ctrl_bps.
2#
3# Developed for the LSST Data Management System.
4# This product includes software developed by the LSST Project
5# (https://www.lsst.org).
6# See the COPYRIGHT file at the top-level directory of this distribution
7# for details of code ownership.
8#
9# This software is dual licensed under the GNU General Public License and also
10# under a 3-clause BSD license. Recipients may choose which of these licenses
11# to use; please see the files gpl-3.0.txt and/or bsd_license.txt,
12# respectively. If you choose the GPL option then the following text applies
13# (but note that there is still no warranty even if you opt for BSD instead):
14#
15# This program is free software: you can redistribute it and/or modify
16# it under the terms of the GNU General Public License as published by
17# the Free Software Foundation, either version 3 of the License, or
18# (at your option) any later version.
19#
20# This program is distributed in the hope that it will be useful,
21# but WITHOUT ANY WARRANTY; without even the implied warranty of
22# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
23# GNU General Public License for more details.
24#
25# You should have received a copy of the GNU General Public License
26# along with this program. If not, see <https://www.gnu.org/licenses/>.
27"""Unit tests for drivers.py."""
29import logging
30import os
31import shutil
32import tempfile
33import unittest
34from pathlib import Path
36import yaml
38from lsst.ctrl.bps import BaseWmsWorkflow, BpsConfig, WmsRunReport, WmsStates, drivers
39from lsst.ctrl.bps.bps_reports import compile_code_summary, compile_job_summary
41TESTDIR = os.path.abspath(os.path.dirname(__file__))
44class TestInitSubmissionDriver(unittest.TestCase):
45 """Test submission."""
47 def setUp(self):
48 self.cwd = os.getcwd()
49 self.tmpdir = tempfile.mkdtemp(dir=TESTDIR)
51 def tearDown(self):
52 shutil.rmtree(self.tmpdir, ignore_errors=True)
54 @unittest.mock.patch("lsst.ctrl.bps.initialize.BPS_DEFAULTS", {})
55 def testDeprecatedOutCollection(self):
56 config = {
57 "submitPath": "bad",
58 "payload": {
59 "outCollection": "bad",
60 "outputRun": "bad",
61 },
62 }
63 with tempfile.NamedTemporaryFile(mode="w+", suffix=".yaml") as file:
64 yaml.dump(config, stream=file)
65 with self.assertRaisesRegex(KeyError, "outCollection"):
66 drivers._init_submission_driver(file.name)
68 @unittest.mock.patch("lsst.ctrl.bps.initialize.BPS_DEFAULTS", {})
69 def testMissingOutputRun(self):
70 config = {"submitPath": "bad"}
71 with tempfile.NamedTemporaryFile(mode="w+", suffix=".yaml") as file:
72 yaml.dump(config, stream=file)
73 with self.assertRaisesRegex(KeyError, "outputRun"):
74 drivers._init_submission_driver(file.name)
76 @unittest.mock.patch("lsst.ctrl.bps.initialize.BPS_DEFAULTS", {})
77 def testMissingSubmitPath(self):
78 config = {"payload": {"outputRun": "bad"}}
79 with tempfile.NamedTemporaryFile(mode="w+", suffix=".yaml") as file:
80 yaml.dump(config, stream=file)
81 with self.assertRaisesRegex(KeyError, "submitPath"):
82 drivers._init_submission_driver(file.name)
85class TestPingDriver(unittest.TestCase):
86 """Test ping."""
88 def testWmsServiceSuccess(self):
89 retval = drivers.ping_driver("wms_test_utils.WmsServiceSuccess")
90 self.assertEqual(retval, 0)
92 def testWmsServiceFailure(self):
93 with self.assertLogs(level=logging.ERROR) as cm:
94 retval = drivers.ping_driver("wms_test_utils.WmsServiceFailure")
95 self.assertNotEqual(retval, 0)
96 self.assertEqual(cm.records[0].getMessage(), "Couldn't contact service X")
98 def testWmsServiceEnvVar(self):
99 with unittest.mock.patch.dict(
100 os.environ, {"BPS_WMS_SERVICE_CLASS": "wms_test_utils.WmsServiceSuccess"}
101 ):
102 retval = drivers.ping_driver()
103 self.assertEqual(retval, 0)
105 @unittest.mock.patch(
106 "lsst.ctrl.bps.drivers.BPS_DEFAULTS", {"wmsServiceClass": "wms_test_utils.WmsServiceDefault"}
107 )
108 def testWmsServiceNone(self):
109 with unittest.mock.patch.dict(os.environ, {}):
110 with self.assertLogs(level=logging.INFO) as cm:
111 retval = drivers.ping_driver()
112 self.assertEqual(retval, 0)
113 self.assertEqual(cm.records[0].getMessage(), "DEFAULT None")
115 def testWmsServicePassThru(self):
116 with self.assertLogs(level=logging.INFO) as cm:
117 retval = drivers.ping_driver("wms_test_utils.WmsServicePassThru", "EXTRA_VALUES")
118 self.assertEqual(retval, 0)
119 self.assertRegex(cm.output[0], "INFO.+EXTRA_VALUES")
122class TestStatusDriver(unittest.TestCase):
123 """Test status_driver function."""
125 def testWmsServiceSuccess(self):
126 with self.assertLogs(level=logging.INFO) as cm:
127 retval = drivers.status_driver(
128 "wms_test_utils.WmsServiceSuccess", run_id="/dummy/path", hist_days=3
129 )
130 self.assertEqual(retval, WmsStates.SUCCEEDED.value)
131 self.assertEqual(cm.records[0].getMessage(), "status: SUCCEEDED")
133 def testWmsServiceFailure(self):
134 with self.assertLogs(level=logging.WARNING) as cm:
135 retval = drivers.status_driver(
136 "wms_test_utils.WmsServiceFailure", run_id="/dummy/path", hist_days=3
137 )
138 self.assertEqual(retval, WmsStates.FAILED.value)
139 self.assertEqual(cm.records[0].getMessage(), "Dummy error message.")
141 @unittest.mock.patch(
142 "lsst.ctrl.bps.drivers.BPS_DEFAULTS", {"wmsServiceClass": "wms_test_utils.WmsServiceDefault"}
143 )
144 def testWmsServiceNone(self):
145 with unittest.mock.patch.dict(os.environ, {}):
146 retval = drivers.status_driver(None, run_id="/dummy/path", hist_days=3)
147 self.assertEqual(retval, WmsStates.RUNNING.value)
150class TestReportDriver(unittest.TestCase):
151 """Test report_driver function."""
153 @unittest.mock.patch(
154 "lsst.ctrl.bps.drivers.BPS_DEFAULTS", new={"wmsServiceClass": "wms_test_utils.WmsServiceSuccess"}
155 )
156 def testWmsServiceFromDefaults(self):
157 # Should not raise an exception and use default from BPS_DEFAULTS.
158 with unittest.mock.patch.dict(os.environ, {}, clear=True):
159 drivers.report_driver(
160 wms_service=None,
161 run_id=None,
162 user=None,
163 hist_days=0,
164 pass_thru=None,
165 )
167 def testWmsServiceFromEnvVar(self):
168 # Should not raise an exception.
169 with unittest.mock.patch.dict(
170 os.environ, {"BPS_WMS_SERVICE_CLASS": "wms_test_utils.WmsServiceSuccess"}
171 ):
172 drivers.report_driver(
173 wms_service=None,
174 run_id=None,
175 user=None,
176 hist_days=0.0,
177 pass_thru=None,
178 )
180 @unittest.mock.patch("lsst.ctrl.bps.drivers.retrieve_report")
181 @unittest.mock.patch("lsst.ctrl.bps.drivers.display_report")
182 def testHistDefault(self, mock_display, mock_retrieve):
183 mock_retrieve.return_value = ([], [])
185 drivers.report_driver(
186 wms_service="wms_test_utils.WmsServiceSuccess",
187 run_id="123",
188 user=None,
189 hist_days=0.0,
190 pass_thru=None,
191 )
193 # Verify retrieve_report was called with the default hist setting.
194 _, kwargs = mock_retrieve.call_args
195 self.assertAlmostEqual(kwargs["hist"], 2.0)
197 @unittest.mock.patch("lsst.ctrl.bps.drivers.retrieve_report")
198 @unittest.mock.patch("lsst.ctrl.bps.drivers.display_report")
199 def testHistCustom(self, mock_display, mock_retrieve):
200 mock_retrieve.return_value = ([], [])
202 drivers.report_driver(
203 wms_service="wms_test_utils.WmsServiceSuccess",
204 run_id="123",
205 user=None,
206 hist_days=4.0,
207 pass_thru=None,
208 )
210 # Verify retrieve_report was called with a custom hist setting.
211 _, kwargs = mock_retrieve.call_args
212 self.assertAlmostEqual(kwargs["hist"], 4.0)
214 @unittest.mock.patch("lsst.ctrl.bps.drivers.retrieve_report")
215 @unittest.mock.patch("lsst.ctrl.bps.drivers.display_report")
216 def testPostprocessorsWithoutExitCodes(self, mock_display, mock_retrieve):
217 mock_retrieve.return_value = ([], [])
219 drivers.report_driver(
220 wms_service="wms_test_utils.WmsServiceSuccess",
221 run_id="123",
222 user=None,
223 hist_days=0.0,
224 pass_thru=None,
225 return_exit_codes=False,
226 )
228 # Verify the postprocessors list contains only one postprocessor.
229 args, kwargs = mock_retrieve.call_args
230 self.assertEqual(len(kwargs["postprocessors"]), 1)
231 self.assertIn(compile_job_summary, kwargs["postprocessors"])
233 @unittest.mock.patch("lsst.ctrl.bps.drivers.retrieve_report")
234 @unittest.mock.patch("lsst.ctrl.bps.drivers.display_report")
235 def testPostprocessorsWithExitCodes(self, mock_display, mock_retrieve):
236 mock_retrieve.return_value = ([], [])
238 drivers.report_driver(
239 wms_service="wms_test_utils.WmsServiceSuccess",
240 run_id="123",
241 user=None,
242 hist_days=0.0,
243 pass_thru=None,
244 return_exit_codes=True,
245 )
247 # Verify the postprocessors list contains both postprocessors.
248 _, kwargs = mock_retrieve.call_args
249 self.assertEqual(len(kwargs["postprocessors"]), 2)
250 self.assertIn(compile_code_summary, kwargs["postprocessors"])
251 self.assertIn(compile_job_summary, kwargs["postprocessors"])
253 @unittest.mock.patch("lsst.ctrl.bps.drivers.retrieve_report")
254 @unittest.mock.patch("lsst.ctrl.bps.drivers.display_report")
255 def testPostprocessorsNoRunId(self, mock_display, mock_retrieve):
256 mock_retrieve.return_value = ([], [])
258 drivers.report_driver(
259 wms_service="wms_test_utils.WmsServiceSuccess",
260 run_id=None,
261 user=None,
262 hist_days=0.0,
263 pass_thru=None,
264 )
266 # Verify postprocessors contains compile_job_summary
267 _, kwargs = mock_retrieve.call_args
268 self.assertIsNone(kwargs["postprocessors"])
270 @unittest.mock.patch("lsst.ctrl.bps.drivers.retrieve_report")
271 @unittest.mock.patch("lsst.ctrl.bps.drivers.display_report")
272 def testDisplayCalledIfRuns(self, mock_display, mock_retrieve):
273 mock_runs = [WmsRunReport(wms_id="1", state=WmsStates.SUCCEEDED)]
274 mock_retrieve.return_value = (mock_runs, [])
276 drivers.report_driver(
277 wms_service="wms_test_utils.WmsServiceSuccess",
278 run_id=None,
279 user=None,
280 hist_days=0,
281 pass_thru=None,
282 )
284 # Verify display_report was called with the runs
285 mock_display.assert_called_once()
286 args, kwargs = mock_display.call_args
287 self.assertEqual(args[0], mock_runs)
289 @unittest.mock.patch("lsst.ctrl.bps.drivers.retrieve_report")
290 @unittest.mock.patch("lsst.ctrl.bps.drivers.display_report")
291 def testDisplayCalledIfMessages(self, mock_display, mock_retrieve):
292 mock_messages = ["Warning message 1", "Warning message 2"]
293 mock_retrieve.return_value = ([], mock_messages)
295 drivers.report_driver(
296 wms_service="wms_test_utils.WmsServiceSuccess",
297 run_id=None,
298 user=None,
299 hist_days=0,
300 pass_thru=None,
301 )
303 # Verify display_report was called with messages
304 mock_display.assert_called_once()
305 args, kwargs = mock_display.call_args
306 self.assertEqual(args[1], mock_messages)
308 @unittest.mock.patch("lsst.ctrl.bps.drivers.retrieve_report")
309 @unittest.mock.patch("lsst.ctrl.bps.drivers.display_report")
310 @unittest.mock.patch("builtins.print")
311 def testNoRecordsFoundMessage(self, mock_print, mock_display, mock_retrieve):
312 mock_retrieve.return_value = ([], [])
314 drivers.report_driver(
315 wms_service="wms_test_utils.WmsServiceSuccess",
316 run_id="123",
317 user=None,
318 hist_days=1.5,
319 pass_thru=None,
320 )
322 # Verify display_report() was NOT called.
323 mock_display.assert_not_called()
325 # Verify that a helpful message was printed.
326 mock_print.assert_called_once()
327 call_args = mock_print.call_args[0][0]
328 self.assertIn("No records found", call_args)
329 self.assertIn("123", call_args)
332class TestAcquireQgraphDriver(unittest.TestCase):
333 """Test acquire_qgraph_driver function."""
335 def setUp(self):
336 self.tmpdir = Path(tempfile.mkdtemp())
337 self.config_file = str(self.tmpdir / "config.yaml")
338 config = BpsConfig({"bps_defined": {"submitPath": str(self.tmpdir)}})
340 with open(self.config_file, "w") as fh:
341 config.dump(fh)
343 def tearDown(self):
344 shutil.rmtree(self.tmpdir, ignore_errors=True)
346 @unittest.mock.patch("lsst.ctrl.bps.drivers.read_quantum_graph")
347 @unittest.mock.patch("lsst.ctrl.bps.drivers.acquire_quantum_graph")
348 @unittest.mock.patch("lsst.ctrl.bps.drivers._init_submission_driver")
349 def testSuccess(self, mock_init, mock_acquire, mock_read):
350 drivers.acquire_qgraph_driver(self.config_file)
351 mock_init.assert_called_once()
352 mock_acquire.assert_called_once()
353 mock_read.assert_called_once()
356class TestBatchAcquireDriver(unittest.TestCase):
357 """Test batch_acquire_driver function."""
359 def setUp(self):
360 self.tmpdir = Path(tempfile.mkdtemp())
361 self.config_file = str(self.tmpdir / "config.yaml")
362 config = BpsConfig({"bps_defined": {"submitPath": str(self.tmpdir)}, "computeSite": "site1"})
364 with open(self.config_file, "w") as fh:
365 config.dump(fh)
367 def tearDown(self):
368 shutil.rmtree(self.tmpdir, ignore_errors=True)
370 @unittest.mock.patch("lsst.ctrl.bps.drivers.acquire_quantum_graph")
371 def testSuccess(self, mock_acquire):
372 drivers.batch_acquire_driver(self.config_file)
373 mock_acquire.assert_called_once()
375 @unittest.mock.patch("lsst.ctrl.bps.drivers.acquire_quantum_graph")
376 def testSaveQgraph(self, mock_acquire):
377 config = BpsConfig(
378 {
379 "bps_defined": {"submitPath": str(self.tmpdir)},
380 "computeSite": "site1",
381 "saveQgraph": "/some/run.qgraph",
382 }
383 )
384 with open(self.config_file, "w") as fh:
385 config.dump(fh)
387 drivers.batch_acquire_driver(self.config_file)
389 mock_acquire.assert_called_once()
391 @unittest.mock.patch("lsst.ctrl.bps.drivers.ResourcePath")
392 @unittest.mock.patch("lsst.ctrl.bps.drivers.acquire_quantum_graph")
393 def testUseRunTempSpaceFound(self, mock_acquire, mock_resource_path):
394 config = BpsConfig(
395 {
396 "bps_defined": {"submitPath": str(self.tmpdir), "runQgraphFile": "/local/run.qgraph"},
397 "computeSite": "site1",
398 "qgraphFileTemplate": "template.qgraph",
399 "bpsUseRunTempSpace": True,
400 "fileDistributionEndpoint": "/run/temp/space",
401 }
402 )
403 with open(self.config_file, "w") as fh:
404 config.dump(fh)
406 drivers.batch_acquire_driver(self.config_file)
408 # The quantum graph should have been transferred to the staging area.
409 dest = mock_resource_path.return_value.join.return_value
410 dest.transfer_from.assert_called_once()
411 self.assertEqual(dest.transfer_from.call_args.kwargs["transfer"], "copy")
413 @unittest.mock.patch("lsst.ctrl.bps.drivers.acquire_quantum_graph")
414 def testUseRunTempSpaceMissingEndpoint(self, mock_acquire):
415 config = BpsConfig(
416 {
417 "bps_defined": {"submitPath": str(self.tmpdir), "runQgraphFile": "/local/run.qgraph"},
418 "computeSite": "site1",
419 "qgraphFileTemplate": "template.qgraph",
420 "bpsUseRunTempSpace": True,
421 }
422 )
423 with open(self.config_file, "w") as fh:
424 config.dump(fh)
426 with self.assertRaisesRegex(KeyError, "fileDistributionEndpoint"):
427 drivers.batch_acquire_driver(self.config_file)
429 @unittest.mock.patch("lsst.ctrl.bps.drivers.acquire_quantum_graph")
430 def testUseRunTempSpaceNotFound(self, mock_acquire):
431 # config from setUp has no bpsUseRunTempSpace key.
432 with self.assertLogs("lsst.ctrl.bps.drivers", level=logging.DEBUG) as cm:
433 drivers.batch_acquire_driver(self.config_file)
434 self.assertTrue(any("missing bpsUseRunTempSpace" in msg for msg in cm.output))
437class TestBatchPrepareDriver(unittest.TestCase):
438 """Test batch_prepare_driver function."""
440 def setUp(self):
441 self.tmpdir = tempfile.mkdtemp()
442 self.config_file = f"{self.tmpdir}/config.yaml"
443 config = BpsConfig({"bps_defined": {"submitPath": str(self.tmpdir)}})
445 with open(self.config_file, "w") as fh:
446 config.dump(fh)
448 def tearDown(self):
449 shutil.rmtree(self.tmpdir, ignore_errors=True)
451 @unittest.mock.patch("lsst.ctrl.bps.drivers.batch_payload_prepare")
452 def testSuccess(self, mock_prepare):
453 drivers.batch_prepare_driver(self.config_file, qgraph="test.qg")
454 mock_prepare.assert_called_once()
457class _TestWorkflow(BaseWmsWorkflow):
458 def __init__(self, name, config=None, run_id=None):
459 super().__init__(name, config)
460 self.run_id = run_id
462 def write(self, out_prefix):
463 pass # pragma: no cover
465 def add_to_parent_workflow(self, config):
466 pass # pragma: no cover
469class TestSubmitDriver(unittest.TestCase):
470 """Test submit_driver function."""
472 def setUp(self):
473 self.tmpdir = Path(tempfile.mkdtemp())
474 self.config_file = str(self.tmpdir / "config.yaml")
476 def tearDown(self):
477 shutil.rmtree(self.tmpdir, ignore_errors=True)
479 def _write_config(self, config_info):
480 config = BpsConfig(config_info)
481 with open(self.config_file, "w") as fh:
482 config.dump(fh)
484 @unittest.mock.patch("lsst.ctrl.bps.drivers._make_id_link")
485 @unittest.mock.patch("lsst.ctrl.bps.drivers.submit")
486 @unittest.mock.patch("lsst.ctrl.bps.drivers.batch_submit")
487 @unittest.mock.patch("lsst.ctrl.bps.drivers.prepare_driver")
488 @unittest.mock.patch("lsst.ctrl.bps.drivers._init_submission_driver")
489 @unittest.mock.patch("lsst.ctrl.bps.drivers.translate_command_line_values")
490 def testLocalSubmit(
491 self, mock_translate, mock_init, mock_prepare, mock_batch, mock_submit, mock_make_id_link
492 ):
493 """Neither remote build nor batch submission enabled."""
494 self._write_config({"wmsServiceClass": "wms_test_utils.WmsServiceSuccess", "uniqProcName": "run1"})
495 workflow = _TestWorkflow("run1", run_id="id1")
496 mock_prepare.return_value = (BpsConfig(self.config_file), workflow)
497 mock_submit.return_value = workflow
499 drivers.submit_driver(self.config_file)
501 mock_prepare.assert_called_once()
502 mock_submit.assert_called_once()
503 mock_batch.assert_not_called()
504 mock_init.assert_not_called()
505 mock_make_id_link.assert_called_once()
507 @unittest.mock.patch("lsst.ctrl.bps.drivers._make_id_link")
508 @unittest.mock.patch("lsst.ctrl.bps.drivers.submit")
509 @unittest.mock.patch("lsst.ctrl.bps.drivers.batch_submit")
510 @unittest.mock.patch("lsst.ctrl.bps.drivers.prepare_driver")
511 @unittest.mock.patch("lsst.ctrl.bps.drivers._init_submission_driver")
512 @unittest.mock.patch("lsst.ctrl.bps.drivers.translate_command_line_values")
513 def testBatchSubmission(
514 self, mock_translate, mock_init, mock_prepare, mock_batch, mock_submit, mock_make_id_link
515 ):
516 """Batch submission enabled routes through batch_submit."""
517 self._write_config(
518 {
519 "wmsServiceClass": "wms_test_utils.WmsServiceSuccess",
520 "uniqProcName": "run1",
521 "bpsBatchSubmission": True,
522 }
523 )
524 workflow = _TestWorkflow("run1", run_id="id1")
525 mock_batch.return_value = workflow
527 drivers.submit_driver(self.config_file)
529 mock_batch.assert_called_once()
530 mock_prepare.assert_not_called()
531 mock_submit.assert_not_called()
532 mock_init.assert_called_once()
533 mock_make_id_link.assert_called_once()
535 @unittest.mock.patch("lsst.ctrl.bps.drivers._make_id_link")
536 @unittest.mock.patch("lsst.ctrl.bps.drivers.submit")
537 @unittest.mock.patch("lsst.ctrl.bps.drivers.batch_submit")
538 @unittest.mock.patch("lsst.ctrl.bps.drivers.prepare_driver")
539 @unittest.mock.patch("lsst.ctrl.bps.drivers._init_submission_driver")
540 @unittest.mock.patch("lsst.ctrl.bps.drivers.translate_command_line_values")
541 def testRemoteBuildEnabled(
542 self, mock_translate, mock_init, mock_prepare, mock_batch, mock_submit, mock_make_id_link
543 ):
544 """Test when remoteBuild enabled."""
545 self._write_config(
546 {
547 "wmsServiceClass": "wms_test_utils.WmsServiceSuccess",
548 "uniqProcName": "run1",
549 "remoteBuild": {"enabled": True},
550 }
551 )
552 workflow = _TestWorkflow("run1", run_id="id1")
553 mock_submit.return_value = workflow
555 drivers.submit_driver(self.config_file)
557 mock_init.assert_called_once()
558 mock_prepare.assert_not_called()
559 mock_batch.assert_not_called()
560 mock_submit.assert_called_once()
561 # submit is called with a None workflow, so its return value is used.
562 self.assertIsNone(mock_submit.call_args[0][1])
563 mock_make_id_link.assert_called_once()
565 @unittest.mock.patch("lsst.ctrl.bps.drivers._make_id_link")
566 @unittest.mock.patch("lsst.ctrl.bps.drivers.submit")
567 @unittest.mock.patch("lsst.ctrl.bps.drivers.batch_submit")
568 @unittest.mock.patch("lsst.ctrl.bps.drivers.prepare_driver")
569 @unittest.mock.patch("lsst.ctrl.bps.drivers._init_submission_driver")
570 @unittest.mock.patch("lsst.ctrl.bps.drivers.translate_command_line_values")
571 def testRemoteBuildDisabled(
572 self, mock_translate, mock_init, mock_prepare, mock_batch, mock_submit, mock_make_id_link
573 ):
574 """Test remoteBuild present but disabled."""
575 self._write_config(
576 {
577 "wmsServiceClass": "wms_test_utils.WmsServiceSuccess",
578 "uniqProcName": "run1",
579 "remoteBuild": {"enabled": False},
580 }
581 )
582 workflow = _TestWorkflow("run1", run_id="id1")
583 mock_prepare.return_value = (BpsConfig(self.config_file), workflow)
584 mock_submit.return_value = workflow
586 drivers.submit_driver(self.config_file)
588 mock_init.assert_not_called()
589 mock_prepare.assert_called_once()
590 mock_submit.assert_called_once()
591 mock_batch.assert_not_called()
593 @unittest.mock.patch("builtins.print")
594 @unittest.mock.patch("lsst.ctrl.bps.drivers._make_id_link")
595 @unittest.mock.patch("lsst.ctrl.bps.drivers.submit")
596 @unittest.mock.patch("lsst.ctrl.bps.drivers.prepare_driver")
597 @unittest.mock.patch("lsst.ctrl.bps.drivers.translate_command_line_values")
598 def testPrintsRunInfo(self, mock_translate, mock_prepare, mock_submit, mock_make_id_link, mock_print):
599 """Test run info is printed on completion."""
600 self._write_config({"wmsServiceClass": "wms_test_utils.WmsServiceSuccess", "uniqProcName": "run1"})
601 workflow = _TestWorkflow("run1", run_id="id1")
602 mock_prepare.return_value = (BpsConfig(self.config_file), workflow)
603 mock_submit.return_value = workflow
605 drivers.submit_driver(self.config_file)
607 printed = " ".join(str(call.args[0]) for call in mock_print.call_args_list)
608 self.assertIn("Run Id:", printed)
609 self.assertIn("id1", printed)
610 self.assertIn("Run Name:", printed)
611 self.assertIn("run1", printed)
614if __name__ == "__main__":
615 unittest.main()