Test Coverage Gap Analysis: Microck/tailstick
Executive Summary
The tailstick project is a Go application for managing Tailscale-based USB/network device leases. It has 10 source files and 5 test files. While the existing tests are high-quality and cover several critical paths, there are significant gaps in test coverage across multiple packages.
Source-to-Test Mapping
| Source File |
Test File |
Status |
internal/tailscale/client.go |
internal/tailscale/client_test.go |
✅ Partial |
internal/app/workflow.go |
internal/app/workflow_test.go |
⚠️ Partial |
internal/app/cli.go |
(none) |
❌ No tests |
internal/app/gui.go |
(none) |
❌ No tests |
internal/state/store.go |
(none) |
❌ No tests |
internal/config/config.go |
internal/config/config_test.go |
⚠️ Minimal |
internal/crypto/secret.go |
internal/crypto/secret_test.go |
⚠️ Minimal |
internal/gui/server.go |
internal/gui/server_test.go |
⚠️ Partial |
internal/logging/logger.go |
(none) |
❌ No tests |
internal/platform/exec.go |
(none) |
❌ No tests |
internal/platform/platform.go |
(none) |
❌ No tests |
4 of 10 source packages have zero test files. ~30 exported functions have no tests.
P0 — Critical (No test coverage for core logic)
P0-1: internal/state/store.go — Zero tests for all exported functions
All 4 exported functions (Load, Save, UpsertRecord, AppendAudit) have zero test coverage. State persistence is the source of truth for all lease data. A bug here means lost leases, double-cleanup, or missed cleanup.
P0-2: internal/platform/exec.go — Zero tests for Runner
Runner.Run() and Runner.RunWithTimeout() — empty command guard, dry-run mode, timeout behavior — all untested. Runner is the primary interface used by the tailscale client.
P0-3: internal/platform/platform.go — Zero tests
Detect(), sanitizeHost(), IsElevated(), RequireSupportedLinux(), path resolution functions — all untested. sanitizeHost edge cases: empty string, special characters, Unicode, all-invalid chars.
P1 — High (Missing tests for important business logic)
P1-1: internal/app/cli.go — RunCLI() completely untested
Command dispatch (run, agent, cleanup, version, help), runEnroll(), runAgent(), runCleanup() — all untested.
P1-2: internal/app/workflow.go — Enroll() has zero test coverage
The most complex function in the codebase (~125 lines) has no tests. Missing: privilege check, config loading, preset lookup, password validation, exit node validation, tailscale up, secret encryption, audit logging, agent installation.
P1-3: internal/config/config.go — Minimal test coverage
Only 1 test exists (38 lines). Missing: Validate() error paths, FindPreset() resolution, ResolvePath(), ResolvePresetSecrets() env var handling.
P1-4: internal/crypto/secret.go — Missing error path tests
Only happy-path roundtrip tests exist. Missing: wrong password, corrupted input, empty key material, corrupted nonce/salt/cipher.
P1-5: internal/tailscale/client.go — Multiple untested methods
IsInstalled(), EnsureInstalled(), Down(), Logout(), Status(), Uninstall(), ParseDurationDays(), Future() — all untested.
P2 — Medium (Missing edge cases and error paths)
internal/gui/server.go: Missing enroll success path, non-POST method, invalid JSON body, Run() port validation
internal/logging/logger.go: Zero tests for New(), Close(), Info(), Error()
internal/tailscale/client.go: deleteDevice edge cases — empty apiKey/deviceID silent nil return
P3 — Low (Nice-to-have)
- No CI integration for sandbox E2E tests
- Duplicated fake tailscale binary pattern across test files → extract to
internal/testutil/
- Several functions would benefit from table-driven tests:
sanitizeHost(), ParseDurationDays(), validateExitNode(), FindPreset()
Quantitative Summary
| Category |
Count |
| Packages with zero test files |
4 |
| Source files with zero test coverage |
5 |
| Exported functions with no tests |
~30 |
| Error handling paths untested |
~25 |
| Edge cases untested |
~20 |
Recommended Priority Actions
- [P0] Add
internal/state/store_test.go — Test Load, Save, UpsertRecord, AppendAudit with real temp files
- [P0] Add
internal/platform/exec_test.go — Test Runner.Run() with dry-run, empty command, RunWithTimeout()
- [P0] Add
internal/platform/platform_test.go — Test sanitizeHost() with edge cases, path resolution
- [P1] Expand config_test.go — Cover Validate, FindPreset, ResolvePath, ResolvePresetSecrets with table-driven tests
- [P1] Add crypto error path tests — wrong password, corrupted input, empty key material
- [P2] Add
internal/logging/logger_test.go — Basic New/Close/Write test with temp file
- [P3] Create
internal/testutil/ package to consolidate shared test helpers
Generated by Nightshift v3 (GLM 5.1)
Test Coverage Gap Analysis: Microck/tailstick
Executive Summary
The tailstick project is a Go application for managing Tailscale-based USB/network device leases. It has 10 source files and 5 test files. While the existing tests are high-quality and cover several critical paths, there are significant gaps in test coverage across multiple packages.
Source-to-Test Mapping
internal/tailscale/client.gointernal/tailscale/client_test.gointernal/app/workflow.gointernal/app/workflow_test.gointernal/app/cli.gointernal/app/gui.gointernal/state/store.gointernal/config/config.gointernal/config/config_test.gointernal/crypto/secret.gointernal/crypto/secret_test.gointernal/gui/server.gointernal/gui/server_test.gointernal/logging/logger.gointernal/platform/exec.gointernal/platform/platform.go4 of 10 source packages have zero test files. ~30 exported functions have no tests.
P0 — Critical (No test coverage for core logic)
P0-1:
internal/state/store.go— Zero tests for all exported functionsAll 4 exported functions (
Load,Save,UpsertRecord,AppendAudit) have zero test coverage. State persistence is the source of truth for all lease data. A bug here means lost leases, double-cleanup, or missed cleanup.P0-2:
internal/platform/exec.go— Zero tests for RunnerRunner.Run()andRunner.RunWithTimeout()— empty command guard, dry-run mode, timeout behavior — all untested.Runneris the primary interface used by the tailscale client.P0-3:
internal/platform/platform.go— Zero testsDetect(),sanitizeHost(),IsElevated(),RequireSupportedLinux(), path resolution functions — all untested.sanitizeHostedge cases: empty string, special characters, Unicode, all-invalid chars.P1 — High (Missing tests for important business logic)
P1-1:
internal/app/cli.go—RunCLI()completely untestedCommand dispatch (
run,agent,cleanup,version,help),runEnroll(),runAgent(),runCleanup()— all untested.P1-2:
internal/app/workflow.go—Enroll()has zero test coverageThe most complex function in the codebase (~125 lines) has no tests. Missing: privilege check, config loading, preset lookup, password validation, exit node validation, tailscale up, secret encryption, audit logging, agent installation.
P1-3:
internal/config/config.go— Minimal test coverageOnly 1 test exists (38 lines). Missing:
Validate()error paths,FindPreset()resolution,ResolvePath(),ResolvePresetSecrets()env var handling.P1-4:
internal/crypto/secret.go— Missing error path testsOnly happy-path roundtrip tests exist. Missing: wrong password, corrupted input, empty key material, corrupted nonce/salt/cipher.
P1-5:
internal/tailscale/client.go— Multiple untested methodsIsInstalled(),EnsureInstalled(),Down(),Logout(),Status(),Uninstall(),ParseDurationDays(),Future()— all untested.P2 — Medium (Missing edge cases and error paths)
internal/gui/server.go: Missing enroll success path, non-POST method, invalid JSON body, Run() port validationinternal/logging/logger.go: Zero tests for New(), Close(), Info(), Error()internal/tailscale/client.go:deleteDeviceedge cases — empty apiKey/deviceID silent nil returnP3 — Low (Nice-to-have)
internal/testutil/sanitizeHost(),ParseDurationDays(),validateExitNode(),FindPreset()Quantitative Summary
Recommended Priority Actions
internal/state/store_test.go— Test Load, Save, UpsertRecord, AppendAudit with real temp filesinternal/platform/exec_test.go— Test Runner.Run() with dry-run, empty command, RunWithTimeout()internal/platform/platform_test.go— Test sanitizeHost() with edge cases, path resolutioninternal/logging/logger_test.go— Basic New/Close/Write test with temp fileinternal/testutil/package to consolidate shared test helpersGenerated by Nightshift v3 (GLM 5.1)