Skip to content

Tests(Cronjobs): Adding tests for MonitorLogs and MonitorHoneyPots.#669

Merged
regulartim merged 5 commits intointelowlproject:developfrom
amishhaa:fix-test
Jan 10, 2026
Merged

Tests(Cronjobs): Adding tests for MonitorLogs and MonitorHoneyPots.#669
regulartim merged 5 commits intointelowlproject:developfrom
amishhaa:fix-test

Conversation

@amishhaa
Copy link
Copy Markdown
Contributor

@amishhaa amishhaa commented Jan 2, 2026

Fixes: #653

Description

This PR adds tests for monitor_logs.py and monitor_honeypots.py.

Related issues

#653

Type of change

Please delete options that are not relevant.

  • Bug fix (non-breaking change which fixes an issue).
  • New feature (non-breaking change which adds functionality).

Checklist

  • I have read and understood the rules about how to Contribute to this project.
  • The pull request is for the branch develop.
  • I have added documentation of the new features.
  • Linters (Black, Flake, Isort) gave 0 errors. If you have correctly installed pre-commit, it does these checks and adjustments on your behalf.
  • I have added tests for the feature/bug I solved. All the tests (new and old ones) gave 0 errors.
  • If changes were made to an existing model/serializer/view, the docs were updated and regenerated (check CONTRIBUTE.md).
  • If the GUI has been modified:
    • I have a provided a screenshot of the result in the PR.
    • I have created new frontend tests for the new component or updated existing ones.

Important Rules

  • If you miss to compile the Checklist properly, your PR won't be reviewed by the maintainers.
  • If your changes decrease the overall tests coverage (you will know after the Codecov CI job is done), you should add the required tests to fix the problem
  • Everytime you make changes to the PR and you think the work is done, you should explicitly ask for a review. After being reviewed and received a "change request", you should explicitly ask for a review again once you have made the requested changes.

@amishhaa
Copy link
Copy Markdown
Contributor Author

amishhaa commented Jan 2, 2026

Hey @regulartim ! thank you for pointing me in the right direction in the previous PR. I think this is in a nice shape for a review.

Comment on lines +31 to +35
info_calls = [call[0][0] for call in cronjob.log.info.call_args_list]
warning_calls = [call[0][0] for call in cronjob.log.warning.call_args_list]

self.assertTrue(any("logs available" in msg for msg in info_calls))
self.assertTrue(any("no logs available" in msg for msg in warning_calls))
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.

Wait, you are testing the output of cronjob.log here, but that is a MagicMock right? So this will always succeed! Or am I on the wrong track here?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

I used MagicMock to make a mock object of cronjob.log so we dont actually log something, apart from that the behavior of it depends only on what is being logged by the upper methods that call it, so if your concern was did i mock and pass the log manually, so no that is actually not happening from my understanding. I feel this class can be improved a lot and the tests can be more clear with what they are doing. Thanks for the feedback!

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.

Ah, ok. I think I understand. I think I was confused because I expected that it is tested which honeypot logged what. You verify that some info and warning were logged, but not that Log4pot got the info and Cowrie got the warning. Because this is what happens, right?

Copy link
Copy Markdown
Contributor Author

@amishhaa amishhaa Jan 5, 2026

Choose a reason for hiding this comment

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

@regulartim i think i understand, as we know the name of the honeypot we can actually log the name of it in the assertion, the latest commit actually asserts equal with the number directly, but logging the name is also doable, might make the tests brittle if we do it but also enhances the code from readability point of view because we are clear just by reading whats happening. let me know what you prefer i would assert it accordingly.

Comment on lines +22 to +29
def stat_side_effect():
mock_stat_result = MagicMock()
if stat_side_effect.call_count == 0:
mock_stat_result.st_mtime = recent_time
else:
mock_stat_result.st_mtime = old_time
stat_side_effect.call_count += 1
return mock_stat_result
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.

I don't understand what this does. Could you please explain?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Yes! So if you refer line https://github.com/intelowlproject/GreedyBear/blob/develop/greedybear/cronjobs/monitor_logs.py#L27 we are checking the logs for 4 different pots, so stat_result which contains the time is called four times, so this function returns recent time for the first call and old time for rest. Hence later we assert that the send_message method was only called once with greedy bear as it was the only pot with latest log time.......this can be decoupled into two test functions surely but as already iterated by you that we prefer to follow the test format present, i took reference from test https://github.com/intelowlproject/GreedyBear/blob/develop/tests/greedybear/cronjobs/test_firehol.py where multiple test cases were written in side effect.

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.

I would prefer multiple functions and each method is responsible for testing a specific behavior.

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.

I am sorry, but I still find that function very confusing, although I do understand now why it is here and what it is doing. Would something like this be equivalent?

mock_stat.side_effect = [
       MagicMock(st_mtime=recent_time),
       MagicMock(st_mtime=old_time),
       MagicMock(st_mtime=old_time),
       MagicMock(st_mtime=old_time),
   ]

I think this is more explicit and easier to read and understand. What do you think?

@patch("greedybear.cronjobs.monitor_logs.Path.stat")
@patch("greedybear.cronjobs.monitor_logs.Path.exists")
@patch("greedybear.cronjobs.monitor_logs.send_message")
def test_logs_recent_activity(self, mock_send, mock_exists, mock_stat):
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.

Could you also write a test, where the log was not populated and nothing was sent?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

yes! @regulartim would you prefer the general test design where we write multiple functions and each method is responsible for testing a specific behavior or would you prefer it to how it is currently and all the tests coupled in one single function using side effects?

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.

I would prefer multiple functions and each method is responsible for testing a specific behavior.

@regulartim
Copy link
Copy Markdown
Collaborator

First of all, thanks for your work. But I think there is a lot to be done here. I commented on some parts of the code, but also in the bigger picture your code is not ready in my opinion. Here are a few tips for you:

  • one test case per class is not enough: test edge cases, happy paths and failing paths
  • try to stay consistent with the structure of existing tests
  • use more precise naming: is something is named "...IntegrationTest" it should be an integration test

@gitguardian
Copy link
Copy Markdown

gitguardian bot commented Jan 5, 2026

️✅ There are no secrets present in this pull request anymore.

If these secrets were true positive and are still valid, we highly recommend you to revoke them.
While these secrets were previously flagged, we no longer have a reference to the
specific commits where they were detected. Once a secret has been leaked into a git
repository, you should consider it compromised, even if it was deleted immediately.
Find here more information about risks.


🦉 GitGuardian detects secrets in your source code to help developers and security teams secure the modern development process. You are seeing this because you or someone else with access to this repository has authorized GitGuardian to scan your pull request.

@amishhaa
Copy link
Copy Markdown
Contributor Author

amishhaa commented Jan 5, 2026

hey @regulartim, i have made multiple test cases to reflect the specific behavior that is being tested, also improved the naming. let me know if any further clarification or changes are required. Thank you again for the through feedback!

Copy link
Copy Markdown
Collaborator

@regulartim regulartim left a comment

Choose a reason for hiding this comment

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

Good job! We're getting close! :)

Comment on lines +22 to +29
def stat_side_effect():
mock_stat_result = MagicMock()
if stat_side_effect.call_count == 0:
mock_stat_result.st_mtime = recent_time
else:
mock_stat_result.st_mtime = old_time
stat_side_effect.call_count += 1
return mock_stat_result
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.

I am sorry, but I still find that function very confusing, although I do understand now why it is here and what it is doing. Would something like this be equivalent?

mock_stat.side_effect = [
       MagicMock(st_mtime=recent_time),
       MagicMock(st_mtime=old_time),
       MagicMock(st_mtime=old_time),
       MagicMock(st_mtime=old_time),
   ]

I think this is more explicit and easier to read and understand. What do you think?

@amishhaa
Copy link
Copy Markdown
Contributor Author

amishhaa commented Jan 10, 2026

@regulartim i have made the necessary changes :D, sorry for the delay

@amishhaa
Copy link
Copy Markdown
Contributor Author

amishhaa commented Jan 10, 2026

@regulartim I went through the test file of firehol.py, i believe the tests in that can be decoupled and more edges can be tested also that file no longer strongly follow the format we have established in these test files like seperation of concerns, would you like if i make an issue highlighting some concerns, if you feel its worth working on i would like to take that up.

@regulartim
Copy link
Copy Markdown
Collaborator

@regulartim I went through the test file of firehol.py, i believe the tests in that can be decoupled and more edges can be tested also that file no longer strongly follow the format we have established in these test files like seperation of concerns, would you like if i make an issue highlighting some concerns, if you feel its worth working on i would like to take that up.

Would you please open a separate issue on that?

@regulartim
Copy link
Copy Markdown
Collaborator

@regulartim i have made the necessary changes :D, sorry for the delay

No problem! :)

Copy link
Copy Markdown
Collaborator

@regulartim regulartim left a comment

Choose a reason for hiding this comment

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

Nice! :)

@regulartim regulartim merged commit 5e5678d into intelowlproject:develop Jan 10, 2026
5 checks passed
@regulartim
Copy link
Copy Markdown
Collaborator

For future PRs: when I am asking questions in a review, I would really like to discuss the code with you. Sometimes I'm wrong or I am interested in your rationale.

@amishhaa
Copy link
Copy Markdown
Contributor Author

yes! @regulartim i will open a new issue shortly. yes i would take care in future PRs, thanks again for the thorough review!

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.

2 participants