You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@trafficserver.apache.org by zw...@apache.org on 2017/05/25 01:12:37 UTC
[trafficserver] branch master updated: Removes the tsqa tests,
to avoid confusion. Use autest.
This is an automated email from the ASF dual-hosted git repository.
zwoop pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/trafficserver.git
The following commit(s) were added to refs/heads/master by this push:
new 1e41700 Removes the tsqa tests, to avoid confusion. Use autest.
1e41700 is described below
commit 1e41700ce2f1fa597d4f7cf4e1962743e7f21b18
Author: Leif Hedstrom <zw...@apache.org>
AuthorDate: Wed May 24 11:06:47 2017 -0600
Removes the tsqa tests, to avoid confusion. Use autest.
---
ci/jenkins/bin/tsqa.sh | 26 -
ci/tsqa/Makefile | 90 ---
ci/tsqa/README.rst | 54 --
ci/tsqa/TODO | 7 -
ci/tsqa/files/cert.pem | 20 -
ci/tsqa/files/ec_keys/README.rst | 29 -
ci/tsqa/files/ec_keys/ca.crt | 12 -
ci/tsqa/files/ec_keys/ca.key | 8 -
ci/tsqa/files/ec_keys/intermediate.crt | 10 -
ci/tsqa/files/ec_keys/intermediate.key | 8 -
ci/tsqa/files/ec_keys/www.example.com.pem | 15 -
ci/tsqa/files/ec_keys/www.test.com.pem | 15 -
ci/tsqa/files/header-rewrite.config | 13 -
ci/tsqa/files/key.pem | 28 -
ci/tsqa/files/rsa_keys/README.rst | 28 -
ci/tsqa/files/rsa_keys/ca.crt | 30 -
ci/tsqa/files/rsa_keys/ca.key | 51 --
ci/tsqa/files/rsa_keys/intermediate.crt | 29 -
ci/tsqa/files/rsa_keys/intermediate.key | 51 --
ci/tsqa/files/rsa_keys/www.example.com.pem | 52 --
ci/tsqa/files/rsa_keys/www.test.com.pem | 52 --
ci/tsqa/nosetests | 30 -
ci/tsqa/requirements.txt | 9 -
ci/tsqa/tests/helpers.py | 38 --
ci/tsqa/tests/test_body_factory.py | 73 ---
ci/tsqa/tests/test_cache_generation.py | 159 -----
ci/tsqa/tests/test_chunked.py | 199 -------
ci/tsqa/tests/test_connect_attempts.py | 250 --------
ci/tsqa/tests/test_custom_log.py | 66 ---
ci/tsqa/tests/test_example.py | 185 ------
ci/tsqa/tests/test_header_rewrite.py | 130 -----
ci/tsqa/tests/test_headrequest.py | 115 ----
ci/tsqa/tests/test_hostdb.py | 639 ---------------------
ci/tsqa/tests/test_http2.py | 97 ----
ci/tsqa/tests/test_http2_spec.py | 115 ----
ci/tsqa/tests/test_https.py | 345 -----------
ci/tsqa/tests/test_keepalive.py | 481 ----------------
ci/tsqa/tests/test_origin_max_connections.py | 213 -------
.../tests/test_origin_min_keep_alive_connection.py | 99 ----
ci/tsqa/tests/test_redirection.py | 42 --
ci/tsqa/tests/test_remap.py | 130 -----
ci/tsqa/tests/test_tls_ticket_key_rotation.py | 175 ------
42 files changed, 4218 deletions(-)
diff --git a/ci/jenkins/bin/tsqa.sh b/ci/jenkins/bin/tsqa.sh
deleted file mode 100755
index 744bdb5..0000000
--- a/ci/jenkins/bin/tsqa.sh
+++ /dev/null
@@ -1,26 +0,0 @@
-#!/bin/sh
-#
-# 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.
-
-# Run all the TSQA tests.
-TSQA_LAYOUT_DIR="${WORKSPACE}/${BUILD_NUMBER}"
-cd "${WORKSPACE}/src/ci/tsqa" || exit 2
-make test "TSQA_LAYOUT_DIR=${TSQA_LAYOUT_DIR}"
-status=$?
-
-# Exit with proper status
-exit $status
diff --git a/ci/tsqa/Makefile b/ci/tsqa/Makefile
deleted file mode 100644
index 205a03b..0000000
--- a/ci/tsqa/Makefile
+++ /dev/null
@@ -1,90 +0,0 @@
-# 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.
-
--include /etc/os-release
-DISTRIBUTION := $(NAME)$(VERSION_ID)
-
-# Search for a program in $PATH (direct from the GNU make manual.
-pathsearch = $(firstword $(wildcard $(addsuffix /$(1),$(subst :, ,$(PATH)))))
-
-APT := $(call pathsearch,apt-get)
-DNF := $(call pathsearch,dnf)
-YUM := $(call pathsearch,yum)
-
-ifndef DISTRIBUTION
-ifneq ($(APT),)
-DISTRIBUTION := DebianGeneric
-else ifneq ($(DNF),)
-DISTRIBUTION := RedHatGeneric
-else ifneq ($(YUM),)
-DISTRIBUTION := RedHatGeneric
-endif
-endif
-
-PACKAGES_Fedora23 := python-pip python-virtualenv python-devel libffi-devel redhat-rpm-config
-PACKAGES_RedHatGeneric := python-pip python-virtualenv python-devel libcffi-devel
-PACKAGES_DebianGeneric := python-pip python-virtualenv python-dev libffi-dev
-
-PACKAGES := $(PACKAGES_$(DISTRIBUTION))
-
-VIRTUALENV_DIR := virtualenv
-
-NOSETESTS := ./nosetests
-
-# Run all tests.
-.PHONY: test
-test: $(VIRTUALENV_DIR)
- @$(NOSETESTS) --with-xunit --nocapture --verbose --logging-level=INFO
-
-# Scan and list the tests.
-.PHONY: list
-list: $(VIRTUALENV_DIR)
- @$(NOSETESTS) -sv --collect-only
-
-# Construct the virtualenv.
-.PHONY: $(VIRTUALENV_DIR)
-$(VIRTUALENV_DIR): $(VIRTUALENV_DIR)/.done
-
-$(VIRTUALENV_DIR)/.done:
- @if [ ! -d $(VIRTUALENV_DIR) ]; then\
- virtualenv $(VIRTUALENV_DIR);\
- fi
- $(MAKE) update
- @echo "Virtualenv ready!"
-
-# Update the virtualenv with the latest TSQA package and dependencies.
-.PHONY: update
-update:
- @rm -f $(VIRTUALENV_DIR)/.done
- @. $(VIRTUALENV_DIR)/bin/activate && \
- $(VIRTUALENV_DIR)/bin/pip install --upgrade pip && \
- $(VIRTUALENV_DIR)/bin/pip install --upgrade -r requirements.txt && \
- touch $(VIRTUALENV_DIR)/.done
-
-# Install TSQA bootstrap dependencies.
-.PHONY: bootstrap
-bootstrap:
- @echo package list is $(PACKAGES)
- @if [ -e /etc/debian_version ]; then \
- $(APT) install -y $(PACKAGES) ; \
- fi
- @if [ -e /etc/redhat-release ]; then \
- $(YUM) install -y $(PACKAGES) ; \
- fi
-
-.PHONY: clean
-clean:
- rm -rf virtualenv
diff --git a/ci/tsqa/README.rst b/ci/tsqa/README.rst
deleted file mode 100644
index 0e55c8b..0000000
--- a/ci/tsqa/README.rst
+++ /dev/null
@@ -1,54 +0,0 @@
-.. 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.
-
-==================
-How do I run TSQA?
-==================
-TSQA is mostly self contained (using python's virutalenv). There are currently only
-two external depencies (below package names are for RHEL/Centos):
- - python-virtualenv
- - libcffi-devel
-
-Run ``sudo make bootstrap`` to install the TSQA dependencies.
-
-Once these two packages are available you simply need to run "make test" in this
-directory to run all tests.
-
-If you wish to run single tests you may do so by using nosetests from the
-virtualenv directly-- this can be done by running something like:
-
- ./virtualenv/bin/nosetests tests/test_example.py
-
-
-=====================
-How do I write tests?
-=====================
-There are examples here in the trafficserver source tree (test_example.py), in
-trafficserver-qa (https://github.com/apache/trafficserver-qa/tree/master/examples),
-and other test cases to read through. If you have any questions please feel free
-to send mail to the mailing lists, or pop onto IRC.
-
-
-=====================
-Where do I put tests?
-=====================
-At this point there aren't a lot of tests, so it may be difficult to know *where*
-to put your test. The general plan is to group tests by functionality. For example,
-if you have a keepalive test it should go with the rest of the keepalive tests.
-In general where we put the test is a lot less important than the test itself.
-So if you are confused about where to put it please write the test and submit a
-patch or pull request, and someone will help you place it.
diff --git a/ci/tsqa/TODO b/ci/tsqa/TODO
deleted file mode 100644
index c01205b..0000000
--- a/ci/tsqa/TODO
+++ /dev/null
@@ -1,7 +0,0 @@
-# TODO list for tsqa
-
-- runtests script
- - run specific things within the virtualenv
- - package up output from specific tests in a relocateable way
-- Documentation/Examples of TSQA framework
-- pylint for test cases
diff --git a/ci/tsqa/files/cert.pem b/ci/tsqa/files/cert.pem
deleted file mode 100644
index fcac091..0000000
--- a/ci/tsqa/files/cert.pem
+++ /dev/null
@@ -1,20 +0,0 @@
------BEGIN CERTIFICATE-----
-MIIDVzCCAj+gAwIBAgIJAOY9Arrh4/IgMA0GCSqGSIb3DQEBBQUAMEIxCzAJBgNV
-BAYTAlhYMRUwEwYDVQQHDAxEZWZhdWx0IENpdHkxHDAaBgNVBAoME0RlZmF1bHQg
-Q29tcGFueSBMdGQwHhcNMTUwMTIyMDE1MjU3WhcNMTUwMjIxMDE1MjU3WjBCMQsw
-CQYDVQQGEwJYWDEVMBMGA1UEBwwMRGVmYXVsdCBDaXR5MRwwGgYDVQQKDBNEZWZh
-dWx0IENvbXBhbnkgTHRkMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA
-08GU61mR18JO9X20utgemoeeYyKx+LXZYQBc0cKwHzZIiYfokwCkCNekMjZ87DT2
-+++8lBf3PatSgtA8/xanr8+TTDbKPehqdItDAy9e/xYgPBz9RXHuBUeOw+CPxt2e
-aGrGwy6ybW3jne/+vm73wn+ZzldpwGGXwIQAS9lFqtmisx/DftL8fhzpfp/uIU/K
-Y33iMiPpEHi8CHrOsaREl787ipKoqfxs+d1JNTHu1I+wJKgppOrtyjF1AjYDmrRg
-RO8rJqIaUKS+8teV2KazwfdPkgNyaoZO7NCPPEjWkbp2c+2AJQqCSyZmJ63idgkR
-msaSjRx45vJPOU/KFVHLuQIDAQABo1AwTjAdBgNVHQ4EFgQUtL1CTVRABxDQVbZy
-WwOZWMCs08QwHwYDVR0jBBgwFoAUtL1CTVRABxDQVbZyWwOZWMCs08QwDAYDVR0T
-BAUwAwEB/zANBgkqhkiG9w0BAQUFAAOCAQEAComsgXv9V7utk6yY1XV+rtjZmyRV
-758Jjzb2sqqVtw8jtEvdiO6rK+Chb49cAcBGJFHZL2/CJ6BWSOf79fLj/IGKC/nX
-UBz0dxrlg9x/KR/Jtp0qqQXIw/HT/NvaytYxMIBKqkmjG+kWiPn61dvwFjIERPOb
-xM4lHhaO/PKWDDVx6Sf7UzMalmwFjaGQFXCNM5dfqvdqDYYrbZwEWuqmxNy1sZBY
-SfY7Tyz6OP9NnlgtWRAITPqBS2kx/MVCGd2TtzJcJDxKK67tr0QFenGtXSZy555Q
-bNKjXKVWiHrVCEgttPri22o7Ax1Q6FpLHMXDIiveUl6aXq4ulNzRqXpmaw==
------END CERTIFICATE-----
diff --git a/ci/tsqa/files/ec_keys/README.rst b/ci/tsqa/files/ec_keys/README.rst
deleted file mode 100644
index c3dd1e1..0000000
--- a/ci/tsqa/files/ec_keys/README.rst
+++ /dev/null
@@ -1,29 +0,0 @@
-All of these certificates are self-signed and are *not* secure. They are intended
-only for use in testing.
-
-Try to use existing certs if possible rather than generating your own.
-
-# generated using (make sure to set "hostname"):
-openssl ecparam -name prime256v1 -genkey -out key.pem
-openssl req -new -x509 -key key.pem -out cert.pem
-
-
-## Since we want to verify all of the certificate verification, we need to generate
-## our own CA and intermediate CA
-# Create CA
-openssl ecparam -name prime256v1 -genkey -out ca.key
-openssl req -new -x509 -nodes -sha1 -days 1825 -key ca.key -out ca.crt
-
-# Create Intermediate
-openssl ecparam -name prime256v1 -genkey -out intermediate.key
-openssl req -new -sha1 -key intermediate.key -out intermediate.csr
-
-# CA signs Intermediate
-openssl x509 -req -days 1825 -in intermediate.csr -CA ca.crt -CAkey ca.key -set_serial 01 -out intermediate.crt
-
-# Create Server
-openssl ecparam -name prime256v1 -genkey -out www.example.com.key
-openssl req -new -key test.example.com.key -out test.example.com.csr
-
-# Intermediate signs Server
-openssl x509 -req -days 1825 -in test.example.com.csr -CA intermediate.crt -CAkey intermediate.key -set_serial 01 -out test.example.com.crt
diff --git a/ci/tsqa/files/ec_keys/ca.crt b/ci/tsqa/files/ec_keys/ca.crt
deleted file mode 100644
index a70f990..0000000
--- a/ci/tsqa/files/ec_keys/ca.crt
+++ /dev/null
@@ -1,12 +0,0 @@
------BEGIN CERTIFICATE-----
-MIIByDCCAW6gAwIBAgIJAP0vC/lirtMJMAkGByqGSM49BAEwQTELMAkGA1UEBhMC
-WFgxFTATBgNVBAcMDERlZmF1bHQgQ2l0eTEMMAoGA1UECgwDQVRTMQ0wCwYDVQQD
-DARyb290MB4XDTE1MDQxMzIwMTEwMloXDTIwMDQxMTIwMTEwMlowQTELMAkGA1UE
-BhMCWFgxFTATBgNVBAcMDERlZmF1bHQgQ2l0eTEMMAoGA1UECgwDQVRTMQ0wCwYD
-VQQDDARyb290MFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEVRCzxLeGp2zzqqz6
-YTHRJ+sTuEzrFNUUQX/sEb4s1uceiqtTgFJ8kglWGMk/3WIC09PF4aRvkXM+xVvx
-U9EcaKNQME4wHQYDVR0OBBYEFF9E7e3RCj6b4rQeNVTnNHGgRhzvMB8GA1UdIwQY
-MBaAFF9E7e3RCj6b4rQeNVTnNHGgRhzvMAwGA1UdEwQFMAMBAf8wCQYHKoZIzj0E
-AQNJADBGAiEAtKiG3JParqhQz1N+QOGKJtbgFS/qwNpK9FanbC6MOLQCIQD+heQN
-eow8AF4hAUZNYvxyhZDd5FKzF2kRdxJUGkZK8w==
------END CERTIFICATE-----
diff --git a/ci/tsqa/files/ec_keys/ca.key b/ci/tsqa/files/ec_keys/ca.key
deleted file mode 100644
index 275e3e9..0000000
--- a/ci/tsqa/files/ec_keys/ca.key
+++ /dev/null
@@ -1,8 +0,0 @@
------BEGIN EC PARAMETERS-----
-BggqhkjOPQMBBw==
------END EC PARAMETERS-----
------BEGIN EC PRIVATE KEY-----
-MHcCAQEEIKR1N01PYCnkwa07tTnZ3Ri6dsGxu/OlTmExDWS1JIt6oAoGCCqGSM49
-AwEHoUQDQgAEVRCzxLeGp2zzqqz6YTHRJ+sTuEzrFNUUQX/sEb4s1uceiqtTgFJ8
-kglWGMk/3WIC09PF4aRvkXM+xVvxU9EcaA==
------END EC PRIVATE KEY-----
diff --git a/ci/tsqa/files/ec_keys/intermediate.crt b/ci/tsqa/files/ec_keys/intermediate.crt
deleted file mode 100644
index 2a2fc1d..0000000
--- a/ci/tsqa/files/ec_keys/intermediate.crt
+++ /dev/null
@@ -1,10 +0,0 @@
------BEGIN CERTIFICATE-----
-MIIBcTCCARcCAQEwCQYHKoZIzj0EATBBMQswCQYDVQQGEwJYWDEVMBMGA1UEBwwM
-RGVmYXVsdCBDaXR5MQwwCgYDVQQKDANBVFMxDTALBgNVBAMMBHJvb3QwHhcNMTUw
-NDEzMjAxMTQ4WhcNMjAwNDExMjAxMTQ4WjBJMQswCQYDVQQGEwJYWDEVMBMGA1UE
-BwwMRGVmYXVsdCBDaXR5MQwwCgYDVQQKDANBVFMxFTATBgNVBAMMDGludGVybWVk
-aWF0ZTBZMBMGByqGSM49AgEGCCqGSM49AwEHA0IABCLloHhXc49EwEI94gb6186J
-zp5mHmEBD49I3pFuQwkVLu249uCsyEnjhoAlMohC/Oc/ROtvZTnujcdBZ2OBh4cw
-CQYHKoZIzj0EAQNJADBGAiEAzevMu2yohbN5dzRp5/TTxKSOrenLh56jtSJrtFai
-/wUCIQDV40abfGSiioLyb5PoyJRPa6M+AhWbK9caa2SQei+KnQ==
------END CERTIFICATE-----
diff --git a/ci/tsqa/files/ec_keys/intermediate.key b/ci/tsqa/files/ec_keys/intermediate.key
deleted file mode 100644
index bb1cdc5..0000000
--- a/ci/tsqa/files/ec_keys/intermediate.key
+++ /dev/null
@@ -1,8 +0,0 @@
------BEGIN EC PARAMETERS-----
-BggqhkjOPQMBBw==
------END EC PARAMETERS-----
------BEGIN EC PRIVATE KEY-----
-MHcCAQEEIMtffsDv9JDl4AFznb1ftzA8IqIVxA344PSpyZU6PfA/oAoGCCqGSM49
-AwEHoUQDQgAEIuWgeFdzj0TAQj3iBvrXzonOnmYeYQEPj0jekW5DCRUu7bj24KzI
-SeOGgCUyiEL85z9E629lOe6Nx0FnY4GHhw==
------END EC PRIVATE KEY-----
diff --git a/ci/tsqa/files/ec_keys/www.example.com.pem b/ci/tsqa/files/ec_keys/www.example.com.pem
deleted file mode 100644
index ee31b56..0000000
--- a/ci/tsqa/files/ec_keys/www.example.com.pem
+++ /dev/null
@@ -1,15 +0,0 @@
------BEGIN EC PRIVATE KEY-----
-MHcCAQEEIGCAR+s6Sno+AteQgnMBOsS7sD4EbSxGN7anPQaossvkoAoGCCqGSM49
-AwEHoUQDQgAEwNOf/ym+XidKYjQg2WDM3GPK2eMbRz2VmvdB4dbzBxQ4gMYCIl2l
-2L7lLqGtmUcuUhDaOxf91hhXAfprU+qRvA==
------END EC PRIVATE KEY-----
------BEGIN CERTIFICATE-----
-MIIBfDCCASICAQEwCQYHKoZIzj0EATBJMQswCQYDVQQGEwJYWDEVMBMGA1UEBwwM
-RGVmYXVsdCBDaXR5MQwwCgYDVQQKDANBVFMxFTATBgNVBAMMDGludGVybWVkaWF0
-ZTAeFw0xNTA0MTMyMDEzMjlaFw0yMDA0MTEyMDEzMjlaMEwxCzAJBgNVBAYTAlhY
-MRUwEwYDVQQHDAxEZWZhdWx0IENpdHkxDDAKBgNVBAoMA0FUUzEYMBYGA1UEAwwP
-d3d3LmV4YW1wbGUuY29tMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEwNOf/ym+
-XidKYjQg2WDM3GPK2eMbRz2VmvdB4dbzBxQ4gMYCIl2l2L7lLqGtmUcuUhDaOxf9
-1hhXAfprU+qRvDAJBgcqhkjOPQQBA0kAMEYCIQCU7CxO/zdFc4BDUCHO07wVuFe7
-RyiVVJs4llEZTXoBiAIhAIwrXtE2psZBRx/TE7miPunqa+1E4IxrtWn2fkzJyJ57
------END CERTIFICATE-----
diff --git a/ci/tsqa/files/ec_keys/www.test.com.pem b/ci/tsqa/files/ec_keys/www.test.com.pem
deleted file mode 100644
index e519276..0000000
--- a/ci/tsqa/files/ec_keys/www.test.com.pem
+++ /dev/null
@@ -1,15 +0,0 @@
------BEGIN EC PRIVATE KEY-----
-MHcCAQEEILVRI/Y9isXZJKXwb4srPN4hjx+ZUWGmSL3cn8AEhTVQoAoGCCqGSM49
-AwEHoUQDQgAEh4NjyzcxA2B/b281cUsRHaF+yAUV4CnIhUkPQigXw10GO9lQx69w
-of7PjZkJRdeBlEMBVUcwTKEuENMZ7a3+Tw==
------END EC PRIVATE KEY-----
------BEGIN CERTIFICATE-----
-MIIBdzCCAR8CAQEwCQYHKoZIzj0EATBJMQswCQYDVQQGEwJYWDEVMBMGA1UEBwwM
-RGVmYXVsdCBDaXR5MQwwCgYDVQQKDANBVFMxFTATBgNVBAMMDGludGVybWVkaWF0
-ZTAeFw0xNTA0MTMyMDEzMzZaFw0yMDA0MTEyMDEzMzZaMEkxCzAJBgNVBAYTAlhY
-MRUwEwYDVQQHDAxEZWZhdWx0IENpdHkxDDAKBgNVBAoMA0FUUzEVMBMGA1UEAwwM
-d3d3LnRlc3QuY29tMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEh4NjyzcxA2B/
-b281cUsRHaF+yAUV4CnIhUkPQigXw10GO9lQx69wof7PjZkJRdeBlEMBVUcwTKEu
-ENMZ7a3+TzAJBgcqhkjOPQQBA0cAMEQCIH083uGRd7b1crw6TH8paBZNeliJTiFU
-eg6lrnGEVIKpAiBtCERpWAlJhYBrR5ApPp6jSoM+Zk6YfswUSg2YR7c4Sg==
------END CERTIFICATE-----
diff --git a/ci/tsqa/files/header-rewrite.config b/ci/tsqa/files/header-rewrite.config
deleted file mode 100644
index 4a06c96..0000000
--- a/ci/tsqa/files/header-rewrite.config
+++ /dev/null
@@ -1,13 +0,0 @@
-cond %{READ_REQUEST_PRE_REMAP_HOOK}
-cond %{PATH} /^.*addcookie$/ [AND]
-add-cookie testkey testaddvalue
-
-cond %{READ_REQUEST_PRE_REMAP_HOOK}
-cond %{PATH} /^.*rmcookie$/ [AND]
-rm-cookie testkey
-
-
-cond %{READ_REQUEST_PRE_REMAP_HOOK}
-cond %{PATH} /^.*setcookie$/ [AND]
-set-cookie testkey testsetvalue
-
diff --git a/ci/tsqa/files/key.pem b/ci/tsqa/files/key.pem
deleted file mode 100644
index fddcacb..0000000
--- a/ci/tsqa/files/key.pem
+++ /dev/null
@@ -1,28 +0,0 @@
------BEGIN PRIVATE KEY-----
-MIIEvgIBADANBgkqhkiG9w0BAQEFAASCBKgwggSkAgEAAoIBAQDTwZTrWZHXwk71
-fbS62B6ah55jIrH4tdlhAFzRwrAfNkiJh+iTAKQI16QyNnzsNPb777yUF/c9q1KC
-0Dz/Fqevz5NMNso96Gp0i0MDL17/FiA8HP1Fce4FR47D4I/G3Z5oasbDLrJtbeOd
-7/6+bvfCf5nOV2nAYZfAhABL2UWq2aKzH8N+0vx+HOl+n+4hT8pjfeIyI+kQeLwI
-es6xpESXvzuKkqip/Gz53Uk1Me7Uj7AkqCmk6u3KMXUCNgOatGBE7ysmohpQpL7y
-15XYprPB90+SA3Jqhk7s0I88SNaRunZz7YAlCoJLJmYnreJ2CRGaxpKNHHjm8k85
-T8oVUcu5AgMBAAECggEBANFqt8kNGtPDIW1c9Vh3FcUDbFtkW5e42BM7VZBItv8X
-IyOIWjTPRGpOQN87zc2YD85WaCwZi3TcsswV/szTbeDMK0MLSHVzHZzGgO5scclZ
-62Un0j5Uju1/uCv1MJueXuOq/YjX7LOWIq32Q/u3KKWcpdJP1pDgs0A8C0L3zBNK
-PjxnCO0FvJdcpqajEhtepYyTQAtWm/igWbuFgUcfZ55HTOBfBiLdACh6anbCdDJ8
-f2COFRrKu9Gn9mVyRirbyCa4B3VSj4R+WlKsc3erR2vNiEdJLd9x5OK7ZvMFHTvG
-V4BhWt3ffSBRIaVi0pIpYekWbnXjbqY6zjchiy3ruOUCgYEA6W4yBrbExJmelXCj
-dPOp5Ds/uAYaq9TkRLWzX837swPNh1+XJ9xGNgn4d5DbikN1xSdsJO/1dpwk3Uxg
-qE/tEvA2gip/DaxIcj3PfoPtFyebgZItvs5k97zGw9n0bgqoRAezzUl4Guz4AQVV
-Xz+3gICN1lFhRqxKm7Pt8Kc3D5cCgYEA6DrpLJCzOEd8qlhm6w7UGruBRA+QLACu
-zlqzkf4rw1vaXx4cP8ctoCiVWUIsPI0mD2sQvtXAPT8KzZqh3UCu1zyyochyCuVg
-C3fBQiSDtUb2Uk6u7fNFrn36oN7W/Q+sarJvIIECR1PjEGuT3eJppQgJB/VGUZqa
-OQJyTJPXaS8CgYEAskz8o0o51F3u1wEZqbxw+acUDbGD79qGncEYiUZiSqPN+uhW
-IhlL+/zzsAiS2PKcY4KwRSqRGQ89zVeIwSeD06JuUFC7iaseDz0NX/rPP49+ZaNN
-k+A9GUo1nOW/oco8KvKjMVw8BH0bFlSHmGCn/tyy+pBguEXkGzh9uANRuHMCgYAM
-TZKs2b2k7aSdIbHSIib6g5SFlo18x0x7gjKhOWX4I5WeFGpKtrKkGYJQCEFvs8qg
-ZnusoIZeuEhKPDb3EcYxgPW1vHjOOvirotyKNIUFxYynL6P01z6J0ALHIwcgwQPR
-Y0Kf5jXIsZkF9a0PxD70j0hrM4NWL2qcOpTzmaF/4QKBgFYQVrrI6YBxexKQ4J/m
-tG/OKlxef6mzrctu7RJGxzt9ag1IgOi10BMCIKCW7tfvhzzLuBiJ0imEGe+MYrau
-yIWCOVpmwcSnww8bV/25oqRxduVwZzmtZdUJbNSdiZ7jq4tsV9a8TZXts45veSFQ
-X+HWsoFkRoYLOx96mqN94/ZS
------END PRIVATE KEY-----
diff --git a/ci/tsqa/files/rsa_keys/README.rst b/ci/tsqa/files/rsa_keys/README.rst
deleted file mode 100644
index 9fb6a8d..0000000
--- a/ci/tsqa/files/rsa_keys/README.rst
+++ /dev/null
@@ -1,28 +0,0 @@
-All of these certificates are self-signed and are *not* secure. They are intended
-only for use in testing.
-
-Try to use existing certs if possible rather than generating your own.
-
-# generated using (make sure to set "hostname"):
-openssl req -x509 -newkey rsa:2048 -keyout key.pem -out cert.pem -nodes && cat key.pem cert.pem > keypair.pem && rm key.pem cert.pem
-
-
-## Since we want to verify all of the certificate verification, we need to generate
-## our own CA and intermediate CA
-# Create CA
-openssl genrsa -out ca.key 4096
-openssl req -new -x509 -nodes -sha1 -days 1825 -key ca.key -out ca.crt
-
-# Create Intermediate
-openssl genrsa -out intermediate.key 4096
-openssl req -new -sha1 -key intermediate.key -out intermediate.csr
-
-# CA signs Intermediate
-openssl x509 -req -days 1825 -in intermediate.csr -CA ca.crt -CAkey ca.key -set_serial 01 -out intermediate.crt
-
-# Create Server
-openssl genrsa -out test.example.com.key 4096
-openssl req -new -key test.example.com.key -out test.example.com.csr
-
-# Intermediate signs Server
-openssl x509 -req -days 1825 -in test.example.com.csr -CA intermediate.crt -CAkey intermediate.key -set_serial 01 -out test.example.com.crt
diff --git a/ci/tsqa/files/rsa_keys/ca.crt b/ci/tsqa/files/rsa_keys/ca.crt
deleted file mode 100644
index b0ce838..0000000
--- a/ci/tsqa/files/rsa_keys/ca.crt
+++ /dev/null
@@ -1,30 +0,0 @@
------BEGIN CERTIFICATE-----
-MIIFNzCCAx+gAwIBAgIJAL8yIx0Q66ZXMA0GCSqGSIb3DQEBBQUAMDIxCzAJBgNV
-BAYTAlhYMRUwEwYDVQQHDAxEZWZhdWx0IENpdHkxDDAKBgNVBAoMA0FUUzAeFw0x
-NTA0MTMxODQ5NTNaFw0yMDA0MTExODQ5NTNaMDIxCzAJBgNVBAYTAlhYMRUwEwYD
-VQQHDAxEZWZhdWx0IENpdHkxDDAKBgNVBAoMA0FUUzCCAiIwDQYJKoZIhvcNAQEB
-BQADggIPADCCAgoCggIBANYzN4s+B8KAbPxdpMzoVh+xsgPeauothjQq8tQmViT5
-3bnEf7zb+4Wy/7Y9CLj2CSnf6tv271OVwVQZWlDrmqr6greUePz28j3/sJ/lQ9bR
-aZOWQI3d4rgCy6UdJ6rhD2BYrZVFnIZQ5zVZu3rbUBuPwBuRQdTLOWjzcSguyg2R
-jiJ/W2/IToRjgX27cPPArhJQ2ibwsbtvqecj1lQfT5yg8WEDeeOyYwzfT4VEGm7f
-8Q4qrBKxhdRTF6LhNkVKkOM6Jvvq7ULNpSAh1+zFAfzMpPUt1T+sjObQ0HHMeh0J
-ghwOh8OAqFyMAsNdzFwjz4lSrliTMYoq6JdK0In5FUqlCt5RsKrfxsykhvUb66/R
-+a9uGboEMlce/sZcxSpnDJYOmxrecQYmEaoKhbIcJBrRqYMgyQL9X+JJfsdyKR2V
-CbSV0FjHeybpOwl76QGoZPhRy2e551uqKN0qdQMmfI3ZjZqmN1EuuOcRNKU8r0He
-AOTRZ2BssDfvs/YWgZsKoHqoLIQCGgWw1ZhsK8bhFKKBtBqbyAu995XxhJezbSAg
-57+1Icp8qmCWvCO0zxm5ckCRNICxGolT/0Mi5Cl8hmfbx9Gv4Na/KEcxpKLPy43t
-UUqfCtvGOUE/S6TWleL5YII4mI86fIOHFkAozdeokcF54lhENpcLL3R5ggRiBJ83
-AgMBAAGjUDBOMB0GA1UdDgQWBBTMx2X9hPjXNTOKTSQELEBv4pEHADAfBgNVHSME
-GDAWgBTMx2X9hPjXNTOKTSQELEBv4pEHADAMBgNVHRMEBTADAQH/MA0GCSqGSIb3
-DQEBBQUAA4ICAQCZ+B8wevb1DsA0XsGkBIHrAK2zc4u54nIhVEw/6PnJBBpV5Eha
-rKtamhyeBjKt1267SaoQIWy/os9QlEYmn2AKn7J0rxqokowr0r8jdh4nDDeCGGkb
-g7ieinIpuUr5Unpp+J+9/FXtrX1m5sXuHlMao9eTK86NoXPJgt4z4HQd1ZaEJp5s
-H60PVd93TwcIDQjbsGdpFS7LhtYSx5Np/LmrQj0tnt18AUh1SgVwvtAqiSsyhxFa
-yPBZKIsdbNQkPoaIKQovCg0cRjlRr1XAk+cfRbf8OUmS1JMs1+/b0zX0kk9xynhj
-4CUPxsVy4SnOeg95yPB8BEyvU1uxnflq3QTJsSxcePYte5ni1wx8Vbn7cJusJRYK
-LNaEFq/nkFxAlP4PTkv9mGq7ZYLqwpE9s6rPmJZc37ti0OUmLiVpqk6DtN5x/TD2
-vKeZMupGCWF71kueR4QAClEnDHe6/lKqe7CH3OuY8bA+7N0RNrEqUBJ7qnD6Frcu
-UfmrkZcIj6DWSnpfwL884WoSCkYuyYP/v+PhR5fSao3l7ZB9UQXdXYhx/Kyd3lPZ
-DKSZjOthCm1dblzKLK4VHy0dmAQdIczIXY6ztIKUY8z0poMNiyJEGeYYPf5jjxU4
-Q2u9W/ReEaza6HshFnoka4IZqlfLinWRoAt92rA+nFIShaBBimvc32kHrQ==
------END CERTIFICATE-----
diff --git a/ci/tsqa/files/rsa_keys/ca.key b/ci/tsqa/files/rsa_keys/ca.key
deleted file mode 100644
index d892296..0000000
--- a/ci/tsqa/files/rsa_keys/ca.key
+++ /dev/null
@@ -1,51 +0,0 @@
------BEGIN RSA PRIVATE KEY-----
-MIIJKQIBAAKCAgEA1jM3iz4HwoBs/F2kzOhWH7GyA95q6i2GNCry1CZWJPnducR/
-vNv7hbL/tj0IuPYJKd/q2/bvU5XBVBlaUOuaqvqCt5R4/PbyPf+wn+VD1tFpk5ZA
-jd3iuALLpR0nquEPYFitlUWchlDnNVm7ettQG4/AG5FB1Ms5aPNxKC7KDZGOIn9b
-b8hOhGOBfbtw88CuElDaJvCxu2+p5yPWVB9PnKDxYQN547JjDN9PhUQabt/xDiqs
-ErGF1FMXouE2RUqQ4zom++rtQs2lICHX7MUB/Myk9S3VP6yM5tDQccx6HQmCHA6H
-w4CoXIwCw13MXCPPiVKuWJMxiirol0rQifkVSqUK3lGwqt/GzKSG9Rvrr9H5r24Z
-ugQyVx7+xlzFKmcMlg6bGt5xBiYRqgqFshwkGtGpgyDJAv1f4kl+x3IpHZUJtJXQ
-WMd7Juk7CXvpAahk+FHLZ7nnW6oo3Sp1AyZ8jdmNmqY3US645xE0pTyvQd4A5NFn
-YGywN++z9haBmwqgeqgshAIaBbDVmGwrxuEUooG0GpvIC733lfGEl7NtICDnv7Uh
-ynyqYJa8I7TPGblyQJE0gLEaiVP/QyLkKXyGZ9vH0a/g1r8oRzGkos/Lje1RSp8K
-28Y5QT9LpNaV4vlggjiYjzp8g4cWQCjN16iRwXniWEQ2lwsvdHmCBGIEnzcCAwEA
-AQKCAgEA0Sxc3mYp77+4Lk5IRC3TBMpjW7HU2HCycLlMPu5dC2jSJLoGP+jW275s
-Roudu/nQAwt+b2XaWtaQX88OSp15geR2yE1+RRHmh7LsyYh60gnYPt7olWGMKEPa
-mJg7B30WpfCTOoUrEGNrFcdV9Oi8dt3PLVyRW/tFSf8JjsL6X3u3wGp8YVHLky8U
-4jKsX+zWUF6SWpqMBc1KrsRpZebZuMvWS/W4DypB3e0o26wg4AtifIIhXXPsi+bE
-2zNw6wOhL7S3IyVMowLtcM577OSKR1OU9zTV3YNkaXabR7X1vetuGnX6EGnQf+fe
-PuiXS5dQ8PpD9Y1wQEwcrLnLoiESrvK8zYytZDR4KTlWP6eIhnn/6EyEV13pV7AH
-LQ4ZarRq0A2i9HAPeZuUYZ8YxT5Yhl+CvyzsCwd08e9YGSLKTCmZKYwmVZVOcwsq
-OOB6srHNwSH15lxwf1uHh1zn1QyG29tXlJeEKTqZ64VYxDAHiuXFBrEAFXmwvzw3
-YcuTRkDoxUFNuwdr35lXBpjtYuUDYprODEDnyJC2T+bDo1htczKNlSKLJNZJPsYS
-47C7DFj1S2CGXGM3WuEPV76ge92F42U6F0cGvThnB02D09wUilSWiCeJmhUW9LRD
-N5QofYra1DdJ4N5bBqMwoUafF7fH7qb1Dwq9tQo0qaIP2YR8JTECggEBAPsKRg+j
-IKETzcxlwCIZvAeoMny3srMrRYbqA8UnBDvzd81fOXj/r1PSEfGFKeuRhOqANQ6o
-mowIQibIKcUb6Lc51voWGb5VeRwfLLoMkHZLHcKysJtRwMP+ceRUZCTfxetvptsd
-laalVLxfXzoy/UKrUPtz2V6LtCtB5u77Xucz9GQoqWdHAmFcjlUqFUEXU3wj/J7k
-roS7n++pKfxeA0YhiQHjBj2i0d0W+rX1B78AeS7IbG0nUIxj2yb6OojxLTIhsRox
-CYbmX+7UmLO79rdJ2YAKMWoEC3erHfyGduxWUWVEy0gw4Xgzd0VnbD78iAn8LVbd
-D9dC2bHWmx11UVkCggEBANpunIAKxsU6U6rnMrRm/p3KxdOLPNksxmEg983SG1AW
-sDH/ZSycNYphHB8vQmVsH0DDI//djRbdbx4gCSBInZm6x97nsSeq4zk8ymoHiL34
-KVZcCgDfW+n7cl1DVHCQAdqv295cn2NX4VPaGG0CFyMGU48C1Xo1GnAYAHJC4OiA
-vn+OWMUoRjDNRNvl03zmWpXMcR0DMuKKlnYh/0sHuNtlKVHIVMpubk6xXYKF32Ku
-+nxpYSTyVl/gZWNbxveDELCH9fatGcGidDytEMELvrYOPTAhwGLBfC8b5r1jNF9o
-WRDOy3IV+vBM4m+IZQ6NBsjly7HII4SCvFBHHH9NUw8CggEAfC1uzplgsIz9Rdgn
-HDcinZ8DqlGr4ZjMAZqMVt+f5o/eeQZbhZDkh0/odFHslIwc9WqJ1EBugkorfseQ
-ceIGUWwY/Qgln9Lj35dEJpvEcd9iT0bYuVvNQKYCbHGaP+s5GebW4JhXyGEL80ox
-7rX+NRZNLrT1lyD/9E3bD+fj3/YBM/IxKdckREjmVxZEATiqoUOj2G1CLoIo8QH6
-tM1ETVKVVQuZsK9zpCuTxKH6PO7dAtk9WRkTbP6QD03D2q2CL8QeuNf84G/gkGE1
-T+LwfWXYYs+n9cseaQmKAbn55ZolFTTcYU9cmHrMytYH43hDSr0lKEydY1u8F44S
-mJXJsQKCAQAUjQ+gZGMrLz+r9rColIAkLG3MZ29EJ5hKjyWBceEr+dZ9/b9xIQlQ
-ia5xqKqgjDmsiC+c5SVfH1pTBUSWiv549j/T0wyx5LwYKIYKz8anyO9qtqIiTuGA
-9C1gZPNO292wy5buJtzAJgaHMx/VMbsninLWI7geFVz1auyv02cBuQszSRtFAXMJ
-KGbwIYFyYOHo8iE6T5C8C7n4R16Tmphj2/K1RRnlKdqrALkBjMLlr/zVM7z2Eu7Z
-em1PmdTweJ5bXY9gtAyWUUiKZOYMo6Q/0LslCiflorqiXAerjefhihnHIQ23ICZJ
-8ZHkWHrZkZ8vy58MjP36e6poCyi9OXM1AoIBAQC01zUvApHgYUprHmnsO4ynazao
-DYSLHTJq/VYjH/TjxuXML2xOF72IL/l/e9xN9OiWHAGIda63N7m7j5rnyWsMm8vR
-nUeJlraFDBN4T96Xf3YaNvbZHfuLjBur2q+SIUMdvqZzllRghLaDAf3g9VHtXBWO
-d70FveQS2dImpYp5XhhdOEVCOkMqUuOCu2Gfe8a8K+GoHMTrSD5z5amjzHx6t02d
-4oU9Rr7TZnrkrxL0JapyqLsZr6ZafK26lqqRANNQIX5crUkprKp8HGv7fmqDsdGI
-qTKbYliQ8KjyfSlfj5qBsqhic1RsonNmf/RL5dNevKxxVR7OCzTnN5lHM8Ln
------END RSA PRIVATE KEY-----
diff --git a/ci/tsqa/files/rsa_keys/intermediate.crt b/ci/tsqa/files/rsa_keys/intermediate.crt
deleted file mode 100644
index eacc2b9..0000000
--- a/ci/tsqa/files/rsa_keys/intermediate.crt
+++ /dev/null
@@ -1,29 +0,0 @@
------BEGIN CERTIFICATE-----
-MIIE7zCCAtcCAQEwDQYJKoZIhvcNAQEFBQAwMjELMAkGA1UEBhMCWFgxFTATBgNV
-BAcMDERlZmF1bHQgQ2l0eTEMMAoGA1UECgwDQVRTMB4XDTE1MDQxMzIwMDI0M1oX
-DTIwMDQxMTIwMDI0M1owSTELMAkGA1UEBhMCWFgxFTATBgNVBAcMDERlZmF1bHQg
-Q2l0eTEMMAoGA1UECgwDQVRTMRUwEwYDVQQDDAxpbnRlcm1lZGlhdGUwggIiMA0G
-CSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQDe2tfo88v44Tl9TATixb5qmBobnAy/
-oYpaX2St28qNuAC47ftkFaE+4zZIN8IeOAKkMC29ZVxOhXoNWovu4aa9PXdnmatQ
-M/vezta451JE7lVQK0q6dViGyeevBkumgQ2TD+Kj6R2uH5zHDSSVEWEJIb8rTb5i
-1pA4pF4ZLMBLAoZwrQfH9xjNZWSi7UJ0g1eYwRh5ahjl2SBRxSrH6GEUBCuI7S1o
-AvUvj0aDVXmPJEuyrkvw1u566g7DyQ242SnqdZnHVP17g1YmqCbq6qxipb6YKOke
-LBOL1zMKjdVQ3QAbw7Y7RBFcVUdUvoh4uL+IoWr+A8s99OxUhz2kEXU+gjwJtOOR
-keZGzMo9rA9cProwHC414Q++Ct0YhUAO2vTjEhnEvlJFv8cGRYT/Oifwrxny6KTA
-kC+4gwgrJgWR9DHeL814aTnotRUGLLsZAeo+O0al3/0QlN09XDFstkmn/mgaCmbF
-LN9dqwvg1gwS5Hbd+vdlguhcx5mlaI+jZp29CBwBdkkKVAns/3Tne+KpwJIsdRMp
-es+ajkFEZoOc6GVBrW/BjxQ6JBgQA6R4//eWunbMYfhkNY5l9SS1qZak1j9+qWAX
-JcSQVbUxgRSe01MzIqScc2btB8WJbi/IJp+hcdFLDzKYIolT7mRm8Xu6j3M6YF7E
-UaOuyRqoRiIr/wIDAQABMA0GCSqGSIb3DQEBBQUAA4ICAQCk4HQOq4A9cwmrPVk6
-vqR8CmRYiStM76RmLqX3XeVx1GybfvZzK/WYLcwInmXD4iitQflB9S0Ut0ChuLKo
-klj10wdAv6iNrRMUtmY9w8zV8GSLRHZrOo6Rd0affUNjBy79FaNypmdrydc8+M7L
-pGWKVN4qN5cOs/XLFT2TFk8davnyFOucP7kxWeNiZ38Kh8cAYYkovMpfcEJSrMGS
-musUqvAlPVZXDgBjblVHjZ2dvgRCdYFwrMxo14SALOmM1Hi7oWbX5A8uNdeoq8lB
-mwdUBpdWDm6IgJ2aiufOqBV3Mv6AUysLE+qHdP/lTHIHNc0LinuJK10F/jqbf9uY
-gzETU6HT1gQ3X3noDRB2vMMPJQOx8uQX04dfUx8WOmgwCx1X5Vc8gLhH+JbZz1PZ
-GlWgX5VGiGgLkq+rgQBLOLIe/NAnUCXPG78DttQpWMs8JjxEcgnVjLNZNAaWymAl
-U3JzmbX5UZePwEMjKSjKNDraU3Tuq+QTdPr+W2ilJEsLLPbsenc1QTNsPUv5aI8h
-LaayTP7aWMVg0QFfV1O7+vVz5ej7CO7Be7w57VWGDwBBVm81vDbeFna4RJPk2qAw
-K5wOYak0Z27v+0wBXHaceH0j45fn/lixt7FANv9NhB3krcjrUwUsooMAIsnCKAlK
-nQD8ySYdm+OGchPeRVW+MH8FPw==
------END CERTIFICATE-----
diff --git a/ci/tsqa/files/rsa_keys/intermediate.key b/ci/tsqa/files/rsa_keys/intermediate.key
deleted file mode 100644
index 561765f..0000000
--- a/ci/tsqa/files/rsa_keys/intermediate.key
+++ /dev/null
@@ -1,51 +0,0 @@
------BEGIN RSA PRIVATE KEY-----
-MIIJKgIBAAKCAgEA3trX6PPL+OE5fUwE4sW+apgaG5wMv6GKWl9krdvKjbgAuO37
-ZBWhPuM2SDfCHjgCpDAtvWVcToV6DVqL7uGmvT13Z5mrUDP73s7WuOdSRO5VUCtK
-unVYhsnnrwZLpoENkw/io+kdrh+cxw0klRFhCSG/K02+YtaQOKReGSzASwKGcK0H
-x/cYzWVkou1CdINXmMEYeWoY5dkgUcUqx+hhFAQriO0taAL1L49Gg1V5jyRLsq5L
-8NbueuoOw8kNuNkp6nWZx1T9e4NWJqgm6uqsYqW+mCjpHiwTi9czCo3VUN0AG8O2
-O0QRXFVHVL6IeLi/iKFq/gPLPfTsVIc9pBF1PoI8CbTjkZHmRszKPawPXD66MBwu
-NeEPvgrdGIVADtr04xIZxL5SRb/HBkWE/zon8K8Z8uikwJAvuIMIKyYFkfQx3i/N
-eGk56LUVBiy7GQHqPjtGpd/9EJTdPVwxbLZJp/5oGgpmxSzfXasL4NYMEuR23fr3
-ZYLoXMeZpWiPo2advQgcAXZJClQJ7P9053viqcCSLHUTKXrPmo5BRGaDnOhlQa1v
-wY8UOiQYEAOkeP/3lrp2zGH4ZDWOZfUktamWpNY/fqlgFyXEkFW1MYEUntNTMyKk
-nHNm7QfFiW4vyCafoXHRSw8ymCKJU+5kZvF7uo9zOmBexFGjrskaqEYiK/8CAwEA
-AQKCAgBagZZeTWTxVsb6U/1H+/cxY0R3IhErYnfF7Cf/U9wXYjso373RD9fEqpJJ
-EhwMGcM42zg4SwoJ+btv4O4jvhDxmhz8PjSNBg+slWQvBAMta33KaUqYH0AsvaMS
-OgRPQuo4Z6Mr3mjnZn9Nd9D7mWtHQiVZeOFxUqKP3nE42CvgSs4+xIb8dyXjhOIy
-KRlsKEtTBljiNmyWLHArxV9ygLWsY2Uq3ugp7cmV3yJMBFKyB5OWpaLB1QhVcuk8
-KlMgV1HmnowtoB6yIszCNlhX36bTCW02bqb+Ufg+Os/H4YJYrOh2Xi2MNEC4twmZ
-KShTnvRqkOPa9b99EhNI4QPvtgde8XzZ15etuLG5Jg1McjJi6EK5AQx6NAfKWSpd
-lEryShnePd6Tx8taBsBG29ibPfAGuH/enhhgHjs2Tw4WY+fHq0laH3H0NI9EpV80
-ygAynoYfCeyUJiTpv9/dq49V+lJ+SJ5Wpc9kGRGxcMlIvCUETgiSHkz9TOmhb15H
-qX63B+AfMDwLSFwhnWJydPslXNqNH+ACzRAr0vSFYtfAs1I537JGKAJT3eZOt3lg
-lfXrEe5HKSxANx1qUvFIyRBFZYVWCb3gXvfU8fKGLM2xDuRBaNsEtlQzFuAN6lXd
-iDe9+upHJHRiAKb3xtM7Gfjp9UzffXZjwxmg+p2w5wHQKVFbgQKCAQEA9hFafDVH
-RwchKEAzGA+CxVIIA/1LIq0ZenOZJGX+px2nP5C0L0DV4L66c+r1b8zzt7+dooA/
-f0UQg++a/DzHCaM4SB0GAhzeHndq1P+1/9rFabOJmWpkeTCvkTW6Onq0yjOoYhnI
-7DeoKrK8jxZGIRUV0bOLIKro3w764SnjAwNgdfi0MVDdEAgMn/ZM9ZetoEVeTY7K
-saq/Gz/N/sTO/qv13ARqCxIzQr578pXP50Z0h9l9ln1DWaVoqa9IhpkMlPzrlmU8
-8ZVJIIofOUcvSq8366LmdFJ2ftIgFkYfAT5iVyoauikeGkWTWbKCxqrHz9R6HvLi
-9LguykeBeoml2QKCAQEA59mgyivkaYBolozJkD2C4mJfnQZB6znMzDsccDxqBvDu
-L6vAZYaIFsvW5df9G7uqKsQ4NTlfr1Ea2vdFHxs+nSO3v7cHdj0KFQBO2LkIr31z
-lfvGm73+eK+7d0tmD2L9GZ0swCxDzt94iT9tUuiPj8f3CEOCuUbHdlszHE3Q8jFD
-GSW688v9nxKTR0eQhYY248Var67puHF+CuzOjlgbr+W2+21h0wLAfu9Qqwp+2ry9
-8S1qJ8Mi2y7SGvjxMpWbMBA7O1/sCcrcuHpsata+RwowctyvqEEfaKyLmlfxJGCI
-wPoTHwLuoIMjLQJ+OxAm5URnhbKhsAjcDgi2zveBlwKCAQEAxLaKx9Ev8jBY6Xyp
-XArKWESD8+yCLG6Fd8cCHn8LXT3vfnmIEl6anNjc5d5n58DI9ZRRyJ8OJAhqc48R
-L6TG2YWKcNwC+Z1qVKDS3wSt0qRqPV4yGltbhybMtCFnh2ihLySs7//9CBpWbgwF
-gb4kwj3A+6u1BaCcGfY3ydlaigYhDy6LnwEuOKq2rQqR66QeQYozIX2NvQrrTDVt
-0MY1VJLUMde1jrQ2Fp2BKSVq11ETx6avJ6dsODZrvXtLV47y6Ahprgmw9tCJbWH+
-JCQsQmBhLBdGdKeX4zrIPAZCsxPUOiqGw1wrnIUSjxqOQZQ1uIf8ONGjbk/v1/Xi
-JLv1wQKCAQEAln5hLFoJTaIYQYDpZUNILgKE5bwmFbXTBc5oy0Gr4Q2Kzk7B+CS3
-OXTe7RqiJNpPvqrXgVTYk0gmEnPm3iYlIoMIxtzbbxh37uHgTDTvOlpIKNbhOD6/
-az9GhEzg1qP+fh3T6nnRGftcllohcGucpEu8QhTwSatz1ZOlPX4VXuAzGaOwEoga
-/KJmDyKY4NMZ1gdIsjjrZNnmYtkLysHOVwLZH6MEmJ90q/BTgHKznPBeqqo7+ctk
-WLmvj+p/RcJulWgzynqdEE4pr2Vn8oGpyRsID8bIDoMXDC7T/z+OO3qdygWJW9vf
-YTk+H/06SsRVOwSH3fTxlv5pOILXhsiJyQKCAQEAvSS36aam59KHJP8MG0Xm1OId
-cXSQqC1TUFt9mfIfiNdlmQWqlX/FWQSKo3B/ufJVChSu7Vy4pWd2FKfqhDsVrJ/W
-6U1U7QJdqsYMN8yWGHEC9riBFl/Pu6vaCluWm/qANzoSMaLB1oMy4SCxGui+6yxN
-YktI6E+fRTzPdj/1hznyqicnmOBarzUKItfkwyh6fyIgfaFD9N79CmjZWLpKf16Y
-lp6hmCR6BAErj0jjKZjsC51DfAs5fnnA6csZxWtGF3HJnIqz/Fdjsb2R+RNlWQGX
-2pZ8hMV0OvEajK66ApbqQMeJzQwGi91Xr6w1z+EvAr6H6jECE+daY2GDtJ7V5Q==
------END RSA PRIVATE KEY-----
diff --git a/ci/tsqa/files/rsa_keys/www.example.com.pem b/ci/tsqa/files/rsa_keys/www.example.com.pem
deleted file mode 100644
index 4bc273d..0000000
--- a/ci/tsqa/files/rsa_keys/www.example.com.pem
+++ /dev/null
@@ -1,52 +0,0 @@
------BEGIN PRIVATE KEY-----
-MIIEvgIBADANBgkqhkiG9w0BAQEFAASCBKgwggSkAgEAAoIBAQCrS3J3uL2MNr1Q
-9zL7ODukw8UOHN4AwuWsNSDJzaswrgxtFO3VfJbCfo7CUtojoJY39783m3HnLhPA
-cFxfsSgQ0Z8TdUZYtq2I1p/eEp/A6kdQffHS4To0ueYQ8r1I6pMJTniaDi8ICD0d
-837WwbUUaxx8IhzaFNPrvSdhJb1LGPxj8YvfKvHF9rkwqpJSEAXFCKTa/H0i8wb8
-h3u4cXZmYN6aooai3SY1KGlWZtAfbgTlMMtvB3ZE3JsNNwbL4gfzxYsfXTW9QUZ2
-kT3irmB80koQjzDiW6MpxmLpvDD/NpQWSiR9TDZYCJtACwWyoxqo8gHZVqsF/rkK
-yqkg2cbJAgMBAAECggEAf/ZGtsUdZGdoGdnxDda+R6GvzZEnDy6JYJH3womP/zem
-NL7TxQ3jmbvtbaFzL/ZBAeJjyGipOGglfTby6tFu+tF9oo2TVaZyEK00lDMZgIYD
-bFAJnN2AG+9bvQF5AcWqveMPGRbLb5aoAX3rHQdr/KrfhqP9JbU1cv/FMT9+H2B7
-Spty/WJYOL6AhzN4H4YHJzfhn2e0iMfA3usu1hha84FWWAR3+Z4sphSCtY+edumT
-ygES/j5TAX7nu5Eyqe2L4natuDLXiLEbKEpqyfAg1SmTDqAiHrMtWkWv/e+tdTs8
-+DE+wPVhRCjVyjejjvsgDV/d9B805bbpq7M4eyIh+QKBgQDhHPcd+b5KZdXU/PiC
-GQ/5C9elW35t7D8gaCzLAzoxW7B/PnTmVyK+QPBsxaUNg87BxB0TTssNUulSY2nk
-TVemOe57xdJKiX7nOG+9vIZFGxlzqywMz0o6kZe3No8PAcp91K7Xr3RkXdHHwyZY
-+NDiUIeMptEnoeEbFZcv+YQ+8wKBgQDCzB/5tD6D8uGKfsiakMs5HGEsYyJNP2b5
-UQ6e1spFg1noMfc5Vj+Av5lF0AE6tELEvJe0J8z2rA9zfHC6JkY/zOGMXrILF0S7
-KSTcxfBUqeE0OUJMkDNy61lRGs5ISul0qcGU473EsBEaxi999GcqzLrB5V4CHZlJ
-EUam9SSqUwKBgQCVkcE/UWh11iO1WD9lcXGDb7LgU2I1dvqadZ0NZh+MG/exE7Zo
-NQ0Ii+0y2D9KM4F0jPEkmv2e5K/R5eu9nQXXlDY4Vr/adnCzAHR+BHzR/adziw/B
-kxkmwQWk3cM/nVkFMgLZm+IhrZRsveUEyI1BUXA+q7fcNVpzvGyvm4GasQKBgEW9
-XMlCLYuB3ht+ToV/xzIYJfYFO9eaFly2F1zomxwN7ZdCpDcD2NJYRiCHWplQxgK3
-Xjyiby/048c9ywHqCAZ5bFqb4HQ2DWZQUaE0wFkfRMA0q7bLfY/sEFsIFMgvAavB
-xstuSZdsTYNfZstaP8FD8KzQWDq7rBBLvhax90F/AoGBANNhkbNxWiUJX/+6VtRj
-u7msBgrUpYQtLkyY+13Ry8cdf+8w1die0LZ4unYjIcAS1ro+XGOc0GASc6pb5dYG
-X+RxTyZzoNazbC6JEsFx9IJLn/L0/8jsg368m1f0Dkptd2LzrLsw2zuY6wm8DrLH
-Re4GALck6zlT+rZNLuN13p5Z
------END PRIVATE KEY-----
------BEGIN CERTIFICATE-----
-MIIECTCCAfECAQEwDQYJKoZIhvcNAQEFBQAwSTELMAkGA1UEBhMCWFgxFTATBgNV
-BAcMDERlZmF1bHQgQ2l0eTEMMAoGA1UECgwDQVRTMRUwEwYDVQQDDAxpbnRlcm1l
-ZGlhdGUwHhcNMTUwNDEzMjAwNDA3WhcNMjAwNDExMjAwNDA3WjBMMQswCQYDVQQG
-EwJYWDEVMBMGA1UEBwwMRGVmYXVsdCBDaXR5MQwwCgYDVQQKDANBVFMxGDAWBgNV
-BAMMD3d3dy5leGFtcGxlLmNvbTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoC
-ggEBAKtLcne4vYw2vVD3Mvs4O6TDxQ4c3gDC5aw1IMnNqzCuDG0U7dV8lsJ+jsJS
-2iOgljf3vzebcecuE8BwXF+xKBDRnxN1Rli2rYjWn94Sn8DqR1B98dLhOjS55hDy
-vUjqkwlOeJoOLwgIPR3zftbBtRRrHHwiHNoU0+u9J2ElvUsY/GPxi98q8cX2uTCq
-klIQBcUIpNr8fSLzBvyHe7hxdmZg3pqihqLdJjUoaVZm0B9uBOUwy28HdkTcmw03
-BsviB/PFix9dNb1BRnaRPeKuYHzSShCPMOJboynGYum8MP82lBZKJH1MNlgIm0AL
-BbKjGqjyAdlWqwX+uQrKqSDZxskCAwEAATANBgkqhkiG9w0BAQUFAAOCAgEAGrOo
-IRDUjxt65cBR9OZSXRdnL6szAMuNHWlK0MfVtTATWXDKU9S3KjK6seo+ebyaqt1J
-nlyUZ79n6+vU5uSIDANpYQ5Z1DuV5NM2V9o2QiRqExwfgpGUcAXAi0lQ79eA2kzi
-cDgDIpbEAJTFP5/uinaRA9H4KqqfMg5m34tu44A01brb2h/czPOWxD89mKKbtS9H
-ODPkDkq3wTUG/F0RQvfFC6Na8IWkW0jijDBxuFeSbRV00GH3/wpMBcxDuIcKBJcy
-tFrXjCFKzop7djU7OuxEnqQdlgiHgQsszjnLP0k5Lz9CrNG7W+zqmYsvO6s6a94Z
-8lHuwl9GAS/IFQS+c+PsPT7uxgSfbdFHWlmOv1+p/PsPaAQ4Hu/ugga8AjMYoyHg
-V6LBCTbUK7aA3lnu6+EW3qpGve6Z2H1D+B5V8ZXLuA6ooIS80CN9xw6jFcAXcUv8
-pNw/sJDnErzRbxsOPKeLl2EjJ/1/MsQf5DNp3xPFyhv5l3oOxodICEr4eeudGmAW
-OGp21xqo7i3K8YQ6GDMPF6RVX4mOCxY5L9qf+VDLYx8AV9gFZ+VWG8we7jyruqxE
-DwetsfCtwXo5gho9p+K8VHA7nWukydBNiekPFD6S6gBu0vMZxIfW/AKolWgxmyPz
-zZhR8034yoSR6qxuh+as+JpXmw+3MypZ5G/1S54=
------END CERTIFICATE-----
diff --git a/ci/tsqa/files/rsa_keys/www.test.com.pem b/ci/tsqa/files/rsa_keys/www.test.com.pem
deleted file mode 100644
index 5a0cfa7..0000000
--- a/ci/tsqa/files/rsa_keys/www.test.com.pem
+++ /dev/null
@@ -1,52 +0,0 @@
------BEGIN PRIVATE KEY-----
-MIIEvgIBADANBgkqhkiG9w0BAQEFAASCBKgwggSkAgEAAoIBAQDUiFw0p0JOfm/G
-0YHivkd5v5Xu5tkBWETu9NgKLr7MkEBeqb1fjkm8Gd1IsndoYh0R/tkRzdE6O+lN
-WjMgEuCtz+5zblBQ9xDMwAKI+1YhudqrwIxqXBzpyvAAZwU5EHftog/WiEDvJPM0
-XEQsx6142kgVR5NfNX6HWHOL8H86j7Yfbdd0Knu0Qv9tulC8aeBbZ+pKU0/cBCVi
-ljr8OFdrCZu1EkKIat3oBjdbEF4boh4gNSsxbX+89uW4SZYR/G4xEX4VZJLMsloG
-YOkcOLTV90+VDbbdrZsnmgQgpKBlp2NBdSx7MZQRU5De3PMBzo2uoIvmwXS9ZxtT
-Lr+/dpxZAgMBAAECggEANh1uVN3NrUzWSypnRwOqEV7t30GaOZRvIOTo6VbTsCR+
-r1vK4zzIm4N+a5c9fi+VNVLNlJHyV0CP++keoWkNGlSaY3vQKX1vIqM1Qgm0+atn
-+Vlyp1ZC6miIyaFxnAEMeE5OeBKDbiDbaBaiKUDCc8Yomnp6FMD7MZ0c9qHK027z
-DL0kYjxjVgYiDnE1fJ1ZV466IcyDnGDky2ebjjvvTI7c55tbrEc+VRZdC5Cn5Yb/
-desjXGAb5snEbdAiNqCgIG9bLw3hHWsn0wCkUPRcEMoSZ73taak54vC7cPda7/D5
-aetzsNQWCMZC5NZ74JD5kyC3xBr7TAarQ5OXsJ0DMQKBgQD8GTQdc2MHvA+4nCpp
-0Xy3J7gOCI63FWETZgw22sboqk1toF/LFQHYY40EdvEkFsqc6zTm09QK8y8G48sC
-j8pvskhO2M9EgLegzPQv6NY0pTqltI0Ye7w9I3FTKNZIJW+XokDEFFqu+lXqf80i
-BRmoUrltoS8L5XB/z5GoNMdk7QKBgQDX0mZSYdjPgTDWDSTCdEOcGB4bjAZzXDTu
-ukYhri0vuStZ51giAWUlbBnN/hlvln5bULqZFnB5svFRujTIwwevxzhSl45aiNl1
-vE8zsRS0bNeNyjjF6HX0HOEuAQtre/k+WHvEH3mnFR1Zngwbrt4CJyuadlCmj7yw
-jv/DVIyznQKBgAbmobiUqgdSLJP/ImIXK/TPj4hCz7VPToL7biYqQvunfcsccsLa
-ZlyIDRosL1mvjghRn/cZoVpTYdwsbCg7y2zXUodmA/Z6F4y9T4noM8TpKPvUP3CG
-IpcB215NZeA/thhOhrtXW0wi6isrKHBf913WNeE8Yk9PDo9RHUmfeD3ZAoGBAJGn
-t9LFopN4t0LfH/30hWSlijxBJmFYy4iKQqacbHaW28ETNxHMKz00Vb4GTZhX0vNB
-6o1C7anUsLTdnJ4ZsehZ5ZMoIbTMQycIbdOPIVAbXOaeoe4/UsvrabWoktJ5mt8O
-zIiyTWIMCADhf353Z/HACdd3HjsrKsdl2wsy1rqpAoGBAOaNsxoyw/BIn/wvkQRs
-YyYXLb8zECO17ad4M+aFsnf7yLY8i3k80JRfjqxis/yrePNuVKHiZYgEvLNBMdJi
-j3YSMgXHYSgYti73+zBcy1uVVlUR5Q2HnihFX5Ho1IAQbC+TXzUCnLOEoR/IIHIz
-+qWsoHgJD98ie3cjys0WujpH
------END PRIVATE KEY-----
------BEGIN CERTIFICATE-----
-MIIEBjCCAe4CAQEwDQYJKoZIhvcNAQEFBQAwSTELMAkGA1UEBhMCWFgxFTATBgNV
-BAcMDERlZmF1bHQgQ2l0eTEMMAoGA1UECgwDQVRTMRUwEwYDVQQDDAxpbnRlcm1l
-ZGlhdGUwHhcNMTUwNDEzMjAwNDE0WhcNMjAwNDExMjAwNDE0WjBJMQswCQYDVQQG
-EwJYWDEVMBMGA1UEBwwMRGVmYXVsdCBDaXR5MQwwCgYDVQQKDANBVFMxFTATBgNV
-BAMMDHd3dy50ZXN0LmNvbTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEB
-ANSIXDSnQk5+b8bRgeK+R3m/le7m2QFYRO702AouvsyQQF6pvV+OSbwZ3Uiyd2hi
-HRH+2RHN0To76U1aMyAS4K3P7nNuUFD3EMzAAoj7ViG52qvAjGpcHOnK8ABnBTkQ
-d+2iD9aIQO8k8zRcRCzHrXjaSBVHk181fodYc4vwfzqPth9t13Qqe7RC/226ULxp
-4Ftn6kpTT9wEJWKWOvw4V2sJm7USQohq3egGN1sQXhuiHiA1KzFtf7z25bhJlhH8
-bjERfhVkksyyWgZg6Rw4tNX3T5UNtt2tmyeaBCCkoGWnY0F1LHsxlBFTkN7c8wHO
-ja6gi+bBdL1nG1Muv792nFkCAwEAATANBgkqhkiG9w0BAQUFAAOCAgEARQSyOqxM
-ecr1SvIu65yZbOPq29343KewRs39ZbjsEbmm5SMdFs7asWHtbD6iiU3mPzqAG0Y3
-i+S98J7xwSvAnWERVNzWhymCu7MQ/mKM9WZWDRGUshFgaYpWDqjw2a/qVC54f/Ye
-OaeDqzWc96Ib0khZdE+IyqpLdclxagVHv0cJOQwqhKOkIDQGEeBTc8AA/luOnC8d
-tE9s8IwTmGpZPYY+kwGVbaLKPanONGDiZM5IyZbBgb9Dq3wL/5DXvQApid37BzHJ
-ceT/gKDQljXOSWacxCPUSNb6aut5ivfbd9w7kXdTZL9UcS+FGPNXQ2z1yu3VaqJV
-MTSfSW5KUHKVLwDsp9hvBpid8S3TpQLeGt68wXoHxvh5PMnsgdA4JxsOTTwKP/gE
-rYhockBGuftKOaRqlRn4+n/nSfLogYoD+32S6ZMBJpPuMBXODiezsP+eAb+wqrV7
-4tiKJC70YNVL7XMdmsDtxj8lcY+aouREnd2+Iutr+YrCM5ZIOKAq57Ib4qTNV3Is
-F0KDEHRBpiS9hcGYzhg39Dovc6RHc6QRqKVrfZfE3jKXfCtefcqceIsh3jH51ONI
-sudX6SOv76PMjnAj0uqF8Kw6YVzLO/MGbAyGilIXYc18GdRWL4gqj9Z9BiLuNcZU
-8AhkHaBWKOHEtVZ8ueEkRBS3I0JZZ8ZKlTM=
------END CERTIFICATE-----
diff --git a/ci/tsqa/nosetests b/ci/tsqa/nosetests
deleted file mode 100755
index 7486f4d..0000000
--- a/ci/tsqa/nosetests
+++ /dev/null
@@ -1,30 +0,0 @@
-#! /usr/bin/env bash
-
-# 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.
-
-set -e # exit on error
-
-TSQA=$(cd $(dirname $0); pwd)
-
-cd $TSQA
-
-. ./virtualenv/bin/activate
-
-./virtualenv/bin/nosetests \
- --with-xunit \
- --nocapture \
- "$@"
diff --git a/ci/tsqa/requirements.txt b/ci/tsqa/requirements.txt
deleted file mode 100644
index 0aa7ecf..0000000
--- a/ci/tsqa/requirements.txt
+++ /dev/null
@@ -1,9 +0,0 @@
-# requirements for the python virtualenv
-
-# TODO: pin a specific version
-https://github.com/apache/trafficserver-qa/archive/master.zip
-pyyaml
-pyOpenSSL
-# TODO: can't do python_version in requirements.txt files
-#hyper; python_version >= '2.7'
-dnslib
diff --git a/ci/tsqa/tests/helpers.py b/ci/tsqa/tests/helpers.py
deleted file mode 100644
index 5bc45ce..0000000
--- a/ci/tsqa/tests/helpers.py
+++ /dev/null
@@ -1,38 +0,0 @@
-# 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 os
-import tempfile
-
-import tsqa.environment
-import tsqa.test_cases
-import tsqa.utils
-
-unittest = tsqa.utils.import_unittest()
-
-
-# TODO: check that the given path is relative
-def tests_file_path(path):
- '''
- Return the absolute path to a file with relative path "name" from tsqa/files
- '''
- base = os.path.realpath(os.path.join(__file__, '..', '..', 'files'))
- return os.path.join(base, path)
-
-
-class EnvironmentCase(tsqa.test_cases.CloneEnvironmentCase):
- '''
- This class will get an environment (which is unique) but won't start it
- '''
diff --git a/ci/tsqa/tests/test_body_factory.py b/ci/tsqa/tests/test_body_factory.py
deleted file mode 100644
index 2842a6f..0000000
--- a/ci/tsqa/tests/test_body_factory.py
+++ /dev/null
@@ -1,73 +0,0 @@
-'''
-Test body_factory
-'''
-
-# 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 os
-import requests
-import logging
-import random
-import tsqa.test_cases
-import helpers
-
-log = logging.getLogger(__name__)
-
-
-class TestDomainSpecificBodyFactory(helpers.EnvironmentCase):
- '''
- Tests for how body factory works with requests of different domains
- '''
- @classmethod
- def setUpEnv(cls, env):
- cls.configs['records.config']['CONFIG'].update({
- 'proxy.config.body_factory.enable_customizations': 3, # enable domain specific body factory
- })
- cls.configs['remap.config'].add_line(
- 'map / http://www.linkedin.com/ @action=deny'
- )
- cls.body_factory_dir = os.path.join(cls.environment.layout.prefix, cls.configs['records.config']['CONFIG']['proxy.config.body_factory.template_sets_dir'])
- cls.domain_directory = ['www.linkedin.com', '127.0.0.1', 'www.foobar.net']
- for directory_item in cls.domain_directory:
- current_dir = os.path.join(cls.body_factory_dir, directory_item)
- try:
- os.mkdir(current_dir)
- except:
- pass
- fname = os.path.join(current_dir, "access#denied")
- with open(fname, "w") as f:
- f.write(directory_item)
- fname = os.path.join(current_dir, ".body_factory_info")
- with open(fname, "w") as f:
- pass
-
- def test_domain_specific_body_factory(self):
- times = 1000
- no_dir_domain = 'www.nodir.com'
- self.domain_directory.append(no_dir_domain)
- self.assertEqual(4, len(self.domain_directory))
- url = 'http://127.1.0.1:{0}'.format(self.configs['records.config']['CONFIG']['proxy.config.http.server_ports'])
- for i in xrange(times):
- domain = random.choice(self.domain_directory)
- headers = {'Host': domain}
- r = requests.get(url, headers=headers)
- domain_in_response = no_dir_domain
- for domain_item in self.domain_directory:
- if domain_item in r.text:
- domain_in_response = domain_item
- break
- self.assertEqual(domain, domain_in_response)
diff --git a/ci/tsqa/tests/test_cache_generation.py b/ci/tsqa/tests/test_cache_generation.py
deleted file mode 100644
index 5e9a39c..0000000
--- a/ci/tsqa/tests/test_cache_generation.py
+++ /dev/null
@@ -1,159 +0,0 @@
-'''
-Test the cache generation configuration
-'''
-
-# 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 os
-import subprocess
-import logging
-import requests
-import random
-import uuid
-import time
-
-import helpers
-import tsqa.test_cases
-import tsqa.utils
-
-log = logging.getLogger(__name__)
-
-
-class TestCacheGeneration(helpers.EnvironmentCase):
- '''
- Test the cache object generation ID.
- '''
-
- def _fetch(self, path):
- url = 'http://127.0.0.1:{}/{}'.format(
- self.configs['records.config']['CONFIG']['proxy.config.http.server_ports'],
- path
- )
- log.debug('get {}'.format(url))
- return requests.get(url, headers={'x-debug': 'x-cache,x-cache-key,via,x-cache-generation'})
-
- def _dump(self, response):
- log.info('HTTP response {}'.format(response.status_code))
- for k, v in response.headers.items():
- log.info(' {}: {}'.format(k, v))
-
- def _ctl(self, *args):
- cmd = [os.path.join(self.environment.layout.bindir, 'traffic_ctl')] + list(args)
- out, _ = tsqa.utils.run_sync_command(
- cmd,
- env=self.environment.shell_env, stdout=subprocess.PIPE, stderr=subprocess.STDOUT
- )
- return out
-
- @classmethod
- def setUpEnv(cls, env):
-
- cls.configs['plugin.config'].add_line('xdebug.so')
-
- cls.configs['remap.config'].add_line(
- 'map /default/ http://127.0.0.1/ @plugin=generator.so'
- )
- cls.configs['remap.config'].add_line(
- 'map /generation1/ http://127.0.0.1/' +
- ' @plugin=conf_remap.so @pparam=proxy.config.http.cache.generation=1' +
- ' @plugin=generator.so'
- )
- cls.configs['remap.config'].add_line(
- 'map /generation2/ http://127.0.0.1/' +
- ' @plugin=conf_remap.so @pparam=proxy.config.http.cache.generation=2' +
- ' @plugin=generator.so'
- )
-
- # Start with cache generation turned off
- cls.configs['records.config']['CONFIG']['proxy.config.http.cache.generation'] = -1
- # Wait for the cache so we don't race client requests against it.
- cls.configs['records.config']['CONFIG']['proxy.config.http.wait_for_cache'] = 1
- cls.configs['records.config']['CONFIG']['proxy.config.config_update_interval_ms'] = 1
-
- def test_generations_are_disjoint(self):
- """Test that the same URL path in different cache generations creates disjoint objects"""
- objectid = uuid.uuid4()
-
- # First touch is a MISS.
- ret = self._fetch('default/cache/10/{}'.format(objectid))
- self.assertEqual(ret.status_code, 200)
- self.assertEqual(ret.headers['x-cache'], 'miss', msg=ret)
- self.assertEqual(ret.headers['x-cache-generation'], '-1')
-
- # Same URL in generation 1 is a MISS.
- ret = self._fetch('generation1/cache/10/{}'.format(objectid))
- self.assertEqual(ret.status_code, 200)
- self.assertEqual(ret.headers['x-cache'], 'miss')
- self.assertEqual(ret.headers['x-cache-generation'], '1')
-
- # Same URL in generation 2 is still a MISS.
- ret = self._fetch('generation2/cache/10/{}'.format(objectid))
- self.assertEqual(ret.status_code, 200)
- self.assertEqual(ret.headers['x-cache'], 'miss')
- self.assertEqual(ret.headers['x-cache-generation'], '2')
-
- # Second touch is a HIT.
- ret = self._fetch('default/cache/10/{}'.format(objectid))
- self.assertEqual(ret.status_code, 200)
- self.assertEqual(ret.headers['x-cache'], 'hit-fresh', msg=ret.headers['x-cache'])
- self.assertEqual(ret.headers['x-cache-generation'], '-1')
-
- def test_online_cache_clear(self):
- """Test that incrementing the cache generation acts like a cache clear"""
- objectid = uuid.uuid4()
-
- # First touch is a MISS.
- ret = self._fetch('default/cache/10/{}'.format(objectid))
- self.assertEqual(ret.status_code, 200)
- self.assertEqual(ret.headers['x-cache'], 'miss')
-
- # Second touch is a HIT.
- ret = self._fetch('default/cache/10/{}'.format(objectid))
- self.assertEqual(ret.status_code, 200)
- self.assertEqual(ret.headers['x-cache'], 'hit-fresh')
-
- # Now update the generation number.
- timeout = float(self._ctl('config', 'get', 'proxy.config.config_update_interval_ms').split(' ')[-1])
- generation = random.randrange(65000)
- gencount = 0
-
- self._ctl('config', 'set', 'proxy.config.http.cache.generation', str(generation))
- self._ctl('config', 'reload')
-
- for _ in xrange(5):
- if gencount == 0:
- log.debug('waiting {} secs for the config to update'.format(timeout / 1000))
- time.sleep(timeout / 1000)
-
- ret = self._fetch('default/cache/10/{}'.format(objectid))
- self.assertEqual(ret.status_code, 200)
-
- if ret.headers['x-cache-generation'] == str(generation):
- if gencount == 0:
- # First time we see the new generation, it should be a miss.
- self.assertEqual(ret.headers['x-cache'], 'miss')
- else:
- # Now the previous hits should become misses.
- self.assertEqual(ret.headers['x-cache'], 'hit-fresh')
- else:
- # Config has not updated, so it should be a hit.
- self.assertEqual(ret.headers['x-cache'], 'hit-fresh')
- self.assertEqual(ret.headers['x-cache-generation'], '-1')
-
- gencount = gencount + 1
-
- self.assertNotEqual(gencount, 0, msg='proxy.config.http.cache.generation never updated')
diff --git a/ci/tsqa/tests/test_chunked.py b/ci/tsqa/tests/test_chunked.py
deleted file mode 100644
index 1a68614..0000000
--- a/ci/tsqa/tests/test_chunked.py
+++ /dev/null
@@ -1,199 +0,0 @@
-'''
-Test chunked request/responses
-'''
-# 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 requests
-import time
-import logging
-import json
-import uuid
-import socket
-
-import helpers
-
-import tsqa.test_cases
-import tsqa.utils
-import tsqa.endpoint
-
-log = logging.getLogger(__name__)
-
-import SocketServer
-
-
-class ChunkedHandler(SocketServer.BaseRequestHandler):
- """
- A subclass of RequestHandler which return chunked encoding optionally
-
- /parts/sleep_time/close
- parts: number of parts to send
- sleep_time: time between parts
- close: bool whether to close properly
- """
-
- def handle(self):
- # Receive the data in small chunks and retransmit it
- conn_id = uuid.uuid4().hex
- while True:
- data = self.request.recv(4096).strip()
- if data:
- log.info('sending data back to the client')
- else:
- log.info('Client disconnected')
- break
- inc_lines = data.splitlines()
- try:
- uri = inc_lines[0].split()[1]
- except IndexError:
- break
- parts = 5 # how many things to send
- sleep_time = 0.2 # how long to sleep between parts
- close = True # whether to close properly
- if uri[1:]: # if there is something besides /
- uri_parts = uri[1:].split('/')
- if len(uri_parts) >= 1:
- parts = int(uri_parts[0])
- if len(uri_parts) >= 2:
- sleep_time = float(uri_parts[1])
- if len(uri_parts) >= 3:
- close = json.loads(uri_parts[2])
- resp = ('HTTP/1.1 200 OK\r\n'
- 'X-Conn-Id: ' + str(conn_id) + '\r\n'
- 'Transfer-Encoding: chunked\r\n'
- 'Connection: keep-alive\r\n'
- '\r\n')
- self.request.sendall(resp)
- for x in xrange(0, parts):
- self.request.sendall('{0}\r\n{1}\r\n'.format(len(str(x)), x))
- time.sleep(sleep_time)
- if close:
- self.request.sendall('0\r\n\r\n')
- else:
- self.request.sendall('lkfjasd;lfjas;d')
-
- time.sleep(2)
-
-
-class TestChunked(helpers.EnvironmentCase):
- @classmethod
- def setUpEnv(cls, env):
- '''
- This function is responsible for setting up the environment for this fixture
- This includes everything pre-daemon start
- '''
-
- # create a socket server
- cls.port = tsqa.utils.bind_unused_port()[1]
- cls.server = tsqa.endpoint.SocketServerDaemon(ChunkedHandler, port=cls.port)
- cls.server.start()
- cls.server.ready.wait()
-
- cls.configs['remap.config'].add_line('map / http://127.0.0.1:{0}/'.format(cls.port))
-
- cls.configs['records.config']['CONFIG'].update({
- 'proxy.config.http.connect_attempts_timeout': 5,
- 'proxy.config.http.connect_attempts_max_retries': 0,
- 'proxy.config.http.keep_alive_enabled_in': 1,
- 'proxy.config.http.keep_alive_enabled_out': 1,
- 'proxy.config.exec_thread.limit': 1,
- 'proxy.config.exec_thread.autoconfig': 0,
- 'proxy.config.http.chunking_enabled': 1,
- })
-
- def test_chunked_origin(self):
- '''
- Test that the origin does in fact support keepalive
- '''
- self._client_test_chunked_keepalive(self.port)
- self._client_test_chunked_keepalive(self.port, num_bytes=2)
- self._client_test_chunked_keepalive(self.port, num_bytes=2, sleep=1)
-
- def _client_test_chunked_keepalive(self,
- port=None,
- times=3,
- num_bytes=None,
- sleep=None,
- ):
- if port is None:
- port = int(self.configs['records.config']['CONFIG']['proxy.config.http.server_ports'])
- s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
- s.connect(('127.0.0.1', port))
-
- url = '/'
- if num_bytes is not None:
- url += str(num_bytes)
- if sleep is not None:
- if num_bytes is None:
- raise Exception()
- url += '/' + str(sleep)
-
- request = ('GET ' + url + ' HTTP/1.1\r\n'
- 'Host: 127.0.0.1\r\n'
- '\r\n')
- uuid = None
- # test basic
- for x in xrange(1, times):
- s.send(request)
- resp = ''
- while True:
- response = s.recv(4096)
- for line in response.splitlines():
- line = line.strip()
- if line.startswith('X-Conn-Id:'):
- r_uuid = line.replace('X-Conn-Id:', '')
- if uuid is None:
- uuid = r_uuid
- else:
- self.assertEqual(uuid, r_uuid)
- resp += response
- if resp.endswith('\r\n0\r\n\r\n'):
- break
- for x in xrange(0, num_bytes or 4):
- self.assertIn('1\r\n{0}\r\n'.format(x), resp)
- s.close()
-
- def test_chunked_basic(self):
- url = 'http://127.0.0.1:{0}'.format(self.port)
- ret = requests.get(url, proxies=self.proxies)
- self.assertEqual(ret.status_code, 200)
- self.assertEqual(ret.text.strip(), '01234')
-
- # TODO: fix keepalive with chunked responses
- def test_chunked_keepalive_server(self):
- url = 'http://127.0.0.1:{0}'.format(self.port)
- ret = requests.get(url, proxies=self.proxies)
- conn_id = ret.headers['x-conn-id']
- self.assertEqual(ret.status_code, 200)
- self.assertEqual(ret.text.strip(), '01234')
-
- # make sure that a second request works, and since we have keep-alive out
- # disabled it should be a new connection
- ret = requests.get(url, proxies=self.proxies)
- self.assertEqual(ret.status_code, 200)
- self.assertEqual(ret.text.strip(), '01234')
- self.assertEqual(conn_id, ret.headers['x-conn-id'])
-
- def test_chunked_keepalive_client(self):
- self._client_test_chunked_keepalive()
- self._client_test_chunked_keepalive(num_bytes=2)
- self._client_test_chunked_keepalive(num_bytes=2, sleep=1)
-
- def test_chunked_bad_close(self):
- url = 'http://127.0.0.1:{0}/5/0.1/false'.format(self.port)
- # TODO: better exception catch (seems to be ConnectionError)
- with self.assertRaises(Exception):
- requests.get(url, proxies=self.proxies, timeout=2)
diff --git a/ci/tsqa/tests/test_connect_attempts.py b/ci/tsqa/tests/test_connect_attempts.py
deleted file mode 100644
index 5bb41bf..0000000
--- a/ci/tsqa/tests/test_connect_attempts.py
+++ /dev/null
@@ -1,250 +0,0 @@
-'''
-Test Origin Server Connect Attempts
-'''
-# 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 requests
-import time
-import logging
-import socket
-import struct
-import select
-import threading
-
-import helpers
-
-log = logging.getLogger(__name__)
-
-
-def thread_die_on_connect(sock):
- sock.listen(0)
- # poll
- select.select([sock], [], [])
- # exit
- sock.close()
-
-
-def thread_reset_after_accept(sock):
- sock.listen(0)
- first = True
- num_requests = 0
- while True:
- connection, addr = sock.accept()
- num_requests += 1
- if first:
- first = False
- connection.setsockopt(socket.SOL_SOCKET, socket.SO_LINGER, struct.pack('ii', 1, 0))
- connection.close()
- else:
- connection.send((
- 'HTTP/1.1 200 OK\r\n'
- 'Content-Length: {body_len}\r\n'
- 'Content-Type: text/html; charset=UTF-8\r\n'
- 'Connection: close\r\n\r\n{body}'.format(body_len=len(str(num_requests)), body=num_requests)
- ))
- connection.close()
-
-
-def thread_partial_response(sock):
- sock.listen(0)
- first = True
- num_requests = 0
- while True:
- connection, addr = sock.accept()
- num_requests += 1
- if first:
- connection.send('HTTP/1.1 500 Internal Server Error\r\n')
- connection.setsockopt(socket.SOL_SOCKET, socket.SO_LINGER, struct.pack('ii', 1, 0))
- connection.close()
- first = False
- else:
- connection.send((
- 'HTTP/1.1 200 OK\r\n'
- 'Content-Length: {body_len}\r\n'
- 'Content-Type: text/html; charset=UTF-8\r\n'
- 'Connection: close\r\n\r\n{body}'.format(body_len=len(str(num_requests)), body=num_requests)
- ))
- connection.close()
-
-
-def thread_slow_response(sock):
- '''
- Thread to sleep a decreasing amount of time before sending the response
-
- sleep times: 2 -> 1 -> 0
- '''
- sock.listen(0)
- sleep_time = 2
- num_requests = 0
- # poll
- while True:
- select.select([sock], [], [])
- try:
- connection, addr = sock.accept()
- time.sleep(sleep_time)
- connection.send((
- 'HTTP/1.1 200 OK\r\n'
- 'Content-Length: {body_len}\r\n'
- 'Content-Type: text/html; charset=UTF-8\r\n'
- 'Connection: close\r\n\r\n{body}'.format(body_len=len(str(num_requests)), body=num_requests)
- ))
- connection.close()
- num_requests += 1
- except Exception as e:
- print 'connection died!', e
- pass
- if sleep_time > 0:
- sleep_time -= 1
-
-
-def thread_slow_close(sock):
- '''
- Thread to sleep a decreasing amount of time after the request, before closing
-
- sleep times: 2 -> 1 -> 0
- '''
- sock.listen(0)
- sleep_time = 2
- num_requests = 0
- # poll
- while True:
- select.select([sock], [], [])
- try:
- connection, addr = sock.accept()
- connection.send((
- 'HTTP/1.1 200 OK\r\n'
- 'Content-Length: {body_len}\r\n'
- 'Content-Type: text/html; charset=UTF-8\r\n'
- 'Connection: close\r\n\r\n{body}'.format(body_len=len(str(num_requests)), body=num_requests)
- ))
- time.sleep(sleep_time)
- connection.close()
- num_requests += 1
- except Exception as e:
- print 'connection died!', e
- pass
- if sleep_time > 0:
- sleep_time -= 1
-
-
-class TestOriginServerConnectAttempts(helpers.EnvironmentCase):
- @classmethod
- def setUpEnv(cls, env):
- '''
- This function is responsible for setting up the environment for this fixture
- This includes everything pre-daemon start
- '''
- cls.sock_map = {}
-
- def _add_sock(name):
- sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
- sock.bind(('127.0.0.1', 0))
- cls.sock_map[name] = sock.getsockname()[1]
- cls.configs['remap.config'].add_line('map /{0}/ http://127.0.0.1:{1}/'.format(name, cls.sock_map[name]))
- return sock
- # create a socket where we just bind
- _add_sock('bound')
-
- # create a socket where we bind + listen
- sock = _add_sock('listen')
- sock.listen(1)
-
- # create a bunch of special socket servers
- sock = _add_sock('die_on_connect')
- t = threading.Thread(target=thread_die_on_connect, args=(sock,))
- t.daemon = True
- t.start()
-
- sock = _add_sock('reset_after_accept')
- t = threading.Thread(target=thread_reset_after_accept, args=(sock,))
- t.daemon = True
- t.start()
-
- sock = _add_sock('slow_response')
- t = threading.Thread(target=thread_slow_response, args=(sock,))
- t.daemon = True
- t.start()
-
- sock = _add_sock('partial_response')
- t = threading.Thread(target=thread_partial_response, args=(sock,))
- t.daemon = True
- t.start()
-
- sock = _add_sock('slow_close')
- t = threading.Thread(target=thread_slow_close, args=(sock,))
- t.daemon = True
- t.start()
-
- # only add server headers when there weren't any
- cls.configs['records.config']['CONFIG']['proxy.config.http.response_server_enabled'] = 2
-
- # enable re-connects, timeout of 1s, max retires of 3
- cls.configs['records.config']['CONFIG']['proxy.config.http.connect_attempts_timeout'] = 1
- cls.configs['records.config']['CONFIG']['proxy.config.http.connect_attempts_max_retries'] = 3
-
- def test_bound_origin(self):
- '''Verify that we get 502s from an origin which just did a bind'''
- url = 'http://127.0.0.1:{0}/bound/s'.format(self.configs['records.config']['CONFIG']['proxy.config.http.server_ports'])
- ret = requests.get(url, timeout=2)
- self.assertEqual(ret.status_code, 502)
-
- def test_listen_origin(self):
- '''Verify that we get 502s from origins that bind + listen'''
- url = 'http://127.0.0.1:{0}/listen/s'.format(self.configs['records.config']['CONFIG']['proxy.config.http.server_ports'])
- ret = requests.get(url, timeout=2)
- self.assertEqual(ret.status_code, 502)
-
- url = 'http://127.0.0.1:{0}/listen/s'.format(self.configs['records.config']['CONFIG']['proxy.config.http.server_ports'])
- ret = requests.get(url, timeout=2)
- self.assertEqual(ret.status_code, 502)
-
- def test_die_on_connect_origin(self):
- '''Verify that we get 504s from origins that die_on_connect'''
- url = 'http://127.0.0.1:{0}/die_on_connect/s'.format(self.configs['records.config']['CONFIG']['proxy.config.http.server_ports'])
- ret = requests.get(url, timeout=2)
- self.assertEqual(ret.status_code, 504)
-
- def test_partial_response_origin(self):
- '''
- Verify that we get 504s from origins that return a partial_response
-
- We want to bail out-- since the origin already got the request, we can't
- gaurantee that the request is re-entrant
- '''
- url = 'http://127.0.0.1:{0}/partial_response/s'.format(self.configs['records.config']['CONFIG']['proxy.config.http.server_ports'])
- ret = requests.get(url, timeout=2)
- self.assertEqual(ret.status_code, 500)
-
- def test_reset_after_accept_origin(self):
- '''Verify that we get 502s from origins that reset_after_accept, once any bytes are sent to origin we assume we cannot re-dispatch'''
- url = 'http://127.0.0.1:{0}/reset_after_accept/s'.format(self.configs['records.config']['CONFIG']['proxy.config.http.server_ports'])
- ret = requests.get(url, timeout=2)
- self.assertEqual(ret.status_code, 502)
-
- def test_slow_response(self):
- '''Verify that we get 5xx from origins that take longer than acceptable, since we will not retry them'''
- url = 'http://127.0.0.1:{0}/slow_response/s'.format(self.configs['records.config']['CONFIG']['proxy.config.http.server_ports'])
- ret = requests.get(url, timeout=2)
- # make sure it worked
- self.assertEqual(ret.status_code, 504)
-
- def test_slow_close(self):
- '''Verify that we retry connecting to an origin when there is a connection failure'''
- url = 'http://127.0.0.1:{0}/slow_close/s'.format(self.configs['records.config']['CONFIG']['proxy.config.http.server_ports'])
- ret = requests.get(url, timeout=2)
- # make sure it worked
- self.assertEqual(ret.status_code, 200)
diff --git a/ci/tsqa/tests/test_custom_log.py b/ci/tsqa/tests/test_custom_log.py
deleted file mode 100644
index 7f32b52..0000000
--- a/ci/tsqa/tests/test_custom_log.py
+++ /dev/null
@@ -1,66 +0,0 @@
-'''
-Test custom log field
-'''
-
-# 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 os
-import requests
-import time
-import logging
-import random
-import tsqa.test_cases
-import helpers
-
-log = logging.getLogger(__name__)
-
-
-class TestCustomLogField(helpers.EnvironmentCase):
- '''
- Tests for a customed log field called hii
- '''
- @classmethod
- def setUpEnv(cls, env):
-
- cls.configs['remap.config'].add_line(
- 'map / http://www.linkedin.com/ @action=deny'
- )
- cls.log_file_name = 'test_log_field'
-
- cls.log_file_path = os.path.join(cls.environment.layout.prefix, 'var/log/test_log_field.log')
- cls.log_etc_file = os.path.join(cls.environment.layout.prefix, 'etc/trafficserver/logging.config')
- cls.configs['logging.config'].add_line('log.ascii(Format = "%<hii> %<hiih>", Filename = "test_log_field"')
-
- def ip_to_hex(self, ipstr):
- num_list = ipstr.split('.')
- int_value = (int(num_list[0]) << 24) + (int(num_list[1]) << 16) + (int(num_list[2]) << 8) + (int(num_list[3]))
- return hex(int_value).upper()[2:]
-
- def test_log_field(self):
- random.seed()
- times = 10
- for i in xrange(times):
- request_ip = "127.%d.%d.%d" % (random.randint(1, 255), random.randint(1, 255), random.randint(1, 255))
- url = 'http://%s:%s' % (request_ip, self.configs['records.config']['CONFIG']['proxy.config.http.server_ports'])
- requests.get(url)
- # get the last line of the log file
- time.sleep(10)
- with open(self.log_file_path) as f:
- for line in f:
- pass
- expected_line = "%s %s\n" % (request_ip, self.ip_to_hex(request_ip))
- self.assertEqual(line, expected_line)
diff --git a/ci/tsqa/tests/test_example.py b/ci/tsqa/tests/test_example.py
deleted file mode 100644
index 3ba0cf0..0000000
--- a/ci/tsqa/tests/test_example.py
+++ /dev/null
@@ -1,185 +0,0 @@
-'''
-Some example tests of the new tsqa
-'''
-
-# 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 os
-import requests
-import time
-import subprocess
-
-import helpers
-
-import tsqa.test_cases
-import tsqa.utils
-
-# TODO: for some reason subclasses of subclasses of TestCase don't work with the
-# decorator
-# @helpers.unittest.skip('Not running TestNoOp, as it is a NoOp test')
-
-
-class TestNoOp(helpers.EnvironmentCase):
- '''
- This is purely a documentation test
- '''
- # you can set dependencies on specific "features" (according to traffic_layout)
- # if the requirement isn't met the test is skipped
- feature_requirements = {'TS_HAS_WCCP': 0}
-
- @classmethod
- def setUpClass(cls):
- '''
- If you'd like to skip an entire test
- '''
- # you can also skip (or conditionally skip) tests
- raise helpers.unittest.SkipTest('Skip the entire class')
-
- @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://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,
- })
-
- def test_something(self):
- '''
- All functions beginning with "test_" will be run as tests for the class.
- Within these functions your environment is already set up and started--
- you only need to excercise the code that you intend to test
- '''
- # 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']))
-
- self.assertEqual(ret.status_code, 404)
- self.assertIn('ATS', ret.headers['server'])
-
-
-class TestConfigureFlags(helpers.EnvironmentCase):
- feature_requirements = {'TS_HAS_WCCP': 0}
- def test_wccp(self):
- self.assertTrue(True)
-
-
-class TestBootstrap(helpers.EnvironmentCase):
- def test_default_404(self):
- ret = requests.get('http://127.0.0.1:{0}/'.format(self.configs['records.config']['CONFIG']['proxy.config.http.server_ports']))
-
- self.assertEqual(ret.status_code, 404)
- self.assertIn('ATS', ret.headers['server'])
-
- def test_trafficctl(self):
- '''
- Test that traffic_ctl works, and verify that the values for proxy.config
- match what we put in records.config
- '''
- cmd = [os.path.join(self.environment.layout.bindir, 'traffic_ctl'),
- 'config',
- 'match',
- 'proxy.config',
- ]
- stdout, _ = tsqa.utils.run_sync_command(cmd, stdout=subprocess.PIPE)
- for line in stdout.splitlines():
- if not line.strip():
- continue
- k, v = line.split(' ', 1)
- if k not in self.configs['records.config']['CONFIG']:
- continue
- r_val = self.configs['records.config']['CONFIG'][k]
- self.assertEqual(type(r_val)(v), self.configs['records.config']['CONFIG'][k])
-
-
-class TestServerIntercept(helpers.EnvironmentCase, tsqa.test_cases.DynamicHTTPEndpointCase):
- endpoint_port = 60000
-
- @classmethod
- def setUpEnv(cls, env):
- cls.configs['remap.config'].add_line('map / http://127.0.0.1:{0}'.format(cls.endpoint_port))
-
- cls.configs['plugin.config'].add_line('intercept.so')
-
- def hello(request):
- return 'hello'
- cls.http_endpoint.add_handler('/', hello)
-
- def test_basic_intercept(self):
- for _ in xrange(0, 10):
- ret = requests.get('http://127.0.0.1:{0}/'.format(self.configs['records.config']['CONFIG']['proxy.config.http.server_ports']))
-
- self.assertEqual(ret.status_code, 200)
-
-
-class TestLogs(helpers.EnvironmentCase):
- @classmethod
- def setUpEnv(cls, env):
- '''
- This funciton is responsible for setting up the environment for this fixture
- This includes everything pre-daemon start
- '''
- # only add server headers when there weren't any
- cls.configs['records.config']['CONFIG'].update({
- 'proxy.config.diags.debug.tags': 'log-.*',
- 'proxy.config.diags.debug.enabled': 1,
- 'proxy.config.log.hostname': 'test',
- })
-
- def test_logs_exist(self):
- # send some requests
- for x in xrange(0, 10):
- ret = requests.get('http://127.0.0.1:{0}/'.format(self.configs['records.config']['CONFIG']['proxy.config.http.server_ports']))
-
- self.assertEqual(ret.status_code, 404)
- self.assertIn('ATS', ret.headers['server'])
-
- # TODO: some better way to know when the logs where syncd
- time.sleep(10) # wait for logs to hit disk
-
- # verify that the log files exist
- for logfile in ('diags.log', 'error.log', 'squid.blog', 'traffic.out', 'manager.log'):
- logfile_path = os.path.join(self.environment.layout.logdir, logfile)
- self.assertTrue(os.path.isfile(logfile_path), logfile_path)
-
-
-class TestDynamicHTTPEndpointCase(tsqa.test_cases.DynamicHTTPEndpointCase, helpers.EnvironmentCase):
- @classmethod
- def setUpEnv(cls, env):
- '''
- This funciton is responsible for setting up the environment for this fixture
- This includes everything pre-daemon start
- '''
- cls.configs['remap.config'].add_line('map / http://127.0.0.1:{0}/\n'.format(cls.http_endpoint.address[1]))
-
- # only add server headers when there weren't any
- cls.configs['records.config']['CONFIG']['proxy.config.http.response_server_enabled'] = 2
-
- def test_basic_proxy(self):
- ret = requests.get(self.endpoint_url('/test'),
- proxies=self.proxies,
- )
- self.assertEqual(ret.status_code, 404)
- self.assertIn('WSGIServer', ret.headers['server'])
diff --git a/ci/tsqa/tests/test_header_rewrite.py b/ci/tsqa/tests/test_header_rewrite.py
deleted file mode 100644
index ed8d3c3..0000000
--- a/ci/tsqa/tests/test_header_rewrite.py
+++ /dev/null
@@ -1,130 +0,0 @@
-'''
-Test cookie rewrite
-'''
-# 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 os
-import requests
-import time
-import logging
-import random
-import tsqa.test_cases
-import helpers
-import shutil
-import SocketServer
-import urllib2
-
-log = logging.getLogger(__name__)
-
-class EchoServerHandler(SocketServer.BaseRequestHandler):
- """
- A subclass of RequestHandler which will return all data received back
- """
-
- def handle(self):
- # Receive the data in small chunks and retransmit it
- while True:
- data = self.request.recv(4096).strip()
- if data:
- log.debug('Sending data back to the client')
- else:
- log.debug('Client disconnected')
- break
- cookie = ''
- if 'Cookie' in data:
- cookie = data.split('Cookie: ')[1].split('\r\n')[0]
-
- resp = ('HTTP/1.1 200 OK\r\n'
- 'Content-Length: {data_length}\r\n'
- 'Content-Type: text/html; charset=UTF-8\r\n'
- 'Connection: keep-alive\r\n'
- '\r\n{data_string}'.format(
- data_length = len(cookie),
- data_string = cookie
- ))
- self.request.sendall(resp)
-
-class TestHeaderRewrite(helpers.EnvironmentCase):
- '''
- Tests for header rewrite
- '''
- @classmethod
- def setUpEnv(cls, env):
- cls.traffic_server_port = int(cls.configs['records.config']['CONFIG']['proxy.config.http.server_ports'])
-
- # create a socket server
- cls.socket_server = tsqa.endpoint.SocketServerDaemon(EchoServerHandler)
- cls.socket_server.start()
- cls.socket_server.ready.wait()
-
- cls.configs['remap.config'].add_line(
- 'map / http://127.0.0.1:%d' %(cls.socket_server.port)
- )
-
- # setup the plugin
- cls.config_file = 'header-rewrite.config'
- cls.test_config_path = helpers.tests_file_path(cls.config_file)
-
- cls.configs['plugin.config'].add_line('%s/header_rewrite.so %s' % (
- cls.environment.layout.plugindir,
- cls.test_config_path
- ))
-
- def test_cookie_rewrite(self):
-
- cookie_test_add_dict = {
- '' : 'testkey=testaddvalue',
- 'testkey=somevalue' : 'testkey=somevalue',
- 'otherkey=testvalue' : 'otherkey=testvalue;testkey=testaddvalue',
- 'testkey = "other=value"; a = a' : 'testkey = "other=value"; a = a',
- 'testkeyx===' : 'testkeyx===;testkey=testaddvalue'
- }
- for key in cookie_test_add_dict:
- opener = urllib2.build_opener()
- opener.addheaders.append(('Cookie', key))
- f = opener.open("http://127.0.0.1:%d/addcookie" % (self.traffic_server_port))
- resp = f.read()
- self.assertEqual(resp, cookie_test_add_dict[key])
-
- cookie_test_rm_dict = {
- '' : '',
- ' testkey=somevalue' : '',
- 'otherkey=testvalue' : 'otherkey=testvalue',
- 'testkey = "other=value" ; a = a' : ' a = a',
- 'otherkey=othervalue= ; testkey===' : 'otherkey=othervalue= ',
- 'firstkey ="firstvalue" ; testkey = =; secondkey=\'\'' : 'firstkey ="firstvalue" ; secondkey=\'\''
- }
- for key in cookie_test_rm_dict:
- opener = urllib2.build_opener()
- opener.addheaders.append(('Cookie', key))
- f = opener.open("http://127.0.0.1:%d/rmcookie" % (self.traffic_server_port))
- resp = f.read()
- self.assertEqual(resp, cookie_test_rm_dict[key])
-
- cookie_test_set_dict = {
- '' : 'testkey=testsetvalue',
- 'testkey=somevalue' : 'testkey=testsetvalue',
- 'otherkey=testvalue' : 'otherkey=testvalue;testkey=testsetvalue',
- 'testkey = "other=value"; a = a' : 'testkey = testsetvalue; a = a',
- 'testkeyx===' : 'testkeyx===;testkey=testsetvalue',
- 'firstkey ="firstvalue" ; testkey = =; secondkey=\'\'' : 'firstkey ="firstvalue" ; testkey = testsetvalue; secondkey=\'\''
- }
- for key in cookie_test_set_dict:
- opener = urllib2.build_opener()
- opener.addheaders.append(('Cookie', key))
- f = opener.open("http://127.0.0.1:%d/setcookie" % (self.traffic_server_port))
- resp = f.read()
- self.assertEqual(resp, cookie_test_set_dict[key])
diff --git a/ci/tsqa/tests/test_headrequest.py b/ci/tsqa/tests/test_headrequest.py
deleted file mode 100644
index e19312a..0000000
--- a/ci/tsqa/tests/test_headrequest.py
+++ /dev/null
@@ -1,115 +0,0 @@
-'''
-Test Head Request
-'''
-
-# 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 time
-import logging
-import SocketServer
-import tsqa.test_cases
-import helpers
-import socket
-
-log = logging.getLogger(__name__)
-
-
-class HeadRequestServerHandler(SocketServer.BaseRequestHandler):
- """
- A subclass of RequestHandler which will response to head requests
- """
-
- def handle(self):
- # Receive the data in small chunks and retransmit it
- while True:
- data = self.request.recv(4096).strip()
- if data:
- log.debug('Sending data back to the client')
- else:
- log.debug('Client disconnected')
- break
- if 'TE' in data:
- resp = ('HTTP/1.1 200 OK\r\n'
- 'Server: Apache-Coyote/1.1\r\n'
- 'Transfer-Encoding: chunked\r\n'
- 'Vary: Accept-Encoding\r\n'
- '\r\n'
- )
- self.request.sendall(resp)
- elif 'CL' in data:
- resp = ('HTTP/1.1 200 OK\r\n'
- 'Server: Apache-Coyote/1.1\r\n'
- 'Content-Length: 123\r\n'
- 'Vary: Accept-Encoding\r\n'
- '\r\n'
- )
- self.request.sendall(resp)
- else:
- resp = ('HTTP/1.1 200 OK\r\n'
- 'Server: Apache-Coyote/1.1\r\n'
- 'Vary: Accept-Encoding\r\n'
- '\r\n'
- )
- self.request.sendall(resp)
-
-
-class TestHeadRequestWithoutTimeout(helpers.EnvironmentCase):
- '''
- Tests for ATS handling head requests correctly without waiting for the http body
- '''
- @classmethod
- def setUpEnv(cls, env):
- cls.timeout = 5
- cls.configs['records.config']['CONFIG'].update({
- 'proxy.config.http.transaction_no_activity_timeout_out': cls.timeout,
- })
- cls.socket_server = tsqa.endpoint.SocketServerDaemon(HeadRequestServerHandler)
- cls.socket_server.start()
- cls.socket_server.ready.wait()
- cls.configs['remap.config'].add_line('map / http://127.0.0.1:{0}/'.format(cls.socket_server.port))
- log.info('map / http://127.0.0.1:{0}/'.format(cls.socket_server.port))
-
- cls.proxy_host = '127.0.0.1'
- cls.proxy_port = int(cls.configs['records.config']['CONFIG']['proxy.config.http.server_ports'])
-
- def test_head_request_without_timout(cls):
- request_cases = ['TE', 'CL', '']
- for request_case in request_cases:
- begin_time = time.time()
- conn = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
- conn.connect((cls.proxy_host, cls.proxy_port))
- request_content = 'HEAD / HTTP/1.1\r\nConnection: close\r\nHost: 127.0.0.1\r\nContent-Length: %d\r\n\r\n%s' % (
- len(request_case), request_case)
- conn.setblocking(1)
- conn.send(request_content)
- while 1:
- try:
- resp = conn.recv(4096)
- if len(resp) == 0:
- break
- response_content = resp
- log.info(resp)
- except:
- break
- conn.shutdown(socket.SHUT_RDWR)
- conn.close()
- end_time = time.time()
- log.info("head request with case(%s) costs %f seconds while the timout is %f seconds." % (
- request_case, end_time - begin_time, cls.timeout))
- cls.assertGreater(cls.timeout, end_time - begin_time)
- if request_case == 'CL':
- cls.assertIn('Content-Length', response_content)
diff --git a/ci/tsqa/tests/test_hostdb.py b/ci/tsqa/tests/test_hostdb.py
deleted file mode 100644
index 124a32e..0000000
--- a/ci/tsqa/tests/test_hostdb.py
+++ /dev/null
@@ -1,639 +0,0 @@
-'''
-Test hostdb
-'''
-
-# 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 os
-import requests
-import time
-import logging
-import socket
-import SocketServer
-
-import contextlib
-import dnslib
-import dnslib.server
-
-import tsqa.test_cases
-import helpers
-
-log = logging.getLogger(__name__)
-
-
-@contextlib.contextmanager
-def kill_dns(dns_server):
- ''' Temporarily kill the dns server
- '''
- dns_server.stop()
- yield
- dns_server.start_thread()
-
-
-class StubDNSResolver(object):
- '''Resolver to serve defined responses from `response_dict` or return SOA
- '''
- def __init__(self, responses):
- self.responses = responses
- self.resp_headers = {}
-
- def resolve(self, request, handler):
- reply = request.reply()
- for q in request.questions:
- qname = str(q.get_qname())
- if qname in self.responses:
- for resp in self.responses[qname]:
- reply.add_answer(resp)
- else:
- reply.add_answer(dnslib.server.RR(
- q.get_qname(),
- rtype=dnslib.QTYPE.SOA,
- ttl=1,
- rdata=dnslib.dns.SOA(
- 'nameserver.local',
- q.get_qname(),
- ),
- ))
- for k, v in self.resp_headers.iteritems():
- if k == 'rcode':
- reply.header.set_rcode(v)
- print 'setting rcode'
- else:
- log.warning('Unsupported header sent to StubDNSResolver %s' % k)
- return reply
-
-
-class EchoServerIpHandler(SocketServer.BaseRequestHandler):
- """
- A subclass of RequestHandler which will return a connection uuid
- """
-
- def handle(self):
- # Receive the data in small chunks and retransmit it
- while True:
- data = self.request.recv(4096).strip()
- if data:
- log.debug('Sending data back to the client')
- else:
- log.debug('Client disconnected')
- break
- resp = ('HTTP/1.1 200 OK\r\n'
- 'Content-Length: 0\r\n'
- 'Content-Type: text/html; charset=UTF-8\r\n'
- 'Connection: keep-alive\r\n'
- 'X-Server-Ip: {server_ip}\r\n'
- 'X-Server-Port: {server_port}\r\n'
- 'X-Client-Ip: {client_ip}\r\n'
- 'X-Client-Port: {client_port}\r\n'
- '\r\n'.format(
- server_ip=self.request.getsockname()[0],
- server_port=self.request.getsockname()[1],
- client_ip=self.request.getpeername()[0],
- client_port=self.request.getpeername()[1],
- ))
- self.request.sendall(resp)
-
-
-class TestHostDBBadResolvConf(helpers.EnvironmentCase):
- '''
- Test that ATS can handle an empty resolv_conf
- '''
- @classmethod
- def setUpEnv(cls, env):
- cls.configs['records.config']['CONFIG'].update({
- 'proxy.config.http.response_server_enabled': 2, # only add server headers when there weren't any
- 'proxy.config.hostdb.lookup_timeout': 2,
- 'proxy.config.dns.resolv_conf': '/tmp/non_existant_file',
- 'proxy.config.url_remap.remap_required': 0,
-
- })
-
- def test_working(self):
- ret = requests.get('http://trafficserver.readthedocs.org',
- proxies=self.proxies,
- )
- self.assertEqual(ret.status_code, 502)
-
-
-class TestHostDBPartiallyFailedDNS(helpers.EnvironmentCase):
- '''
- Tests for how hostdb handles when there is one failed and one working resolver
- '''
- @classmethod
- def setUpEnv(cls, env):
- # TODO: Fix this!
- # This intermittently fails on Jenkins (such as https://ci.trafficserver.apache.org/job/tsqa-master/387/testReport/test_hostdb/TestHostDBPartiallyFailedDNS/test_working/)
- # we aren't sure if this is a failure of ATS or just a race on jenkins (since its slow)
- raise helpers.unittest.SkipTest()
-
- resolv_conf_path = os.path.join(env.layout.prefix, 'resolv.conf')
-
- cls.configs['records.config']['CONFIG'].update({
- 'proxy.config.http.response_server_enabled': 2, # only add server headers when there weren't any
- 'proxy.config.hostdb.lookup_timeout': 2,
- 'proxy.config.dns.resolv_conf': resolv_conf_path,
- 'proxy.config.url_remap.remap_required': 0,
-
- })
-
- with open(resolv_conf_path, 'w') as fh:
- fh.write('nameserver 1.1.1.0\n') # some non-existant nameserver
- fh.write('nameserver 8.8.8.8\n') # some REAL nameserver
-
- def test_working(self):
- start = time.time()
- ret = requests.get('http://trafficserver.readthedocs.org',
- proxies=self.proxies,
- )
- self.assertLess(time.time() - start, self.configs['records.config']['CONFIG']['proxy.config.hostdb.lookup_timeout'])
- self.assertEqual(ret.status_code, 200)
-
-
-class TestHostDBFailedDNS(helpers.EnvironmentCase):
- '''
- Tests for how hostdb handles when there is no reachable resolver
- '''
- @classmethod
- def setUpEnv(cls, env):
- resolv_conf_path = os.path.join(env.layout.prefix, 'resolv.conf')
-
- cls.configs['records.config']['CONFIG'].update({
- 'proxy.config.http.response_server_enabled': 2, # only add server headers when there weren't any
- 'proxy.config.hostdb.lookup_timeout': 2,
- 'proxy.config.dns.resolv_conf': resolv_conf_path,
- 'proxy.config.url_remap.remap_required': 0,
-
- })
-
- with open(resolv_conf_path, 'w') as fh:
- fh.write('nameserver 1.1.1.0\n') # some non-existant nameserver
-
- def test_lookup_timeout(self):
- start = time.time()
- ret = requests.get('http://some_nonexistant_domain',
- proxies=self.proxies,
- )
- self.assertGreater(time.time() - start, self.configs['records.config']['CONFIG']['proxy.config.hostdb.lookup_timeout'])
- self.assertEqual(ret.status_code, 502)
- self.assertIn('ATS', ret.headers['server'])
-
-
-class TestHostDBHostsFile(helpers.EnvironmentCase, tsqa.test_cases.HTTPBinCase):
- '''
- Tests for hostdb's host-file implementation
- '''
- @classmethod
- def setUpEnv(cls, env):
- cls.hosts_file_path = os.path.join(env.layout.prefix, 'hosts')
- with open(cls.hosts_file_path, 'w') as fh:
- fh.write('127.0.0.1 local\n')
- fh.write('127.0.0.2 local2\n')
-
- cls.configs['records.config']['CONFIG'].update({
- 'proxy.config.http.response_server_enabled': 2, # only add server headers when there weren't any
- 'proxy.config.hostdb.lookup_timeout': 2,
- 'proxy.config.url_remap.remap_required': 1,
- 'proxy.config.http.connect_attempts_max_retries': 1,
- 'proxy.config.hostdb.host_file.interval': 1,
- 'proxy.config.hostdb.host_file.path': cls.hosts_file_path,
- 'proxy.config.diags.debug.enabled': 1,
- 'proxy.config.diags.debug.tags': 'hostdb',
- })
- # create a socket server
- cls.socket_server = tsqa.endpoint.SocketServerDaemon(EchoServerIpHandler)
- cls.socket_server.start()
- cls.socket_server.ready.wait()
- cls.configs['remap.config'].add_line('map http://local/ http://local:{0}/'.format(cls.socket_server.port))
- cls.configs['remap.config'].add_line('map http://local2/ http://local2:{0}/'.format(cls.socket_server.port))
- cls.configs['remap.config'].add_line('map http://local3/ http://local3:{0}/'.format(cls.socket_server.port))
-
- def test_basic(self):
- '''
- Test basic fnctionality of hosts files
- '''
- # TODO add stat, then wait for the stat to increment
- time.sleep(2) # wait for the continuation to load the hosts file
- ret = requests.get(
- 'http://local/get',
- proxies=self.proxies,
- )
- self.assertEqual(ret.status_code, 200)
- self.assertEqual('127.0.0.1', ret.headers['X-Server-Ip'])
-
- ret = requests.get(
- 'http://local2/get',
- proxies=self.proxies,
- )
- self.assertEqual(ret.status_code, 200)
- self.assertEqual('127.0.0.2', ret.headers['X-Server-Ip'])
-
- def test_reload(self):
- '''
- Test that changes to hosts file get loaded within host_file.interval
- '''
- # TODO add stat, then wait for the stat to increment
- time.sleep(2) # wait for the continuation to load the hosts file
- ret = requests.get(
- 'http://local3/get',
- proxies=self.proxies,
- )
- self.assertEqual(ret.status_code, 502)
-
- with open(self.hosts_file_path, 'a') as fh:
- fh.write('127.0.0.3 local3\n')
-
- # TODO add stat, then wait for the stat to increment, with a timeout
- time.sleep(2)
-
- ret = requests.get(
- 'http://local3/get',
- proxies=self.proxies,
- )
- self.assertEqual(ret.status_code, 200)
- self.assertEqual('127.0.0.3', ret.headers['X-Server-Ip'])
-
-
-class TestHostDB(helpers.EnvironmentCase, tsqa.test_cases.HTTPBinCase):
- @classmethod
- def setUpEnv(cls, env):
- cls.dns_sock = socket.socket (socket.AF_INET, socket.SOCK_DGRAM)
- cls.dns_sock.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
- cls.dns_sock.bind(('', 0)) # bind to all interfaces on an ephemeral port
- dns_port = cls.dns_sock.getsockname()[1]
-
- # set up dns resolver
- cls.responses = {
- 'www.foo.com.': dnslib.server.RR.fromZone("foo.com. 1 A 127.0.0.1"),
- 'www.stale_for.com.': dnslib.server.RR.fromZone("foo.com. 1 A 127.0.0.1"),
- }
-
- cls.dns_server = dnslib.server.DNSServer(
- StubDNSResolver(cls.responses),
- port=dns_port,
- address="localhost",
- )
- cls.dns_server.start_thread()
-
- cls.hosts_file_path = os.path.join(env.layout.prefix, 'resolv')
- with open(cls.hosts_file_path, 'w') as fh:
- fh.write('nameserver 127.0.0.1:{0}\n'.format(dns_port))
-
- cls.configs['records.config']['CONFIG'].update({
- 'proxy.config.http.response_server_enabled': 2, # only add server headers when there weren't any
- 'proxy.config.hostdb.lookup_timeout': 1,
- 'proxy.config.url_remap.remap_required': 0,
- 'proxy.config.http.connect_attempts_max_retries': 1,
- 'proxy.config.diags.debug.enabled': 1,
- 'proxy.config.diags.debug.tags': 'hostdb',
- 'proxy.config.dns.resolv_conf': os.path.join(env.layout.prefix, 'resolv'),
- 'proxy.config.hostdb.serve_stale_for': 2,
- 'proxy.config.hostdb.ttl_mode': 0,
- 'proxy.config.http_ui_enabled': 3,
- })
-
- cls.configs['remap.config'].add_line('map /_hostdb/ http://{hostdb}')
-
- def _hostdb_entries(self):
- # mapping of name -> entries
- ret = {}
- showall_ret = requests.get('http://127.0.0.1:{0}/_hostdb/showall?format=json'.format(
- self.configs['records.config']['CONFIG']['proxy.config.http.server_ports']
- ), timeout=1).json()
-
- for item in showall_ret:
- ret[item['hostname']] = item
-
- return ret
-
- def test_dns(self):
- '''Test that DNS lookups end up in hostdb as we expect
- '''
- # TODO: remove
- self.test_basic()
- print self._hostdb_entries()
-
- # test something with a LARGE number of entries
- zone_parts = []
- # TODO: fix this, right now there is `#define DNS_MAX_ADDRS 35` which
- # controls how many work-- we should make this configurable
- # 30 works, once you pass 35 some records are missing, and at some point
- # you start getting garbage (50 for example) and at some point (100) it
- # seems to crash
- NUM_RECORDS = 2
- for x in xrange(0, NUM_RECORDS):
- zone_parts.append("www.huge.com. 1 A 127.0.0.{0}".format(x + 1))
- self.responses['www.huge.com.'] = dnslib.server.RR.fromZone('\n'.join(zone_parts))
-
- ret = requests.get(
- 'http://www.huge.com:{0}/get'.format(self.http_endpoint.address[1]),
- proxies=self.proxies,
- )
- #self.assertEqual(ret.status_code, 200)
-
- for item in self._hostdb_entries()['www.huge.com']['rr_records']:
- print item['ip']
-
- self.assertEqual(len(self._hostdb_entries()['www.huge.com']['rr_records']), NUM_RECORDS)
-
-
- def test_basic(self):
- '''
- Test basic fnctionality of resolver
- '''
-
- # test one that works
- ret = requests.get(
- 'http://www.foo.com:{0}/get'.format(self.http_endpoint.address[1]),
- proxies=self.proxies,
- )
- self.assertEqual(ret.status_code, 200)
-
- # check one that doesn't exist
- ret = requests.get(
- 'http://www.bar.com:{0}/get'.format(self.http_endpoint.address[1]),
- proxies=self.proxies,
- )
- self.assertEqual(ret.status_code, 502)
-
- def test_serve_stail_for(self):
- start = time.time()
- ret = requests.get(
- 'http://www.stale_for.com:{0}/get'.format(self.http_endpoint.address[1]),
- proxies=self.proxies,
- )
- self.assertEqual(ret.status_code, 200)
- # mark the DNSServer down
- with kill_dns(self.dns_server):
- timeout_at = time.time() + 10
- end_working = None
- end = None
- count = 0
-
- while time.time() < timeout_at:
- ret = requests.get(
- 'http://www.stale_for.com:{0}/get'.format(self.http_endpoint.address[1]),
- proxies=self.proxies,
- )
- count += 1
- if ret.status_code != 200:
- end = time.time()
- break
- else:
- end_working = time.time()
- time.sleep(0.5)
- # ensure that it was for at least 2 seconds
- print end_working - start
- self.assertTrue(end_working - start >= 2)
- # TODO: Fix this!
- # for whatever reason the failed DNS response is taking ~3.5s to timeout
- # even though the hostdb.lookup_timeout is set to 1 (meaning it should be ~1s)
- #print end - end_working
- #self.assertTrue(end - start >= 2)
-
-
-class TestHostDBSRV(helpers.EnvironmentCase):
- '''Tests for SRV records within hostdb
-
- Tests:
- - SRV record
- - port overriding
- - http/https lookups
- - fallback to non SRV
- '''
- SS_CONFIG = {
- '_http._tcp.www.foo.com.': lambda: tsqa.endpoint.SocketServerDaemon(EchoServerIpHandler),
- '_https._tcp.www.foo.com.': lambda: tsqa.endpoint.SSLSocketServerDaemon(
- EchoServerIpHandler,
- helpers.tests_file_path('cert.pem'),
- helpers.tests_file_path('key.pem'),
- ),
- }
-
- # TODO: clean up and push into trafficserver-qa
- @property
- def proxies(self):
- '''
- Return a dict of schema -> proxy. This is primarily used for requests
- '''
- ret = {}
- for item in self.configs['records.config']['CONFIG']['proxy.config.http.server_ports'].split():
- # TODO: better parsing? For now assume first is port
- parts = item.split(':')
- dst = 'http://127.0.0.1:{0}'.format(parts[0])
- if len(parts) > 1:
- if parts[1] not in ret:
- ret[parts[1]] = dst
- elif 'http' not in ret:
- ret['http'] = dst
- return ret
-
-
- @classmethod
- def setUpEnv(cls, env):
- cls.dns_sock = socket.socket (socket.AF_INET, socket.SOCK_DGRAM)
- cls.dns_sock.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
- cls.dns_sock.bind(('', 0)) # bind to all interfaces on an ephemeral port
- dns_port = cls.dns_sock.getsockname()[1]
-
- # set up dns resolver
- cls.responses = {
- 'www.foo.com.': dnslib.server.RR.fromZone("foo.com. 1 A 127.0.0.3\nfoo.com. 1 A 127.0.0.2"),
- 'www.stale_for.com.': dnslib.server.RR.fromZone("foo.com. 1 A 127.0.0.1"),
- }
-
- cls.dns_server = dnslib.server.DNSServer(
- StubDNSResolver(cls.responses),
- port=dns_port,
- address="localhost",
- )
- cls.dns_server.start_thread()
-
- cls.ssl_port = tsqa.utils.bind_unused_port()[1]
- cls.configs['records.config']['CONFIG']['proxy.config.http.server_ports'] += ' {0}:ssl'.format(cls.ssl_port)
-
- cls.configs['records.config']['CONFIG'].update({
- 'proxy.config.http.response_server_enabled': 2, # only add server headers when there weren't any
- 'proxy.config.hostdb.lookup_timeout': 1,
- 'proxy.config.http.connect_attempts_max_retries': 1,
- 'proxy.config.diags.debug.enabled': 1,
- 'proxy.config.diags.debug.tags': 'hostdb',
- 'proxy.config.dns.resolv_conf': os.path.join(env.layout.prefix, 'resolv'),
- 'proxy.config.hostdb.serve_stale_for': 2,
- 'proxy.config.hostdb.ttl_mode': 0,
- 'proxy.config.http_ui_enabled': 3,
- 'proxy.config.dns.nameservers': '127.0.0.1:{0}'.format(dns_port),
- 'proxy.config.srv_enabled': 1,
- })
-
- cls.configs['ssl_multicert.config'].add_line('dest_ip=* ssl_cert_name={0}'.format(
- helpers.tests_file_path('rsa_keys/www.test.com.pem'),
- ))
-
- y = -1
- for name, factory in cls.SS_CONFIG.iteritems():
- y += 1
- ss_dns_results = []
- for x in xrange(0, 3):
- ss = factory()
- ss.start()
- ss.ready.wait()
- ss_dns_results.append(dnslib.server.RR(
- name,
- dnslib.dns.QTYPE.SRV,
- rdata = dnslib.dns.SRV(
- priority=10,
- weight=10,
- port=ss.port,
- target='127.0.{0}.{1}.'.format(y, x + 1), # note: NUM_REALS must be < 253
- ),
- ttl=1,
- ))
- cls.responses[name] = ss_dns_results
-
- cls.configs['remap.config'].add_line('map http://www.foo.com/ http://www.foo.com/')
- cls.configs['remap.config'].add_line('map https://www.foo.com/ https://www.foo.com/')
- cls.configs['remap.config'].add_line('map /_hostdb/ http://{hostdb}')
-
- def _hostdb_entries(self):
- # mapping of name -> entries
- ret = {}
- showall_ret = requests.get('http://127.0.0.1:{0}/_hostdb/showall?format=json'.format(
- self.configs['records.config']['CONFIG']['proxy.config.http.server_ports']
- ), timeout=1)
- return showall_ret.text
-
- for item in showall_ret:
- ret[item['hostname']] = item
-
- return ret
-
- def test_https(self):
- '''Test https SRV lookups
-
- we expect the SRV lookup to get different hosts, but otherwise act the same
- '''
- time.sleep(1)
- expected_set = set([d.rdata.port for d in self.responses['_https._tcp.www.foo.com.']])
-
- actual_set = set()
- for x in xrange(0, 10):
- # test one that works
- ret = requests.get(
- 'https://localhost:{0}/'.format(self.ssl_port),
- headers={'Host': 'www.foo.com'},
- verify=False, # self signed certs, don't bother verifying
- )
- self.assertEqual(ret.status_code, 200)
- actual_set.add(int(ret.headers['X-Server-Port']))
-
- self.assertEqual(expected_set, actual_set)
-
- def test_ports(self):
- '''Test port functionality of SRV responses
-
- SRV responses include ports-- so we want to ensure that we are correctly
- overriding the port based on the response
- '''
- time.sleep(1)
- expected_set = set([d.rdata.port for d in self.responses['_http._tcp.www.foo.com.']])
-
- actual_set = set()
- for x in xrange(0, 10):
- # test one that works
- ret = requests.get(
- 'http://www.foo.com/',
- proxies=self.proxies,
- )
- self.assertEqual(ret.status_code, 200)
- actual_set.add(int(ret.headers['X-Server-Port']))
-
- self.assertEqual(expected_set, actual_set)
-
- def test_priority(self):
- '''Test port functionality of SRV responses
-
- SRV responses include ports-- so we want to ensure that we are correctly
- overriding the port based on the response
- '''
- time.sleep(3) # TODO: clear somehow? waiting for expiry is lame
-
- NUM_REQUESTS = 10
- orig_responses = self.responses['_http._tcp.www.foo.com.']
- try:
- self.responses['_http._tcp.www.foo.com.'][0].rdata.priority=1
-
- request_distribution = {}
- for x in xrange(0, NUM_REQUESTS):
- # test one that works
- ret = requests.get(
- 'http://www.foo.com/',
- proxies=self.proxies,
- )
- self.assertEqual(ret.status_code, 200)
- port = int(ret.headers['X-Server-Port'])
- if port not in request_distribution:
- request_distribution[port] = 0
- request_distribution[port] += 1
-
- # since one has a lower priority, we want to ensure that it got all requests
- self.assertEqual(
- request_distribution[self.responses['_http._tcp.www.foo.com.'][0].rdata.port],
- NUM_REQUESTS,
- )
-
- finally:
- self.responses['_http._tcp.www.foo.com.'] = orig_responses
-
- def test_weight(self):
- '''Test port functionality of SRV responses
-
- SRV responses include ports-- so we want to ensure that we are correctly
- overriding the port based on the response
- '''
- time.sleep(3) # TODO: clear somehow? waiting for expiry is lame
-
- NUM_REQUESTS = 100
- orig_responses = self.responses['_http._tcp.www.foo.com.']
- try:
- self.responses['_http._tcp.www.foo.com.'][0].rdata.weight=100
-
- request_distribution = {}
- for x in xrange(0, NUM_REQUESTS):
- # test one that works
- ret = requests.get(
- 'http://www.foo.com/',
- proxies=self.proxies,
- )
- self.assertEqual(ret.status_code, 200)
- port = int(ret.headers['X-Server-Port'])
- if port not in request_distribution:
- request_distribution[port] = 0
- request_distribution[port] += 1
-
- # since the first one has a significantly higher weight, we expect it to
- # take ~10x the traffic of the other 2
- self.assertTrue(
- request_distribution[self.responses['_http._tcp.www.foo.com.'][0].rdata.port] >
- (NUM_REQUESTS / len(self.responses['_http._tcp.www.foo.com.'])) * 2,
- 'Expected significantly more traffic on {0} than the rest: {1}'.format(
- self.responses['_http._tcp.www.foo.com.'][0].rdata.port,
- request_distribution,
- ),
- )
-
- finally:
- self.responses['_http._tcp.www.foo.com.'] = orig_responses
diff --git a/ci/tsqa/tests/test_http2.py b/ci/tsqa/tests/test_http2.py
deleted file mode 100644
index 7f8be87..0000000
--- a/ci/tsqa/tests/test_http2.py
+++ /dev/null
@@ -1,97 +0,0 @@
-# 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
-
-import helpers
-
-import tsqa.endpoint
-import tsqa.test_cases
-import tsqa.utils
-
-try:
- import hyper
-except ImportError:
- raise helpers.unittest.SkipTest('Cannot import hyper, skipping tests for HTTP/2')
-
-log = logging.getLogger(__name__)
-
-
-class TestHTTP2(helpers.EnvironmentCase, tsqa.test_cases.HTTPBinCase):
- @classmethod
- def setUpEnv(cls, env):
- '''
- Setting up environment for testing of HTTP2
- '''
- # get HTTP/2 server ports
- cls.http2_port = tsqa.utils.bind_unused_port()[1]
-
- # HTTP2 configs
- cls.configs['records.config']['CONFIG']['proxy.config.http.server_ports'] += ' {0}:ssl'.format(cls.http2_port)
- cls.configs['records.config']['CONFIG']['proxy.config.ssl.server.cert.path'] = helpers.tests_file_path('rsa_keys')
- cls.configs['records.config']['CONFIG']['proxy.config.diags.debug.enabled'] = 1
- cls.configs['records.config']['CONFIG']['proxy.config.diags.debug.tags'] = 'http2.*|ssl.*'
-
- # configure SSL multicert
- cls.configs['ssl_multicert.config'].add_line(
- 'dest_ip=* ssl_cert_name={0}\n'.format(helpers.tests_file_path('rsa_keys/www.example.com.pem'))
- )
-
- # remap configs
- cls.configs['remap.config'].add_line(
- 'map / http://127.0.0.1:{0}/'.format(cls.http_endpoint.address[1])
- )
-
- # Turn off certificate verification for the tests.
- # hyper-0.4.0 verify certs in default and can't turn it off without below hack:(
- hyper.tls._context = hyper.tls.init_context()
- hyper.tls._context.check_hostname = False
- hyper.tls._context.verify_mode = hyper.compat.ssl.CERT_NONE
-
- def __cat(self, target_file_path):
- '''
- Cat given file
- '''
- for line in open(target_file_path).readlines():
- log.debug(line[:-1])
-
- def __traffic_out(self):
- '''
- Cat traffic.out
- '''
- self.__cat(os.path.join(self.environment.layout.logdir, 'traffic.out'))
-
- def __diags_log(self):
- '''
- Cat diags.log
- '''
- self.__cat(os.path.join(self.environment.layout.logdir, 'diags.log'))
-
- def test_http2_request_hyper(self):
- '''
- Test HTTP/2 w/ hyper (Normal Scenario)
- '''
- try:
- conn = hyper.HTTPConnection('127.0.0.1', self.http2_port, secure=True)
- stream_id = conn.request('GET', '/')
- ret = conn.get_response()
-
- self.assertNotEqual(stream_id, None)
- self.assertEqual(ret.status, 200)
- except Exception as e:
- log.error(e)
- self.__traffic_out()
- self.__diags_log()
diff --git a/ci/tsqa/tests/test_http2_spec.py b/ci/tsqa/tests/test_http2_spec.py
deleted file mode 100644
index 915ca1a..0000000
--- a/ci/tsqa/tests/test_http2_spec.py
+++ /dev/null
@@ -1,115 +0,0 @@
-# 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.
-
-#
-# Note: This test case uses h2spec. Please install it yourself.
-# https://github.com/summerwind/h2spec
-#
-
-import logging
-import os
-import subprocess
-
-import helpers
-
-import tsqa.endpoint
-import tsqa.test_cases
-import tsqa.utils
-
-log = logging.getLogger(__name__)
-
-
-# helper function to get h2spec path
-def which(program):
- def is_exe(fpath):
- return os.path.isfile(fpath) and os.access(fpath, os.X_OK)
- fpath, fname = os.path.split(program)
- if fpath:
- if is_exe(program):
- return program
- else:
- for path in os.environ["PATH"].split(os.pathsep):
- path = path.strip('"')
- exe_file = os.path.join(path, program)
- if is_exe(exe_file):
- return exe_file
- return None
-
-
-class TestH2Spec(helpers.EnvironmentCase, tsqa.test_cases.HTTPBinCase):
- @classmethod
- def setUpEnv(cls, env):
- '''
- Setting up environment for testing of HTTP2
- '''
- # get path to h2spec
- cls.h2spec = which('h2spec')
- if cls.h2spec is None:
- raise helpers.unittest.SkipTest('Cannot find h2spec. skipping test.')
-
- # get HTTP/2 server ports
- cls.http2_port = tsqa.utils.bind_unused_port()[1]
-
- # HTTP2 configs
- cls.configs['records.config']['CONFIG']['proxy.config.http.server_ports'] += ' {0}:ssl'.format(cls.http2_port)
- cls.configs['records.config']['CONFIG']['proxy.config.ssl.server.cert.path'] = helpers.tests_file_path('rsa_keys')
- cls.configs['records.config']['CONFIG']['proxy.config.diags.debug.enabled'] = 1
- cls.configs['records.config']['CONFIG']['proxy.config.diags.debug.tags'] = 'http2.*|ssl.*'
-
- # configure SSL multicert
- cls.configs['ssl_multicert.config'].add_line(
- 'dest_ip=* ssl_cert_name={0}\n'.format(helpers.tests_file_path('rsa_keys/www.example.com.pem'))
- )
-
- # remap configs
- cls.configs['remap.config'].add_line(
- 'map / http://127.0.0.1:{0}/'.format(cls.http_endpoint.address[1])
- )
-
- def __callH2Spec(self, section=None):
- '''
- Call h2spec
- '''
- args = [self.h2spec, '-h', 'localhost', '-p', str(self.http2_port), '-t', '-k']
- if section is not None:
- args.extend(['-s', section])
-
- log.info('full args = {0}'.format(args))
- p = subprocess.Popen(
- args,
- stdout=subprocess.PIPE,
- stdin=subprocess.PIPE,
- )
- self.stdout, self.stderr = p.communicate()
- log.info('\n' + self.stdout)
-
- return p.returncode
-
- def test_http2_spec_section(self):
- '''
- Test HTTP/2 w/ h2spec (Exceptional Scenario)
- '''
- sections = ['3.5', '4.2', '5.1', '5.3.1', '5.4.1', '5.5', '6.1', '6.2', '6.3', '6.4', '6.5', '6.5.2', '6.7', '6.8',
- '6.9', '6.9.1', '6.10', '8.1', '8.1.2', '8.1.2.2', '8.1.2.3', '8.1.2.6', '8.2']
- for section in sections:
- self.__callH2Spec(section)
- self.assertIn('All tests passed', self.stdout, 'Failed at section %s of RFC7540' % section)
-
- # TODO these tests cannot pass currently. move to above after ATS can pass them
- failing_sections = ['4.3']
- for section in failing_sections:
- self.__callH2Spec(section)
- self.assertNotIn('All tests passed', self.stdout, 'Failed at section %s of RFC7540' % section)
diff --git a/ci/tsqa/tests/test_https.py b/ci/tsqa/tests/test_https.py
deleted file mode 100644
index 8e45d6e..0000000
--- a/ci/tsqa/tests/test_https.py
+++ /dev/null
@@ -1,345 +0,0 @@
-# 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 OpenSSL import SSL
-import socket
-import time
-import helpers
-import tsqa.utils
-import os
-import logging
-unittest = tsqa.utils.import_unittest()
-
-log = logging.getLogger(__name__)
-# some ciphers to test with
-CIPHER_MAP = {
- 'rsa': 'ECDHE-RSA-AES256-GCM-SHA384',
- 'ecdsa': 'ECDHE-ECDSA-AES256-GCM-SHA384',
-}
-
-
-class CertSelectionMixin(object):
- def _get_cert(self, addr, sni_name=None, ciphers=None):
- '''
- Return the certificate for addr. Optionally sending sni_name
- '''
- ctx = SSL.Context(SSL.TLSv1_2_METHOD)
- # Set up client
- sock = SSL.Connection(ctx, socket.socket(socket.AF_INET, socket.SOCK_STREAM))
- sock.connect(addr)
- if sni_name is not None:
- sock.set_tlsext_host_name(sni_name)
- if ciphers is not None:
- ctx.set_cipher_list(ciphers)
- sock.do_handshake()
- return sock.get_peer_certificate()
-
- def _get_cert_chain(self, addr, sni_name=None, ciphers=None):
- '''
- Return the certificate chain for addr. Optionally sending sni_name
- '''
- ctx = SSL.Context(SSL.TLSv1_2_METHOD)
- # Set up client
- sock = SSL.Connection(ctx, socket.socket(socket.AF_INET, socket.SOCK_STREAM))
- sock.connect(addr)
- if sni_name is not None:
- sock.set_tlsext_host_name(sni_name)
- if ciphers is not None:
- ctx.set_cipher_list(ciphers)
- sock.do_handshake()
- return sock.get_peer_cert_chain()
-
- def test_star_ordering(self):
- '''
- We should be served the first match, since we aren't sending SNI headers
- '''
- addr = ('127.0.0.1', self.ssl_port)
- cert = self._get_cert(addr)
- self.assertEqual(cert.get_subject().commonName.decode(), 'www.example.com')
-
- def test_star_sni(self):
- '''
- Make sure we get the certificate we asked for if we pass in SNI headers
- '''
- addr = ('127.0.0.1', self.ssl_port)
- cert = self._get_cert(addr, sni_name='www.test.com')
- self.assertEqual(cert.get_subject().commonName.decode(), 'www.test.com')
-
- cert = self._get_cert(addr, sni_name='www.example.com')
- self.assertEqual(cert.get_subject().commonName.decode(), 'www.example.com')
-
- def test_ip_ordering(self):
- '''
- We should be served the first match, since we aren't sending SNI headers
- '''
- addr = ('127.0.0.2', self.ssl_port)
- cert = self._get_cert(addr)
- self.assertEqual(cert.get_subject().commonName.decode(), 'www.example.com')
-
- def test_ip_sni(self):
- '''
- Make sure we get the certificate we asked for if we pass in SNI headers
- '''
- addr = ('127.0.0.2', self.ssl_port)
- cert = self._get_cert(addr, sni_name='www.test.com')
- self.assertEqual(cert.get_subject().commonName.decode(), 'www.test.com')
-
- cert = self._get_cert(addr, sni_name='www.example.com')
- self.assertEqual(cert.get_subject().commonName.decode(), 'www.example.com')
-
- def _intermediate_ca_t(self, cipher):
- '''
- Method for testing intermediate CAs. We assume that www.example.com should
- return a certificate chaing of len 2 which includes intermediate.
- We also assume that www.test.com returns a single cert in the chain which
- is *not* intermediate
- '''
- # send a request that *should* get an intermediate CA
- addr = ('127.0.0.1', self.ssl_port)
- cert_chain = self._get_cert_chain(addr, ciphers=CIPHER_MAP[cipher])
- self.assertEqual(len(cert_chain), 2)
- self.assertEqual(cert_chain[0].get_subject().commonName.decode(), 'www.example.com')
- self.assertEqual(cert_chain[1].get_subject().commonName.decode(), 'intermediate')
-
- # send a request that shouldn't get an intermediate CA
- addr = ('127.0.0.1', self.ssl_port)
- cert_chain = self._get_cert_chain(addr, ciphers=CIPHER_MAP[cipher], sni_name='www.test.com')
- self.assertEqual(len(cert_chain), 1)
- self.assertEqual(cert_chain[0].get_subject().commonName.decode(), 'www.test.com')
-
-
-class TestRSA(helpers.EnvironmentCase, CertSelectionMixin):
- '''
- Tests for https for ATS configured with RSA certificates
- '''
- @classmethod
- def setUpEnv(cls, env):
- # add an SSL port to ATS
- cls.ssl_port = tsqa.utils.bind_unused_port()[1]
- cls.configs['records.config']['CONFIG']['proxy.config.http.server_ports'] += ' {0}:ssl'.format(cls.ssl_port)
- cls.configs['records.config']['CONFIG'].update({
- 'proxy.config.diags.debug.enabled': 1,
- 'proxy.config.diags.debug.tags': 'ssl',
- 'proxy.config.ssl.server.cipher_suite': CIPHER_MAP['rsa'],
- })
-
- # configure SSL multicert
- cls.configs['ssl_multicert.config'].add_line('dest_ip=127.0.0.2 ssl_cert_name={0} ssl_ca_name={1}'.format(
- helpers.tests_file_path('rsa_keys/www.example.com.pem'),
- helpers.tests_file_path('rsa_keys/intermediate.crt'),
- ))
- cls.configs['ssl_multicert.config'].add_line('dest_ip=127.0.0.2 ssl_cert_name={0}'.format(
- helpers.tests_file_path('rsa_keys/www.test.com.pem'),
- ))
-
- cls.configs['ssl_multicert.config'].add_line('dest_ip=* ssl_cert_name={0} ssl_ca_name={1}'.format(
- helpers.tests_file_path('rsa_keys/www.example.com.pem'),
- helpers.tests_file_path('rsa_keys/intermediate.crt'),
- ))
- cls.configs['ssl_multicert.config'].add_line('dest_ip=* ssl_cert_name={0}'.format(
- helpers.tests_file_path('rsa_keys/www.test.com.pem'),
- ))
-
- def test_rsa(self):
- addr = ('127.0.0.1', self.ssl_port)
- cert = self._get_cert(addr, ciphers=CIPHER_MAP['rsa'])
- self.assertEqual(cert.get_subject().commonName.decode(), 'www.example.com')
-
- def test_ecdsa(self):
- addr = ('127.0.0.1', self.ssl_port)
- with self.assertRaises(Exception):
- cert = self._get_cert(addr, ciphers=CIPHER_MAP['ecdsa'])
- self.assertEqual(cert.get_subject().commonName.decode(), 'www.example.com')
-
- def test_intermediate_ca_rsa(self):
- self._intermediate_ca_t('rsa')
-
- def test_intermediate_ca_ecdsa(self):
- with self.assertRaises(Exception):
- self._intermediate_ca_t('ecdsa')
-
-
-class TestECDSA(helpers.EnvironmentCase, CertSelectionMixin):
- '''
- Tests for https for ATS configured with ECDSA certificates
- '''
- @classmethod
- def setUpEnv(cls, env):
- # add an SSL port to ATS
- cls.ssl_port = tsqa.utils.bind_unused_port()[1]
- cls.configs['records.config']['CONFIG']['proxy.config.http.server_ports'] += ' {0}:ssl'.format(cls.ssl_port)
- cls.configs['records.config']['CONFIG'].update({
- 'proxy.config.diags.debug.enabled': 1,
- 'proxy.config.diags.debug.tags': 'ssl',
- 'proxy.config.ssl.server.cipher_suite': CIPHER_MAP['ecdsa'],
- })
-
- # configure SSL multicert
- cls.configs['ssl_multicert.config'].add_line('dest_ip=127.0.0.2 ssl_cert_name={0} ssl_ca_name={1}'.format(
- helpers.tests_file_path('ec_keys/www.example.com.pem'),
- helpers.tests_file_path('ec_keys/intermediate.crt'),
- ))
- cls.configs['ssl_multicert.config'].add_line('dest_ip=127.0.0.2 ssl_cert_name={0}'.format(
- helpers.tests_file_path('ec_keys/www.test.com.pem'),
- ))
-
- cls.configs['ssl_multicert.config'].add_line('dest_ip=* ssl_cert_name={0} ssl_ca_name={1}'.format(
- helpers.tests_file_path('ec_keys/www.example.com.pem'),
- helpers.tests_file_path('ec_keys/intermediate.crt'),
- ))
- cls.configs['ssl_multicert.config'].add_line('dest_ip=* ssl_cert_name={0}'.format(
- helpers.tests_file_path('ec_keys/www.test.com.pem'),
- ))
-
- def test_rsa(self):
- addr = ('127.0.0.1', self.ssl_port)
- with self.assertRaises(Exception):
- cert = self._get_cert(addr, ciphers=CIPHER_MAP['rsa'])
- self.assertEqual(cert.get_subject().commonName.decode(), 'www.example.com')
-
- def test_ecdsa(self):
- addr = ('127.0.0.1', self.ssl_port)
- cert = self._get_cert(addr, ciphers=CIPHER_MAP['ecdsa'])
- self.assertEqual(cert.get_subject().commonName.decode(), 'www.example.com')
-
- def test_intermediate_ca_rsa(self):
- with self.assertRaises(Exception):
- self._intermediate_ca_t('rsa')
-
- def test_intermediate_ca_ecdsa(self):
- self._intermediate_ca_t('ecdsa')
-
-
-class TestMix(helpers.EnvironmentCase, CertSelectionMixin):
- '''
- Tests for https for ATS configured with both ECDSA and RSA certificates
- '''
- @classmethod
- def setUpEnv(cls, env):
- # Temporarily skipping TestMix until we can figure out how to specify underlying open ssl versions
- # The behaviour of the intermediate cert chains depends on openssl version
- raise helpers.unittest.SkipTest('Skip TestMix until we figure out openssl version tracking');
- # add an SSL port to ATS
- cls.ssl_port = tsqa.utils.bind_unused_port()[1]
- cls.configs['records.config']['CONFIG']['proxy.config.http.server_ports'] += ' {0}:ssl'.format(cls.ssl_port)
- cls.configs['records.config']['CONFIG'].update({
- 'proxy.config.diags.debug.enabled': 1,
- 'proxy.config.diags.debug.tags': 'ssl',
- 'proxy.config.ssl.server.cipher_suite': '{0}:{1}'.format(CIPHER_MAP['ecdsa'], CIPHER_MAP['rsa']),
- })
-
- # configure SSL multicert
- cls.configs['ssl_multicert.config'].add_line('dest_ip=127.0.0.2 ssl_cert_name={0},{1} ssl_ca_name={2},{3}'.format(
- helpers.tests_file_path('rsa_keys/www.example.com.pem'),
- helpers.tests_file_path('ec_keys/www.example.com.pem'),
- helpers.tests_file_path('rsa_keys/intermediate.crt'),
- helpers.tests_file_path('ec_keys/intermediate.crt'),
- ))
- cls.configs['ssl_multicert.config'].add_line('dest_ip=127.0.0.2 ssl_cert_name={0},{1}'.format(
- helpers.tests_file_path('rsa_keys/www.test.com.pem'),
- helpers.tests_file_path('ec_keys/www.test.com.pem'),
- ))
-
- cls.configs['ssl_multicert.config'].add_line('dest_ip=* ssl_cert_name={0},{1} ssl_ca_name={2},{3}'.format(
- helpers.tests_file_path('rsa_keys/www.example.com.pem'),
- helpers.tests_file_path('ec_keys/www.example.com.pem'),
- helpers.tests_file_path('rsa_keys/intermediate.crt'),
- helpers.tests_file_path('ec_keys/intermediate.crt'),
- ))
- cls.configs['ssl_multicert.config'].add_line('dest_ip=* ssl_cert_name={0},{1}'.format(
- helpers.tests_file_path('rsa_keys/www.test.com.pem'),
- helpers.tests_file_path('ec_keys/www.test.com.pem'),
- ))
-
- def test_rsa(self):
- addr = ('127.0.0.1', self.ssl_port)
- cert = self._get_cert(addr, ciphers=CIPHER_MAP['rsa'])
- self.assertEqual(cert.get_subject().commonName.decode(), 'www.example.com')
-
- def test_ecdsa(self):
- addr = ('127.0.0.1', self.ssl_port)
- cert = self._get_cert(addr, ciphers=CIPHER_MAP['ecdsa'])
- self.assertEqual(cert.get_subject().commonName.decode(), 'www.example.com')
-
- def test_intermediate_ca_rsa(self):
- self._intermediate_ca_t('rsa')
-
- def test_intermediate_ca_ecdsa(self):
- self._intermediate_ca_t('ecdsa')
-
-
-class TestConfigFileGroup(helpers.EnvironmentCase, CertSelectionMixin):
- '''
- Tests for config file group with https
- The config file group includes a parent file ssl_multicert.config and some children files.
- when the content of a child file is updated but the file name hasn't been changed.
- The behavior is the same as the parent file in the group has been changed.
- In the test, a child file named www.unknown.com.pem, which is rsa_keys/www.test.com.pem at first,
- is updated to ec_keys/www.test.com.pem.
- The difference can be told by different results from calling get_cert() with different ciphers as paramters
- '''
- @classmethod
- def setUpEnv(cls, env):
- # add an SSL port to ATS
- cls.ssl_port = tsqa.utils.bind_unused_port()[1]
- cls.configs['records.config']['CONFIG']['proxy.config.http.server_ports'] += ' {0}:ssl'.format(cls.ssl_port)
- cls.configs['records.config']['CONFIG'].update({
- 'proxy.config.diags.debug.enabled': 1,
- 'proxy.config.diags.debug.tags': 'ssl',
- 'proxy.config.ssl.server.cipher_suite': '{0}:{1}'.format(CIPHER_MAP['ecdsa'], CIPHER_MAP['rsa']),
- })
- cls.configs['ssl_multicert.config'].add_line('dest_ip=* ssl_cert_name={0},{1} ssl_ca_name={2},{3}'.format(
- helpers.tests_file_path('rsa_keys/www.example.com.pem'),
- helpers.tests_file_path('ec_keys/www.example.com.pem'),
- helpers.tests_file_path('rsa_keys/intermediate.crt'),
- helpers.tests_file_path('ec_keys/intermediate.crt'),
- ))
- cls.configs['ssl_multicert.config'].add_line('dest_ip=127.0.0.3 ssl_cert_name={0}'.format(
- helpers.tests_file_path('www.unknown.com.pem'),
- ))
- os.system('cp %s %s' % (helpers.tests_file_path('rsa_keys/www.test.com.pem'), helpers.tests_file_path('www.unknown.com.pem')))
- log.info('cp %s %s' % (helpers.tests_file_path('rsa_keys/www.test.com.pem'), helpers.tests_file_path('www.unknown.com.pem')))
-
- def test_config_file_group(self):
- traffic_ctl = os.path.join(self.environment.layout.bindir, 'traffic_ctl')
- signal_cmd = [traffic_ctl, 'config', 'reload']
- addr = ('127.0.0.3', self.ssl_port)
- cert = self._get_cert(addr, ciphers=CIPHER_MAP['rsa'])
- self.assertEqual(cert.get_subject().commonName.decode(), 'www.test.com')
- with self.assertRaises(Exception):
- self._get_cert(addr, ciphers=CIPHER_MAP['ecdsa'])
- time.sleep(5)
- os.system('cp %s %s' % (helpers.tests_file_path('ec_keys/www.test.com.pem'), helpers.tests_file_path('www.unknown.com.pem')))
- log.info('cp %s %s' % (helpers.tests_file_path('ec_keys/www.test.com.pem'), helpers.tests_file_path('www.unknown.com.pem')))
- os.system(' '.join(signal_cmd))
- log.info(signal_cmd)
- # waiting for the reconfiguration completed
- sec = 0
- while True:
- time.sleep(5)
- sec += 5
- log.info("reloading: %d seconds" % (sec))
- self.assertLess(sec, 30)
- try:
- self._get_cert(addr, ciphers=CIPHER_MAP['ecdsa'])
- break
- except:
- continue
- cert = self._get_cert(addr, ciphers=CIPHER_MAP['ecdsa'])
- self.assertEqual(cert.get_subject().commonName.decode(), 'www.test.com')
- with self.assertRaises(Exception):
- self._get_cert(addr, ciphers=CIPHER_MAP['rsa'])
- os.system('rm %s' %(helpers.tests_file_path('www.unknown.com.pem')))
diff --git a/ci/tsqa/tests/test_keepalive.py b/ci/tsqa/tests/test_keepalive.py
deleted file mode 100644
index 9a67507..0000000
--- a/ci/tsqa/tests/test_keepalive.py
+++ /dev/null
@@ -1,481 +0,0 @@
-# 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 uuid
-import requests
-import time
-import logging
-import socket
-
-import helpers
-
-import tsqa.test_cases
-import tsqa.utils
-import tsqa.endpoint
-
-log = logging.getLogger(__name__)
-
-import SocketServer
-
-
-class KeepaliveTCPHandler(SocketServer.BaseRequestHandler):
- """
- A subclass of RequestHandler which will return a connection uuid
- """
-
- def handle(self):
- # Receive the data in small chunks and retransmit it
- start = time.time()
- conn_id = uuid.uuid4().hex
- while True:
- now = time.time() - start
- data = self.request.recv(4096).strip()
- if data:
- log.debug('Sending data back to the client: {uid}'.format(uid=conn_id))
- else:
- log.debug('Client disconnected: {timeout}seconds'.format(timeout=now))
- break
- body = conn_id
- resp = ('HTTP/1.1 200 OK\r\n'
- 'Content-Length: {content_length}\r\n'
- 'Content-Type: text/html; charset=UTF-8\r\n'
- 'Connection: keep-alive\r\n'
- '\r\n'
- '{body}'.format(content_length=len(body), body=body))
- self.request.sendall(resp)
-
-
-class KeepAliveInMixin(object):
- """Mixin for keep alive in.
-
- TODO: Allow protocol to be specified for ssl traffic
- """
- def _get_socket(self):
- s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
- s.connect(('127.0.0.1', int(self.configs['records.config']['CONFIG']['proxy.config.http.server_ports'])))
- return s
-
- def _headers_to_str(self, headers):
- if headers is None:
- headers = {}
- request = ''
- for k, v in headers.iteritems():
- request += '{0}: {1}\r\n'.format(k, v)
- return request
-
- def _aux_KA_working_path_connid(self, protocol, headers=None):
- if headers is None:
- headers = {}
- with requests.Session() as s:
- url = '{0}://127.0.0.1:{1}/'.format(protocol, int(self.configs['records.config']['CONFIG']['proxy.config.http.server_ports']))
- conn_id = None
- for x in xrange(1, 10):
- ret = s.get(url, headers=headers)
- self.assertEqual(ret.status_code, 200)
- if conn_id is None:
- conn_id = ret.text
- else:
- self.assertEqual(ret.text, conn_id)
-
- def _aux_working_path(self, protocol, headers=None):
- # connect tcp
- s = self._get_socket()
-
- request = ('GET /exists/ HTTP/1.1\r\n'
- 'Host: foobar.com\r\n')
- request += self._headers_to_str(headers)
- request += '\r\n'
-
- for x in xrange(1, 10):
- s.send(request)
- response = s.recv(4096)
- # cheat, since we know what the body should have
- if not response.endswith('hello'):
- response += s.recv(4096)
- self.assertIn('HTTP/1.1 200 OK', response)
- self.assertIn('hello', response)
-
- def _aux_error_path(self, protocol, headers=None):
- # connect tcp
- s = self._get_socket()
-
- request = ('GET / HTTP/1.1\r\n'
- 'Host: foobar.com\r\n')
- request += self._headers_to_str(headers)
- request += '\r\n'
- for x in xrange(1, 10):
- s.send(request)
- response = s.recv(4096)
- self.assertIn('HTTP/1.1 404 Not Found on Accelerator', response)
-
- def _aux_error_path_post(self, protocol, headers=None):
- '''
- Ensure that sending a request with a body doesn't break the keepalive session
- '''
- # connect tcp
- s = self._get_socket()
-
- request = ('POST / HTTP/1.1\r\n'
- 'Host: foobar.com\r\n'
- 'Content-Length: 10\r\n')
- request += self._headers_to_str(headers)
- request += '\r\n'
- request += '1234567890'
-
- for x in xrange(1, 10):
- try:
- s.send(request)
- except IOError:
- s = self._get_socket()
- s.send(request)
-
- response = s.recv(4096)
- # Check if client disconnected
- if response:
- self.assertIn('HTTP/1.1 404 Not Found on Accelerator', response)
-
-
-class BasicTestsOutMixin(object):
-
- def _aux_KA_origin(self, protocol, headers=None):
- '''
- Test that the origin does in fact support keepalive
- '''
- conn_id = None
- with requests.Session() as s:
- url = '{0}://127.0.0.1:{1}/'.format(protocol, self.socket_server.port)
- for x in xrange(1, 10):
- ret = s.get(url, verify=False, headers=headers)
- if not conn_id:
- conn_id = ret.text.strip()
- self.assertEqual(ret.status_code, 200)
- self.assertEqual(ret.text.strip(), conn_id, "Client reports server closed connection")
-
- def _aux_KA_proxy(self, protocol, headers=None):
- '''
- Test that keepalive works through ATS to that origin
- '''
- url = '{0}://127.0.0.1:{1}'.format(
- protocol,
- self.configs['records.config']['CONFIG']['proxy.config.http.server_ports'],
- )
- conn_id = None
- for x in xrange(1, 10):
- ret = requests.get(url, verify=False, headers=headers)
- if not conn_id:
- conn_id = ret.text.strip()
- self.assertEqual(ret.status_code, 200)
- self.assertEqual(ret.text.strip(), conn_id, "Client reports server closed connection")
-
-
-class TimeoutOutMixin(object):
-
- def _aux_KA_timeout_direct(self, protocol):
- '''Tests that origin does not timeout using keepalive.'''
- with requests.Session() as s:
- url = '{0}://127.0.0.1:{1}/'.format(protocol, self.socket_server.port)
- conn_id = None
- for x in xrange(0, 3):
- ret = s.get(url, verify=False)
- if not conn_id:
- conn_id = ret.text.strip()
- self.assertEqual(ret.text.strip(), conn_id, "Client reports server closed connection")
- time.sleep(3)
-
- def _aux_KA_timeout_proxy(self, protocol):
- '''Tests that keepalive timeout is honored through ATS to origin.'''
- url = '{0}://127.0.0.1:{1}'.format(
- protocol,
- self.configs['records.config']['CONFIG']['proxy.config.http.server_ports'],
- )
- conn_id = None
- for x in xrange(0, 3):
- ret = requests.get(url, verify=False)
- if not conn_id:
- conn_id = ret.text.strip()
- self.assertEqual(ret.text.strip(), conn_id, "Client reports server closed connection")
- time.sleep(3)
-
-
-class OriginMinMaxMixin(object):
-
- def _aux_KA_min_origin(self, protocol):
- '''Tests that origin_min_keep_alive_connections is honored.'''
- url = '{0}://127.0.0.1:{1}'.format(
- protocol,
- self.configs['records.config']['CONFIG']['proxy.config.http.server_ports'],
- )
- ret = requests.get(url, verify=False)
- conn_id = ret.text.strip()
- time.sleep(3)
- ret = requests.get(url, verify=False)
- self.assertEqual(ret.text.strip(), conn_id, "Client reports server closed connection")
-
-
-class TestKeepAliveInHTTP(tsqa.test_cases.DynamicHTTPEndpointCase, helpers.EnvironmentCase, KeepAliveInMixin):
- @classmethod
- def setUpEnv(cls, env):
-
- def hello(request):
- return 'hello'
- cls.http_endpoint.add_handler('/exists/', hello)
-
- cls.configs['remap.config'].add_line('map /exists/ http://127.0.0.1:{0}/exists/'.format(cls.http_endpoint.address[1]))
-
- # only add server headers when there weren't any
- cls.configs['records.config']['CONFIG']['proxy.config.http.response_server_enabled'] = 2
- cls.configs['records.config']['CONFIG']['proxy.config.http.keep_alive_enabled_in'] = 1
- cls.configs['records.config']['CONFIG']['share_server_session'] = 2
-
- # set only one ET_NET thread (so we don't have to worry about the per-thread pools causing issues)
- cls.configs['records.config']['CONFIG']['proxy.config.exec_thread.limit'] = 1
- cls.configs['records.config']['CONFIG']['proxy.config.exec_thread.autoconfig'] = 0
-
- def test_working_path(self):
- self._aux_working_path("http")
-
- def test_error_path(self):
- self._aux_error_path("http")
-
- def test_error_path_post(self):
- '''
- Ensure that sending a request with a body doesn't break the keepalive session
- '''
- self._aux_error_path_post("http")
-
-
-class TestKeepAliveOriginConnOutHTTP(helpers.EnvironmentCase, OriginMinMaxMixin):
- @classmethod
- def setUpEnv(cls, env):
- '''
- This function is responsible for setting up the environment for this fixture
- This includes everything pre-daemon start
- '''
- # create a socket server
- cls.socket_server = tsqa.endpoint.SocketServerDaemon(KeepaliveTCPHandler)
- cls.socket_server.start()
- cls.socket_server.ready.wait()
- cls.configs['remap.config'].add_line('map / http://127.0.0.1:{0}/'.format(cls.socket_server.port))
-
- # only add server headers when there weren't any
- cls.configs['records.config']['CONFIG']['proxy.config.http.response_server_enabled'] = 2
- cls.configs['records.config']['CONFIG']['proxy.config.http.keep_alive_enabled_out'] = 1
- cls.configs['records.config']['CONFIG']['share_server_session'] = 2
-
- # set only one ET_NET thread (so we don't have to worry about the per-thread pools causing issues)
- cls.configs['records.config']['CONFIG']['proxy.config.exec_thread.limit'] = 1
- cls.configs['records.config']['CONFIG']['proxy.config.exec_thread.autoconfig'] = 0
-
- # Timeouts
- cls.configs['records.config']['CONFIG']['proxy.config.http.keep_alive_no_activity_timeout_out'] = 1
- cls.configs['records.config']['CONFIG']['proxy.config.http.transaction_no_activity_timeout_out'] = 1
-
- cls.configs['records.config']['CONFIG']['proxy.config.http.origin_min_keep_alive_connections'] = 1
-
- def test_KA_min_origin(self):
- '''Tests that origin_min_keep_alive_connections is honored via http.'''
- self._aux_KA_min_origin("http")
-
-
-class TestKeepAliveOriginConnOutHTTPS(helpers.EnvironmentCase, OriginMinMaxMixin):
- @classmethod
- def setUpEnv(cls, env):
- '''
- This function is responsible for setting up the environment for this fixture
- This includes everything pre-daemon start
- '''
- # create a socket server
- cls.socket_server = tsqa.endpoint.SSLSocketServerDaemon(
- KeepaliveTCPHandler,
- helpers.tests_file_path('cert.pem'),
- helpers.tests_file_path('key.pem'),
- )
- cls.socket_server.start()
- cls.socket_server.ready.wait()
- cls.configs['remap.config'].add_line('map / https://127.0.0.1:{0}/\n'.format(cls.socket_server.port))
-
- # only add server headers when there weren't any
- cls.configs['records.config']['CONFIG']['proxy.config.http.response_server_enabled'] = 2
- cls.configs['records.config']['CONFIG']['proxy.config.http.keep_alive_enabled_out'] = 1
- cls.configs['records.config']['CONFIG']['share_server_session'] = 2
-
- # set only one ET_NET thread (so we don't have to worry about the per-thread pools causing issues)
- cls.configs['records.config']['CONFIG']['proxy.config.exec_thread.limit'] = 1
- cls.configs['records.config']['CONFIG']['proxy.config.exec_thread.autoconfig'] = 0
-
- # Timeouts
- cls.configs['records.config']['CONFIG']['proxy.config.http.keep_alive_no_activity_timeout_out'] = 1
- cls.configs['records.config']['CONFIG']['proxy.config.http.transaction_no_activity_timeout_out'] = 1
-
- cls.configs['records.config']['CONFIG']['proxy.config.http.origin_min_keep_alive_connections'] = 1
-
- def test_KA_min_origin(self):
- '''Tests that origin_min_keep_alive_connections is honored via https.'''
- self._aux_KA_min_origin("http")
-
-
-class TestKeepAliveOutHTTP(helpers.EnvironmentCase, BasicTestsOutMixin, TimeoutOutMixin):
- @classmethod
- def setUpEnv(cls, env):
- '''
- This function is responsible for setting up the environment for this fixture
- This includes everything pre-daemon start
- '''
- # create a socket server
- cls.socket_server = tsqa.endpoint.SocketServerDaemon(KeepaliveTCPHandler)
- cls.socket_server.start()
- cls.socket_server.ready.wait()
- cls.configs['remap.config'].add_line('map / http://127.0.0.1:{0}/'.format(cls.socket_server.port))
-
- # only add server headers when there weren't any
- cls.configs['records.config']['CONFIG']['proxy.config.http.response_server_enabled'] = 2
- cls.configs['records.config']['CONFIG']['proxy.config.http.keep_alive_enabled_out'] = 1
- cls.configs['records.config']['CONFIG']['share_server_session'] = 2
-
- # set only one ET_NET thread (so we don't have to worry about the per-thread pools causing issues)
- cls.configs['records.config']['CONFIG']['proxy.config.exec_thread.limit'] = 1
- cls.configs['records.config']['CONFIG']['proxy.config.exec_thread.autoconfig'] = 0
-
- # Timeouts
- cls.configs['records.config']['CONFIG']['proxy.config.http.keep_alive_no_activity_timeout_out'] = 10
- cls.configs['records.config']['CONFIG']['proxy.config.http.transaction_no_activity_timeout_out'] = 2
-
- def test_KA_origin(self):
- '''Test that the origin does in fact support keepalive via http.'''
- self._aux_KA_origin("http")
-
- def test_KA_proxy(self):
- '''Tests that keepalive works through ATS to origin via http.'''
- self._aux_KA_proxy("http")
-
- def test_KA_timeout_direct(self):
- '''Tests that origin does not timeout using keepalive via http.'''
- self._aux_KA_timeout_direct("http")
-
- def test_KA_timeout_proxy(self):
- '''Tests that keepalive timeout is honored through ATS to origin via http.'''
- self._aux_KA_timeout_proxy("http")
-
-
-class TestKeepAliveOutHTTPS(helpers.EnvironmentCase, BasicTestsOutMixin, TimeoutOutMixin):
- @classmethod
- def setUpEnv(cls, env):
- '''
- This function is responsible for setting up the environment for this fixture
- This includes everything pre-daemon start
- '''
- # create a socket server
- cls.socket_server = tsqa.endpoint.SSLSocketServerDaemon(
- KeepaliveTCPHandler,
- helpers.tests_file_path('cert.pem'),
- helpers.tests_file_path('key.pem'),
- )
- cls.socket_server.start()
- cls.socket_server.ready.wait()
- cls.configs['remap.config'].add_line('map / https://127.0.0.1:{0}/\n'.format(cls.socket_server.port))
-
- # only add server headers when there weren't any
- cls.configs['records.config']['CONFIG']['proxy.config.http.response_server_enabled'] = 2
- cls.configs['records.config']['CONFIG']['proxy.config.http.keep_alive_enabled_out'] = 1
- cls.configs['records.config']['CONFIG']['share_server_session'] = 2
-
- # set only one ET_NET thread (so we don't have to worry about the per-thread pools causing issues)
- cls.configs['records.config']['CONFIG']['proxy.config.exec_thread.limit'] = 1
- cls.configs['records.config']['CONFIG']['proxy.config.exec_thread.autoconfig'] = 0
-
- # Timeouts
- cls.configs['records.config']['CONFIG']['proxy.config.http.keep_alive_no_activity_timeout_out'] = 10
- cls.configs['records.config']['CONFIG']['proxy.config.http.transaction_no_activity_timeout_out'] = 2
-
- def test_KA_origin(self):
- '''Test that the origin does in fact support keepalive via https.'''
- self._aux_KA_origin("https")
-
- def test_KA_proxy(self):
- '''Tests that keepalive works through ATS to origin via https.'''
- self._aux_KA_proxy("http")
-
- def test_KA_timeout_direct(self):
- '''Tests that origin does not timeout using keepalive via https.'''
- self._aux_KA_timeout_direct("https")
-
- def test_KA_timeout_proxy(self):
- '''Tests that keepalive timeout is honored through ATS to origin via https.'''
- self._aux_KA_timeout_proxy("http")
-
-
-# TODO: refactor these tests, these are *very* similar, we should paramatarize them
-# Some basic tests for auth_sever_session_private
-class TestKeepAlive_Authorization_private(helpers.EnvironmentCase, BasicTestsOutMixin, KeepAliveInMixin):
- @classmethod
- def setUpEnv(cls, env):
-
- cls.socket_server = tsqa.endpoint.SocketServerDaemon(KeepaliveTCPHandler)
- cls.socket_server.start()
- cls.socket_server.ready.wait()
- cls.configs['remap.config'].add_line('map / http://127.0.0.1:{0}/exists/'.format(cls.socket_server.port))
-
- # only add server headers when there weren't any
- cls.configs['records.config']['CONFIG']['proxy.config.http.response_server_enabled'] = 2
- cls.configs['records.config']['CONFIG']['proxy.config.http.keep_alive_enabled_in'] = 1
- cls.configs['records.config']['CONFIG']['share_server_session'] = 2
-
- # set only one ET_NET thread (so we don't have to worry about the per-thread pools causing issues)
- cls.configs['records.config']['CONFIG']['proxy.config.exec_thread.limit'] = 1
- cls.configs['records.config']['CONFIG']['proxy.config.exec_thread.autoconfig'] = 0
-
- # make auth sessions private
- cls.configs['records.config']['CONFIG']['proxy.config.auth_server_session_private'] = 1
-
- def test_KA_server(self):
- '''Tests that keepalive works through ATS to origin via https.'''
- with self.assertRaises(AssertionError):
- self._aux_KA_proxy("http", headers={'Authorization': 'Foo'})
-
- def test_KA_client(self):
- '''Tests that keepalive works through ATS to origin via https.'''
- with self.assertRaises(AssertionError):
- self._aux_KA_working_path_connid("http", headers={'Authorization': 'Foo'})
-
-
-class TestKeepAlive_Authorization_no_private(helpers.EnvironmentCase, BasicTestsOutMixin, KeepAliveInMixin):
- @classmethod
- def setUpEnv(cls, env):
-
- cls.socket_server = tsqa.endpoint.SocketServerDaemon(KeepaliveTCPHandler)
- cls.socket_server.start()
- cls.socket_server.ready.wait()
- cls.configs['remap.config'].add_line('map / http://127.0.0.1:{0}/exists/'.format(cls.socket_server.port))
-
- # only add server headers when there weren't any
- cls.configs['records.config']['CONFIG']['proxy.config.http.response_server_enabled'] = 2
- cls.configs['records.config']['CONFIG']['proxy.config.http.keep_alive_enabled_in'] = 1
- cls.configs['records.config']['CONFIG']['share_server_session'] = 2
-
- # set only one ET_NET thread (so we don't have to worry about the per-thread pools causing issues)
- cls.configs['records.config']['CONFIG']['proxy.config.exec_thread.limit'] = 1
- cls.configs['records.config']['CONFIG']['proxy.config.exec_thread.autoconfig'] = 0
-
- # make auth sessions private
- cls.configs['records.config']['CONFIG']['proxy.config.http.auth_server_session_private'] = 0
-
- def test_KA_server(self):
- '''Tests that keepalive works through ATS to origin via https.'''
- self._aux_KA_proxy("http", headers={'Authorization': 'Foo'})
-
- def test_KA_client(self):
- '''Tests that keepalive works through ATS to origin via https.'''
- self._aux_KA_working_path_connid("http", headers={'Authorization': 'Foo'})
diff --git a/ci/tsqa/tests/test_origin_max_connections.py b/ci/tsqa/tests/test_origin_max_connections.py
deleted file mode 100644
index c5bf41a..0000000
--- a/ci/tsqa/tests/test_origin_max_connections.py
+++ /dev/null
@@ -1,213 +0,0 @@
-'''
-Test the configure entry : proxy.config.http.origin_max_connections
-'''
-
-# 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 time
-import logging
-import uuid
-import socket
-import requests
-import tsqa.test_cases
-import helpers
-import thread
-from multiprocessing import Pool
-import SocketServer
-import os
-
-log = logging.getLogger(__name__)
-
-
-# TODO: seems like a useful shared class- either add to httpbin or some shared lib
-class KAHandler(SocketServer.BaseRequestHandler):
- '''SocketServer that returns the connection-id as the body
- '''
- # class variable to set number of active sessions
- alive_sessions = 0
-
- def handle(self):
- KAHandler.alive_sessions += 1
- # Receive the data in small chunks and retransmit it
- conn_id = uuid.uuid4().hex
- start = time.time()
- while True:
- data = self.request.recv(4096).strip()
- if data:
- log.info('Sending data back to the client: {uid}'.format(uid=conn_id))
- else:
- log.info('Client disconnected: {timeout}seconds'.format(timeout=time.time() - start))
- break
- body = conn_id
- if 'timeout' in data:
- print 'sleep for a long time!'
- time.sleep(4)
- else:
- time.sleep(2)
- resp = ('HTTP/1.1 200 OK\r\n'
- 'Content-Length: {content_length}\r\n'
- 'Content-Type: text/html; charset=UTF-8\r\n'
- 'Connection: keep-alive\r\n'
- 'X-Current-Sessions: {alive_sessions}\r\n'
- '\r\n'
- '{body}'.format(content_length=len(body), alive_sessions=KAHandler.alive_sessions, body=body))
- self.request.sendall(resp)
- KAHandler.alive_sessions -= 1
-
-
-class TestKeepAlive_Origin_Max_connections(helpers.EnvironmentCase):
- @classmethod
- def setUpEnv(cls, env):
- cls.traffic_server_host = '127.0.0.1'
- cls.traffic_server_port = int(cls.configs['records.config']['CONFIG']['proxy.config.http.server_ports'])
- cls.socket_server_port = int(tsqa.utils.bind_unused_port()[1])
-
- log.info("socket_server_port = %d" % (cls.socket_server_port))
- cls.server = tsqa.endpoint.SocketServerDaemon(KAHandler, port=cls.socket_server_port)
- cls.server.start()
- cls.server.ready.wait()
-
- cls.socket_server_port2 = int(tsqa.utils.bind_unused_port()[1])
- cls.server2 = tsqa.endpoint.SocketServerDaemon(KAHandler, port=cls.socket_server_port2)
- cls.server2.start()
- cls.server2.ready.wait()
-
- queue_path = os.path.join(cls.environment.layout.sysconfdir, 'queue.conf')
- with open(queue_path, 'w') as fh:
- fh.write('CONFIG proxy.config.http.origin_max_connections_queue INT 2')
-
- noqueue_path = os.path.join(cls.environment.layout.sysconfdir, 'noqueue.conf')
- with open(noqueue_path, 'w') as fh:
- fh.write('CONFIG proxy.config.http.origin_max_connections_queue INT 0')
-
- cls.configs['remap.config'].add_line('map /other/queue/ http://127.0.0.1:{0} @plugin=conf_remap.so @pparam={1}'.format(cls.socket_server_port2, queue_path))
- cls.configs['remap.config'].add_line('map /other/noqueue/ http://127.0.0.1:{0} @plugin=conf_remap.so @pparam={1}'.format(cls.socket_server_port2, noqueue_path))
- cls.configs['remap.config'].add_line('map /other/ http://127.0.0.1:{0}'.format(cls.socket_server_port2))
- cls.configs['remap.config'].add_line('map /queue/ http://127.0.0.1:{0} @plugin=conf_remap.so @pparam={1}'.format(cls.socket_server_port, queue_path))
- cls.configs['remap.config'].add_line('map /noqueue/ http://127.0.0.1:{0} @plugin=conf_remap.so @pparam={1}'.format(cls.socket_server_port, noqueue_path))
- cls.configs['remap.config'].add_line('map / http://127.0.0.1:{0}'.format(cls.socket_server_port))
-
- cls.configs['records.config']['CONFIG'].update({
- 'proxy.config.http.origin_max_connections': 1,
- 'proxy.config.http.keep_alive_enabled_out': 1,
- 'proxy.config.http.keep_alive_no_activity_timeout_out': 1,
- 'proxy.config.http.transaction_active_timeout_out': 2,
- 'proxy.config.http.connect_attempts_timeout': 2,
- 'proxy.config.http.connect_attempts_rr_retries': 0,
- 'proxy.config.exec_thread.limit': 1,
- 'proxy.config.exec_thread.autoconfig': 0,
- })
-
- def _send_requests(self, total_requests, path='', other=False):
- url = 'http://{0}:{1}/{2}'.format(self.traffic_server_host, self.traffic_server_port, path)
- url2 = 'http://{0}:{1}/other/{2}'.format(self.traffic_server_host, self.traffic_server_port, path)
- jobs = []
- jobs2 = []
- pool = Pool(processes=4)
- for _ in xrange(0, total_requests):
- jobs.append(pool.apply_async(requests.get, (url,)))
- if other:
- jobs2.append(pool.apply_async(requests.get, (url2,)))
-
- results = []
- results2 = []
- for j in jobs:
- try:
- results.append(j.get())
- except Exception as e:
- results.append(e)
-
- for j in jobs2:
- try:
- results2.append(j.get())
- except Exception as e:
- results2.append(e)
-
- return results, results2
-
-
- # TODO: enable after TS-4340 is merged
- # and re-enable `other` for the remaining queueing tests
- def tesst_origin_scoping(self):
- '''Send 2 requests to loopback (on separate ports) and ensure that they run in parallel
- '''
- results, results2 = self._send_requests(1, other=True)
-
- # TS-4340
- # ensure that the 2 origins (2 different ports on loopback) were running in parallel
- for i in xrange(0, REQUEST_COUNT):
- self.assertEqual(int(results[i].get().headers['X-Current-Sessions']), 2)
- self.assertEqual(int(results2[i].get().headers['X-Current-Sessions']), 2)
-
- def test_origin_default_queueing(self):
- '''By default we have no queue limit
- '''
- REQUEST_COUNT = 4
- results, results2 = self._send_requests(REQUEST_COUNT)
-
- for x in xrange(0, REQUEST_COUNT):
- self.assertEqual(results[x].status_code, 200)
- #self.assertEqual(results2[x].status_code, 200)
-
- def test_origin_queueing(self):
- '''If a queue is set, N requests are queued and the rest immediately fail
- '''
- REQUEST_COUNT = 4
- results, results2 = self._send_requests(REQUEST_COUNT, path='queue/')
-
- success = 0
- fail = 0
- for x in xrange(0, REQUEST_COUNT):
- if results[x].status_code == 200:
- success += 1
- else:
- fail += 1
- self.assertEqual(success, 3)
-
- def test_origin_queueing_timeouts(self):
- '''Lets have some requests timeout and ensure that the queue is freed up
- '''
- REQUEST_COUNT = 4
- results, results2 = self._send_requests(REQUEST_COUNT, path='queue/timeout')
-
- success = 0
- fail = 0
- for x in xrange(0, REQUEST_COUNT):
- if results[x].status_code == 200:
- success += 1
- print 'success', x
- else:
- fail += 1
- self.assertEqual(fail, 4)
-
- self.test_origin_queueing()
-
- def test_origin_no_queueing(self):
- '''If the queue is set to 0, all requests past the max immediately fail
- '''
- REQUEST_COUNT = 4
- results, results2 = self._send_requests(REQUEST_COUNT, path='noqueue/')
-
- success = 0
- fail = 0
- for x in xrange(0, REQUEST_COUNT):
- if results[x].status_code == 200:
- success += 1
- else:
- fail += 1
- print 'results:', success, fail
- self.assertEqual(success, 1)
diff --git a/ci/tsqa/tests/test_origin_min_keep_alive_connection.py b/ci/tsqa/tests/test_origin_min_keep_alive_connection.py
deleted file mode 100644
index 36625f5..0000000
--- a/ci/tsqa/tests/test_origin_min_keep_alive_connection.py
+++ /dev/null
@@ -1,99 +0,0 @@
-'''
-Test the configure entry : proxy.config.http.origin_min_keep_alive_connections
-'''
-
-# 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 time
-import logging
-import uuid
-import socket
-import requests
-import tsqa.test_cases
-import helpers
-import SocketServer
-
-log = logging.getLogger(__name__)
-
-
-class KAHandler(SocketServer.BaseRequestHandler):
- """
- A subclass of RequestHandler which return chunked encoding optionally
-
- /parts/sleep_time/close
- parts: number of parts to send
- sleep_time: time between parts
- close: bool whether to close properly
- """
-
- def handle(self):
- # Receive the data in small chunks and retransmit it
- conn_id = uuid.uuid4().hex
- start = time.time()
- while True:
- data = self.request.recv(4096).strip()
- if data:
- log.info('Sending data back to the client: {uid}'.format(uid=conn_id))
- else:
- log.info('Client disconnected: {timeout}seconds'.format(timeout=time.time() - start))
- break
- body = conn_id
- time.sleep(1)
- resp = ('HTTP/1.1 200 OK\r\n'
- 'Content-Length: {content_length}\r\n'
- 'Content-Type: text/html; charset=UTF-8\r\n'
- 'Connection: keep-alive\r\n'
- '\r\n'
- '{body}'.format(content_length=len(body), body=body))
- self.request.sendall(resp)
-
-
-class TestKeepAlive_Origin_Min_connections(helpers.EnvironmentCase):
- @classmethod
- def setUpEnv(cls, env):
- cls.traffic_server_host = '127.0.0.1'
- cls.traffic_server_port = int(cls.configs['records.config']['CONFIG']['proxy.config.http.server_ports'])
- cls.socket_server_port = int(tsqa.utils.bind_unused_port()[1])
- log.info("socket_server_port = %d" % (cls.socket_server_port))
- cls.server = tsqa.endpoint.SocketServerDaemon(KAHandler, port=cls.socket_server_port)
- cls.server.start()
- cls.server.ready.wait()
-
- cls.configs['remap.config'].add_line('map / http://127.0.0.1:{0}'.format(cls.socket_server_port))
- cls.origin_keep_alive_timeout = 1
-
- cls.configs['records.config']['CONFIG'].update({
- 'proxy.config.http.origin_min_keep_alive_connections': 1,
- 'proxy.config.http.keep_alive_enabled_out': 1,
- 'proxy.config.http.keep_alive_no_activity_timeout_out': cls.origin_keep_alive_timeout,
- 'proxy.config.exec_thread.limit': 1,
- 'proxy.config.exec_thread.autoconfig': 0,
- })
-
- def test_origin_min_connection(self):
- response_uuids = []
- # make the request N times, ensure that they are on the same connection
- for _ in xrange(0, 3):
- ret = requests.get('http://{0}:{1}/'.format(self.traffic_server_host, self.traffic_server_port))
- response_uuids.append(ret.text)
-
- self.assertEqual(1, len(set(response_uuids)))
-
- # sleep for a time greater than the keepalive timeout and ensure its the same connection
- time.sleep(self.origin_keep_alive_timeout * 2)
- ret = requests.get('http://{0}:{1}/'.format(self.traffic_server_host, self.traffic_server_port))
- self.assertEqual(ret.text, response_uuids[0])
diff --git a/ci/tsqa/tests/test_redirection.py b/ci/tsqa/tests/test_redirection.py
deleted file mode 100644
index 5a0b4ce..0000000
--- a/ci/tsqa/tests/test_redirection.py
+++ /dev/null
@@ -1,42 +0,0 @@
-# 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 requests
-import helpers
-import tsqa.test_cases
-import tsqa.utils
-import tsqa.endpoint
-
-
-class TestRedirection(helpers.EnvironmentCase, tsqa.test_cases.HTTPBinCase):
- @classmethod
- def setUpEnv(cls, env):
- cls.configs['records.config']['CONFIG'].update({
- 'proxy.config.http.redirection_enabled': 1,
- 'proxy.config.http.number_of_redirections': 10
- })
- cls.configs['remap.config'].add_line('map / http://127.0.0.1:{0}'.format(cls.http_endpoint.address[1]))
-
- def test_redirection(self):
- server_ports = self.configs['records.config']['CONFIG']['proxy.config.http.server_ports']
-
- # By default Requests will perform location redirection
- # Disable redirection handling with the allow_redirects parameter
- r = requests.get('http://127.0.0.1:{0}/redirect/9'.format(server_ports), allow_redirects=False)
- self.assertEqual(r.status_code, 200)
-
- r = requests.get('http://127.0.0.1:{0}/redirect/10'.format(server_ports), allow_redirects=False)
- self.assertEqual(r.status_code, 302)
diff --git a/ci/tsqa/tests/test_remap.py b/ci/tsqa/tests/test_remap.py
deleted file mode 100644
index 9b42f10..0000000
--- a/ci/tsqa/tests/test_remap.py
+++ /dev/null
@@ -1,130 +0,0 @@
-# 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 requests
-import logging
-
-import helpers
-
-import tsqa.test_cases
-import tsqa.utils
-import tsqa.endpoint
-
-log = logging.getLogger(__name__)
-
-
-class TestRemapHTTP(tsqa.test_cases.DynamicHTTPEndpointCase, helpers.EnvironmentCase):
- @classmethod
- def setUpEnv(cls, env):
- cls.configs['records.config']['CONFIG'].update({
- 'proxy.config.diags.debug.enabled': 1,
- 'proxy.config.diags.debug.tags': 'url.*',
- })
-
- cls.configs['remap.config'].add_line(
- 'map http://www.example.com http://127.0.0.1:{0}'.format(cls.http_endpoint.address[1])
- )
- cls.configs['remap.config'].add_line(
- 'map http://www.example.com:8080 http://127.0.0.1:{0}'.format(cls.http_endpoint.address[1])
- )
-
- def hello(request):
- return 'hello'
- cls.http_endpoint.add_handler('/', hello)
-
- def test_remap_http(self):
- s = requests.Session()
- http_port = self.configs['records.config']['CONFIG']['proxy.config.http.server_ports']
- url = 'http://127.0.0.1:{0}/'.format(http_port)
-
- ret = s.get(url)
- self.assertEqual(ret.status_code, 404)
-
- s.headers.update({'Host': 'www.example.com'})
- ret = s.get(url)
- self.assertEqual(ret.status_code, 200)
-
- s.headers.update({'Host': 'www.example.com:80'})
- ret = s.get(url)
- self.assertEqual(ret.status_code, 200)
-
- s.headers.update({'Host': 'www.example.com:8080'})
- ret = s.get(url)
- self.assertEqual(ret.status_code, 200)
-
- s.headers.update({'Host': 'www.test.com'})
- ret = s.get(url)
- self.assertEqual(ret.status_code, 404)
-
- s.headers.update({'Host': 'www.example.com:1234'})
- ret = s.get(url)
- self.assertEqual(ret.status_code, 404)
-
-
-class TestRemapHTTPS(tsqa.test_cases.DynamicHTTPEndpointCase, helpers.EnvironmentCase):
- @classmethod
- def setUpEnv(cls, env):
- # set an SSL port to ATS
- cls.ssl_port = tsqa.utils.bind_unused_port()[1]
- cls.configs['records.config']['CONFIG']['proxy.config.http.server_ports'] += ' {0}:ssl'.format(cls.ssl_port)
- cls.configs['records.config']['CONFIG'].update({
- 'proxy.config.diags.debug.enabled': 1,
- 'proxy.config.diags.debug.tags': 'url.*'
- })
-
- cls.configs['remap.config'].add_line(
- 'map https://www.example.com http://127.0.0.1:{0}'.format(cls.http_endpoint.address[1])
- )
- cls.configs['remap.config'].add_line(
- 'map https://www.example.com:4443 http://127.0.0.1:{0}'.format(cls.http_endpoint.address[1])
- )
- # configure SSL multicert
- cls.configs['ssl_multicert.config'].add_line(
- 'dest_ip=* ssl_cert_name={0}'.format(helpers.tests_file_path('rsa_keys/www.example.com.pem'))
- )
-
- def hello(request):
- return 'hello'
- cls.http_endpoint.add_handler('/', hello)
-
- def test_remap_https(self):
- s = requests.Session()
- url = 'https://127.0.0.1:{0}/'.format(self.ssl_port)
-
- # We lack of SNI support in requests module, so we do not verify SSL certificate here.
- # ret = s.get(url, verify=(helpers.tests_file_path('certs/ca.crt')))
- ret = s.get(url, verify=False)
- self.assertEqual(ret.status_code, 404)
-
- s.headers.update({'Host': 'www.example.com'})
- ret = s.get(url, verify=False)
- self.assertEqual(ret.status_code, 200)
-
- s.headers.update({'Host': 'www.example.com:443'})
- ret = s.get(url)
- self.assertEqual(ret.status_code, 200)
-
- s.headers.update({'Host': 'www.example.com:4443'})
- ret = s.get(url)
- self.assertEqual(ret.status_code, 200)
-
- s.headers.update({'Host': 'www.test.com'})
- ret = s.get(url)
- self.assertEqual(ret.status_code, 404)
-
- s.headers.update({'Host': 'www.example.com:1234'})
- ret = s.get(url)
- self.assertEqual(ret.status_code, 404)
diff --git a/ci/tsqa/tests/test_tls_ticket_key_rotation.py b/ci/tsqa/tests/test_tls_ticket_key_rotation.py
deleted file mode 100644
index 7af883a..0000000
--- a/ci/tsqa/tests/test_tls_ticket_key_rotation.py
+++ /dev/null
@@ -1,175 +0,0 @@
-# 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 OpenSSL import SSL
-import socket
-import subprocess
-
-import helpers
-import tsqa.utils
-
-import os
-
-
-# helper function to get the path of a program.
-def which(program):
- def is_exe(fpath):
- return os.path.isfile(fpath) and os.access(fpath, os.X_OK)
- fpath, fname = os.path.split(program)
- if fpath:
- if is_exe(program):
- return program
- else:
- for path in os.environ["PATH"].split(os.pathsep):
- path = path.strip('"')
- exe_file = os.path.join(path, program)
- if is_exe(exe_file):
- return exe_file
- return None
-
-
-class TestTLSTicketKeyRotation(helpers.EnvironmentCase):
- """
- Test TLS session resumption through session tickets and TLS ticket key rotation.
- """
- @classmethod
- def setUpEnv(cls, env):
- '''
- This function is responsible for setting up the environment for this fixture
- This includes everything pre-daemon start
- '''
-
- # add an SSL port to ATS
- cls.ssl_port = tsqa.utils.bind_unused_port()[1]
- cls.configs['records.config']['CONFIG']['proxy.config.http.server_ports'] += ' {0}:ssl'.format(cls.ssl_port)
- cls.configs['records.config']['CONFIG']['proxy.config.diags.debug.enabled'] = 1
- cls.configs['records.config']['CONFIG']['proxy.config.diags.debug.tags'] = 'ssl'
-
- # configure SSL multicert
-
- cls.configs['ssl_multicert.config'].add_line('dest_ip=* ssl_cert_name={0} ssl_key_name={1} ticket_key_name={2}'.format(helpers.tests_file_path('rsa_keys/ca.crt'), helpers.tests_file_path('rsa_keys/ca.key'), helpers.tests_file_path('rsa_keys/ssl_ticket.key')))
-
- def start_connection(self, addr):
- '''
- Return the certificate for addr.
- '''
- ctx = SSL.Context(SSL.SSLv23_METHOD)
- # Set up client
- sock = SSL.Connection(ctx, socket.socket(socket.AF_INET, socket.SOCK_STREAM))
- sock.connect(addr)
- sock.do_handshake()
-
- def test_tls_ticket_resumption(self):
- '''
- Make sure the new ticket key is loaded
- '''
- addr = ('127.0.0.1', self.ssl_port)
- self.start_connection(addr)
-
- # openssl s_client -connect 127.0.0.1:443 -tls1 < /dev/null
- sess = os.path.join(self.environment.layout.logdir, 'sess')
- ticket_cmd = 'echo | openssl s_client -connect {0}:{1} -sess_out {2}'.format(addr[0], addr[1], sess)
-
- # check whether TLS session tickets are received by s_client.
- stdout, _ = tsqa.utils.run_sync_command(ticket_cmd, stdout=subprocess.PIPE, shell=True)
- ticket_exists = False
- for line in stdout.splitlines():
- text = line.strip()
- if text.startswith("TLS session ticket:"):
- ticket_exists = True
- break
- self.assertTrue(ticket_exists, "Sesssion tickets are not received")
-
- # check whether the session has been reused
- reused = False
- ticket_cmd = 'echo | openssl s_client -connect {0}:{1} -sess_in {2}'.format(addr[0], addr[1], sess)
- stdout, _ = tsqa.utils.run_sync_command(ticket_cmd, stdout=subprocess.PIPE, shell=True)
- for line in stdout.splitlines():
- text = line.strip()
- if text.startswith("Reused, TLSv1/SSLv3,"):
- reused = True
- break
- self.assertTrue(reused, "TLS session was not reused!")
-
- # negative test case. The session is not reused.
- reused = False
- ticket_cmd = 'echo | openssl s_client -connect {0}:{1}'.format(addr[0], addr[1])
- stdout, _ = tsqa.utils.run_sync_command(ticket_cmd, stdout=subprocess.PIPE, shell=True)
- for line in stdout.splitlines():
- text = line.strip()
- if text.startswith("Reused, TLSv1/SSLv3,"):
- reused = True
- break
- self.assertFalse(reused, "TLS session has been reused!")
-
- def test_tls_ticket_rotation(self):
- '''
- Make sure the new ticket key is loaded
- '''
- traffic_ctl = os.path.join(self.environment.layout.bindir, 'traffic_ctl')
- addr = ('127.0.0.1', self.ssl_port)
- self.start_connection(addr)
-
- '''
- openssl s_client -connect server_ip:ssl_port -tls1 < /dev/null
- '''
-
- # Generate and push a new ticket key
- rotate_cmd = 'openssl rand 48 -base64 > {0}'.format(helpers.tests_file_path('rsa_keys/ssl_ticket.key'))
- stdout, _ = tsqa.utils.run_sync_command(rotate_cmd, stdout=subprocess.PIPE, shell=True)
-
- # touch the ssl_multicert.config file
- ssl_multicert = os.path.join(self.environment.layout.sysconfdir, 'ssl_multicert.config')
-
- read_renewed_cmd = [
- traffic_ctl, 'config', 'get', 'proxy.process.ssl.total_ticket_keys_renewed'
- ]
-
- # Check whether the config file exists.
- self.assertTrue(os.path.isfile(ssl_multicert), ssl_multicert)
- touch_cmd = which('touch') + ' ' + ssl_multicert
- tsqa.utils.run_sync_command(touch_cmd, stdout=subprocess.PIPE, shell=True)
-
- count = 0
- while True:
- try:
- stdout, _ = tsqa.utils.run_sync_command(read_renewed_cmd, stdout=subprocess.PIPE, shell=True)
- old_renewed = stdout
- break
- except Exception:
- count += 1
- # If we have tried 30 times and the command still failed, quit here.
- if count > 30:
- self.assertTrue(False, "Failed to get the number of renewed keys!")
-
- signal_cmd = [traffic_ctl, 'config', 'reload']
- tsqa.utils.run_sync_command(signal_cmd, stdout=subprocess.PIPE, shell=True)
-
- # wait for the ticket keys to be sucked in by traffic_server.
- count = 0
- while True:
- try:
- stdout, _ = tsqa.utils.run_sync_command(read_renewed_cmd, stdout=subprocess.PIPE, shell=True)
- cur_renewed = stdout
- if old_renewed != cur_renewed:
- break
- except Exception:
- ++count
- if count > 30:
- self.assertTrue(False, "Failed to get the number of renewed keys!")
-
- # the number of ticket keys renewed has been increased.
- self.assertNotEqual(old_renewed, cur_renewed)
--
To stop receiving notification emails like this one, please contact
['"commits@trafficserver.apache.org" <co...@trafficserver.apache.org>'].
Re: [trafficserver] branch master updated: Removes the tsqa tests, to
avoid confusion. Use autest.
Posted by James Peach <jp...@apache.org>.
On 24 May 2017, at 18:12, zwoop@apache.org wrote:
> This is an automated email from the ASF dual-hosted git repository.
>
> zwoop pushed a commit to branch master
> in repository https://gitbox.apache.org/repos/asf/trafficserver.git
>
> The following commit(s) were added to refs/heads/master by this push:
> new 1e41700 Removes the tsqa tests, to avoid confusion. Use
> autest.
Does autest cover all these tests now?
J
Re: [trafficserver] branch master updated: Removes the tsqa tests, to
avoid confusion. Use autest.
Posted by James Peach <jp...@apache.org>.
On 24 May 2017, at 18:12, zwoop@apache.org wrote:
> This is an automated email from the ASF dual-hosted git repository.
>
> zwoop pushed a commit to branch master
> in repository https://gitbox.apache.org/repos/asf/trafficserver.git
>
> The following commit(s) were added to refs/heads/master by this push:
> new 1e41700 Removes the tsqa tests, to avoid confusion. Use
> autest.
Does autest cover all these tests now?
J