You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@trafficserver.apache.org by zw...@apache.org on 2019/11/06 00:43:40 UTC
[trafficserver] branch 9.0.x updated: Adding an autest for
traffic_dump.
This is an automated email from the ASF dual-hosted git repository.
zwoop pushed a commit to branch 9.0.x
in repository https://gitbox.apache.org/repos/asf/trafficserver.git
The following commit(s) were added to refs/heads/9.0.x by this push:
new 617c6f5 Adding an autest for traffic_dump.
617c6f5 is described below
commit 617c6f5a3587f3fb63f2fab1c11e909d9a487cf9
Author: bneradt <bn...@verizonmedia.com>
AuthorDate: Fri Nov 1 16:22:14 2019 +0000
Adding an autest for traffic_dump.
(cherry picked from commit 452d60ea7878b202e45b297083641ed3968fc3fb)
---
plugins/experimental/traffic_dump/traffic_dump.cc | 2 +-
tests/Pipfile | 1 +
.../pluginTest/traffic_dump/gold/200.gold | 12 +++
.../pluginTest/traffic_dump/traffic_dump.test.py | 112 +++++++++++++++++++++
.../pluginTest/traffic_dump/verify_replay.py | 96 ++++++++++++++++++
5 files changed, 222 insertions(+), 1 deletion(-)
diff --git a/plugins/experimental/traffic_dump/traffic_dump.cc b/plugins/experimental/traffic_dump/traffic_dump.cc
index dc73e16..464dd41 100644
--- a/plugins/experimental/traffic_dump/traffic_dump.cc
+++ b/plugins/experimental/traffic_dump/traffic_dump.cc
@@ -602,7 +602,7 @@ TSPluginInit(int argc, const char *argv[])
TSHttpHookAdd(TS_HTTP_SSN_START_HOOK, ssncont);
TSHttpHookAdd(TS_HTTP_SSN_CLOSE_HOOK, ssncont);
TSLifecycleHookAdd(TS_LIFECYCLE_MSG_HOOK, ssncont);
- TSDebug(PLUGIN_NAME, "Initialized with sample pool size %" PRId64 " bytes and disk limit %" PRId64 "bytes",
+ TSDebug(PLUGIN_NAME, "Initialized with sample pool size %" PRId64 " bytes and disk limit %" PRId64 " bytes",
sample_pool_size.load(), max_disk_usage.load());
}
diff --git a/tests/Pipfile b/tests/Pipfile
index f8a6bcc..aa4a6e8 100644
--- a/tests/Pipfile
+++ b/tests/Pipfile
@@ -31,6 +31,7 @@ requests = "*"
gunicorn = "*"
httpbin = "*"
microserver = ">=1.0.4"
+jsonschema = "*"
[requires]
python_version = "3"
diff --git a/tests/gold_tests/pluginTest/traffic_dump/gold/200.gold b/tests/gold_tests/pluginTest/traffic_dump/gold/200.gold
new file mode 100644
index 0000000..71aa5d5
--- /dev/null
+++ b/tests/gold_tests/pluginTest/traffic_dump/gold/200.gold
@@ -0,0 +1,12 @@
+``
+> GET /`` HTTP/1.1
+> Host: www.example.com``
+> User-Agent: curl/``
+> Accept: */*
+``
+< HTTP/1.1 200 OK
+< Content-Length: 0
+< Date: ``
+< Age: ``
+< Server: ATS/``
+``
diff --git a/tests/gold_tests/pluginTest/traffic_dump/traffic_dump.test.py b/tests/gold_tests/pluginTest/traffic_dump/traffic_dump.test.py
new file mode 100644
index 0000000..1b4be84
--- /dev/null
+++ b/tests/gold_tests/pluginTest/traffic_dump/traffic_dump.test.py
@@ -0,0 +1,112 @@
+"""
+Verify traffic_dump functionality.
+"""
+# 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 = '''
+Verify traffic_dump functionality.
+'''
+
+Test.SkipUnless(
+ Condition.PluginExists('traffic_dump.so'),
+)
+
+# Configure the origin server.
+server = Test.MakeOriginServer("server")
+
+request_header = {"headers": "GET / HTTP/1.1\r\nHost: www.example.com\r\nContent-Length: 0\r\n\r\n",
+ "timestamp": "1469733493.993", "body": ""}
+response_header = {"headers": "HTTP/1.1 200 OK\r\nConnection: close\r\nContent-Length: 0\r\n\r\n",
+ "timestamp": "1469733493.993", "body": ""}
+server.addResponse("sessionfile.log", request_header, response_header)
+
+# Define ATS and configure
+ts = Test.MakeATSProcess("ts")
+replay_dir = os.path.join(ts.RunDirectory, "ts", "log")
+ts.Disk.records_config.update({
+ 'proxy.config.diags.debug.enabled': 1,
+ 'proxy.config.diags.debug.tags': 'traffic_dump',
+})
+ts.Disk.remap_config.AddLine(
+ 'map / http://127.0.0.1:{0}'.format(server.Variables.Port)
+)
+# Configure traffic_dump.
+ts.Disk.plugin_config.AddLine(
+ 'traffic_dump.so --logdir {0} --sample 1 --limit 1000000000'.format(replay_dir)
+)
+
+# Set up trafficserver expectations.
+ts.Disk.diags_log.Content = Testers.ContainsExpression(
+ "loading plugin.*traffic_dump.so",
+ "Verify the traffic_dump plugin got loaded.")
+ts.Streams.stderr = Testers.ContainsExpression(
+ "Initialized with log directory: {0}".format(replay_dir),
+ "Verify traffic_dump initialized with the configured directory.")
+ts.Streams.stderr += Testers.ContainsExpression(
+ "Initialized with sample pool size 1 bytes and disk limit 1000000000 bytes",
+ "Verify traffic_dump initialized with the configured disk limit.")
+
+# Set up the json replay file expectations.
+replay_file_session_1 = os.path.join(replay_dir, "127", "0000000000000000")
+ts.Disk.File(replay_file_session_1, exists=True)
+replay_file_session_2 = os.path.join(replay_dir, "127", "0000000000000001")
+ts.Disk.File(replay_file_session_2, exists=True)
+
+# Execute the first transaction.
+tr = Test.AddTestRun("First transaction")
+
+tr.Processes.Default.StartBefore(server, ready=When.PortOpen(server.Variables.Port))
+tr.Processes.Default.StartBefore(Test.Processes.ts)
+tr.Processes.Default.Command = 'curl http://127.0.0.1:{0} -H\'Host: www.example.com\' --verbose'.format(
+ ts.Variables.port)
+tr.Processes.Default.ReturnCode = 0
+tr.Processes.Default.Streams.stderr = "gold/200.gold"
+tr.StillRunningAfter = server
+tr.StillRunningAfter = ts
+
+# Execute the second transaction.
+tr = Test.AddTestRun("Second transaction")
+tr.Processes.Default.Command = 'curl http://127.0.0.1:{0} -H\'Host: www.example.com\' --verbose'.format(
+ ts.Variables.port)
+tr.Processes.Default.ReturnCode = 0
+tr.Processes.Default.Streams.stderr = "gold/200.gold"
+tr.StillRunningAfter = server
+tr.StillRunningAfter = ts
+
+# Verify the properties of the replay file for the first transaction.
+tr = Test.AddTestRun("Verify the json content of the first session")
+verify_replay = "verify_replay.py"
+tr.Setup.CopyAs(verify_replay, Test.RunDirectory)
+tr.Processes.Default.Command = "python3 {0} {1} {2}".format(
+ verify_replay,
+ os.path.join(Test.Variables.AtsTestToolsDir, 'lib', 'replay_schema.json'),
+ replay_file_session_1)
+tr.Processes.Default.ReturnCode = 0
+tr.StillRunningAfter = server
+tr.StillRunningAfter = ts
+
+# Verify the properties of the replay file for the second transaction.
+tr = Test.AddTestRun("Verify the json content of the second session")
+tr.Setup.CopyAs(verify_replay, Test.RunDirectory)
+tr.Processes.Default.Command = "python3 {0} {1} {2}".format(
+ verify_replay,
+ os.path.join(Test.Variables.AtsTestToolsDir, 'lib', 'replay_schema.json'),
+ replay_file_session_2)
+tr.Processes.Default.ReturnCode = 0
+tr.StillRunningAfter = server
+tr.StillRunningAfter = ts
diff --git a/tests/gold_tests/pluginTest/traffic_dump/verify_replay.py b/tests/gold_tests/pluginTest/traffic_dump/verify_replay.py
new file mode 100644
index 0000000..5b5738a
--- /dev/null
+++ b/tests/gold_tests/pluginTest/traffic_dump/verify_replay.py
@@ -0,0 +1,96 @@
+"""
+Verify that a given JSON replay file fulfills basic expectations.
+"""
+# 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 argparse
+import json
+import jsonschema
+import sys
+
+
+def validate_json(schema_json, replay_json):
+ """
+ Validate the replay file against the provided schema.
+ """
+ try:
+ jsonschema.validate(instance=replay_json, schema=schema_json)
+ except jsonschema.ValidationError:
+ print("The replay file does not validate against the schema.")
+ return False
+ else:
+ return True
+
+
+def verify_there_was_a_transaction(replay_json):
+ """
+ Verify that the replay file has a sensible looking transaction.
+ """
+ try:
+ transactions = replay_json['sessions'][0]['transactions']
+ except KeyError:
+ print("The replay file did not have transactions in it.")
+ return False
+
+ if len(transactions) < 1:
+ print("There are no transactions in the replay file.")
+ return False
+ transaction = transactions[0]
+ if not ('client-request' in transaction and 'server-response' in transaction):
+ print("There was not request and response in the transaction of the replay file.")
+ return False
+
+ return True
+
+
+def parse_args():
+ parser = argparse.ArgumentParser()
+ parser.add_argument("schema_file",
+ type=argparse.FileType('r'),
+ help="The schema in which to interpret validate the replay file.")
+ parser.add_argument("replay_file",
+ type=argparse.FileType('r'),
+ help="The replay file to validate.")
+ return parser.parse_args()
+
+
+def main():
+ args = parse_args()
+
+ schema_json = json.load(args.schema_file)
+ replay_json = json.load(args.replay_file)
+
+ if not validate_json(schema_json, replay_json):
+ return 1
+
+ # Verifying that there is a transaction in the replay file may seem
+ # unnecessary since the replay file validated against the schema. But a JSON
+ # file that doesn't have conflicting entry names will pass the schema. For
+ # instance, this passes against our replay schema:
+ #
+ # {"name": "Bob", "languages": ["English", "French"]}
+ #
+ # Thus we do the following sanity check to make sure that the replay file
+ # appears to have some transaction in it.
+ if not verify_there_was_a_transaction(replay_json):
+ return 1
+
+ return 0
+
+
+if __name__ == '__main__':
+ sys.exit(main())