Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(499)

Side by Side Diff: recipe_engine/recipe_test_api.py

Issue 1785543004: Split Placeholder into InputPlaceholder and OutputPlaceholder. (Closed) Base URL: https://chromium.googlesource.com/external/github.com/luci/recipes-py@master
Patch Set: Address comments. Created 4 years, 9 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « no previous file | recipe_engine/step_runner.py » ('j') | recipe_engine/step_runner.py » ('J')
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 # Copyright 2013-2015 The Chromium Authors. All rights reserved. 1 # Copyright 2013-2015 The Chromium Authors. All rights reserved.
2 # Use of this source code is governed by a BSD-style license that can be 2 # Use of this source code is governed by a BSD-style license that can be
3 # found in the LICENSE file. 3 # found in the LICENSE file.
4 4
5 import collections 5 import collections
6 import contextlib 6 import contextlib
7 7
8 from .util import ModuleInjectionSite, static_call, static_wraps 8 from .util import ModuleInjectionSite, static_call, static_wraps
9 from .types import freeze 9 from .types import freeze
10 10
(...skipping 37 matching lines...) Expand 10 before | Expand all | Expand 10 after
48 48
49 class StepTestData(BaseTestData): 49 class StepTestData(BaseTestData):
50 """ 50 """
51 Mutable container for per-step test data. 51 Mutable container for per-step test data.
52 52
53 This data is consumed while running the recipe (during 53 This data is consumed while running the recipe (during
54 annotated_run.run_steps). 54 annotated_run.run_steps).
55 """ 55 """
56 def __init__(self): 56 def __init__(self):
57 super(StepTestData, self).__init__() 57 super(StepTestData, self).__init__()
58 # { (module, placeholder) -> [data] } 58 # { (module, placeholder) -> [data] }. These are for output placeholders.
59 self.placeholder_data = collections.defaultdict(list) 59 self.placeholder_data = collections.defaultdict(list)
60 self.override = False 60 self.override = False
61 self._stdout = None 61 self._stdout = None
62 self._stderr = None 62 self._stderr = None
63 self._retcode = None 63 self._retcode = None
64 64
65 def __add__(self, other): 65 def __add__(self, other):
66 assert isinstance(other, StepTestData) 66 assert isinstance(other, StepTestData)
67 67
68 if other.override: 68 if other.override:
(...skipping 208 matching lines...) Expand 10 before | Expand all | Expand 10 after
277 mod_name = self._module.NAME # pylint: disable=W0212 277 mod_name = self._module.NAME # pylint: disable=W0212
278 ret = TestData(None) 278 ret = TestData(None)
279 data = static_call(self, func, *args, **kwargs) 279 data = static_call(self, func, *args, **kwargs)
280 ret.mod_data[mod_name][inner.__name__] = data 280 ret.mod_data[mod_name][inner.__name__] = data
281 return ret 281 return ret
282 return inner 282 return inner
283 283
284 284
285 def placeholder_step_data(func): 285 def placeholder_step_data(func):
286 """Decorates RecipeTestApi member functions to allow those functions to 286 """Decorates RecipeTestApi member functions to allow those functions to
287 return just the placeholder data, instead of the normally required 287 return just the output placeholder data, instead of the normally required
288 StepTestData() object. 288 StepTestData() object.
289 289
290 The wrapped function may return either: 290 The wrapped function may return either:
291 * <placeholder data>, <retcode or None> 291 * <placeholder data>, <retcode or None>
292 * StepTestData containing exactly one PlaceholderTestData and possible a 292 * StepTestData containing exactly one PlaceholderTestData and possible a
293 retcode. This is useful for returning the result of another method which 293 retcode. This is useful for returning the result of another method which
294 is wrapped with placeholder_step_data. 294 is wrapped with placeholder_step_data.
295 295
296 In either case, the wrapper function will return a StepTestData object with 296 In either case, the wrapper function will return a StepTestData object with
297 the retcode and placeholder datum inserted with a name of: 297 the retcode and placeholder datum inserted with a name of:
(...skipping 33 matching lines...) Expand 10 before | Expand all | Expand 10 after
331 @static_wraps(func) 331 @static_wraps(func)
332 def inner(self, *args, **kwargs): 332 def inner(self, *args, **kwargs):
333 assert isinstance(self, RecipeTestApi) 333 assert isinstance(self, RecipeTestApi)
334 mod_name = self._module.NAME # pylint: disable=W0212 334 mod_name = self._module.NAME # pylint: disable=W0212
335 data = static_call(self, func, *args, **kwargs) 335 data = static_call(self, func, *args, **kwargs)
336 if isinstance(data, StepTestData): 336 if isinstance(data, StepTestData):
337 all_data = [i 337 all_data = [i
338 for l in data.placeholder_data.values() 338 for l in data.placeholder_data.values()
339 for i in l] 339 for i in l]
340 assert len(all_data) == 1, ( 340 assert len(all_data) == 1, (
341 'placeholder_step_data is only expecting a single placeholder datum. ' 341 'placeholder_step_data is only expecting a single output placeholder '
342 'Got: %r' % data 342 'datum. Got: %r' % data
343 ) 343 )
344 placeholder_data, retcode = all_data[0], data.retcode 344 placeholder_data, retcode = all_data[0], data.retcode
345 else: 345 else:
346 placeholder_data, retcode = data 346 placeholder_data, retcode = data
347 placeholder_data = PlaceholderTestData(placeholder_data) 347 placeholder_data = PlaceholderTestData(placeholder_data)
348 348
349 ret = StepTestData() 349 ret = StepTestData()
350 ret.placeholder_data[(mod_name, inner.__name__)].append(placeholder_data) 350 ret.placeholder_data[(mod_name, inner.__name__)].append(placeholder_data)
351 ret.retcode = retcode 351 ret.retcode = retcode
352 return ret 352 return ret
(...skipping 84 matching lines...) Expand 10 before | Expand all | Expand 10 after
437 437
438 Used by step_data and override_step_data. 438 Used by step_data and override_step_data.
439 439
440 Args: 440 Args:
441 name - The name of the step we're providing data for 441 name - The name of the step we're providing data for
442 data - Zero or more StepTestData objects. These may fill in placeholder 442 data - Zero or more StepTestData objects. These may fill in placeholder
443 data for zero or more modules, as well as possibly setting the 443 data for zero or more modules, as well as possibly setting the
444 retcode for this step. 444 retcode for this step.
445 retcode=(int or None) - Override the retcode for this step, even if it 445 retcode=(int or None) - Override the retcode for this step, even if it
446 was set by |data|. This must be set as a keyword arg. 446 was set by |data|. This must be set as a keyword arg.
447 stdout - StepTestData object with placeholder data for a step's stdout. 447 stdout - StepTestData object with a single output placeholder datum for a
448 stderr - StepTestData object with placeholder data for a step's stderr. 448 step's stdout.
449 stderr - StepTestData object with a single output placeholder datum for a
450 step's stderr.
449 override=(bool) - This step data completely replaces any previously 451 override=(bool) - This step data completely replaces any previously
450 generated step data, instead of adding on to it. 452 generated step data, instead of adding on to it.
451 453
452 Use in GenTests: 454 Use in GenTests:
453 # Hypothetically, suppose that your recipe has default test data for two 455 # Hypothetically, suppose that your recipe has default test data for two
454 # steps 'init' and 'sync' (probably via recipe_api.inject_test_data()). 456 # steps 'init' and 'sync' (probably via recipe_api.inject_test_data()).
455 # For this example, lets say that the default test data looks like: 457 # For this example, lets say that the default test data looks like:
456 # api.step_data('init', api.json.output({'some': ["cool", "json"]})) 458 # api.step_data('init', api.json.output({'some': ["cool", "json"]}))
457 # AND 459 # AND
458 # api.step_data('sync', api.json.output({'src': {'rev': 100}})) 460 # api.step_data('sync', api.json.output({'src': {'rev': 100}}))
(...skipping 44 matching lines...) Expand 10 before | Expand all | Expand 10 after
503 505
504 def expect_exception(self, exc_type): #pylint: disable=R0201 506 def expect_exception(self, exc_type): #pylint: disable=R0201
505 ret = TestData(None) 507 ret = TestData(None)
506 ret.expect_exception(exc_type) 508 ret.expect_exception(exc_type)
507 return ret 509 return ret
508 510
509 def depend_on(self, recipe, properties, result): 511 def depend_on(self, recipe, properties, result):
510 ret = TestData() 512 ret = TestData()
511 ret.depend_on(recipe, properties, result) 513 ret.depend_on(recipe, properties, result)
512 return ret 514 return ret
OLDNEW
« no previous file with comments | « no previous file | recipe_engine/step_runner.py » ('j') | recipe_engine/step_runner.py » ('J')

Powered by Google App Engine
This is Rietveld 408576698