You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@trafficserver.apache.org by ja...@apache.org on 2015/02/10 22:55:10 UTC
[1/5] trafficserver-qa git commit: Restructure docs
Repository: trafficserver-qa
Updated Branches:
refs/heads/master 5f3f5fb2a -> 1eb2e71eb
Restructure docs
Project: http://git-wip-us.apache.org/repos/asf/trafficserver-qa/repo
Commit: http://git-wip-us.apache.org/repos/asf/trafficserver-qa/commit/1bfad94b
Tree: http://git-wip-us.apache.org/repos/asf/trafficserver-qa/tree/1bfad94b
Diff: http://git-wip-us.apache.org/repos/asf/trafficserver-qa/diff/1bfad94b
Branch: refs/heads/master
Commit: 1bfad94b7066d0f794fb23d8b504fe9fdd547c8b
Parents: 5f3f5fb
Author: Thomas Jackson <ja...@gmail.com>
Authored: Fri Feb 6 15:27:22 2015 -0800
Committer: Thomas Jackson <ja...@gmail.com>
Committed: Fri Feb 6 15:27:22 2015 -0800
----------------------------------------------------------------------
README.rst | 52 ------------------------------------------------
TODO.rst | 4 ++++
doc/design.rst | 46 ++++++++++++++++++++++++++++++++++++++++++
tsqa/environment.py | 1 +
4 files changed, 51 insertions(+), 52 deletions(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/trafficserver-qa/blob/1bfad94b/README.rst
----------------------------------------------------------------------
diff --git a/README.rst b/README.rst
index 5678c03..af9cbe4 100644
--- a/README.rst
+++ b/README.rst
@@ -12,53 +12,6 @@ secondary goal of being generic enough to test other proxies-- this has come up
since after writing the majority of code is not ATS specific.
-=================
-Design Principles
-=================
-The goal of this design is to create a flexible framework to write tests in. Additionaly
-we don't want to duplicate things that already exist. There are quite a few frameworks
-out there that do more for you, but they all come with some restrictions. The idea
-here is to enforce (in the framework) very few restrictions. Instead these restrictions
-should be created as style/testing requirements of the project the tests are for.
-This is done by effectively just creating a variety of helper classes that TestCases
-can sub-class to get some common functionality for free.
-
-
-============
-Architecture
-============
-Due to the flexible design principles at play there is very little in terms of
-architecture, but we'll go over the design of a few of the basic helper concepts.
-
-
-Environment
-============
-One of the common use-cases of a test framework is to build and run the application.
-The Environment is a directory (effectively a root dir) with the source code
-installed in it. In addition to the code this root is also where configs live.
-This means that the Environment object is responsible for maintining any daemons
-or configs that the application needs while testing.
-
-To reduce the amount of work to build environments there is an EnvironmentFactory.
-This Factory class will create all unique builds of an application that it is asked
-for. It will then return a copy of the requested environment to the caller. This
-means that if N tests require the same base environment we only have to compile
-once instead of N times.
-
-
-Endpoint
-========
-Another common requirement for integration testing a proxy is an origin. Not only
-do we need an origin, it is common to test the request/response on the origin as well
-as the client (since the proxy will modify the request/response). To aid in these
-sorts of tests we provide a DynamicHTTPEndpoint class which will create a Flask
-server in a separate thread with APIs to register endpoints and track requests.
-
-
-test_cases
-==========
-These are intended to be test cases that you would subclass to create your own test.
-
Environment Variables
=====================
@@ -66,8 +19,3 @@ TSQA_LAYOUT_PREFIX: Prefix to create layouts for each test execution (defaults t
TSQA_LOG_LEVEL: Log level for TSQA (defaults to INFO)
TSQA_TMP_DIR: temp directory for building of source (environment factory)
-
-====
-TODO
-====
-- abstract out "daemon" from environment. This will make it more generic (less ATS specific)and make it easy to wrap commands in other commands (such as valgrind)
http://git-wip-us.apache.org/repos/asf/trafficserver-qa/blob/1bfad94b/TODO.rst
----------------------------------------------------------------------
diff --git a/TODO.rst b/TODO.rst
new file mode 100644
index 0000000..5693ae6
--- /dev/null
+++ b/TODO.rst
@@ -0,0 +1,4 @@
+====
+TODO
+====
+- abstract out "daemon" from environment. This will make it more generic (less ATS specific)and make it easy to wrap commands in other commands (such as valgrind)
http://git-wip-us.apache.org/repos/asf/trafficserver-qa/blob/1bfad94b/doc/design.rst
----------------------------------------------------------------------
diff --git a/doc/design.rst b/doc/design.rst
new file mode 100644
index 0000000..2010405
--- /dev/null
+++ b/doc/design.rst
@@ -0,0 +1,46 @@
+=================
+Design Principles
+=================
+The goal of this design is to create a flexible framework to write tests in. Additionaly
+we don't want to duplicate things that already exist. There are quite a few frameworks
+out there that do more for you, but they all come with some restrictions. The idea
+here is to enforce (in the framework) very few restrictions. Instead these restrictions
+should be created as style/testing requirements of the project the tests are for.
+This is done by effectively just creating a variety of helper classes that TestCases
+can sub-class to get some common functionality for free.
+
+
+============
+Architecture
+============
+Due to the flexible design principles at play there is very little in terms of
+architecture, but we'll go over the design of a few of the basic helper concepts.
+
+
+Environment
+============
+One of the common use-cases of a test framework is to build and run the application.
+The Environment is a directory (effectively a root dir) with the source code
+installed in it. In addition to the code this root is also where configs live.
+This means that the Environment object is responsible for maintining any daemons
+or configs that the application needs while testing.
+
+To reduce the amount of work to build environments there is an EnvironmentFactory.
+This Factory class will create all unique builds of an application that it is asked
+for. It will then return a copy of the requested environment to the caller. This
+means that if N tests require the same base environment we only have to compile
+once instead of N times.
+
+
+Endpoint
+========
+Another common requirement for integration testing a proxy is an origin. Not only
+do we need an origin, it is common to test the request/response on the origin as well
+as the client (since the proxy will modify the request/response). To aid in these
+sorts of tests we provide a DynamicHTTPEndpoint class which will create a Flask
+server in a separate thread with APIs to register endpoints and track requests.
+
+
+test_cases
+==========
+These are intended to be test cases that you would subclass to create your own test.
http://git-wip-us.apache.org/repos/asf/trafficserver-qa/blob/1bfad94b/tsqa/environment.py
----------------------------------------------------------------------
diff --git a/tsqa/environment.py b/tsqa/environment.py
index 15580a6..600dfd4 100644
--- a/tsqa/environment.py
+++ b/tsqa/environment.py
@@ -14,6 +14,7 @@ import logging
log = logging.getLogger(__name__)
+
class EnvironmentFactory(object):
'''
Make builds of <SOURCE CODE> with optional env/configure flags
[4/5] trafficserver-qa git commit: Add examples to document various
test classes
Posted by ja...@apache.org.
Add examples to document various test classes
Project: http://git-wip-us.apache.org/repos/asf/trafficserver-qa/repo
Commit: http://git-wip-us.apache.org/repos/asf/trafficserver-qa/commit/80581888
Tree: http://git-wip-us.apache.org/repos/asf/trafficserver-qa/tree/80581888
Diff: http://git-wip-us.apache.org/repos/asf/trafficserver-qa/diff/80581888
Branch: refs/heads/master
Commit: 80581888dc5b94dd50f442d983202e0d13d54ccc
Parents: c5b0498
Author: Thomas Jackson <ja...@gmail.com>
Authored: Fri Feb 6 17:03:15 2015 -0800
Committer: Thomas Jackson <ja...@gmail.com>
Committed: Tue Feb 10 13:54:08 2015 -0800
----------------------------------------------------------------------
examples/README.rst | 19 +++++++++
examples/endpoint_cases.py | 56 ++++++++++++++++++++++++++
examples/environment_cases.py | 78 ++++++++++++++++++++++++++++++++++++
examples/environment_helpers.py | 71 ++++++++++++++++++++++++++++++++
examples/skip_examples.py | 38 ++++++++++++++++++
tsqa/test_cases.py | 7 +++-
6 files changed, 268 insertions(+), 1 deletion(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/trafficserver-qa/blob/80581888/examples/README.rst
----------------------------------------------------------------------
diff --git a/examples/README.rst b/examples/README.rst
new file mode 100644
index 0000000..2c673bd
--- /dev/null
+++ b/examples/README.rst
@@ -0,0 +1,19 @@
+.. Licensed to the Apache Software Foundation (ASF) under one
+ or more contributor license agreements. See the NOTICE file
+ distributed with this work for additional information
+ regarding copyright ownership. The ASF licenses this file
+ to you 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.
+
+This directory is for examples to document how to use TSQA. There is no gaurantee
+(or even intent) that these tests work or test anything.
http://git-wip-us.apache.org/repos/asf/trafficserver-qa/blob/80581888/examples/endpoint_cases.py
----------------------------------------------------------------------
diff --git a/examples/endpoint_cases.py b/examples/endpoint_cases.py
new file mode 100644
index 0000000..66ca6a6
--- /dev/null
+++ b/examples/endpoint_cases.py
@@ -0,0 +1,56 @@
+'''
+Examples of how to use DynamicHTTPEndpointCase
+'''
+# Licensed to the Apache Software Foundation (ASF) under one
+# or more contributor license agreements. See the NOTICE file
+# distributed with this work for additional information
+# regarding copyright ownership. The ASF licenses this file
+# to you 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.
+
+
+class TestDynamicHTTPEndpointCase(tsqa.test_cases.DynamicHTTPEndpointCase):
+ '''
+ DynamicHTTPEndpointCase will set up an instance attribute of "http_endpoint"
+ as well as a method (endpoint_url) to generate http request strings from paths.
+ '''
+ def test_base(self):
+ '''
+ By default there are no handlers registered to the server thread, so
+ all requests will 404
+ '''
+ ret = requests.get(self.endpoint_url('/footest'))
+ self.assertEqual(ret.status_code, 404)
+
+ def test_endpoint_url(self):
+ '''
+ self.endpoint_url is useful for converting paths into http request strings
+ '''
+ self.assertEqual(self.endpoint_url(), 'http://127.0.0.1:{0}'.format(self.http_endpoint.address[1]))
+
+ self.assertEqual(self.endpoint_url('/foo'), 'http://127.0.0.1:{0}/foo'.format(self.http_endpoint.address[1]))
+
+ def test_with_endpoint():
+ '''
+ You can register custom handlers to the http_endpoint
+ '''
+ # create a function which will take the Flask request object (http://werkzeug.pocoo.org/docs/0.10/wrappers/#werkzeug.wrappers.Request)
+ # and return a valid return for Flask (http://flask.pocoo.org/docs/0.10/quickstart/#about-responses)
+ def handler(request):
+ return "hello world"
+
+ # register the endpoint on a context path. Now any request to /hello will
+ # be sent to the handler function specified
+ self.http_endpoint.add_handler('/hello', handler)
+
+ ret = requests.get(self.endpoint_url('/hello'))
+ self.assertEqual(ret.text, 'hello world')
http://git-wip-us.apache.org/repos/asf/trafficserver-qa/blob/80581888/examples/environment_cases.py
----------------------------------------------------------------------
diff --git a/examples/environment_cases.py b/examples/environment_cases.py
new file mode 100644
index 0000000..8f33b2a
--- /dev/null
+++ b/examples/environment_cases.py
@@ -0,0 +1,78 @@
+'''
+Examples of how to use EnvironmentCase
+'''
+# Licensed to the Apache Software Foundation (ASF) under one
+# or more contributor license agreements. See the NOTICE file
+# distributed with this work for additional information
+# regarding copyright ownership. The ASF licenses this file
+# to you 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.
+
+
+class HelloWorld(tsqa.test_cases.EnvironmentCase):
+ '''
+ This is the trivial example of a TestCase. The parent class (in this case
+ EnvironmentCase) is responsible for all the heavy lifting. By the time
+ test_base is called EnvironmentCase will have aquired a unique environment,
+ configured ATS, and started ATS.
+ '''
+ def test_base(self):
+ # for example, you could send a request to ATS and check the response
+ ret = requests.get('http://127.0.0.1:{0}/'.format(self.configs['records.config']['CONFIG']['proxy.config.http.server_ports']))
+
+ # you also have access to your own logger.
+ self.log('Something interesting to log')
+
+ self.assertEqual(ret.status_code, 404)
+ self.assertIn('ATS', ret.headers['server'], 'message to print on test failure')
+
+
+class OverrideConfigureFlags(tsqa.test_cases.EnvironmentCase):
+ '''
+ The default getEnv() uses EnvironmentFactory to build trafficserver from
+ source with given environment/configure options. You can override these
+ values for a test class using the attribute "environment_factory"
+ '''
+ # Override the build options for environment factory
+ environment_factory = {
+ 'env': {'ENV_VAR': 'VALUE'},
+ 'configure': {'enable-spdy': None},
+ }
+
+
+class ConfiguredCase(tsqa.test_cases.EnvironmentCase):
+ '''
+ This is the trivial example of a TestCase. The parent class (in this case
+ EnvironmentCase) is responsible for all the heavy lifting. By the time
+ test_base is called EnvironmentCase will have aquired a unique environment,
+ configured ATS, and started ATS.
+ '''
+ @classmethod
+ def setUpEnv(cls, env):
+ '''
+ This funciton is responsible for setting up the environment for this fixture
+ This includes everything pre-daemon start.
+
+ You are passed in cls (which is the instance of this class) and env (which
+ is an environment object)
+ '''
+ # we can modify any/all configs (note: all pre-daemon start)
+ cls.configs['remap.config'].add_line('map / http://http://trafficserver.readthedocs.org/')
+
+ # Some configs have nicer wrapper objects to give you a more pythonic interface
+ cls.configs['records.config']['CONFIG'].update({
+ 'proxy.config.log.squid_log_enabled': 1,
+ 'proxy.config.log.squid_log_is_ascii': 1,
+ })
+
+
+
http://git-wip-us.apache.org/repos/asf/trafficserver-qa/blob/80581888/examples/environment_helpers.py
----------------------------------------------------------------------
diff --git a/examples/environment_helpers.py b/examples/environment_helpers.py
new file mode 100644
index 0000000..bb37a31
--- /dev/null
+++ b/examples/environment_helpers.py
@@ -0,0 +1,71 @@
+'''
+Environment cases will by default pull source from ~/trafficserver. For most
+applications you will want to create a sub-class of tsqa.traffic_tests.EnvironmentCase
+which will override the getEnv() method.
+'''
+# Licensed to the Apache Software Foundation (ASF) under one
+# or more contributor license agreements. See the NOTICE file
+# distributed with this work for additional information
+# regarding copyright ownership. The ASF licenses this file
+# to you 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.
+
+
+class HelperEnvironmentCase(tsqa.test_cases.EnvironmentCase):
+ '''
+ This is an example of how to subclass EnviromentCase and return your own
+ environments. This one is pulled from the ATS core.
+ '''
+ @classmethod
+ def getEnv(cls):
+ '''
+ This function is responsible for returning a unique environment
+ '''
+ SOURCE_DIR = os.path.realpath(os.path.join(__file__, '..', '..', '..', '..'))
+ TMP_DIR = os.path.join(tempfile.gettempdir(), 'tsqa')
+ ef = tsqa.environment.EnvironmentFactory(SOURCE_DIR,
+ os.path.join(TMP_DIR, 'base_envs'),
+ default_configure={'enable-example-plugins': None,
+ 'enable-test-tools': None,
+ 'enable-example-plugins': None,
+ },
+ )
+ # anywhere in this method you can raize SkipTest, and the test will be skipped
+ # in this example we skip any exceptions in building the environment,
+ # but you can put any logic in here to determine when a test should be
+ # skipped (primarily if you can't provide the environment requested)
+ try:
+ return ef.get_environment(cls.environment_factory['configure'], cls.environment_factory['env'])
+ except Exception as e:
+ raise unittest.SkipTest(e)
+
+
+class StaticEnvironmentCase(tsqa.test_cases.EnvironmentCase):
+ '''
+ This is an example which returns a static environment for all tests to run
+ with. This is useful for testing specific builds of ATS or its plugins.
+
+ An example would be to test a new internal plugin against the current internal
+ build of ATS.
+ '''
+ @classmethod
+ def getEnv(cls):
+ '''
+ This function is responsible for returning a unique environment
+ '''
+ # create a layout from the static root we have
+ layout = tsqa.environment.Layout('static/environment/dir')
+ # create a new environment
+ env = tsqa.environment.Environment()
+ # clone the static layout we have
+ env.clone(layout=layout)
+ return env
http://git-wip-us.apache.org/repos/asf/trafficserver-qa/blob/80581888/examples/skip_examples.py
----------------------------------------------------------------------
diff --git a/examples/skip_examples.py b/examples/skip_examples.py
new file mode 100644
index 0000000..d972e37
--- /dev/null
+++ b/examples/skip_examples.py
@@ -0,0 +1,38 @@
+'''
+Examples of how to skip tests
+ More examples: https://docs.python.org/2/library/unittest.html#unittest-skipping
+'''
+# Licensed to the Apache Software Foundation (ASF) under one
+# or more contributor license agreements. See the NOTICE file
+# distributed with this work for additional information
+# regarding copyright ownership. The ASF licenses this file
+# to you 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.
+
+
+class SkipEntireClass(helpers.EnvironmentCase):
+ @classmethod
+ def setUpClass(cls):
+ '''
+ If you'd like to skip an entire test
+ '''
+ # If you raise SkipTest in setUpClass (or within a test case) the test
+ # will be skipped. You can build logic around this to conditionally
+ # skip tests based on environment conditions.
+ raise unittest.SkipTest('Skip the entire class')
+
+
+class SkipSingleTestCase(helpers.EnvironmentCase):
+ @unittest.skip('Always skip this test with this message')
+ def test_example(self):
+ self.assertTrue(False)
+
http://git-wip-us.apache.org/repos/asf/trafficserver-qa/blob/80581888/tsqa/test_cases.py
----------------------------------------------------------------------
diff --git a/tsqa/test_cases.py b/tsqa/test_cases.py
index 7b84833..494a4fe 100644
--- a/tsqa/test_cases.py
+++ b/tsqa/test_cases.py
@@ -31,7 +31,12 @@ import os
# Base environment case
class EnvironmentCase(unittest.TestCase):
'''
- This class will get an environment (which is unique)
+ This class will:
+ - get a unique environment (using getEnv())
+ - create wrappers for ATS configs available in self.configs
+ - setup the environment (setUpEnv())
+ - write out the configs
+ - start the environment (environment.start())
'''
# TODO: better naming??
environment_factory = {'configure': None,
[5/5] trafficserver-qa git commit: Cleanup of the basic tests that
exist.
Posted by ja...@apache.org.
Cleanup of the basic tests that exist.
Change assert() to assertEqual
Project: http://git-wip-us.apache.org/repos/asf/trafficserver-qa/repo
Commit: http://git-wip-us.apache.org/repos/asf/trafficserver-qa/commit/1eb2e71e
Tree: http://git-wip-us.apache.org/repos/asf/trafficserver-qa/tree/1eb2e71e
Diff: http://git-wip-us.apache.org/repos/asf/trafficserver-qa/diff/1eb2e71e
Branch: refs/heads/master
Commit: 1eb2e71eb6f7810cf1b68859b4750faeba7b1ece
Parents: 8058188
Author: Thomas Jackson <ja...@gmail.com>
Authored: Fri Feb 6 17:16:42 2015 -0800
Committer: Thomas Jackson <ja...@gmail.com>
Committed: Tue Feb 10 13:54:08 2015 -0800
----------------------------------------------------------------------
tests/example_test.py | 14 -------------
tests/hello_world_test.py | 4 +++-
tests/helpers.py | 39 ++++++++++++++++++++++++++++++------
tests/utils/buildcache_test.py | 10 +++++-----
tests/utils/utils_test.py | 40 +++++++++++++++++++------------------
5 files changed, 62 insertions(+), 45 deletions(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/trafficserver-qa/blob/1eb2e71e/tests/example_test.py
----------------------------------------------------------------------
diff --git a/tests/example_test.py b/tests/example_test.py
deleted file mode 100644
index d91cf19..0000000
--- a/tests/example_test.py
+++ /dev/null
@@ -1,14 +0,0 @@
-'''
-This is a terrible example of how you would write some tests for tsqa
-'''
-
-import tsqa.utils
-unittest = tsqa.utils.import_unittest()
-
-def test_example():
- assert True == True
-
-class TestExample(unittest.TestCase):
- def test_example(self):
- assert True == True
-
http://git-wip-us.apache.org/repos/asf/trafficserver-qa/blob/1eb2e71e/tests/hello_world_test.py
----------------------------------------------------------------------
diff --git a/tests/hello_world_test.py b/tests/hello_world_test.py
index 302e4b2..0c13651 100644
--- a/tests/hello_world_test.py
+++ b/tests/hello_world_test.py
@@ -8,6 +8,8 @@ This should:
- send a request through
- check that it worked
'''
+import helpers
+
import tsqa.utils
unittest = tsqa.utils.import_unittest()
import tsqa.test_cases
@@ -16,7 +18,7 @@ import tsqa.environment
import requests
import time
-class TestEnvironmentCase(tsqa.test_cases.EnvironmentCase):
+class TestEnvironmentCase(helpers.EnvironmentCase):
def test_base(self):
assert isinstance(self.environment, tsqa.environment.Environment)
http://git-wip-us.apache.org/repos/asf/trafficserver-qa/blob/1eb2e71e/tests/helpers.py
----------------------------------------------------------------------
diff --git a/tests/helpers.py b/tests/helpers.py
index df5a18a..e01b2e1 100644
--- a/tests/helpers.py
+++ b/tests/helpers.py
@@ -1,22 +1,49 @@
import subprocess
import os
+import os.path
+import tempfile
-from tsqa.utils import run_sync_command
+import tsqa.test_cases
-TMP_DIR = '/tmp/tsqa/'
+import tsqa.utils
+
+TMP_DIR = os.path.join(tempfile.gettempdir(), 'tsqa')
+unittest = tsqa.utils.import_unittest()
def source_dir():
'''
return the directory where source code is checked out
'''
+ path = os.path.join(TMP_DIR, 'trafficserver')
# if we don't have it, clone it
- if not os.path.exists(TMP_DIR):
- os.makedirs(TMP_DIR)
- run_sync_command(['git', 'clone', 'https://github.com/apache/trafficserver.git'],
+ if not os.path.exists(path):
+ tsqa.utils.run_sync_command(['git', 'clone', 'https://github.com/apache/trafficserver.git'],
cwd=TMP_DIR,
stdout=subprocess.PIPE,
stderr=subprocess.PIPE,
)
- return TMP_DIR
+ return os.path.join(TMP_DIR, 'trafficserver')
+
+class EnvironmentCase(tsqa.test_cases.EnvironmentCase):
+ '''
+ This class will get an environment (which is unique) but won't start it
+ '''
+ @classmethod
+ def getEnv(cls):
+ '''
+ This function is responsible for returning an environment
+ '''
+ SOURCE_DIR = os.path.realpath(os.path.join(__file__, '..', '..', '..', '..'))
+ TMP_DIR = os.path.join(tempfile.gettempdir(), 'tsqa')
+ ef = tsqa.environment.EnvironmentFactory(source_dir(),
+ os.path.join(TMP_DIR, 'base_envs'),
+ default_configure={'enable-example-plugins': None,
+ 'enable-test-tools': None,
+ 'enable-example-plugins': None,
+ },
+ )
+ # TODO: figure out a way to determine why the build didn't fail and
+ # not skip all build failures?
+ return ef.get_environment(cls.environment_factory['configure'], cls.environment_factory['env'])
http://git-wip-us.apache.org/repos/asf/trafficserver-qa/blob/1eb2e71e/tests/utils/buildcache_test.py
----------------------------------------------------------------------
diff --git a/tests/utils/buildcache_test.py b/tests/utils/buildcache_test.py
index 818fa65..ac75fcd 100644
--- a/tests/utils/buildcache_test.py
+++ b/tests/utils/buildcache_test.py
@@ -24,11 +24,11 @@ class TestBuildCache(unittest.TestCase):
def test_base(self):
cache = tsqa.utils.BuildCache(self.tmp_dir)
- assert cache == {}
+ self.assertEqual(cache, {})
cache.save_cache()
- assert os.path.exists(self.cache_map_file)
+ self.assertTrue(os.path.exists(self.cache_map_file))
cache.load_cache()
- assert cache == {}
+ self.assertEqual(cache, {})
def test_load_cache(self):
# make sure that a bad cache file gets emptied
@@ -36,7 +36,7 @@ class TestBuildCache(unittest.TestCase):
fh.write(json.dumps({'foo': {}}))
cache = tsqa.utils.BuildCache(self.tmp_dir)
- assert cache == {}
+ self.assertEqual(cache, {})
def test_save_cache(self):
cache = tsqa.utils.BuildCache(self.tmp_dir)
@@ -44,7 +44,7 @@ class TestBuildCache(unittest.TestCase):
with open(self.cache_map_file) as fh:
json_cache = json.load(fh)
- assert json_cache == {'foo': {'a': 'somepath'}}
+ self.assertEqual(json_cache, {'foo': {'a': 'somepath'}})
http://git-wip-us.apache.org/repos/asf/trafficserver-qa/blob/1eb2e71e/tests/utils/utils_test.py
----------------------------------------------------------------------
diff --git a/tests/utils/utils_test.py b/tests/utils/utils_test.py
index 91547bd..324adfe 100644
--- a/tests/utils/utils_test.py
+++ b/tests/utils/utils_test.py
@@ -3,26 +3,28 @@ Test the utils
'''
import tsqa.utils
+unittest = tsqa.utils.import_unittest()
-def test_merge_dicts():
- '''
- These dicts should be merged in order, meaning latter ones will override
- earlier ones.
- '''
- assert tsqa.utils.merge_dicts({'a': 1}, {'a': 2}) == {'a': 2}
- assert tsqa.utils.merge_dicts({'a': 1}, {'b': 2}) == {'a': 1, 'b': 2}
+class TestUtils(unittest.TestCase):
+ def test_merge_dicts(self):
+ '''
+ These dicts should be merged in order, meaning latter ones will override
+ earlier ones.
+ '''
+ self.assertEqual(tsqa.utils.merge_dicts({'a': 1}, {'a': 2}), {'a': 2})
+ self.assertEqual(tsqa.utils.merge_dicts({'a': 1}, {'b': 2}), {'a': 1, 'b': 2})
-def test_configure_list():
- '''
- Test that we can convert a dict to a list of configure strings
- '''
- assert tsqa.utils.configure_list({'a': 'b', 'c': None}) == ['--a=b', '--c']
+ def test_configure_list(self):
+ '''
+ Test that we can convert a dict to a list of configure strings
+ '''
+ self.assertEqual(tsqa.utils.configure_list({'a': 'b', 'c': None}), ['--a=b', '--c'])
-def test_configure_string_to_dict():
- '''
- Can we reverse it?
- '''
- assert tsqa.utils.configure_string_to_dict('--a') == {'a': None}
- assert tsqa.utils.configure_string_to_dict('--a=b') == {'a': 'b'}
- assert tsqa.utils.configure_string_to_dict('--a=b --c') == {'a': 'b', 'c': None}
+ def test_configure_string_to_dict(self):
+ '''
+ Can we reverse it?
+ '''
+ self.assertEqual(tsqa.utils.configure_string_to_dict('--a'), {'a': None})
+ self.assertEqual(tsqa.utils.configure_string_to_dict('--a=b'), {'a': 'b'})
+ self.assertEqual(tsqa.utils.configure_string_to_dict('--a=b --c'), {'a': 'b', 'c': None})
[2/5] trafficserver-qa git commit: Apache license for all the files
Posted by ja...@apache.org.
Apache license for all the files
Project: http://git-wip-us.apache.org/repos/asf/trafficserver-qa/repo
Commit: http://git-wip-us.apache.org/repos/asf/trafficserver-qa/commit/ee89895d
Tree: http://git-wip-us.apache.org/repos/asf/trafficserver-qa/tree/ee89895d
Diff: http://git-wip-us.apache.org/repos/asf/trafficserver-qa/diff/ee89895d
Branch: refs/heads/master
Commit: ee89895d4a37125769534db86733729421289299
Parents: 1bfad94
Author: Thomas Jackson <ja...@gmail.com>
Authored: Fri Feb 6 15:31:39 2015 -0800
Committer: Thomas Jackson <ja...@gmail.com>
Committed: Fri Feb 6 15:31:39 2015 -0800
----------------------------------------------------------------------
README.rst | 17 +++++++++++++++++
doc/design.rst | 17 +++++++++++++++++
tsqa/__init__.py | 16 ++++++++++++++++
tsqa/configs.py | 17 +++++++++++++++++
tsqa/endpoint.py | 16 ++++++++++++++++
tsqa/environment.py | 16 ++++++++++++++++
tsqa/log.py | 16 ++++++++++++++++
tsqa/test_cases.py | 17 +++++++++++++++++
tsqa/utils.py | 16 ++++++++++++++++
9 files changed, 148 insertions(+)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/trafficserver-qa/blob/ee89895d/README.rst
----------------------------------------------------------------------
diff --git a/README.rst b/README.rst
index af9cbe4..49d1b61 100644
--- a/README.rst
+++ b/README.rst
@@ -1,3 +1,20 @@
+.. Licensed to the Apache Software Foundation (ASF) under one
+ or more contributor license agreements. See the NOTICE file
+ distributed with this work for additional information
+ regarding copyright ownership. The ASF licenses this file
+ to you 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.
+
=============
What is TSQA?
=============
http://git-wip-us.apache.org/repos/asf/trafficserver-qa/blob/ee89895d/doc/design.rst
----------------------------------------------------------------------
diff --git a/doc/design.rst b/doc/design.rst
index 2010405..18adfe7 100644
--- a/doc/design.rst
+++ b/doc/design.rst
@@ -1,3 +1,20 @@
+.. Licensed to the Apache Software Foundation (ASF) under one
+ or more contributor license agreements. See the NOTICE file
+ distributed with this work for additional information
+ regarding copyright ownership. The ASF licenses this file
+ to you 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.
+
=================
Design Principles
=================
http://git-wip-us.apache.org/repos/asf/trafficserver-qa/blob/ee89895d/tsqa/__init__.py
----------------------------------------------------------------------
diff --git a/tsqa/__init__.py b/tsqa/__init__.py
index 92492c8..b2a3f59 100644
--- a/tsqa/__init__.py
+++ b/tsqa/__init__.py
@@ -1,2 +1,18 @@
+# Licensed to the Apache Software Foundation (ASF) under one
+# or more contributor license agreements. See the NOTICE file
+# distributed with this work for additional information
+# regarding copyright ownership. The ASF licenses this file
+# to you 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.
+
# initialize logger
import tsqa.log
http://git-wip-us.apache.org/repos/asf/trafficserver-qa/blob/ee89895d/tsqa/configs.py
----------------------------------------------------------------------
diff --git a/tsqa/configs.py b/tsqa/configs.py
index abfec7f..1e2fd96 100644
--- a/tsqa/configs.py
+++ b/tsqa/configs.py
@@ -1,3 +1,20 @@
+# Licensed to the Apache Software Foundation (ASF) under one
+# or more contributor license agreements. See the NOTICE file
+# distributed with this work for additional information
+# regarding copyright ownership. The ASF licenses this file
+# to you 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.
+
+
# TODO: keep track of stat when it was loaded? So we don't clobber manual file changes...
class Config(object):
http://git-wip-us.apache.org/repos/asf/trafficserver-qa/blob/ee89895d/tsqa/endpoint.py
----------------------------------------------------------------------
diff --git a/tsqa/endpoint.py b/tsqa/endpoint.py
index 80ff841..de897f2 100644
--- a/tsqa/endpoint.py
+++ b/tsqa/endpoint.py
@@ -1,3 +1,19 @@
+# Licensed to the Apache Software Foundation (ASF) under one
+# or more contributor license agreements. See the NOTICE file
+# distributed with this work for additional information
+# regarding copyright ownership. The ASF licenses this file
+# to you 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.
+
# TODO: some request/response class to load the various libary's implementations and allow for comparison
import os
http://git-wip-us.apache.org/repos/asf/trafficserver-qa/blob/ee89895d/tsqa/environment.py
----------------------------------------------------------------------
diff --git a/tsqa/environment.py b/tsqa/environment.py
index 600dfd4..fbe0331 100644
--- a/tsqa/environment.py
+++ b/tsqa/environment.py
@@ -1,3 +1,19 @@
+# Licensed to the Apache Software Foundation (ASF) under one
+# or more contributor license agreements. See the NOTICE file
+# distributed with this work for additional information
+# regarding copyright ownership. The ASF licenses this file
+# to you 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.
+
import subprocess
import tempfile
import os
http://git-wip-us.apache.org/repos/asf/trafficserver-qa/blob/ee89895d/tsqa/log.py
----------------------------------------------------------------------
diff --git a/tsqa/log.py b/tsqa/log.py
index edfd0b7..f7d247c 100644
--- a/tsqa/log.py
+++ b/tsqa/log.py
@@ -1,3 +1,19 @@
+# Licensed to the Apache Software Foundation (ASF) under one
+# or more contributor license agreements. See the NOTICE file
+# distributed with this work for additional information
+# regarding copyright ownership. The ASF licenses this file
+# to you 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.
+
import logging
import os
http://git-wip-us.apache.org/repos/asf/trafficserver-qa/blob/ee89895d/tsqa/test_cases.py
----------------------------------------------------------------------
diff --git a/tsqa/test_cases.py b/tsqa/test_cases.py
index 33f9dc0..7b84833 100644
--- a/tsqa/test_cases.py
+++ b/tsqa/test_cases.py
@@ -1,6 +1,23 @@
'''
Some base test cases that do environment handling for you
'''
+# Licensed to the Apache Software Foundation (ASF) under one
+# or more contributor license agreements. See the NOTICE file
+# distributed with this work for additional information
+# regarding copyright ownership. The ASF licenses this file
+# to you 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.
+
+
import logging
import tsqa.endpoint
http://git-wip-us.apache.org/repos/asf/trafficserver-qa/blob/ee89895d/tsqa/utils.py
----------------------------------------------------------------------
diff --git a/tsqa/utils.py b/tsqa/utils.py
index 1878738..81efdb0 100644
--- a/tsqa/utils.py
+++ b/tsqa/utils.py
@@ -1,3 +1,19 @@
+# Licensed to the Apache Software Foundation (ASF) under one
+# or more contributor license agreements. See the NOTICE file
+# distributed with this work for additional information
+# regarding copyright ownership. The ASF licenses this file
+# to you 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.
+
from collections import MutableMapping
import os
import json
[3/5] trafficserver-qa git commit: Cleanup/add documentation to the
main classes in the python source
Posted by ja...@apache.org.
Cleanup/add documentation to the main classes in the python source
Project: http://git-wip-us.apache.org/repos/asf/trafficserver-qa/repo
Commit: http://git-wip-us.apache.org/repos/asf/trafficserver-qa/commit/c5b04980
Tree: http://git-wip-us.apache.org/repos/asf/trafficserver-qa/tree/c5b04980
Diff: http://git-wip-us.apache.org/repos/asf/trafficserver-qa/diff/c5b04980
Branch: refs/heads/master
Commit: c5b0498032adf866f548ae8db2a699ba7113a187
Parents: ee89895
Author: Thomas Jackson <ja...@gmail.com>
Authored: Fri Feb 6 16:02:53 2015 -0800
Committer: Thomas Jackson <ja...@gmail.com>
Committed: Tue Feb 10 13:54:08 2015 -0800
----------------------------------------------------------------------
tsqa/endpoint.py | 69 +++++++++++++++++++++++++++++++++++++++++-------
tsqa/environment.py | 8 ++++++
2 files changed, 67 insertions(+), 10 deletions(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/trafficserver-qa/blob/c5b04980/tsqa/endpoint.py
----------------------------------------------------------------------
diff --git a/tsqa/endpoint.py b/tsqa/endpoint.py
index de897f2..99e3d38 100644
--- a/tsqa/endpoint.py
+++ b/tsqa/endpoint.py
@@ -14,8 +14,6 @@
# See the License for the specific language governing permissions and
# limitations under the License.
-# TODO: some request/response class to load the various libary's implementations and allow for comparison
-
import os
import threading
import requests
@@ -30,7 +28,21 @@ from wsgiref.simple_server import make_server
REQUESTS = defaultdict(dict)
+# TODO: some request/response class to load the various libary's implementations and allow for comparison
class TrackingRequests():
+ '''
+ This class gives you a "requests" like object that will return a dict of:
+ - client_request
+ - client_response
+ - server_request
+ - server_response
+ assuming the request is going to the instance of DynamicHTTPEndpoint this object
+ was created with
+
+ In general this is useful for a proxy testing framework beause you commonly
+ need to check that the proxy (for example) added a header to the request
+ before the origin got it.
+ '''
def __init__(self, endpoint):
self.endpoint = endpoint
@@ -62,10 +74,44 @@ class TrackingRequests():
class DynamicHTTPEndpoint(threading.Thread):
- TRACKING_HEADER = '__cool_test_header__'
+ '''
+ A threaded webserver which allows you to dynamically add/remove handlers.
+ This is implemented using flask (http://flask.pocoo.org/) primarily because
+ it is very common and (almost more importantly) *very* picky about http
+ semantics.
+
+ To use this in a TestCase you simply need to create the thread:
+
+ # create the thread object
+ http_endpoint = tsqa.endpoint.DynamicHTTPEndpoint(port=cls.endpoint_port)
+ # start the thread
+ http_endpoint.start()
+ # wait for the webserver to listen
+ http_endpoint.ready.wait()
+
+ At this point the webserver is listening and returning 404 for all requests.
+ To register an endpoint you must (1) define a request-handler function and
+ (2) add that handler to the http_endpoint.
+
+ (1): To define a request handler you must create a function which takes a single
+ argument which is the Request wrapper (http://werkzeug.pocoo.org/docs/0.10/wrappers/#werkzeug.wrappers.Request).
+ Flask support a variety or return types (http://flask.pocoo.org/docs/0.10/quickstart/#about-responses),
+ for this example we will simply return "hello world"
+
+ def handler_func(request):
+ return "hello world"
+
+ (2): Now that we have a function, we can add it as a handler to a context path
+ http_endpoint.add_handler('/hello', handler_func)
+
+ '''
+ TRACKING_HEADER = '__cool_test_header__' # TODO: better name?
@property
def address(self):
+ '''
+ Return a tuple of (ip, port) that this thread is listening on.
+ '''
return (self.server.server_address, self.server.server_port)
def __init__(self, port=0):
@@ -74,9 +120,7 @@ class DynamicHTTPEndpoint(threading.Thread):
self.tracked_requests = {}
self.daemon = True
-
self.port = port
-
self.ready = threading.Event()
# dict of pathname (no starting /) -> function
@@ -225,10 +269,18 @@ class ThreadedSSLTCPServer(SocketServer.ThreadingMixIn, SocketServer.TCPServer):
class SSLSocketServerDaemon(threading.Thread):
'''
A daemon thread to run a socketserver
+
+ This is just a thread wrapper to https://docs.python.org/2/library/socketserver.html
'''
def __init__(self, handler, cert, key, port=0):
- # TODO: nicer import?
- import requests
+ '''
+ handler: instance of SocketServer.BaseRequestHandler
+ https://docs.python.org/2/library/socketserver.html#socketserver-tcpserver-example
+ cert: path to certificate file
+ key: path to key file
+ '''
+ # for testing it is *very* common to have self-signed certs, so we
+ # will disable warnings so we don't flood logs
requests.packages.urllib3.disable_warnings()
threading.Thread.__init__(self)
@@ -248,9 +300,6 @@ class SSLSocketServerDaemon(threading.Thread):
)
self.server.allow_reuse_address = True
self.port = self.server.socket.getsockname()[1]
-
self.ready.set()
- # Activate the server; this will keep running until you
- # interrupt the program with Ctrl-C
self.server.serve_forever()
http://git-wip-us.apache.org/repos/asf/trafficserver-qa/blob/c5b04980/tsqa/environment.py
----------------------------------------------------------------------
diff --git a/tsqa/environment.py b/tsqa/environment.py
index fbe0331..4c0c96e 100644
--- a/tsqa/environment.py
+++ b/tsqa/environment.py
@@ -250,6 +250,14 @@ class Layout:
class Environment:
+ '''
+ This is the core of tsqa. An environment is a directory (effectively a root dir)
+ with code and configs installed into it. This object is also responsible for
+ the daemon that will run out of this environment. All environments should be
+ sandboxed (seperate directories), and failures in one environment should not
+ cause failures in other environments.
+
+ '''
@property
def shell_env(self):
environ = copy.copy(os.environ)