|
| 1 | +import errno |
| 2 | +import logging |
| 3 | +from pathlib import Path |
1 | 4 | from unittest.mock import AsyncMock, patch |
2 | 5 |
|
3 | 6 | import pytest |
@@ -67,6 +70,41 @@ def test_reclaim_container_zero_usage_writes_nothing(fake_cgroup_root): |
67 | 70 | assert (cgroup / "memory.reclaim").read_text() == "" |
68 | 71 |
|
69 | 72 |
|
| 73 | +def test_reclaim_container_eagain_is_debug_not_warning( |
| 74 | + fake_cgroup_root, caplog, monkeypatch |
| 75 | +): |
| 76 | + # Requesting the full RSS always ends in EAGAIN once nothing more can be |
| 77 | + # paged out — expected on every pause, so it must not log a warning. |
| 78 | + _make_cgroup(fake_cgroup_root, "docker/eag123", 4096) |
| 79 | + |
| 80 | + def _raise_eagain(self, *args, **kwargs): |
| 81 | + raise OSError(errno.EAGAIN, "write could not complete without blocking") |
| 82 | + |
| 83 | + monkeypatch.setattr(Path, "write_text", _raise_eagain) |
| 84 | + with caplog.at_level(logging.DEBUG, logger=memory_pressure.log.name): |
| 85 | + memory_pressure._reclaim_container("eag123") |
| 86 | + |
| 87 | + assert not any(r.levelno == logging.WARNING for r in caplog.records) |
| 88 | + assert any("EAGAIN" in r.getMessage() for r in caplog.records) |
| 89 | + |
| 90 | + |
| 91 | +def test_reclaim_container_other_oserror_warns(fake_cgroup_root, caplog, monkeypatch): |
| 92 | + # A genuine error (not EAGAIN) still surfaces as a warning. |
| 93 | + _make_cgroup(fake_cgroup_root, "docker/err123", 4096) |
| 94 | + |
| 95 | + def _raise_eperm(self, *args, **kwargs): |
| 96 | + raise OSError(errno.EPERM, "operation not permitted") |
| 97 | + |
| 98 | + monkeypatch.setattr(Path, "write_text", _raise_eperm) |
| 99 | + with caplog.at_level(logging.DEBUG, logger=memory_pressure.log.name): |
| 100 | + memory_pressure._reclaim_container("err123") |
| 101 | + |
| 102 | + assert any( |
| 103 | + r.levelno == logging.WARNING and "failed" in r.getMessage() |
| 104 | + for r in caplog.records |
| 105 | + ) |
| 106 | + |
| 107 | + |
70 | 108 | async def test_reclaim_compose_stack_reclaims_each_container(fake_cgroup_root): |
71 | 109 | cgroup_a = _make_cgroup(fake_cgroup_root, "docker/aaa", 100) |
72 | 110 | cgroup_b = _make_cgroup(fake_cgroup_root, "docker/bbb", 200) |
|
0 commit comments