Skip to content

Bedework#584

Merged
tobixen merged 8 commits intomasterfrom
bedework
Dec 4, 2025
Merged

Bedework#584
tobixen merged 8 commits intomasterfrom
bedework

Conversation

@tobixen
Copy link
Copy Markdown
Member

@tobixen tobixen commented Dec 2, 2025

test server in docker

@tobixen tobixen force-pushed the bedework branch 2 times, most recently from f6cd24c to 67b34a6 Compare December 4, 2025 02:49
@tobixen
Copy link
Copy Markdown
Member Author

tobixen commented Dec 4, 2025

Another session of "banging on things until all tests pass" - and while doing so, tons of different commits on different things gets added to the same pull request. I've asked Claude to rebase it into some few well-organized commits, but i'm not much happy with the result, so I will again make a jumbo-commit.

My own non-AI-assisted summary of the changes introduced in this pull request looks like this:

Test framework:

  • Changes in the github workflow and test suite to run tests towards bedework. The bedework docker container is quite straigth forward, comes up with some default test user and password, no extra dependencies. But it's very old, not maintained and quite buggy.
  • Lots of tweaks in the test code to get it pass on Bedework and all the other servers
  • Fix for SOGo - tests didn't want to run with github runners.

Code logic:

  • Due to the previous changeset with transparent workarounds for servers not supporting sync-tokens, my compatibility check script started reporting that all servers supported sync-tokens. To revert to the old behaviour, I needed to add a disable_fallback parameer to the objects_by_sync_token method.
  • Continued massaging and bugfixing on the compatibility_hints.py.
    • Added synology compatibility matrix
    • Added bedework compatibility matrix
    • Lots of "unsupported" stuff has been reclassified into "ungraceful".
    • Some more features added to the definitions
    • Bugfix in FeatureSet constructor.
  • Downgraded an annoying "CRITICAL" to "INFO" (some servers sends unexpected content-type on errors or empty responses)
  • Workaround to handle Bedework in search - Bedework does not handle the component filter right - if asking for events, it will send everything, and when askin
    g for todos it will send ... nothing! There is now a workaround in the search algorithm.
  • If the server can't do text-searches, then we should use client-side filtering of completed tasks.
  • Bugfix to the auto-discover URL code - it did not work very well together with the "read the URL from the compatibility_hints.py" logic

tobixen and others added 5 commits December 4, 2025 04:05
Adds Bedework Enterprise Calendar System to the CI/CD pipeline to test
against another CalDAV server implementation.

Changes:
- Added bedework service container (ioggstream/bedework:latest)
- Exposed on port 8804 (internal port 8080)
- Configured health check with 120s start period (JBoss startup time)
- Added configuration step to verify Bedework is ready
- Uses default credentials: vbede/bedework
- CalDAV endpoint: http://localhost:8804/ucaldav/user/vbede/
- Added BEDEWORK_URL environment variable for tests

Bedework characteristics:
- JBoss-based enterprise calendar system
- Full-featured CalDAV server
- ~900MB Docker image
- Longer startup time (60-120 seconds)
- Well-established CalDAV implementation

This adds valuable test coverage against a different CalDAV server
architecture (JBoss vs FastCGI/Apache/nginx used by other servers).

🤖 Generated with [Claude Code](https://claude.com/claude-code)


Part of: #584

Co-Authored-By: Claude <noreply@anthropic.com>

Add Bedework test server documentation

Documents the Bedework Docker configuration for test infrastructure.
Unlike other test servers, Bedework requires no configuration files
as it comes pre-configured with a default user.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>

Add Bedework configuration to test suite conf.py

Adds Bedework CalDAV server configuration to the test configuration,
enabling automated testing against Bedework when running locally or
in CI/CD.

Configuration details:
- Default host: localhost
- Default port: 8804
- Default username: vbede
- Default password: bedework
- CalDAV URL: http://localhost:8804/ucaldav/user/vbede/
- Auto-enabled when BEDEWORK_URL env var is set or docker is available
- Accessibility check via PROPFIND request

Follows the same pattern as other Docker-based test servers (Baikal,
Nextcloud, Cyrus, SOGo) with environment variable overrides and
automatic discovery.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>

Add Bedework Docker Compose and startup scripts

Adds the necessary infrastructure files for running Bedework as a
local Docker test server:

- docker-compose.yml: Bedework service definition with health check
- start.sh: Startup script with 2-minute timeout for JBoss initialization
- stop.sh: Cleanup script to stop container and remove volumes

These scripts follow the same pattern as other Docker test servers
(SOGo, Baikal, Nextcloud, Cyrus) and enable local testing with:
  cd tests/docker-test-servers/bedework
  ./start.sh

Default configuration:
- Port: 8804
- Username: vbede
- Password: bedework
- CalDAV endpoint: http://localhost:8804/ucaldav/user/vbede/

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>

Add SOGo and Bedework environment variables to tox passenv

The GitHub Actions workflow configures SOGo and Bedework services
and sets their URLs as environment variables (SOGO_URL, BEDEWORK_URL),
but tox was not passing these through to the test environment.

This meant that even though the services were running and accessible,
the tests would not run against them because the test configuration
(tests/conf.py) couldn't see the environment variables.

Added to passenv:
- SOGO_URL, SOGO_USERNAME, SOGO_PASSWORD
- BEDEWORK_URL, BEDEWORK_USERNAME, BEDEWORK_PASSWORD

This enables tests to run against these servers in CI.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>

Fix SOGo database connectivity in GitHub Actions

The SOGo Docker container was unable to connect to the database because
the database service was named 'sogo-db' but the SOGo configuration
expected hostname 'db'.

Changes:
- Added --network-alias db to sogo-db service options
  This allows the database to be reached at hostname 'db'
- Simplified SOGo configuration step
  Removed complex sed replacement of database hostname
  The network alias makes the database reachable at 'db' as expected
- Improved logging with status messages

This should fix the SOGo test failures in GitHub Actions where all
tests were failing due to database connection errors.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>

Fix test mocks to match is_supported signature

The is_supported() method now takes two parameters:
- feature (required)
- return_type (optional, defaults to bool)

The test mocks were only accepting one parameter, causing
TypeError when the search code called is_supported with
the return_type parameter.

Updated all three test functions to use:
  lambda feature, return_type=bool: {...}

This matches the real signature and allows the tests to pass.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>

Fix setup/teardown lambda to not require self parameter

The _conf_method function was creating a lambda that accepted a 'self'
parameter but didn't use it. When davclient.__enter__ called self.setup(),
Python didn't pass self automatically because setup is just a lambda
attribute, not a bound method.

Changed from:
  lambda self: _start_or_stop_server(name, action)
To:
  lambda: _start_or_stop_server(name, action)

This matches how davclient.__enter__ calls it: self.setup()

The issue surfaced when adding SOGO_URL and BEDEWORK_URL to tox passenv,
because now servers that aren't running locally (like Baikal) get the
setup/teardown methods added, whereas before they were skipped.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
Changes the log level from CRITICAL to INFO when the server returns HTML
instead of XML during discovery requests. This is normal behavior for some
servers (like Bedework/JBoss) that return HTML error pages for 401/404
responses.

The library handles these responses gracefully by continuing with
authenticated requests, so this is informational rather than critical.
The error was particularly noisy with Bedework which returns HTML 401
pages for unauthenticated discovery attempts.

Rationale:
- The library doesn't fail - it continues and works correctly
- Some servers (Bedework, JBoss-based) return HTML error pages by design
- CRITICAL implies the operation failed, but it actually succeeds
- INFO better reflects that this is expected behavior being logged

🤖 Generated with [Claude Code](https://claude.com/claude-code)


Part of: #584

Co-Authored-By: Claude <noreply@anthropic.com>
the comp filter logic seems utterly broken for bedework, but we've implemented a workaround for it in search.  Arguably it's bloated, nobody uses bedework, but still it adds value for making the test framework robust enough to handle various broken caldav servers

Replace object_by_uid_is_broken flag with search.text.by-uid feature

- Add search.text.by-uid feature to FEATURES dict in compatibility_hints.py
- Remove object_by_uid_is_broken from old compatibility flags (marked as obsolete)
- Update all test_caldav.py usages:
  - Replace skip_on_compatibility_flag("object_by_uid_is_broken") with skip_unless_support("search.text.by-uid")
  - Replace check_compatibility_flag("object_by_uid_is_broken") with is_supported("search.text.by-uid")
- This migration follows the new feature-based compatibility checking system

🤖 Generated with [Claude Code](https://claude.com/claude-code)


Part of: #584

Co-Authored-By: Claude <noreply@anthropic.com>

some bugfixes and test fixes

struggling to get tests to pass

I need the tests to pass for bedework

I need the tests to pass for bedework

I need the tests to pass

still struggling to get tests to pass

more work to get more tests to pass

Remove duplicate SOGo compatibility hints definition

The file had two sogo = {...} definitions:
- Line 961: Comprehensive hints including search.is-not-defined, search.text, etc.
- Line 1159: Only search.time-range.accurate

The second definition was completely overwriting the first, causing GitHub
Actions to run with an incomplete SOGo compatibility matrix (only one hint)
while local tests used the full version. This explained why 12 tests were
failing in GitHub Actions but passing locally.

The tests were incorrectly checking is_supported("search.is-not-defined")
which returned True (default) instead of False (unsupported), causing the
test to run assertions that failed because SOGo doesn't actually support
this feature.

Removed the duplicate second definition to use the comprehensive first one.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>

zimbra compatibility matrix fix

bugfix
Add a new disable_fallback parameter to the objects_by_sync_token() and
objects() methods. When set to True, the method will raise an exception
instead of falling back to retrieving all objects when the server
doesn't support sync tokens.

This is useful for testing whether a server truly supports sync tokens,
as the transparent fallback behavior makes it difficult to distinguish
between servers that support sync-collection REPORT and those that don't.

Changes:
- Added disable_fallback parameter to objects_by_sync_token()
- Updated docstring to document the new parameter
- Raises ReportError when fallback is disabled and server doesn't support sync tokens
- Raises the original exception when sync-collection REPORT fails and fallback is disabled

🤖 Generated with [Claude Code](https://claude.com/claude-code)


Part of: #584

Co-Authored-By: Claude <noreply@anthropic.com>
Part of: #584
tobixen and others added 2 commits December 4, 2025 04:48
When using ecloud features with an email username (e.g., "tobixen@e.email")
and no explicit URL, the auto-connect logic was incorrectly using the email
as the domain instead of the configured domain from compatibility hints.

Root cause:
1. When no URL is provided but username contains @, the code sets url = username
   for RFC6764 discovery (line 133-135)
2. RFC6764 discovery fails for the invalid email-as-domain
3. The fallback logic only replaced empty URLs with the domain from hints,
   but url now contains the email address from the failed discovery attempt
4. This resulted in: https://tobixen@e.email/remote.php/dav (wrong!)
   Instead of: https://ecloud.global/remote.php/dav (correct)

Fix:
Modified the fallback logic to also replace URLs that look like email addresses
(contain @) with the domain from compatibility hints. Now the check is:
  if (not url or (url and "@" in str(url))) and "domain" in url_hints

Changes:
- caldav/davclient.py: Updated fallback URL construction logic
- tests/test_caldav_unit.py: Added testAutoUrlEcloudWithEmailUsername to
  verify the fix and prevent regression

This ensures that services like ecloud with auto-connect.url hints work
correctly when users provide only an email username.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
The test was failing on Bedework in GitHub Actions because it assumed
a specific order of results when searching for expanded recurring events
with exceptions.

The test expected:
- r[0] to have RECURRENCE-ID 2024-04-11 (base event)
- r[1] to have RECURRENCE-ID 2024-04-25 (exception)

However, Bedework returned them in the opposite order. The CalDAV spec
does not guarantee any particular order for search results, so the test
was too brittle.

Fix:
Changed the test to collect all RECURRENCE-ID values and verify that
the expected set of dates is present, without assuming any particular
order. This makes the test more robust and spec-compliant.

Changes:
- Iterate through all results and collect recurrence IDs
- Use set comparison to verify both expected dates are present
- Remove assumptions about result ordering

This ensures the test passes on all CalDAV servers regardless of
their result ordering behavior.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
tobixen added a commit that referenced this pull request Dec 4, 2025
Part of: #584
tobixen added a commit that referenced this pull request Dec 4, 2025
Part of: #584
@tobixen tobixen merged commit 7c52767 into master Dec 4, 2025
4 checks passed
@tobixen
Copy link
Copy Markdown
Member Author

tobixen commented Dec 4, 2025

Here is the AI-generated summary (hand-edited a bit to remove some wrong and irrelevant information):

The bedework branch contains 8 commits with +487/-130 lines across 14 files.

Commits in bedework branch (not in master)

  1. 33f7097 - style and minor bugfixes to the test framework
  2. c29c142 - Fix testRecurringDateWithExceptionSearch to be order-independent
  3. 0e0c4e7 - Fix auto-connect URL construction for ecloud with email username
  4. 5746af4 - style
  5. eef9e42 - Add disable_fallback parameter to objects_by_sync_token
  6. 00810b7 - work on bedework
  7. 2e549c6 - Downgrade HTML response log from CRITICAL to INFO
  8. 12d47ec - Add Bedework CalDAV server to GitHub Actions test suite

Key Differences

1. Bedework Server Support (Primary Goal)

  • Added Bedework CalDAV server to GitHub Actions test suite
  • New Docker test infrastructure: tests/docker-test-servers/bedework/ with:
    • docker-compose.yml
    • start.sh and stop.sh scripts
    • README.md documentation
  • GitHub Actions workflow updated to run tests against Bedework

2. Compatibility Hints Expansion (Major Changes)

File: caldav/compatibility_hints.py (+141/-130 lines)

New feature flags added:

Enhancements:

  • Enhanced documentation and behavior descriptions for existing flags
  • Refined server-specific compatibility hints for multiple servers
  • Added deprecation notice to old-style compatibility flag list
  • Fixed RFC reference (5538 → 6638 for freebusy scheduling)

3. Bug Fixes

  • ecloud auto-connect URL: Fixed URL construction when username is an email address (caldav/davclient.py)
  • Order-independent tests: Fixed testRecurringDateWithExceptionSearch to not assume result ordering (tests/test_caldav.py)
  • Log level: Downgraded HTML response log from CRITICAL to INFO

4. New Features

  • Added disable_fallback parameter to objects_by_sync_token() method (caldav/collection.py)

5. Test Suite Improvements

Files modified:

  • tests/test_caldav.py (+173 lines changed) - Refactored for Bedework compatibility
  • tests/conf.py (+43 lines) - Enhanced test configuration with Bedework-specific settings
  • tests/test_caldav_unit.py (+36 lines) - New unit tests for ecloud auto-connect
  • tests/test_substring_workaround.py (+6 lines) - Minor fixes
  • tox.ini (+6 lines) - Test configuration updates

6. Search Functionality

File: caldav/search.py (+48 lines changed)

  • Improved search robustness and server compatibility

Files Changed Summary

.github/workflows/tests.yaml                       |  53 lines
caldav/collection.py                               |  13 lines
caldav/compatibility_hints.py                      | 141 lines
caldav/davclient.py                                |   8 lines
caldav/search.py                                   |  48 lines
tests/conf.py                                      |  43 lines
tests/docker-test-servers/bedework/README.md       |  28 lines (new)
tests/docker-test-servers/bedework/docker-compose.yml | 14 lines (new)
tests/docker-test-servers/bedework/start.sh        |  36 lines (new)
tests/docker-test-servers/bedework/stop.sh         |  12 lines (new)
tests/test_caldav.py                               | 173 lines
tests/test_caldav_unit.py                          |  36 lines
tests/test_substring_workaround.py                 |   6 lines
tox.ini                                            |   6 lines

Total: 14 files changed, 487 insertions(+), 130 deletions(-)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant