You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@trafficserver.apache.org by ja...@apache.org on 2015/04/30 22:39:49 UTC
[2/4] trafficserver git commit: Remove old tsqa,
and replace it with the new python based one.
http://git-wip-us.apache.org/repos/asf/trafficserver/blob/51ea4aa9/ci/tsqa/functions
----------------------------------------------------------------------
diff --git a/ci/tsqa/functions b/ci/tsqa/functions
deleted file mode 100644
index f839108..0000000
--- a/ci/tsqa/functions
+++ /dev/null
@@ -1,303 +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.
-
-NCPU=${NCPU:-$(( $(getconf _NPROCESSORS_ONLN) * 2 ))} # Numer of CPUs to build with
-PORT=${PORT:-9090} # Initial listen port for Traffic Server
-VALGRIND=${VALGRIND:-N} # Whether to run under valgrind
-TMPDIR=${TMPDIR:-/tmp} # Scratch directory for test instance construction
-
-TSQA_FAIL=0 # Test failure count
-TSQA_TESNAME=${TSQA_TESTNAME:-tsqa} # Name of current test
-TSQA_ROOT=${TSQA_ROOT:-/tmp/$TSQA_TESTNAME.$RANDOM} # Filesystem root for current test
-TSQA_TSXS=${TSQA_TSXS:-tsxs}
-
-# Print a log message/
-msg() {
- echo "MSG:" "$@"
-}
-
-msgwait() {
- local secs="$1"
- shift
-
- echo "MSG: waiting ${secs}s" "$@"
- sleep $secs
-}
-
-# Print a failure message and increment the failure count.
-fail() {
- TSQA_FAIL=$(($TSQA_FAIL + 1))
- echo "FAIL:" "$@" 1>&2
-}
-
-# Fail and exit.
-fatal() {
- TSQA_FAIL=$(($TSQA_FAIL + 1))
- echo "FATAL:" "$@" 1>&2
- exit $TSQA_FAIL
-}
-
-# Run a command and silence any output on stderr.
-quiet() {
- "$@" 2>/dev/null
-}
-
-# Run a command with all output redirected to the pest log file.
-logexec() {
- echo "$@" >> "$TSQA_ROOT/$TSQA_TESTNAME.log" 2>&1
- "$@" >> "$TSQA_ROOT/$TSQA_TESTNAME.log" 2>&1
-}
-
-tsxs() {
- $TSQA_TSXS "$@"
-}
-
-tsexec() {
- local cmd="$1"
- local run
- shift
-
- case $VALGRIND in
- y|yes|Y|YES|1) run="valgrind --trace-children=yes --trace-children-skip=env env" ;;
- *) run=env ;;
- esac
-
- # XXX enabling MallocStackLogging on all processes is annoying
- # because it logs 3 lines to stderr every time. We generally only
- # want leaks detection on traffic_server, so this is a bit of a
- # waste ...
-
- # MALLOC_CHECK_=2 => enable glibc malloc checking, abort on error
- # MallocStackLogging=1 => record OS X malloc stacks for leak checking
- $run \
- MALLOC_CHECK_=2 \
- MallocErrorAbort=1 \
- TS_ROOT=$TSQA_ROOT \
- $(bindir)/$cmd "$@"
-}
-
-reconfigure() {
- local srcdir="$1"
- msg running autoreconf in $srcdir ...
- (
- cd "$srcdir"
- autoreconf -i
- ) > autoreconf.log 2>&1
-}
-
-install () {
- [[ -d $BUILD ]] && rm -rf $BUILD
- [[ -d $PREFIX ]] && rm -rf $PREFIX
-
- msg installing ...
- mkdir -p $BUILD && (
- cd $BUILD
- $SRC/configure \
- --prefix=$PREFIX \
- --with-user=$(id -un) \
- --enable-debug \
- CCFLAGS=-O0 CXXFLAGS=-O0
- make -j $NCPU && make install
- ) > /dev/null
-
- msg installed to $PREFIX
-}
-
-logdir() {
- local prefix=$(tsxs -q PREFIX)
- tsxs -q LOGDIR | sed -es+$prefix/++
-}
-
-runtimedir() {
- local prefix=$(tsxs -q PREFIX)
- tsxs -q RUNTIMEDIR | sed -es+$prefix/++
-}
-
-sysconfdir() {
- local prefix=$(tsxs -q PREFIX)
- tsxs -q SYSCONFDIR | sed -es+$prefix/++
-}
-
-bindir() {
- tsxs -q BINDIR
-}
-
-# pidof(name): echo the pid of the given process name
-pidof() {
- case "$1" in
- cop|manager|server);;
- *) fatal no such process name: $1
- esac
- quiet cat $TSQA_ROOT/$(runtimedir)/${1}.lock
-}
-
-# alive(name): Test whether the process "name" is alive.
-alive() {
- local pid=$(pidof $1)
- if [[ ! -z "$pid" ]] ; then
- quiet kill -0 $pid
- return $?
- fi
-
- false
-}
-
-# Start up Traffic Server. Test for all the processes so that we have a better
-# chance of delaying the test until traffic_server is ready.
-startup() {
- local log=$TSQA_ROOT/$(logdir)/cop.log
- ( tsexec traffic_cop --stdout > $log )&
- for proc in cop manager server; do
- for i in $(seq 10) ; do
- alive $proc && msg $proc is alive && break
- sleep 1
- done
- done
-
- # And a final sleep to let traffic_server come up ...
- sleep 2
-}
-
-# Shut down Traffic Server.
-shutdown() {
-
- # Quick'n'dirty cleanup of background jobs.
- jobs -p | while read pid ; do
- kill $pid
- done
-
- local pid=$(pidof cop)
- if [[ -z "$pid" ]] ; then
- return
- fi
-
-# XXX If we are on Darwin, we can check the traffic_server for leaks before shutting down, but
-# we really only want to do this for traffic_server ... or we should sink the output to the test
-# log and fail on the exit status.
-
-# if [ -x /usr/bin/leaks ]; then
-# msg checking for leaks ...
-# /usr/bin/leaks $(pidof server)
-# fi
-
- msg shutting down ...
- while quiet kill -0 $pid ; do
- quiet kill -TERM $pid
- pid=$(pidof cop)
- if [[ -z "$pid" ]] ; then
- return
- fi
- done
-
- exit $TSQA_FAIL
-}
-
-restart() {
- local pid=$(pidof cop)
- if [[ -z "$pid" ]] ; then
- return
- fi
-
- msg shutting down ...
- while quiet kill -0 $pid ; do
- quiet kill -TERM $pid
- pid=$(pidof cop)
- if [[ -z "$pid" ]] ; then
- return
- fi
- done
-
- startup
-}
-
-# Test for Traffic Server crash logs.
-crash() {
- local outfile="$TSQA_ROOT/$(logdir)/traffic.out"
-
- msg checking for crashes ...
- for i in $(seq 10); do
- sleep 1
- [[ -e $outfile ]] && \
- grep -a -A 10 "STACK TRACE" $outfile && \
- fail detected a crash
- done
-}
-
-# Bootstrap a TSQA test root. The result of this is an independent test root
-# that contains all the variable parts of a traffic server configuration, while
-# referring to the parent installation for the actual test binaries.
-bootstrap() {
- local prefix=$(tsxs -q PREFIX)
- local sysconfdir=$(tsxs -q SYSCONFDIR | sed -es+$prefix/++)
- local dir
- local userid=${SUDO_USER:-$(whoami)}
-
- # Create runtime directories in the test root.
- for dir in SYSCONFDIR LOCALSTATEDIR RUNTIMEDIR LOGDIR ; do
- local p=$(tsxs -q $dir | sed -es+$prefix/++)
- mkdir -p $TSQA_ROOT/$p
- done
-
- # Copy config across
- cp -r $(tsxs -q SYSCONFDIR)/*.{config,xml} $TSQA_ROOT/$sysconfdir
-
- # Delete any config variables we are about to set.
- sed -i.orig \
- -e/proxy.config.body_factory.template_sets_dir/d \
- -e/proxy.config.plugin.plugin_dir/d \
- -e/proxy.config.bin_path/d \
- -e/proxy.config.admin.user_id/d \
- -e/proxy.config.diags/d \
- -e/proxy.config.http.server_ports/d \
- -e/proxy.config.config_update_interval_ms/d \
- $TSQA_ROOT/$sysconfdir/records.config || fatal failed to initialize records.config
-
- cat >> $TSQA_ROOT/$sysconfdir/records.config <<EOF
-CONFIG proxy.config.bin_path STRING $(tsxs -q BINDIR)
-CONFIG proxy.config.plugin.plugin_dir STRING $(tsxs -q LIBEXECDIR)
-CONFIG proxy.config.body_factory.template_sets_dir STRING $(tsxs -q SYSCONFDIR)/body_factory
-
-CONFIG proxy.config.admin.user_id STRING $userid
-CONFIG proxy.config.http.server_ports STRING $PORT
-
-# Flush config updates every 0.5s so that we don't have to sleep so long making config changes.
-CONFIG proxy.config.config_update_interval_ms INT 500
-
-# Send all diagnostics to both traffic.out and diags.log.
-CONFIG proxy.config.diags.output.diag STRING OL
-CONFIG proxy.config.diags.output.debug STRING OL
-CONFIG proxy.config.diags.output.status STRING OL
-CONFIG proxy.config.diags.output.note STRING OL
-CONFIG proxy.config.diags.output.warning STRING OL
-CONFIG proxy.config.diags.output.error STRING OL
-CONFIG proxy.config.diags.output.fatal STRING OL
-CONFIG proxy.config.diags.output.alert STRING OL
-CONFIG proxy.config.diags.output.emergency STRING OL
-
-CONFIG proxy.config.diags.debug.enabled INT 1
-CONFIG proxy.config.diags.debug.tags STRING NULL
-CONFIG proxy.config.diags.show_location INT 1
-EOF
-
- chown -R "$userid" $TSQA_ROOT
-
- msg bootstrapped Traffic Server into $TSQA_ROOT
- tsexec traffic_layout
-}
-
-# vim: set sw=2 ts=2 et :
http://git-wip-us.apache.org/repos/asf/trafficserver/blob/51ea4aa9/ci/tsqa/requirements.txt
----------------------------------------------------------------------
diff --git a/ci/tsqa/requirements.txt b/ci/tsqa/requirements.txt
new file mode 100644
index 0000000..5897503
--- /dev/null
+++ b/ci/tsqa/requirements.txt
@@ -0,0 +1,6 @@
+# requirements for the python virtualenv
+
+# TODO: pin a specific version
+https://github.com/apache/trafficserver-qa/archive/master.zip
+pyyaml
+pyOpenSSL
http://git-wip-us.apache.org/repos/asf/trafficserver/blob/51ea4aa9/ci/tsqa/run_all.sh
----------------------------------------------------------------------
diff --git a/ci/tsqa/run_all.sh b/ci/tsqa/run_all.sh
deleted file mode 100755
index d2f04f2..0000000
--- a/ci/tsqa/run_all.sh
+++ /dev/null
@@ -1,85 +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.
-
-OK=()
-FAIL=()
-EXCLUDE=()
-STATUS=0
-
-# Produce a help page
-do_help() {
- echo "run_all.sh: Run all TSQA tests"
- echo
- echo "Options:"
- echo " -e Exclude the given test"
- echo " -h Show this help page"
-}
-
-# Parse the arguments
-while getopts "e:" opt; do
- case $opt in
- e)
- EXCLUDE+=($OPTARG)
- ;;
- \?|h)
- do_help
- exit 1
- ;;
- esac
-done
-
-
-# Run all tests, record the results
-for test in test-*; do
- run_it=1
- for ex in ${EXCLUDE[@]}; do
- echo $ex
- if [ "$ex" == "$test" ]; then
- run_it=0
- break
- fi
- done
- if [ $run_it -ne 0 ]; then
- echo "--> Starting test: $test"
- ./${test}
- res=$?
- if [ $res != 0 ]; then
- echo "Failure: ${test}"
- FAIL+=(${test})
- STATUS=1
- else
- echo "Success: ${test}"
- OK+=(${test})
- fi
- fi
-done
-
-
-# Print out a results summary
-echo
-echo
-echo "RESULT SUMMARY"
-echo "=============="
-for t in ${OK[@]}; do
- echo "$t ...OK"
-done
-for t in ${FAIL[@]}; do
- echo "$t ...FAIL"
-done
-
-exit ${STATUS}
http://git-wip-us.apache.org/repos/asf/trafficserver/blob/51ea4aa9/ci/tsqa/test-bootstrap
----------------------------------------------------------------------
diff --git a/ci/tsqa/test-bootstrap b/ci/tsqa/test-bootstrap
deleted file mode 100755
index 4f817b4..0000000
--- a/ci/tsqa/test-bootstrap
+++ /dev/null
@@ -1,41 +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.
-
-TSQA_TSXS=${TSQA_TSXS:-/opt/ats/bin/tsxs}
-TSQA_TESTNAME=$(basename $0)
-source $(dirname $0)/functions
-
-# This test verifies that we can start Traffic Server in the test root. It is primarily
-# intended as a trivial payload to test the TSQA harness.
-check() {
-
- msg waiting ...
- sleep 2
-}
-
-bootstrap
-
-# If Traffic Server is not up, bring it up ...
-alive cop || startup || fatal unable to start Traffic Server
-trap shutdown 0 EXIT
-
-check
-
-exit $TSQA_FAIL
-
-# vim: set sw=2 ts=2 et :
http://git-wip-us.apache.org/repos/asf/trafficserver/blob/51ea4aa9/ci/tsqa/test-log-configuration
----------------------------------------------------------------------
diff --git a/ci/tsqa/test-log-configuration b/ci/tsqa/test-log-configuration
deleted file mode 100755
index 3393c23..0000000
--- a/ci/tsqa/test-log-configuration
+++ /dev/null
@@ -1,68 +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.
-
-COUNT=${COUNT:-10}
-TSQA_TSXS=${TSQA_TSXS:-/opt/ats/bin/tsxs}
-TSQA_TESTNAME=$(basename $0)
-source $(dirname $0)/functions
-
-# Make up an arbitratry URL to generate error logs. We use the loopback address
-# number because I've seen "localhost" resolve to an IPv6 address. That sucked.
-URL=http://127.0.0.1:$PORT
-
-# This test verifies that online reloading of the logging configuration
-# does not crash Traffic Server.
-check() {
- local logdir=$(logdir)
-
- for i in $(seq $COUNT) ; do
- msg check $i ...
- curl --silent --show-error -o /dev/null -H "Host: not there" $URL
- tsexec traffic_line -s proxy.config.diags.debug.tags -v 'log-.*'
- tsexec traffic_line -s proxy.config.diags.debug.enabled -v 1
- tsexec traffic_line -x
- msgwait 2
- curl --silent --show-error -o /dev/null -H "Host: not there" $URL
- # Set a harmless proxy.config.log.hostname to trigger a config reload ...
- tsexec traffic_line -s proxy.config.log.hostname -v jpeach-test-$$-$i
- tsexec traffic_line -s proxy.config.log.search_top_sites -v $i
- tsexec traffic_line -x
- msgwait 2
- curl --silent --show-error -o /dev/null -H "Host: not there" $URL
- crash
-
- # Verify that we have all the error logs that we expect.
- for logfile in error.log diags.log manager.log traffic.out ; do
- [[ -e $TSQA_ROOT/$logdir/$logfile ]] || fatal $logfile is missing
- done
-
- done
-}
-
-bootstrap
-
-# If Traffic Server is not up, bring it up ...
-alive cop || startup || fatal unable to start Traffic Server
-trap shutdown 0 EXIT
-
-msgwait 6
-check
-
-exit $TSQA_FAIL
-
-# vim: set sw=2 ts=2 et :
http://git-wip-us.apache.org/repos/asf/trafficserver/blob/51ea4aa9/ci/tsqa/test-log-refcounting
----------------------------------------------------------------------
diff --git a/ci/tsqa/test-log-refcounting b/ci/tsqa/test-log-refcounting
deleted file mode 100755
index 41bd312..0000000
--- a/ci/tsqa/test-log-refcounting
+++ /dev/null
@@ -1,112 +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.
-
-TSQA_TSXS=${TSQA_TSXS:-/opt/ats/bin/tsxs}
-TSQA_TESTNAME=$(basename $0)
-source $(dirname $0)/functions
-
-COUNT=${COUNT:-100}
-SERVER_PORT=${SERVER_PORT:-4000}
-RELOAD_INTERVAL_SECS=${RELOAD_INTERVAL_SECS:-30}
-
-bootstrap
-
-# Force a logging subsystem reload.
-reload() {
- while sleep $RELOAD_INTERVAL_SECS ; do
- msg reloading logging configuration
- tsexec traffic_line -s proxy.config.log.hostname -v "$(date)"
- tsexec traffic_line -x
- done
-}
-
-if [ ! -x $(bindir)/jtest ] ; then
- fatal "missing jtest program; rebuild with --enable-test-tools"
-fi
-
-cat >$TSQA_ROOT/$(sysconfdir)/remap.config <<REMAP
-map http://jtest.trafficserver.apache.org:$SERVER_PORT http://127.0.0.1:$SERVER_PORT
-REMAP
-
-# Configure the tcpinfo plugin so that we have some API log objects.
-cat >$TSQA_ROOT/$(sysconfdir)/plugin.config <<REMAP
-tcpinfo.so --log-file=tcpinfo1 --hooks=ssn_start,txn_start,send_resp_hdr,ssn_close,txn_close --log-level=2
-tcpinfo.so --log-file=tcpinfo2 --hooks=ssn_start,txn_start,send_resp_hdr,ssn_close,txn_close --log-level=2
-tcpinfo.so --log-file=tcpinfo3 --hooks=ssn_start,txn_start,send_resp_hdr,ssn_close,txn_close --log-level=2
-tcpinfo.so --log-file=tcpinfo4 --hooks=ssn_start,txn_start,send_resp_hdr,ssn_close,txn_close --log-level=2
-REMAP
-
-# If Traffic Server is not up, bring it up ...
-alive cop || startup || fatal unable to start Traffic Server
-trap shutdown 0 EXIT
-
-# Wait for traffic_manager to start.
-alive manager
-alive server
-msgwait 2
-
-# Logging configuration ...
-tsexec traffic_line -s proxy.config.log.max_space_mb_for_logs -v 10
-tsexec traffic_line -s proxy.config.log.max_space_mb_for_orphan_logs -v 10
-tsexec traffic_line -s proxy.config.log.squid_log_enabled -v 1
-tsexec traffic_line -s proxy.config.log.squid_log_is_ascii -v 1
-# Roll every megabyte ...
-tsexec traffic_line -s proxy.config.log.rolling_interval_sec -v 60
-tsexec traffic_line -s proxy.config.log.rolling_size_mb -v 1
-# Don't declare log space exhausted until there is < 1MB free.
-tsexec traffic_line -s proxy.config.log.max_space_mb_headroom -v 1
-# Flush log buffers every second.
-tsexec traffic_line -s proxy.config.log.max_secs_per_buffer -v 1
-
-# Enable logging diagnostics for test debugging. If you enable this
-# for the test itself, the diagnostics log will exhaust all the logging
-# space and everything will go to hell.
-#tsexec traffic_line -s proxy.config.diags.debug.tags -v log
-
-# The sleep is needed to let Traffic Server schedule the config change.
-msgwait 4 to restart with updated logging configuration
-# XXX: this needs a full bounce
-tsexec traffic_line -L
-
-# Wait for traffic_manager to start.
-alive manager
-alive server
-msgwait 10
-
-msg starting config reload every $RELOAD_INTERVAL_SECS seconds
-reload&
-
-for i in $(seq $COUNT) ; do
- msg $(bindir)/jtest --proxy_port $PORT --proxy_host 127.0.0.1 \
- --server_port $SERVER_PORT --server_host jtest.trafficserver.apache.org \
- --clients 10 --test_time 60
- $(bindir)/jtest --proxy_port $PORT --proxy_host 127.0.0.1 \
- --server_port $SERVER_PORT --server_host jtest.trafficserver.apache.org \
- --clients 10 --test_time 60
-
- if [ -r $(logdir)/squid.log ]; then
- fatal squid.log is missing
- fi
-
- # Check for a crash ...
- crash
-done
-
-exit $TSQA_FAIL
-
-# vim: set sw=2 ts=2 et :
http://git-wip-us.apache.org/repos/asf/trafficserver/blob/51ea4aa9/ci/tsqa/test-multicert-loading
----------------------------------------------------------------------
diff --git a/ci/tsqa/test-multicert-loading b/ci/tsqa/test-multicert-loading
deleted file mode 100755
index cc0e49e..0000000
--- a/ci/tsqa/test-multicert-loading
+++ /dev/null
@@ -1,81 +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.
-
-# test-multicert-loading: test loading large numbers of SSL certificates.
-
-TSQA_TSXS=${TSQA_TSXS:-/opt/ats/bin/tsxs}
-TSQA_TESTNAME=$(basename $0)
-source $(dirname $0)/functions
-
-bootstrap
-
-# If Traffic Server is not up, bring it up ...
-alive cop || startup || fatal unable to start Traffic Server
-trap shutdown 0 EXIT
-
-#msg unpacking the SSL certificates into \$sysconfdir/ssl.
-#(
-# tarball=$(cd $(dirname $0) && pwd)/ssl-multicert-bundle.tar.bz2
-# conf=$TSQA_ROOT/$(sysconfdir)/ssl
-#
-# cd $TSQA_ROOT/$(sysconfdir) && tar -xf $tarball
-#)
-
-msg updating SSL configuration paths
-tsexec traffic_line -s proxy.config.ssl.server.cert.path -v $TSQA_ROOT/$(sysconfdir)/ssl
-tsexec traffic_line -s proxy.config.ssl.server.multicert.filename -v $TSQA_ROOT/$(sysconfdir)/ssl/ssl_multicert.config
-
-# XXX configure an exampe plugin that uses the TS-2437 SSL lifecycle hooks
-
-# XXX hardcoding the ports is lame ...
-PORT=9443:ssl,10443:ssl,11443:ssl
-
-# Enable SSL and bounce Traffic Server.
-tsexec traffic_line -s proxy.config.diags.action.enabled -v 1
-tsexec traffic_line -s proxy.config.diags.action.tags -v test.multicert.delay
-
-tsexec traffic_line -s proxy.config.http.server_ports -v $PORT
-tsexec traffic_line -s proxy.config.diags.debug.enabled -v 1
-tsexec traffic_line -s proxy.config.diags.debug.tags -v ssl
-
-# Stash the admin port while we have traffic_server running. It won't be
-# available later if traffic_server does not come back up.
-admin_port=$(tsexec traffic_line -r proxy.config.process_manager.mgmt_port)
-
-# The sleep is needed to let Traffic Server schedule the config change.
-msgwait 2 to restart with SSL ports enabled
-tsexec traffic_line -L
-
-msgwait 6 for traffic_server to restart
-alive server || startup || fatal unable to start Traffic Server
-
-# XXX use the SSL lifecycle hooks in TS-2437 to verify that we loaded the
-# certificates.
-
-START=$(date +%s)
-
-# Verify that the healthcheck comes up within about 60 seconds.
-for c in $(seq 60) ; do
- curl --silent --max-time 1 -o /dev/null http://127.0.0.1:${admin_port}/synthetic.txt && exit $TSQA_FAIL
- sleep 1
-done
-
-fail unable to start traffic_server after $(( $(date +%s) - $START )) seconds
-exit $TSQA_FAIL
-
-# vim: set sw=2 ts=2 et :
http://git-wip-us.apache.org/repos/asf/trafficserver/blob/51ea4aa9/ci/tsqa/test-privilege-elevation
----------------------------------------------------------------------
diff --git a/ci/tsqa/test-privilege-elevation b/ci/tsqa/test-privilege-elevation
deleted file mode 100755
index 2d4eda0..0000000
--- a/ci/tsqa/test-privilege-elevation
+++ /dev/null
@@ -1,83 +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.
-
-TSQA_TSXS=${TSQA_TSXS:-/opt/ats/bin/tsxs}
-TSQA_TESTNAME=$(basename $0)
-COUNT=${COUNT:-10}
-source $(dirname $0)/functions
-
-# This test verifies Traffic Server can elevate privileges correctly, based on
-# the configuration settings:
-#
-# proxy.config.ssl.cert.load_elevated
-# proxy.config.plugin.load_elevated
-
-check() {
-
- for i in $(seq $COUNT) ; do
- msg check $i ...
- touch $TSQA_ROOT/$(sysconfdir)/remap.config
- touch $TSQA_ROOT/$(sysconfdir)/ssl_multicert.config
- tsexec traffic_line -x
- msgwait 2
- done
-
- crash
-}
-
-if [ x"$(id -u)" != x"0" ] ; then
- fatal this test needs to be run as root
-fi
-
-bootstrap
-
-# If Traffic Server is not up, bring it up ...
-alive cop || startup || fatal unable to start Traffic Server
-trap shutdown 0 EXIT
-
-tsexec traffic_line -s proxy.config.ssl.cert.load_elevated -v 1
-tsexec traffic_line -s proxy.config.plugin.load_elevated -v 1
-tsexec traffic_line -s proxy.config.diags.debug.tags -v 'privileges'
-tsexec traffic_line -s proxy.config.diags.debug.enabled -v 1
-
-cat >$TSQA_ROOT/$(sysconfdir)/remap.config <<REMAP
-# Add a remap rule, it doesn't matter what it is ..
-map http://jtest.trafficserver.apache.org http://127.0.0.1 \
- @plugin=conf_remap.so @pparam=proxy.config.url_remap.pristine_host_hdr=1
-REMAP
-
-cat >$TSQA_ROOT/$(sysconfdir)/plugin.config <<PLUGIN
-# Add a plugin, it doesn't matter which one. A better test would load
-# a plugin that requires elevated access, and checks for it in the
-# plugin interface.
-
-xdebug.so
-PLUGIN
-
-# The sleep is needed to let Traffic Server schedule the config change.
-msgwait 4 to restart load elevation enabled
-tsexec traffic_line -L
-
-msgwait 6 for traffic_server to restart
-alive server || startup || fatal unable to start Traffic Server
-
-check
-
-exit $TSQA_FAIL
-
-# vim: set sw=2 ts=2 et :
http://git-wip-us.apache.org/repos/asf/trafficserver/blob/51ea4aa9/ci/tsqa/test-server-intercept
----------------------------------------------------------------------
diff --git a/ci/tsqa/test-server-intercept b/ci/tsqa/test-server-intercept
deleted file mode 100755
index ee1eab3..0000000
--- a/ci/tsqa/test-server-intercept
+++ /dev/null
@@ -1,80 +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.
-
-TSQA_TSXS=${TSQA_TSXS:-/opt/ats/bin/tsxs}
-TSQA_TESTNAME=$(basename $0)
-source $(dirname $0)/functions
-
-# The intercept example plugin is hard-coded to port 60000.
-SERVER_PORT=${SERVER_PORT:-60000}
-
-# Use traffic_line -m to list all the configuration variables. Verify their values with
-# traffic_line -r. This tests the TSRecordGet() and TSRecordGetMatchMult() remote APIs.
-check() {
- local key
- local val1
- local val2
-
- local bindir=$(bindir)
-
- tsexec traffic_line -m proxy.config | while read key val1 ; do
- val2=$(TS_ROOT=$TSQA_ROOT $bindir/traffic_line -r $key)
- if [ "$?" != "0" ]; then
- fail failed to fetch value for $key
- elif [ "$val1" != "$val1" ] ; then
- fail value mismatch for $key, expected:\"$val1\", received:\"$val2\"
- fi
- done
-}
-
-bootstrap
-
-if [ ! -x $(bindir)/jtest ] ; then
- fatal "missing jtest program; rebuild with --enable-test-tools"
-fi
-
-cat >$TSQA_ROOT/$(sysconfdir)/remap.config <<REMAP
-map http://jtest.trafficserver.apache.org:$SERVER_PORT http://127.0.0.1:$SERVER_PORT
-REMAP
-
-cat >$TSQA_ROOT/$(sysconfdir)/plugin.config <<REMAP
-#intercept.so
-REMAP
-
-# If Traffic Server is not up, bring it up ...
-alive cop || startup || fatal unable to start Traffic Server
-trap shutdown 0 EXIT
-
-# Wait for traffic_manager to start.
-alive manager
-alive server
-msgwait 1
-
-# Run jtest for a while to exercise the intercept path. Note that jtest only exercises
-# one of many possible sequences of events. Specifically, the jtest server will always
-# close the socket before the client finishes reasing the response.
-$(bindir)/jtest --proxy_port $PORT --proxy_host 127.0.0.1 \
- --server_port $SERVER_PORT --server_host jtest.trafficserver.apache.org \
- --clients 10 --test_time 60
-
-# Check for a crash ...
-crash
-
-exit $TSQA_FAIL
-
-# vim: set sw=2 ts=2 et :
http://git-wip-us.apache.org/repos/asf/trafficserver/blob/51ea4aa9/ci/tsqa/test-ssl-certificates
----------------------------------------------------------------------
diff --git a/ci/tsqa/test-ssl-certificates b/ci/tsqa/test-ssl-certificates
deleted file mode 100755
index e12b798..0000000
--- a/ci/tsqa/test-ssl-certificates
+++ /dev/null
@@ -1,153 +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.
-
-TSQA_TSXS=${TSQA_TSXS:-/opt/ats/bin/tsxs}
-TSQA_TESTNAME=$(basename $0)
-source $(dirname $0)/functions
-
-OPENSSL=${OPENSSL:-openssl}
-
-check_openssl_version() {
- local vers=$($OPENSSL version)
-
- # Apparantly OpenSSL SNI was added in 0.9.8f, but I'm too lazy to
- # parse the version properly, so let's just say that 1.0 and greater is ok.
- case $vers in
- OpenSSL\ [1-9].[0-9].*) return 0;;
- *) return 1;;
- esac
-}
-
-make_ssl_certificate() {
- local cn="$1"
- local filename="$2"
-
- msg generating SSL key and certificate for "$cn"
-
- $OPENSSL genrsa -out ${cn}.key 2048
- $OPENSSL req -new -key ${cn}.key -out ${cn}.csr \
- -subj "/C=US/ST=CA/L=Norm/O=TrafficServer/OU=Test/CN=${cn}"
- $OPENSSL x509 -req -days 1 -in ${cn}.csr -signkey ${cn}.key -out ${cn}.crt
-
- cat ${cn}.crt ${cn}.key > ${filename}
-
- rm -rf ${cn}.csr ${cn}.key ${cn}.crt
-}
-
-openssl_verify_certificate() {
- local certname="$1" # Certificate CN to expect
- local result="$TSQA_ROOT/${certname}.result"
- local commonName=
- local status=1 # default status is FAIL
-
- shift
- msg "checking for the $certname certificate ..." | tee -a "$TSQA_ROOT/$TSQA_TESTNAME.log"
-
- # When s_client verifies the certificate, it will log a line that looks like:
- # depth=0 C = US, ST = CA, L = Norm, O = TrafficServer, OU = Test, CN = address.tsqa.trafficserver.apache.org
- $OPENSSL s_client "$@" < /dev/null > "$result" 2>&1
- if [ "$?" != 0 ]; then
- fail "openssl check for $certname failed"
- fi
-
- # The output of this openssl formulation is:
- # subject=
- # countryName = US
- # stateOrProvinceName = CA
- # localityName = Norm
- # organizationName = TrafficServer
- # organizationalUnitName = Test
- # commonName = *.tsqa.trafficserver.apache.org
- commonName=$($OPENSSL x509 -in "$result" -noout -subject -nameopt multiline | awk '/commonName/{print $3}')
-
- if [ "$commonName" != "$certname" ]; then
- fail "received certificate CN \"$commonName\", expected \"$certname\""
- fi
-
- if [ "$?" != 0 ]; then
- fail "certificate name $certname did not match"
- fi
-}
-
-check_openssl_version || fatal OpenSSL 1.0 or later is required
-
-bootstrap
-
-# If Traffic Server is not up, bring it up ...
-alive cop || startup || fatal unable to start Traffic Server
-trap shutdown 0 EXIT
-
-for name in \
- \*.tsqa.trafficserver.apache.org \
- sni.tsqa.trafficserver.apache.org \
- port.tsqa.trafficserver.apache.org \
- address.tsqa.trafficserver.apache.org \
- default.tsqa.trafficserver.apache.org
-do
- logexec make_ssl_certificate $name $TSQA_ROOT/$(sysconfdir)/${name}.pem \
- || fatal failed to generate SSL certificate for "$name"
-done
-
-cat > $TSQA_ROOT/$(sysconfdir)/ssl_multicert.config <<EOF
-ssl_cert_name=sni.tsqa.trafficserver.apache.org.pem
-ssl_cert_name=*.tsqa.trafficserver.apache.org.pem
-
-ssl_cert_name=port.tsqa.trafficserver.apache.org.pem dest_ip=127.0.0.1:10443
-ssl_cert_name=address.tsqa.trafficserver.apache.org.pem dest_ip=127.0.0.1
-ssl_cert_name=default.tsqa.trafficserver.apache.org.pem dest_ip=*
-EOF
-
-# XXX hardcoding the ports is lame ...
-PORT=9443:ssl,10443:ssl,11443:ssl
-
-# Enable SSL and bounce Traffic Server.
-tsexec traffic_line -s proxy.config.http.server_ports -v $PORT
-tsexec traffic_line -s proxy.config.diags.debug.tags -v ssl
-
-# The sleep is needed to let Traffic Server schedule the config change.
-msgwait 2 to restart with SSL ports enabled
-tsexec traffic_line -L
-
-msgwait 6 for traffic_server to restart
-alive server || startup || fatal unable to start Traffic Server
-
-# debugging ...
-# tsexec traffic_line -r proxy.config.diags.debug.tags
-# tsexec traffic_line -r proxy.config.http.server_ports
-
-# This should get *.tsqa.trafficserver.apache.org ...
-openssl_verify_certificate '*.tsqa.trafficserver.apache.org' \
- -connect 127.0.0.1:9443 -servername wildcard.tsqa.trafficserver.apache.org
-
-# This should get sni.tsqa.trafficserver.apache.org ...
-openssl_verify_certificate 'sni.tsqa.trafficserver.apache.org' \
- -connect 127.0.0.1:9443 -servername sni.tsqa.trafficserver.apache.org
-
-# This should get port.tsqa.trafficserver.apache.org ...
-openssl_verify_certificate 'port.tsqa.trafficserver.apache.org' \
- -connect 127.0.0.1:10443
-
-# This should get address.tsqa.trafficserver.apache.org ...
-openssl_verify_certificate 'address.tsqa.trafficserver.apache.org' \
- -connect 127.0.0.1:9443
-
-# XXX not sure how to get the default.tsqa.trafficserver.apache.org; need to listen on a second address for that.
-
-exit $TSQA_FAIL
-
-# vim: set sw=2 ts=2 et :
http://git-wip-us.apache.org/repos/asf/trafficserver/blob/51ea4aa9/ci/tsqa/test-trafficline-metrics
----------------------------------------------------------------------
diff --git a/ci/tsqa/test-trafficline-metrics b/ci/tsqa/test-trafficline-metrics
deleted file mode 100755
index 1f28cbd..0000000
--- a/ci/tsqa/test-trafficline-metrics
+++ /dev/null
@@ -1,56 +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.
-
-TSQA_TSXS=${TSQA_TSXS:-/opt/ats/bin/tsxs}
-TSQA_TESTNAME=$(basename $0)
-source $(dirname $0)/functions
-
-# Use traffic_line -m to list all the configuration variables. Verify their values with
-# traffic_line -r. This tests the TSRecordGet() and TSRecordGetMatchMult() remote APIs.
-check() {
- local key
- local val1
- local val2
-
- local bindir=$(bindir)
-
- tsexec traffic_line -m proxy.config | while read key val1 ; do
- val2=$(TS_ROOT=$TSQA_ROOT $bindir/traffic_line -r $key)
- if [ "$?" != "0" ]; then
- fail failed to fetch value for $key
- elif [ "$val1" != "$val1" ] ; then
- fail value mismatch for $key, expected:\"$val1\", received:\"$val2\"
- fi
- done
-}
-
-bootstrap
-
-# If Traffic Server is not up, bring it up ...
-alive cop || startup || fatal unable to start Traffic Server
-trap shutdown 0 EXIT
-
-# Wait for traffic_manager to start.
-alive manager
-msgwait 1
-
-check
-
-exit $TSQA_FAIL
-
-# vim: set sw=2 ts=2 et :
http://git-wip-us.apache.org/repos/asf/trafficserver/blob/51ea4aa9/ci/tsqa/tests/helpers.py
----------------------------------------------------------------------
diff --git a/ci/tsqa/tests/helpers.py b/ci/tsqa/tests/helpers.py
new file mode 100644
index 0000000..7333569
--- /dev/null
+++ b/ci/tsqa/tests/helpers.py
@@ -0,0 +1,57 @@
+# 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.EnvironmentCase):
+ '''
+ This class will get an environment (which is unique) but won't start it
+ '''
+ @classmethod
+ def getEnv(cls):
+ '''
+ This function is responsible for returning an environment
+ '''
+ SOURCE_DIR = os.path.realpath(os.path.join(__file__, '..', '..', '..', '..'))
+ TMP_DIR = os.path.join(tempfile.gettempdir(), 'tsqa')
+ ef = tsqa.environment.EnvironmentFactory(SOURCE_DIR,
+ os.path.join(TMP_DIR, 'base_envs'),
+ default_configure={'enable-example-plugins': None,
+ 'enable-test-tools': None,
+ 'disable-dependency-tracking': None,
+ 'enable-ccache': None,
+ },
+ )
+ # TODO: figure out a way to determine why the build didn't fail and
+ # not skip all build failures?
+ try:
+ return ef.get_environment(cls.environment_factory.get('configure'), cls.environment_factory.get('env'))
+ except Exception as e:
+ raise unittest.SkipTest(e)
http://git-wip-us.apache.org/repos/asf/trafficserver/blob/51ea4aa9/ci/tsqa/tests/test_buildoptions.py
----------------------------------------------------------------------
diff --git a/ci/tsqa/tests/test_buildoptions.py b/ci/tsqa/tests/test_buildoptions.py
new file mode 100644
index 0000000..2279062
--- /dev/null
+++ b/ci/tsqa/tests/test_buildoptions.py
@@ -0,0 +1,61 @@
+'''
+Test that configuration options successfully compile
+'''
+
+# 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 sys
+import requests
+import time
+import subprocess
+import logging
+
+import helpers
+import tsqa.test_cases
+import tsqa.utils
+
+log = logging.getLogger(__name__)
+
+class TestBuildOption(helpers.EnvironmentCase):
+ '''
+ Run the built-in traffic_server regression test suite.
+ '''
+
+ def test_buildoption(self):
+ pass
+
+class TestBuildOptionFastSDK(TestBuildOption):
+ '''Build with --enable-fast-sdk'''
+ environment_factory = { 'configure': { 'enable-fast-sdk': None }, }
+
+class TestBuildOptionDisableDiags(TestBuildOption):
+ '''Build with --disable-diags'''
+ environment_factory = { 'configure': { 'disable-diags': None }, }
+
+class TestBuildOptionDisableTests(TestBuildOption):
+ '''Build with --disable-tests'''
+ environment_factory = { 'configure': { 'disable-tests': None }, }
+
+class TestBuildOptionEnableStaticProxy(TestBuildOption):
+ '''Build with --enable-static-proxy'''
+ environment_factory = { 'configure': { 'enable-static-proxy': None }, }
+
+class TestBuildOptionEnableCxxApi(TestBuildOption):
+ '''Build with --enable-cppapi'''
+ environment_factory = { 'configure': { 'enable-cppapi': None }, }
+
http://git-wip-us.apache.org/repos/asf/trafficserver/blob/51ea4aa9/ci/tsqa/tests/test_chunked.py
----------------------------------------------------------------------
diff --git a/ci/tsqa/tests/test_chunked.py b/ci/tsqa/tests/test_chunked.py
new file mode 100644
index 0000000..9b7fdc0
--- /dev/null
+++ b/ci/tsqa/tests/test_chunked.py
@@ -0,0 +1,196 @@
+'''
+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 os
+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 wether 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)
+ with self.assertRaises(requests.exceptions.ConnectionError):
+ ret = requests.get(url, proxies=self.proxies, timeout=2)
http://git-wip-us.apache.org/repos/asf/trafficserver/blob/51ea4aa9/ci/tsqa/tests/test_connect_attempts.py
----------------------------------------------------------------------
diff --git a/ci/tsqa/tests/test_connect_attempts.py b/ci/tsqa/tests/test_connect_attempts.py
new file mode 100644
index 0000000..9979e33
--- /dev/null
+++ b/ci/tsqa/tests/test_connect_attempts.py
@@ -0,0 +1,209 @@
+'''
+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
+
+import tsqa.test_cases
+import tsqa.utils
+import tsqa.endpoint
+
+log = logging.getLogger(__name__)
+
+
+def thread_die_on_connect(sock):
+ sock.listen(0)
+ # poll
+ read_sock = select.select([sock], [], [])
+ # exit
+ sock.close()
+
+def thread_delayed_accept_after_connect(sock):
+ '''
+ Thread to sleep a decreasing amount of time before requests
+
+ sleep times: 2 -> 1 -> 0
+ '''
+ sock.listen(0)
+ sleep_time = 2
+ requests = 0
+ # poll
+ while True:
+ read_sock = select.select([sock], [], [])
+ time.sleep(sleep_time)
+ 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(requests)), body=requests)))
+ connection.close()
+ requests += 1
+ except Exception as e:
+ print 'connection died!', e
+ pass
+ if sleep_time > 0:
+ sleep_time -= 1
+
+
+def thread_reset_after_accept(sock):
+ sock.listen(0)
+ first = True
+ requests = 0
+ while True:
+ connection, addr = sock.accept()
+ 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(requests)), body=requests)))
+ connection.close()
+
+def thread_partial_response(sock):
+ sock.listen(0)
+ first = True
+ requests = 0
+ while True:
+ connection, addr = sock.accept()
+ requests += 1
+ if first:
+ connection.send('HTTP/1.1 200 OK\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(requests)), body=requests)))
+ connection.close()
+
+
+
+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('delayed_accept_after_connect')
+ t = threading.Thread(target=thread_delayed_accept_after_connect, 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()
+
+ # 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)
+ 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)
+ 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)
+ 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)
+ self.assertEqual(ret.status_code, 504)
+
+ # TODO: FIX THIS!!! The test is correct, ATS isn't!
+ # we should fail in this case-- or at least have a config which lets you control
+ 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)
+ self.assertEqual(ret.status_code, 502)
+
+ def test_reset_after_accept_origin(self):
+ '''Verify that we get 200s from origins that reset_after_accept'''
+ 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)
+ self.assertEqual(ret.status_code, 200)
+ self.assertGreater(int(ret.text), 0)
+
+ def test_delayed_accept_after_connect_origin(self):
+ '''Verify that we get 200s from origins that delayed_accept_after_connect'''
+ url = 'http://127.0.0.1:{0}/delayed_accept_after_connect/s'.format(self.configs['records.config']['CONFIG']['proxy.config.http.server_ports'])
+ ret = requests.get(url)
+ # make sure it worked
+ self.assertEqual(ret.status_code, 200)
+ # make sure its not the first one (otherwise the test messed up somehow)
+ self.assertGreater(int(ret.text), 0)
http://git-wip-us.apache.org/repos/asf/trafficserver/blob/51ea4aa9/ci/tsqa/tests/test_example.py
----------------------------------------------------------------------
diff --git a/ci/tsqa/tests/test_example.py b/ci/tsqa/tests/test_example.py
new file mode 100644
index 0000000..0a7f468
--- /dev/null
+++ b/ci/tsqa/tests/test_example.py
@@ -0,0 +1,234 @@
+'''
+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 configure/environment options for the source build here
+ environment_factory = {
+ 'configure': {# A value of None means that the argument has no value
+ 'enable-spdy': None,
+ # if there is a value it will be converted to --key=value
+ 'with-max-api-stats': 2048,
+ },
+ 'env': None,
+ }
+
+ @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://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):
+ environment_factory = {
+ 'configure': {'enable-spdy': None},
+ }
+
+ def test_spdy(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_trafficline(self):
+ '''
+ Test that traffic_line 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_line'),
+ '-m',
+ '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',
+ 'proxy.config.log.search_top_sites': 1,
+ })
+ 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 TestLogRefCounting(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]))
+
+ cls.configs['plugin.config'].add_lines([
+ 'tcpinfo.so --log-file=tcpinfo1 --hooks=ssn_start,txn_start,send_resp_hdr,ssn_close,txn_close --log-level=2',
+ 'tcpinfo.so --log-file=tcpinfo2 --hooks=ssn_start,txn_start,send_resp_hdr,ssn_close,txn_close --log-level=2',
+ 'tcpinfo.so --log-file=tcpinfo3 --hooks=ssn_start,txn_start,send_resp_hdr,ssn_close,txn_close --log-level=2',
+ 'tcpinfo.so --log-file=tcpinfo4 --hooks=ssn_start,txn_start,send_resp_hdr,ssn_close,txn_close --log-level=2',
+ ])
+
+ # only add server headers when there weren't any
+ cls.configs['records.config']['CONFIG'].update({
+ 'proxy.config.log.max_space_mb_for_logs': 10,
+ 'proxy.config.log.max_space_mb_for_orphan_logs': 10,
+ 'proxy.config.log.squid_log_enabled': 1,
+ 'proxy.config.log.squid_log_is_ascii': 1,
+ 'proxy.config.log.rolling_interval_sec': 60,
+ 'proxy.config.log.rolling_size_mb': 1,
+ 'proxy.config.log.max_space_mb_headroom': 1,
+ 'proxy.config.log.max_secs_per_buffer': 1,
+ })
+
+ 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
+
+ logfile_path = os.path.join(self.environment.layout.logdir, 'squid.log')
+ 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'])
http://git-wip-us.apache.org/repos/asf/trafficserver/blob/51ea4aa9/ci/tsqa/tests/test_hostdb.py
----------------------------------------------------------------------
diff --git a/ci/tsqa/tests/test_hostdb.py b/ci/tsqa/tests/test_hostdb.py
new file mode 100644
index 0000000..46bec6a
--- /dev/null
+++ b/ci/tsqa/tests/test_hostdb.py
@@ -0,0 +1,86 @@
+'''
+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 helpers
+
+import tsqa.test_cases
+
+
+class TestHostDBPartiallyFailedDNS(helpers.EnvironmentCase):
+ '''
+ Tests for how hostdb handles when there is one failed and one working 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': 1,
+ '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': 1,
+ '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'])
+
http://git-wip-us.apache.org/repos/asf/trafficserver/blob/51ea4aa9/ci/tsqa/tests/test_https.py
----------------------------------------------------------------------
diff --git a/ci/tsqa/tests/test_https.py b/ci/tsqa/tests/test_https.py
new file mode 100644
index 0000000..a8914e6
--- /dev/null
+++ b/ci/tsqa/tests/test_https.py
@@ -0,0 +1,273 @@
+# 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
+from OpenSSL import SSL
+import socket
+
+import helpers
+import tsqa.utils
+
+# 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):
+ # 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')