@@ -116,5 +116,111 @@ def test_uncomment_on_ok_still_runs_in_hc_program(self):
116116 self .assertEqual (["uncomment" ], calls )
117117
118118
119+ def load_check_runner ():
120+ required_env = {
121+ "SLURMD_NODENAME" : "worker-1" ,
122+ "CHECKS_OUTPUTS_BASE_DIR" : "/opt/soperator-outputs" ,
123+ "CHECKS_CONTEXT" : "hc_program" ,
124+ "CHECKS_CONFIG" : "/opt/slurm_scripts/checks.json" ,
125+ }
126+ with mock .patch .dict (os .environ , required_env ):
127+ spec = importlib .util .spec_from_file_location (
128+ "check_runner_under_test" , CHECK_RUNNER_PATH
129+ )
130+ module = importlib .util .module_from_spec (spec )
131+ assert spec .loader is not None
132+ spec .loader .exec_module (module )
133+ return module
134+
135+
136+ check_runner = load_check_runner ()
137+
138+
139+ class NodeRealMemoryMetadataTest (unittest .TestCase ):
140+ def setUp (self ):
141+ check_runner .get_node_real_memory_bytes .cache_clear ()
142+
143+ def test_reads_real_memory_from_local_metadata_without_node_rpc (self ):
144+ with tempfile .TemporaryDirectory () as tmpdir :
145+ metadata_file = Path (tmpdir ) / "node_metadata.env"
146+ metadata_file .write_text (
147+ "IGNORED=value\n "
148+ "SOPERATOR_NODE_REAL_MEMORY_BYTES=999292928\n " ,
149+ encoding = "utf-8" ,
150+ )
151+
152+ with (
153+ mock .patch .object (
154+ check_runner , "SOPERATOR_NODE_METADATA_FILE" , str (metadata_file )
155+ ),
156+ mock .patch .object (check_runner , "get_node_info" ) as get_node_info ,
157+ ):
158+ result = check_runner .get_node_real_memory_bytes ()
159+
160+ self .assertEqual (999292928 , result )
161+ get_node_info .assert_not_called ()
162+
163+ def test_exports_local_real_memory_for_checks (self ):
164+ with tempfile .TemporaryDirectory () as tmpdir :
165+ metadata_file = Path (tmpdir ) / "node_metadata.env"
166+ metadata_file .write_text (
167+ "SOPERATOR_NODE_REAL_MEMORY_BYTES=999292928\n " ,
168+ encoding = "utf-8" ,
169+ )
170+ check = check_runner .Check (need_env = ["CHECKS_NODE_REAL_MEM_BYTES" ])
171+
172+ with (
173+ mock .patch .object (
174+ check_runner , "SOPERATOR_NODE_METADATA_FILE" , str (metadata_file )
175+ ),
176+ mock .patch .object (check_runner , "get_node_info" ) as get_node_info ,
177+ mock .patch .dict (os .environ , {}, clear = False ),
178+ ):
179+ check_runner .export_needed_env (check )
180+ exported_value = os .environ ["CHECKS_NODE_REAL_MEM_BYTES" ]
181+
182+ self .assertEqual ("999292928" , exported_value )
183+ get_node_info .assert_not_called ()
184+
185+ def test_falls_back_to_slurm_when_metadata_is_missing (self ):
186+ with tempfile .TemporaryDirectory () as tmpdir :
187+ missing_file = Path (tmpdir ) / "missing.env"
188+ node_info = check_runner .NodeInfo (real_memory_bytes = 2147483648 )
189+
190+ with (
191+ mock .patch .object (
192+ check_runner , "SOPERATOR_NODE_METADATA_FILE" , str (missing_file )
193+ ),
194+ mock .patch .object (
195+ check_runner , "get_node_info" , return_value = node_info
196+ ) as get_node_info ,
197+ ):
198+ result = check_runner .get_node_real_memory_bytes ()
199+
200+ self .assertEqual (2147483648 , result )
201+ get_node_info .assert_called_once_with ()
202+
203+ def test_falls_back_to_slurm_when_metadata_is_invalid (self ):
204+ with tempfile .TemporaryDirectory () as tmpdir :
205+ metadata_file = Path (tmpdir ) / "node_metadata.env"
206+ metadata_file .write_text (
207+ "SOPERATOR_NODE_REAL_MEMORY_BYTES=invalid\n " , encoding = "utf-8"
208+ )
209+ node_info = check_runner .NodeInfo (real_memory_bytes = 1073741824 )
210+
211+ with (
212+ mock .patch .object (
213+ check_runner , "SOPERATOR_NODE_METADATA_FILE" , str (metadata_file )
214+ ),
215+ mock .patch .object (
216+ check_runner , "get_node_info" , return_value = node_info
217+ ) as get_node_info ,
218+ ):
219+ result = check_runner .get_node_real_memory_bytes ()
220+
221+ self .assertEqual (1073741824 , result )
222+ get_node_info .assert_called_once_with ()
223+
224+
119225if __name__ == "__main__" :
120226 unittest .main (verbosity = 2 )
0 commit comments