| ''' |
| ''' |
| # 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 |