Files

219 lines
7.9 KiB
Python

# Copyright 2015 Google Inc. All Rights Reserved.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
"""Unit test support library for GAE Externalized Runtimes."""
from __future__ import absolute_import
from __future__ import division
from __future__ import print_function
import logging
import os
import shutil
import tempfile
import unittest
from gae_ext_runtime import ext_runtime
class InvalidRuntime(Exception):
"""Raised when the runtime directory is doesn't match the runtime."""
class AppInfoFake(dict):
"""Serves as a fake for an AppInfo object."""
def ToDict(self):
return self
class TestBase(unittest.TestCase):
"""Unit testing base class.
Derived classes must define a setUp() method that sets a runtime_def_root
attribute containing the path to the root directory of the runtime.
"""
def setUp(self):
self.exec_env = ext_runtime.DefaultExecutionEnvironment()
self.temp_path = tempfile.mkdtemp()
self.assertTrue(hasattr(self, 'runtime_def_root'),
'Your test suite must define a setUp() method that '
'sets a runtime_def_root attribute to the root of the '
'runtime.')
def tearDown(self):
shutil.rmtree(self.temp_path)
def set_execution_environment(self, exec_env):
"""Set the execution environment used by generate_configs.
If this is not set, an instance of
ext_runtime.DefaultExecutionEnvironment is used.
Args:
exec_env: (ext_runtime.ExecutionEnvironment) The execution
environment to be used for config generation.
"""
self.exec_env = exec_env
def maybe_get_configurator(self, params=None, **kwargs):
"""Load the runtime definition.
Args:
params: (ext_runtime.Params) Runtime parameters. DEPRECATED.
Use the keyword args, instead.
**kwargs: ({str: object, ...}) If specified, these are the
arguments to the ext_runtime.Params() constructor
(valid args are at this time are: appinfo, custom and deploy,
check ext_runtime.Params() for full details)
Returns:
configurator or None if configurator didn't match
"""
rt = ext_runtime.ExternalizedRuntime.Load(self.runtime_def_root,
self.exec_env)
params = params or ext_runtime.Params(**kwargs)
print(params.ToDict())
configurator = rt.Detect(self.temp_path, params)
return configurator
def generate_configs(self, params=None, **kwargs):
"""Load the runtime definition and generate configs from it.
Args:
params: (ext_runtime.Params) Runtime parameters. DEPRECATED.
Use the keyword args, instead.
**kwargs: ({str: object, ...}) If specified, these are the
arguments to the ext_runtime.Params() constructor
(valid args are at this time are: appinfo, custom and deploy,
check ext_runtime.Params() for full details)
Returns:
(bool) Returns True if files are generated, False if not, None
if configurator didn't match
"""
configurator = self.maybe_get_configurator(params, **kwargs)
if not configurator:
return None
configurator.Prebuild()
return configurator.GenerateConfigs()
def generate_config_data(self, params=None, **kwargs):
"""Load the runtime definition and generate configs from it.
Args:
params: (ext_runtime.Params) Runtime parameters. DEPRECATED.
Use the keyword args, instead.
**kwargs: ({str: object, ...}) If specified, these are the
arguments to the ext_runtime.Params() constructor
(valid args are at this time are: appinfo, custom and deploy,
check ext_runtime.Params() for full details)
Returns:
([ext_runtime.GeneratedFile, ...]) Returns list of generated files.
Raises:
InvalidRuntime: Couldn't detect a matching runtime.
"""
configurator = self.maybe_get_configurator(params, **kwargs)
if not configurator:
raise InvalidRuntime('Runtime defined in {} did not detect '
'code in {}'.format(self.runtime_def_root,
self.temp_path))
configurator.Prebuild()
return configurator.GenerateConfigData()
def detect(self, params=None, **kwargs):
"""Load the runtime definition and generate configs from it.
Args:
params: (ext_runtime.Params) Runtime parameters. DEPRECATED.
Use the keyword args, instead.
**kwargs: ({str: object, ...}) If specified, these are the
arguments to the ext_runtime.Params() constructor
(valid args are at this time are: appinfo, custom and deploy,
check ext_runtime.Params() for full details)
Returns:
(ext_runtime.Configurator or None) the identified runtime if found,
None if not.
"""
rt = ext_runtime.ExternalizedRuntime.Load(self.runtime_def_root,
self.exec_env)
params = params or ext_runtime.Params(**kwargs)
configurator = rt.Detect(self.temp_path, params)
return configurator
def full_path(self, *path_components):
"""Returns the fully qualified path for a relative filename.
e.g. self.full_path('foo', 'bar', 'baz') -> '/temp/path/foo/bar/baz'
Args:
*path_components: ([str, ...]) Path components.
Returns:
(str)
"""
return os.path.join(self.temp_path, *path_components)
def write_file(self, filename, contents):
with open(os.path.join(self.temp_path, filename), 'w') as fp:
fp.write(contents)
def read_runtime_def_file(self, *args):
"""Read the entire contents of the file.
Returns the entire contents of the file identified by a set of
arguments forming a path relative to the root of the runtime
definition.
Args:
*args: A set of path components (see full_path()). Note that
these are relative to the runtime definition root, not the
temporary directory.
"""
with open(os.path.join(self.runtime_def_root, *args)) as fp:
return fp.read()
def assert_file_exists_with_contents(self, filename, contents):
"""Assert that the specified file exists with the given contents.
Args:
filename: (str) New file name.
contents: (str) File contents.
"""
full_name = self.full_path(filename)
self.assertTrue(os.path.exists(full_name))
with open(full_name) as fp:
actual_contents = fp.read()
self.assertEqual(contents, actual_contents)
def assert_genfile_exists_with_contents(self, gen_files,
filename, contents):
for gen_file in gen_files:
if gen_file.filename == filename:
self.assertEqual(gen_file.contents, contents)
break
else:
self.fail('filename {} not found in generated files {}'.format(
filename, gen_files))