mirror of
https://github.com/pypiserver/pypiserver
synced 2024-12-20 13:55:49 +01:00
fmt: tests/test_app.py
This commit is contained in:
parent
9496be122f
commit
a52c0d6f4c
@ -2,6 +2,7 @@
|
||||
|
||||
# Builtin imports
|
||||
import logging
|
||||
import os
|
||||
|
||||
|
||||
try: # python 3
|
||||
@ -9,6 +10,7 @@ try: # python 3
|
||||
from html import unescape
|
||||
except ImportError:
|
||||
from HTMLParser import HTMLParser
|
||||
|
||||
unescape = HTMLParser().unescape
|
||||
|
||||
try:
|
||||
@ -40,6 +42,7 @@ def _app(app):
|
||||
@pytest.fixture
|
||||
def app(tmpdir):
|
||||
from pypiserver import app
|
||||
|
||||
return app(root=tmpdir.strpath, authenticated=[])
|
||||
|
||||
|
||||
@ -70,15 +73,17 @@ def testpriv(priv):
|
||||
@pytest.fixture
|
||||
def search_xml():
|
||||
"""Return an xml dom suitable for passing to search"""
|
||||
xml = '<xml><methodName>search</methodName><string>test</string></xml>'
|
||||
xml = "<xml><methodName>search</methodName><string>test</string></xml>"
|
||||
return xml
|
||||
|
||||
|
||||
@pytest.fixture(params=[
|
||||
" ", # Mustcontain test below fails when string is empty.
|
||||
"Hey there!",
|
||||
"<html><body>Hey there!</body></html>",
|
||||
])
|
||||
@pytest.fixture(
|
||||
params=[
|
||||
" ", # Mustcontain test below fails when string is empty.
|
||||
"Hey there!",
|
||||
"<html><body>Hey there!</body></html>",
|
||||
]
|
||||
)
|
||||
def welcome_file_no_vars(request, root):
|
||||
"""Welcome file fixture
|
||||
|
||||
@ -127,37 +132,45 @@ def test_root_hostname(testapp):
|
||||
|
||||
def test_root_welcome_msg_no_vars(root, welcome_file_no_vars):
|
||||
from pypiserver import app
|
||||
|
||||
app = app(root=root.strpath, welcome_file=welcome_file_no_vars.strpath)
|
||||
testapp = webtest.TestApp(app)
|
||||
resp = testapp.get("/")
|
||||
from pypiserver import __version__ as pver
|
||||
|
||||
resp.mustcontain(welcome_file_no_vars.read(), no=pver)
|
||||
|
||||
|
||||
def test_root_welcome_msg_all_vars(root, welcome_file_all_vars):
|
||||
from pypiserver import app
|
||||
|
||||
app = app(root=root.strpath, welcome_file=welcome_file_all_vars.strpath)
|
||||
testapp = webtest.TestApp(app)
|
||||
resp = testapp.get("/")
|
||||
|
||||
from pypiserver import __version__ as pver
|
||||
|
||||
resp.mustcontain(pver)
|
||||
|
||||
|
||||
def test_root_welcome_msg_antiXSS(testapp):
|
||||
"""https://github.com/pypiserver/pypiserver/issues/77"""
|
||||
resp = testapp.get(
|
||||
"/?<alert>Red</alert>", headers={"Host": "somehost.org"})
|
||||
resp = testapp.get("/?<alert>Red</alert>", headers={"Host": "somehost.org"})
|
||||
resp.mustcontain("alert", "somehost.org", no="<alert>")
|
||||
|
||||
|
||||
def test_root_remove_not_found_msg_antiXSS(testapp):
|
||||
"""https://github.com/pypiserver/pypiserver/issues/77"""
|
||||
resp = testapp.post("/", expect_errors=True,
|
||||
headers={"Host": "somehost.org"},
|
||||
params={':action': 'remove_pkg',
|
||||
'name': '<alert>Red</alert>',
|
||||
'version': '1.1.1'})
|
||||
resp = testapp.post(
|
||||
"/",
|
||||
expect_errors=True,
|
||||
headers={"Host": "somehost.org"},
|
||||
params={
|
||||
":action": "remove_pkg",
|
||||
"name": "<alert>Red</alert>",
|
||||
"version": "1.1.1",
|
||||
},
|
||||
)
|
||||
resp.mustcontain("alert", "somehost.org", no="<alert>")
|
||||
|
||||
|
||||
@ -165,7 +178,7 @@ def test_packages_redirect(testapp):
|
||||
resp = testapp.get("/packages")
|
||||
assert resp.status_code >= 300
|
||||
assert resp.status_code < 400
|
||||
assert resp.location.endswith('/packages/')
|
||||
assert resp.location.endswith("/packages/")
|
||||
|
||||
|
||||
def test_packages_empty(testapp):
|
||||
@ -203,7 +216,7 @@ def test_simple_redirect(testapp):
|
||||
resp = testapp.get("/simple")
|
||||
assert resp.status_code >= 300
|
||||
assert resp.status_code < 400
|
||||
assert resp.location.endswith('/simple/')
|
||||
assert resp.location.endswith("/simple/")
|
||||
|
||||
|
||||
def test_simple_list_no_dotfiles(root, testapp):
|
||||
@ -245,21 +258,24 @@ def test_simple_name_redirect(testapp):
|
||||
resp = testapp.get("/simple/foobar")
|
||||
assert resp.status_code >= 300
|
||||
assert resp.status_code < 400
|
||||
assert resp.location.endswith('/simple/foobar/')
|
||||
assert resp.location.endswith("/simple/foobar/")
|
||||
|
||||
|
||||
@pytest.mark.parametrize('package,normalized', [
|
||||
('FooBar', 'foobar'),
|
||||
('Foo.Bar', 'foo-bar'),
|
||||
('foo_bar', 'foo-bar'),
|
||||
('Foo-Bar', 'foo-bar'),
|
||||
('foo--_.bar', 'foo-bar'),
|
||||
])
|
||||
@pytest.mark.parametrize(
|
||||
"package,normalized",
|
||||
[
|
||||
("FooBar", "foobar"),
|
||||
("Foo.Bar", "foo-bar"),
|
||||
("foo_bar", "foo-bar"),
|
||||
("Foo-Bar", "foo-bar"),
|
||||
("foo--_.bar", "foo-bar"),
|
||||
],
|
||||
)
|
||||
def test_simple_normalized_name_redirect(testapp, package, normalized):
|
||||
resp = testapp.get("/simple/{0}/".format(package))
|
||||
assert resp.status_code >= 300
|
||||
assert resp.status_code < 400
|
||||
assert resp.location.endswith('/simple/{0}/'.format(normalized))
|
||||
assert resp.location.endswith("/simple/{0}/".format(normalized))
|
||||
|
||||
|
||||
def test_simple_index(root, testapp):
|
||||
@ -316,7 +332,9 @@ def test_nonroot_simple_index(root, testpriv):
|
||||
|
||||
def test_nonroot_simple_index_with_x_forwarded_host(root, testapp):
|
||||
root.join("foobar-1.0.zip").write("")
|
||||
resp = testapp.get("/simple/foobar/", headers={"X-Forwarded-Host": "forwarded.ed/priv/"})
|
||||
resp = testapp.get(
|
||||
"/simple/foobar/", headers={"X-Forwarded-Host": "forwarded.ed/priv/"}
|
||||
)
|
||||
links = resp.html("a")
|
||||
assert len(links) == 1
|
||||
assert links[0]["href"].startswith("/priv/packages/foobar-1.0.zip#")
|
||||
@ -332,7 +350,9 @@ def test_nonroot_simple_packages(root, testpriv):
|
||||
|
||||
def test_nonroot_simple_packages_with_x_forwarded_host(root, testapp):
|
||||
root.join("foobar-1.0.zip").write("123")
|
||||
resp = testapp.get("/packages/", headers={"X-Forwarded-Host": "forwarded/priv/"})
|
||||
resp = testapp.get(
|
||||
"/packages/", headers={"X-Forwarded-Host": "forwarded/priv/"}
|
||||
)
|
||||
links = resp.html("a")
|
||||
assert len(links) == 1
|
||||
assert links[0]["href"].startswith("/priv/packages/foobar-1.0.zip#")
|
||||
@ -342,8 +362,11 @@ def test_root_no_relative_paths(testpriv):
|
||||
"""https://github.com/pypiserver/pypiserver/issues/25"""
|
||||
resp = testpriv.get("/priv/")
|
||||
hrefs = [x["href"] for x in resp.html("a")]
|
||||
assert hrefs == ['/priv/packages/', '/priv/simple/',
|
||||
'https://pypi.org/project/pypiserver/']
|
||||
assert hrefs == [
|
||||
"/priv/packages/",
|
||||
"/priv/simple/",
|
||||
"https://pypi.org/project/pypiserver/",
|
||||
]
|
||||
|
||||
|
||||
def test_simple_index_list_no_duplicates(root, testapp):
|
||||
@ -391,103 +414,121 @@ def test_no_cache_control_set(root, _app, testapp):
|
||||
|
||||
def test_cache_control_set(root):
|
||||
from pypiserver import app
|
||||
|
||||
AGE = 86400
|
||||
app_with_cache = webtest.TestApp(app(root=root.strpath, cache_control=AGE))
|
||||
root.join("foo_bar-1.0.tar.gz").write("")
|
||||
resp = app_with_cache.get("/packages/foo_bar-1.0.tar.gz")
|
||||
assert "Cache-Control" in resp.headers
|
||||
assert resp.headers["Cache-Control"] == 'public, max-age=%s' % AGE
|
||||
assert resp.headers["Cache-Control"] == "public, max-age=%s" % AGE
|
||||
|
||||
|
||||
def test_upload_noAction(root, testapp):
|
||||
resp = testapp.post("/", expect_errors=1)
|
||||
assert resp.status == '400 Bad Request'
|
||||
assert resp.status == "400 Bad Request"
|
||||
assert "Missing ':action' field!" in unescape(resp.text)
|
||||
|
||||
|
||||
def test_upload_badAction(root, testapp):
|
||||
resp = testapp.post("/", params={':action': 'BAD'}, expect_errors=1)
|
||||
assert resp.status == '400 Bad Request'
|
||||
resp = testapp.post("/", params={":action": "BAD"}, expect_errors=1)
|
||||
assert resp.status == "400 Bad Request"
|
||||
assert "Unsupported ':action' field: BAD" in unescape(resp.text)
|
||||
|
||||
|
||||
@pytest.mark.parametrize("package", [f[0]
|
||||
for f in test_core.files
|
||||
if f[1] and '/' not in f[0]])
|
||||
@pytest.mark.parametrize(
|
||||
"package", [f[0] for f in test_core.files if f[1] and "/" not in f[0]]
|
||||
)
|
||||
def test_upload(package, root, testapp):
|
||||
resp = testapp.post("/", params={':action': 'file_upload'},
|
||||
upload_files=[('content', package, b'')])
|
||||
resp = testapp.post(
|
||||
"/",
|
||||
params={":action": "file_upload"},
|
||||
upload_files=[("content", package, b"")],
|
||||
)
|
||||
assert resp.status_int == 200
|
||||
uploaded_pkgs = [f.basename for f in root.listdir()]
|
||||
assert len(uploaded_pkgs) == 1
|
||||
assert uploaded_pkgs[0].lower() == package.lower()
|
||||
|
||||
|
||||
@pytest.mark.parametrize("package", [f[0]
|
||||
for f in test_core.files
|
||||
if f[1] and '/' not in f[0]])
|
||||
@pytest.mark.parametrize(
|
||||
"package", [f[0] for f in test_core.files if f[1] and "/" not in f[0]]
|
||||
)
|
||||
def test_upload_with_signature(package, root, testapp):
|
||||
resp = testapp.post("/", params={':action': 'file_upload'},
|
||||
upload_files=[
|
||||
('content', package, b''),
|
||||
('gpg_signature', '%s.asc' % package, b'')])
|
||||
resp = testapp.post(
|
||||
"/",
|
||||
params={":action": "file_upload"},
|
||||
upload_files=[
|
||||
("content", package, b""),
|
||||
("gpg_signature", "%s.asc" % package, b""),
|
||||
],
|
||||
)
|
||||
assert resp.status_int == 200
|
||||
uploaded_pkgs = [f.basename.lower() for f in root.listdir()]
|
||||
assert len(uploaded_pkgs) == 2
|
||||
assert package.lower() in uploaded_pkgs
|
||||
assert '%s.asc' % package.lower() in uploaded_pkgs
|
||||
assert "%s.asc" % package.lower() in uploaded_pkgs
|
||||
|
||||
|
||||
@pytest.mark.parametrize("package", [
|
||||
f[0] for f in test_core.files
|
||||
if f[1] is None])
|
||||
@pytest.mark.parametrize(
|
||||
"package", [f[0] for f in test_core.files if f[1] is None]
|
||||
)
|
||||
def test_upload_badFilename(package, root, testapp):
|
||||
resp = testapp.post("/", params={':action': 'file_upload'},
|
||||
upload_files=[('content', package, b'')],
|
||||
expect_errors=1)
|
||||
assert resp.status == '400 Bad Request'
|
||||
resp = testapp.post(
|
||||
"/",
|
||||
params={":action": "file_upload"},
|
||||
upload_files=[("content", package, b"")],
|
||||
expect_errors=1,
|
||||
)
|
||||
assert resp.status == "400 Bad Request"
|
||||
assert "Bad filename: %s" % package in resp.text
|
||||
|
||||
|
||||
@pytest.mark.parametrize(("name", "version"), [
|
||||
@pytest.mark.parametrize(
|
||||
("name", "version"),
|
||||
[
|
||||
(None, None),
|
||||
(None, ''),
|
||||
('', None),
|
||||
(None, '1'),
|
||||
('pkg', None),
|
||||
('', '1'),
|
||||
('pkg', ''),
|
||||
])
|
||||
(None, ""),
|
||||
("", None),
|
||||
(None, "1"),
|
||||
("pkg", None),
|
||||
("", "1"),
|
||||
("pkg", ""),
|
||||
],
|
||||
)
|
||||
def test_remove_pkg_missingNaveVersion(name, version, root, testapp):
|
||||
msg = "Missing 'name'/'version' fields: name=%s, version=%s"
|
||||
params = {':action': 'remove_pkg', 'name': name, 'version': version}
|
||||
params = {":action": "remove_pkg", "name": name, "version": version}
|
||||
params = dict((k, v) for k, v in params.items() if v is not None)
|
||||
resp = testapp.post("/", expect_errors=1, params=params)
|
||||
|
||||
assert resp.status == '400 Bad Request'
|
||||
assert resp.status == "400 Bad Request"
|
||||
assert msg % (name, version) in unescape(resp.text)
|
||||
|
||||
|
||||
def test_remove_pkg_notFound(root, testapp):
|
||||
resp = testapp.post("/", expect_errors=1,
|
||||
params={
|
||||
':action': 'remove_pkg',
|
||||
'name': 'foo',
|
||||
'version': '123',
|
||||
})
|
||||
assert resp.status == '404 Not Found'
|
||||
resp = testapp.post(
|
||||
"/",
|
||||
expect_errors=1,
|
||||
params={":action": "remove_pkg", "name": "foo", "version": "123"},
|
||||
)
|
||||
assert resp.status == "404 Not Found"
|
||||
assert "foo (123) not found" in unescape(resp.text)
|
||||
|
||||
|
||||
@pytest.mark.parametrize('pkgs,matches', [
|
||||
([], []),
|
||||
(['test-1.0.tar.gz'], [('test', '1.0')]),
|
||||
(['test-1.0.tar.gz', 'test-test-2.0.1.tar.gz'],
|
||||
[('test', '1.0'), ('test-test', '2.0.1')]),
|
||||
(['test-1.0.tar.gz', 'other-2.0.tar.gz'], [('test', '1.0')]),
|
||||
(['test-2.0-py2.py3-none-any.whl'], [('test', '2.0')]),
|
||||
(['other-2.0.tar.gz'], [])
|
||||
])
|
||||
@pytest.mark.parametrize(
|
||||
"pkgs,matches",
|
||||
[
|
||||
([], []),
|
||||
(["test-1.0.tar.gz"], [("test", "1.0")]),
|
||||
(
|
||||
["test-1.0.tar.gz", "test-test-2.0.1.tar.gz"],
|
||||
[("test", "1.0"), ("test-test", "2.0.1")],
|
||||
),
|
||||
(["test-1.0.tar.gz", "other-2.0.tar.gz"], [("test", "1.0")]),
|
||||
(["test-2.0-py2.py3-none-any.whl"], [("test", "2.0")]),
|
||||
(["other-2.0.tar.gz"], []),
|
||||
],
|
||||
)
|
||||
def test_search(root, testapp, search_xml, pkgs, matches):
|
||||
"""Test the search functionality at the RPC2 endpoint
|
||||
|
||||
@ -520,18 +561,18 @@ def test_search(root, testapp, search_xml, pkgs, matches):
|
||||
version) matches for the "test" query
|
||||
"""
|
||||
for pkg in pkgs:
|
||||
root.join(pkg).write('')
|
||||
resp = testapp.post('/RPC2', search_xml)
|
||||
root.join(pkg).write("")
|
||||
resp = testapp.post("/RPC2", search_xml)
|
||||
parsed = xmlrpclib.loads(resp.text)
|
||||
assert len(parsed) == 2 and parsed[1] == 'search'
|
||||
assert len(parsed) == 2 and parsed[1] == "search"
|
||||
if not matches:
|
||||
assert len(parsed[0]) == 1 and not parsed[0][0]
|
||||
else:
|
||||
assert len(parsed[0][0]) == len(matches) and parsed[0][0]
|
||||
for returned in parsed[0][0]:
|
||||
print(returned)
|
||||
assert returned['name'] in [match[0] for match in matches]
|
||||
assert returned['version'] in [match[1] for match in matches]
|
||||
assert returned["name"] in [match[0] for match in matches]
|
||||
assert returned["version"] in [match[1] for match in matches]
|
||||
|
||||
|
||||
@pytest.mark.xfail()
|
||||
|
Loading…
Reference in New Issue
Block a user