blob: d9995dd62465f5db54df1bc6454d004e03c398a5 [file] [log] [blame]
# Copyright 2019 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.
"""Provides a 'mock' version of the RecipeDeps object.
This is very lightweight and should be used for testing recipe_engine
functionality when you don't need to use actual recipe or recipe module code.
Access this via test_env.RecipeEngineUnitTest.MockRecipeDeps().
NOTE: This only contains constructs which are sufficient for the existing tests.
Lots of APIs are missing from these, and you should feel free to extend these
mocks.
Since these mocks are typically passed directly to recipe_engine functions in
lieu of the real RecipeDeps, please try not to add too many APIs here which
don't exist on the real objects (i.e. "path helpers" or things of that nature).
"""
from future.utils import iteritems
import sys
import os
from recipe_engine.internal.recipe_deps import parse_deps_spec
class MockRecipeDeps(object):
"""A mock version of recipe_deps.RecipeDeps."""
def __init__(self, modules_to_deps=None, recipes_to_deps=None):
"""Creates a MockRecipeDeps with a single 'main' repo containing the modules
and recipes specified by modules_to_deps and recipes_to_deps.
Args:
* modules_to_deps (None|Dict[str, DEPS specification]) - Passed to the
main_repo (MockRecipeRepo). Maps available recipe modules (by name)
to their DEPS specification.
* recipes_to_deps (None|Dict[str, DEPS specification]) - Passed to the
main_repo (MockRecipeRepo). Maps available recipes (by name)
to their DEPS specification.
"""
self.main_repo_id = 'main'
self.main_repo = MockRecipeRepo(
self, 'main', modules_to_deps or {}, recipes_to_deps or {})
self.repos = {'main': self.main_repo}
def add_repo(self, name, modules_to_deps=None, recipes_to_deps=None):
"""Creates and adds an additional repo to the MockRecipeDeps.
This will be available in `.repos`, and can be referred to in DEPS entries
of other repos currently in this MockRecipeDeps.
Args:
* name (str) - The name of the repo to add.
* modules_to_deps (None|Dict[str, DEPS specification]) - Passed to the
repo (MockRecipeRepo). Maps available recipe modules (by name)
to their DEPS specification.
* recipes_to_deps (None|Dict[str, DEPS specification]) - Passed to the
repo (MockRecipeRepo). Maps available recipes (by name)
to their DEPS specification.
"""
self.repos[name] = MockRecipeRepo(
self,
name,
modules_to_deps or {},
recipes_to_deps or {}
)
class MockRecipeRepo(object):
"""A mock version of recipe_deps.RecipeRepo."""
def __init__(self, rdeps, name, modules_to_deps, recipes_to_deps):
"""Creates a MockRecipeRepo with the name `name` containing the
modules and recipes specified by modules_to_deps and recipes_to_deps.
NOTE: You shouldn't call this directly, but instead use
`MockRecipeDeps.add_repo`.
Args:
* rdeps (MockRecipeDeps) - The MockRecipeDeps that this repo belongs to.
* name (str) - The name of this repo.
* modules_to_deps (None|Dict[str, DEPS specification]) - Maps available
recipe modules (by name) to their DEPS specification.
* recipes_to_deps (None|Dict[str, DEPS specification]) - Maps available
recipes (by name) to their DEPS specification.
"""
self.recipe_deps = rdeps
self.name = name
if sys.platform.startswith('win'):
self.path = 'c:\\%s_ROOT\\' % name.upper()
else:
self.path = '/%s_ROOT/' % name.upper()
self.modules = {
module_name: MockRecipeModule(self, module_name, DEPS)
for module_name, DEPS in iteritems(modules_to_deps)
}
self.recipes = {
recipe_name: MockRecipe(self, recipe_name, DEPS)
for recipe_name, DEPS in iteritems(recipes_to_deps)
}
class MockRecipeModule(object):
"""A mock version of recipe_deps.RecipeModule."""
def __init__(self, repo, name, DEPS):
"""Creates a MockRecipeModule with the given name and DEPS spec.
Args:
* repo (MockRecipeRepo) - The MockRecipeRepo that this recipe belongs to.
* name (str) - The name of the recipe module.
* DEPS (List[str]|Dict[str, str]) - A valid DEPS spec, as understood by
recipe_deps.parse_deps_spec().
"""
self.repo = repo
self.name = '%s/%s' % (repo.name, name)
self.path = os.path.join(repo.path, 'recipe_modules', name)
# pylint: disable=invalid-name
self.normalized_DEPS = parse_deps_spec(repo.name, DEPS)
class MockRecipe(object):
"""A mock version of recipe_deps.Recipe."""
def __init__(self, repo, name, DEPS):
"""Creates a MockRecipe with the given name and DEPS spec.
Args:
* repo (MockRecipeRepo) - The MockRecipeRepo that this recipe belongs to.
* name (str) - The name of the recipe. Note that this allows for
'modname:tests/name' type names as well.
* DEPS (List[str]|Dict[str, str]) - A valid DEPS spec, as understood by
recipe_deps.parse_deps_spec().
"""
self.repo = repo
self.path = os.path.join(repo.path, 'recipes', name) + '.py'
self.resources_dir = os.path.join(repo.path, 'recipes', name) + '.resources'
# pylint: disable=invalid-name
self.normalized_DEPS = parse_deps_spec(repo.name, DEPS)