blob: adf0ba7c6a10e03271f611506668a940bc9a3378 [file]
# 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.
'''
Tests for TSHttpTxnServerAddrSet() retry behavior with and without cache enabled.
'''
import os
from ports import get_port
Test.Summary = '''
Verify TSHttpTxnServerAddrSet() retry works with and without cache enabled
'''
plugin_name = "test_TSHttpTxnServerAddrSet_retry"
class TestServerAddrSetRetry:
"""Verify retry behavior for TSHttpTxnServerAddrSet() with and without cache."""
def _configure_dns(self, tr: 'TestRun', name: str) -> 'Process':
"""Configure the DNS process for a TestRun."""
return tr.MakeDNServer(name, default=['127.0.0.1'])
def _configure_traffic_server(self, tr: 'TestRun', name: str, dns: 'Process', enable_cache: bool) -> 'Process':
"""Configure the Traffic Server process for a TestRun."""
ts = tr.MakeATSProcess(name, enable_cache=enable_cache)
plugin_path = os.path.join(Test.Variables.AtsBuildGoldTestsDir, 'pluginTest', 'tsapi', '.libs', f'{plugin_name}.so')
ts.Setup.Copy(plugin_path, ts.Env['PROXY_CONFIG_PLUGIN_PLUGIN_DIR'])
ts.Disk.plugin_config.AddLine(f"{plugin_path}")
ts.Disk.records_config.update(
{
'proxy.config.dns.nameservers': f'127.0.0.1:{dns.Variables.Port}',
'proxy.config.dns.resolv_conf': 'NULL',
'proxy.config.diags.debug.enabled': 1,
'proxy.config.diags.debug.tags': 'http|dns|test_TSHttpTxnServerAddrSet_retry',
# Enable retries so we can see if OS_DNS is called multiple times
'proxy.config.http.connect_attempts_max_retries': 3,
'proxy.config.http.connect_attempts_timeout': 1,
})
# Remap to a nonexisting server - the plugin will set addresses
bogus_port = get_port(ts, "bogus_port")
ts.Disk.remap_config.AddLine(f'map / http://non.existent.server.com:{bogus_port}')
return ts
def run(self, enable_cache: bool, description: str, name_suffix: str) -> None:
"""Configure a TestRun."""
tr = Test.AddTestRun(description)
dns = self._configure_dns(tr, f"dns_{name_suffix}")
ts = self._configure_traffic_server(tr, f"ts_{name_suffix}", dns, enable_cache)
# Make a simple request - it should fail since first address is non-routable
# but the plugin should log whether OS_DNS was called multiple times
tr.Processes.Default.Command = f'curl -vs --connect-timeout 5 http://127.0.0.1:{ts.Variables.port}/ -o /dev/null 2>&1; true'
tr.Processes.Default.ReturnCode = 0
tr.Processes.Default.StartBefore(dns)
tr.Processes.Default.StartBefore(ts)
# Override the default diags.log error check - we use TSError() for test output
# Using '=' instead of '+=' replaces the default "no errors" check
ts.Disk.diags_log.Content = Testers.ContainsExpression("OS_DNS hook called, count=1", "First OS_DNS call logged")
ts.Disk.diags_log.Content += Testers.ContainsExpression(
"SUCCESS: OS_DNS hook was called", "Plugin was able to retry with different address")
if enable_cache:
ts.Disk.traffic_out.Content = Testers.ExcludesExpression(
"failed assertion", "ATS should not hit the redirect write-lock assertion")
ts.Disk.traffic_out.Content += Testers.ExcludesExpression(
"received signal 6", "ATS should not abort while retrying origin selection")
test = TestServerAddrSetRetry()
test.run(enable_cache=False, description="Reproduce issue #12611 without cache", name_suffix="nocache")
test.run(enable_cache=True, description="Verify TSHttpTxnServerAddrSet retry is safe with cache enabled", name_suffix="cache")