Skip to content

test: cover backend helpers#30

Closed
kunal-9090 wants to merge 0 commit into
PranavAgarkar07:mainfrom
kunal-9090:codex/issue-14-backend-tests
Closed

test: cover backend helpers#30
kunal-9090 wants to merge 0 commit into
PranavAgarkar07:mainfrom
kunal-9090:codex/issue-14-backend-tests

Conversation

@kunal-9090

@kunal-9090 kunal-9090 commented May 28, 2026

Copy link
Copy Markdown
Contributor

Summary

  • add unit tests for transfer permission defaults, device rules, and blocked extensions
  • add port manager tests for busy-port skipping and exhaustion behavior
  • add server helper tests for token middleware, auto-renaming, and token format

Tests

  • Not run locally: Go tooling is not available on this machine (go/gofmt not on PATH).

Closes #14

Summary by CodeRabbit

  • New Features

    • Server now supports manifest processing to map file metadata for uploads.
  • Tests

    • Added extensive test coverage for transfer defaults, device trust/block rules, case-insensitive extension blocking, port discovery behavior, and server behavior including token validation, CORS, file upload handling, file-writing workers, event emission, and related utilities.

@coderabbitai

coderabbitai Bot commented May 28, 2026

Copy link
Copy Markdown

Review Change Stack

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: 0735e28f-2c6b-493c-b15f-d8d744631f1b

📥 Commits

Reviewing files that changed from the base of the PR and between 2d9b565 and 09c0e8d.

📒 Files selected for processing (4)
  • beamsync/permissions_test.go
  • beamsync/port_manager_test.go
  • beamsync/server.go
  • beamsync/server_test.go
🚧 Files skipped from review as they are similar to previous changes (3)
  • beamsync/permissions_test.go
  • beamsync/server.go
  • beamsync/server_test.go

📝 Walkthrough

Walkthrough

Adds tests for permissions and port management, a processManifest helper in server.go, and extensive server unit and HTTP integration tests that cover token middleware, CORS, file I/O workers, upload handling, and related helpers.

Changes

Test Coverage for Permissions, Port Management, and Server Components

Layer / File(s) Summary
Permissions and Device Rules Tests
beamsync/permissions_test.go
DefaultTransferSettings() defaults to AskFirst with unlimited max size and empty lists; device rules match by exact IP with friendly-name lookup; blocked extensions matched case-insensitively.
Port Availability Detection Tests
beamsync/port_manager_test.go
FindAvailablePort skips occupied ports and reports exhaustion with port==0 and listener==nil when no ports available.
Manifest parsing implementation
beamsync/server.go
Adds manifestEntry and processManifest(io.Reader) to decode JSON manifest arrays into map[string]int64; /upload handler now calls this helper.
Server utilities and unit tests
beamsync/server_test.go
Unit tests for token middleware, autoRenamePath, generateToken uniqueness/format, setCORSHeaders, copyChunked, safeEmit, processManifest cases, writeFileToDisk behavior and progress/events, and startWriteWorkers job processing.
HTTP integration and upload endpoint tests
beamsync/server_test.go
Starts real server for tests: verifies GET / includes session token, POST /heartbeat emits device_connected, POST /upload without file returns 400, multipart upload with manifest+file saves file and updates /stats.
Test helpers for events and test server lifecycle
beamsync/server_test.go
Adds eventSeen, waitForEvent, startServerForTest (temp upload dir, free port, event callback), and freePort helpers used across integration tests.

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~20 minutes

Suggested labels

level:advanced

Poem

🐇
I hopped through tests with whiskers bright,
Tokens, ports, and manifests in sight.
Files saved snug, events in a row,
CI hums softly — off I go!

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 11.11% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title 'test: cover backend helpers' is concise and clearly indicates the main change—adding test coverage for backend helper functions.
Linked Issues check ✅ Passed The PR successfully implements comprehensive unit tests for all three required modules (server, permissions, port manager) covering the primary objectives from issue #14.
Out of Scope Changes check ✅ Passed All changes are scoped to test files (permissions_test.go, port_manager_test.go, server_test.go) and a minor refactor (processManifest helper in server.go) directly supporting test coverage objectives.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests

Warning

There were issues while running some tools. Please review the errors and either fix the tool's configuration or disable the tool if it's a critical failure.

🔧 golangci-lint (2.12.2)

level=error msg="[linters_context] typechecking error: pattern ./...: directory prefix . does not contain main module or its selected dependencies"


Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

@PranavAgarkar07

Copy link
Copy Markdown
Owner

Thanks for the contribution. The permissions and port manager tests are well-written and all pass.

I checked the test coverage against the issue requirements. The PR covers most of the permissions and port manager deliverables, but the server tests are missing the bulk of what issue #14 asks for. Specifically, these server areas still need tests:

  • StartServer lifecycle (starts on available port, returns valid token, clean shutdown)
  • The / route returns 200 with HTML content
  • /heartbeat updates lastHeartbeat
  • /stats returns TransferStats JSON when authorized
  • /upload without file returns 400
  • /upload with file saves to disk and emits events
  • copyChunked verifies byte count and data integrity
  • safeEmit does not panic on nil callback
  • writeFileToDisk with mock state/history/stats
  • startWriteWorkers handles multiple jobs and errors
  • ProcessManifest handles valid JSON, empty manifest, and malformed JSON
  • CORS headers check Allow-Origin, Allow-Methods, Allow-Headers

These are all listed in the issue under the Server Tests section. Without them, the server coverage is roughly 3% when the target is 60%.

Could you take a pass at adding those? The existing test files in the PR show the right patterns to follow.

@PranavAgarkar07 PranavAgarkar07 added gssoc:approved Approved for GSSoC contributions level:intermediate Intermediate level task type:testing Testing labels May 30, 2026
@kunal-9090

Copy link
Copy Markdown
Contributor Author

Thanks for the detailed review. I took another pass at the server-side coverage and pushed commit 2d9b565 to this PR.

Added coverage for:

  • StartServer lifecycle, root page HTML/token rendering, heartbeat, and clean shutdown
  • upload bad-request path when no file is provided
  • upload success path that saves a multipart file and emits completion events
  • copyChunked byte count and data integrity
  • safeEmit nil callback and callback panic handling
  • writeFileToDisk event/file write behavior
  • startWriteWorkers processing, including a create-error job that should not break the worker pool
  • manifest parsing cases for valid, empty, and malformed JSON
  • CORS header assertions and token collision sample coverage

Validation: git diff --check passes. I still cannot run go test ./beamsync/ in this local environment because the Go CLI is not installed, and Docker Desktop's daemon is not running for containerized Go validation. The GitHub workflow should be the source of truth for the actual Go test run.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Actionable comments posted: 3

🧹 Nitpick comments (2)
beamsync/server.go (1)

287-298: ⚡ Quick win

processManifest/manifestEntry duplicate the inline upload parsing and aren't wired into production.

The /upload handler still decodes the manifest with an inline anonymous struct (lines 665-678) using the same logic. As-is, processManifest and manifestEntry are only exercised by tests and add no production value while diverging from the real parsing path. Reuse the helper in the handler so the tests actually cover the code path that runs in production.

♻️ Wire the handler to the new helper
 			if formName == "beam_manifest" && filename == "" {
-				var manifest []struct {
-					Name string `json:"name"`
-					Size int64  `json:"size"`
-				}
-				if err := json.NewDecoder(part).Decode(&manifest); err == nil {
-					for _, f := range manifest {
-						fileSizes[f.Name] = f.Size
-					}
-					fmt.Printf("📦 Manifest received: %d files registered\n", len(manifest))
-				}
+				if parsed, err := processManifest(part); err == nil {
+					for name, size := range parsed {
+						fileSizes[name] = size
+					}
+					fmt.Printf("📦 Manifest received: %d files registered\n", len(parsed))
+				}
 				part.Close()
 				continue
 			}
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@beamsync/server.go` around lines 287 - 298, The upload handler currently
decodes the manifest using an inline anonymous struct instead of reusing
processManifest/manifestEntry; update the /upload handler to call
processManifest(r) (or pass the request body reader) and use the returned
map[string]int64 instead of re-parsing with the inline struct, preserving the
existing error handling and validation logic; remove or replace the inline
anonymous manifest parsing so tests exercise processManifest/manifestEntry and
ensure any variable names (e.g., fileSizes) and error paths in the handler are
adjusted to use the helper's output.
beamsync/server_test.go (1)

256-258: 💤 Low value

Redundant second Shutdown().

server.Shutdown() here duplicates the defer server.Shutdown() on line 222. The double call is harmless but adds no coverage; drop it (or remove the defer) to avoid confusion.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@beamsync/server_test.go` around lines 256 - 258, The test currently calls
server.Shutdown() twice (once via defer server.Shutdown() and again explicitly),
so remove the redundant explicit call by deleting the final if err :=
server.Shutdown(); ... block; keep the deferred defer server.Shutdown() to
ensure cleanup, or alternatively remove the defer and keep the explicit
call—make sure only one server.Shutdown() invocation remains to avoid confusion.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@beamsync/permissions_test.go`:
- Around line 5-17: The test TestDefaultTransferSettings currently asserts Mode,
MaxFileSizeMB, and BlockedExtensions but omits verifying TrustedDevices and
BlockedDevices; update TestDefaultTransferSettings to call
DefaultTransferSettings() and add assertions that len(settings.TrustedDevices)
== 0 and len(settings.BlockedDevices) == 0 (ensuring the default returns empty
slices), using t.Fatalf with a clear message similar to the existing checks.

In `@beamsync/port_manager_test.go`:
- Around line 8-25: The test TestFindAvailablePortSkipsBusyPorts creates a busy
listener on "127.0.0.1:0" while FindAvailablePort binds to ":port" (all
interfaces), so the busy socket doesn't actually block the binding; update the
test to bind the busy listener to the same address family used by
FindAvailablePort (e.g., use "0.0.0.0:0" or ":" instead of "127.0.0.1:0") so
busy.Addr().(*net.TCPAddr).Port yields a port that FindAvailablePort will
attempt to bind and thus correctly verifies port-skipping behavior for
FindAvailablePort.
- Around line 27-46: The test TestFindAvailablePortReportsExhaustion creates a
listener on "127.0.0.1:0" while FindAvailablePort binds to ":port", so the
addresses differ and the busy socket doesn't block the tested bind; change the
test's busy listener to bind to the same address family as FindAvailablePort
(use ":0" / all interfaces) so the busy port actually prevents FindAvailablePort
from acquiring the same port, keep capturing startPort from
busy.Addr().(*net.TCPAddr).Port and leave the rest of the test logic (calls to
FindAvailablePort, checks for error/zero port/nil listener) unchanged.

---

Nitpick comments:
In `@beamsync/server_test.go`:
- Around line 256-258: The test currently calls server.Shutdown() twice (once
via defer server.Shutdown() and again explicitly), so remove the redundant
explicit call by deleting the final if err := server.Shutdown(); ... block; keep
the deferred defer server.Shutdown() to ensure cleanup, or alternatively remove
the defer and keep the explicit call—make sure only one server.Shutdown()
invocation remains to avoid confusion.

In `@beamsync/server.go`:
- Around line 287-298: The upload handler currently decodes the manifest using
an inline anonymous struct instead of reusing processManifest/manifestEntry;
update the /upload handler to call processManifest(r) (or pass the request body
reader) and use the returned map[string]int64 instead of re-parsing with the
inline struct, preserving the existing error handling and validation logic;
remove or replace the inline anonymous manifest parsing so tests exercise
processManifest/manifestEntry and ensure any variable names (e.g., fileSizes)
and error paths in the handler are adjusted to use the helper's output.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: 2267abbb-3052-4d78-a8ca-0e90fe002e0c

📥 Commits

Reviewing files that changed from the base of the PR and between 069dcb8 and 2d9b565.

📒 Files selected for processing (4)
  • beamsync/permissions_test.go
  • beamsync/port_manager_test.go
  • beamsync/server.go
  • beamsync/server_test.go

Comment thread beamsync/permissions_test.go
Comment thread beamsync/port_manager_test.go
Comment thread beamsync/port_manager_test.go
@kunal-9090 kunal-9090 force-pushed the codex/issue-14-backend-tests branch from 2d9b565 to e0a706e Compare May 31, 2026 12:29
@kunal-9090

Copy link
Copy Markdown
Contributor Author

Follow-up: rebased this PR onto the latest upstream main and updated the new server tests to match the current stats/history-aware helper signatures. The latest Go and frontend checks CI run is passing now, along with CodeRabbit.

@PranavAgarkar07

Copy link
Copy Markdown
Owner

This is looking really solid now @kunal-9090! 🔥

The test coverage is comprehensive — 534 lines across permissions, port manager, and server tests is a significant addition. I tested the merge locally and everything passes cleanly with zero race conditions.

A few things I noticed while going through it:

  1. processManifest — the upload handler still uses the inline anonymous struct for manifest parsing while processManifest is only exercised by tests. Wiring them together would let the tests cover the actual production code path. Happy to do that as a quick follow-up after merge.

  2. Double shutdown — there's a redundant explicit server.Shutdown() alongside the defer. Minor, but worth cleaning up.

  3. Port test binding — coderabbitai flagged that the busy listeners bind to 127.0.0.1:0 while FindAvailablePort binds to :port (all interfaces). The fix would be binding to :0 instead. Low priority since the tests still pass in practice.

None of these are blockers — the CI passes, coverage is way up, and these are easy follow-ups. Let me know if you want to address them before merge or we can ship and clean up after!

Great work on this! 🚀

@kunal-9090

Copy link
Copy Markdown
Contributor Author

Thanks for the detailed review. I pushed a small follow-up that wires the upload manifest parsing through the existing processManifest helper, removes the redundant shutdown pattern in the lifecycle test, tightens the default permission assertions, and updates the port-manager tests to bind busy listeners on all interfaces.\n\nValidation: the PR's GitHub Go and frontend checks workflow passed on commit

@PranavAgarkar07 PranavAgarkar07 left a comment

Copy link
Copy Markdown
Owner

Choose a reason for hiding this comment

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

Thank you for this thoughtful contribution, Kunal. The tests add real coverage to previously untested paths like writeFileToDisk, processManifest, copyChunked, and the worker pool error tolerance. These are the kinds of tests that catch production bugs rather than just padding coverage numbers.

The add/add conflicts with main were straightforward to resolve. Your additional device rule assertions in permissions_test.go, the ':0' bind address alignment with production in port_manager_test.go, and the removal of the redundant defer Shutdown() in server_test.go were all kept in the merge.

A few things worth considering for future contributions:

  • Table-driven tests are the most idiomatic Go pattern for multi-case scenarios. The extension blocking and token middleware tests would benefit from them.
  • Running tests with the -race flag would add confidence for the concurrent paths you tested.
  • Using httptest.NewServer instead of a raw listener in test helpers aligns with established Go conventions.

None of these are merge blockers. The core logic is sound and the tests provide real value. Appreciate you taking this on.

@PranavAgarkar07

Copy link
Copy Markdown
Owner

Merged via 1fcb3cf. The conflicts with main were resolved locally by combining both sets of test additions. Thank you for contributing these, Kunal. The tests for writeFileToDisk, processManifest, copyChunked, and the worker pool are exactly the kind of coverage this codebase needed.

@PranavAgarkar07 PranavAgarkar07 added type:docs Documentation and removed type:docs Documentation labels Jun 2, 2026
@PranavAgarkar07 PranavAgarkar07 force-pushed the codex/issue-14-backend-tests branch from 09c0e8d to 1fcb3cf Compare June 2, 2026 18:21
PranavAgarkar07 added a commit that referenced this pull request Jun 2, 2026
…r tests

Merging PR #42 which replaces PR #30 (closed due to merge workflow issue). Contributed by @kunal-9090. Closes #14.
@PranavAgarkar07

Copy link
Copy Markdown
Owner

Apologies for the workflow misstep. I originally merged this directly to main instead of via the PR, which closed it without a proper merge status. I then tried to reopen but GitHub did not allow reopening a closed PR with identical head and base refs. Since I cannot push to your fork branch, I created PR #42 with the exact same changes and merged it properly with the 'gssoc:approved', 'level:intermediate', and 'type:testing' labels. The commit 3444f84 on main includes your contributions. For GSSoC credit, could you please either enable maintainer edits on PR #30 so I can update the branch and merge it, or confirm that PR #42 works for tracking purposes on your end?

@PranavAgarkar07

PranavAgarkar07 commented Jun 2, 2026

Copy link
Copy Markdown
Owner

Hey Kunal, I ran into a GitHub limitation with this PR -- since the branch state is locked it can not be reopened from this side. No worries though. Could you open a fresh pull request from your fork with any small change (even a README typo fix or a blank line)? I will merge it right away and apply the gssoc:approved label so you get GSSoC credit. The actual test code from PR 30 is already on main (landed via 3444f84), so the dummy PR is just for attribution. Thank you for the contribution.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

gssoc:approved Approved for GSSoC contributions level:intermediate Intermediate level task type:testing Testing

Projects

None yet

Development

Successfully merging this pull request may close these issues.

test: add unit tests for Go backend (server, permissions, port manager)

2 participants