Skip to content

test: add _check_memory_health missing and incomplete data tests#1212

Merged
muddlebee merged 4 commits intoTracer-Cloud:mainfrom
RajGajjar-01:test/add-memory-health-tests
May 3, 2026
Merged

test: add _check_memory_health missing and incomplete data tests#1212
muddlebee merged 4 commits intoTracer-Cloud:mainfrom
RajGajjar-01:test/add-memory-health-tests

Conversation

@RajGajjar-01
Copy link
Copy Markdown
Contributor

Fixes #1125

Added 3 tests for _check_memory_health() covering the missing file, incomplete data, and OSError branches. Used monkeypatch to avoid touching the real /proc/meminfo filesystem.

Demo/Screenshot for feature changes and bug fixes -

image

Code Understanding and AI Usage

Did you use AI assistance (ChatGPT, Claude, Copilot, etc.) to write any part of this code?

  • Yes, I used AI assistance

If you used AI assistance:

  • I have reviewed every single line of the AI-generated code
  • I can explain the purpose and logic of each function/component I added
  • I have tested edge cases and understand how the code handles them
  • I have modified the AI output to follow this project's coding standards and conventions

Explain your implementation approach:

  • _check_memory_health() has 3 early-return branches that needed test coverage.

  • For each test I used monkeypatch to replace Path.exists() and Path.read_text() with fakes so the tests never touch the real /proc/meminfo filesystem.

  • Test 1 fakes exists() returning False to hit the missing file branch.

  • Test 2 fakes exists() returning True and read_text() returning content without MemAvailable to hit the incomplete data branch.

  • Test 3 fakes read_text() raising OSError to hit the read error branch.

  • All 3 assert status == "missing" with a useful detail message.


    Checklist before requesting a review

    • I have added proper PR title and linked to the issue
    • I have performed a self-review of my code
    • I can explain the purpose of every function, class, and logic block I added
    • I understand why my changes work and have tested them thoroughly
    • I have considered potential edge cases and how my code handles them
    • If it is a core feature, I have added thorough tests
    • My code follows the project's style guidelines and conventions

@greptile-apps
Copy link
Copy Markdown
Contributor

greptile-apps Bot commented May 2, 2026

Greptile Summary

This PR adds three unit tests for _check_memory_health() covering the missing-file, incomplete-data, and OSError branches, using monkeypatch to avoid touching the real /proc/meminfo. The test logic is sound and all three branches are correctly exercised, but a handful of ruff formatting violations (missing space after comma, trailing-whitespace blank line, no EOF newline) will cause make format-check to fail in CI.

Confidence Score: 4/5

Safe to merge after fixing the ruff formatting violations that will break CI.

All three new tests are logically correct and cover the intended branches. Only P2 style issues are present (formatting violations that will fail make format-check).

tests/app/remote/test_server.py — ruff formatting fixes needed before CI will pass.

Important Files Changed

Filename Overview
tests/app/remote/test_server.py Adds 3 new tests for the _check_memory_health missing-file, incomplete-data, and OSError branches. Logic is correct; minor ruff formatting violations (missing space after comma, trailing-whitespace blank line, no EOF newline) will fail make format-check.

Flowchart

%%{init: {'theme': 'neutral'}}%%
flowchart TD
    A["_check_memory_health()"] --> B{"Path('/proc/meminfo').exists()"}
    B -- "False\n(test 1 covers)" --> C["return DeepHealthCheck\nstatus='missing'\ndetail='/proc/meminfo unavailable...'"]
    B -- "True" --> D["read_text(encoding='utf-8')"]
    D -- "OSError\n(test 3 covers)" --> E["return DeepHealthCheck\nstatus='missing'\ndetail='Unable to read meminfo: ...'"]
    D -- "success" --> F{"MemTotal and MemAvailable\npresent in values?"}
    F -- "No\n(test 2 covers)" --> G["return DeepHealthCheck\nstatus='missing'\ndetail='Incomplete /proc/meminfo data.'"]
    F -- "Yes" --> H["Compute used_pct"]
    H --> I{"used_pct < 90?"}
    I -- "Yes" --> J["return DeepHealthCheck\nstatus='passed'"]
    I -- "No" --> K["return DeepHealthCheck\nstatus='warn'"]
Loading

Reviews (1): Last reviewed commit: "test: add _check_memory_health missing a..." | Re-trigger Greptile

Comment thread tests/app/remote/test_server.py Outdated
assert isinstance(result, DeepHealthCheck)
assert result.name == "Memory"
assert result.status == "missing"
assert "Unable to read meminfo:" in result.detail No newline at end of file
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

P2 Missing newline at end of file

The file has no trailing newline. This will cause ruff format --check (and thus make format-check) to fail in CI.

Context Used: Code style and conventions (source)

Comment thread tests/app/remote/test_server.py Outdated
Comment on lines +396 to +399
def fake_read_text(self, **kwargs):
raise OSError("permission denied")

monkeypatch.setattr(Path, "read_text",fake_read_text)
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

P2 Formatting issues — ruff will reject

Two ruff-enforced style violations in this function: a missing space after the comma in the monkeypatch.setattr call and a trailing-whitespace-only blank line inside fake_read_text. Running make format-check will fail on both.

Suggested change
def fake_read_text(self, **kwargs):
raise OSError("permission denied")
monkeypatch.setattr(Path, "read_text",fake_read_text)
def fake_read_text(self, **kwargs):
raise OSError("permission denied")
monkeypatch.setattr(Path, "read_text", fake_read_text)

Context Used: Code style and conventions (source)

Comment thread tests/app/remote/test_server.py Outdated
Comment on lines +369 to +371
monkeypatch.setattr(Path, "exists", lambda self: False)
result = _check_memory_health()

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

P2 Broad Path class patch may bleed into unrelated code

monkeypatch.setattr(Path, "exists", lambda self: False) replaces the method on the class itself, so every Path instance created anywhere during the test call-graph (e.g. inside imports, pytest internals, or future changes to _check_memory_health) will be affected. A narrower patch targeting only the specific path object — or patching at the module level with monkeypatch.setattr("app.remote.server.Path", ...) — limits the blast radius and makes intent clearer. The same applies to the read_text patches in the other two tests.

@muddlebee
Copy link
Copy Markdown
Collaborator

@RajGajjar-01 CI is still failing.

@muddlebee
Copy link
Copy Markdown
Collaborator

image

formatting issue it seems

Copy link
Copy Markdown
Collaborator

@yashksaini-coder yashksaini-coder left a comment

Choose a reason for hiding this comment

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

Thanks for picking this up, the test scope maps cleanly to issue #1125 and the three branches you covered are exactly the ones that needed coverage. Two things to sort before this can land, plus one design note.

Blocking — CI will fail: I ran make lint and make format-check locally and got 7 lint errors (I001 import ordering, 5x ARG005 unused lambda args, W293 trailing whitespace) plus 3 format-check failures. The fastest path is make format && ruff check tests/ --fix from the repo root in your venv, that should auto-fix the trailing comma, blank-line whitespace, import sort, and long-line split. The ARG005 errors are trickier because the lambda signatures are correct (they replace a method, so self is required); see the inline comment below for two clean ways to address them.

One design note: greptile's broad-Path-patch comment is worth taking seriously. I left a concrete suggestion inline.

Heads up — greptile's "missing newline at end of file" comment looks stale; your follow-up commit 66f45d83 did add the trailing newline, and I confirmed locally with od -c. So you can mark that one resolved.

Comment thread tests/app/remote/test_server.py Outdated
_lifespan,
investigate,
investigate_stream,
_check_memory_health
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

Quick formatting one. Two ruff issues here:

  1. I001 — the import block is sorted alphabetically by name; _check_memory_health should be next to _check_disk_health, _imds_get, _imds_token, _lifespan (the underscore-prefixed group), not after investigate_stream.
  2. Trailing comma needed (_check_memory_health,) per ruff's format rules.

Both are auto-fixable with make format && ruff check tests/ --fix. Worth running both before pushing, there are 7 ruff errors in this file as-is and CI will reject them.

Comment thread tests/app/remote/test_server.py Outdated
def test_check_memory_health_returns_missing_when_proc_file_absent(
monkeypatch: pytest.MonkeyPatch,
) -> None:
monkeypatch.setattr(remote_server.Path, "exists", lambda self: False)
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

Reinforcing greptile's "broad Path class patch" concern with a concrete fix. The issue is that remote_server.Path is the same object as pathlib.Path, Python imports are references, not copies, so monkeypatch.setattr(remote_server.Path, "exists", ...) mutates the global Path class for the test's duration. Anything that creates a Path during your test (pytest internals, plugins, transitive imports inside _check_memory_health's call graph) sees the fake.

A cleaner pattern that scopes to just the module under test:

class _FakeMeminfoPath:
    def __init__(self, *_args, **_kwargs): ...
    def exists(self) -> bool: return False

monkeypatch.setattr("app.remote.server.Path", _FakeMeminfoPath)

This replaces the Path name in the app.remote.server namespace only. Anywhere else still gets the real Path. Bonus: the named class lets you name the fake methods clearly per-test (_FakeMissingPath, _FakeIncompletePath, _FakeOsErrorPath) and you don't need lambdas, which sidesteps the ARG005 lint issue entirely.

Comment thread tests/app/remote/test_server.py Outdated
monkeypatch: pytest.MonkeyPatch,
) -> None:
monkeypatch.setattr(remote_server.Path, "exists", lambda self: True)
monkeypatch.setattr(remote_server.Path, "read_text", lambda self, **kwargs: "MemTotal: 16384 kB\n")
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

The lambda self: ... and lambda self, **kwargs: ... patterns are technically correct (you need a self slot when the lambda is bound as a method), but ruff's ARG005 flags 5 unused-argument errors across these tests. Two clean ways to silence them without disabling the rule:

  1. Switch to the named-class approach from the comment above, replaces Path wholesale, no lambdas needed.
  2. If you'd rather keep the patch shape, prefix unused params with underscore: lambda _self: ... and lambda _self, **_kwargs: .... ruff treats _-prefixed names as intentionally unused.

Also on this line specifically: it's 107 chars, longer than the project's 100-char limit, so ruff format will want to split it across multiple lines anyway. make format will do that automatically.

@yashksaini-coder
Copy link
Copy Markdown
Collaborator

@RajGajjar-01 CI is failing, and resolve git merge conflicts as well. Fail to respond back will result in issue handover and PR close

@RajGajjar-01 RajGajjar-01 force-pushed the test/add-memory-health-tests branch from 6e82131 to 7299a90 Compare May 2, 2026 19:09
@RajGajjar-01
Copy link
Copy Markdown
Contributor Author

Hey @yashksaini-coder I have made changes and pushed those changes as per you said.

Thank you for guiding.

) -> None:

class _FakeMeminfoPath:
def __init__(self, *_args, **_kwargs) -> None: ...
) -> None:

class _FakeIncompletePath:
def __init__(self, *_args: object, **_kwargs: object) -> None: ...
monkeypatch: pytest.MonkeyPatch,
) -> None:
class _FakeOsErrorPath:
def __init__(self, *_args: object, **_kwargs: object) -> None: ...
@RajGajjar-01
Copy link
Copy Markdown
Contributor Author

@yashksaini-coder CI is now passing and conflicts are resolved. Could you please take another look?

@RajGajjar-01
Copy link
Copy Markdown
Contributor Author

RajGajjar-01 commented May 3, 2026

Hey @yashksaini-coder should I resolve the issue raised by codeql ?
Because in the comments you have provided so I followed that

class _FakeMeminfoPath:
    def __init__(self, *_args, **_kwargs): ...
    def exists(self) -> bool: return False

monkeypatch.setattr("app.remote.server.Path", _FakeMeminfoPath)

@muddlebee
Copy link
Copy Markdown
Collaborator

@RajGajjar-01 yes needs to be fixed

@muddlebee
Copy link
Copy Markdown
Collaborator

anyhow merging this for velocity @RajGajjar-01 take care of the greptile and codeql reviews next time. :)

@muddlebee muddlebee merged commit 8b9e38a into Tracer-Cloud:main May 3, 2026
10 checks passed
@github-actions
Copy link
Copy Markdown
Contributor

github-actions Bot commented May 3, 2026

LGTM → Merged. @RajGajjar-01, your work is in. Every commit counts — thank you for this one.


👋 Join us on Discord - OpenSRE : hang out, contribute, or hunt for features and issues. Everyone's welcome.

@RajGajjar-01
Copy link
Copy Markdown
Contributor Author

anyhow merging this for velocity @RajGajjar-01 take care of the greptile and codeql reviews next time. :)

Yes from further I will definitely take care thank you.

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.

Add _check_memory_health() missing and incomplete data tests

4 participants