| OLD | NEW |
| 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 Loading... |
| 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 Loading... |
| 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 Loading... |
| 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 Loading... |
| 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 Loading... |
| 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 |
| OLD | NEW |