Skip to content

Commit

Permalink
bug-1909870: Make system test cases independent of each other.
Browse files Browse the repository at this point in the history
  • Loading branch information
smarnach committed Sep 9, 2024
1 parent 692c34a commit 144b0ea
Show file tree
Hide file tree
Showing 4 changed files with 155 additions and 169 deletions.
1 change: 0 additions & 1 deletion systemtests/lib/fake_data.py
Original file line number Diff line number Diff line change
Expand Up @@ -114,7 +114,6 @@ def __init__(

self.file_name: Optional[str] = None
self.members: list[FakeSymFile] = []
self.uploaded = False

def create(self, tmp_dir: os.PathLike):
LOGGER.info(
Expand Down
24 changes: 9 additions & 15 deletions systemtests/tests/conftest.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@
import logging
import os
import tempfile
from typing import Generator
from typing import Callable, Generator

import pytest

Expand Down Expand Up @@ -143,21 +143,15 @@ def fake_data_bucket(pytestconfig: pytest.Config) -> FakeDataBucket:
return FakeDataBucket(bucket_name, public_url, credentials_path)


@pytest.fixture(scope="class")
def zip_archive(
request: pytest.FixtureRequest,
) -> Generator[FakeZipArchive, None, None]:
size, platform = request.param
sym_file_size = size // 2
zip = FakeZipArchive(size, sym_file_size, platform)
@pytest.fixture
def create_zip_archive() -> Generator[Callable[[int, str], FakeZipArchive], None, None]:
os.makedirs(TMP_DIR, exist_ok=True)
with tempfile.TemporaryDirectory(dir=TMP_DIR) as tmp_dir:
zip.create(tmp_dir)
yield zip

def _create_zip_archive(size: int, platform: str) -> FakeZipArchive:
sym_file_size = size // 2
zip = FakeZipArchive(size, sym_file_size, platform)
zip.create(tmp_dir)
return zip

@pytest.fixture(scope="class")
def zip_archive_url(
zip_archive: FakeZipArchive, fake_data_bucket: FakeDataBucket
) -> str:
return fake_data_bucket.upload_scratch(zip_archive.file_name)
yield _create_zip_archive
235 changes: 117 additions & 118 deletions systemtests/tests/test_direct_upload.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
# License, v. 2.0. If a copy of the MPL was not distributed with this
# file, You can obtain one at https://mozilla.org/MPL/2.0/.

from typing import Callable
from unittest.mock import ANY
from urllib.parse import unquote

Expand All @@ -14,129 +15,127 @@
# Mark all tests in this module as upload tests
pytestmark = pytest.mark.upload

small_archive_param = pytest.param((2**19, "windows"), id="small")
large_archive_param = pytest.param(
(2**30, "linux"), id="large", marks=pytest.mark.large_files
)

small_and_large_archives = pytest.mark.parametrize(
"zip_archive", [small_archive_param, large_archive_param], indirect=True
)
small_archive = pytest.mark.parametrize(
"zip_archive", [small_archive_param], indirect=True
)
# Upload sizes
SMALL = 2**16
LARGE = 2**30


class TestDirectUpload:
# Tests within a class scope are executed in definition order.

@small_and_large_archives
def test_upload(self, tecken_client: TeckenClient, zip_archive: FakeZipArchive):
response = tecken_client.upload(zip_archive.file_name)
assert response.status_code == 201
zip_archive.uploaded = True

@small_and_large_archives
def test_download(self, tecken_client: TeckenClient, zip_archive: FakeZipArchive):
if not zip_archive.uploaded:
pytest.skip("upload failed")

for sym_file in zip_archive.members:
response = tecken_client.download(sym_file.key())
assert response.status_code == 200
[redirect] = response.history
assert redirect.status_code == 302

@small_archive
def test_head_request(
self, tecken_client: TeckenClient, zip_archive: FakeZipArchive
):
if not zip_archive.uploaded:
pytest.skip("upload failed")

for sym_file in zip_archive.members:
response = tecken_client.download(sym_file.key(), method="HEAD")
assert response.status_code == 200
assert not response.history

@small_archive
@pytest.mark.nginx
def test_headers(self, tecken_client: TeckenClient, zip_archive: FakeZipArchive):
if not zip_archive.uploaded:
pytest.skip("upload failed")

# These are exclusively security headers added by nginx
expected_tecken_headers = {
"X-Content-Type-Options": "nosniff",
"X-Frame-Options": "DENY",
"Content-Security-Policy": ANY,
"Strict-Transport-Security": "max-age=31536000",
}
# These are headers sent by the storage backend (S3 or GCS)
expected_storage_headers = {
"Content-Encoding": "gzip",
"Content-Length": ANY,
}
response = tecken_client.download(zip_archive.members[0].key())
@pytest.mark.parametrize(
["size", "platform"],
[
pytest.param(SMALL, "windows", id="small"),
pytest.param(LARGE, "linux", id="large", marks=pytest.mark.large_files),
],
)
def test_upload_and_download(
size: int,
platform: str,
tecken_client: TeckenClient,
create_zip_archive: Callable[[int, str], FakeZipArchive],
):
zip_archive = create_zip_archive(size, platform)
response = tecken_client.upload(zip_archive.file_name)
assert response.status_code == 201

for sym_file in zip_archive.members:
response = tecken_client.download(sym_file.key())
assert response.status_code == 200
[redirect] = response.history
assert redirect.status_code == 302


def test_head_request(
tecken_client: TeckenClient,
create_zip_archive: Callable[[int, str], FakeZipArchive],
):
zip_archive = create_zip_archive(SMALL, "windows")
response = tecken_client.upload(zip_archive.file_name)
response.raise_for_status()

for sym_file in zip_archive.members:
response = tecken_client.download(sym_file.key(), method="HEAD")
assert response.status_code == 200
assert not response.history


@pytest.mark.nginx
def test_headers(
tecken_client: TeckenClient,
create_zip_archive: Callable[[int, str], FakeZipArchive],
):
zip_archive = create_zip_archive(SMALL, "windows")
response = tecken_client.upload(zip_archive.file_name)
response.raise_for_status()

# These are exclusively security headers added by nginx
expected_tecken_headers = {
"X-Content-Type-Options": "nosniff",
"X-Frame-Options": "DENY",
"Content-Security-Policy": ANY,
"Strict-Transport-Security": "max-age=31536000",
}
# These are headers sent by the storage backend (S3 or GCS)
expected_storage_headers = {
"Content-Encoding": "gzip",
"Content-Length": ANY,
}
response = tecken_client.download(zip_archive.members[0].key())
[redirect] = response.history

actual_tecken_headers = {
name: redirect.headers[name] for name in expected_tecken_headers
}
assert actual_tecken_headers == expected_tecken_headers

actual_storage_headers = {
name: response.headers[name] for name in expected_storage_headers
}
assert actual_storage_headers == expected_storage_headers


def test_code_info_lookup(
tecken_client: TeckenClient,
create_zip_archive: Callable[[int, str], FakeZipArchive],
):
zip_archive = create_zip_archive(SMALL, "windows")
response = tecken_client.upload(zip_archive.file_name)
response.raise_for_status()

for sym_file in zip_archive.members:
response = tecken_client.download(
sym_file.code_info_key(), allow_redirects=False
)
assert response.status_code == 302
redirect_key = unquote(response.headers["location"])[1:]
assert redirect_key == sym_file.key()


def test_try_upload_and_download(
tecken_client: TeckenClient,
create_zip_archive: Callable[[int, str], FakeZipArchive],
):
zip_archive = create_zip_archive(SMALL, "windows")
response = tecken_client.upload(zip_archive.file_name, try_storage=True)
assert response.status_code == 201

for sym_file in zip_archive.members:
# regular download should fail
key = sym_file.key()
response = tecken_client.download(key)
assert response.status_code == 404

# download using `?try` query parameter
response = tecken_client.download(key, try_storage=True)
assert response.status_code == 200
[redirect] = response.history
assert redirect.status_code == 302

actual_tecken_headers = {
name: redirect.headers[name] for name in expected_tecken_headers
}
assert actual_tecken_headers == expected_tecken_headers

actual_storage_headers = {
name: response.headers[name] for name in expected_storage_headers
}
assert actual_storage_headers == expected_storage_headers

@small_archive
def test_code_info_lookup(
self, tecken_client: TeckenClient, zip_archive: FakeZipArchive
):
if not zip_archive.uploaded:
pytest.skip("upload failed")

for sym_file in zip_archive.members:
response = tecken_client.download(
sym_file.code_info_key(), allow_redirects=False
)
assert response.status_code == 302
redirect_key = unquote(response.headers["location"])[1:]
assert redirect_key == sym_file.key()


class TestDirectTryUpload:
# Tests within a class scope are executed in definition order.

@small_archive
def test_upload(self, tecken_client: TeckenClient, zip_archive: FakeZipArchive):
response = tecken_client.upload(zip_archive.file_name, try_storage=True)
assert response.status_code == 201
zip_archive.uploaded = True

@small_archive
def test_download(self, tecken_client: TeckenClient, zip_archive: FakeZipArchive):
if not zip_archive.uploaded:
pytest.skip("upload failed")

for sym_file in zip_archive.members:
# regular download should fail
key = sym_file.key()
response = tecken_client.download(key)
assert response.status_code == 404

# download using `?try` query parameter
response = tecken_client.download(key, try_storage=True)
assert response.status_code == 200
[redirect] = response.history
assert redirect.status_code == 302

# download by prefixing the key with try/
response = tecken_client.download(f"try/{key}")
assert response.status_code == 200
[redirect] = response.history
assert redirect.status_code == 302
# download by prefixing the key with try/
response = tecken_client.download(f"try/{key}")
assert response.status_code == 200
[redirect] = response.history
assert redirect.status_code == 302


def test_no_token(tecken_client: TeckenClient):
Expand Down
64 changes: 29 additions & 35 deletions systemtests/tests/test_upload_by_download.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,53 +2,47 @@
# License, v. 2.0. If a copy of the MPL was not distributed with this
# file, You can obtain one at https://mozilla.org/MPL/2.0/.

from typing import Callable
import pytest

from systemtests.lib.fake_data import FakeZipArchive
from systemtests.lib.fake_data import FakeDataBucket, FakeZipArchive
from systemtests.lib.tecken_client import TeckenClient


# Mark all tests in this module as upload tests
pytestmark = pytest.mark.upload

small_archive_param = pytest.param((2**19, "windows"), id="small")
large_archive_param = pytest.param(
(3 * 2**30, "linux"), id="large", marks=pytest.mark.large_files
)

small_and_large_archives = pytest.mark.parametrize(
"zip_archive", [small_archive_param, large_archive_param], indirect=True
)
small_archive = pytest.mark.parametrize(
"zip_archive", [small_archive_param], indirect=True
)
# Upload sizes
SMALL = 2**16
LARGE = 2**30


@pytest.mark.parametrize(
["size", "platform"],
[
pytest.param(SMALL, "windows", id="small"),
pytest.param(LARGE, "linux", id="large", marks=pytest.mark.large_files),
],
)
@pytest.mark.write_bucket
class TestUploadByDownload:
# Tests within a class scope are executed in definition order.

@small_and_large_archives
def test_upload(
self,
tecken_client: TeckenClient,
zip_archive: FakeZipArchive,
zip_archive_url: str,
):
response = tecken_client.upload_by_download(zip_archive_url)
assert response.status_code == 201
zip_archive.uploaded = True

@small_and_large_archives
def test_download(self, tecken_client: TeckenClient, zip_archive: FakeZipArchive):
if not zip_archive.uploaded:
pytest.skip("upload failed")

for sym_file in zip_archive.members:
response = tecken_client.download(sym_file.key())
assert response.status_code == 200
[redirect] = response.history
assert redirect.status_code == 302
def test_upload_and_download(
size: int,
platform: str,
tecken_client: TeckenClient,
create_zip_archive: Callable[[int, str], FakeZipArchive],
fake_data_bucket: FakeDataBucket,
):
zip_archive = create_zip_archive(size, platform)
url = fake_data_bucket.upload_scratch(zip_archive.file_name)
response = tecken_client.upload_by_download(url)
assert response.status_code == 201

for sym_file in zip_archive.members:
response = tecken_client.download(sym_file.key())
assert response.status_code == 200
[redirect] = response.history
assert redirect.status_code == 302


def test_disallowed_domain(tecken_client: TeckenClient):
Expand Down

0 comments on commit 144b0ea

Please sign in to comment.