Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Improve tests for BkRepoStorage, cover different name type for .save() #156

Merged
merged 2 commits into from
Mar 28, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -117,7 +117,7 @@ known-first-party = [
"bkpaas_auth",
"bkapi_client_core",
"bkapi_component",
"bk_storages",
"bkstorages",
"apigw_manager",
]

Expand Down
14 changes: 9 additions & 5 deletions sdks/bk-storages/pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -6,15 +6,19 @@ readme = "README.md"
authors = ["blueking <[email protected]>"]
license = "MIT"
classifiers = [
"Programming Language :: Python :: 3",
"License :: OSI Approved :: MIT License",
"Framework :: Django",
"Programming Language :: Python :: 3",
"License :: OSI Approved :: MIT License",
"Framework :: Django",
]

[project.urls]
Homepage = "https://github.com/TencentBlueKing/bkpaas-python-sdk/"
Repository = "https://github.com/TencentBlueKing/bkpaas-python-sdk/"

[build-system]
requires = ["poetry-core>=1.0.0"]
build-backend = "poetry.core.masonry.api"

[tool.poetry.dependencies]
python = ">=3.6.2,<3.11"
boto3 = ">=1.4.1"
Expand Down Expand Up @@ -44,7 +48,7 @@ types-six = "0.1.7"
types-toml = "0.1.3"
# isort
isort = "^5.9.2"
moto = {extras = ["s3"], version = "^3.1.3"}
moto = { extras = ["s3"], version = "^3.1.3" }

[tool.black]
line-length = 119
Expand All @@ -70,7 +74,7 @@ max-line-length = 119
max-complexity = 12
format = "pylint"
# ignore example
exclude = "*.pyc,.git,__pycache__,*/dist/*"
exclude = "*.pyc,.git,__pycache__,*/dist/*"

[tool.mypy]
ignore_missing_imports = true
Expand Down
5 changes: 0 additions & 5 deletions sdks/bk-storages/requirements-tests.txt

This file was deleted.

54 changes: 0 additions & 54 deletions sdks/bk-storages/setup.py

This file was deleted.

90 changes: 54 additions & 36 deletions sdks/bk-storages/tests/test_bkrepo.py
Original file line number Diff line number Diff line change
Expand Up @@ -22,66 +22,66 @@
from tests.utils import generate_random_string


@pytest.fixture
@pytest.fixture()
def username():
return generate_random_string()


@pytest.fixture
@pytest.fixture()
def password():
return generate_random_string()


@pytest.fixture
@pytest.fixture()
def endpoint():
return "http://dummy.com"
return "http://example.com"


@pytest.fixture
@pytest.fixture()
def session():
return requests.session()


@pytest.fixture()
def adapter(session):
adapter = requests_mock.Adapter()
session.mount('http://', adapter)
session.mount("http://", adapter)
return adapter


@pytest.fixture
def bk_repo_cli(session, username, password, endpoint):
bk_repo_cli = BKGenericRepoClient(
@pytest.fixture()
def bk_repo_client(session, username, password, endpoint):
bk_repo_client = BKGenericRepoClient(
bucket="dummy-bucket", username=username, password=password, project="dummy-project", endpoint_url=endpoint
)
with mock.patch.object(bk_repo_cli, "get_client", lambda: session):
yield bk_repo_cli
with mock.patch.object(bk_repo_client, "get_client", return_value=session):
yield bk_repo_client


@pytest.fixture
@pytest.fixture()
def make_dummy_file(adapter, endpoint):
def core(key, content):
def fake_upload(request):
g._responses[0]._params["body"] = io.BytesIO(request.text.read())
return True

g = adapter.register_uri(
'GET', urljoin(endpoint, f'/generic/dummy-project/dummy-bucket/{key}'), body=io.BytesIO(content)
"GET", urljoin(endpoint, f"/generic/dummy-project/dummy-bucket/{key}"), body=io.BytesIO(content)
)
adapter.register_uri(
'PUT',
urljoin(endpoint, f'/generic/dummy-project/dummy-bucket/{key}'),
"PUT",
urljoin(endpoint, f"/generic/dummy-project/dummy-bucket/{key}"),
json={"code": 0, "message": ""},
additional_matcher=fake_upload,
)

return core


@pytest.fixture
def bk_repo_storage(bk_repo_cli):
@pytest.fixture()
def bk_repo_storage(bk_repo_client):
storage = BKRepoStorage()
storage.client = bk_repo_cli
storage.client = bk_repo_client
return storage


Expand Down Expand Up @@ -115,7 +115,7 @@ def file(name):

class TestBKRepoStorage:
@pytest.mark.parametrize(
"mock_responses, expect_directories, expect_files",
("mock_responses", "expect_directories", "expect_files"),
[
(([folder("d-a"), folder("d-b"), file("f-a")],), ["d-a", "d-b"], ["f-a"]),
(
Expand All @@ -129,11 +129,11 @@ def test_list_dir(self, bk_repo_storage, adapter, endpoint, mock_responses, expe
path = "dummy-key"
for idx, records in enumerate(mock_responses):
adapter.register_uri(
'GET',
"GET",
urljoin(
endpoint,
f'/repository/api/node/page/dummy-project/dummy-bucket/'
f'{path}?pageSize=1000&PageNumber={idx + 1}&includeFolder=True',
f"/repository/api/node/page/dummy-project/dummy-bucket/"
f"{path}?pageSize=1000&PageNumber={idx + 1}&includeFolder=True",
),
json={"code": 0, "message": 0, "data": {"totalPages": len(mock_responses), "records": records}},
)
Expand All @@ -148,30 +148,48 @@ def test_save_without_name(self, bk_repo_storage, adapter, endpoint):
content = b"aaa"
fh = File(io.BytesIO(content))
adapter.register_uri(
"PUT", urljoin(endpoint, f'/generic/dummy-project/dummy-bucket/{filename}'), json={"code": 0}
"PUT", urljoin(endpoint, f"/generic/dummy-project/dummy-bucket/{filename}"), json={"code": 0}
)
assert bk_repo_storage.save(filename, fh)
assert adapter.called
assert adapter.last_request.headers["Content-Length"] == str(len(content))
assert fh.name == filename

def test_save_with_name(self, bk_repo_storage, adapter, endpoint):
key = "foo/bar"
filename = "baz.py"
content = b"aaa"
fh = File(io.BytesIO(content), name=filename)
adapter.register_uri("PUT", urljoin(endpoint, f'/generic/dummy-project/dummy-bucket/{key}'), json={"code": 0})
assert bk_repo_storage.save(key, fh)
assert adapter.called
assert adapter.last_request.headers["Content-Length"] == str(len(content))
assert fh.name == filename
@pytest.mark.parametrize(
("root_path", "name", "has_error", "expected_key"),
[
("", "foo/bar", False, "foo/bar"),
("", "/foo/bar", False, "foo/bar"),
("/foo-prefix", "/bar/baz", False, "foo-prefix/bar/baz"),
# Invalid paths
("/foo-prefix", "../../../bar", True, ""),
],
)
def test_save_with_name(self, root_path, name, has_error, expected_key, bk_repo_client, adapter, endpoint):
storage = BKRepoStorage(root_path=root_path)
storage.client = bk_repo_client

filename = "foobar.py"
content = b"import this"
fh = File(io.BytesIO(content), name="foobar.py")
adapter.register_uri(
"PUT", urljoin(endpoint, f"/generic/dummy-project/dummy-bucket/{expected_key}"), json={"code": 0}
)
if has_error:
with pytest.raises(ValueError, match="joined path"):
storage.save(name, fh)
else:
assert storage.save(name, fh)
assert adapter.called
assert adapter.last_request.headers["Content-Length"] == str(len(content))
assert fh.name == filename


@pytest.mark.parametrize(
"gmt, expected",
("gmt", "expected"),
[
('Fri, 03 Dec 2021 10:55:04 GMT', datetime.datetime(2021, 12, 3, 10, 55, 4)),
('Thu, 15 Aug 2019 03:02:38 GMT', datetime.datetime(2019, 8, 15, 3, 2, 38)),
("Fri, 03 Dec 2021 10:55:04 GMT", datetime.datetime(2021, 12, 3, 10, 55, 4)),
("Thu, 15 Aug 2019 03:02:38 GMT", datetime.datetime(2019, 8, 15, 3, 2, 38)),
],
)
def test_parse_gmt_datetime(gmt, expected):
Expand Down
28 changes: 10 additions & 18 deletions sdks/bk-storages/tox.ini
Original file line number Diff line number Diff line change
Expand Up @@ -4,27 +4,19 @@
# and then run "tox" from this directory.

[tox]
envlist = py{27,36}-django{18,111}
envlist = py{38}-django{111,22,32}
isolated_build = True
skip_missing_interpreters = True
requires =
tox-poetry-installer[poetry] == 0.10.3

[testenv]
# Required env vars:
# RGW_ENDPOINT_URL=http://s3.com/
# RGW_STORAGE_BUCKET_NAME=bucket_name
# RGW_ACCESS_KEY_ID=id
# RGW_SECRET_ACCESS_KEY=key
passenv =
RGW_ENDPOINT_URL
RGW_STORAGE_BUCKET_NAME
RGW_ACCESS_KEY_ID
RGW_SECRET_ACCESS_KEY
install_dev_deps = True
poetry_dep_groups =
dev
piglei marked this conversation as resolved.
Show resolved Hide resolved
deps =
pytest
pytest-django
requests
requests_mock

django18: django==1.8
django111: django==1.11
django111: Django>=1.11,<1.12
django22: Django>=2.2,<2.3
django32: Django>=3.2,<3.3
commands =
pytest -s --maxfail 1
Loading