Skip to content

Commit

Permalink
tests: update tests that used local_fs&mock_s3 to use one or the other (
Browse files Browse the repository at this point in the history
#6015)

## Problem

This was wasting resources: if we run a test with mock s3 we don't then
need to run it again with local fs. When we're running in CI, we don't
need to run with the mock/local storage as well as real S3. There is
some value in having CI notice/spot issues that might otherwise only
happen when running locally, but that doesn't justify the cost of
running the tests so many more times on every PR.

## Summary of changes

- For tests that used available_remote_storages or
available_s3_storages, update them to either specify no remote storage
(therefore inherit the default, which is currently local fs), or to
specify s3_storage() for the tests that actually want an S3 API.
  • Loading branch information
jcsp authored Dec 8, 2023
1 parent 699049b commit 5e98855
Show file tree
Hide file tree
Showing 10 changed files with 142 additions and 239 deletions.
3 changes: 2 additions & 1 deletion test_runner/fixtures/neon_fixtures.py
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,7 @@
RemoteStorageKind,
RemoteStorageUser,
S3Storage,
default_remote_storage,
remote_storage_to_toml_inline_table,
)
from fixtures.types import Lsn, TenantId, TimelineId
Expand Down Expand Up @@ -468,7 +469,7 @@ def init_configs(self, default_remote_storage_if_missing: bool = True) -> NeonEn
# Cannot create more than one environment from one builder
assert self.env is None, "environment already initialized"
if default_remote_storage_if_missing and self.pageserver_remote_storage is None:
self.enable_pageserver_remote_storage(RemoteStorageKind.LOCAL_FS)
self.enable_pageserver_remote_storage(default_remote_storage())
self.env = NeonEnv(self)
return self.env

Expand Down
7 changes: 7 additions & 0 deletions test_runner/fixtures/remote_storage.py
Original file line number Diff line number Diff line change
Expand Up @@ -372,6 +372,13 @@ def s3_storage() -> RemoteStorageKind:
return RemoteStorageKind.MOCK_S3


def default_remote_storage() -> RemoteStorageKind:
"""
The remote storage kind used in tests that do not specify a preference
"""
return RemoteStorageKind.LOCAL_FS


# serialize as toml inline table
def remote_storage_to_toml_inline_table(remote_storage: RemoteStorage) -> str:
if not isinstance(remote_storage, (LocalFsStorage, S3Storage)):
Expand Down
22 changes: 4 additions & 18 deletions test_runner/regress/test_ondemand_download.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,6 @@
from collections import defaultdict
from typing import Any, DefaultDict, Dict, Tuple

import pytest
from fixtures.log_helper import log
from fixtures.neon_fixtures import (
NeonEnvBuilder,
Expand All @@ -19,7 +18,7 @@
wait_for_upload,
wait_for_upload_queue_empty,
)
from fixtures.remote_storage import RemoteStorageKind, available_remote_storages
from fixtures.remote_storage import RemoteStorageKind
from fixtures.types import Lsn
from fixtures.utils import query_scalar, wait_until

Expand All @@ -45,13 +44,7 @@ def get_num_downloaded_layers(client: PageserverHttpClient):
# If you have a large relation, check that the pageserver downloads parts of it as
# require by queries.
#
@pytest.mark.parametrize("remote_storage_kind", available_remote_storages())
def test_ondemand_download_large_rel(
neon_env_builder: NeonEnvBuilder,
remote_storage_kind: RemoteStorageKind,
):
neon_env_builder.enable_pageserver_remote_storage(remote_storage_kind)

def test_ondemand_download_large_rel(neon_env_builder: NeonEnvBuilder):
# thinking about using a shared environment? the test assumes that global
# metrics are for single tenant.
env = neon_env_builder.init_start(
Expand Down Expand Up @@ -145,13 +138,7 @@ def test_ondemand_download_large_rel(
# If you have a relation with a long history of updates, the pageserver downloads the layer
# files containing the history as needed by timetravel queries.
#
@pytest.mark.parametrize("remote_storage_kind", available_remote_storages())
def test_ondemand_download_timetravel(
neon_env_builder: NeonEnvBuilder,
remote_storage_kind: RemoteStorageKind,
):
neon_env_builder.enable_pageserver_remote_storage(remote_storage_kind)

def test_ondemand_download_timetravel(neon_env_builder: NeonEnvBuilder):
# thinking about using a shared environment? the test assumes that global
# metrics are for single tenant.

Expand Down Expand Up @@ -229,8 +216,7 @@ def get_resident_physical_size():
assert filled_current_physical == filled_size, "we don't yet do layer eviction"

# Wait until generated image layers are uploaded to S3
if remote_storage_kind is not None:
wait_for_upload_queue_empty(pageserver_http, env.initial_tenant, timeline_id)
wait_for_upload_queue_empty(pageserver_http, env.initial_tenant, timeline_id)

env.pageserver.stop()

Expand Down
155 changes: 70 additions & 85 deletions test_runner/regress/test_tenant_delete.py
Original file line number Diff line number Diff line change
Expand Up @@ -23,23 +23,18 @@
wait_until_tenant_active,
wait_until_tenant_state,
)
from fixtures.remote_storage import (
RemoteStorageKind,
available_remote_storages,
available_s3_storages,
)
from fixtures.remote_storage import RemoteStorageKind, available_s3_storages, s3_storage
from fixtures.types import TenantId
from fixtures.utils import run_pg_bench_small, wait_until


@pytest.mark.parametrize("remote_storage_kind", available_remote_storages())
def test_tenant_delete_smoke(
neon_env_builder: NeonEnvBuilder,
remote_storage_kind: RemoteStorageKind,
pg_bin: PgBin,
):
neon_env_builder.pageserver_config_override = "test_remote_failures=1"

remote_storage_kind = s3_storage()
neon_env_builder.enable_pageserver_remote_storage(remote_storage_kind)

env = neon_env_builder.init_start()
Expand Down Expand Up @@ -78,16 +73,15 @@ def test_tenant_delete_smoke(
run_pg_bench_small(pg_bin, endpoint.connstr())
wait_for_last_flush_lsn(env, endpoint, tenant=tenant_id, timeline=timeline_id)

if remote_storage_kind in available_s3_storages():
assert_prefix_not_empty(
neon_env_builder,
prefix="/".join(
(
"tenants",
str(tenant_id),
)
),
)
assert_prefix_not_empty(
neon_env_builder,
prefix="/".join(
(
"tenants",
str(tenant_id),
)
),
)

parent = timeline

Expand All @@ -100,16 +94,15 @@ def test_tenant_delete_smoke(
tenant_path = env.pageserver.tenant_dir(tenant_id)
assert not tenant_path.exists()

if remote_storage_kind in available_s3_storages():
assert_prefix_empty(
neon_env_builder,
prefix="/".join(
(
"tenants",
str(tenant_id),
)
),
)
assert_prefix_empty(
neon_env_builder,
prefix="/".join(
(
"tenants",
str(tenant_id),
)
),
)

# Deletion updates the tenant count: the one default tenant remains
assert ps_http.get_metric_value("pageserver_tenant_manager_slots") == 1
Expand Down Expand Up @@ -149,9 +142,7 @@ class Check(enum.Enum):
def combinations():
result = []

remotes = [RemoteStorageKind.MOCK_S3]
if os.getenv("ENABLE_REAL_S3_REMOTE_STORAGE"):
remotes.append(RemoteStorageKind.REAL_S3)
remotes = available_s3_storages()

for remote_storage_kind in remotes:
for delete_failpoint in FAILPOINTS:
Expand All @@ -165,8 +156,8 @@ def combinations():
return result


@pytest.mark.parametrize("remote_storage_kind, failpoint, simulate_failures", combinations())
@pytest.mark.parametrize("check", list(Check))
@pytest.mark.parametrize("remote_storage_kind, failpoint, simulate_failures", combinations())
def test_delete_tenant_exercise_crash_safety_failpoints(
neon_env_builder: NeonEnvBuilder,
remote_storage_kind: RemoteStorageKind,
Expand Down Expand Up @@ -214,16 +205,15 @@ def test_delete_tenant_exercise_crash_safety_failpoints(
run_pg_bench_small(pg_bin, endpoint.connstr())
last_flush_lsn_upload(env, endpoint, tenant_id, timeline_id)

if remote_storage_kind in available_s3_storages():
assert_prefix_not_empty(
neon_env_builder,
prefix="/".join(
(
"tenants",
str(tenant_id),
)
),
)
assert_prefix_not_empty(
neon_env_builder,
prefix="/".join(
(
"tenants",
str(tenant_id),
)
),
)

ps_http.configure_failpoints((failpoint, "return"))

Expand Down Expand Up @@ -276,25 +266,23 @@ def test_delete_tenant_exercise_crash_safety_failpoints(
assert not tenant_dir.exists()

# Check remote is empty
if remote_storage_kind in available_s3_storages():
assert_prefix_empty(
neon_env_builder,
prefix="/".join(
(
"tenants",
str(tenant_id),
)
),
allowed_postfix="initdb.tar.zst",
)
assert_prefix_empty(
neon_env_builder,
prefix="/".join(
(
"tenants",
str(tenant_id),
)
),
allowed_postfix="initdb.tar.zst",
)


@pytest.mark.parametrize("remote_storage_kind", available_remote_storages())
def test_tenant_delete_is_resumed_on_attach(
neon_env_builder: NeonEnvBuilder,
remote_storage_kind: RemoteStorageKind,
pg_bin: PgBin,
):
remote_storage_kind = s3_storage()
neon_env_builder.enable_pageserver_remote_storage(remote_storage_kind)

env = neon_env_builder.init_start(initial_tenant_conf=MANY_SMALL_LAYERS_TENANT_CONFIG)
Expand All @@ -314,16 +302,15 @@ def test_tenant_delete_is_resumed_on_attach(
wait_for_last_flush_lsn(env, endpoint, tenant=tenant_id, timeline=timeline_id)

# sanity check, data should be there
if remote_storage_kind in available_s3_storages():
assert_prefix_not_empty(
neon_env_builder,
prefix="/".join(
(
"tenants",
str(tenant_id),
)
),
)
assert_prefix_not_empty(
neon_env_builder,
prefix="/".join(
(
"tenants",
str(tenant_id),
)
),
)

# failpoint before we remove index_part from s3
failpoint = "timeline-delete-before-index-delete"
Expand Down Expand Up @@ -354,16 +341,15 @@ def test_tenant_delete_is_resumed_on_attach(
iterations=iterations,
)

if remote_storage_kind in available_s3_storages():
assert_prefix_not_empty(
neon_env_builder,
prefix="/".join(
(
"tenants",
str(tenant_id),
)
),
)
assert_prefix_not_empty(
neon_env_builder,
prefix="/".join(
(
"tenants",
str(tenant_id),
)
),
)

reason = tenant_info["state"]["data"]["reason"]
# failpoint may not be the only error in the stack
Expand All @@ -389,17 +375,16 @@ def test_tenant_delete_is_resumed_on_attach(
tenant_path = env.pageserver.tenant_dir(tenant_id)
assert not tenant_path.exists()

if remote_storage_kind in available_s3_storages():
ps_http.deletion_queue_flush(execute=True)
assert_prefix_empty(
neon_env_builder,
prefix="/".join(
(
"tenants",
str(tenant_id),
)
),
)
ps_http.deletion_queue_flush(execute=True)
assert_prefix_empty(
neon_env_builder,
prefix="/".join(
(
"tenants",
str(tenant_id),
)
),
)


def test_long_timeline_create_cancelled_by_tenant_delete(neon_env_builder: NeonEnvBuilder):
Expand Down
15 changes: 1 addition & 14 deletions test_runner/regress/test_tenant_detach.py
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,6 @@
)
from fixtures.remote_storage import (
RemoteStorageKind,
available_remote_storages,
)
from fixtures.types import Lsn, TenantId, TimelineId
from fixtures.utils import query_scalar, wait_until
Expand Down Expand Up @@ -59,16 +58,11 @@ class ReattachMode(str, enum.Enum):


# Basic detach and re-attach test
@pytest.mark.parametrize("remote_storage_kind", available_remote_storages())
@pytest.mark.parametrize(
"mode",
[ReattachMode.REATTACH_EXPLICIT, ReattachMode.REATTACH_RESET, ReattachMode.REATTACH_RESET_DROP],
)
def test_tenant_reattach(
neon_env_builder: NeonEnvBuilder, remote_storage_kind: RemoteStorageKind, mode: str
):
neon_env_builder.enable_pageserver_remote_storage(remote_storage_kind)

def test_tenant_reattach(neon_env_builder: NeonEnvBuilder, mode: str):
# Exercise retry code path by making all uploads and downloads fail for the
# first time. The retries print INFO-messages to the log; we will check
# that they are present after the test.
Expand Down Expand Up @@ -187,16 +181,13 @@ def test_tenant_reattach(
#
# I don't know what's causing that...
@pytest.mark.skip(reason="fixme")
@pytest.mark.parametrize("remote_storage_kind", available_remote_storages())
def test_tenant_reattach_while_busy(
neon_env_builder: NeonEnvBuilder,
remote_storage_kind: RemoteStorageKind,
):
updates_started = 0
updates_finished = 0
updates_to_perform = 0

neon_env_builder.enable_pageserver_remote_storage(remote_storage_kind)
env = neon_env_builder.init_start()

# Run random UPDATEs on test table. On failure, try again.
Expand Down Expand Up @@ -439,13 +430,9 @@ def test_tenant_detach_regular_tenant(neon_simple_env: NeonEnv):
should not be present in pageserver's memory"


@pytest.mark.parametrize("remote_storage_kind", available_remote_storages())
def test_detach_while_attaching(
neon_env_builder: NeonEnvBuilder,
remote_storage_kind: RemoteStorageKind,
):
neon_env_builder.enable_pageserver_remote_storage(remote_storage_kind)

##### First start, insert secret data and upload it to the remote storage
env = neon_env_builder.init_start()
pageserver_http = env.pageserver.http_client()
Expand Down
Loading

1 comment on commit 5e98855

@github-actions
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

No tests were run or test report is not available

Test coverage report is not available

The comment gets automatically updated with the latest test results
5e98855 at 2023-12-08T15:00:37.900Z :recycle:

Please sign in to comment.