blob: 6c0ebfe1184d2488ab9a86f864d9166916fc1e36 [file] [log] [blame]
# Copyright 2012 The ChromiumOS Authors
# Use of this source code is governed by a BSD-style license that can be
# found in the LICENSE file.
"""Unittests for build stages."""
from unittest import mock
from chromite.cbuildbot import cbuildbot_unittest
from chromite.cbuildbot.stages import generic_stages_unittest
from chromite.cbuildbot.stages import release_stages
from chromite.cbuildbot.stages.generic_stages_unittest import patch
from chromite.lib import config_lib
from chromite.lib import constants
from chromite.lib import failures_lib
from chromite.lib import parallel
from chromite.lib import parallel_unittest
from chromite.lib import results_lib
from chromite.lib import timeout_util
from chromite.lib.buildstore import FakeBuildStore
from chromite.lib.paygen import gspaths
from chromite.lib.paygen import paygen_build_lib
# pylint: disable=protected-access
class SigningStageTest(
generic_stages_unittest.AbstractStageTestCase,
cbuildbot_unittest.SimpleBuilderTestCase,
):
"""Test the SigningStage."""
RELEASE_TAG = "0.0.1"
SIGNER_RESULT = """
{ "status": { "status": "passed" }, "board": "link",
"keyset": "link-mp-v4", "type": "recovery", "channel": "stable" }
"""
INSNS_URLS_PER_CHANNEL = {
"chan1": ["chan1_uri1", "chan1_uri2"],
"chan2": ["chan2_uri1"],
}
def setUp(self):
self._Prepare()
self.buildstore = FakeBuildStore()
def ConstructStage(self):
return release_stages.SigningStage(
self._run, self.buildstore, self._current_board
)
def testWaitForPushImageSuccess(self):
"""Test waiting for input from PushImage."""
stage = self.ConstructStage()
stage.board_runattrs.SetParallel(
"instruction_urls_per_channel", self.INSNS_URLS_PER_CHANNEL
)
self.assertEqual(stage.WaitUntilReady(), True)
self.assertEqual(
stage.instruction_urls_per_channel, self.INSNS_URLS_PER_CHANNEL
)
def testWaitForPushImageError(self):
"""Test WaitForPushImageError with an error output from pushimage."""
stage = self.ConstructStage()
stage.board_runattrs.SetParallel("instruction_urls_per_channel", None)
self.assertEqual(stage.WaitUntilReady(), False)
def testWaitForSigningResultsSuccess(self):
"""Test that _WaitForSigningResults works when signing works."""
results = ["chan1_uri1.json", "chan1_uri2.json", "chan2_uri1.json"]
with patch(release_stages.gs, "GSContext") as mock_gs_ctx_init:
mock_gs_ctx = mock_gs_ctx_init.return_value
mock_gs_ctx.Cat.return_value = self.SIGNER_RESULT
notifier = mock.Mock()
stage = self.ConstructStage()
stage._WaitForSigningResults(self.INSNS_URLS_PER_CHANNEL, notifier)
self.assertEqual(
notifier.mock_calls, [mock.call("chan1"), mock.call("chan2")]
)
for result in results:
mock_gs_ctx.Cat.assert_any_call(result)
def testWaitForSigningResultsSuccessNoNotifier(self):
"""Test that _WaitForSigningResults works when signing works."""
results = ["chan1_uri1.json", "chan1_uri2.json", "chan2_uri1.json"]
with patch(release_stages.gs, "GSContext") as mock_gs_ctx_init:
mock_gs_ctx = mock_gs_ctx_init.return_value
mock_gs_ctx.Cat.return_value = self.SIGNER_RESULT
stage = self.ConstructStage()
stage._WaitForSigningResults(self.INSNS_URLS_PER_CHANNEL, None)
for result in results:
mock_gs_ctx.Cat.assert_any_call(result)
def testWaitForSigningResultsSuccessNothingSigned(self):
"""Test _WaitForSigningResults when there are no signed images."""
with patch(release_stages.gs, "GSContext") as mock_gs_ctx_init:
mock_gs_ctx = mock_gs_ctx_init.return_value
mock_gs_ctx.Cat.return_value = self.SIGNER_RESULT
notifier = mock.Mock()
stage = self.ConstructStage()
stage._WaitForSigningResults({}, notifier)
self.assertEqual(notifier.mock_calls, [])
self.assertEqual(mock_gs_ctx.Cat.mock_calls, [])
def testWaitForSigningResultsFailure(self):
"""Test _WaitForSigningResults when the signers report an error."""
with patch(release_stages.gs, "GSContext") as mock_gs_ctx_init:
mock_gs_ctx = mock_gs_ctx_init.return_value
mock_gs_ctx.Cat.return_value = """
{ "status": { "status": "failed" }, "board": "link",
"keyset": "link-mp-v4", "type": "recovery", "channel": "stable" }
"""
notifier = mock.Mock()
stage = self.ConstructStage()
self.assertRaisesStringifyable(
release_stages.SignerFailure,
stage._WaitForSigningResults,
{"chan1": ["chan1_uri1"]},
notifier,
)
# Ensure we didn't notify anyone of success.
self.assertEqual(notifier.mock_calls, [])
self.assertEqual(
mock_gs_ctx.Cat.mock_calls, [mock.call("chan1_uri1.json")]
)
def testWaitForSigningResultsTimeout(self):
"""Test that _WaitForSigningResults reports timeouts correctly."""
with patch(release_stages.timeout_util, "WaitForSuccess") as mock_wait:
mock_wait.side_effect = timeout_util.TimeoutError
notifier = mock.Mock()
stage = self.ConstructStage()
self.assertRaises(
release_stages.SignerResultsTimeout,
stage._WaitForSigningResults,
{"chan1": ["chan1_uri1"]},
notifier,
)
self.assertEqual(notifier.mock_calls, [])
def testCheckForResultsSuccess(self):
"""Test that _CheckForResults works when signing works."""
with patch(release_stages.gs, "GSContext") as mock_gs_ctx_init:
mock_gs_ctx = mock_gs_ctx_init.return_value
mock_gs_ctx.Cat.return_value = self.SIGNER_RESULT
notifier = mock.Mock()
stage = self.ConstructStage()
self.assertTrue(
stage._CheckForResults(
mock_gs_ctx, self.INSNS_URLS_PER_CHANNEL, notifier
)
)
self.assertEqual(
notifier.mock_calls, [mock.call("chan1"), mock.call("chan2")]
)
def testCheckForResultsSuccessNoChannels(self):
"""Test that _CheckForResults works when there is nothing to check for."""
with patch(release_stages.gs, "GSContext") as mock_gs_ctx_init:
mock_gs_ctx = mock_gs_ctx_init.return_value
notifier = mock.Mock()
stage = self.ConstructStage()
# Ensure we find that we are ready if there are no channels to look for.
self.assertTrue(stage._CheckForResults(mock_gs_ctx, {}, notifier))
# Ensure we didn't contact GS while checking for no channels.
self.assertFalse(mock_gs_ctx.Cat.called)
self.assertEqual(notifier.mock_calls, [])
def testCheckForResultsPartialComplete(self):
"""Verify _CheckForResults handles partial signing results."""
def catChan2Success(url):
if url.startswith("chan2"):
return self.SIGNER_RESULT
else:
raise release_stages.gs.GSNoSuchKey()
with patch(release_stages.gs, "GSContext") as mock_gs_ctx_init:
mock_gs_ctx = mock_gs_ctx_init.return_value
mock_gs_ctx.Cat.side_effect = catChan2Success
notifier = mock.Mock()
stage = self.ConstructStage()
self.assertFalse(
stage._CheckForResults(
mock_gs_ctx, self.INSNS_URLS_PER_CHANNEL, notifier
)
)
self.assertEqual(
stage.signing_results,
{
"chan1": {},
"chan2": {
"chan2_uri1.json": {
"board": "link",
"channel": "stable",
"keyset": "link-mp-v4",
"status": {"status": "passed"},
"type": "recovery",
}
},
},
)
self.assertEqual(notifier.mock_calls, [mock.call("chan2")])
def testCheckForResultsUnexpectedJson(self):
"""Verify _CheckForResults handles unexpected Json values."""
with patch(release_stages.gs, "GSContext") as mock_gs_ctx_init:
mock_gs_ctx = mock_gs_ctx_init.return_value
mock_gs_ctx.Cat.return_value = "{}"
notifier = mock.Mock()
stage = self.ConstructStage()
self.assertFalse(
stage._CheckForResults(
mock_gs_ctx, self.INSNS_URLS_PER_CHANNEL, notifier
)
)
self.assertEqual(stage.signing_results, {"chan1": {}, "chan2": {}})
self.assertEqual(notifier.mock_calls, [])
def testCheckForResultsMalformedJson(self):
"""Verify _CheckForResults handles unexpected Json values."""
with patch(release_stages.gs, "GSContext") as mock_gs_ctx_init:
mock_gs_ctx = mock_gs_ctx_init.return_value
mock_gs_ctx.Cat.return_value = "{"
notifier = mock.Mock()
stage = self.ConstructStage()
self.assertFalse(
stage._CheckForResults(
mock_gs_ctx, self.INSNS_URLS_PER_CHANNEL, notifier
)
)
self.assertEqual(stage.signing_results, {"chan1": {}, "chan2": {}})
self.assertEqual(notifier.mock_calls, [])
def testCheckForResultsNoResult(self):
"""Verify _CheckForResults handles missing signer results."""
with patch(release_stages.gs, "GSContext") as mock_gs_ctx_init:
mock_gs_ctx = mock_gs_ctx_init.return_value
mock_gs_ctx.Cat.side_effect = release_stages.gs.GSNoSuchKey
notifier = mock.Mock()
stage = self.ConstructStage()
self.assertFalse(
stage._CheckForResults(
mock_gs_ctx, self.INSNS_URLS_PER_CHANNEL, notifier
)
)
self.assertEqual(stage.signing_results, {"chan1": {}, "chan2": {}})
self.assertEqual(notifier.mock_calls, [])
def testCheckForResultsFailed(self):
"""Verify _CheckForResults handles missing signer results."""
with patch(release_stages.gs, "GSContext") as mock_gs_ctx_init:
mock_gs_ctx = mock_gs_ctx_init.return_value
mock_gs_ctx.Cat.side_effect = release_stages.gs.GSNoSuchKey
notifier = mock.Mock()
stage = self.ConstructStage()
self.assertFalse(
stage._CheckForResults(
mock_gs_ctx, self.INSNS_URLS_PER_CHANNEL, notifier
)
)
self.assertEqual(stage.signing_results, {"chan1": {}, "chan2": {}})
self.assertEqual(notifier.mock_calls, [])
def testPerformStageSuccess(self):
"""Test that SigningStage works when signing works."""
stage = self.ConstructStage()
stage.instruction_urls_per_channel = self.INSNS_URLS_PER_CHANNEL
self.PatchObject(stage, "_WaitForSigningResults")
stage.PerformStage()
# Verify that we send the right notifications.
result = stage.board_runattrs.GetParallel(
"signed_images_ready", timeout=0
)
self.assertEqual(result, ["chan1", "chan2"])
class PaygenStageTest(
generic_stages_unittest.AbstractStageTestCase,
cbuildbot_unittest.SimpleBuilderTestCase,
):
"""Test the PaygenStage Stage."""
# We use a variant board to make sure the '_' is translated to '-'.
BOT_ID = "beaglebone_servo-release"
RELEASE_TAG = "0.0.1"
def setUp(self):
self._Prepare()
self.buildstore = FakeBuildStore()
# This method fetches a file from GS, mock it out.
self.validateMock = self.PatchObject(
paygen_build_lib, "ValidateBoardConfig"
)
instanceMock = mock.MagicMock()
self.paygenBuildMock = self.PatchObject(
paygen_build_lib, "PaygenBuild", return_value=instanceMock
)
self.payload_config1 = mock.MagicMock()
self.payload_config1.payload_type = paygen_build_lib.PAYLOAD_TYPE_FSI
self.payload_config1.applicable_models = ["model1", "model3"]
self.payload_config2 = mock.MagicMock()
self.payload_config2.payload_type = paygen_build_lib.PAYLOAD_TYPE_OMAHA
self.payload_config2.applicable_models = ["model2", "model3"]
self.payload_config3 = mock.MagicMock()
self.payload_config3.payload_type = paygen_build_lib.PAYLOAD_TYPE_OMAHA
self.payload_config4 = mock.MagicMock()
self.payload_config4.payload_type = paygen_build_lib.PAYLOAD_TYPE_N2N
self.payload_config5 = mock.MagicMock()
self.payload_config5.payload_type = (
paygen_build_lib.PAYLOAD_TYPE_STEPPING_STONE
)
instanceMock.CreatePayloads.side_effect = iter(
[
(
"foo-suite-name",
"foo-archive-board",
"foo-archive-build",
[
self.payload_config1,
self.payload_config2,
self.payload_config3,
self.payload_config4,
self.payload_config5,
],
)
]
)
# pylint: disable=arguments-differ
def ConstructStage(self, channels=None):
return release_stages.PaygenStage(
self._run, self.buildstore, self._current_board, channels=channels
)
def testWaitUntilReadSigning(self):
"""Test that PaygenStage works when signing works."""
stage = self.ConstructStage()
stage.board_runattrs.SetParallel(
"signed_images_ready", ["stable", "beta"]
)
self.assertEqual(stage.WaitUntilReady(), True)
self.assertEqual(stage.channels, ["stable", "beta"])
def testWaitUntilReadSigningFailure(self):
"""Test that PaygenStage works when signing works."""
stage = self.ConstructStage()
stage.board_runattrs.SetParallel("signed_images_ready", None)
self.assertEqual(stage.WaitUntilReady(), False)
def testWaitUntilReadSigningEmpty(self):
"""Test that PaygenStage works when signing works."""
stage = self.ConstructStage()
stage.board_runattrs.SetParallel("signed_images_ready", [])
self.assertEqual(stage.WaitUntilReady(), True)
self.assertEqual(stage.channels, [])
def testPerformStageSuccess(self):
"""Test that PaygenStage works when signing works."""
with patch(release_stages.PaygenStage, "_RunPaygenInProcess") as runner:
channels = ["stable", "beta"]
stage = self.ConstructStage(channels=channels)
with parallel_unittest.ParallelMock():
stage.PerformStage()
metadata_channels = self._run.attrs.metadata.GetValue("channels")
self.assertEqual(",".join(channels), metadata_channels)
# Verify that we validate with the board name in release name space.
self.assertEqual(
self.validateMock.call_args_list,
[mock.call("beaglebone-servo")],
)
# Verify that we queue up work.
runner.assert_has_calls(
[
mock.call(
stage,
"stable",
"beaglebone-servo",
"0.0.1",
False,
False,
False,
),
mock.call(
stage,
"beta",
"beaglebone-servo",
"0.0.1",
False,
False,
False,
),
]
)
def testPerformStageNoChannels(self):
"""Test that PaygenStage works when signing works."""
with patch(release_stages.PaygenStage, "_RunPaygenInProcess") as runner:
stage = self.ConstructStage(channels=[])
with parallel_unittest.ParallelMock():
stage.PerformStage()
# Verify that we did not queue up work.
runner.assert_not_called()
def testPerformStageTrybot(self):
"""Test the PerformStage alternate behavior for trybot runs."""
with patch(release_stages.PaygenStage, "_RunPaygenInProcess") as runner:
# The stage is constructed differently for trybots, so don't use
# ConstructStage.
stage = self.ConstructStage(channels=["foo", "bar"])
with parallel_unittest.ParallelMock():
stage.PerformStage()
# Notice that we didn't put anything in _wait_for_channel_signing, but
# still got results right away.
runner.assert_has_calls(
[
mock.call(
stage,
"foo",
"beaglebone-servo",
"0.0.1",
False,
False,
False,
),
mock.call(
stage,
"bar",
"beaglebone-servo",
"0.0.1",
False,
False,
False,
),
]
)
def testPerformStageUnknownBoard(self):
"""Test that PaygenStage exits when an unknown board is specified."""
self._current_board = "unknown-board-name"
# Setup a board validation failure.
badBoardException = paygen_build_lib.BoardNotConfigured(
self._current_board
)
self.validateMock.side_effect = badBoardException
stage = self.ConstructStage()
with self.assertRaises(release_stages.PaygenNoPaygenConfigForBoard):
stage.PerformStage()
def testRunPaygenInProcess(self):
"""Test that _RunPaygenInProcess works in the simple case."""
# Have to patch and verify that the PaygenTestStage is created.
stage = self.ConstructStage()
with patch(paygen_build_lib, "ScheduleAutotestTests") as sched_tests:
# Call the method under test.
stage._RunPaygenInProcess(
"foo", "foo-board", "foo-version", True, False, False
)
# Ensure that PaygenTestStage is created and schedules the test suite
# with the correct arguments.
sched_tests.assert_called_once_with(
"foo-suite-name",
"foo-archive-board",
None,
"foo-archive-build",
[
self.payload_config1,
self.payload_config2,
self.payload_config3,
self.payload_config4,
self.payload_config5,
],
)
# Ensure arguments are properly converted and passed along.
self.paygenBuildMock.assert_called_with(
gspaths.Build(
version="foo-version",
board="foo-board",
channel="foo-channel",
bucket=gspaths.ChromeosReleases.BUCKET,
),
mock.ANY,
work_dir=mock.ANY,
site_config=stage._run.site_config,
dry_run=True,
skip_delta_payloads=False,
)
def testRunPaygenInProcessInSkylab(self):
"""Test that _RunPaygenInProcess works in Skylab."""
self._run.config.enable_skylab_hw_tests = True
# Have to patch and verify that the PaygenTestStage is created.
stage = self.ConstructStage()
with patch(paygen_build_lib, "ScheduleAutotestTests") as sched_tests:
# Call the method under test.
stage._RunPaygenInProcess(
"foo", "foo-board", "foo-version", True, False, False
)
# Ensure that PaygenTestStage is created and schedules the test suite
# with the correct arguments.
sched_tests.assert_called_once_with(
"foo-suite-name",
"foo-archive-board",
None,
"foo-archive-build",
[
self.payload_config1,
self.payload_config2,
self.payload_config3,
self.payload_config4,
self.payload_config5,
],
)
def testRunPaygenInProcessComplex(self):
"""Test that _RunPaygenInProcess with arguments that are more unusual."""
# Call the method under test.
# Use release tools channel naming, and a board name including a variant.
stage = self.ConstructStage()
stage._RunPaygenInProcess(
"foo-channel", "foo-board-variant", "foo-version", True, True, True
)
# Ensure arguments are properly converted and passed along.
self.paygenBuildMock.assert_called_with(
gspaths.Build(
version="foo-version",
board="foo-board-variant",
channel="foo-channel",
bucket=gspaths.ChromeosReleases.BUCKET,
),
mock.ANY,
dry_run=True,
work_dir=mock.ANY,
site_config=stage._run.site_config,
skip_delta_payloads=True,
)
def testRunPaygenInProcessWithUnifiedBuild(self):
self._run.config.models = [
config_lib.ModelTestConfig("model1", "model1"),
config_lib.ModelTestConfig("model2", "board", ["au"]),
]
# Have to patch and verify that the PaygenTestStage is created.
stage = self.ConstructStage()
with patch(paygen_build_lib, "ScheduleAutotestTests") as sched_tests:
# Call the method under test.
stage._RunPaygenInProcess(
"foo", "foo-board", "foo-version", True, False, False
)
# Ensure that the first model from the unified build was selected
# as the platform to be tested
sched_tests.assert_called_once_with(
"foo-suite-name",
"board",
"model2",
"foo-archive-build",
[
self.payload_config1,
self.payload_config2,
self.payload_config3,
self.payload_config4,
self.payload_config5,
],
)
def testRunPaygenInProcessWithUnifiedBuildInSkylab(self):
"""Test that _RunPaygenInProcess works for unibuild in Skylab."""
self._run.config.enable_skylab_hw_tests = True
self._run.config.models = [
config_lib.ModelTestConfig(
"model2", "board", ["au"], enable_skylab=True
),
]
# Have to patch and verify that the PaygenTestStage is created.
stage = self.ConstructStage()
with patch(paygen_build_lib, "ScheduleAutotestTests") as sched_tests:
# Call the method under test.
stage._RunPaygenInProcess(
"foo", "foo-board", "foo-version", True, False, False
)
# Ensure that the first model from the unified build was selected
# as the platform to be tested
sched_tests.assert_called_once_with(
"foo-suite-name",
"board",
"model2",
"foo-archive-build",
[
self.payload_config1,
self.payload_config2,
self.payload_config3,
self.payload_config4,
self.payload_config5,
],
)
def testRunPaygenInParallelWithUnifiedBuild(self):
# payload_config1 defines applicable_models as model1 and model3.
# model3 does not have au enabled but gets scheduled since it has type FSI.
# payload_config2 defines applicable_models as model2 and model3.
# model3 does not get scheduled since config2 has type OMAHA.
# payload_config3 has type OMAHA with no applicable models so doesn't get
# scheduled.
# payload_config4 has type N2N and which never have applicable_models but
# should get scheduled on all ['au'] models.
# payload_config5 has type STEPPING_STONE which also never has
# applicable models but should get scheduled on all ['au'] models too.
self._run.config.models = [
config_lib.ModelTestConfig("model1", "model1", ["au"]),
config_lib.ModelTestConfig("model2", "model1", ["au"]),
config_lib.ModelTestConfig("model3", "model1"),
]
# Have to patch and verify that the PaygenTestStage is created.
stage = self.ConstructStage()
with patch(parallel, "RunParallelSteps") as parallel_tests:
stage._RunPaygenInProcess(
"foo", "foo-board", "foo-version", True, False, False
)
# 2 tests scheduled for FSI, 1 test scheduled for OMAHA,
# 2 tests scheduled for N2N, 2 tests scheduled for STEPPING_STONE.
parallel_tests.assert_called_once_with([mock.ANY] * 7)
def testPayloadBuildSetCorrectly(self):
"""Test that payload build is passed correctly to PaygenBuild."""
stage = self.ConstructStage()
self.PatchObject(paygen_build_lib, "ScheduleAutotestTests")
# Call the method under test.
stage._RunPaygenInProcess(
"foo", "foo-board", "foo-version", False, False, False
)
# Ensure arguments are properly converted and passed along.
build = gspaths.Build(
version="foo-version",
board="foo-board",
channel="foo-channel",
bucket=gspaths.ChromeosReleases.BUCKET,
)
self.paygenBuildMock.assert_called_with(
build,
build,
work_dir=mock.ANY,
site_config=stage._run.site_config,
dry_run=False,
skip_delta_payloads=False,
)
def testTestPayloadBuildSetCorrectly(self):
"""Test that test payload build is passed correctly to PaygenBuild."""
stage = self.ConstructStage()
self.PatchObject(paygen_build_lib, "ScheduleAutotestTests")
# Call the method under test.
stage._RunPaygenInProcess(
"foo", "foo-board", "foo-version", True, False, False
)
# Ensure arguments are properly converted and passed along.
build = gspaths.Build(
version="foo-version",
board="foo-board",
channel="foo-channel",
bucket=gspaths.ChromeosReleases.BUCKET,
)
test_payload_build = gspaths.Build(build)
test_payload_build.bucket = gspaths.ChromeosReleases.TEST_BUCKET
self.paygenBuildMock.assert_called_with(
build,
test_payload_build,
work_dir=mock.ANY,
site_config=stage._run.site_config,
dry_run=True,
skip_delta_payloads=False,
)
class PaygenBuildStageTest(
generic_stages_unittest.AbstractStageTestCase,
cbuildbot_unittest.SimpleBuilderTestCase,
):
"""Test the PaygenBuild stage."""
# We use a variant board to make sure the '_' is translated to '-'.
BOT_ID = "beaglebone_servo-release"
RELEASE_TAG = "0.0.1"
def setUp(self):
self._Prepare()
self.buildstore = FakeBuildStore()
# pylint: disable=arguments-differ
def ConstructStage(self):
return release_stages.PaygenBuildStage(
self._run,
self.buildstore,
board=self._current_board,
channel="foochan",
version="foo-version",
debug=True,
skip_testing=False,
skip_delta_payloads=False,
)
def testStageName(self):
"""See if the stage name is correctly formed."""
stage = self.ConstructStage()
self.assertEqual(stage.name, "PaygenBuildFoochan")
class PaygenTestStageTest(
generic_stages_unittest.AbstractStageTestCase,
cbuildbot_unittest.SimpleBuilderTestCase,
):
"""Test the PaygenTestStage stage."""
# We use a variant board to make sure the '_' is translated to '-'.
BOT_ID = "beaglebone_servo-release"
RELEASE_TAG = "0.0.1"
def setUp(self):
self._Prepare()
self.buildstore = FakeBuildStore()
# pylint: disable=arguments-differ
def ConstructStage(self):
return release_stages.PaygenTestStage(
builder_run=self._run,
buildstore=self.buildstore,
suite_name="foo-test-suite",
board=self._current_board,
model=self._current_board,
lab_board_name=self._current_board,
# The PaygenBuild stage will add the '-channel' suffix to the channel
# when converting to release tools naming.
channel="foochan-channel",
build="foo-version",
debug=True,
payload_test_configs=[],
test_env=constants.ENV_AUTOTEST,
)
def testStageName(self):
"""See if the stage name is correctly formed."""
stage = self.ConstructStage()
self.assertEqual(stage.name, "PaygenTestFoochan [beaglebone_servo]")
def testPerformStageTestLabFail(self):
"""Test that exception from RunHWTestSuite are properly handled."""
with patch(paygen_build_lib, "ScheduleAutotestTests") as sched_tests:
sched_tests.side_effect = failures_lib.TestLabFailure
stage = self.ConstructStage()
with patch(stage, "_HandleExceptionAsWarning") as warning_handler:
warning_handler.return_value = (
results_lib.Results.FORGIVEN,
"description",
0,
)
stage.Run()
# This proves the exception was turned into a warning.
self.assertTrue(warning_handler.called)