@@ -131,23 +131,34 @@ def _get_job_failure_metadata(self):
131131
132132 @classmethod
133133 def _get_login_case (cls , tests ):
134- tests_map = {test ['name' ]: test for test in tests }
135- login = (
136- tests_map .get ('auto-login-action' ) or tests_map .get ('login-action' )
137- )
138- if not login :
134+ # When boot has failure_retry set, there may be multiple login attempts
135+ # We should return 'pass' if ANY attempt passed, 'fail' only if ALL failed
136+ login_tests = [
137+ test for test in tests
138+ if test ['name' ] in ('auto-login-action' , 'login-action' )
139+ ]
140+ if not login_tests :
139141 return None
140- result = login and login ['result' ] == 'pass'
141- return 'pass' if result else 'fail'
142+
143+ # Check if any login attempt passed
144+ any_passed = any (test ['result' ] == 'pass' for test in login_tests )
145+ return 'pass' if any_passed else 'fail'
142146
143147 @classmethod
144148 def _get_kernelmsg_case (cls , tests ):
145- tests_map = {test ['name' ]: test for test in tests }
146- kernelmsg = tests_map .get ('kernel-messages' )
147- if not kernelmsg :
149+ # When boot has failure_retry set, there may be multiple kernel-messages checks
150+ # Unlike login, we return 'fail' if ANY attempt failed, because kernel-messages
151+ # failure means we caught kernel panic, oops, or other critical errors
152+ kernelmsg_tests = [
153+ test for test in tests
154+ if test ['name' ] == 'kernel-messages'
155+ ]
156+ if not kernelmsg_tests :
148157 return None
149- result = kernelmsg and kernelmsg ['result' ] == 'pass'
150- return 'pass' if result else 'fail'
158+
159+ # Check if any kernel-messages check failed (caught panic/oops/etc)
160+ any_failed = any (test ['result' ] == 'fail' for test in kernelmsg_tests )
161+ return 'fail' if any_failed else 'pass'
151162
152163 def _get_os_release_measurement (self ):
153164 for suite_name , suite_results in self ._data ['results' ].items ():
0 commit comments