blob: ce9f21da39892b0debd88765e493c814e4963f24 [file] [log] [blame]
# Copyright 2018 The Chromium OS Authors. All rights reserved.
# Use of this source code is governed by a BSD-style license that can be
# found in the LICENSE file.
"""Shared libs by run_suite.py & run_suite_skylab.py."""
from __future__ import absolute_import
from __future__ import division
from __future__ import print_function
import collections
import json
import sys
import time
from autotest_lib.client.common_lib import enum
# Return code that will be sent back to callers.
#
# Note: Do not modify this enum; it is dependend upon by several clients.
RETURN_CODES = enum.Enum(
'OK',
'ERROR',
'WARNING',
'INFRA_FAILURE',
'SUITE_TIMEOUT',
'BOARD_NOT_AVAILABLE',
'INVALID_OPTIONS',
)
# TODO (xixuan): This is duplicated from suite_tracking.py in skylab.
# Make skylab caller also use this func.
TASK_COMPLETED = 'COMPLETED'
TASK_COMPLETED_SUCCESS = 'COMPLETED (SUCCESS)'
TASK_COMPLETED_FAILURE = 'COMPLETED (FAILURE)'
TASK_EXPIRED = 'EXPIRED'
TASK_CANCELED = 'CANCELED'
TASK_TIMEDOUT = 'TIMED_OUT'
TASK_RUNNING = 'RUNNING'
TASK_PENDING = 'PENDING'
TASK_BOT_DIED = 'BOT_DIED'
TASK_NO_RESOURCE = 'NO_RESOURCE'
TASK_KILLED = 'KILLED'
# Test status in _IGNORED_TEST_STATE won't be reported as test failure.
# Or test may be reported as failure as
# it's probably caused by the DUT is not well-provisioned.
# TODO: Stop ignoring TASK_NO_RESOURCE if we drop TEST_NA feature.
# Blocking issues:
# - Not all DUT labels are in skylab yet (crbug.com/871978)
IGNORED_TEST_STATE = [TASK_NO_RESOURCE]
class SuiteResult(collections.namedtuple('SuiteResult',
['return_code', 'output_dict'])):
"""Result of running a suite to return."""
def __new__(cls, return_code, output_dict=None):
if output_dict is None:
output_dict = dict()
else:
output_dict = output_dict.copy()
output_dict['return_code'] = return_code
return super(SuiteResult, cls).__new__(cls, return_code, output_dict)
@property
def string_code(self):
"""Return the enum string name of the numerical return_code."""
return RETURN_CODES.get_string(self.return_code)
def dump_json(obj):
"""Write obj JSON to stdout."""
output_json = json.dumps(obj, sort_keys=True)
# These sleeps and flushes are a hack around the fact that when running
# in the autotest proxy in --json_dump_postfix mode, run_suite.py co-mingles
# both stdout and stderr (which include both logging output and json output)
# to a single output stream. This can cause the json output to be corrupted
# by concurrent writes (which is particularly likely because this dump
# occurs at the end of run_suite's execution, along with other ending
# logging). Buffer time and forced stream flushes reduce the likelihood of
# concurrent writes.
sys.stderr.flush()
time.sleep(0.5)
sys.stdout.flush()
sys.stdout.write('\n#JSON_START#%s#JSON_END#\n' % output_json.strip())
sys.stdout.flush()
time.sleep(0.5)
# TODO (xixuan): This is duplicated from suite_tracking.py in skylab.
# Make skylab caller also use this func.
def get_final_skylab_task_state(task_result):
"""Get the final state of a swarming task.
@param task_result: A json dict of SwarmingRpcsTaskResult object.
"""
state = task_result['state']
if state == TASK_COMPLETED:
state = (TASK_COMPLETED_FAILURE if task_result['failure'] else
TASK_COMPLETED_SUCCESS)
return state
def get_final_skylab_suite_states():
return {
TASK_COMPLETED_FAILURE:
(
TASK_COMPLETED_FAILURE,
RETURN_CODES.ERROR,
),
# Task No_Resource means no available bots to accept the task.
# Deputy should check whether it's infra failure.
TASK_NO_RESOURCE:
(
TASK_NO_RESOURCE,
RETURN_CODES.INFRA_FAILURE,
),
# Task expired means a task is not triggered, could be caused by
# 1. No healthy DUTs/bots to run it.
# 2. Expiration seconds are too low.
# 3. Suite run is too slow to finish.
# Deputy should check whether it's infra failure.
TASK_EXPIRED:
(
TASK_EXPIRED,
RETURN_CODES.INFRA_FAILURE,
),
# Task canceled means a task is canceled intentionally. Deputy
# should check whether it's infra failure.
TASK_CANCELED:
(
TASK_CANCELED,
RETURN_CODES.INFRA_FAILURE,
),
TASK_TIMEDOUT:
(
TASK_TIMEDOUT,
RETURN_CODES.SUITE_TIMEOUT,
),
# Task pending means a task is still waiting for picking up, but
# the suite already hits deadline. So report it as suite TIMEOUT.
# It could also be an INFRA_FAILURE due to DUTs/bots shortage.
TASK_PENDING:
(
TASK_TIMEDOUT,
RETURN_CODES.SUITE_TIMEOUT,
),
}