diff --git a/test/functional/checkupdate/chk-update-slow-server.bats b/test/functional/checkupdate/chk-update-slow-server.bats index a18a264e..d7ac168d 100755 --- a/test/functional/checkupdate/chk-update-slow-server.bats +++ b/test/functional/checkupdate/chk-update-slow-server.bats @@ -5,6 +5,7 @@ load "../testlib" global_setup() { create_test_environment "$TEST_NAME" + create_version "$TEST_NAME" 99990 10 staging # start slow response web server start_web_server -s @@ -28,11 +29,7 @@ global_teardown() { @test "check-update with a slow server" { - # Pre-req: create a web server that can serve as a slow content download server - slow_opts="-p $TEST_NAME/target-dir -F staging -u http://localhost:$PORT/" - - # test - run sudo sh -c "$SWUPD check-update $slow_opts" + run sudo sh -c "$SWUPD check-update $SWUPD_OPTS_HTTP_NO_CERT" assert_status_is 0 expected_output=$(cat <<-EOM Current OS version: 10 diff --git a/test/functional/server.py b/test/functional/server.py index 85be18fa..f33c2317 100755 --- a/test/functional/server.py +++ b/test/functional/server.py @@ -2,22 +2,57 @@ import argparse import http.server as server +import os import ssl import sys import time -class SlowResponse(server.BaseHTTPRequestHandler): - """Handler that returns data with a set delay between writes""" +partial_download_file = "" +slow_server = False + +class TestServer(server.BaseHTTPRequestHandler): + first_time = True + + """Handler that returns data with a set delay between writes and/or + simulates a partial download on the first download attempt for the + file specified by partial_download_file.""" def do_GET(self): - self.send_response(200) + try: + f = open(os.getcwd() + self.path, 'rb') + except: + self.send_response(404) + self.end_headers() + return + + #Simulate partial download + partial_download = False + split_paths = os.path.split(self.path) + + if split_paths[1] == partial_download_file and TestServer.first_time: + partial_download = True + TestServer.first_time = False + self.send_response(206) + else: + self.send_response(200) self.send_header("Content-type", "text/html") self.end_headers() - response = "99990" - delay = 0.00001 # seconds - for c in response: - self.wfile.write(str.encode(c)) + while True: + b = f.read(1) + if b == b'': + break + + self.wfile.write(b) + if partial_download: + break; + + # Insert delay for slow server + if slow_server: + delay = 0.00001 # seconds + time.sleep(delay) + self.wfile.flush() + f.close() if __name__ == '__main__': @@ -25,6 +60,11 @@ if __name__ == '__main__': parser.add_argument('--client_cert', help='client public key') + parser.add_argument('--partial_download_file', default="", + help='file name to download partially. On first download \ + fail with partial download error and succeed on 2nd \ + download.') + parser.add_argument('--port_file', help='File path to write port used by web server') @@ -40,9 +80,13 @@ if __name__ == '__main__': # host web server on localhost with available port addr = ('localhost', 0) - # server with delay or normal - if args.slow_server: - request_handler = SlowResponse + partial_download_file = args.partial_download_file + slow_server = args.slow_server + + # The TestServer is used when simulating a slow server and/or a + # partial file download. Otherwise use the simple HTTP server. + if slow_server or partial_download_file: + request_handler = TestServer else: request_handler = server.SimpleHTTPRequestHandler diff --git a/test/functional/testlib.bash b/test/functional/testlib.bash index fac4e86e..8c533b9a 100644 --- a/test/functional/testlib.bash +++ b/test/functional/testlib.bash @@ -280,6 +280,8 @@ set_env_variables() { # swupd_function PORT=$(cat "$PORT_FILE") export PORT export SWUPD_OPTS_HTTPS="-S $path/$env_name/state -p $path/$env_name/target-dir -F staging -u https://localhost:$PORT/$env_name/web-dir -C $FUNC_DIR/Swupd_Root.pem -I" + export SWUPD_OPTS_HTTP="-S $path/$env_name/state -p $path/$env_name/target-dir -F staging -u http://localhost:$PORT/$env_name/web-dir -C $FUNC_DIR/Swupd_Root.pem -I" + export SWUPD_OPTS_HTTP_NO_CERT="-S $path/$env_name/state -p $path/$env_name/target-dir -F staging -u http://localhost:$PORT/$env_name/web-dir/" fi if [ -f "$SERVER_PID_FILE" ]; then @@ -1398,13 +1400,12 @@ start_web_server() { # swupd_function cb_usage() { echo $(cat <<-EOF Usage: - start_web_server [-k] [-p] [-s] - - Options: - start_web_server [-c] [-p] [-k] [-s] + start_web_server [-c] [-d] [-k] [-p] [-s] Options: -c Path to public key to be used for client certificate authentication + -d File name that will be partially downloaded on the first attempt and successfully + downloaded on the second attempt. -k Path to server private key which must correspond to the provided server public key -p Path to server public key which enables SSL authentication -s Use a slow update server @@ -1424,9 +1425,10 @@ start_web_server() { # swupd_function ) } - while getopts :c:k:p:s opt; do + while getopts :c:d:k:p:s opt; do case "$opt" in c) server_args="$server_args --client_cert $OPTARG" ;; + d) server_args="$server_args --partial_download_file $OPTARG" ;; k) server_args="$server_args --server_key $OPTARG" ;; p) server_args="$server_args --server_cert $OPTARG" ;; s) server_args="$server_args --slow_server" ;; diff --git a/test/functional/update/update-slow-server.bats b/test/functional/update/update-slow-server.bats index 8dfa0ee9..305af92d 100755 --- a/test/functional/update/update-slow-server.bats +++ b/test/functional/update/update-slow-server.bats @@ -6,7 +6,7 @@ server_pid="" port="" THEME_DIRNAME="$FUNC_DIR/update" -test_setup() { +global_setup() { # Skip this test if not running in Travis CI, because test takes too long for # local development. To run this locally do: TRAVIS=true make check @@ -18,15 +18,22 @@ test_setup() { create_version -p "$TEST_NAME" 100 10 update_bundle "$TEST_NAME" test-bundle --update /foo/bar + start_web_server -d pack-test-bundle-from-10.tar -s +} + +test_setup() { + return } test_teardown() { + return +} + +global_teardown() { # teardown only if in travis CI if [ -n "${TRAVIS}" ]; then - print "terminating web server (PID: $server_pid)..." - kill "$server_pid" >&3 - print "server killed" + destroy_web_server destroy_test_environment "$TEST_NAME" fi @@ -34,12 +41,7 @@ test_teardown() { @test "update --download with a slow server" { - # Pre-req: create a web server that can serve as a slow content download server - print "starting web server..." - start_web_server - slow_opts="-u http://localhost:$port/" - - run sudo sh -c "$SWUPD update $slow_opts $SWUPD_OPTS" + run sudo sh -c "$SWUPD update $SWUPD_OPTS_HTTP" assert_status_is 0 expected_output=$(cat <<-EOM @@ -72,30 +74,3 @@ test_teardown() { assert_file_exists "$TARGETDIR"/foo/bar } - -start_web_server() { - - for i in {8081..8181}; do - "$THEME_DIRNAME"/update_slow_server.py $i & - sleep .5 - server_pid=$! - if [ -d /proc/$server_pid ]; then - port=$i - break - fi - done - - # wait until server becomes available by expecting a successful curl - for i in $(seq 1 10); do - flag=true - curl http://localhost:"$port"/ || flag=false - if [ "$flag" == false ]; then - sleep .5 - continue - else - print "server up" - break - fi - done - -} diff --git a/test/functional/update/update_slow_server.py b/test/functional/update/update_slow_server.py deleted file mode 100755 index a9c5579d..00000000 --- a/test/functional/update/update_slow_server.py +++ /dev/null @@ -1,47 +0,0 @@ -#!/usr/bin/env python3 - -import http.server as server -import sys -import time - -class SlowResponse(server.BaseHTTPRequestHandler): - first_time = True - - """Handler that returns data with a set delay between writes""" - def do_GET(self): - try: - f = open('update-slow-server/web-dir/' + self.path, 'rb') - except: - self.send_response(404) - self.end_headers() - return - - #Simulate partial download - partial_download = False - if self.path == "//100/pack-test-bundle-from-10.tar" and SlowResponse.first_time: - partial_download = True - SlowResponse.first_time = False - self.send_response(206) - else: - self.send_response(200) - self.send_header("Content-type", "text/html") - self.end_headers() - delay = 0.00001 # seconds - - while True: - b = f.read(100) - if b == b'': - break - - self.wfile.write(b) - if partial_download: - break; - time.sleep(delay) - self.wfile.flush() - f.close() - -if __name__ == '__main__': - print(sys.argv) - addr = ('', int(sys.argv[1])) - httpd = server.HTTPServer(addr, SlowResponse) - httpd.serve_forever()