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

Get ready for 0.4 #408

Merged
merged 12 commits into from
Oct 23, 2024
2 changes: 1 addition & 1 deletion README-PyPI.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
# FediTest

Testing distributed, heterogeneous systems...
Test framework to test distributed, heterogeneous systems...

...with complex protocols

Expand Down
84 changes: 52 additions & 32 deletions RELEASE-HOWTO.md
Original file line number Diff line number Diff line change
@@ -1,69 +1,89 @@
# Release How-To

## Merge

1. Repo `feditest`: merge `develop` into `main`
1. Repo `feditest-tests-fediverse`: merge `develop` into `main`
1. Repo `feditest-tests-sandbox`: merge `develop` into `main`

## Smoke test and test with sandbox

1. On the Mac:
1. Repo `feditest`: `git checkout main`
1. Repo `feditest`: `git checkout develop`
1. In `pyproject.toml`, change `project` / `version` to the new version `VERSION` (needed so the generated files have the right version in them before check-in)
1. Clean rebuild:
1. `rm -rf venv.*`
1. `make venv PYTHON=python3.11`
1. `make venv`
1. `make lint`: ruff and mypy show no errors
1. `make`
1. Repo `feditest-tests-sandbox`: `git checkout main`
1. `make tests`: unit tests show no errors (smoke tests don't run on macOS)
1. Repo `feditest-tests-sandbox`: `git checkout develop`
1. Clean re-run and report generation of the sandbox tests:
1. `make -f Makefile.generate clean FEDITEST=../feditest/venv.darwin.main/bin/feditest`
1. `make -f Makefile.run clean FEDITEST=../feditest/venv.darwin.main/bin/feditest`
1. `make -f Makefile.generate examples FEDITEST=../feditest/venv.darwin.main/bin/feditest`
1. `make -f Makefile.run sandbox FEDITEST=../feditest/venv.darwin.main/bin/feditest`
1. `make -f Makefile.create clean FEDITEST=../feditest/venv.darwin.default/bin/feditest`
1. `make -f Makefile.run clean FEDITEST=../feditest/venv.darwin.default/bin/feditest`
1. `make -f Makefile.create examples FEDITEST=../feditest/venv.darwin.default/bin/feditest`
1. `make -f Makefile.run sandbox FEDITEST=../feditest/venv.darwin.default/bin/feditest`
1. `open examples/testresults/*.html` and check for plausbility of reports

## Smoke test and test quickstart

1. On UBOS:
1. Repo `feditest`: `git checkout main`
1. Repo `feditest`: `git checkout develop`
1. Clean rebuild:
1. `rm -rf venv.*`
1. `make`
1. Repo `feditest-tests-fediverse`: `git checkout main`
1. `rm -rf venv.*`
1. `make venv`
1. `make lint`: ruff and mypy show no errors
1. `make tests`: unit tests and smoke tests show no errors
1. Repo `feditest-tests-fediverse`: `git checkout develop`
1. Clean re-run and report generation of the sandbox tests:
1. `make -f Makefile.generate clean FEDITEST=../feditest/venv.linux.main/bin/feditest`
1. `make -f Makefile.create clean FEDITEST=../feditest/venv.linux.main/bin/feditest`
1. `make -f Makefile.run clean FEDITEST=../feditest/venv.linux.main/bin/feditest`
1. `make -f Makefile.generate examples FEDITEST=../feditest/venv.linux.main/bin/feditest`
1. `make -f Makefile.create examples FEDITEST=../feditest/venv.linux.main/bin/feditest`
1. `make -f Makefile.run examples FEDITEST=../feditest/venv.linux.main/bin/feditest`
1. `xdg-open examples/testresults/*.html` and check for plausbility of reports

## Tag versions

1. On the Mac:
1. Update repo `feditest-tests-fediverse`
1. `git commit` to `main`
1. Update repo `feditest-tests-fediverse`, branch `develop`:
1. `git tag -a vVERSION -m vVERSION`
1. `git push`
1. `git push --tags`
1. Update repo `feditest-tests-sandbox`
1. `git commit` to `main`
1. Update repo `feditest-tests-sandbox`, branch `develop`:
1. `git tag -a vVERSION -m vVERSION`
1. `git push`
1. `git push --tags`
1. Update repo `feditest`:
1. Change the `python-version` value in `pyproject.toml` to the "production value" that permits Python 3.11 and greater
1. Update repo `feditest`, branch `develop`:
1. `git commit` to `main`
1. `git tag -a vVERSION -m vVERSION`
1. `git push`
1. `git push --tags`
1. Release to PyPi
1. `make release PYTHON=python3.11`
1. `venv.release/bin/twine upload dist/*`
1. `pip install --upgrade feditest`
1. `feditest version` now shows `VERSION`
1. Return `python-version` value in `pyproject.toml` to the "development value" that only permits Python 3.11

## Merge into main

1. Repo `feditest-tests-fediverse`: pull request `develop` into `main`
1. Repo `feditest-tests-sandbox`: pull request `develop` into `main`
1. Repo `feditest`: pull request `develop` into `main`
1. Approve all three pull requests

## Publish to PyPi

1. On the Mac:
1. `make release`
1. `venv.release/bin/twine upload dist/*`
1. `pip install --upgrade feditest`
1. `feditest version` now shows `VERSION`

## Publish to UBOS repos

1. On UBOS:
1. Build `feditest` for the UBOS package repos so it can be installed with `pacman -S feditest`

1. Release notes:
1. Repo: `feditest.org`: create release notes
1. `git push`
## Create release notes

1. Repo: `feditest.org`: create release notes
1. `git push`

## Announce

1. Announce:
1. `@[email protected]`: post link to release notes
1. `https://matrix.to/#/#fediverse-testing:matrix.org`: post link to release notes
1. `https://matrix.to/#/#fediverse-testing:matrix.org`: post link to release notes
1. `@[email protected]`: post link to release notes
4 changes: 2 additions & 2 deletions pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ build-backend = "hatchling.build"

[project]
name = "feditest"
version = "0.3"
version = "0.4"
authors = [
{ name="Johannes Ernst", email="[email protected]" },
{ name="Steve Bate", email="[email protected]" }
Expand All @@ -27,7 +27,7 @@ dependencies = [
"types-requests",
"pre-commit"
]
description = "Testing federated protocols"
description = "Test framework to test distributed, heterogeneous systems with complex protocols such as the Fediverse"
readme = "README-PyPI.md"

# We develop on 3.11, so we can support debian 12 (including Raspberry PI OS) systems,
Expand Down
4 changes: 3 additions & 1 deletion src/feditest/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -242,6 +242,7 @@ class SpecLevel(Enum):
UNSPECIFIED = 4


@property
def formatted_name(self):
return self.name.capitalize()

Expand All @@ -253,6 +254,7 @@ class InteropLevel(Enum):
UNKNOWN = 4


@property
def formatted_name(self):
return self.name.capitalize()

Expand All @@ -268,7 +270,7 @@ def __init__(self, spec_level: SpecLevel, interop_level: InteropLevel, msg: Any)


def __str__(self):
return str(self.msg)
return f'AssertionFailure ({ self.spec_level.formatted_name }, { self.interop_level.formatted_name }): { self.msg }'


def _assert_match(
Expand Down
2 changes: 1 addition & 1 deletion src/feditest/cli/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@ def main() -> None:

set_reporting_level(args.verbose)

if sys.version_info.major != 3 or sys.version_info != 11:
if sys.version_info.major != 3 or sys.version_info.minor != 11:
warning(f"feditest currently requires Python 3.11. You are using { sys.version }"
+ " and may get unpredictable results. We'll get to other versions in the future.")

Expand Down
2 changes: 1 addition & 1 deletion src/feditest/cli/commands/version.py
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ def run(parser: ArgumentParser, args: Namespace, remaining: list[str]) -> int:
parser.print_help()
return 0

print(f'feditest version { FEDITEST_VERSION }')
print(FEDITEST_VERSION)
return 0


Expand Down
2 changes: 1 addition & 1 deletion src/feditest/nodedrivers/imp/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@

_HEADERS = {
"User-Agent": f"feditest/{ FEDITEST_VERSION }",
"Origin": "test.example" # to trigger CORS headers in response
"Origin": "https://test.example" # to trigger CORS headers in response
}

class Imp(AbstractWebFingerDiagClient):
Expand Down
15 changes: 5 additions & 10 deletions src/feditest/protocols/webfinger/abstract.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@
from feditest.protocols.web.diag import HttpRequest, HttpRequestResponsePair, WebDiagClient
from feditest.protocols.webfinger import WebFingerServer
from feditest.protocols.webfinger.diag import ClaimedJrd, WebFingerDiagClient
from feditest.protocols.webfinger.utils import construct_webfinger_uri_for, WebFingerQueryResponse
from feditest.protocols.webfinger.utils import construct_webfinger_uri_for, WebFingerQueryDiagResponse
from feditest.utils import ParsedUri


Expand All @@ -17,7 +17,7 @@ def diag_perform_webfinger_query(
resource_uri: str,
rels: list[str] | None = None,
server: WebFingerServer | None = None
) -> WebFingerQueryResponse:
) -> WebFingerQueryDiagResponse:
query_url = construct_webfinger_uri_for(resource_uri, rels, server.hostname() if server else None )
parsed_uri = ParsedUri.parse(query_url)
if not parsed_uri:
Expand All @@ -29,10 +29,10 @@ def diag_perform_webfinger_query(
pair = self.http(current_request)
if pair.response and pair.response.is_redirect():
if redirect_count <= 0:
return WebFingerQueryResponse(pair, None, WebDiagClient.TooManyRedirectsError(current_request))
return WebFingerQueryDiagResponse(pair, None, [ WebDiagClient.TooManyRedirectsError(current_request) ])
parsed_location_uri = ParsedUri.parse(pair.response.location())
if not parsed_location_uri:
return WebFingerQueryResponse(pair, None, ValueError('Location header is not a valid URI:', query_url, '(from', resource_uri, ')'))
return WebFingerQueryDiagResponse(pair, None, [ ValueError('Location header is not a valid URI:', query_url, '(from', resource_uri, ')') ] )
current_request = HttpRequest(parsed_location_uri)
break

Expand Down Expand Up @@ -67,9 +67,4 @@ def diag_perform_webfinger_query(
except Exception as exc:
excs.append(exc)

if len(excs) > 1:
return WebFingerQueryResponse(ret_pair, jrd, ExceptionGroup('WebFinger errors', excs))
elif len(excs) == 1:
return WebFingerQueryResponse(ret_pair, jrd, excs[0])
else:
return WebFingerQueryResponse(ret_pair, jrd, None)
return WebFingerQueryDiagResponse(ret_pair, jrd, excs)
22 changes: 18 additions & 4 deletions src/feditest/protocols/webfinger/diag.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
"""

import json
from dataclasses import dataclass
from dataclasses import dataclass, field
from typing import Any

from feditest.nodedrivers import NotImplementedByNodeError
Expand Down Expand Up @@ -471,10 +471,24 @@ def __str__(self):


@dataclass
class WebFingerQueryResponse:
class WebFingerQueryDiagResponse:
http_request_response_pair: HttpRequestResponsePair
jrd : ClaimedJrd | None # This may be an invalid jrd
exc : Exception | None #
exceptions : list[Exception] = field(default_factory=list) # List of all things that were found to be wrong


def exceptions_of_type(self, filter_by: type) -> list[Exception]:
"""
Return only the subset of exceptions that are of type filter_by
"""
return [ ex for ex in self.exceptions if isinstance(ex, filter_by) ]


def not_exceptions_of_type(self, filter_by: tuple) -> list[Exception]:
"""
Return only the subset of exceptions that are not of any of the types in filter_by
"""
return [ ex for ex in self.exceptions if not isinstance(ex, filter_by) ]


class WebFingerDiagClient(WebFingerClient, WebDiagClient):
Expand All @@ -491,7 +505,7 @@ def diag_perform_webfinger_query(
resource_uri: str,
rels: list[str] | None = None,
server: WebFingerServer | None = None
) -> WebFingerQueryResponse:
) -> WebFingerQueryDiagResponse:
"""
Make this Node perform a WebFinger query for the provided resource_uri.
The resource_uri must be a valid, absolute URI, such as 'acct:[email protected]` or
Expand Down
22 changes: 7 additions & 15 deletions src/feditest/protocols/webfinger/utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@
from hamcrest.core.base_matcher import BaseMatcher
from hamcrest.core.description import Description

from .diag import ClaimedJrd, WebFingerQueryResponse
from .diag import ClaimedJrd, WebFingerQueryDiagResponse


class UnsupportedUriSchemeError(RuntimeError):
Expand Down Expand Up @@ -203,23 +203,15 @@ def none_except(*allowed_excs : Type[Exception]) -> NoneExceptMatcher :
return NoneExceptMatcher(list(allowed_excs))


def wf_error(response: WebFingerQueryResponse) -> str:
def wf_error(response: WebFingerQueryDiagResponse) -> str:
"""
Construct an error message
"""
if not response.exc:
if not response.exceptions:
return 'ok'

if isinstance(response.exc, ExceptionGroup):
# Make this more compact than the default
msg = str(response.exc.args[0]).split('\n', maxsplit=1)[0]
msg += f' ({ len(response.exc.exceptions) })'
msg += f'\nAccessed URI: "{ response.http_request_response_pair.request.parsed_uri.uri }".'
for i, exc in enumerate(response.exc.exceptions):
msg += f'\n{ i }: { exc }'

else:
msg = str(response.exc).split('\n', maxsplit=1)[0]
msg += f'\nAccessed URI: "{ response.http_request_response_pair.request.parsed_uri.uri }".'
msg += '\n'.join(str(response.exc).split('\n')[1:])
msg = f'Accessed URI: "{ response.http_request_response_pair.request.parsed_uri.uri }":'
for i, exc in enumerate(response.exceptions):
msg += f'\n{ i }: { exc }'

return msg
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
<html lang="en">
<head>
{% include "partials/shared/head.jinja2" %}
<title>{{ transcript.name }} | Feditest</title>
<title>{{ transcript.plan.name }} | Feditest</title>
</head>
<body>
<header class="feditest title">
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -54,7 +54,7 @@
</tr>
{%- for spec_level in [ feditest.SpecLevel.SHOULD, feditest.SpecLevel.IMPLIED, feditest.SpecLevel.UNSPECIFIED ] %}
<tr>
<th>{{ spec_level.formatted_name() }}</th>
<th>{{ spec_level.formatted_name }}</th>
{%- for interop_level in feditest.InteropLevel %}
<td class="status {{ spec_level.name.lower() }} {{ interop_level.name.lower() }} moreinfo">
<div>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@
<h2>Test Results</h2>
<div class="feditest tests">
{%- for test_index, run_test in enumerate(run_session.run_tests) %}
{%- set plan_test_spec = transcript.plan.session.tests[run_test.plan_test_index] %}
{%- set plan_test_spec = transcript.plan.session_template.tests[run_test.plan_test_index] %}
{%- set test_meta = transcript.test_meta[plan_test_spec.name] %}
<div class="test" id="test-{{ test_index }}">
<h4><span class="prefix">Test:</span> {{ test_meta.name }}</h4>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
<html lang="en">
<head>
{% include "partials/shared/head.jinja2" %}
<title>{{ transcript.name }} | Feditest</title>
<title>{{ transcript.plan.name }} | Feditest</title>
</head>
<body>
<header class="feditest title">
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -167,7 +167,6 @@ div.feditest.session > h3::before {
}

.feditest .status div {
margin: 3px 6px;
padding: 5px;
}

Expand Down
Loading