Skip to content

Commit

Permalink
Add test for detecting S3 http2 upgrade request (#5911)
Browse files Browse the repository at this point in the history
* Add test for detecting S3 http2 upgrade request

* Enhance testing

* Copyright year update
  • Loading branch information
kthui authored Jun 8, 2023
1 parent 771c237 commit b2eab2f
Show file tree
Hide file tree
Showing 2 changed files with 134 additions and 4 deletions.
107 changes: 107 additions & 0 deletions qa/L0_storage_S3_local/mock_s3_service.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,107 @@
# Copyright 2023, NVIDIA CORPORATION & AFFILIATES. All rights reserved.
#
# Redistribution and use in source and binary forms, with or without
# modification, are permitted provided that the following conditions
# are met:
# * Redistributions of source code must retain the above copyright
# notice, this list of conditions and the following disclaimer.
# * Redistributions in binary form must reproduce the above copyright
# notice, this list of conditions and the following disclaimer in the
# documentation and/or other materials provided with the distribution.
# * Neither the name of NVIDIA CORPORATION nor the names of its
# contributors may be used to endorse or promote products derived
# from this software without specific prior written permission.
#
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ``AS IS'' AND ANY
# EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
# PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
# CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
# EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
# PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
# PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
# OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

import time
import threading
from http.server import HTTPServer, BaseHTTPRequestHandler


class MockS3Service():

__address = "localhost"
__port = 8080

def __init__(self):
# Test passed when:
# - at least one HEAD request is received; and
# - at least one GET request is received; and
# - all received requests do not advertise for HTTP/2.
test_results = {"head_count": 0, "get_count": 0, "http2_ads": False}

class RequestValidator(BaseHTTPRequestHandler):
protocol_version = "HTTP/1.1"

def __CheckHttp2Ads(self):
if "connection" in self.headers:
v = self.headers["connection"].lower()
if "upgrade" in v or "http2" in v:
test_results["http2_ads"] = True
if "upgrade" in self.headers and "h2c" in self.headers[
"upgrade"].lower():
test_results["http2_ads"] = True
if "http2-settings" in self.headers:
test_results["http2_ads"] = True

def do_HEAD(self):
self.__CheckHttp2Ads()
test_results["head_count"] += 1
self.send_response(200)
self.end_headers()

def do_GET(self):
self.__CheckHttp2Ads()
test_results["get_count"] += 1
self.send_error(404, "Thank you for using the mock s3 service!",
"Your bucket is not found here!")

self.__test_results = test_results
self.__server = HTTPServer((self.__address, self.__port),
RequestValidator)
self.__service_thread = threading.Thread(
target=self.__server.serve_forever)

def __enter__(self):
self.__service_thread.start()

def __exit__(self, exc_type, exc_val, exc_tb):
self.__server.shutdown()
self.__server.server_close()
self.__service_thread.join()

def TestPassed(self):
return self.__test_results["head_count"] > 0 and self.__test_results[
"get_count"] > 0 and not self.__test_results["http2_ads"]


if __name__ == "__main__":

# Initialize mock service
mock_s3_service = MockS3Service()

# Start service and poll until test passed or timed-out
with mock_s3_service:
poll_interval = 1 # seconds
timeout = 10 # seconds
elapsed_time = 0 # seconds
while not mock_s3_service.TestPassed() and elapsed_time < timeout:
elapsed_time += poll_interval
time.sleep(poll_interval)

# Print the result
if mock_s3_service.TestPassed():
print("TEST PASSED")
else:
print("TEST FAILED")
31 changes: 27 additions & 4 deletions qa/L0_storage_S3_local/test.sh
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
#!/bin/bash
# Copyright 2020-2022, NVIDIA CORPORATION & AFFILIATES. All rights reserved.
# Copyright 2020-2023, NVIDIA CORPORATION & AFFILIATES. All rights reserved.
#
# Redistribution and use in source and binary forms, with or without
# modification, are permitted provided that the following conditions
Expand Down Expand Up @@ -355,10 +355,33 @@ done
kill $MINIO_PID
wait $MINIO_PID

if [ $RET -eq 0 ]; then
echo -e "\n***\n*** Test Passed\n***"
# Test the S3 client will not advertise HTTP/2
TEST_LOG="./http2_advertise_test.log"
python3 mock_s3_service.py > $TEST_LOG 2>&1 &
sleep 2 # make sure the mock service has started
SERVER_LOG="./http2_advertise_test.server.log"
SERVER_ARGS="--model-repository=s3://localhost:8080/dummy-bucket --exit-timeout-secs=120"
run_server
if [ "$SERVER_PID" != "0" ]; then
echo -e "\n***\n*** Unexpected server start $SERVER\n***"
cat $SERVER_LOG
kill $SERVER_PID
wait $SERVER_PID
RET=1
else
echo -e "\n***\n*** Test Failed\n***"
sleep 2 # make sure the mock service has stopped
PASSED_MSG="TEST PASSED"
if ! grep "$PASSED_MSG" $TEST_LOG; then
echo -e "\n***\n*** S3 client HTTP/2 advertise test failed\n***"
cat $TEST_LOG
RET=1
fi
fi

# Print and return test result
if [ $RET -eq 0 ]; then
echo -e "\n***\n*** Test Passed\n***"
else
echo -e "\n***\n*** Test Failed\n***"
fi
exit $RET

0 comments on commit b2eab2f

Please sign in to comment.