Skip to content

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

Merged
dkropachev merged 5 commits into
scylladb:masterfrom
sylwiaszunejko:enable-libev-unittest
Jul 2, 2026
Merged

Run libev unit tests in CI and stop silently skipping tests#911
dkropachev merged 5 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.

@coderabbitai

coderabbitai Bot commented Jun 18, 2026

Copy link
Copy Markdown

Review Change Stack

📝 Walkthrough

Walkthrough

This PR fixes a callback argument bug in Session._set_keyspace_for_all_pools where the wrong error variable was passed to the completion callback. It also addresses silent test skipping in CI by adding a CASS_DRIVER_NO_SKIP mechanism in tests/conftest.py that converts skips to failures, adds -v to integration test invocations, and updates pyproject.toml cibuildwheel configuration with explicit test exclusions and per-reactor-backend test runs across Linux, macOS, and PyPy. Additionally, libev reactor unit tests are updated to properly restore global loop state after simulating shutdown, and subprocess diagnostics/import precedence are improved in a related shutdown test.

Possibly related issues

Suggested reviewers: Lorak-mmk

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Out of Scope Changes check ⚠️ Warning The cluster.py error-aggregation fix is unrelated to the CI/libev test issue and appears to be extra scope. Split the unrelated cluster.py bug fix into a separate PR so this change set stays focused on the CI/libev test work.
✅ Passed checks (4 passed)
Check name Status Explanation
Title check ✅ Passed The title clearly matches the PR’s main change: making libev unit tests run in CI and stopping silent skips.
Description check ✅ Passed The description covers motivation, changes, and fixes, and it follows the repository template closely.
Linked Issues check ✅ Passed The PR implements the linked issue’s CI changes: verbose pytest output, no-skip CI behavior, and explicit test filtering.
Docstring Coverage ✅ Passed Docstring coverage is 100.00% which is sufficient. The required threshold is 80.00%.

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.

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR makes CI test runs more trustworthy by preventing “silent skips” (where tests skip due to missing deps/config and CI still passes), and by making pytest output more verbose so skips are visible. It also includes a small bug fix in Session._set_keyspace_for_all_pools plus test adjustments to keep the shared libev reactor singleton in a working state for subsequent tests.

Changes:

  • Add a CASS_DRIVER_NO_SKIP-gated pytest hook to turn unexpected skips into failures, and enable it in cibuildwheel Linux/macOS test commands while explicitly deselecting known-incompatible tests.
  • Increase test visibility by adding -v to pytest invocations and ensuring compress-lz4 is installed so lz4-related tests run in CI.
  • Fix keyspace-setting error aggregation in Session._set_keyspace_for_all_pools and adjust libev shutdown/reactor tests to avoid CI/import pitfalls and cross-test contamination.

Reviewed changes

Copilot reviewed 6 out of 6 changed files in this pull request and generated 2 comments.

Show a summary per file
File Description
tests/unit/io/test_libevreactor.py Restores libev singleton reactor state after cleanup to prevent downstream hangs.
tests/unit/io/test_libevreactor_shutdown.py Adjusts subprocess import path precedence and improves subprocess failure diagnostics.
tests/conftest.py Adds a no-skip CI mode by converting non-xfail skips into failures.
pyproject.toml Enables no-skip + verbose pytest in cibuildwheel where extensions are required; installs lz4 extra for tests.
cassandra/cluster.py Fixes _set_keyspace_for_all_pools to return aggregated errors rather than only the last pool’s errors.
.github/workflows/integration-tests.yml Makes integration pytest runs verbose (-v) for better skip/failure visibility.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment thread tests/unit/io/test_libevreactor.py
Comment thread tests/conftest.py
test_watchers_are_finished calls libev__cleanup(), which stops the shared
libev loop preparer. If a timer test runs later, the stopped preparer means
timers are never scheduled and the test can hang.

Restore _global_loop._shutdown and restart _global_loop._preparer after the
cleanup path runs. Put the restoration in a finally block so the shared loop is
left usable even if the post-cleanup watcher assertions fail.
Python 3.12 removed distutils from the standard library. Some Cython test
helpers import pyximport, which still imports distutils through setuptools'
compatibility shim during collection. Add setuptools to the dev test
dependencies so those tests can collect in cibuildwheel's test environment.
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 is convenient locally but a footgun in CI, where a test may be silently
skipped because a dependency was not installed. The libev unit tests were
effectively not running in any CI configuration.

Add a CASS_DRIVER_NO_SKIP-gated pytest hook in tests/conftest.py that turns
skips into failures (xfail untouched), and enable it in the cibuildwheel
test-commands where the C extensions are mandatory (Linux/macOS). Tests that
genuinely cannot run in the default configuration 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). Add -v
to every pytest invocation and install the compress-lz4 extra so the lz4
tests actually run.

Pass --import-mode=append in the cibuildwheel pytest commands so the installed
compiled wheel takes precedence on sys.path over the in-tree pure-Python
cassandra source during wheel tests. Keep the global pytest addopts unchanged
so local pytest runs keep their normal import behavior.

Windows and PyPy keep no-skip off: the extensions are optional on Windows and
are never built on PyPy (setup.py forces is_pypy to skip libev/cmurmur3/Cython),
so their extension-dependent skips are legitimate. The PyPy override also drops
the compress-lz4 extra (no prebuilt PyPy lz4 wheel), uses cross-shell quoting,
and deselects the known PyPy/Windows/macOS-incompatible tests.
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 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 project path instead so the installed wheel takes precedence,
falling back to the source tree only when the driver is not installed. Also
assert the subprocess return code and include stdout/stderr in the failure
message so future subprocess import/runtime failures are easier to diagnose.
@sylwiaszunejko sylwiaszunejko force-pushed the enable-libev-unittest branch from f453690 to bd81cd9 Compare July 1, 2026 14:15
@sylwiaszunejko sylwiaszunejko self-assigned this Jul 1, 2026
@sylwiaszunejko sylwiaszunejko marked this pull request as ready for review July 1, 2026 14:27

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🧹 Nitpick comments (1)
pyproject.toml (1)

161-180: 📐 Maintainability & Code Quality | 🔵 Trivial | 💤 Low value

&& chaining hides later reactor-suite results

test-command entries are run sequentially with &&, so a failure in the main unit-test run stops the gevent/asyncio/eventlet commands from running in that CI attempt. If you want full signal from one job, run them as separate steps or accumulate exit codes instead.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@pyproject.toml` around lines 161 - 180, The test-command in pyproject.toml
currently relies on sequential execution, so a failure in the main unit-test
invocation prevents the reactor-specific runs from executing. Update the
test-command entries so the gevent, asyncio, and eventlet suites still run and
report results even when an earlier command fails, either by splitting them into
separate CI steps or by using an exit-code accumulation approach; keep the
existing test-command grouping and CASS_DRIVER_NO_SKIP=1 / EVENT_LOOP_MANAGER
setup intact.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Nitpick comments:
In `@pyproject.toml`:
- Around line 161-180: The test-command in pyproject.toml currently relies on
sequential execution, so a failure in the main unit-test invocation prevents the
reactor-specific runs from executing. Update the test-command entries so the
gevent, asyncio, and eventlet suites still run and report results even when an
earlier command fails, either by splitting them into separate CI steps or by
using an exit-code accumulation approach; keep the existing test-command
grouping and CASS_DRIVER_NO_SKIP=1 / EVENT_LOOP_MANAGER setup intact.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro Plus

Run ID: 8a63b946-ca4f-45bf-8cb3-10fdcd36c208

📥 Commits

Reviewing files that changed from the base of the PR and between ca42a54 and bd81cd9.

📒 Files selected for processing (6)
  • .github/workflows/integration-tests.yml
  • cassandra/cluster.py
  • pyproject.toml
  • tests/conftest.py
  • tests/unit/io/test_libevreactor.py
  • tests/unit/io/test_libevreactor_shutdown.py

@dkropachev dkropachev merged commit 34490d3 into scylladb:master Jul 2, 2026
24 checks passed
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

3 participants