File indexing completed on 2026-11-09 10:47:30
0001 from unittest.mock import patch
0002
0003 from django.test import SimpleTestCase
0004
0005 from monitor_app.error_corrections import reading
0006 from monitor_app.panda.sql import extract_errors
0007
0008
0009 class ErrorReadingTests(SimpleTestCase):
0010 def setUp(self):
0011 self.rules = patch('monitor_app.error_corrections._rules', return_value=[])
0012 self.rules.start()
0013 self.addCleanup(self.rules.stop)
0014
0015 def test_known_patterns_use_only_the_evidence_in_the_record(self):
0016 cases = [
0017 ('ddm', 200, "bytes mismatch for 'x.log.tgz': 100!=200", 'Log file catalog registration'),
0018 ('pilot', 1213, 'Reached maxtime', 'runtime limit'),
0019 ('pilot', 1212, 'Memory cgroup out of memory: Killed process 42', 'memory limit'),
0020 ('pilot', 1326, 'No replica found (allow_lan=True, allow_wan=False)', 'WAN'),
0021 ('dispatcher', 100, 'lost heartbeat : time', 'unknown'),
0022 ('taskbuffer', 300, 'The worker was cancelled while the job was running : Condor HoldReason: Job disappeared from remote schedd', 'underlying batch cause not reported'),
0023 ('taskbuffer', 300, 'The worker was finished while the job was running : None', 'not recorded'),
0024 ('executor', 139, 'payload exited 139', 'segfault'),
0025 ('executor', 1, 'payload exited 1', 'does not identify the cause'),
0026 ]
0027 for component, code, diag, expected in cases:
0028 with self.subTest(component=component, code=code):
0029 self.assertIn(expected, reading(component, code, diag)['label'])
0030 self.assertIsNone(reading('pilot', 9999, 'unknown error'))
0031
0032 def test_incidental_warning_does_not_override_payload_signal(self):
0033 result = reading('pilot', 1305, 'Failed to execute payload: group: unknown groupid 123',
0034 {'139': {'n': 5, 'rep': 1}})
0035 self.assertEqual(result['label'], 'payload segfault')
0036 self.assertEqual(result['modes'][0]['count'], 5)
0037 self.assertNotIn('group', result['label'])
0038
0039 def test_job_error_root_uses_shared_reading(self):
0040 errors = extract_errors({'piloterrorcode': 1305,
0041 'piloterrordiag': 'Failed to execute payload', 'transexitcode': '139'})
0042 self.assertEqual(errors[0]['correction']['label'], 'payload segfault')
0043 self.assertEqual(errors[1]['correction']['label'], 'payload segfault')
0044
0045
0046 class DiagnosticFocusTests(SimpleTestCase):
0047 def test_pattern_drilldown_preserves_time_task_execution_queue_and_code(self):
0048 from datetime import datetime, timedelta, timezone
0049 from unittest.mock import MagicMock
0050 from monitor_app.panda.queries import diagnose_jobs
0051 end = datetime(2026, 10, 24, tzinfo=timezone.utc)
0052 cursor = MagicMock()
0053 cursor.fetchall.return_value = []
0054 conn = MagicMock()
0055 conn.cursor.return_value.__enter__.return_value = cursor
0056 with patch('monitor_app.panda.queries.connections', {'panda': conn}), \
0057 patch('monitor_app.panda.queries._bulk_destinationse', return_value={}):
0058 result = diagnose_jobs(site='BNL_OSG_PanDA_1', taskid='41051',
0059 execsite='SU-ITS', ended_after=end-timedelta(hours=1), ended_before=end,
0060 status='failed', error_component='pilot', error_code='1213')
0061 self.assertNotIn('error', result)
0062 sql, params = cursor.execute.call_args.args
0063 for clause in ('"endtime" > %s', '"endtime" <= %s',
0064 '"destinationsite" = %s', '"piloterrorcode" = %s'):
0065 self.assertIn(clause, sql)
0066 self.assertIn('SU-ITS', params)
0067 self.assertIn('41051', params)
0068 self.assertIn(1213, params)
0069 self.assertNotIn('"modificationtime" >= %s', sql)