blob: 776072f420c8e6078c837ce108bc3615a2826df5 [file] [log] [blame]
# -*- coding: utf-8 -*-
# Copyright 2014 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.
DEPS = [
'path',
'platform',
'properties',
'raw_io',
'step',
]
def RunSteps(api):
# Read command's stdout and stderr.
step_result = api.step('echo', ['echo', 'Hello World'],
stdout=api.raw_io.output_text(),
stderr=api.raw_io.output_text())
assert step_result.stdout == 'Hello World\n'
assert step_result.stderr == ''
# Pass stuff to command's stdin, read it from stdout.
step_result = api.step('cat', ['cat'],
stdin=api.raw_io.input_text(data='hello'),
stdout=api.raw_io.output_text('out'))
assert step_result.stdout == 'hello'
step_result = api.step(
'cat',
['cat', api.raw_io.input_text(data='hello')],
stdout=api.raw_io.output_text('out'))
assert step_result.stdout == 'hello'
step_result = api.step(
'cat (unicode)',
['cat', api.raw_io.input_text(data='hello 💩')],
stdout=api.raw_io.output_text('out'))
assert step_result.stdout == 'hello 💩'
# \xe2 is not encodable by utf-8 (and has shown up in actual recipe data)
# so test that input correctly doesn't try to encode it as utf-8.
step_result = api.step('cat', ['cat'],
stdin=api.raw_io.input(data=b'\xe2hello'),
stdout=api.raw_io.output())
assert step_result.stdout == b'\xe2hello', step_result.stdout
# Example of auto-mocking stdout. '\n' appended to mock 'echo' behavior.
step_result = api.step('automock', ['echo', 'huh'],
stdout=api.raw_io.output_text('out'),
step_test_data=(
lambda: api.raw_io.test_api.stream_output_text('huh\n')))
assert step_result.stdout == 'huh\n'
# Example of auto-mocking stdout + stderr.
step_result = api.step(
'automock (fail)', ['bash', '-c', 'echo blah && echo fail 1>&2'],
stdout=api.raw_io.output_text('out'),
stderr=api.raw_io.output_text('err'),
step_test_data=(
lambda: (api.raw_io.test_api.stream_output_text('blah\n') + api.raw_io
.test_api.stream_output_text('fail\n', 'stderr'))))
assert step_result.stdout == 'blah\n'
assert step_result.stderr == 'fail\n'
# leak_to coverage.
step_result = api.step(
'leak stdout', ['echo', 'leaking'],
stdout=api.raw_io.output_text(
leak_to=api.path.tmp_base_dir / 'out.txt'),
step_test_data=(
lambda: api.raw_io.test_api.stream_output_text('leaking\n')))
assert step_result.stdout == 'leaking\n'
api.step('list temp dir', ['ls', api.raw_io.output_dir()])
api.step('leak dir', ['ls', api.raw_io.output_dir(
leak_to=api.path.tmp_base_dir / 'out')])
step_result = api.step(
'dump output_dir',
['python3',
api.resource('dump_files.py'),
api.raw_io.output_dir()])
outdir = step_result.raw_io.output_dir
some_file = api.path.join('some', 'file')
assert set(outdir) == {some_file, 'other_file'}
assert outdir[some_file] == b'cool contents'
assert outdir['other_file'] == b'whatever'
assert 'not_here' not in outdir
del outdir['some/file'] # delete to save memory
assert 'some/file' not in outdir
# Fail to write to leak_to file.
step_result = api.step(
'nothing leaked to leak_to',
['echo',
api.raw_io.output(leak_to=api.path.tmp_base_dir / 'missing.txt')])
# Example of overriding default mocked output for a single named output.
step_result = api.step(
'override_default_mock', [
'python3', api.resource('override_default_mock.py'),
api.raw_io.output_text(name='test'),
api.properties.get('some_prop', 'good_value'),
],
step_test_data=(
lambda: api.raw_io.test_api.output_text(
'second_bad_value', name='test')))
assert step_result.raw_io.output_texts['test'] == 'good_value'
assert step_result.raw_io.output_text == 'good_value'
# Example of add_output_log.
step_result = api.step(
'success output log', [
'python3', api.resource('success_output_log.py'),
api.raw_io.output_text(name='success_log', add_output_log=True),
],
step_test_data=(
lambda: api.raw_io.test_api.output_text(
'success', name='success_log')))
assert (['success'] ==
step_result.presentation.logs['raw_io.output_text[success_log]'])
# Example of add_output_log on failure.
try:
api.step(
'failure output log', [
'python3', api.resource('failure_output_log.py'),
api.raw_io.output_text(name='failure_log',
add_output_log='on_failure'),
],
step_test_data=(
lambda: api.raw_io.test_api.output_text(
'failure', name='failure_log')))
except api.step.StepFailure:
pass # This step is expected to fail.
finally:
step_result = api.step.active_result
assert (['failure'] ==
step_result.presentation.logs['raw_io.output_text[failure_log]'])
# Example of the placeholder backing file being missing at the time the
# result is retrieved.
step_result = api.step(
'missing backing file', [
'cat',
api.raw_io.output_text(
suffix='.txt',
name='outfile',
leak_to='/this/file/doesnt/exist',
)
],
ok_ret=(1,))
assert step_result.raw_io.output_text is None
def GenTests(api):
# This test shows that you can override a specific placeholder, even with
# default `step_test_data`. However, since this recipe is ACTUALLY run in
# the presubmit, we need to do a trick with properties:
# When run for real, "some_prop" will be "good_value" and pass.
# When run for simulation, we override this property to provide a bad value,
# AND the default step_test_data in RunSteps above ALSO provides another
# bad value, the simulation passes ONLY because of the
# 'override_default_mock' below.
for osname in ('linux', 'win'):
sep = '/' if osname == 'linux' else '\\'
yield (api.test('basic_'+osname) +
api.properties(some_prop='bad_value') +
api.platform.name(osname) +
api.step_data('echo',
stdout=api.raw_io.output_text('Hello World\n'),
stderr=api.raw_io.output_text('')) +
api.step_data('cat',
stdout=api.raw_io.output_text('hello')) +
api.step_data('cat (2)',
stdout=api.raw_io.output_text('hello')) +
api.step_data('cat (3)',
stdout=api.raw_io.output(b'\xe2hello')) +
api.step_data('cat (unicode)',
stdout=api.raw_io.output_text('hello 💩')) +
api.step_data('dump output_dir', api.raw_io.output_dir({
sep.join(['some', 'file']): b'cool contents',
'other_file': b'whatever',
})) +
api.step_data('override_default_mock',
api.raw_io.output_text('good_value', name='test')) +
api.step_data('failure output log', retcode=1) +
api.step_data('missing backing file',
api.raw_io.backing_file_missing(name='outfile'), retcode=1)
)