blob: 3799a1c2f48f5cef97c2a50e9e71f957f8f3a631 [file] [log] [blame]
# -*- coding: utf-8 -*-
# Copyright 2017 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.
"""Module containing unit tests for failure_message_lib."""
from __future__ import print_function
from chromite.lib import constants
from chromite.lib import cros_test_lib
from chromite.lib import failure_message_lib
DEFAULT_BUILD_SCRIPT_FAILURE_EXTRA_INFO = (
'{\"shortname\": \"security_test_image\"}')
DEFAULT_PACKAGE_BUILD_FAILURE_EXTRA_INFO = (
'{\"shortname\": \"./build_image\", \"failed_packages\":'
'[\"chromeos-base/chromeos-chrome\", \"chromeos-base/chromeos-init\"]}')
class StageFailureHelper(object):
"""Helper method to create StageFailure instances for test."""
@classmethod
def CreateStageFailure(
cls, failure_id=1, build_stage_id=1, outer_failure_id=None,
exception_type='StepFailure', exception_message='exception message',
exception_category=constants.EXCEPTION_CATEGORY_UNKNOWN,
extra_info=None, timestamp=None, stage_name='stage_1', board='board_1',
stage_status=constants.BUILDER_STATUS_PASSED, build_id=1,
master_build_id=None, builder_name='builder_name_1',
build_number='build_number_1',
build_config='config_1', build_status=constants.BUILDER_STATUS_PASSED,
important=True, buildbucket_id='bb_id'):
return failure_message_lib.StageFailure(
failure_id, build_stage_id, outer_failure_id, exception_type,
exception_message, exception_category, extra_info, timestamp,
stage_name, board, stage_status, build_id, master_build_id,
builder_name, build_number, build_config, build_status,
important, buildbucket_id)
@classmethod
def GetStageFailure(
cls,
failure_id=1,
build_stage_id=1,
outer_failure_id=None,
exception_type='StepFailure',
exception_message='exception msg',
exception_category=constants.EXCEPTION_CATEGORY_UNKNOWN,
extra_info=None,
stage_name='Paygen',
build_config=None):
return cls.CreateStageFailure(
failure_id, build_stage_id, outer_failure_id, exception_type,
exception_message, exception_category, extra_info, None, stage_name,
None, None, None, None, None, None, build_config, None, None,
None)
class StageFailureTests(cros_test_lib.TestCase):
"""Tests for StageFailure."""
def testGetStageFailureFromMessage(self):
"""Test GetStageFailureFromMessage."""
failure_message = FailureMessageHelper.GetStageFailureMessage()
stage_failure = failure_message_lib.StageFailure.GetStageFailureFromMessage(
failure_message)
self.assertEqual(stage_failure.id, 1)
self.assertEqual(stage_failure.exception_type, 'StepFailure')
self.assertEqual(stage_failure.exception_category,
constants.EXCEPTION_CATEGORY_UNKNOWN)
class FailureMessageHelper(object):
"""Helper class to help create stage failure message instances for test."""
@classmethod
def GetStageFailureMessage(
cls,
failure_id=1,
build_stage_id=1,
outer_failure_id=None,
exception_type='StepFailure',
exception_message='exception msg',
exception_category=constants.EXCEPTION_CATEGORY_UNKNOWN,
extra_info=None,
stage_name='Paygen'):
stage_failure = StageFailureHelper.GetStageFailure(
failure_id, build_stage_id, outer_failure_id, exception_type,
exception_message, exception_category, extra_info, stage_name)
return failure_message_lib.StageFailureMessage(stage_failure)
@classmethod
def GetBuildScriptFailureMessage(
cls,
failure_id=2,
build_stage_id=0,
outer_failure_id=None,
exception_type='BuildScriptFailure',
exception_message='exception msg',
exception_category=constants.EXCEPTION_CATEGORY_BUILD,
extra_info=DEFAULT_BUILD_SCRIPT_FAILURE_EXTRA_INFO,
stage_name='InitSDK',):
stage_failure = StageFailureHelper.GetStageFailure(
failure_id, build_stage_id, outer_failure_id, exception_type,
exception_message, exception_category, extra_info, stage_name)
return failure_message_lib.BuildScriptFailureMessage(stage_failure)
@classmethod
def GetPackageBuildFailureMessage(
cls,
failure_id=3,
build_stage_id=0,
outer_failure_id=None,
exception_type='PackageBuildFailure',
exception_message='exception msg',
exception_category=constants.EXCEPTION_CATEGORY_BUILD,
extra_info=DEFAULT_PACKAGE_BUILD_FAILURE_EXTRA_INFO,
stage_name='BuildImage',):
stage_failure = StageFailureHelper.GetStageFailure(
failure_id, build_stage_id, outer_failure_id, exception_type,
exception_message, exception_category, extra_info, stage_name)
return failure_message_lib.PackageBuildFailureMessage(stage_failure)
@classmethod
def GetCompoundFailureMessage(
cls,
failure_id=4,
build_stage_id=0,
outer_failure_id=None,
exception_type='BackgroundFailure',
exception_message='exception msg',
exception_category=constants.EXCEPTION_CATEGORY_UNKNOWN,
extra_info=None,
stage_name='Archive',
stage_prefix_name='Archive'):
stage_failure = StageFailureHelper.GetStageFailure(
failure_id, build_stage_id, outer_failure_id, exception_type,
exception_message, exception_category, extra_info, stage_name)
return failure_message_lib.CompoundFailureMessage(
stage_failure, extra_info=extra_info,
stage_prefix_name=stage_prefix_name)
@classmethod
def GetTestFailureMessage(
cls,
failure_id=5,
build_stage_id=0,
outer_failure_id=None,
exception_type='TestFailure',
exception_message='** HWTest failed (code 1) **',
exception_category=constants.EXCEPTION_CATEGORY_TEST,
extra_info=None,
stage_name='HWTest'):
stage_failure = StageFailureHelper.GetStageFailure(
failure_id, build_stage_id, outer_failure_id, exception_type,
exception_message, exception_category, extra_info, stage_name)
return failure_message_lib.StageFailureMessage(stage_failure)
@classmethod
def GetBuildFailureMessageWithMixedMsgs(cls):
f_1 = cls.GetStageFailureMessage(failure_id=1, outer_failure_id=4)
f_2 = cls.GetBuildScriptFailureMessage(failure_id=2, outer_failure_id=4)
f_3 = cls.GetPackageBuildFailureMessage(failure_id=3, outer_failure_id=4)
f_4 = cls.GetStageFailureMessage(failure_id=4)
f_5 = cls.GetStageFailureMessage(failure_id=5)
f_6 = cls.GetBuildScriptFailureMessage(failure_id=6)
f_7 = cls.GetPackageBuildFailureMessage(failure_id=7)
return (failure_message_lib.FailureMessageManager.ReconstructMessages(
[f_1, f_2, f_3, f_4, f_5, f_6, f_7]))
class StageFailureMessageTests(cros_test_lib.TestCase):
"""Tests for StageFailureMessage."""
def testDecodeExtraInfoWithNoneExtraInfo(self):
"""Test _DecodeExtraInfo with None extra_info."""
failure_message = FailureMessageHelper.GetStageFailureMessage()
self.assertEqual(failure_message.extra_info, {})
def testDecodeExtraInfoWithNoneValidExtraInfo(self):
"""Test _DecodeExtraInfo with valid extra_info."""
failure_message = FailureMessageHelper.GetStageFailureMessage(
extra_info=DEFAULT_BUILD_SCRIPT_FAILURE_EXTRA_INFO)
self.assertEqual(failure_message.extra_info['shortname'],
'security_test_image')
def testDecodeExtraInfoWithNoneInvalidExtraInfo(self):
"""Test _DecodeExtraInfo with invalid extra_info."""
failure_message = FailureMessageHelper.GetStageFailureMessage(
extra_info='{\"shortname\": \"security_test_image\"')
self.assertEqual(failure_message.extra_info, {})
def testExtractStagePrefixName(self):
"""Test _ExtractStagePrefixName."""
prefix_name_map = {
'HWTest [bvt-arc]': 'HWTest',
'HWTest': 'HWTest',
'ImageTest': 'ImageTest',
'ImageTest [amd64-generic]': 'ImageTest',
'VMTest (attempt 1)': 'VMTest',
'VMTest [amd64-generic] (attempt 1)': 'VMTest'
}
for k, v in prefix_name_map.items():
failure_message = FailureMessageHelper.GetStageFailureMessage(
stage_name=k)
self.assertEqual(failure_message.stage_prefix_name, v)
class BuildScriptFailureMessageTests(cros_test_lib.TestCase):
"""Tests for BuildScriptFailureMessage."""
def testGetShortname(self):
"""Test GetShortname."""
failure_message = FailureMessageHelper.GetBuildScriptFailureMessage()
self.assertEqual(failure_message.GetShortname(), 'security_test_image')
class PackageBuildFailureMessageTests(cros_test_lib.TestCase):
"""Tests for PackageBuildFailureMessage."""
def testGetShortname(self):
"""Test GetShortname."""
failure_message = FailureMessageHelper.GetPackageBuildFailureMessage()
self.assertEqual(failure_message.GetShortname(),
'./build_image')
def testGetFailedPackages(self):
"""Test GetFailedPackages."""
failure_message = FailureMessageHelper.GetPackageBuildFailureMessage()
self.assertCountEqual(
['chromeos-base/chromeos-chrome', 'chromeos-base/chromeos-init'],
failure_message.GetFailedPackages())
class CompoundFailureMessageTests(cros_test_lib.TestCase):
"""Tests for CompoundFailureMessage."""
def testGetCompoundFailureMessage(self):
"""Test GetCompoundFailureMessage."""
failure_message = FailureMessageHelper.GetPackageBuildFailureMessage()
new_failure_message = (
failure_message_lib.CompoundFailureMessage.GetFailureMessage(
failure_message))
self.assertEqual(new_failure_message.inner_failures, [])
def testHasEmptyList(self):
"""Test HasEmptyList."""
failure_message = FailureMessageHelper.GetCompoundFailureMessage()
self.assertTrue(failure_message.HasEmptyList())
failure_message.inner_failures.append(
FailureMessageHelper.GetPackageBuildFailureMessage())
self.assertFalse(failure_message.HasEmptyList())
def testHasExceptionCategories(self):
"""Test HasExceptionCategories."""
failure_message = FailureMessageHelper.GetCompoundFailureMessage()
self.assertFalse(failure_message.HasExceptionCategories(
{constants.EXCEPTION_CATEGORY_BUILD}))
failure_message.inner_failures.append(
FailureMessageHelper.GetPackageBuildFailureMessage())
self.assertTrue(failure_message.HasExceptionCategories(
{constants.EXCEPTION_CATEGORY_BUILD}))
self.assertFalse(failure_message.HasExceptionCategories(
{constants.EXCEPTION_CATEGORY_LAB}))
self.assertTrue(failure_message.HasExceptionCategories(
{constants.EXCEPTION_CATEGORY_BUILD, constants.EXCEPTION_CATEGORY_LAB}))
def testMatchesExceptionCategories(self):
"""Test MatchesExceptionCategories."""
failure_message = FailureMessageHelper.GetCompoundFailureMessage()
self.assertFalse(failure_message.MatchesExceptionCategories(
{constants.EXCEPTION_CATEGORY_BUILD}))
failure_message.inner_failures.append(
FailureMessageHelper.GetPackageBuildFailureMessage())
self.assertTrue(failure_message.MatchesExceptionCategories(
{constants.EXCEPTION_CATEGORY_BUILD}))
self.assertFalse(failure_message.MatchesExceptionCategories(
{constants.EXCEPTION_CATEGORY_LAB}))
self.assertTrue(failure_message.MatchesExceptionCategories(
{constants.EXCEPTION_CATEGORY_BUILD, constants.EXCEPTION_CATEGORY_LAB}))
failure_message.inner_failures.append(
FailureMessageHelper.GetStageFailureMessage())
self.assertFalse(failure_message.MatchesExceptionCategories(
{constants.EXCEPTION_CATEGORY_BUILD}))
self.assertFalse(failure_message.MatchesExceptionCategories(
{constants.EXCEPTION_CATEGORY_LAB}))
class FailureMessageManagerTests(cros_test_lib.TestCase):
"""Tests for FailureMessageManager."""
def testCreateMessageForBuildScriptFailureMessage(self):
"""Test CreateMessage for BuildScriptFailureMessage."""
stage_failure = StageFailureHelper.GetStageFailure(
1, 1, 0, 'BuildScriptFailure', 'exception msg', 'build',
'{\"shortname\": \"./security_test_image\"', 'InitSDK')
failure_message = failure_message_lib.FailureMessageManager.CreateMessage(
stage_failure)
self.assertTrue(isinstance(failure_message,
failure_message_lib.BuildScriptFailureMessage))
def testCreateMessageForPackageBuildFailureMessage(self):
"""Test CreateMessage for PackageBuildFailureMessage."""
stage_failure = StageFailureHelper.GetStageFailure(
1, 1, 0, 'PackageBuildFailure', 'exception msg', 'build',
DEFAULT_PACKAGE_BUILD_FAILURE_EXTRA_INFO, 'BuildImage')
failure_message = failure_message_lib.FailureMessageManager.CreateMessage(
stage_failure)
self.assertTrue(isinstance(failure_message,
failure_message_lib.PackageBuildFailureMessage))
def testCreateMessageForStageFailureMessage(self):
"""Test CreateMessage for StageFailureMessage."""
stage_failure = StageFailureHelper.GetStageFailure(
1, 1, None, 'TestFailure', 'exception msg', 'build', None, 'VMTest')
failure_message = failure_message_lib.FailureMessageManager.CreateMessage(
stage_failure)
self.assertTrue(isinstance(failure_message,
failure_message_lib.StageFailureMessage))
def testReconstructMessagesOnMixedMsgs(self):
"""Test ReconstructMessages on mixed messages."""
failures = FailureMessageHelper.GetBuildFailureMessageWithMixedMsgs()
self.assertEqual(len(failures), 4)
failure_ids = [f.failure_id for f in failures]
self.assertCountEqual(failure_ids, [4, 5, 6, 7])
for f in failures:
if f.failure_id == 4:
self.assertTrue(isinstance(
f, failure_message_lib.CompoundFailureMessage))
inner_failures = f.inner_failures
inner_failure_ids = [n_f.failure_id for n_f in inner_failures]
self.assertCountEqual([1, 2, 3], inner_failure_ids)
def testReconstructMessagesOnEmptyMsgs(self):
"""Test ReconstructMessages on empty messages."""
failures = failure_message_lib.FailureMessageManager.ReconstructMessages([])
self.assertEqual(failures, [])
def testConstructStageFailureMessagesOnNonCompoundFailures(self):
"""Test ConstructStageFailureMessages on non-compound failures."""
entry_1 = StageFailureHelper.GetStageFailure(failure_id=1)
entry_2 = StageFailureHelper.GetStageFailure(failure_id=2)
entry_3 = StageFailureHelper.GetStageFailure(failure_id=3)
failure_entries = [entry_1, entry_2, entry_3]
failures = (
failure_message_lib.FailureMessageManager.ConstructStageFailureMessages(
failure_entries))
self.assertEqual(len(failures), 3)
failure_ids = [f.failure_id for f in failures]
self.assertCountEqual(failure_ids, [1, 2, 3])
def testConstructStageFailureMessagesOnCompoundFailures(self):
"""Test ConstructStageFailureMessages on compound failures."""
entry_1 = StageFailureHelper.GetStageFailure(failure_id=1)
entry_2 = StageFailureHelper.GetStageFailure(
failure_id=2, outer_failure_id=1)
entry_3 = StageFailureHelper.GetStageFailure(
failure_id=3, outer_failure_id=1)
failure_entries = [entry_1, entry_2, entry_3]
failures = (
failure_message_lib.FailureMessageManager.ConstructStageFailureMessages(
failure_entries))
self.assertEqual(len(failures), 1)
f = failures[0]
self.assertEqual(f.failure_id, 1)
self.assertTrue(isinstance(f, failure_message_lib.CompoundFailureMessage))
inner_failure_ids = [n_f.failure_id for n_f in f.inner_failures]
self.assertCountEqual([2, 3], inner_failure_ids)