This is an automated email from the ASF dual-hosted git repository.

bcall pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/trafficserver.git


The following commit(s) were added to refs/heads/master by this push:
     new e069475210 Fix autest compatibility with Fedora 43 / Python 3.14 
(#12857)
e069475210 is described below

commit e0694752109acfde70eb09c499e3d8db64642ae3
Author: Bryan Call <[email protected]>
AuthorDate: Tue Feb 10 15:09:34 2026 -0800

    Fix autest compatibility with Fedora 43 / Python 3.14 (#12857)
    
    Fix autest compatibility with Python 3.14, OpenSSL 3.x, and
    Fedora 43 crypto-policies. Updates deprecated Python APIs, adds
    socket timeouts, skips legacy TLS tests when TLSv1.0/1.1 are
    disabled by system policy, and fixes a timing flake.
---
 tests/gold_tests/autest-site/conditions.test.ext   | 53 ++++++++++++++++++++++
 tests/gold_tests/autest-site/microserver.test.ext  | 25 ++++++----
 tests/gold_tests/autest-site/ports.py              |  2 +-
 .../polite_hook_wait/polite_hook_wait.cc           |  3 +-
 tests/gold_tests/tls/tls_client_versions.test.py   |  1 +
 .../tls/tls_client_versions_minmax.test.py         |  1 +
 6 files changed, 74 insertions(+), 11 deletions(-)

diff --git a/tests/gold_tests/autest-site/conditions.test.ext 
b/tests/gold_tests/autest-site/conditions.test.ext
index ed2656a32c..e01fecdb85 100644
--- a/tests/gold_tests/autest-site/conditions.test.ext
+++ b/tests/gold_tests/autest-site/conditions.test.ext
@@ -16,6 +16,7 @@
 #  See the License for the specific language governing permissions and
 #  limitations under the License.
 
+import os
 import subprocess
 import json
 import re
@@ -51,6 +52,57 @@ def IsOpenSSL(self):
         "SSL library is not OpenSSL")
 
 
+def HasLegacyTLSSupport(self):
+    """Check if the system supports legacy TLS protocols (TLSv1.0 and TLSv1.1).
+
+    Modern OpenSSL 3.x installations often disable these protocols entirely,
+    even if the openssl binary still accepts the -tls1 flag and lists TLSv1 
ciphers.
+
+    On Fedora/RHEL systems, the crypto-policies framework may disable legacy
+    TLS at runtime even when OpenSSL is compiled with support for it. This
+    causes 'openssl ciphers -v -tls1' to still list TLSv1 ciphers, but actual
+    TLS 1.0 connections will fail with "no protocols available".
+
+    We only probe TLSv1.0 (not TLSv1.1 separately) because crypto-policies
+    always disable both legacy versions together. If TLSv1.0 is unavailable,
+    TLSv1.1 will be too.
+
+    The check connects to localhost on a closed port to avoid any external
+    network dependency. A "connection refused" error means the TLS protocol
+    was available but nothing was listening; "no protocols available" means
+    the crypto-policy blocked TLSv1.0 entirely.
+    """
+
+    def check_tls1_support():
+        try:
+            # Connect to localhost on a port nothing is listening on.
+            # This avoids external network dependency while still detecting
+            # whether the crypto-policy allows TLSv1.0.
+            result = subprocess.run(
+                ['openssl', 's_client', '-tls1', '-connect', '127.0.0.1:1'],
+                capture_output=True,
+                text=True,
+                timeout=5,
+                input=''  # Don't wait for interactive input
+            )
+            output = result.stdout + result.stderr
+            # "no protocols available" means TLSv1 is disabled by crypto-policy
+            if 'no protocols available' in output:
+                return False
+            # Connection refused or other errors mean TLSv1 was attempted
+            # (the protocol is available, just no server listening)
+            return True
+        except subprocess.TimeoutExpired:
+            # Timeout on localhost shouldn't happen, but if it does,
+            # assume TLSv1 is not available (safer than false positive)
+            return False
+        except Exception:
+            # If we can't determine, assume TLSv1 is not available (safer)
+            return False
+
+    return self.Condition(check_tls1_support, "System does not support legacy 
TLS protocols (TLSv1.0/TLSv1.1)")
+
+
 def HasCurlVersion(self, version):
     return self.EnsureVersion(["curl", "--version"], min_version=version)
 
@@ -118,6 +170,7 @@ ExtendCondition(HasOpenSSLVersion)
 ExtendCondition(HasProxyVerifierVersion)
 ExtendCondition(IsBoringSSL)
 ExtendCondition(IsOpenSSL)
+ExtendCondition(HasLegacyTLSSupport)
 ExtendCondition(HasATSFeature)
 ExtendCondition(HasCurlVersion)
 ExtendCondition(HasCurlFeature)
diff --git a/tests/gold_tests/autest-site/microserver.test.ext 
b/tests/gold_tests/autest-site/microserver.test.ext
index e15547ff18..70c734f42d 100644
--- a/tests/gold_tests/autest-site/microserver.test.ext
+++ b/tests/gold_tests/autest-site/microserver.test.ext
@@ -17,6 +17,7 @@
 #  limitations under the License.
 
 import json
+import os
 import socket
 import ssl
 
@@ -109,7 +110,7 @@ def addSessionFromFiles(self, session_dir):
 # make headers with the key and values provided
 def makeHeader(self, requestString, **kwargs):
     headerStr = requestString + '\r\n'
-    for k, v in kwargs.iteritems():
+    for k, v in kwargs.items():
         headerStr += k + ': ' + v + '\r\n'
     headerStr = headerStr + '\r\n'
     return headerStr
@@ -142,14 +143,20 @@ def uServerUpAndRunning(serverHost, port, isSsl, isIPv6, 
request, clientcert='',
 
     sock.sendall(request.encode())
     decoded_output = ''
-    while True:
-        host.WriteDebug("??")
-        output = sock.recv(4096)  # suggested bufsize from docs.python.org
-        host.WriteDebug("!!")
-        if len(output) <= 0:
-            break
-        else:
-            decoded_output += output.decode()
+    sock.settimeout(10.0)  # 10 second timeout for recv
+    try:
+        while True:
+            host.WriteDebug("??")
+            output = sock.recv(4096)  # suggested bufsize from docs.python.org
+            host.WriteDebug("!!")
+            if len(output) <= 0:
+                break
+            else:
+                decoded_output += output.decode('utf-8', errors='replace')
+    except socket.timeout:
+        host.WriteDebug(['uServerUpAndRunning', 'when'], "Socket timeout 
waiting for response")
+        sock.close()
+        return False
     sock.close()
     sock = None
 
diff --git a/tests/gold_tests/autest-site/ports.py 
b/tests/gold_tests/autest-site/ports.py
index fc68367fc1..fb36b4088d 100644
--- a/tests/gold_tests/autest-site/ports.py
+++ b/tests/gold_tests/autest-site/ports.py
@@ -74,7 +74,7 @@ def PortOpen(port: int, address: str = None, listening_ports: 
Set[int] = None) -
         host.WriteDebug(
             'PortOpen', f"Connection to port {port} succeeded, the port is 
open, "
             "and a future connection cannot use it")
-    except socket.error:
+    except OSError:
         host.WriteDebug(
             'PortOpen', f"socket error for port {port}, port is closed, "
             "and therefore a future connection can use it")
diff --git a/tests/gold_tests/pluginTest/polite_hook_wait/polite_hook_wait.cc 
b/tests/gold_tests/pluginTest/polite_hook_wait/polite_hook_wait.cc
index 1e071a0dfc..3642bdbac0 100644
--- a/tests/gold_tests/pluginTest/polite_hook_wait/polite_hook_wait.cc
+++ b/tests/gold_tests/pluginTest/polite_hook_wait/polite_hook_wait.cc
@@ -202,8 +202,9 @@ Blocking_action::_thread_func(void *vba)
   ba->_cont_mutex_locked.store(true, std::memory_order_release);
 
   // This is a stand-in for some blocking call to validate the HTTP request in 
some way.
+  // Use a longer delay to account for slower systems and variable scheduling 
latency.
   //
-  std::this_thread::sleep_for(std::chrono::milliseconds(200));
+  std::this_thread::sleep_for(std::chrono::milliseconds(500));
 
   // Pass "validation" for first transaction, fail it for second.
   //
diff --git a/tests/gold_tests/tls/tls_client_versions.test.py 
b/tests/gold_tests/tls/tls_client_versions.test.py
index fcd53c265e..1f0343d9cd 100644
--- a/tests/gold_tests/tls/tls_client_versions.test.py
+++ b/tests/gold_tests/tls/tls_client_versions.test.py
@@ -24,6 +24,7 @@ Test TLS protocol offering  based on SNI
 # for special domain foo.com only offer TLSv1 and TLSv1_1
 
 Test.SkipUnless(Condition.HasOpenSSLVersion("1.1.1"))
+Test.SkipUnless(Condition.HasLegacyTLSSupport())
 
 # Define default ATS
 ts = Test.MakeATSProcess("ts", enable_tls=True)
diff --git a/tests/gold_tests/tls/tls_client_versions_minmax.test.py 
b/tests/gold_tests/tls/tls_client_versions_minmax.test.py
index 2ea7853580..9c63d0700d 100644
--- a/tests/gold_tests/tls/tls_client_versions_minmax.test.py
+++ b/tests/gold_tests/tls/tls_client_versions_minmax.test.py
@@ -24,6 +24,7 @@ Test TLS protocol offering  based on SNI
 # for special domain foo.com only offer TLSv1 and TLSv1_1
 
 Test.SkipUnless(Condition.HasOpenSSLVersion("1.1.1"))
+Test.SkipUnless(Condition.HasLegacyTLSSupport())
 
 # Define default ATS
 ts = Test.MakeATSProcess("ts", enable_tls=True)

Reply via email to