Build API: Add mock-call functionality.
The core functionality for making mock calls to the API.
Support added for success, error, and invalid responses.
Allows consumers to test their implementations against the
potentially branched API without needing to run the full
endpoint.
BUG=chromium:999178
TEST=run_tests
Change-Id: I5de9c37f8a759c175627b6db5e9696533aada031
Reviewed-on: https://chromium-review.googlesource.com/c/chromiumos/chromite/+/1787836
Tested-by: Alex Klein <saklein@chromium.org>
Commit-Queue: Alex Klein <saklein@chromium.org>
Reviewed-by: Evan Hernandez <evanhernandez@chromium.org>
Reviewed-by: David Burger <dburger@chromium.org>
diff --git a/api/validate.py b/api/validate.py
index 285b5b2..e4dfdef 100644
--- a/api/validate.py
+++ b/api/validate.py
@@ -3,7 +3,13 @@
# Use of this source code is governed by a BSD-style license that can be
# found in the LICENSE file.
-"""Validation helpers for simple input validation in the API."""
+"""Validation helpers for simple input validation in the API.
+
+Note: Every validator MUST respect config.do_validation. This is an internally
+set config option that allows the mock call decorators to be placed before or
+after the validation decorators, rather than forcing an ordering that could then
+produce incorrect outputs if missed.
+"""
from __future__ import print_function
@@ -52,15 +58,16 @@
def decorator(func):
@functools.wraps(func)
- def _exists(input_proto, *args, **kwargs):
- for field in fields:
- logging.debug('Validating %s exists.', field)
+ def _exists(input_proto, output_proto, config, *args, **kwargs):
+ if config.do_validation:
+ for field in fields:
+ logging.debug('Validating %s exists.', field)
- value = _value(field, input_proto)
- if not value or not os.path.exists(value):
- cros_build_lib.Die('%s path does not exist: %s' % (field, value))
+ value = _value(field, input_proto)
+ if not value or not os.path.exists(value):
+ cros_build_lib.Die('%s path does not exist: %s' % (field, value))
- return func(input_proto, *args, **kwargs)
+ return func(input_proto, output_proto, config, *args, **kwargs)
return _exists
@@ -79,14 +86,15 @@
def decorator(func):
@functools.wraps(func)
- def _is_in(input_proto, *args, **kwargs):
- logging.debug('Validating %s is in %r', field, values)
- value = _value(field, input_proto)
+ def _is_in(input_proto, output_proto, config, *args, **kwargs):
+ if config.do_validation:
+ logging.debug('Validating %s is in %r', field, values)
+ value = _value(field, input_proto)
- if value not in values:
- cros_build_lib.Die('%s (%r) must be in %r', field, value, values)
+ if value not in values:
+ cros_build_lib.Die('%s (%r) must be in %r', field, value, values)
- return func(input_proto, *args, **kwargs)
+ return func(input_proto, output_proto, config, *args, **kwargs)
return _is_in
@@ -104,15 +112,16 @@
def decorator(func):
@functools.wraps(func)
- def _require(input_proto, *args, **kwargs):
- for field in fields:
- logging.debug('Validating %s is set.', field)
+ def _require(input_proto, output_proto, config, *args, **kwargs):
+ if config.do_validation:
+ for field in fields:
+ logging.debug('Validating %s is set.', field)
- value = _value(field, input_proto)
- if not value:
- cros_build_lib.Die('%s is required.', field)
+ value = _value(field, input_proto)
+ if not value:
+ cros_build_lib.Die('%s is required.', field)
- return func(input_proto, *args, **kwargs)
+ return func(input_proto, output_proto, config, *args, **kwargs)
return _require