Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
22 commits
Select commit Hold shift + click to select a range
94e4a12
Update conftest.py for using in container PyTest
phracek Mar 23, 2026
b0364dd
Add test_container_basics.py testing suite
phracek Mar 23, 2026
2529553
Add testing suite test_container_configuration.py
phracek Mar 23, 2026
153f1a1
Add testing suite for extensions `test_container_extensions.py`
phracek Mar 23, 2026
ece2114
Add general tests to test_container_general.py
phracek Mar 23, 2026
cba70d4
Add logging test for PostgreSQL
phracek Mar 23, 2026
40a485f
Add password test suite
phracek Mar 23, 2026
df8b5a0
Add test suite for replication
phracek Mar 23, 2026
c2ce14c
Add test suite for SSL functionality
phracek Mar 23, 2026
43a29bf
Fix calling PyTest suite with proper Python interpreter
phracek Mar 23, 2026
9d77d7a
Add migration suite to PyTest test suite
phracek Mar 24, 2026
c1ebe3c
Do not support upgrades on Fedora
phracek Mar 30, 2026
e17ebf4
Upgrade path for PSQL 18 is not supported for RHEL8
phracek Mar 31, 2026
f8c8472
Add couple more text detection if server is really up.
phracek Apr 1, 2026
aa35f10
Fix upgrade tests to check if database is really ready.
phracek Apr 1, 2026
eba7a0f
Some fixes caught by @frenzymadness.
phracek Apr 7, 2026
adb526a
Rewrite get_upgrade_path to Pythonish code.
phracek Apr 13, 2026
082f740
Add removing tree in case tests failed / passed.
phracek Apr 13, 2026
fdc76b5
Fix condition
phracek Apr 22, 2026
f5c2d04
Typo in pytest definition
phracek Apr 22, 2026
57e09bc
Several python improvements.
phracek Apr 22, 2026
e0ad923
Fix several comments and one wrong import
phracek Apr 27, 2026
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
248 changes: 219 additions & 29 deletions test/conftest.py
Original file line number Diff line number Diff line change
@@ -1,10 +1,15 @@
import os
import re
import sys
import time

from pathlib import Path
from collections import namedtuple

from container_ci_suite.utils import check_variables
from container_ci_suite.container_lib import ContainerTestLib, DatabaseWrapper
from container_ci_suite.engines.podman_wrapper import PodmanCLIWrapper


if not check_variables():
sys.exit(1)
Expand All @@ -20,12 +25,39 @@
"TAG",
"TEST_APP",
"VERY_LONG_IDENTIFIER",
"PREVIOUS_VERSION",
"MIGRATION_PATHS",
"UPGRADE_PATH_DICT",
"SQL_CMDS",
"DB_TYPE",
],
)
VERSION = os.getenv("VERSION")
OS = os.getenv("TARGET").lower()
TEST_APP = TEST_DIR / "test-app"
VERY_LONG_IDENTIFIER = "very_long_identifier_" + "x" * 40
MIGRATION_PATHS = ["12", "13", "15", "16", "18"]
PREVIOUS_VERSION_DICT = {
"13": "12",
"15": "13",
"16": "15",
"18": "16",
}
SQL_CMDS = {
"select count(*) from information_schema.triggers;": "16",
"select count(*) from staff;": "2",
"select * from information_schema.tables;": "28",
}
RHEL9 = ["13", "15", "16", "18"]
RHEL10 = ["16", "18"]
UPGRADE_PATH_DICT = {
"rhel8": ["12", "13", "15", "16"],
"rhel9": RHEL9,
"c9s": RHEL9,
"rhel10": RHEL10,
"c10s": RHEL10,
"fedora": ["15", "16", "18"],
}
VARS = Vars(
OS=OS,
VERSION=VERSION,
Expand All @@ -34,40 +66,198 @@
TAG=OS.replace("rh", "-", 1),
TEST_APP=TEST_APP,
VERY_LONG_IDENTIFIER=VERY_LONG_IDENTIFIER,
PREVIOUS_VERSION=PREVIOUS_VERSION_DICT.get(VERSION),
MIGRATION_PATHS=MIGRATION_PATHS,
UPGRADE_PATH_DICT=UPGRADE_PATH_DICT,
SQL_CMDS=SQL_CMDS,
DB_TYPE="postgresql",
)


def get_previous_major_version():
version_dict = {
"13": "12",
"15": "13",
"16": "15",
}
return version_dict.get(VARS.VERSION)


def get_upgrade_path():
upgrade_path = {
"rhel8": "none 12 13 15 16 none",
"rhel9": "none 13 15 16 none",
"rhel10": "none 13 15 16 none",
"fedora": "none 12 13 14 15 16 none",
}
for version in upgrade_path.keys():
if version == VARS.VERSION:
break
prev = version
if prev == "none":
"""
Get the upgrade path of the PostgreSQL container.
Comment thread
phracek marked this conversation as resolved.
"""
upgrade_path = UPGRADE_PATH_DICT[VARS.OS]
if VARS.VERSION not in upgrade_path:
return None
return prev
current_index = upgrade_path.index(VARS.VERSION)
if current_index == 0:
return None
return upgrade_path[current_index - 1]


def get_image_id(version):
ns = {
"rhel8": f"registry.redhat.io/rhel8/postgresql-{version}",
"rhel9": f"registry.redhat.io/rhel9/postgresql-{version}",
"rhel10": f"registry.redhat.io/rhel10/postgresql-{version}",
"c9s": f"quay.io/sclorg/postgresql-{version}-c9s",
"c10s": f"quay.io/sclorg/postgresql-{version}-c10s",
}
return ns[VARS.OS]
"""
Get the image ID of the PostgreSQL container.
"""
if VARS.OS.startswith("rhel"):
return f"registry.redhat.io/{VARS.OS}/postgresql-{version}"
return f"quay.io/sclorg/postgresql-{version}-{VARS.OS}"


def check_db_output(
dw_api,
cip,
username,
password,
database,
):
"""
Check the database output if the data is inserted correctly
by running a SELECT statement.
"""
dw_api.run_sql_command(
container_ip=cip,
username=username,
password=password,
container_id=VARS.IMAGE_NAME,
database=database,
sql_cmd='-At -c "CREATE TABLE tbl (a integer, b integer);"',
)

dw_api.run_sql_command(
container_ip=cip,
username=username,
password=password,
container_id=VARS.IMAGE_NAME,
database=database,
sql_cmd=[
'-At -c "INSERT INTO tbl VALUES (1, 2);"',
'-At -c "INSERT INTO tbl VALUES (3, 4);"',
'-At -c "INSERT INTO tbl VALUES (5, 6);"',
],
)
output = dw_api.run_sql_command(
container_ip=cip,
username=username,
password=password,
container_id=VARS.IMAGE_NAME,
database=database,
sql_cmd='-At -c "SELECT * FROM tbl;"',
)
expected_db_output = [
"1|2",
"3|4",
"5|6",
]
for expected_row in expected_db_output:
assert re.search(expected_row, output), (
f"Row {expected_row} not found in {output}"
)


def create_and_wait_for_container(
db: ContainerTestLib,
cid_file_name: str,
container_args: list[str],
command: str,
) -> tuple[str, str]:
"""
Create a container and wait for it to be ready.
Args:
db: ContainerTestLib instance
cid_file_name: Name of the container ID file
container_args: List of container arguments
command: Command to run in the container
Steps:
1. Create the container
2. Get the container ID and IP
3. Wait for the database to be ready
4. Return the container ID and IP
"""
assert db.create_container(
cid_file_name=cid_file_name,
container_args=container_args,
command=command,
)
cip, cid = db.get_cip_cid(cid_file_name=cid_file_name)
assert cid and cip
dw_api = db.db_lib
assert dw_api is not None
dw_api.db_type = VARS.DB_TYPE
assert dw_api.wait_for_database(
container_id=cid, command="/usr/libexec/check-container"
)
return cid, cip


def build_s2i_app(app_path: Path) -> ContainerTestLib:
"""
Build a S2I app.
Args:
app_path: Path to the app
Returns:
ContainerTestLib instance
"""
container_lib = ContainerTestLib(image_name=VARS.IMAGE_NAME, db_type=VARS.DB_TYPE)
app_name = app_path.name
container_test_lib_app = container_lib.build_as_df(
app_path=app_path,
s2i_args="--pull-policy=never",
src_image=VARS.IMAGE_NAME,
dst_image=f"{VARS.IMAGE_NAME}-{app_name}",
)
return container_test_lib_app


def check_pagila_db(cid):
"""
Check the pagila database.
"""
for sql, expected_count in VARS.SQL_CMDS.items():
cmd = f'psql -tA -c "{sql}"'
output = PodmanCLIWrapper.podman_exec_shell_command(
cid_file_name=cid,
cmd=cmd,
)
if "information_schema.tables" in sql:
table_count = [x for x in output.split("\n") if "|public|" in x]
assert len(table_count) == int(expected_count)
else:
assert re.search(expected_count, output)


def is_db_ready(dw_api: DatabaseWrapper, cid: str) -> bool:
"""
Check if the database is ready.
"""
is_ready: bool = False
for _ in range(5):
# Let's check if the database is ready by running a simple query.
# Sometimes check-container can return before the database is fully ready to accept connections.
if not dw_api.wait_for_database(
container_id=cid,
command='psql -h localhost -tA -c "select 1;"',
):
time.sleep(5)
continue
is_ready = True
break
return is_ready


def check_table_output_in_db(cid: str):
"""
Check the database output.
"""
output = PodmanCLIWrapper.podman_exec_shell_command(
cid_file_name=cid, cmd='psql -tA -c "CREATE TABLE blah (id int);"'
)
output = PodmanCLIWrapper.podman_exec_shell_command(
cid_file_name=cid,
cmd='psql -tA -c "INSERT INTO blah VALUES (100), (200), (300);"',
)
output = PodmanCLIWrapper.podman_exec_shell_command(
cid_file_name=cid,
cmd='psql -h localhost -At -c "SELECT * FROM blah ORDER BY id;"',
)
expected_rows = [
"100",
"200",
"300",
]
for expected_row in expected_rows:
assert re.search(expected_row, output), (
f"Row {expected_row} not found in {output}"
)
Loading