blob: 51a7ea06c0c737dfc78f8cb01d71c9b788f012c7 [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 builtins import str as text
from recipe_engine import recipe_test_api
class RawIOTestApi(recipe_test_api.RecipeTestApi): # pragma: no cover
@recipe_test_api.placeholder_step_data
@staticmethod
def output(data, retcode=None, name=None):
"""Returns an output Placeholder for the provided data.
The data is expected to be bytes (i.e. str in python2). However, to help
with the Python3 migration, the unicode (str in python3) data will also be
accepted and will be encoded to bytes internally because in Python3,
`raw_io.output('foo')` pass will actually 'foo' as type 'str' instead of
'bytes' to this method and we have lots of usages like this. Please
make 'foo' a byte literal like `b'foo'`. We may drop the unicode support in
the future.
"""
if isinstance(data, text):
# TODO(yiwzhang): implicitly encode the data to bytes to avoid excessive
# errors during migration to python3. After we drop python2 support,
# consider raise ValueError instead for non-bytes data.
data = data.encode('utf-8')
if not isinstance(data, (type(None), bytes)):
raise ValueError(
'expected bytes, got %s: %r' % (type(data), data))
return data, retcode, name
@recipe_test_api.placeholder_step_data
@staticmethod
def output_text(data, retcode=None, name=None):
"""Returns an output Placeholder for the provided text data.
data must be either str (unicode in py2) or bytes (str in py2) that has
valid encoded utf-8 text in it.
"""
if isinstance(data, bytes):
data = data.decode('utf-8')
if not isinstance(data, (type(None), text)):
raise ValueError(
'expected None or utf-8 text, got %s: %r' % (type(data), data))
return data, retcode, name
@recipe_test_api.placeholder_step_data
@staticmethod
def output_dir(files_dict, retcode=None, name=None):
"""Use to mock an `output_dir` placeholder.
Note that slashes should match the platform that this test is targeting.
i.e. if this test is targeting Windows, you need to use backslashes.
Example:
yield api.test('tname') + api.step_data('sname', api.raw_io.output_dir({
"some/file": "contents of some/file",
}))
"""
assert type(files_dict) is dict
assert all(isinstance(key, str) for key in files_dict)
assert all(isinstance(value, bytes) for value in files_dict.values())
return files_dict, retcode, name
def stream_output(self, data, stream='stdout', retcode=None, name=None):
return self._stream_output(data, self.output,
stream=stream,
retcode=retcode,
name=name)
def stream_output_text(self, data, stream='stdout', retcode=None, name=None):
return self._stream_output(data, self.output_text,
stream=stream,
retcode=retcode,
name=name)
def _stream_output(self, data, to_step_data_fn,
stream='stdout', retcode=None, name=None):
ret = recipe_test_api.StepTestData()
assert stream in ('stdout', 'stderr')
step_data = to_step_data_fn(data, retcode=retcode, name=name)
setattr(ret, stream, step_data.unwrap_placeholder())
if retcode:
ret.retcode = retcode
return ret
@recipe_test_api.placeholder_step_data('output')
@staticmethod
def backing_file_missing(retcode=None, name=None):
"""Simulates a missing backing file.
Only valid if the corresponding placeholder has `leak_to` specified.
"""
# Passing None as the data of a placeholder causes the placeholder to
# behave during testing as if its backing file was missing.
return None, retcode, name