Coverage for tests/test_drivers.py: 100%

323 statements  

« prev     ^ index     » next       coverage.py v7.15.4, created at 2026-09-09 02:14 -0700

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.""" 

28 

29import logging 

30import os 

31import shutil 

32import tempfile 

33import unittest 

34from pathlib import Path 

35 

36import yaml 

37 

38from lsst.ctrl.bps import BaseWmsWorkflow, BpsConfig, WmsRunReport, WmsStates, drivers 

39from lsst.ctrl.bps.bps_reports import compile_code_summary, compile_job_summary 

40 

41TESTDIR = os.path.abspath(os.path.dirname(__file__)) 

42 

43 

44class TestInitSubmissionDriver(unittest.TestCase): 

45 """Test submission.""" 

46 

47 def setUp(self): 

48 self.cwd = os.getcwd() 

49 self.tmpdir = tempfile.mkdtemp(dir=TESTDIR) 

50 

51 def tearDown(self): 

52 shutil.rmtree(self.tmpdir, ignore_errors=True) 

53 

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) 

67 

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) 

75 

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) 

83 

84 

85class TestPingDriver(unittest.TestCase): 

86 """Test ping.""" 

87 

88 def testWmsServiceSuccess(self): 

89 retval = drivers.ping_driver("wms_test_utils.WmsServiceSuccess") 

90 self.assertEqual(retval, 0) 

91 

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") 

97 

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) 

104 

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") 

114 

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") 

120 

121 

122class TestStatusDriver(unittest.TestCase): 

123 """Test status_driver function.""" 

124 

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") 

132 

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.") 

140 

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) 

148 

149 

150class TestReportDriver(unittest.TestCase): 

151 """Test report_driver function.""" 

152 

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 ) 

166 

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 ) 

179 

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 = ([], []) 

184 

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 ) 

192 

193 # Verify retrieve_report was called with the default hist setting. 

194 _, kwargs = mock_retrieve.call_args 

195 self.assertAlmostEqual(kwargs["hist"], 2.0) 

196 

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 = ([], []) 

201 

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 ) 

209 

210 # Verify retrieve_report was called with a custom hist setting. 

211 _, kwargs = mock_retrieve.call_args 

212 self.assertAlmostEqual(kwargs["hist"], 4.0) 

213 

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 = ([], []) 

218 

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 ) 

227 

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"]) 

232 

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 = ([], []) 

237 

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 ) 

246 

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"]) 

252 

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 = ([], []) 

257 

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 ) 

265 

266 # Verify postprocessors contains compile_job_summary 

267 _, kwargs = mock_retrieve.call_args 

268 self.assertIsNone(kwargs["postprocessors"]) 

269 

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, []) 

275 

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 ) 

283 

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) 

288 

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) 

294 

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 ) 

302 

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) 

307 

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 = ([], []) 

313 

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 ) 

321 

322 # Verify display_report() was NOT called. 

323 mock_display.assert_not_called() 

324 

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) 

330 

331 

332class TestAcquireQgraphDriver(unittest.TestCase): 

333 """Test acquire_qgraph_driver function.""" 

334 

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)}}) 

339 

340 with open(self.config_file, "w") as fh: 

341 config.dump(fh) 

342 

343 def tearDown(self): 

344 shutil.rmtree(self.tmpdir, ignore_errors=True) 

345 

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() 

354 

355 

356class TestBatchAcquireDriver(unittest.TestCase): 

357 """Test batch_acquire_driver function.""" 

358 

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"}) 

363 

364 with open(self.config_file, "w") as fh: 

365 config.dump(fh) 

366 

367 def tearDown(self): 

368 shutil.rmtree(self.tmpdir, ignore_errors=True) 

369 

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() 

374 

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) 

386 

387 drivers.batch_acquire_driver(self.config_file) 

388 

389 mock_acquire.assert_called_once() 

390 

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) 

405 

406 drivers.batch_acquire_driver(self.config_file) 

407 

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") 

412 

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) 

425 

426 with self.assertRaisesRegex(KeyError, "fileDistributionEndpoint"): 

427 drivers.batch_acquire_driver(self.config_file) 

428 

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)) 

435 

436 

437class TestBatchPrepareDriver(unittest.TestCase): 

438 """Test batch_prepare_driver function.""" 

439 

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)}}) 

444 

445 with open(self.config_file, "w") as fh: 

446 config.dump(fh) 

447 

448 def tearDown(self): 

449 shutil.rmtree(self.tmpdir, ignore_errors=True) 

450 

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() 

455 

456 

457class _TestWorkflow(BaseWmsWorkflow): 

458 def __init__(self, name, config=None, run_id=None): 

459 super().__init__(name, config) 

460 self.run_id = run_id 

461 

462 def write(self, out_prefix): 

463 pass # pragma: no cover 

464 

465 def add_to_parent_workflow(self, config): 

466 pass # pragma: no cover 

467 

468 

469class TestSubmitDriver(unittest.TestCase): 

470 """Test submit_driver function.""" 

471 

472 def setUp(self): 

473 self.tmpdir = Path(tempfile.mkdtemp()) 

474 self.config_file = str(self.tmpdir / "config.yaml") 

475 

476 def tearDown(self): 

477 shutil.rmtree(self.tmpdir, ignore_errors=True) 

478 

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) 

483 

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 

498 

499 drivers.submit_driver(self.config_file) 

500 

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() 

506 

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 

526 

527 drivers.submit_driver(self.config_file) 

528 

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() 

534 

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 

554 

555 drivers.submit_driver(self.config_file) 

556 

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() 

564 

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 

585 

586 drivers.submit_driver(self.config_file) 

587 

588 mock_init.assert_not_called() 

589 mock_prepare.assert_called_once() 

590 mock_submit.assert_called_once() 

591 mock_batch.assert_not_called() 

592 

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 

604 

605 drivers.submit_driver(self.config_file) 

606 

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) 

612 

613 

614if __name__ == "__main__": 

615 unittest.main()