Skip to content

Commit

Permalink
Adds test infrastructure
Browse files Browse the repository at this point in the history
  • Loading branch information
justin-russell committed Feb 26, 2024
1 parent 99e7cb4 commit b9a7915
Show file tree
Hide file tree
Showing 20 changed files with 600 additions and 8 deletions.
14 changes: 7 additions & 7 deletions .github/workflows/ci.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -6,15 +6,15 @@ on:
- '**' # This will run the workflow on every push to any branch

jobs:
# build_and_test:
# runs-on: ubuntu-latest
build_and_test:
runs-on: ubuntu-latest

# steps:
# - name: Checkout repository
# uses: actions/checkout@v2
steps:
- name: Checkout repository
uses: actions/checkout@v2

# - name: Run tests
# run: make test-ci
- name: Run tests
run: make test-ci

pypi-publish:
if: github.ref == 'refs/heads/main'
Expand Down
2 changes: 1 addition & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
**.env*
!**.env.example
**venv*
**/.coverage
**.coverage*
**/coverage.lcov
**/build
**/*.egg-info
24 changes: 24 additions & 0 deletions Dockerfile.test
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
# syntax=docker/dockerfile:1
FROM python:3.11.4

ENV PYTHONUNBUFFERED=1
ENV PYTHON_BIN=python

WORKDIR /code

# install fractal-database from pypi
RUN pip install fractal-database

COPY fractal_database_matrix /code/fractal_database_matrix
COPY pyproject.toml README.md /code/

# install modules
RUN pip3 install -e /code[dev]

COPY tests /code/tests
COPY .coveragerc conftest.py pytest.ini /code/

COPY test-config /test-config
COPY Makefile /code

ENTRYPOINT [ "/test-config/entrypoint.sh" ]
24 changes: 24 additions & 0 deletions Makefile
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
.PHONY: test-ci synapse
SHELL=/bin/bash
# get makefile directory
MAKEFILE_DIR := $(dir $(abspath $(lastword $(MAKEFILE_LIST))))
PROJECT_ENV_FILE=${MAKEFILE_DIR}fractal_database_matrix.dev.env
TEST_PROJECT_DIR=${MAKEFILE_DIR}test-config/test_project
TEST = ""

test-ci:
docker compose up synapse --build --force-recreate -d --wait
docker compose up test --build --force-recreate --exit-code-from test
docker compose down

setup:
python test-config/prepare-test.py

test:
. ${PROJECT_ENV_FILE} && export PYTHONPATH=${TEST_PROJECT_DIR} && pytest -k ${TEST} -s --cov-config=.coveragerc --cov=fractal_database_matrix -v --asyncio-mode=auto --cov-report=lcov --cov-report=term tests/

qtest:
. ${PROJECT_ENV_FILE} && export PYTHONPATH=${TEST_PROJECT_DIR} && pytest -k ${TEST} -s --cov-config=.coveragerc --cov=fractal_database_matrix --asyncio-mode=auto --cov-report=lcov tests/

synapse:
docker compose -f ./synapse/docker-compose.yml up synapse -d --force-recreate --build
107 changes: 107 additions & 0 deletions conftest.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,107 @@
import os
import secrets
from unittest.mock import MagicMock, patch

import pytest
from fractal.cli.controllers.auth import AuthController
from fractal_database.models import Database, Device

try:
TEST_HOMESERVER_URL = os.environ["MATRIX_HOMESERVER_URL"]
TEST_USER_USER_ID = os.environ["HS_USER_ID"]
TEST_USER_ACCESS_TOKEN = os.environ["MATRIX_ACCESS_TOKEN"]
except KeyError as e:
raise Exception(
f"Please run prepare-test.py first, then source the generated environment file: {e}"
)


@pytest.fixture
def test_homeserver_url() -> str:
return os.environ.get("TEST_HOMESERVER_URL", "http://localhost:8008")


@pytest.fixture(scope="function")
def logged_in_db_auth_controller(test_homeserver_url):
# create an AuthController object and login variables
auth_cntrl = AuthController()
matrix_id = "@admin:localhost"

# log the user in patching prompt_matrix_password to use preset password
with patch(
"fractal.cli.controllers.auth.prompt_matrix_password", new_callable=MagicMock()
) as mock_password_prompt:
mock_password_prompt.return_value = "admin"
auth_cntrl.login(matrix_id=matrix_id, homeserver_url=test_homeserver_url)

return auth_cntrl


@pytest.fixture(scope="function")
def test_database(db):
""" """

from fractal_database.signals import create_database_and_matrix_replication_target

create_database_and_matrix_replication_target()

return Database.current_db()


@pytest.fixture(scope="function")
def test_device(db, test_database):
""" """
unique_id = f"test-device-{secrets.token_hex(8)[:4]}"

return Device.objects.create(name=unique_id)


@pytest.fixture(scope="function")
def second_test_device(db, test_database):
""" """
unique_id = f"test-device-{secrets.token_hex(8)[:4]}"

return Device.objects.create(name=unique_id)


# @pytest.fixture(scope="function")
# def test_matrix_creds(db, test_database):
# """
# """
# unique_id = f"test-device-{secrets.token_hex(8)[:4]}"

# return MatrixCredentials.objects.create(name=unique_id)


@pytest.fixture
def test_user_access_token():
return os.environ["MATRIX_ACCESS_TOKEN"]


# @pytest.fixture(scope="function")
# def matrix_client() -> Generator[AsyncClient, None, None]:
# client = AsyncClient(homeserver=TEST_HOMESERVER_URL)
# client.user_id = TEST_USER_USER_ID
# client.access_token = TEST_USER_ACCESS_TOKEN
# yield client
# asyncio.run(client.close())


# @pytest.fixture(scope="function")
# def test_user(db):
# return MatrixAccount.objects.create(matrix_id=TEST_USER_USER_ID)


# @pytest.fixture(scope="function")
# def database(db):
# return Database.objects.get()


# @pytest.fixture
# def test_room_id() -> str:
# return TEST_ROOM_ID


# @pytest.fixture
# def test_user_id() -> str:
# return TEST_USER_USER_ID
37 changes: 37 additions & 0 deletions docker-compose.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
services:
synapse:
image: fractal-database-synapse:latest
build:
context: ./synapse/config
dockerfile: Dockerfile.synapse
args:
SYNAPSE_SERVER_NAME: "localhost"
SYNAPSE_REPORT_STATS: "no"
healthcheck:
test: curl localhost:8008/health
interval: 1s
timeout: 10s
retries: 10
labels:
- "org.homeserver.test=true"
# --timeout on up doesn't work with --exit-code-from. This ensures the synapse
# container is stopped immediately when the device exits
stop_signal: SIGKILL
test:
image: fractal-database-test:test
build:
context: ./
dockerfile: Dockerfile.test
depends_on:
synapse:
condition: service_healthy
environment:
ENV: test
TEST_CONFIG_DIR: /test-config
TEST_HOMESERVER_URL: http://synapse:8008
# not actually running a second synapse currently
TEST_ALTERNATE_HOMESERVER_URL: https://synapse2:8008
SYNAPSE_DOCKER_LABEL: "org.homeserver.test=true"
volumes:
- /var/run/docker.sock:/var/run/docker.sock
working_dir: /code
10 changes: 10 additions & 0 deletions pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,17 @@ django = "^5.0.0"
matrix-nio = "^0.22.1"
fractal-matrix-client = ">=0.0.1"
taskiq-matrix = ">=0.0.1"
fractal-cli = ">=0.0.1"
pytest = { version = "^7.4.3", optional = true }
pytest-asyncio = { version = "^0.21.1", optional = true }
pytest-cov = { version = "^4.1.0", optional = true }
pytest-mock = { version = "^3.11.1", optional = true }
ipython = { version = "^8.17.2", optional = true }
pytest-django = { version = "^4.5.2", optional = true }

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

[tool.poetry.extras]
dev = ["pytest-django", "pytest", "pytest-cov", "pytest-mock", "pytest-asyncio", "ipython"]
6 changes: 6 additions & 0 deletions pytest.ini
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
[pytest]

DJANGO_SETTINGS_MODULE = test_project.settings

filterwarnings =
ignore::DeprecationWarning
19 changes: 19 additions & 0 deletions synapse/config/Dockerfile.synapse
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
FROM matrixdotorg/synapse:v1.95.1

ARG SYNAPSE_SERVER_NAME=localhost
ARG SYNAPSE_REPORT_STATS=no

RUN apt update; apt install sqlite3 -y
RUN rm -rf /var/lib/apt/lists/*

RUN mkdir -p /data

RUN bash -c 'python /start.py generate'

COPY config_to_add.yaml /config_to_add.yaml

# append config to homeserver.yaml only if it's not already there
RUN cat /config_to_add.yaml >> /data/homeserver.yaml

ENTRYPOINT bash -c ' \
python /start.py &> /dev/null'
21 changes: 21 additions & 0 deletions synapse/config/config_to_add.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@

enable_registration: true
registration_requires_token: true
presence_enabled: false
max_upload_size: 5000M

# increasing default rate limiting burst counts to avoid tests hanging for unauthenticated
# requtests to login
rc_login:
address:
per_second: 0.15
burst_count: 656565
account:
per_second: 0.18
burst_count: 656565
failed_attempts:
per_second: 0.19
burst_count: 656565
rc_registration:
per_second: 0.15
burst_count: 656565
25 changes: 25 additions & 0 deletions synapse/docker-compose.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
version: "3.9"
services:
synapse:
image: homeserver-synapse:latest
build:
context: ./config
dockerfile: Dockerfile.synapse
args:
SYNAPSE_SERVER_NAME: "localhost"
SYNAPSE_REPORT_STATS: "no"
ports:
- 8008:8008
healthcheck:
test: curl localhost:8008/health
interval: 5s
timeout: 10s
retries: 5
labels:
- "org.homeserver=true"
restart: "unless-stopped"
element:
image: vectorim/element-web:latest
ports:
- "8009:80"
restart: "unless-stopped"
20 changes: 20 additions & 0 deletions test-config/entrypoint.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
#!/bin/bash

# expected environment variables:
# ENV - environment name (e.g. test, dev, prod)
# TEST_CONFIG_DIR - path to the test-config directory
# PROJECT_NAME - name of the project in snake case (e.g. fractal_database_matrix)

set -e

PREPARE_SCRIPT="$TEST_CONFIG_DIR/prepare-test.py"
# PROJECT_NAME is optional, if not set, it will be set to "fractal_database_matrix"
PROJECT_NAME="${PROJECT_NAME:-fractal_database_matrix}"
PROJECT_ENV_FILE="$TEST_CONFIG_DIR/$PROJECT_NAME.$ENV.env"

python3 "$PREPARE_SCRIPT"

# environment file should be created by prepare-test.py
source "$PROJECT_ENV_FILE"

make -C /code test PROJECT_ENV_FILE="$PROJECT_ENV_FILE" PYTHONPATH="$TEST_CONFIG_DIR/test_project" TEST_PROJECT_DIR="$TEST_CONFIG_DIR/test_project" # PYTHONPATH="$TEST_CONFIG_DIR/test_project" pytest -v -s --asyncio-mode=auto --cov=/code/fractal_database --cov-report=lcov --cov-report=term tests/
Loading

0 comments on commit b9a7915

Please sign in to comment.