File indexing completed on 2026-11-09 10:47:31
0001 """Submission refuses occupied Rucio namespaces without modifying them."""
0002 import importlib.util
0003 from pathlib import Path
0004 from types import SimpleNamespace
0005 import unittest
0006 from unittest.mock import MagicMock, patch
0007
0008 from rucio.common.exception import DataIdentifierNotFound
0009
0010 SCRIPTS = Path(__file__).resolve().parents[3] / 'scripts'
0011 spec = importlib.util.spec_from_file_location('submit_evgen_guard', SCRIPTS / 'submit-evgen-task.py')
0012 submit = importlib.util.module_from_spec(spec)
0013 spec.loader.exec_module(submit)
0014
0015
0016 class SubmissionNamespaceTest(unittest.TestCase):
0017 def test_jedi_suffixed_dataset_is_collision_without_template_container(self):
0018 client = MagicMock()
0019 client.get_did.side_effect = DataIdentifierNotFound()
0020 client.list_dids.return_value = iter(['group.EIC.test_log.123.123'])
0021 with patch('rucio.client.Client', return_value=client):
0022 with self.assertRaisesRegex(RuntimeError, 'test_log.123.123'):
0023 submit._require_fresh_bnl_namespace({'outDS': 'group.EIC.test'})
0024 self.assertEqual(client.list_dids.call_args.kwargs['filters'],
0025 {'name': 'group.EIC.test_log.*'})
0026 client.add_dataset.assert_not_called()
0027
0028 def test_orphan_log_file_is_collision(self):
0029 client = MagicMock()
0030 client.get_did.side_effect = DataIdentifierNotFound()
0031 client.list_dids.side_effect = [iter([]), iter(['group.EIC.test.000001.log.tgz'])]
0032 with patch('rucio.client.Client', return_value=client):
0033 with self.assertRaisesRegex(RuntimeError, 'log name already used'):
0034 submit._require_fresh_bnl_namespace({'outDS': 'group.EIC.test'})
0035
0036 def test_no_log_and_no_stageout_needs_no_bnl_client(self):
0037 with patch('rucio.client.Client') as client:
0038 submit._require_fresh_bnl_namespace({'outDS': 'group.EIC.test', 'noLog': True})
0039 client.assert_not_called()
0040
0041 def test_bnl_catalog_error_is_not_absence(self):
0042 client = MagicMock()
0043 client.get_did.side_effect = RuntimeError('catalog unavailable')
0044 with patch('rucio.client.Client', return_value=client):
0045 with self.assertRaisesRegex(RuntimeError, 'catalog unavailable'):
0046 submit._require_fresh_bnl_namespace({'outDS': 'group.EIC.test'})
0047
0048 def precreate(self, client):
0049 args = SimpleNamespace(canary_stamp=None, trial=False, proxy='proxy')
0050 task = {'outDS': 'group.EIC.test', 'outputs': [
0051 {'dataset': '/fresh', 'level': 'FULL'}, {'dataset': '/second', 'level': 'RECO'}]}
0052 evgen = SimpleNamespace(RUCIO_SCOPE='epic', rucio_client=lambda proxy: client)
0053 with patch.object(submit, '_load_sibling', return_value=evgen), \
0054 patch.object(submit, '_require_fresh_bnl_namespace'):
0055 return submit._precreate_outputs(task, args)
0056
0057 def test_second_jlab_collision_does_not_create_first(self):
0058 client = MagicMock()
0059 client.get_did.side_effect = [DataIdentifierNotFound(), {'type': 'DATASET'}]
0060 with self.assertRaisesRegex(RuntimeError, 'epic:/second'):
0061 self.precreate(client)
0062 client.add_dataset.assert_not_called()
0063 client.set_metadata.assert_not_called()
0064 client.add_replication_rule.assert_not_called()
0065
0066 def test_jlab_error_does_not_create_anything(self):
0067 client = MagicMock()
0068 client.get_did.side_effect = RuntimeError('catalog unavailable')
0069 with self.assertRaisesRegex(RuntimeError, 'catalog unavailable'):
0070 self.precreate(client)
0071 client.add_dataset.assert_not_called()
0072
0073 def test_fresh_outputs_created_only_after_all_lookups(self):
0074 client = MagicMock(account='eicprod')
0075 client.get_did.side_effect = DataIdentifierNotFound()
0076 result = self.precreate(client)
0077 calls = [call[0] for call in client.mock_calls]
0078 self.assertEqual(calls[:4], ['get_did', 'get_did', 'add_dataset', 'add_dataset'])
0079 self.assertEqual([row['dataset'] for row in result], ['epic:/fresh', 'epic:/second'])
0080 self.assertTrue(all(row['created'] for row in result))
0081
0082 def test_stageout_names_follow_kernel_naming(self):
0083 names = submit._load_sibling('evgen_dataset_names.py').panda_dataset_names
0084 self.assertEqual(names({'outDS': 'group.EIC.test', 'stageOutFiles': ['report.json']}),
0085 ['group.EIC.test_log/', 'group.EIC.test_report/'])