This is an automated email from the ASF dual-hosted git repository.
bneradt 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 4c5fd62302 esi_nested_include test updates (#12471)
4c5fd62302 is described below
commit 4c5fd62302c0db681228169b2a267a36236fac03
Author: Brian Neradt <[email protected]>
AuthorDate: Wed Aug 27 20:06:10 2025 -0500
esi_nested_include test updates (#12471)
Some updates to the esi_nested_include autest. This uses Proxy Verifier
and adds type hints.
---
.../pluginTest/esi/esi_nested_include.replay.yaml | 77 ++++++++++++
.../pluginTest/esi/esi_nested_include.test.py | 130 ++++++++-------------
2 files changed, 126 insertions(+), 81 deletions(-)
diff --git a/tests/gold_tests/pluginTest/esi/esi_nested_include.replay.yaml
b/tests/gold_tests/pluginTest/esi/esi_nested_include.replay.yaml
new file mode 100644
index 0000000000..e664aea62f
--- /dev/null
+++ b/tests/gold_tests/pluginTest/esi/esi_nested_include.replay.yaml
@@ -0,0 +1,77 @@
+# 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.
+
+sessions:
+
+- transactions:
+
+ # Initial request for the main ESI document
+ - client-request:
+ method: GET
+ url: /main.php
+ version: '1.1'
+ headers:
+ fields:
+ - [ Host, www.example.com ]
+ - [ Accept, "*/*" ]
+
+ server-response:
+ status: 200
+ headers:
+ fields:
+ - [ X-Esi, "1" ]
+ - [ Cache-Control, "private" ]
+ - [ Content-Type, "text/html" ]
+ - [ Connection, "close" ]
+ - [ Transfer-Encoding, "chunked" ]
+ content:
+ encoding: plain
+ data: "<head>\n<title>Main ESI
Document</title>\n</head>\n<body>\n<esi:include
src=\"http://www.example.com/esi-nested-include.html\"/>\n</body>\n"
+
+ # This is what the client receives /after/ ESI processing and fetching.
+ # Note: since the maximum inclusion depth is reached, the ESI include is
+ # not expanded.
+ proxy-response:
+ status: 200
+ headers:
+ fields:
+ - [ Content-Type, { value: "text/html", as: equal } ]
+ content:
+ encoding: plain
+ data: "<esi:include
src=\"http://www.example.com/esi-nested-include.html\"/>"
+ verify: { as: contains }
+
+ # ESI nested include requests for the ATS-generated ESI include.
+ - client-request:
+ method: GET
+ url: /esi-nested-include.html
+ version: '1.1'
+ headers:
+ fields:
+ - [ Host, www.example.com ]
+
+ server-response:
+ status: 200
+ headers:
+ fields:
+ - [ X-Esi, "1" ]
+ - [ Cache-Control, "private" ]
+ - [ Content-Type, "text/html" ]
+ - [ Connection, "close" ]
+ - [ Transfer-Encoding, "chunked" ]
+ content:
+ encoding: plain
+ data: "<esi:include
src=\"http://www.example.com/esi-nested-include.html\"/>"
diff --git a/tests/gold_tests/pluginTest/esi/esi_nested_include.test.py
b/tests/gold_tests/pluginTest/esi/esi_nested_include.test.py
index d9ea49442d..b69c381415 100644
--- a/tests/gold_tests/pluginTest/esi/esi_nested_include.test.py
+++ b/tests/gold_tests/pluginTest/esi/esi_nested_include.test.py
@@ -17,8 +17,6 @@ Test nested include for the ESI plugin.
# See the License for the specific language governing permissions and
# limitations under the License.
-import os
-
Test.Summary = '''
Test nested include for the ESI plugin.
'''
@@ -31,107 +29,77 @@ class EsiTest():
A class that encapsulates the configuration and execution of a set of ESI
test cases.
"""
- """ static: The same server Process is used across all tests. """
- _server = None
- """ static: A counter to keep the ATS process names unique across tests.
"""
- _ts_counter = 0
- """ static: A counter to keep any output file names unique across tests.
"""
- _output_counter = 0
- """ The ATS process for this set of test cases. """
- _ts = None
-
- def __init__(self, plugin_config):
- """
- Args:
- plugin_config (str): The config line to place in plugin.config for
- the ATS process.
- """
- if EsiTest._server is None:
- EsiTest._server = EsiTest._create_server()
- self._ts = EsiTest._create_ats(self, plugin_config)
+ _replay_file: str = "esi_nested_include.replay.yaml"
- @staticmethod
- def _create_server():
+ def __init__(self, plugin_config) -> None:
"""
- Create and start a server process.
+ :param plugin_config: esi.so configuration for plugin.config.
"""
- # Configure our server.
- server = Test.MakeOriginServer("server", lookup_key="{%uuid}")
-
- # Generate the set of ESI responses.
- request_header = {
- "headers": "GET /esi-nested-include.php HTTP/1.1\r\n" + "Host:
www.example.com\r\n" + "Content-Length: 0\r\n\r\n",
- "timestamp": "1469733493.993",
- "body": ""
- }
- esi_body = r'''<p>
-<esi:include src="http://www.example.com/esi-nested-include.html"/>
-</p>
-'''
- response_header = {
- "headers":
- "HTTP/1.1 200 OK\r\n" + "X-Esi: 1\r\n" + "Cache-Control:
private\r\n" + "Content-Type: text/html\r\n" +
- "Connection: close\r\n" + "Content-Length:
{}\r\n".format(len(esi_body)) + "\r\n",
- "timestamp": "1469733493.993",
- "body": esi_body
- }
- server.addResponse("sessionfile.log", request_header, response_header)
-
- # Create a run to start the server.
- tr = Test.AddTestRun("Start the server.")
- tr.Processes.Default.StartBefore(server)
- tr.Processes.Default.Command = "echo starting the server"
- tr.Processes.Default.ReturnCode = 0
- tr.StillRunningAfter = server
+ tr = Test.AddTestRun("Request the ESI generated document")
+ self._create_server(tr)
+ self._create_ats(tr, plugin_config)
+ self._create_client(tr)
+
+ def _create_server(self, tr: 'TestRun') -> 'Process':
+ """ Create and start a server process.
+ :param tr: The test run to add the server to.
+ :return: The server process.
+ """
+ # Configure our server using proxy verifier.
+ server = tr.AddVerifierServerProcess("server", self._replay_file,
other_args='--format "{url}"')
+ self._server = server
+
+ # Validate server traffic
+ server.Streams.All += Testers.ContainsExpression('GET /main.php',
'Verify the server received the initial request.')
+ server.Streams.All += Testers.ContainsExpression(
+ 'GET /esi-nested-include.html', 'Verify the server received the
nested include request.')
return server
- @staticmethod
- def _create_ats(self, plugin_config):
- """
- Create and start an ATS process.
+ def _create_ats(self, tr: 'TestRun', plugin_config: str) -> 'Process':
+ """ Create and start an ATS process.
+ :param tr: The test run to add the ATS to.
+ :param plugin_config: The plugin configuration to use.
+ :return: The ATS process.
"""
- EsiTest._ts_counter += 1
-
# Configure ATS with a vanilla ESI plugin configuration.
- ts = Test.MakeATSProcess("ts{}".format(EsiTest._ts_counter))
+ ts = tr.MakeATSProcess(f"ts")
+ self._ts = ts
ts.Disk.records_config.update({
'proxy.config.diags.debug.enabled': 1,
'proxy.config.diags.debug.tags': 'http|plugin_esi',
})
- ts.Disk.remap_config.AddLine(f'map http://www.example.com/
http://127.0.0.1:{EsiTest._server.Variables.Port}')
+ server_port = self._server.Variables.http_port
+ ts.Disk.remap_config.AddLine(f'map http://www.example.com/
http://127.0.0.1:{server_port}')
ts.Disk.plugin_config.AddLine(plugin_config)
ts.Disk.diags_log.Content = Testers.ContainsExpression(
r'The current esi inclusion depth \(3\) is larger than or equal to
the max \(3\)',
'Verify the ESI error concerning the max inclusion depth')
-
- # Create a run to start the ATS process.
- tr = Test.AddTestRun("Start the ATS process.")
- tr.Processes.Default.StartBefore(ts)
- tr.Processes.Default.Command = "echo starting ATS"
- tr.Processes.Default.ReturnCode = 0
- tr.StillRunningAfter = ts
return ts
- def run_test(self):
- # Test 1: Verify basic ESI functionality without processing internal
txn.
- tr = Test.AddTestRun("First request")
- tr.MakeCurlCommand(
- f'http://127.0.0.1:{self._ts.Variables.port}/main.php -H"Host:
www.example.com" '
- '-H"Accept: */*" --verbose',
- ts=self._ts)
- tr.Processes.Default.ReturnCode = 0
- tr.Processes.Default.Streams.stdout = "gold/nested_include_body.gold"
- tr.StillRunningAfter = self._server
- tr.StillRunningAfter = self._ts
+ def _create_client(self, tr: 'TestRun') -> None:
+ """ Create and start a client process to generate the request.
+ :param tr: The test run to add the client to.
+ """
+ # Note, just request the main.php file. Otherwise the client will do
the
+ # ESI requests in the replay file as well.
+ p = tr.AddVerifierClientProcess(
+ "client", self._replay_file, http_ports=[self._ts.Variables.port],
other_args='--format "{url}" --keys /main.php')
+ p.ReturnCode = 0
+ p.StartBefore(self._server)
+ p.StartBefore(self._ts)
+
+ # Double check that the client received the response.
+ p.Streams.stdout += Testers.ContainsExpression(
+ 'Received an HTTP/1 chunked body', 'Verify the client received the
response.')
+
+ p.Streams.stdout += Testers.ContainsExpression(
+ 'esi:include
src="http://www.example.com/esi-nested-include.html"/>', 'Verify the ATS
received the esi include.')
#
# Configure and run the test cases.
#
-
-# Run the tests with ESI configured with private response.
-first_test = EsiTest(plugin_config='esi.so')
-first_test.run_test()
+EsiTest(plugin_config='esi.so')