diff --git a/tests/Makefile.am b/tests/Makefile.am index d936e1d45c9..e3d4097678a 100644 --- a/tests/Makefile.am +++ b/tests/Makefile.am @@ -32,6 +32,7 @@ AM_LDFLAGS += -rpath $(abs_builddir) include gold_tests/continuations/plugins/Makefile.inc include gold_tests/chunked_encoding/Makefile.inc +include gold_tests/timeout/Makefile.inc include gold_tests/tls/Makefile.inc include tools/plugins/Makefile.inc diff --git a/tests/gold_tests/timeout/Makefile.inc b/tests/gold_tests/timeout/Makefile.inc new file mode 100644 index 00000000000..6323d7ceee6 --- /dev/null +++ b/tests/gold_tests/timeout/Makefile.inc @@ -0,0 +1,19 @@ +# Licensed to the Apache Software Foundation (ASF) under one +# or more contributor license agreements. See the NOTICE file +# distributed with this work for additional information +# regarding copyright ownership. The ASF licenses this file +# to you under the Apache License, Version 2.0 (the +# "License"); you may not use this file except in compliance +# with the License. You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +noinst_PROGRAMS += gold_tests/timeout/ssl-delay-server +gold_tests_timeout_ssl_delay_server_SOURCES = gold_tests/timeout/ssl-delay-server.cc +gold_tests_timeout_ssl_delay_server_LDADD = -lssl -lcrypto diff --git a/tests/gold_tests/timeout/case1.sh b/tests/gold_tests/timeout/case1.sh new file mode 100755 index 00000000000..126b5931b8b --- /dev/null +++ b/tests/gold_tests/timeout/case1.sh @@ -0,0 +1,23 @@ +# Licensed to the Apache Software Foundation (ASF) under one +# or more contributor license agreements. See the NOTICE file +# distributed with this work for additional information +# regarding copyright ownership. The ASF licenses this file +# to you under the Apache License, Version 2.0 (the +# "License"); you may not use this file except in compliance +# with the License. You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +# This is funky delaying and backgrounding the client request, but I just +# could not get the command executing in the network space to go to background +# without blocking the autest. + +(sleep 1; curl -i http://127.0.0.1:${1}/not-blocked ) & + +sudo ip netns exec testserver nc -4 -l $2 -c "sh ./delay-server.sh" diff --git a/tests/gold_tests/timeout/case2.sh b/tests/gold_tests/timeout/case2.sh new file mode 100755 index 00000000000..4b9d7b7f060 --- /dev/null +++ b/tests/gold_tests/timeout/case2.sh @@ -0,0 +1,37 @@ +# Licensed to the Apache Software Foundation (ASF) under one +# or more contributor license agreements. See the NOTICE file +# distributed with this work for additional information +# regarding copyright ownership. The ASF licenses this file +# to you under the Apache License, Version 2.0 (the +# "License"); you may not use this file except in compliance +# with the License. You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +# This is funky delaying and backgrounding the client request, but I just +# could not get the command executing in the network space to go to background +# without blocking the autest. + + +if [ $# == 5 ] +then +./ssl-delay-server $1 $2 $3 server.pem 2> server${1}post.log & +sleep 1 +curl -H'Connection:close' -d "bob" -i http://127.0.0.1:$4/${5} --tlsv1.2 +else +./ssl-delay-server $1 $2 $3 server.pem 2> server${1}get.log & +sleep 1 +curl -H'Connection:close' -i http://127.0.0.1:$4/${5} --tlsv1.2 +fi + +kill $(jobs -pr) + +exit 0 + + diff --git a/tests/gold_tests/timeout/conn_timeout.test.py b/tests/gold_tests/timeout/conn_timeout.test.py new file mode 100644 index 00000000000..9ce5b4b7bc4 --- /dev/null +++ b/tests/gold_tests/timeout/conn_timeout.test.py @@ -0,0 +1,71 @@ +''' +''' +# 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.Summary = 'Testing ATS TCP handshake timeout' + +# Skipping this in the normal CI because it requires privilege. +# Comment out to run in your privileged environment +Test.SkipIf(Condition.true("Test requires privilege")) + +ts = Test.MakeATSProcess("ts") + +Test.ContinueOnFail = True +Test.GetTcpPort("blocked_upstream_port") +Test.GetTcpPort("upstream_port") + +ts.Disk.records_config.update({ + 'proxy.config.url_remap.remap_required': 1, + 'proxy.config.http.connect_attempts_timeout': 2, + 'proxy.config.http.connect_attempts_max_retries': 0, + 'proxy.config.http.transaction_no_activity_timeout_out': 5, + 'proxy.config.diags.debug.enabled': 0, + 'proxy.config.diags.debug.tags': 'http', +}) + +ts.Disk.remap_config.AddLine('map /blocked http://10.1.1.1:{0}'.format(Test.Variables.blocked_upstream_port)) +ts.Disk.remap_config.AddLine('map /not-blocked http://10.1.1.1:{0}'.format(Test.Variables.upstream_port)) + +# Set up the network name space. Requires privilege +tr = Test.AddTestRun("tr-ns-setup") +tr.Processes.Default.StartBefore(ts) +tr.Processes.Default.TimeOut = 2 +tr.Setup.Copy('setupnetns.sh') +tr.Processes.Default.Command = 'echo start; sudo sh -x ./setupnetns.sh {0} {1}'.format(Test.Variables.blocked_upstream_port, Test.Variables.upstream_port) + +# Request to the port that is blocked in the network ns. The SYN should never be responded to +# and the connect timeout should trigger with a 50x return. If the SYN handshake occurs, the +# no activity timeout would trigger, but not before the test timeout expires +tr = Test.AddTestRun("tr-blocking") +tr.Processes.Default.Command = 'curl -i http://127.0.0.1:{0}/blocked {0}'.format(ts.Variables.port) +tr.Processes.Default.TimeOut = 4 +tr.Processes.Default.Streams.All = Testers.ContainsExpression("HTTP/1.1 502 internal error - server connection terminated", "Connect failed") + +# Should not catch the connect timeout. Even though the first bytes are not sent until after the 2 second connect timeout +# But before the no-activity timeout +tr = Test.AddTestRun("tr-delayed") +tr.Setup.Copy('delay-server.sh') +tr.Setup.Copy('case1.sh') +tr.Processes.Default.Command = 'sh ./case1.sh {0} {1}'.format(ts.Variables.port, ts.Variables.upstream_port) +tr.Processes.Default.TimeOut = 7 +tr.Processes.Default.Streams.All = Testers.ContainsExpression("HTTP/1.1 200", "Connect succeeded") + + +# cleanup the network namespace and virtual network +tr = Test.AddTestRun("tr-cleanup") +tr.Processes.Default.Command = 'sudo ip netns del testserver; sudo ip link del veth0 type veth peer name veth1' +tr.Processes.Default.TimeOut = 4 diff --git a/tests/gold_tests/timeout/delay-server.sh b/tests/gold_tests/timeout/delay-server.sh new file mode 100644 index 00000000000..335df64cd18 --- /dev/null +++ b/tests/gold_tests/timeout/delay-server.sh @@ -0,0 +1,20 @@ +# Licensed to the Apache Software Foundation (ASF) under one +# or more contributor license agreements. See the NOTICE file +# distributed with this work for additional information +# regarding copyright ownership. The ASF licenses this file +# to you under the Apache License, Version 2.0 (the +# "License"); you may not use this file except in compliance +# with the License. You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +sleep 3 +printf "HTTP/1.1 200\r\nTransfer-encoding: chunked\r\n\r\n" +printf "F\r\n1234567890" +printf "12345\r\n0\r\n\r\n" diff --git a/tests/gold_tests/timeout/setupnetns.sh b/tests/gold_tests/timeout/setupnetns.sh new file mode 100644 index 00000000000..1ce948251e9 --- /dev/null +++ b/tests/gold_tests/timeout/setupnetns.sh @@ -0,0 +1,30 @@ +# 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. + +ip netns del testserver +ip link del veth0 type veth peer name veth1 +ip netns add testserver +ip link add veth0 type veth peer name veth1 +ip addr add 10.1.1.2/24 dev veth0 +ip link set up dev veth0 +ip link set veth1 netns testserver +ip netns exec testserver ip addr add 10.1.1.1/24 dev veth1 +ip netns exec testserver ip link set up dev veth1 +ip netns exec testserver iptables -t filter -A INPUT -p tcp --dport $1 -m tcp --tcp-flags FIN,SYN,RST,ACK SYN -m comment --comment v4-new-connections -j DROP +ip netns exec testserver iptables -t filter -A INPUT -p tcp --dport $2 -j ACCEPT +ip netns exec testserver iptables -t filter -A OUTPUT -p tcp -j ACCEPT +# Depending on your iptables policy, you may need to adjust to allow traffic to pass over the veth0 virtual connection + diff --git a/tests/gold_tests/timeout/ssl-delay-server.cc b/tests/gold_tests/timeout/ssl-delay-server.cc new file mode 100644 index 00000000000..4d1bf8756b1 --- /dev/null +++ b/tests/gold_tests/timeout/ssl-delay-server.cc @@ -0,0 +1,256 @@ +/** @file + + SSL delay test server + + @section license License + + 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 +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +char req_buf[10000]; +char post_buf[1000]; + +SSL_CTX *svr_ctx; +int connect_delay; +int ttfb_delay; + +pthread_mutex_t *mutex_buf = NULL; + +struct thread_info { + struct addrinfo *result, *rp; + SSL_SESSION *session; +}; + +void +SSL_locking_callback(int mode, int type, const char *file, int line) +{ + if (mode & CRYPTO_LOCK) { + pthread_mutex_lock(&mutex_buf[type]); + } else if (mode & CRYPTO_UNLOCK) { + pthread_mutex_unlock(&mutex_buf[type]); + } else { + printf("invalid SSL locking mode 0x%x\n", mode); + } +} + +void +SSL_pthreads_thread_id(CRYPTO_THREADID *id) +{ + CRYPTO_THREADID_set_numeric(id, (unsigned long)pthread_self()); +} + +char input_buf[1000]; +char response_buf[] = "200 HTTP/1.1\r\nConnection: close\r\n\r\n"; + +void * +run_session(void *arg) +{ + int sfd = (intptr_t)arg; + SSL *ssl = SSL_new(svr_ctx); + if (ssl == NULL) { + fprintf(stderr, "Failed to create ssl\n"); + exit(1); + } + +#if OPENSSL_VERSION_NUMBER >= 0x10100000 + SSL_set_max_proto_version(ssl, TLS1_2_VERSION); +#endif + + SSL_set_fd(ssl, sfd); + + fprintf(stderr, "Accept try %d\n", sfd); + + // Potentially delay before processing the TLS handshake + if (connect_delay > 0) { + fprintf(stderr, "Connect delay %d\n", connect_delay); + // Delay here + sleep(connect_delay); + } + int did_accept = 0; + struct timeval timeout; + fd_set read_fd, write_fd, except_fd; + + int ret = SSL_accept(ssl); + while (ret < 0) { + timeout.tv_sec = 1; + timeout.tv_usec = 0; + FD_ZERO(&read_fd); + FD_ZERO(&write_fd); + FD_ZERO(&except_fd); + FD_SET(sfd, &read_fd); + FD_SET(sfd, &write_fd); + FD_SET(sfd, &except_fd); + int select_r; + if ((select_r = select(sfd + 1, &read_fd, &write_fd, &except_fd, &timeout)) < 0) { + perror("Select failed"); + exit(1); + } + if (select_r > 0) { + if (FD_ISSET(sfd, &except_fd)) { + fprintf(stderr, "Socket failed\n"); + break; + } + if (FD_ISSET(sfd, &read_fd)) { + ret = SSL_accept(ssl); + } else if (FD_ISSET(sfd, &write_fd)) { + ret = SSL_connect(ssl); + } + } else { + fprintf(stderr, "Select timeout %ld\n", time(NULL)); + } + } + + if (!did_accept && ret == 1) { + did_accept = 1; + fprintf(stderr, "Done accept\n"); + } else { + fprintf(stderr, "Failed accept\n"); + exit(1); + } + + if (did_accept) { + int opt = fcntl(sfd, F_GETFL); + opt = opt & ~O_NONBLOCK; + if (fcntl(sfd, F_SETFL, opt) < 0) { + perror("Failed to set block"); + exit(1); + } + + ret = SSL_read(ssl, input_buf, sizeof(input_buf)); + if (ret < 0) { + // Failure + fprintf(stderr, "Server read failure\n"); + } else { + fprintf(stderr, "TTFB delay\n"); + if (ttfb_delay > 0) { + // TTFB delay + sleep(ttfb_delay); + } + fprintf(stderr, "Write response\n"); + ret = SSL_write(ssl, response_buf, strlen(response_buf)); + fprintf(stderr, "Write response %d\n", ret); + if (ret <= 0) { + fprintf(stderr, "Server write failure\n"); + } else { + fprintf(stderr, "Write response succeeded. Go to the next one\n"); + } + } + } + if (ssl) { + SSL_free(ssl); + } + close(sfd); + + return NULL; +} + +/** + * Simple TLS server with configurable delays + */ +int +main(int argc, char *argv[]) +{ + int sfd; + + if (argc != 5) { + fprintf(stderr, "Usage: %s \n", argv[0]); + exit(EXIT_FAILURE); + } + short listen_port = atoi(argv[1]); + connect_delay = atoi(argv[2]); + ttfb_delay = atoi(argv[3]); + const char *pem_file = argv[4]; + + fprintf(stderr, "Listen on %d connect delay=%d ttfb delay=%d\n", listen_port, connect_delay, ttfb_delay); + + int listenfd = socket(AF_INET, SOCK_STREAM, 0); + struct sockaddr_in serv_addr; + + memset(&serv_addr, '0', sizeof(serv_addr)); + + serv_addr.sin_family = AF_INET; + serv_addr.sin_addr.s_addr = htonl(INADDR_ANY); + serv_addr.sin_port = htons(listen_port); + + bind(listenfd, (struct sockaddr *)&serv_addr, sizeof(serv_addr)); + + SSL_load_error_strings(); + SSL_library_init(); + + mutex_buf = (pthread_mutex_t *)OPENSSL_malloc(CRYPTO_num_locks() * sizeof(pthread_mutex_t)); + for (int i = 0; i < CRYPTO_num_locks(); i++) { + pthread_mutex_init(&mutex_buf[i], NULL); + } + + CRYPTO_set_locking_callback(SSL_locking_callback); +#if CRYPTO_THREADID_set_callback + CRYPTO_THREADID_set_callback(SSL_pthreads_thread_id); +#endif + + svr_ctx = SSL_CTX_new(SSLv23_server_method()); + // Associate cert and key + if (SSL_CTX_use_certificate_file(svr_ctx, pem_file, SSL_FILETYPE_PEM) != 1) { + printf("Failed to load certificate from %s\n", pem_file); + exit(1); + } + + if (SSL_CTX_use_PrivateKey_file(svr_ctx, pem_file, SSL_FILETYPE_PEM) != 1) { + printf("Failed to load private key from %s\n", pem_file); + exit(1); + } + + listen(listenfd, 10); + + for (;;) { + sfd = accept(listenfd, (struct sockaddr *)NULL, NULL); + if (sfd <= 0) { + // Failure + printf("Listen failure\n"); + exit(1); + } + + fprintf(stderr, "Spawn off new sesson thread %d\n", sfd); + + if (fcntl(sfd, F_SETFL, O_NONBLOCK) < 0) { + perror("Failed to set non-blocking"); + } + + // Spawn off new thread + pthread_t thread_id; + pthread_create(&thread_id, NULL, run_session, (void *)((intptr_t)sfd)); + } + + exit(0); +} diff --git a/tests/gold_tests/timeout/timeout.gold b/tests/gold_tests/timeout/timeout.gold deleted file mode 100644 index 8f268083075..00000000000 --- a/tests/gold_tests/timeout/timeout.gold +++ /dev/null @@ -1,3 +0,0 @@ -`` -HTTP/1.1 200 OK -`` diff --git a/tests/gold_tests/timeout/timeout.test.py b/tests/gold_tests/timeout/timeout.test.py deleted file mode 100644 index 63c8ca3f8ec..00000000000 --- a/tests/gold_tests/timeout/timeout.test.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. - -Test.Summary = 'Testing ATS TCP handshake timeout' - -ts = Test.MakeATSProcess("ts") -server = Test.MakeOriginServer("server", delay=15) -dns = Test.MakeDNServer("dns", ip='127.0.0.1', default=['127.0.0.1']) - -request_header = {"headers": "GET /file HTTP/1.1\r\nHost: *\r\n\r\n", "timestamp": "5678", "body": ""} -response_header = {"headers": "HTTP/1.1 200 OK\r\nConnection: close\r\n\r\n", "timestamp": "5678", "body": ""} - -server.addResponse("sessionfile.log", request_header, response_header) - -ts.Disk.records_config.update({ - 'proxy.config.dns.nameservers': '127.0.0.1:{0}'.format(dns.Variables.Port), - 'proxy.config.dns.resolv_conf': 'NULL', - 'proxy.config.url_remap.remap_required': 0, - 'proxy.config.http.connect_attempts_timeout': 5 -}) - -tr = Test.AddTestRun("tr") -tr.Processes.Default.StartBefore(server) -tr.Processes.Default.StartBefore(ts) -tr.Processes.Default.StartBefore(dns) -tr.Processes.Default.Command = 'curl -i -x http://127.0.0.1:{0} http://127.0.0.1:{1}/file'.format(ts.Variables.port, server.Variables.Port) -tr.Processes.Default.Streams.stdout = "timeout.gold" diff --git a/tests/gold_tests/timeout/tls_conn_timeout.test.py b/tests/gold_tests/timeout/tls_conn_timeout.test.py new file mode 100644 index 00000000000..7eed209d371 --- /dev/null +++ b/tests/gold_tests/timeout/tls_conn_timeout.test.py @@ -0,0 +1,104 @@ +''' +''' +# 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.Summary = 'Testing ATS TLS handshake timeout' + +ts = Test.MakeATSProcess("ts") + +server2 = Test.MakeOriginServer("server2") + +Test.Setup.Copy('ssl-delay-server') + +Test.ContinueOnFail = True +Test.GetTcpPort("block_connect_port") +Test.GetTcpPort("block_ttfb_port") +Test.GetTcpPort("get_block_connect_port") +Test.GetTcpPort("get_block_ttfb_port") + +ts.Disk.records_config.update({ + 'proxy.config.url_remap.remap_required': 1, + 'proxy.config.http.connect_attempts_timeout': 1, + 'proxy.config.http.post_connect_attempts_timeout': 1, + 'proxy.config.http.connect_attempts_max_retries': 1, + 'proxy.config.http.transaction_no_activity_timeout_out': 4, + 'proxy.config.diags.debug.enabled': 0, + 'proxy.config.diags.debug.tags': 'http|ssl', +}) + +ts.Disk.remap_config.AddLine('map /connect_blocked https://127.0.0.1:{0}'.format(Test.Variables.block_connect_port)) +ts.Disk.remap_config.AddLine('map /ttfb_blocked https://127.0.0.1:{0}'.format(Test.Variables.block_ttfb_port)) +ts.Disk.remap_config.AddLine('map /get_connect_blocked https://127.0.0.1:{0}'.format(Test.Variables.get_block_connect_port)) +ts.Disk.remap_config.AddLine('map /get_ttfb_blocked https://127.0.0.1:{0}'.format(Test.Variables.get_block_ttfb_port)) + +# Run the connection and TTFB timeout tests first with POST. + +# Request the port that should timeout in the handshake +# Should retry once +tr = Test.AddTestRun("tr-blocking") +tr.Setup.Copy("case2.sh") +tr.Processes.Default.StartBefore(Test.Processes.ts, ready=When.PortOpen(ts.Variables.port)) +tr.Setup.Copy("../chunked_encoding/ssl/server.pem") +tr.Processes.Default.Command = 'sh ./case2.sh {0} 3 0 {1} connect_blocked'.format(Test.Variables.block_connect_port, ts.Variables.port) +tr.Processes.Default.TimeOut = 6 +tr.Processes.Default.Streams.All = Testers.ContainsExpression("HTTP/1.1 502 internal error - server connection terminated", "Connect failed") + +# Should not catch the connect timeout. Even though the first bytes are not sent until after the 2 second connect timeout +# Shoudl not retry the connection +tr = Test.AddTestRun("tr-delayed") +tr.Processes.Default.Command = 'sh ./case2.sh {0} 0 6 {1} ttfb_blocked'.format(Test.Variables.block_ttfb_port, ts.Variables.port) +tr.Processes.Default.TimeOut = 15 +tr.Processes.Default.Streams.All = Testers.ContainsExpression("504 Connection Timed Out", "Conntect timeout") +tr.Processes.Default.ReturnCode = 0 + +tr = Test.AddTestRun("tr-connect-retry") +tr.Processes.Default.Command = 'grep "Accept try" server{0}post.log | wc -l'.format(Test.Variables.block_connect_port) +tr.Processes.Default.Streams.All = Testers.ContainsExpression("^2$", "Two accept tries") +tr.Processes.Default.ReturnCode = 0 + +tr = Test.AddTestRun("tr-post-ttfb-retry") +tr.Processes.Default.Command = 'grep "Accept try" server{0}post.log | wc -l'.format(Test.Variables.block_ttfb_port) +tr.Processes.Default.Streams.All = Testers.ContainsExpression("^1$", "Only 1 accept try") +tr.Processes.Default.ReturnCode = 0 + +# Run the connection and TTFB timeout tests again with GET + +# Request the port that should timeout in the handshake +# Should retry once +tr = Test.AddTestRun("tr-blocking") +tr.Processes.Default.Command = 'sh ./case2.sh {0} 3 0 {1} get_connect_blocked get'.format(Test.Variables.get_block_connect_port, ts.Variables.port) +tr.Processes.Default.TimeOut = 6 +tr.Processes.Default.Streams.All = Testers.ContainsExpression("HTTP/1.1 502 internal error - server connection terminated", "Connect failed") + +# Should not catch the connect timeout. Even though the first bytes are not sent until after the 2 second connect timeout +# Since get is idempotent, It will try to connect again even though the GET request had been sent +tr = Test.AddTestRun("tr-delayed") +tr.Processes.Default.Command = 'sh ./case2.sh {0} 0 6 {1} get_ttfb_blocked get'.format(Test.Variables.get_block_ttfb_port, ts.Variables.port) +tr.Processes.Default.TimeOut = 15 +tr.Processes.Default.Streams.All = Testers.ContainsExpression("504 Connection Timed Out", "Conntect timeout") +tr.Processes.Default.ReturnCode = 0 + +tr = Test.AddTestRun("tr-connect-retry") +tr.Processes.Default.Command = 'grep "Accept try" server{0}get.log | wc -l'.format(Test.Variables.get_block_connect_port) +tr.Processes.Default.Streams.All = Testers.ContainsExpression("^2$", "Two accept tries") +tr.Processes.Default.ReturnCode = 0 + +tr = Test.AddTestRun("tr-get-ttfb-retry") +tr.Processes.Default.Command = 'grep "Accept try" server{0}get.log | wc -l'.format(Test.Variables.get_block_ttfb_port) +tr.Processes.Default.Streams.All = Testers.ContainsExpression("^2$", "Two accept tries") +tr.Processes.Default.ReturnCode = 0 +