|
|
dbd702 |
From 8bba792da37142028f6b6e61137ec2988b5578ee Mon Sep 17 00:00:00 2001
|
|
|
dbd702 |
From: Pavla Kratochvilova <pkratoch@redhat.com>
|
|
|
dbd702 |
Date: Mon, 26 Apr 2021 09:42:15 +0200
|
|
|
dbd702 |
Subject: [PATCH] Replace python3-flask with http.server in python tests
|
|
|
dbd702 |
|
|
|
dbd702 |
---
|
|
|
dbd702 |
README.md | 1 -
|
|
|
dbd702 |
librepo.spec | 1 -
|
|
|
dbd702 |
tests/README.rst | 36 ++++++++++--------------------------
|
|
|
dbd702 |
tests/python/tests/base.py | 24 ++++--------------------
|
|
|
dbd702 |
tests/python/tests/servermock/server.py | 31 +++++++++----------------------
|
|
|
dbd702 |
tests/python/tests/servermock/yum_mock/yum_mock.py | 279 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++------------------------------------------------------------------------------------------------------------------------------------
|
|
|
dbd702 |
tests/python/tests/test_yum_package_downloading.py | 9 +++------
|
|
|
dbd702 |
tests/python/tests/test_yum_repo_downloading.py | 5 ++---
|
|
|
dbd702 |
8 files changed, 175 insertions(+), 211 deletions(-)
|
|
|
dbd702 |
|
|
|
dbd702 |
diff --git a/README.md b/README.md
|
|
|
dbd702 |
index ad6bc23..d9fb062 100644
|
|
|
dbd702 |
--- a/README.md
|
|
|
dbd702 |
+++ b/README.md
|
|
|
dbd702 |
@@ -19,7 +19,6 @@ Fedora/Ubuntu name
|
|
|
dbd702 |
* openssl (http://www.openssl.org/) - openssl-devel/libssl-dev
|
|
|
dbd702 |
* python (http://python.org/) - python3-devel/libpython3-dev
|
|
|
dbd702 |
* **Test requires:** pygpgme (https://pypi.python.org/pypi/pygpgme/0.1) - python3-pygpgme/python3-gpgme
|
|
|
dbd702 |
-* **Test requires:** python3-flask (http://flask.pocoo.org/) - python-flask/python-flask
|
|
|
dbd702 |
* **Test requires:** python3-pyxattr (https://github.com/xattr/xattr) - python3-pyxattr/python3-pyxattr
|
|
|
dbd702 |
|
|
|
dbd702 |
### Build from your checkout dir:
|
|
|
dbd702 |
diff --git a/librepo.spec b/librepo.spec
|
|
|
dbd702 |
index 6db1fc2..ed90a84 100644
|
|
|
dbd702 |
--- a/librepo.spec
|
|
|
dbd702 |
+++ b/librepo.spec
|
|
|
dbd702 |
@@ -51,7 +51,6 @@ Summary: Python 3 bindings for the librepo library
|
|
|
dbd702 |
%{?python_provide:%python_provide python3-%{name}}
|
|
|
dbd702 |
BuildRequires: python3-devel
|
|
|
dbd702 |
BuildRequires: python3-gpg
|
|
|
dbd702 |
-BuildRequires: python3-flask
|
|
|
dbd702 |
BuildRequires: python3-pyxattr
|
|
|
dbd702 |
BuildRequires: python3-requests
|
|
|
dbd702 |
BuildRequires: python3-sphinx
|
|
|
dbd702 |
diff --git a/tests/README.rst b/tests/README.rst
|
|
|
dbd702 |
index ea55c87..f7e6d03 100644
|
|
|
dbd702 |
--- a/tests/README.rst
|
|
|
dbd702 |
+++ b/tests/README.rst
|
|
|
dbd702 |
@@ -33,15 +33,13 @@ Files of C tests
|
|
|
dbd702 |
* Test suites
|
|
|
dbd702 |
|
|
|
dbd702 |
|
|
|
dbd702 |
-Python tests with Flask
|
|
|
dbd702 |
-=======================
|
|
|
dbd702 |
+Python tests http.server
|
|
|
dbd702 |
+========================
|
|
|
dbd702 |
|
|
|
dbd702 |
-Some python tests use **Flask** python framework (http://flask.pocoo.org/)
|
|
|
dbd702 |
+Some python tests use **http.server** python standard library
|
|
|
dbd702 |
to simulate web server. The server is started automatically during that tests.
|
|
|
dbd702 |
|
|
|
dbd702 |
-*TestCases with Flask inherit from TestCaseWithApp class.*
|
|
|
dbd702 |
-
|
|
|
dbd702 |
-The Flask is then set as the app to the test case by 'application' class attribute.
|
|
|
dbd702 |
+*TestCases with http.server inherit from TestCaseWithServer class.*
|
|
|
dbd702 |
|
|
|
dbd702 |
If you want to start server manually::
|
|
|
dbd702 |
|
|
|
dbd702 |
@@ -57,27 +55,13 @@ http://127.0.0.1:5000/yum/badgpg/static/01/repodata/repomd.xml.asc
|
|
|
dbd702 |
|
|
|
dbd702 |
etc..
|
|
|
dbd702 |
|
|
|
dbd702 |
-Modularity of tests with Flask
|
|
|
dbd702 |
-------------------------------
|
|
|
dbd702 |
-
|
|
|
dbd702 |
-Flask tests are intended to be modular.
|
|
|
dbd702 |
-
|
|
|
dbd702 |
-Modularity is provided by use of http://flask.pocoo.org/docs/blueprints/
|
|
|
dbd702 |
-Currently there is only one module (blueprint) for yum repo mocking
|
|
|
dbd702 |
-in servermock/yum_mock.
|
|
|
dbd702 |
-
|
|
|
dbd702 |
-Repos for test with Flask
|
|
|
dbd702 |
--------------------------
|
|
|
dbd702 |
-
|
|
|
dbd702 |
-Currently each module (blueprint) uses its own data (repositories,
|
|
|
dbd702 |
-packages, ..).
|
|
|
dbd702 |
+Repos for test with http.server
|
|
|
dbd702 |
+-------------------------------
|
|
|
dbd702 |
|
|
|
dbd702 |
-E.g. for yum mocking module: servermock/yum_mock/static/
|
|
|
dbd702 |
+All data (repositories, packages, ..) are in servermock/yum_mock/static/
|
|
|
dbd702 |
|
|
|
dbd702 |
-Configuration and globals for tests with Flask
|
|
|
dbd702 |
-----------------------------------------------
|
|
|
dbd702 |
+Configuration and globals for tests with http.server
|
|
|
dbd702 |
+----------------------------------------------------
|
|
|
dbd702 |
|
|
|
dbd702 |
-Each module (blueprint) has its own configuration and globals which uses
|
|
|
dbd702 |
-and provides to tests which use the module.
|
|
|
dbd702 |
+Configuration and globals used by these tests are in servermock/yum_mock/config.py
|
|
|
dbd702 |
|
|
|
dbd702 |
-E.g. for yum mocking module: servermock/yum_mock/config.py
|
|
|
dbd702 |
diff --git a/tests/python/tests/base.py b/tests/python/tests/base.py
|
|
|
dbd702 |
index 1d01c9d..ecabbb5 100644
|
|
|
dbd702 |
--- a/tests/python/tests/base.py
|
|
|
dbd702 |
+++ b/tests/python/tests/base.py
|
|
|
dbd702 |
@@ -5,7 +5,7 @@ import ctypes
|
|
|
dbd702 |
import os.path
|
|
|
dbd702 |
import requests
|
|
|
dbd702 |
from multiprocessing import Process, Value
|
|
|
dbd702 |
-from tests.servermock.server import app
|
|
|
dbd702 |
+from tests.servermock.server import start_server
|
|
|
dbd702 |
try:
|
|
|
dbd702 |
import unittest2 as unittest
|
|
|
dbd702 |
except ImportError:
|
|
|
dbd702 |
@@ -53,39 +53,23 @@ class TestCase(unittest.TestCase):
|
|
|
dbd702 |
pass
|
|
|
dbd702 |
|
|
|
dbd702 |
|
|
|
dbd702 |
-class TestCaseWithApp(TestCase):
|
|
|
dbd702 |
- application = NotImplemented
|
|
|
dbd702 |
-
|
|
|
dbd702 |
- @classmethod
|
|
|
dbd702 |
- def setUpClass(cls):
|
|
|
dbd702 |
- cls.server = Process(target=cls.application.run)
|
|
|
dbd702 |
- cls.server.start()
|
|
|
dbd702 |
- time.sleep(0.5)
|
|
|
dbd702 |
-
|
|
|
dbd702 |
- @classmethod
|
|
|
dbd702 |
- def tearDownClass(cls):
|
|
|
dbd702 |
- cls.server.terminate()
|
|
|
dbd702 |
- cls.server.join()
|
|
|
dbd702 |
-
|
|
|
dbd702 |
-
|
|
|
dbd702 |
def application(port):
|
|
|
dbd702 |
"""Sometimes, the port is used, in that case, use different port"""
|
|
|
dbd702 |
|
|
|
dbd702 |
while True:
|
|
|
dbd702 |
try:
|
|
|
dbd702 |
port_val = port.value
|
|
|
dbd702 |
- app._librepo_port = port_val # Store used port into Flask app
|
|
|
dbd702 |
- app.run(port=port_val)
|
|
|
dbd702 |
- except socket.error as e:
|
|
|
dbd702 |
+ start_server(port=port_val)
|
|
|
dbd702 |
+ except OSError as e:
|
|
|
dbd702 |
if e.errno == 98:
|
|
|
dbd702 |
# Address already in use
|
|
|
dbd702 |
port.value += 1
|
|
|
dbd702 |
continue
|
|
|
dbd702 |
raise
|
|
|
dbd702 |
break
|
|
|
dbd702 |
|
|
|
dbd702 |
|
|
|
dbd702 |
-class TestCaseWithFlask(TestCase):
|
|
|
dbd702 |
+class TestCaseWithServer(TestCase):
|
|
|
dbd702 |
_TS_PORT = Value(ctypes.c_int, 5000)
|
|
|
dbd702 |
MOCKURL = None
|
|
|
dbd702 |
PORT = -1
|
|
|
dbd702 |
diff --git a/tests/python/tests/servermock/server.py b/tests/python/tests/servermock/server.py
|
|
|
dbd702 |
index 6d17a0a..37ddb64 100644
|
|
|
dbd702 |
--- a/tests/python/tests/servermock/server.py
|
|
|
dbd702 |
+++ b/tests/python/tests/servermock/server.py
|
|
|
dbd702 |
@@ -1,42 +1,29 @@
|
|
|
dbd702 |
-from flask import Flask
|
|
|
dbd702 |
+from http.server import BaseHTTPRequestHandler, HTTPServer
|
|
|
dbd702 |
from optparse import OptionParser
|
|
|
dbd702 |
try:
|
|
|
dbd702 |
- from yum_mock.yum_mock import yum_mock
|
|
|
dbd702 |
+ from yum_mock.yum_mock import yum_mock_handler
|
|
|
dbd702 |
except (ValueError, ImportError):
|
|
|
dbd702 |
- from .yum_mock.yum_mock import yum_mock
|
|
|
dbd702 |
+ from .yum_mock.yum_mock import yum_mock_handler
|
|
|
dbd702 |
|
|
|
dbd702 |
-app = Flask(__name__)
|
|
|
dbd702 |
-#app.register_blueprint(working_repo)
|
|
|
dbd702 |
-app.register_blueprint(yum_mock, url_prefix='/yum')
|
|
|
dbd702 |
|
|
|
dbd702 |
+def start_server(port, host="127.0.0.1", handler=None):
|
|
|
dbd702 |
+ if handler is None:
|
|
|
dbd702 |
+ handler = yum_mock_handler(port)
|
|
|
dbd702 |
+ with HTTPServer((host, port), handler) as server:
|
|
|
dbd702 |
+ server.serve_forever()
|
|
|
dbd702 |
|
|
|
dbd702 |
if __name__ == '__main__':
|
|
|
dbd702 |
parser = OptionParser("%prog [options]")
|
|
|
dbd702 |
parser.add_option(
|
|
|
dbd702 |
- "-d", "--debug",
|
|
|
dbd702 |
- action="store_true",
|
|
|
dbd702 |
- )
|
|
|
dbd702 |
- parser.add_option(
|
|
|
dbd702 |
"-p", "--port",
|
|
|
dbd702 |
default=5000,
|
|
|
dbd702 |
type="int",
|
|
|
dbd702 |
)
|
|
|
dbd702 |
parser.add_option(
|
|
|
dbd702 |
"-n", "--host",
|
|
|
dbd702 |
default="127.0.0.1",
|
|
|
dbd702 |
)
|
|
|
dbd702 |
- parser.add_option(
|
|
|
dbd702 |
- "--passthrough_errors",
|
|
|
dbd702 |
- action="store_true",
|
|
|
dbd702 |
- )
|
|
|
dbd702 |
options, args = parser.parse_args()
|
|
|
dbd702 |
|
|
|
dbd702 |
- kwargs = {
|
|
|
dbd702 |
- "threaded": True,
|
|
|
dbd702 |
- "debug": options.debug,
|
|
|
dbd702 |
- "port": options.port,
|
|
|
dbd702 |
- "host": options.host,
|
|
|
dbd702 |
- "passthrough_errors": options.passthrough_errors,
|
|
|
dbd702 |
- }
|
|
|
dbd702 |
+ start_server(options.port, options.host)
|
|
|
dbd702 |
|
|
|
dbd702 |
- app.run(**kwargs)
|
|
|
dbd702 |
diff --git a/tests/python/tests/servermock/yum_mock/yum_mock.py b/tests/python/tests/servermock/yum_mock/yum_mock.py
|
|
|
dbd702 |
index 826f7c8..dd5bda6 100644
|
|
|
dbd702 |
--- a/tests/python/tests/servermock/yum_mock/yum_mock.py
|
|
|
dbd702 |
+++ b/tests/python/tests/servermock/yum_mock/yum_mock.py
|
|
|
dbd702 |
@@ -1,137 +1,152 @@
|
|
|
dbd702 |
+import base64
|
|
|
dbd702 |
+from http.server import BaseHTTPRequestHandler, HTTPServer
|
|
|
dbd702 |
import os
|
|
|
dbd702 |
-from flask import Blueprint, render_template, abort, send_file, request, Response
|
|
|
dbd702 |
-from flask import current_app
|
|
|
dbd702 |
-from functools import wraps
|
|
|
dbd702 |
+import sys
|
|
|
dbd702 |
|
|
|
dbd702 |
from .config import AUTH_USER, AUTH_PASS
|
|
|
dbd702 |
|
|
|
dbd702 |
-yum_mock = Blueprint('yum_mock', __name__,
|
|
|
dbd702 |
- template_folder='templates',
|
|
|
dbd702 |
- static_folder='static')
|
|
|
dbd702 |
-
|
|
|
dbd702 |
-@yum_mock.route('/static/mirrorlist/<path:path>')
|
|
|
dbd702 |
-def serve_mirrorlists_with_right_port(path):
|
|
|
dbd702 |
- try:
|
|
|
dbd702 |
- with yum_mock.open_resource('static/mirrorlist/'+path) as f:
|
|
|
dbd702 |
- data = f.read()
|
|
|
dbd702 |
- data = data.decode('utf-8')
|
|
|
dbd702 |
- data = data.replace(":{PORT_PLACEHOLDER}", ":%d" % current_app._librepo_port)
|
|
|
dbd702 |
- return data
|
|
|
dbd702 |
- except IOError:
|
|
|
dbd702 |
- # File probably doesn't exist or we can't read it
|
|
|
dbd702 |
- abort(404)
|
|
|
dbd702 |
-
|
|
|
dbd702 |
-@yum_mock.route('/static/metalink/<path:path>')
|
|
|
dbd702 |
-def serve_metalinks_with_right_port(path):
|
|
|
dbd702 |
- try:
|
|
|
dbd702 |
- with yum_mock.open_resource('static/metalink/'+path) as f:
|
|
|
dbd702 |
- data = f.read()
|
|
|
dbd702 |
- data = data.decode('utf-8')
|
|
|
dbd702 |
- data = data.replace(":{PORT_PLACEHOLDER}", ":%d" % current_app._librepo_port)
|
|
|
dbd702 |
- return data
|
|
|
dbd702 |
- except IOError:
|
|
|
dbd702 |
- # File probably doesn't exist or we can't read it
|
|
|
dbd702 |
- abort(404)
|
|
|
dbd702 |
-
|
|
|
dbd702 |
-@yum_mock.route('/harm_checksum/<keyword>/<path:path>')
|
|
|
dbd702 |
-def harm_checksum(keyword, path):
|
|
|
dbd702 |
- """Append two newlines to content of a file (from the static dir) with
|
|
|
dbd702 |
- specified keyword in the filename. If the filename doesn't contain
|
|
|
dbd702 |
- the keyword, content of the file is returnen unchanged."""
|
|
|
dbd702 |
-
|
|
|
dbd702 |
- if "static/" not in path:
|
|
|
dbd702 |
- # Support changing only files from static directory
|
|
|
dbd702 |
- abort(400)
|
|
|
dbd702 |
- path = path[path.find("static/"):]
|
|
|
dbd702 |
-
|
|
|
dbd702 |
- try:
|
|
|
dbd702 |
- with yum_mock.open_resource(path) as f:
|
|
|
dbd702 |
- data = f.read()
|
|
|
dbd702 |
- if keyword in os.path.basename(path):
|
|
|
dbd702 |
- return "%s\n\n" %data
|
|
|
dbd702 |
- return data
|
|
|
dbd702 |
- except IOError:
|
|
|
dbd702 |
- # File probably doesn't exist or we can't read it
|
|
|
dbd702 |
- abort(404)
|
|
|
dbd702 |
-
|
|
|
dbd702 |
-@yum_mock.route("/not_found/<keyword>/<path:path>")
|
|
|
dbd702 |
-def not_found(keyword, path):
|
|
|
dbd702 |
- """For each file containing keyword in the filename, http status
|
|
|
dbd702 |
- code 404 will be returned"""
|
|
|
dbd702 |
-
|
|
|
dbd702 |
- if "static/" not in path:
|
|
|
dbd702 |
- abort(400)
|
|
|
dbd702 |
- path = path[path.find("static/"):]
|
|
|
dbd702 |
-
|
|
|
dbd702 |
- try:
|
|
|
dbd702 |
- with yum_mock.open_resource(path) as f:
|
|
|
dbd702 |
- data = f.read()
|
|
|
dbd702 |
- if keyword in os.path.basename(path):
|
|
|
dbd702 |
- abort(404)
|
|
|
dbd702 |
- return data
|
|
|
dbd702 |
- except IOError:
|
|
|
dbd702 |
- # File probably doesn't exist or we can't read it
|
|
|
dbd702 |
- abort(404)
|
|
|
dbd702 |
-
|
|
|
dbd702 |
-@yum_mock.route("/badurl/<path:path>")
|
|
|
dbd702 |
-def badurl(path):
|
|
|
dbd702 |
- """Just return 404 for each url with this prefix"""
|
|
|
dbd702 |
- abort(404)
|
|
|
dbd702 |
-
|
|
|
dbd702 |
-@yum_mock.route("/badgpg/<path:path>")
|
|
|
dbd702 |
-def badgpg(path):
|
|
|
dbd702 |
- """Instead of <path>/repomd.xml.asc returns
|
|
|
dbd702 |
- content of <path>/repomd.xml.asc.bad"""
|
|
|
dbd702 |
- if "static/" not in path:
|
|
|
dbd702 |
- abort(400)
|
|
|
dbd702 |
- path = path[path.find("static/"):]
|
|
|
dbd702 |
- if path.endswith("repomd.xml.asc"):
|
|
|
dbd702 |
- path = path + ".bad"
|
|
|
dbd702 |
-
|
|
|
dbd702 |
- try:
|
|
|
dbd702 |
- with yum_mock.open_resource(path) as f:
|
|
|
dbd702 |
- return f.read()
|
|
|
dbd702 |
- except IOError:
|
|
|
dbd702 |
- # File probably doesn't exist or we can't read it
|
|
|
dbd702 |
- abort(404)
|
|
|
dbd702 |
-
|
|
|
dbd702 |
-# Basic Auth
|
|
|
dbd702 |
-
|
|
|
dbd702 |
-def check_auth(username, password):
|
|
|
dbd702 |
- """This function is called to check if a username /
|
|
|
dbd702 |
- password combination is valid.
|
|
|
dbd702 |
- """
|
|
|
dbd702 |
- return username == AUTH_USER and password == AUTH_PASS
|
|
|
dbd702 |
-
|
|
|
dbd702 |
-def authenticate():
|
|
|
dbd702 |
- """Sends a 401 response that enables basic auth"""
|
|
|
dbd702 |
- return Response(
|
|
|
dbd702 |
- 'Could not verify your access level for that URL.\n'
|
|
|
dbd702 |
- 'You have to login with proper credentials', 401,
|
|
|
dbd702 |
- {'WWW-Authenticate': 'Basic realm="Login Required"'})
|
|
|
dbd702 |
-
|
|
|
dbd702 |
-def requires_auth(f):
|
|
|
dbd702 |
- @wraps(f)
|
|
|
dbd702 |
- def decorated(*args, **kwargs):
|
|
|
dbd702 |
- auth = request.authorization
|
|
|
dbd702 |
- if not auth or not check_auth(auth.username, auth.password):
|
|
|
dbd702 |
- return authenticate()
|
|
|
dbd702 |
- return f(*args, **kwargs)
|
|
|
dbd702 |
- return decorated
|
|
|
dbd702 |
-
|
|
|
dbd702 |
-@yum_mock.route("/auth_basic/<path:path>")
|
|
|
dbd702 |
-@requires_auth
|
|
|
dbd702 |
-def secret_repo_basic_auth(path):
|
|
|
dbd702 |
- """Page secured with basic HTTP auth
|
|
|
dbd702 |
- User: admin Password: secret"""
|
|
|
dbd702 |
- if "static/" not in path:
|
|
|
dbd702 |
- abort(400)
|
|
|
dbd702 |
- path = path[path.find("static/"):]
|
|
|
dbd702 |
-
|
|
|
dbd702 |
- try:
|
|
|
dbd702 |
- with yum_mock.open_resource(path) as f:
|
|
|
dbd702 |
- data = f.read()
|
|
|
dbd702 |
- return data
|
|
|
dbd702 |
- except IOError:
|
|
|
dbd702 |
- abort(404)
|
|
|
dbd702 |
+
|
|
|
dbd702 |
+def file_path(path):
|
|
|
dbd702 |
+ return(os.path.join(os.path.dirname(os.path.abspath(__file__)), path))
|
|
|
dbd702 |
+
|
|
|
dbd702 |
+
|
|
|
dbd702 |
+def yum_mock_handler(port):
|
|
|
dbd702 |
+
|
|
|
dbd702 |
+ class YumMockHandler(BaseHTTPRequestHandler):
|
|
|
dbd702 |
+ _port = port
|
|
|
dbd702 |
+
|
|
|
dbd702 |
+ def return_bad_request(self):
|
|
|
dbd702 |
+ self.send_response(400)
|
|
|
dbd702 |
+ self.end_headers()
|
|
|
dbd702 |
+
|
|
|
dbd702 |
+ def return_not_found(self):
|
|
|
dbd702 |
+ self.send_response(404)
|
|
|
dbd702 |
+ self.end_headers()
|
|
|
dbd702 |
+
|
|
|
dbd702 |
+ def return_ok_with_message(self, message, content_type='text/html'):
|
|
|
dbd702 |
+ if content_type == 'text/html':
|
|
|
dbd702 |
+ message = bytes(message, 'utf8')
|
|
|
dbd702 |
+ self.send_response(200)
|
|
|
dbd702 |
+ self.send_header('Content-type', content_type)
|
|
|
dbd702 |
+ self.send_header('Content-Length', str(len(message)))
|
|
|
dbd702 |
+ self.end_headers()
|
|
|
dbd702 |
+ self.wfile.write(message)
|
|
|
dbd702 |
+
|
|
|
dbd702 |
+ def parse_path(self, test_prefix='', keyword_expected=False):
|
|
|
dbd702 |
+ path = self.path[len(test_prefix):]
|
|
|
dbd702 |
+ if keyword_expected:
|
|
|
dbd702 |
+ keyword, path = path.split('/', 1)
|
|
|
dbd702 |
+ # Strip arguments
|
|
|
dbd702 |
+ if '?' in path:
|
|
|
dbd702 |
+ path = path[:path.find('?')]
|
|
|
dbd702 |
+ if keyword_expected:
|
|
|
dbd702 |
+ return keyword, path
|
|
|
dbd702 |
+ return path
|
|
|
dbd702 |
+
|
|
|
dbd702 |
+ def serve_file(self, path, harm_keyword=None):
|
|
|
dbd702 |
+ if "static/" not in path:
|
|
|
dbd702 |
+ # Support changing only files from static directory
|
|
|
dbd702 |
+ return self.return_bad_request()
|
|
|
dbd702 |
+ path = path[path.find("static/"):]
|
|
|
dbd702 |
+ try:
|
|
|
dbd702 |
+ with open(file_path(path), 'rb') as f:
|
|
|
dbd702 |
+ data = f.read()
|
|
|
dbd702 |
+ if harm_keyword is not None and harm_keyword in os.path.basename(file_path(path)):
|
|
|
dbd702 |
+ data += b"\n\n"
|
|
|
dbd702 |
+ return self.return_ok_with_message(data, 'application/octet-stream')
|
|
|
dbd702 |
+ except IOError:
|
|
|
dbd702 |
+ # File probably doesn't exist or we can't read it
|
|
|
dbd702 |
+ return self.return_not_found()
|
|
|
dbd702 |
+
|
|
|
dbd702 |
+ def authenticate(self):
|
|
|
dbd702 |
+ """Sends a 401 response that enables basic auth"""
|
|
|
dbd702 |
+ self.send_response(401)
|
|
|
dbd702 |
+ self.send_header('Content-type', 'text/html')
|
|
|
dbd702 |
+ self.send_header('WWW-Authenticate', 'Basic realm="Login Required')
|
|
|
dbd702 |
+ self.end_headers()
|
|
|
dbd702 |
+ message = (
|
|
|
dbd702 |
+ 'Could not verify your access level for that URL.\n'
|
|
|
dbd702 |
+ 'You have to login with proper credentials'
|
|
|
dbd702 |
+ )
|
|
|
dbd702 |
+ self.wfile.write(bytes(message, "utf8"))
|
|
|
dbd702 |
+
|
|
|
dbd702 |
+ def check_auth(self):
|
|
|
dbd702 |
+ if self.headers.get('Authorization') is None:
|
|
|
dbd702 |
+ return False
|
|
|
dbd702 |
+ expected_authorization = 'Basic {}'.format(
|
|
|
dbd702 |
+ base64.b64encode('{}:{}'.format(AUTH_USER, AUTH_PASS).encode()).decode()
|
|
|
dbd702 |
+ )
|
|
|
dbd702 |
+ if self.headers.get('Authorization') != expected_authorization:
|
|
|
dbd702 |
+ return False
|
|
|
dbd702 |
+ return True
|
|
|
dbd702 |
+
|
|
|
dbd702 |
+ def serve_mirrorlist_or_metalink_with_right_port(self):
|
|
|
dbd702 |
+ path = self.parse_path()
|
|
|
dbd702 |
+ if "static/" not in path:
|
|
|
dbd702 |
+ return self.return_bad_request()
|
|
|
dbd702 |
+ path = path[path.find("static/"):]
|
|
|
dbd702 |
+ try:
|
|
|
dbd702 |
+ with open(file_path(path), 'r') as f:
|
|
|
dbd702 |
+ data = f.read()
|
|
|
dbd702 |
+ data = data.replace(":{PORT_PLACEHOLDER}", ":%d" % self._port)
|
|
|
dbd702 |
+ return self.return_ok_with_message(data)
|
|
|
dbd702 |
+ except IOError:
|
|
|
dbd702 |
+ # File probably doesn't exist or we can't read it
|
|
|
dbd702 |
+ return self.return_not_found()
|
|
|
dbd702 |
+
|
|
|
dbd702 |
+ def serve_harm_checksum(self):
|
|
|
dbd702 |
+ """Append two newlines to content of a file (from the static dir) with
|
|
|
dbd702 |
+ specified keyword in the filename. If the filename doesn't contain
|
|
|
dbd702 |
+ the keyword, content of the file is returnen unchanged."""
|
|
|
dbd702 |
+ keyword, path = self.parse_path('/yum/harm_checksum/', keyword_expected=True)
|
|
|
dbd702 |
+ self.serve_file(path, harm_keyword=keyword)
|
|
|
dbd702 |
+
|
|
|
dbd702 |
+ def serve_not_found(self):
|
|
|
dbd702 |
+ """For each file containing keyword in the filename, http status
|
|
|
dbd702 |
+ code 404 will be returned"""
|
|
|
dbd702 |
+ keyword, path = self.parse_path('/yum/not_found/', keyword_expected=True)
|
|
|
dbd702 |
+ if keyword in os.path.basename(file_path(path)):
|
|
|
dbd702 |
+ return self.return_not_found()
|
|
|
dbd702 |
+ self.serve_file(path)
|
|
|
dbd702 |
+
|
|
|
dbd702 |
+ def serve_badurl(self):
|
|
|
dbd702 |
+ """Just return 404 for each url with this prefix"""
|
|
|
dbd702 |
+ return self.return_not_found()
|
|
|
dbd702 |
+
|
|
|
dbd702 |
+ def serve_badgpg(self):
|
|
|
dbd702 |
+ """Instead of <path>/repomd.xml.asc returns content of <path>/repomd.xml.asc.bad"""
|
|
|
dbd702 |
+ path = self.parse_path('/yum/badgpg/')
|
|
|
dbd702 |
+ if path.endswith("repomd.xml.asc"):
|
|
|
dbd702 |
+ path += ".bad"
|
|
|
dbd702 |
+ self.serve_file(path)
|
|
|
dbd702 |
+
|
|
|
dbd702 |
+ def serve_auth_basic(self):
|
|
|
dbd702 |
+ """Page secured with basic HTTP auth; User: admin Password: secret"""
|
|
|
dbd702 |
+ if not self.check_auth():
|
|
|
dbd702 |
+ return self.authenticate()
|
|
|
dbd702 |
+ path = self.parse_path('/yum/auth_basic/')
|
|
|
dbd702 |
+ self.serve_file(path)
|
|
|
dbd702 |
+
|
|
|
dbd702 |
+ def serve_static(self):
|
|
|
dbd702 |
+ path = self.parse_path()
|
|
|
dbd702 |
+ self.serve_file(path)
|
|
|
dbd702 |
+
|
|
|
dbd702 |
+ def do_GET(self):
|
|
|
dbd702 |
+ if self.path.startswith('/yum/static/mirrorlist/'):
|
|
|
dbd702 |
+ return self.serve_mirrorlist_or_metalink_with_right_port()
|
|
|
dbd702 |
+ if self.path.startswith('/yum/static/metalink/'):
|
|
|
dbd702 |
+ return self.serve_mirrorlist_or_metalink_with_right_port()
|
|
|
dbd702 |
+ if self.path.startswith('/yum/harm_checksum/'):
|
|
|
dbd702 |
+ return self.serve_harm_checksum()
|
|
|
dbd702 |
+ if self.path.startswith('/yum/not_found/'):
|
|
|
dbd702 |
+ return self.serve_not_found()
|
|
|
dbd702 |
+ if self.path.startswith('/badurl/'):
|
|
|
dbd702 |
+ return self.serve_badurl()
|
|
|
dbd702 |
+ if self.path.startswith('/yum/badgpg/'):
|
|
|
dbd702 |
+ return self.serve_badgpg()
|
|
|
dbd702 |
+ if self.path.startswith('/yum/auth_basic/'):
|
|
|
dbd702 |
+ return self.serve_auth_basic()
|
|
|
dbd702 |
+ return self.serve_static()
|
|
|
dbd702 |
+
|
|
|
dbd702 |
+ return YumMockHandler
|
|
|
dbd702 |
|
|
|
dbd702 |
diff --git a/tests/python/tests/test_yum_package_downloading.py b/tests/python/tests/test_yum_package_downloading.py
|
|
|
dbd702 |
index 577a8ce..0364be0 100644
|
|
|
dbd702 |
--- a/tests/python/tests/test_yum_package_downloading.py
|
|
|
dbd702 |
+++ b/tests/python/tests/test_yum_package_downloading.py
|
|
|
dbd702 |
@@ -9,11 +9,10 @@ import xattr
|
|
|
dbd702 |
|
|
|
dbd702 |
import tests.servermock.yum_mock.config as config
|
|
|
dbd702 |
|
|
|
dbd702 |
-from tests.base import TestCaseWithFlask
|
|
|
dbd702 |
-from tests.servermock.server import app
|
|
|
dbd702 |
+from tests.base import TestCaseWithServer
|
|
|
dbd702 |
|
|
|
dbd702 |
|
|
|
dbd702 |
-class TestCaseYumPackageDownloading(TestCaseWithFlask):
|
|
|
dbd702 |
+class TestCaseYumPackageDownloading(TestCaseWithServer):
|
|
|
dbd702 |
|
|
|
dbd702 |
def setUp(self):
|
|
|
dbd702 |
self.tmpdir = tempfile.mkdtemp(prefix="librepotest-", dir="./")
|
|
|
dbd702 |
@@ -163,9 +162,7 @@ class TestCaseYumPackageDownloading(TestCaseWithFlask):
|
|
|
dbd702 |
pkg = os.path.join(self.tmpdir, config.PACKAGE_01_01)
|
|
|
dbd702 |
self.assertTrue(os.path.isfile(pkg))
|
|
|
dbd702 |
|
|
|
dbd702 |
-class TestCaseYumPackagesDownloading(TestCaseWithFlask):
|
|
|
dbd702 |
- application = app
|
|
|
dbd702 |
-
|
|
|
dbd702 |
+class TestCaseYumPackagesDownloading(TestCaseWithServer):
|
|
|
dbd702 |
# @classmethod
|
|
|
dbd702 |
# def setUpClass(cls):
|
|
|
dbd702 |
# super(TestCaseYumPackageDownloading, cls).setUpClass()
|
|
|
dbd702 |
diff --git a/tests/python/tests/test_yum_repo_downloading.py b/tests/python/tests/test_yum_repo_downloading.py
|
|
|
dbd702 |
index 76b067c..4d56d1c 100644
|
|
|
dbd702 |
--- a/tests/python/tests/test_yum_repo_downloading.py
|
|
|
dbd702 |
+++ b/tests/python/tests/test_yum_repo_downloading.py
|
|
|
dbd702 |
@@ -7,13 +7,12 @@ import unittest
|
|
|
dbd702 |
|
|
|
dbd702 |
import librepo
|
|
|
dbd702 |
|
|
|
dbd702 |
-from tests.base import Context, TestCaseWithFlask, TEST_DATA
|
|
|
dbd702 |
-from tests.servermock.server import app
|
|
|
dbd702 |
+from tests.base import Context, TestCaseWithServer, TEST_DATA
|
|
|
dbd702 |
import tests.servermock.yum_mock.config as config
|
|
|
dbd702 |
|
|
|
dbd702 |
PUB_KEY = TEST_DATA+"/key.pub"
|
|
|
dbd702 |
|
|
|
dbd702 |
-class TestCaseYumRepoDownloading(TestCaseWithFlask):
|
|
|
dbd702 |
+class TestCaseYumRepoDownloading(TestCaseWithServer):
|
|
|
dbd702 |
|
|
|
dbd702 |
def setUp(self):
|
|
|
dbd702 |
self.tmpdir = tempfile.mkdtemp(prefix="librepotest-")
|
|
|
dbd702 |
--
|
|
|
dbd702 |
libgit2 1.0.1
|
|
|
dbd702 |
|