Skip to content

Run libev unit tests in CI and stop silently skipping tests#911

Draft
sylwiaszunejko wants to merge 9 commits into
scylladb:masterfrom
sylwiaszunejko:enable-libev-unittest
Draft

Run libev unit tests in CI and stop silently skipping tests#911
sylwiaszunejko wants to merge 9 commits into
scylladb:masterfrom
sylwiaszunejko:enable-libev-unittest

Conversation

@sylwiaszunejko

@sylwiaszunejko sylwiaszunejko commented Jun 18, 2026

Copy link
Copy Markdown
Collaborator

Motivation

Tests skip themselves when their requirements are missing (a library is absent,
the wrong event loop is selected, the C extensions aren't built). That's fine
locally but a footgun in CI: a test can be silently skipped and nobody
notices. The libev unit tests were effectively not running in any CI
configuration — enabling them also surfaced two pre-existing cluster.py bugs.

Changes

  • No silent skips in CI: a CASS_DRIVER_NO_SKIP-gated pytest hook in
    tests/conftest.py turns skips into failures (xfail untouched). Enabled in the
    cibuildwheel test-commands where C extensions are mandatory (Linux/macOS).
    Tests that genuinely can't run in the default config are listed explicitly via
    -k/--ignore (reactor tests run separately per EVENT_LOOP_MANAGER;
    asyncore, column_encryption, and a few upstream-disabled/flaky tests excluded).
    Windows and PyPy keep it off (the C extensions are optional on Windows and are
    never built on PyPy, so their extension-dependent skips are legitimate). Local
    dev is unaffected.
  • Visibility: add -v to all pytest invocations, and install the
    compress-lz4 test-extra so the lz4 tests actually run.
  • Bug fixes (independent, committed separately):
    • Session._set_keyspace_for_all_pools reported only the last pool's errors
      instead of the aggregated dict; failures from other pools were lost.
    • Session.wait_for_schema_agreement now validates scope and raises
      ValueError for unknown values (as the docstring already promised).

Fixes: #904

Pre-review checklist

  • I have split my patch into logically separate commits.
  • All commit messages clearly explain what they change and why.
  • I added relevant tests for new features and bug fixes.
  • All commits compile, pass static checks and pass test.
  • PR description sums up the changes and reasons why they should be introduced.
  • I have provided docstrings for the public items that I want to introduce.
  • I have adjusted the documentation in ./docs/source/.
  • I added appropriate Fixes: annotations to PR description.

test_watchers_are_finished calls libev__cleanup which stops the
preparer, which causes the test_multi_timer_validation to hang if it
runs later. Simplest fix is to not only restore _global_loop._shutdown
but also restart the prepared with _global_loop._preparer.start().
It looks like some recent version of Python removed distutils from
stdlib, which causes test collection to fail for me because of missing
import. The fix is to add setuptools to dev dependencies.
Tests skip themselves when their requirements are missing, which is a
footgun in CI: a libev/lz4/event-loop test could be silently skipped and
nobody would notice. Add a CASS_DRIVER_NO_SKIP-gated pytest hook in
conftest.py that converts skips into failures (leaving xfail untouched),
and enable it in the cibuildwheel test-commands with precise -k/--ignore
filters plus -v output. Install the lz4 test-extra so the compression
tests actually run, and add -v to the integration-tests workflow.
The final callback was invoked with host_errors (the errors from only
the last pool to finish) instead of the accumulated errors dict. If the
last pool succeeded, failures from other pools were silently lost. Pass
the aggregated errors dict, matching the method's docstring.
The docstring promised ValueError for an invalid scope, but no check
existed: an unknown value silently fell through to cluster-wide
behaviour. Coerce/validate the argument against SchemaAgreementScope up
front (also accepting the plain string values) and raise a clear
ValueError listing the valid scopes.
@coderabbitai

coderabbitai Bot commented Jun 18, 2026

Copy link
Copy Markdown

Important

Review skipped

Draft detected.

Please check the settings in the CodeRabbit UI or the .coderabbit.yaml file in this repository. To trigger a single review, invoke the @coderabbitai review command.

⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro Plus

Run ID: 1a456f46-049e-4fe6-b74a-2afb30eed496

You can disable this status message by setting the reviews.review_status to false in the CodeRabbit configuration file.

Use the checkbox below for a quick retry:

  • 🔍 Trigger review

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

PyPy never builds the libev/cmurmur3/Cython C extensions (setup.py forces
is_pypy to skip them even with CASS_DRIVER_BUILD_EXTENSIONS_ARE_MUST=yes),
so the tests depending on those extensions legitimately skip. Under
CASS_DRIVER_NO_SKIP those skips became failures. Add a cibuildwheel
override for 'pp*' that runs the suite without no-skip (same policy as
Windows).
In cibuildwheel the tests are run against the installed wheel, but pytest's
default 'prepend' import mode inserts the project root at sys.path[0]. That
shadows the installed compiled wheel with the in-tree pure-Python cassandra/
source, so 'import cassandra.row_parser' / 'cassandra.io.libevreactor' /
'cassandra.cmurmur3' all fail and every libev/cmurmur3/Cython test skips.
Under CASS_DRIVER_NO_SKIP those skips became failures. Switch to
--import-mode=append so site-packages (the wheel) takes precedence while the
'tests' package is still importable from the appended project root.
The atexit subprocess test inserted the project root at sys.path[0], which
shadows the installed compiled wheel with the in-tree pure-Python source.
Under cibuildwheel that source lacks the libev C extension, so the import
failed and the subprocess produced no output. Append the path instead so the
installed wheel takes precedence (falling back to the source tree only when
the driver isn't installed).
PyPy has no prebuilt lz4 wheel, so 'pip install scylla-driver[compress-lz4]'
compiled lz4 from source and failed (gcc 14 rejects the lz4 C sources). The
pp* override inherited test-extras from [tool.cibuildwheel.linux]; clear it so
lz4 is not installed on PyPy. The lz4 tests just skip there (no-skip is off).
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.

libev-based unit tests are not running in CI

1 participant