Coverage for tests / test_htcondor_service.py: 38%
88 statements
« prev ^ index » next coverage.py v7.13.2, created at 2026-02-03 01:39 -0800
« prev ^ index » next coverage.py v7.13.2, created at 2026-02-03 01:39 -0800
1# This file is part of ctrl_bps_htcondor.
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/>.
28"""Unit tests for the HTCondor WMS service class and related functions."""
30import logging
31import unittest
33import htcondor
35from lsst.ctrl.bps import (
36 BpsConfig,
37 WmsStates,
38)
39from lsst.ctrl.bps.htcondor import htcondor_service
40from lsst.ctrl.bps.htcondor.htcondor_config import HTC_DEFAULTS_URI
42logger = logging.getLogger("lsst.ctrl.bps.htcondor")
44LOCATE_SUCCESS = """[
45 CondorPlatform = "$CondorPlatform: X86_64-CentOS_7.9 $";
46 MyType = "Scheduler";
47 Machine = "testmachine";
48 Name = "testmachine";
49 CondorVersion = "$CondorVersion: 23.0.3 2024-04-04 $";
50 MyAddress = "<127.0.0.1:9618?addrs=127.0.0.1-9618+snip>"
51 ]
52"""
54PING_SUCCESS = """[
55 AuthCommand = 60011;
56 AuthMethods = "FS_REMOTE";
57 Command = 60040;
58 AuthorizationSucceeded = true;
59 ValidCommands = "60002,60003,60011,60014,60045,60046,60047,60048,60049,60050,60052,523";
60 TriedAuthentication = true;
61 RemoteVersion = "$CondorVersion: 10.9.0 2023-09-28 BuildID: 678228 PackageID: 10.9.0-1 $";
62 MyRemoteUserName = "testuser@testmachine";
63 Authentication = "YES";
64 ]
65"""
68class HTCondorServiceTestCase(unittest.TestCase):
69 """Test selected methods of the HTCondor WMS service class."""
71 def setUp(self):
72 config = BpsConfig({}, wms_service_class_fqn="lsst.ctrl.bps.htcondor.HTCondorService")
73 self.service = htcondor_service.HTCondorService(config)
75 def tearDown(self):
76 pass
78 def testDefaults(self):
79 self.assertEqual(self.service.defaults["memoryLimit"], 491520)
81 def testDefaultsPath(self):
82 self.assertEqual(self.service.defaults_uri, HTC_DEFAULTS_URI)
83 self.assertFalse(self.service.defaults_uri.isdir())
85 @unittest.mock.patch.object(htcondor.SecMan, "ping", return_value=PING_SUCCESS)
86 @unittest.mock.patch.object(htcondor.Collector, "locate", return_value=LOCATE_SUCCESS)
87 def testPingSuccess(self, mock_locate, mock_ping):
88 status, message = self.service.ping(None)
89 self.assertEqual(status, 0)
90 self.assertEqual(message, "")
92 def testPingFailure(self):
93 with unittest.mock.patch("htcondor.Collector.locate") as locate_mock:
94 locate_mock.side_effect = htcondor.HTCondorLocateError()
95 status, message = self.service.ping(None)
96 self.assertEqual(status, 1)
97 self.assertEqual(message, "Could not locate Schedd service.")
99 @unittest.mock.patch.object(htcondor.Collector, "locate", return_value=LOCATE_SUCCESS)
100 def testPingPermission(self, mock_locate):
101 with unittest.mock.patch("htcondor.SecMan.ping") as ping_mock:
102 ping_mock.side_effect = htcondor.HTCondorIOError()
103 status, message = self.service.ping(None)
104 self.assertEqual(status, 1)
105 self.assertEqual(message, "Permission problem with Schedd service.")
107 @unittest.mock.patch("lsst.ctrl.bps.htcondor.htcondor_service._get_status_from_id")
108 @unittest.mock.patch("lsst.ctrl.bps.htcondor.htcondor_service._locate_schedds")
109 @unittest.mock.patch("lsst.ctrl.bps.htcondor.htcondor_service._wms_id_type")
110 def testGetStatusLocal(self, mock_type, mock_locate, mock_status):
111 mock_type.return_value = htcondor_service.WmsIdType.LOCAL
112 mock_locate.return_value = {}
113 mock_status.return_value = (WmsStates.RUNNING, "")
115 fake_id = "100"
116 state, message = self.service.get_status(fake_id)
118 mock_type.assert_called_once_with(fake_id)
119 mock_locate.assert_called_once_with(locate_all=False)
120 mock_status.assert_called_once_with(fake_id, 1, schedds={})
122 self.assertEqual(state, WmsStates.RUNNING)
123 self.assertEqual(message, "")
125 @unittest.mock.patch("lsst.ctrl.bps.htcondor.htcondor_service._get_status_from_id")
126 @unittest.mock.patch("lsst.ctrl.bps.htcondor.htcondor_service._locate_schedds")
127 @unittest.mock.patch("lsst.ctrl.bps.htcondor.htcondor_service._wms_id_type")
128 def testGetStatusGlobal(self, mock_type, mock_locate, mock_status):
129 mock_type.return_value = htcondor_service.WmsIdType.GLOBAL
130 mock_locate.return_value = {}
131 fake_message = ""
132 mock_status.return_value = (WmsStates.RUNNING, fake_message)
134 fake_id = "100"
135 state, message = self.service.get_status(fake_id, 2)
137 mock_type.assert_called_once_with(fake_id)
138 mock_locate.assert_called_once_with(locate_all=True)
139 mock_status.assert_called_once_with(fake_id, 2, schedds={})
141 self.assertEqual(state, WmsStates.RUNNING)
142 self.assertEqual(message, fake_message)
144 @unittest.mock.patch("lsst.ctrl.bps.htcondor.htcondor_service._get_status_from_path")
145 @unittest.mock.patch("lsst.ctrl.bps.htcondor.htcondor_service._wms_id_type")
146 def testGetStatusPath(self, mock_type, mock_status):
147 fake_message = "fake message"
148 mock_type.return_value = htcondor_service.WmsIdType.PATH
149 mock_status.return_value = (WmsStates.FAILED, fake_message)
151 fake_id = "/fake/path"
152 state, message = self.service.get_status(fake_id)
154 mock_type.assert_called_once_with(fake_id)
155 mock_status.assert_called_once_with(fake_id)
157 self.assertEqual(state, WmsStates.FAILED)
158 self.assertEqual(message, fake_message)
160 @unittest.mock.patch("lsst.ctrl.bps.htcondor.htcondor_service._wms_id_type")
161 def testGetStatusUnknownType(self, mock_type):
162 mock_type.return_value = htcondor_service.WmsIdType.UNKNOWN
164 fake_id = "100.0"
165 state, message = self.service.get_status(fake_id)
167 mock_type.assert_called_once_with(fake_id)
169 self.assertEqual(state, WmsStates.UNKNOWN)
170 self.assertEqual(message, "Invalid job id")