Skip to content

Conversation

@rm-hull
Copy link
Owner

@rm-hull rm-hull commented Nov 4, 2025

Introduces comprehensive unit tests for the DNSDispatcher to verify core functionality like blocking, caching, and upstream resolution.

  • Tests successful lookups.
  • Verifies NXDOMAIN responses for blocked domains.
  • Checks cache hit and miss behavior.

The github.com/stretchr/testify dependency was added to enable mocking DNS responses and provide robust assertions.

Introduces comprehensive unit tests for the `DNSDispatcher` to
verify core functionality like blocking, caching, and upstream
resolution.

*   Tests successful lookups.
*   Verifies NXDOMAIN responses for blocked domains.
*   Checks cache hit and miss behavior.

The `github.com/stretchr/testify` dependency was added to enable
mocking DNS responses and provide robust assertions.
@gemini-code-assist
Copy link
Contributor

Summary of Changes

Hello @rm-hull, I'm Gemini Code Assist1! I'm currently reviewing this pull request and will post my feedback shortly. In the meantime, here's a summary to help you and other reviewers quickly get up to speed!

This pull request significantly improves the test coverage for the DNSDispatcher component. It introduces a dedicated suite of unit tests to validate critical aspects of its operation, such as how it processes DNS queries, enforces domain blocking, and manages its internal cache. These additions aim to bolster the reliability and ensure the correct behavior of the DNS resolution logic within the system.

Highlights

  • New Unit Tests for DNS Dispatcher: Comprehensive unit tests have been introduced for the DNSDispatcher to verify its core functionalities, including blocking, caching, and upstream resolution.
  • Test Scenarios Covered: The new tests cover successful DNS lookups, verification of NXDOMAIN responses for blocked domains, handling of multiple questions in a single request, and detailed checks for cache hit and miss behavior.
  • New Testing Dependency: The github.com/stretchr/testify library has been added as a dependency to facilitate mocking DNS responses and provide robust assertion capabilities for the tests.
Using Gemini Code Assist

The full guide for Gemini Code Assist can be found on our documentation page, here are some quick tips.

Invoking Gemini

You can request assistance from Gemini at any point by creating a comment using either /gemini <command> or @gemini-code-assist <command>. Below is a summary of the supported commands on the current page.

Feature Command Description
Code Review /gemini review Performs a code review for the current pull request in its current state.
Pull Request Summary /gemini summary Provides a summary of the current pull request in its current state.
Comment @gemini-code-assist Responds in comments when explicitly tagged, both in pull request comments and review comments.
Help /gemini help Displays a list of available commands.

Customization

To customize Gemini Code Assist for GitHub experience, repository maintainers can create a configuration file and/or provide a custom code review style guide (such as PEP-8 for Python) by creating and adding files to a .gemini/ folder in the base of the repository. Detailed instructions can be found here.

Limitations & Feedback

Gemini Code Assist may make mistakes. Please leave feedback on any instances where its feedback is incorrect or counter productive. You can react with 👍 and 👎 on @gemini-code-assist comments. If you're interested in giving your feedback about your experience with Gemini Code Assist for Github and other Google products, sign up here.

You can also get AI-powered code generation, chat, as well as code reviews directly in the IDE at no cost with the Gemini Code Assist IDE Extension.

Footnotes

  1. Review the Privacy Notices, Generative AI Prohibited Use Policy, Terms of Service, and learn how to configure Gemini Code Assist in GitHub here. Gemini can make mistakes, so double check it and use code with caution.

@github-actions
Copy link

github-actions bot commented Nov 4, 2025

TestsPassed ✅SkippedFailed
JUnit Test Report4 ran4 passed0 skipped0 failed
TestResult
JUnit Test Report
dot-block/internal.TestDNSDispatcher_HandleDNSRequest_Allowed✅ passed
dot-block/internal.TestDNSDispatcher_HandleDNSRequest_Blocked✅ passed
dot-block/internal.TestDNSDispatcher_HandleDNSRequest_MultipleQuestions✅ passed
dot-block/internal.TestDNSDispatcher_HandleDNSRequest_CacheHit✅ passed

Copy link
Contributor

@gemini-code-assist gemini-code-assist bot left a comment

Choose a reason for hiding this comment

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

Code Review

This pull request introduces valuable unit tests for the DNSDispatcher, covering core functionality like allowed/blocked domains and caching. The tests are well-structured, but I've identified a critical issue in TestDNSDispatcher_HandleDNSRequest_MultipleQuestions. The test's assertions are incorrect for the current implementation and, more importantly, they highlight a significant flaw in how the dispatcher handles requests with multiple questions. I've provided a fix for the test and strongly recommend addressing the underlying bug in the production code. I've also included a couple of medium-severity suggestions to improve test maintainability and isolation.

Comment on lines +56 to +57
var blockList = NewBlockList([]string{"ads.0xbt.net"}, 0.0001)
var upstream = "8.8.8.8:53"
Copy link
Contributor

Choose a reason for hiding this comment

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

medium

Using global variables for test setup can introduce side effects between tests, especially if tests are run in parallel in the future (t.Parallel()). It's a best practice to define these variables within each test function or a test-specific setup function to ensure complete test isolation.

Comment on lines 59 to 93
func TestDNSDispatcher_HandleDNSRequest_Allowed(t *testing.T) {

dispatcher := NewDNSDispatcher(upstream, blockList, 100)

req := new(dns.Msg)
req.SetQuestion("google.com.", dns.TypeA)

writer := new(MockResponseWriter)
writer.On("WriteMsg", mock.Anything).Return(nil)

// Call the method under test
dispatcher.HandleDNSRequest(writer, req)

// Assert that the response writer was called with a non-nil message
assert.NotNil(t, writer.WrittenMsg)
assert.Equal(t, dns.RcodeSuccess, writer.WrittenMsg.Rcode)
}

func TestDNSDispatcher_HandleDNSRequest_Blocked(t *testing.T) {

dispatcher := NewDNSDispatcher(upstream, blockList, 100)

req := new(dns.Msg)
req.SetQuestion("ads.0xbt.net.", dns.TypeA)

writer := new(MockResponseWriter)
writer.On("WriteMsg", mock.Anything).Return(nil)

// Call the method under test
dispatcher.HandleDNSRequest(writer, req)

// Assert that the response has an NXDOMAIN Rcode
assert.NotNil(t, writer.WrittenMsg)
assert.Equal(t, dns.RcodeNameError, writer.WrittenMsg.Rcode)
}
Copy link
Contributor

Choose a reason for hiding this comment

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

medium

The tests TestDNSDispatcher_HandleDNSRequest_Allowed and TestDNSDispatcher_HandleDNSRequest_Blocked share a lot of boilerplate code. To improve maintainability and reduce duplication, consider refactoring them into a single table-driven test. This would make it easier to add more test cases in the future.

The `NewDNSDispatcher` function is updated to return an error,
propagating registration failures for Prometheus collectors.

A new helper function `shouldRegister` handles collector registration,
ignoring `AlreadyRegisteredError` but returning other errors.

This change ensures that dispatcher creation fails if essential
metrics cannot be properly initialized in `internal/dns.go`.
Corresponding error handling is added in `internal/app.go` and
tests in `internal/dns_test.go` are updated.
This file standardizes formatting rules across the repository.

Key settings include:
*   Enforcing spaces for most files (4 spaces for Python,
    2 for YAML/JSON).
*   Standardizing `lf` line endings and `utf-8` charset.
*   Setting specific line length limits for Python code (120)
    and docstrings (72).
*   Requiring tabs for `Makefile` and **.go** files.
Set up continuous integration using GitHub Actions.

The workflow handles:
* Building, testing (Go 1.25), linting, and coverage reporting.
* Building and pushing the Docker image to GHCR on `main` or tags.

Also configure Dependabot to manage dependencies for Go modules,
GitHub Actions, and Docker base images.
Align expectations in the multiple questions DNS test with the
current implementation bug.

If a DNS request contains multiple questions and one query is
blocked, the system currently returns `NXDOMAIN` instead of
handling the valid queries.

This test is updated to reflect that temporary faulty behavior.
The true fix is tracked elsewhere.
@coveralls
Copy link

Pull Request Test Coverage Report for Build 19086843140

Details

  • 9 of 17 (52.94%) changed or added relevant lines in 2 files are covered.
  • No unchanged relevant lines lost coverage.
  • Overall coverage increased (+43.8%) to 43.75%

Changes Missing Coverage Covered Lines Changed/Added Lines %
internal/app.go 0 4 0.0%
internal/dns.go 9 13 69.23%
Totals Coverage Status
Change from base Build 19086728070: 43.8%
Covered Lines: 175
Relevant Lines: 400

💛 - Coveralls

@rm-hull rm-hull merged commit 606b6a5 into main Nov 5, 2025
3 checks passed
@rm-hull rm-hull deleted the testing/integration branch November 5, 2025 00:16
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.

3 participants