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

Fix _FakeServer to immediately close client connections #524

Open
wants to merge 2 commits into
base: master
Choose a base branch
from

Conversation

cuu508
Copy link
Contributor

@cuu508 cuu508 commented Oct 28, 2024

What do these changes do?

This implements _FakeServer.connection_made() which immediately closes client connections.

Without this, if the SMTP server throws an exception during initialization, Controller.stop() gets stuck indefinitely waiting on active connections.

Note: this only happens in Python 3.12+. Earlier versions of Python allowed wait_closed() to complete regardless of active connections.

With this change the TestFactory testcases can again be enabled for Python 3.12+.

Are there changes in behavior for the user?

No change for the happy path, as _FakeServer is only used if the SMTP server throws exception during initialization.

Related issue number

Fixes: #394

Checklist

  • I think the code is well written
  • Unit tests for the changes exist
  • tox testenvs have been executed in the following environments:
    • Linux (Ubuntu 24.04): {py312}
    • Windows (7, 10): {py36,py37,py38,py39}-{nocov,cov,diffcov}
    • WSL 1.0 (Ubuntu 18.04): {py36,py37,py38,py39}-{nocov,cov,diffcov}, pypy3-{nocov,cov}, qa, docs
    • FreeBSD (12.2, 12.1, 11.4): {py36,pypy3}-{nocov,cov,diffcov}, qa
    • Cygwin: py36-{nocov,cov,diffcov}, qa, docs
  • Documentation reflects the changes
  • Add a news fragment into the NEWS.rst file

Copy link

codecov bot commented Oct 28, 2024

Codecov Report

All modified and coverable lines are covered by tests ✅

Project coverage is 97.77%. Comparing base (f40ac96) to head (96f7a17).
Report is 41 commits behind head on master.

Additional details and impacted files
@@            Coverage Diff             @@
##           master     #524      +/-   ##
==========================================
- Coverage   97.86%   97.77%   -0.10%     
==========================================
  Files          23       23              
  Lines        5707     5696      -11     
  Branches      764      763       -1     
==========================================
- Hits         5585     5569      -16     
- Misses         76       82       +6     
+ Partials       46       45       -1     

☔ View full report in Codecov by Sentry.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • Test Analytics: Detect flaky tests, report on failures, and find test suite problems.

@cuu508
Copy link
Contributor Author

cuu508 commented Mar 4, 2025

To maintainers, I'm happy to provide more information on what this does, or make any changes needed.

@waynew
Copy link
Collaborator

waynew commented Mar 4, 2025

Looks like we had a codecov issue; probably due to no longer skipping the one test 🤔 Or perhaps the added code isn't being hit. I'm guessing this is actually the right way to fix this but it's been a while since I've been in the codebase 🙂

Without this, if the SMTP server throws an exception during
initialization, Controller.stop() gets stuck indefinitely waiting
on active connections.

Note: this only happens in Python 3.12+. Earlier versions of Python
allowed `wait_closed()` to complete regardless of active connections.

With this change the TestFactory testcases can again be enabled for
Python 3.12+.

Fixes: aio-libs#394
@cuu508 cuu508 force-pushed the fix-fakeserver-connection-closing branch from f4782b0 to 06740c4 Compare March 5, 2025 07:34
@cuu508
Copy link
Contributor Author

cuu508 commented Mar 5, 2025

I ran tests like so on my local system:

pytest -p no:warnings

When running it on the master branch, it prints the following coverage report:

---------- coverage: platform linux, python 3.12.3-final-0 -----------
Name                                   Stmts   Miss Branch BrPart  Cover
------------------------------------------------------------------------
aiosmtpd/__init__.py                      15      0      4      1    95%
aiosmtpd/__main__.py                       3      3      2      0     0%
aiosmtpd/controller.py                   221     10     70      3    96%
aiosmtpd/handlers.py                     176      0     66      0   100%
aiosmtpd/lmtp.py                          12      0      4      0   100%
aiosmtpd/main.py                         123      2     38      0    99%
aiosmtpd/proxy_protocol.py               325      0    131      0   100%
aiosmtpd/qa/__init__.py                    0      0      0      0   100%
aiosmtpd/qa/test_0packaging.py            67     11     26      7    81%
aiosmtpd/qa/test_1testsuite.py            46      2     18      2    94%
aiosmtpd/smtp.py                         923      0    380      0   100%
aiosmtpd/testing/__init__.py               0      0      0      0   100%
aiosmtpd/testing/helpers.py               36      0      2      0   100%
aiosmtpd/testing/statuscodes.py          103      0      0      0   100%
aiosmtpd/tests/__init__.py                 0      0      0      0   100%
aiosmtpd/tests/certs/__init__.py           0      0      0      0   100%
aiosmtpd/tests/conftest.py               160     32     56      3    79%
aiosmtpd/tests/test_handlers.py          493     10    100      6    97%
aiosmtpd/tests/test_lmtp.py               33      0      2      0   100%
aiosmtpd/tests/test_main.py              246     40     70      2    83%
aiosmtpd/tests/test_misc.py               35      3      6      1    90%
aiosmtpd/tests/test_proxyprotocol.py     666      9    142      8    97%
aiosmtpd/tests/test_server.py            409     48    101      5    88%
aiosmtpd/tests/test_smtp.py             1249     11    237      3    99%
aiosmtpd/tests/test_smtps.py              34      0      6      0   100%
aiosmtpd/tests/test_smtpsmuggling.py      60      9     18      8    78%
aiosmtpd/tests/test_starttls.py          262      0     32      0   100%
------------------------------------------------------------------------
TOTAL                                   5697    190   1511     49    96%

On the PR branch it prints:

---------- coverage: platform linux, python 3.12.3-final-0 -----------
Name                                   Stmts   Miss Branch BrPart  Cover
------------------------------------------------------------------------
aiosmtpd/__init__.py                      15      0      4      1    95%
aiosmtpd/__main__.py                       3      3      2      0     0%
aiosmtpd/controller.py                   223      3     70      0    99%
aiosmtpd/handlers.py                     176      0     66      0   100%
aiosmtpd/lmtp.py                          12      0      4      0   100%
aiosmtpd/main.py                         123      2     38      0    99%
aiosmtpd/proxy_protocol.py               325      0    131      0   100%
aiosmtpd/qa/__init__.py                    0      0      0      0   100%
aiosmtpd/qa/test_0packaging.py            67     11     26      7    81%
aiosmtpd/qa/test_1testsuite.py            46      2     18      2    94%
aiosmtpd/smtp.py                         923      0    380      0   100%
aiosmtpd/testing/__init__.py               0      0      0      0   100%
aiosmtpd/testing/helpers.py               36      0      2      0   100%
aiosmtpd/testing/statuscodes.py          103      0      0      0   100%
aiosmtpd/tests/__init__.py                 0      0      0      0   100%
aiosmtpd/tests/certs/__init__.py           0      0      0      0   100%
aiosmtpd/tests/conftest.py               160     21     56      5    86%
aiosmtpd/tests/test_handlers.py          493     10    100      6    97%
aiosmtpd/tests/test_lmtp.py               33      0      2      0   100%
aiosmtpd/tests/test_main.py              246     40     70      2    83%
aiosmtpd/tests/test_misc.py               35      3      6      1    90%
aiosmtpd/tests/test_proxyprotocol.py     666      9    142      8    97%
aiosmtpd/tests/test_server.py            408      3     98      5    98%
aiosmtpd/tests/test_smtp.py             1249     11    237      3    99%
aiosmtpd/tests/test_smtps.py              34      0      6      0   100%
aiosmtpd/tests/test_smtpsmuggling.py      60      9     18      8    78%
aiosmtpd/tests/test_starttls.py          262      0     32      0   100%
------------------------------------------------------------------------
TOTAL                                   5698    127   1508     48    97%

The coverage increased--which makes sense as the PR re-enables some previously disabled tests.

I'm not familiar with aiosmtpd build and CI infrastructure, and am not sure why codecov reports different results. Perhaps it's using code coverage from a test run with a different python interpreter version? (my local system has Python 3.12)

@cuu508
Copy link
Contributor Author

cuu508 commented Mar 5, 2025

I thought I found unused code (_FakeServer._cb_client_connected) and removed it to increase coverage. But really I have no idea where the coverage discrepancy comes from, and will hold off from making more changes.

@waynew
Copy link
Collaborator

waynew commented Mar 5, 2025

That's super weird. I'm not familiar with codecov either -- I'm a wee bit confused looking at the coverage report. https://app.codecov.io/gh/aio-libs/aiosmtpd/pull/524/indirect-changes seems to suggest that there are some inderect changes as a result of this PR. If you run with --cov-report term-missing does it show different lines (dis)appearing? 🤔

@cuu508
Copy link
Contributor Author

cuu508 commented Mar 10, 2025

FWIW these indirect coverage changes are not due to code changes in this PR. There are similar coverage changes in previous PRs that did get merged, for example: https://app.codecov.io/gh/aio-libs/aiosmtpd/pull/540/indirect-changes

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.

Some tests in aiosmtpd/tests/test_server.py hang with python 3.12
2 participants