blob: db803deb1877ce1beee750028512c52fb4d9108e [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.
import os
Test.Summary = '''
Combined Slice/crr ident test
'''
# Test description:
# Preload the cache with the entire asset to be range requested.
# Reload remap rule with slice plugin
# Request content through the slice plugin
Test.SkipUnless(
Condition.PluginExists('cache_range_requests.so'),
Condition.PluginExists('header_rewrite.so'),
Condition.PluginExists('slice.so'),
Condition.PluginExists('xdebug.so'),
)
Test.ContinueOnFail = False
# configure origin server
server = Test.MakeOriginServer("server", lookup_key="{%UID}")
# default root
req_header_chk = {
"headers": "GET / HTTP/1.1\r\n" + "Host: www.example.com\r\n" + "UID: none\r\n" + "\r\n",
"timestamp": "1469733493.993",
"body": "",
}
res_header_chk = {
"headers": "HTTP/1.1 200 OK\r\n" + "Connection: close\r\n" + "\r\n",
"timestamp": "1469733493.993",
"body": "",
}
server.addResponse("sessionlog.json", req_header_chk, res_header_chk)
# Define ATS and configure
ts = Test.MakeATSProcess("ts")
# set up slice plugin with remap host into cache_range_requests
ts.Disk.remap_config.AddLines(
[
f'map http://slice/ http://127.0.0.1:{server.Variables.Port}/' +
' @plugin=slice.so @pparam=--blockbytes-test=3 @pparam=--remap-host=crr',
f'map http://crr/ http://127.0.0.1:{server.Variables.Port}/' +
' @plugin=cache_range_requests.so @pparam=--consider-ims @pparam=--consider-ident' +
' @plugin=header_rewrite.so @pparam=hdr_rw.conf',
])
ts.Disk.logging_yaml.AddLines(
'''
logging:
formats:
- name: custom
format: 'cpuup=%<cquup> sssc=%<sssc> pssc=%<pssc> phr=%<phr> range=::%<{Range}cqh>:: x-crr-ident=::%<{X-Crr-Ident}cqh>:: uid=::%<{UID}pqh>:: crc=%<crc>'
logs:
- filename: transaction
format: custom
'''.split("\n"))
ts.Disk.plugin_config.AddLine('xdebug.so --enable=x-cache')
ts.Disk.records_config.update(
{
'proxy.config.diags.debug.enabled': 1,
'proxy.config.diags.debug.tags': 'cache_range_requests|header_rewrite|slice|log',
})
ts.Disk.MakeConfigFile("hdr_rw.conf").AddLines(
[
'cond %{SEND_REQUEST_HDR_HOOK}', 'cond %{HEADER:Range} ="bytes=0-2" [AND]', 'set-header UID %{CLIENT-HEADER:UID} 0'
'', 'cond %{SEND_REQUEST_HDR_HOOK}', 'cond %{HEADER:Range} ="bytes=3-5" [AND]', 'set-header UID %{CLIENT-HEADER:UID} 1'
])
# Test case: short lived asset. second slice should be HIT_FRESH
req_header_plain_0 = {
"headers": "GET /plain HTTP/1.1\r\n" + "Host: www.example.com\r\n" + "UID: plain 0\r\n" + "Range: bytes=0-2\r\n" + "\r\n",
"timestamp": "1469733493.993",
"body": "",
}
res_header_plain_0 = {
"headers":
"HTTP/1.1 206 Partial Content\r\n" + "Accept-Ranges: bytes\r\n" + "Cache-Control: max-age=1\r\n" + "Connection: close\r\n" +
"Content-Range: bytes 0-2/5\r\n" + 'Etag: "plain"\r\n' + "\r\n",
"timestamp": "1469733493.993",
"body": "aaa"
}
server.addResponse("sessionlog.json", req_header_plain_0, res_header_plain_0)
req_header_plain_1 = {
"headers": "GET /plain HTTP/1.1\r\n" + "Host: www.example.com\r\n" + "UID: plain 1\r\n" + "Range: bytes=3-5\r\n" + "\r\n",
"timestamp": "1469733493.993",
"body": "",
}
res_header_plain_1 = {
"headers":
"HTTP/1.1 206 Partial Content\r\n" + "Accept-Ranges: bytes\r\n" + "Cache-Control: max-age=1\r\n" + "Connection: close\r\n" +
"Content-Range: bytes 3-4/5\r\n" + 'Etag: "plain"\r\n' + "\r\n",
"timestamp": "1469733493.993",
"body": "BB"
}
server.addResponse("sessionlog.json", req_header_plain_1, res_header_plain_1)
# curl helper
curl_and_args = '-s -D /dev/stdout -o /dev/stderr -x localhost:{}'.format(ts.Variables.port) + ' -H "x-debug: x-cache"'
# 0 Test - Preload plain asset
tr = Test.AddTestRun("Preload plain")
ps = tr.Processes.Default
ps.StartBefore(server, ready=When.PortOpen(server.Variables.Port))
ps.StartBefore(Test.Processes.ts)
tr.MakeCurlCommand(curl_and_args + ' http://slice/plain -H "UID: plain"', ts=ts)
ps.ReturnCode = 0
ps.Streams.stderr.Content = Testers.ContainsExpression("aaaBB", "expected aaaBB")
ps.Streams.stdout.Content = Testers.ContainsExpression('Etag: "plain"', "expected etag plain")
tr.StillRunningAfter = ts
# 2 Test - Request again, should result in stale asset
tr = Test.AddTestRun("Request 2nd slice (expect slice1 to be fresh)")
tr.DelayStart = 2 # ensure its really stale
ps = tr.Processes.Default
tr.MakeCurlCommand(curl_and_args + ' http://slice/plain -H "UID: plain"', ts=ts)
ps.ReturnCode = 0
ps.Streams.stderr = Testers.ContainsExpression("aaaBB", "expected aaaBB")
ps.Streams.stdout.Content = Testers.ContainsExpression('Etag: "plain"', "expected etag plain")
tr.StillRunningAfter = ts
# change out the asset
req_header_chg_0 = {
"headers": "GET /plain HTTP/1.1\r\n" + "Host: www.example.com\r\n" + "UID: chg 0\r\n" + "Range: bytes=0-2\r\n" + "\r\n",
"timestamp": "1469733493.993",
"body": "",
}
res_header_chg_0 = {
"headers":
"HTTP/1.1 206 Partial Content\r\n" + "Accept-Ranges: bytes\r\n" + "Cache-Control: max-age=60\r\n" +
"Connection: close\r\n" + "Content-Range: bytes 0-2/5\r\n" + 'Etag: "chg"\r\n' + "\r\n",
"timestamp": "1469733493.993",
"body": "AAA"
}
server.addResponse("sessionlog.json", req_header_chg_0, res_header_chg_0)
req_header_chg_1 = {
"headers": "GET /plain HTTP/1.1\r\n" + "Host: www.example.com\r\n" + "UID: chg 1\r\n" + "Range: bytes=3-5\r\n" + "\r\n",
"timestamp": "1469733493.993",
"body": "",
}
res_header_chg_1 = {
"headers":
"HTTP/1.1 206 Partial Content\r\n" + "Accept-Ranges: bytes\r\n" + "Cache-Control: max-age=60\r\n" +
"Connection: close\r\n" + "Content-Range: bytes 3-4/5\r\n" + 'Etag: "chg"\r\n' + "\r\n",
"timestamp": "1469733493.993",
"body": "bb"
}
server.addResponse("sessionlog.json", req_header_chg_1, res_header_chg_1)
# 3 Test - Request again, should result in new asset
tr = Test.AddTestRun("Request again, asset replaced")
tr.DelayStart = 2 # ensure its really stale
ps = tr.Processes.Default
tr.MakeCurlCommand(curl_and_args + ' http://slice/plain -H "UID: chg"', ts=ts)
ps.ReturnCode = 0
ps.Streams.stderr = Testers.ContainsExpression("AAAbb", "expected AAAbb")
ps.Streams.stdout.Content = Testers.ContainsExpression('Etag: "chg"', "expected etag chg")
tr.StillRunningAfter = ts
# 4 Test - Request again, should all be hit
tr = Test.AddTestRun("Request again, asset replaced but hit")
tr.DelayStart = 2 # ensure its really stale
ps = tr.Processes.Default
tr.MakeCurlCommand(curl_and_args + ' http://slice/plain -H "UID: chg"', ts=ts)
ps.ReturnCode = 0
ps.Streams.stderr = Testers.ContainsExpression("AAAbb", "expected AAAbb")
ps.Streams.stdout.Content = Testers.ContainsExpression('Etag: "chg"', "expected etag chg")
tr.StillRunningAfter = ts
# 5 Test - add token to transaction log
tr = Test.AddTestRun("Fetch 404.txt asset")
ps = tr.Processes.Default
tr.MakeCurlCommand(curl_and_args + ' http://crr/404.txt', ts=ts)
ps.ReturnCode = 0
ps.Streams.stdout.Content = Testers.ContainsExpression("404", "expected 404 Not Found response")
tr.StillRunningAfter = ts
tslog = os.path.join(ts.Variables.LOGDIR, 'transaction.log')
Test.AddAwaitFileContainsTestRun('Await ts transactions to finish logging.', tslog, '404.txt')
# 6 Check logs
tr = Test.AddTestRun()
tr.Processes.Default.Command = (f"cat {tslog}")
tr.Streams.stdout = "gold/slice_crr_ident.gold"
tr.Processes.Default.ReturnCode = 0