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)