blob: 68f64a6fb8b103407ab4f43d35b81832edeaa975 [file] [log] [blame]
# Copyright 2015 The LUCI Authors. All rights reserved.
# Use of this source code is governed under the Apache License, Version 2.0
# that can be found in the LICENSE file.
from recipe_engine.post_process import StepSuccess, StepFailure, StepException
DEPS = [
'context',
'step',
]
def RunSteps(api):
# Nest all steps below this.
with api.step.nest('complicated thing'):
with api.step.nest('first part'):
api.step('wait a bit', ['sleep', '1'])
# Prefix the name without indenting.
with api.context(name_prefix='attempt number: '):
step_result = api.step('one', ['echo', 'herpy'])
name_tokens = step_result.name_tokens
expected_name = ('complicated thing', 'attempt number: one')
assert name_tokens == expected_name, name_tokens
api.step('two', ['echo', 'derpy'])
# Outer nested step's status gets the worst child's status by default.
with api.step.nest('inherit status'):
with api.step.nest('inner step') as other_nest_step:
other_nest_step.presentation.status = api.step.EXCEPTION
# But, you could also pick the last status.
with api.step.nest('last status', status='last'):
with api.step.nest('failpants') as other_nest_step:
other_nest_step.presentation.status = api.step.EXCEPTION
api.step('everything OK', ['echo', 'hi'])
# Or, even add a callback
with api.step.nest('callback status') as nest_step:
def _callback(presentation, _nest_data):
# Presumably this would actually combine the result of some other steps
# inside nest_step.
presentation.status = 'FAILURE'
nest_step.callback = _callback
# Exceptions bubbling out take precedence.
try:
with api.step.nest('exception status'):
api.step('I am fine', ['echo', 'the chillest'])
raise Exception('Whoa! Bang!')
except Exception:
pass
try:
with api.step.nest('failure status'):
api.step('I fail', ['echo', 'fail'])
except api.step.StepFailure:
pass
try:
with api.step.nest('timeout status'):
api.step('I fail', ['echo', 'fail'], timeout=1)
except api.step.StepFailure as ex:
assert ex.had_timeout
# Change outer status after nesting is complete.
with api.step.nest('versatile status') as nest_step:
with api.step.nest('inner step'):
with api.step.nest('even deeper'):
pass
nest_step.presentation.status = api.step.FAILURE
# Duplicate nesting names with unique child steps
for i in xrange(3):
with api.step.nest('Do Iteration'):
api.step('Iterate %d' % i, ['echo', 'lerpy'])
api.step('simple thing', ['sleep', '1'])
# Show interaction between name_prefix and namespace.
with api.context(name_prefix='cool '):
api.step('something', ['echo', 'something'])
with api.context(namespace='world', name_prefix='hot '):
api.step('other', ['echo', 'other'])
with api.context(name_prefix='tamale '):
api.step('yowza', ['echo', 'yowza'])
with api.context(namespace='ocean'):
api.step('mild', ['echo', 'mild'])
# Note that "|" is a reserved character:
try:
api.step('cool|step', ['echo', 'hi'])
assert False # pragma: no cover
except ValueError:
pass
# OK to have a nest parent without any children
with api.step.nest('lonely parent'):
pass
def GenTests(api):
yield (
api.test('basic')
+ api.post_process(StepException, 'inherit status')
+ api.post_process(StepSuccess, 'last status')
+ api.post_process(StepFailure, 'callback status')
+ api.post_process(StepException, 'exception status')
# TODO(iannucci): switch to build.proto so these can actually be
# differentiated: annotator protocol only has a subset of the possible
# statuses.
+ api.step_data('failure status.I fail', retcode=1)
+ api.post_process(StepFailure, 'failure status')
# TODO(iannucci): switch to build.proto so these can actually be
# differentiated: annotator protocol only has a subset of the possible
# statuses.
+ api.step_data('timeout status.I fail', times_out_after=20)
+ api.post_process(StepFailure, 'timeout status')
+ api.post_process(StepFailure, 'versatile status')
)