Add Go branch-coverage tests for unified-resource views and pure helpers

Cover pure functions left at 0% after the canonical Operational Trust and
unified-resource work, surfaced by a fresh coverage probe.

- unifiedresources views.go accessors for K8sNodeView, DockerContainerView,
  PodView, K8sDeploymentView, HostView, DockerHostView, K8sClusterView and
  the smaller ContainerView.Pool / NodeView.IsClusterMember /
  PhysicalDiskView.MetricResourceID / PBSInstanceView.Datastores /
  PMGInstanceView.InstanceID accessors. Each exercises the nil-receiver and
  nil-nested defensive arms, the populated projection, and slice/map
  clone-independence.
- unifiedresources clone.go seven Ceph deep-clone helpers, asserting value
  equality, mutation independence, and nil/empty inputs.
- agentcapabilities firstStringPayloadValue, MCPManifestPromptProjectionSupported
  and JSONRPCError.Error.
- ai/tools data_types NormalizeCollections (three receivers),
  ValidateCurrentResourceAvailable and ErrExecutionContextUnavailable.Error.

Test-only. Every target function moved 0% to covered. No source changes.

Contract-Neutral: test-only branch-coverage tests; no source or contract changes
This commit is contained in:
rcourtman 2026-07-19 22:23:42 +01:00
parent 19ec17372e
commit 57f3fa8431
9 changed files with 3168 additions and 0 deletions

View file

@ -0,0 +1,265 @@
package agentcapabilities
import (
"testing"
)
// TestFirstStringPayloadValueAgentCapsBranchcov0719late covers the unexported
// firstStringPayloadValue helper across all of its branches: key present and a
// non-empty string (with surrounding whitespace that must be trimmed), key
// present but a non-string type, key present but an empty/whitespace-only
// string, key absent entirely, multiple keys where a later key is the first
// usable match, and the no-match empty return (including the degenerate
// no-keys case).
func TestFirstStringPayloadValueAgentCapsBranchcov0719late(t *testing.T) {
cases := []struct {
name string
payload map[string]any
keys []string
want string
}{
{
name: "key present as non-empty string returns trimmed value",
payload: map[string]any{"command": " reboot host "},
keys: []string{"command"},
want: "reboot host",
},
{
name: "key present as non-empty string with no surrounding whitespace passes through",
payload: map[string]any{"command": "reboot host"},
keys: []string{"command"},
want: "reboot host",
},
{
name: "key present but wrong type int is skipped",
payload: map[string]any{"command": 42},
keys: []string{"command"},
want: "",
},
{
name: "key present but wrong type bool is skipped",
payload: map[string]any{"command": true},
keys: []string{"command"},
want: "",
},
{
name: "key present but wrong type slice is skipped",
payload: map[string]any{"command": []string{"a", "b"}},
keys: []string{"command"},
want: "",
},
{
name: "key present but empty string is skipped",
payload: map[string]any{"command": ""},
keys: []string{"command"},
want: "",
},
{
name: "key present but whitespace-only string is skipped",
payload: map[string]any{"command": " "},
keys: []string{"command"},
want: "",
},
{
name: "key absent entirely returns empty",
payload: map[string]any{"unrelated": "value"},
keys: []string{"command"},
want: "",
},
{
name: "nil payload returns empty",
payload: nil,
keys: []string{"command"},
want: "",
},
{
name: "multiple keys where first key matches returns first",
payload: map[string]any{"command": "first", "reason": "second"},
keys: []string{"command", "reason"},
want: "first",
},
{
name: "multiple keys where later key matches after wrong type returns later",
payload: map[string]any{"command": 42, "reason": "real reason"},
keys: []string{"command", "reason"},
want: "real reason",
},
{
name: "multiple keys where later key matches after whitespace-only returns later",
payload: map[string]any{"command": " ", "reason": "real reason"},
keys: []string{"command", "reason"},
want: "real reason",
},
{
name: "multiple keys where later key matches after absent first returns later",
payload: map[string]any{"reason": "real reason"},
keys: []string{"command", "reason"},
want: "real reason",
},
{
name: "multiple keys all wrong type returns empty",
payload: map[string]any{"command": 1, "reason": true},
keys: []string{"command", "reason"},
want: "",
},
{
name: "multiple keys all whitespace-only returns empty",
payload: map[string]any{"command": " ", "reason": "\t\n"},
keys: []string{"command", "reason"},
want: "",
},
{
name: "no keys provided returns empty",
payload: map[string]any{"command": "value"},
keys: nil,
want: "",
},
}
for _, tc := range cases {
t.Run(tc.name, func(t *testing.T) {
got := firstStringPayloadValue(tc.payload, tc.keys...)
if got != tc.want {
t.Fatalf("firstStringPayloadValue(%v, %v) = %q, want %q", tc.payload, tc.keys, got, tc.want)
}
})
}
}
// TestMCPManifestPromptProjectionSupportedAgentCapsBranchcov0719late covers both arms
// of MCPManifestPromptProjectionSupported and its unexported helper
// mcpManifestPromptProjectionSupported: a manifest whose Pulse workflow prompts
// include at least one prompt with a non-empty trimmed Name returns true, while
// a manifest with no workflow prompts or only blank-named prompts returns false.
func TestMCPManifestPromptProjectionSupportedAgentCapsBranchcov0719late(t *testing.T) {
t.Run("exported returns true when a workflow prompt has a non-empty name", func(t *testing.T) {
manifest := Manifest{
WorkflowPrompts: []PulseWorkflowPrompt{
{Name: "triage_fleet", Description: "Triage the fleet"},
},
}
if !MCPManifestPromptProjectionSupported(manifest) {
t.Fatalf("MCPManifestPromptProjectionSupported = false, want true for manifest with a named workflow prompt")
}
})
t.Run("exported returns true when only one of several prompts has a non-empty name", func(t *testing.T) {
manifest := Manifest{
WorkflowPrompts: []PulseWorkflowPrompt{
{Name: " "},
{Name: ""},
{Name: "review_finding"},
},
}
if !MCPManifestPromptProjectionSupported(manifest) {
t.Fatalf("MCPManifestPromptProjectionSupported = false, want true when any prompt has a non-blank name")
}
})
t.Run("exported returns false when no workflow prompts are declared", func(t *testing.T) {
manifest := Manifest{}
if MCPManifestPromptProjectionSupported(manifest) {
t.Fatalf("MCPManifestPromptProjectionSupported = true, want false for manifest without workflow prompts")
}
})
t.Run("exported returns false when workflow prompts only have blank names", func(t *testing.T) {
manifest := Manifest{
WorkflowPrompts: []PulseWorkflowPrompt{
{Name: " "},
{Name: ""},
},
}
if MCPManifestPromptProjectionSupported(manifest) {
t.Fatalf("MCPManifestPromptProjectionSupported = true, want false when only blank-named prompts exist")
}
})
t.Run("exported returns true for a name that needs trimming", func(t *testing.T) {
manifest := Manifest{
WorkflowPrompts: []PulseWorkflowPrompt{
{Name: " investigate_resource "},
},
}
if !MCPManifestPromptProjectionSupported(manifest) {
t.Fatalf("MCPManifestPromptProjectionSupported = false, want true for a name that becomes non-empty after trimming")
}
})
t.Run("unexported helper returns true when a workflow prompt has a non-empty name", func(t *testing.T) {
manifest := Manifest{
WorkflowPrompts: []PulseWorkflowPrompt{
{Name: "operations_loop"},
},
}
if !mcpManifestPromptProjectionSupported(manifest) {
t.Fatalf("mcpManifestPromptProjectionSupported = false, want true")
}
})
t.Run("unexported helper returns false when no prompts are declared", func(t *testing.T) {
manifest := Manifest{}
if mcpManifestPromptProjectionSupported(manifest) {
t.Fatalf("mcpManifestPromptProjectionSupported = true, want false for empty manifest")
}
})
t.Run("unexported helper returns false when only blank-named prompts exist", func(t *testing.T) {
manifest := Manifest{
WorkflowPrompts: []PulseWorkflowPrompt{
{Name: " "},
},
}
if mcpManifestPromptProjectionSupported(manifest) {
t.Fatalf("mcpManifestPromptProjectionSupported = true, want false for blank-named prompts")
}
})
}
// TestJSONRPCErrorErrorAgentCapsBranchcov0719late covers JSONRPCError.Error() across its
// two formatting branches: the populated-message arm (returns the message
// verbatim) and the empty-message / zero-state arm (returns the code-formatted
// fallback). Representative codes from the JSON-RPC error vocabulary are used
// alongside the fully zero value.
func TestJSONRPCErrorErrorAgentCapsBranchcov0719late(t *testing.T) {
cases := []struct {
name string
err JSONRPCError
want string
}{
{
name: "representative populated message and code returns the message verbatim",
err: JSONRPCError{Code: JSONRPCErrorMethodNotFound, Message: "method not found: tools/call"},
want: "method not found: tools/call",
},
{
name: "parse error code with populated message returns the message verbatim",
err: JSONRPCError{Code: JSONRPCErrorParse, Message: "malformed JSON-RPC request: unexpected EOF"},
want: "malformed JSON-RPC request: unexpected EOF",
},
{
name: "empty message with representative code returns code-formatted fallback",
err: JSONRPCError{Code: JSONRPCErrorInternal, Message: ""},
want: "json-rpc error -32603",
},
{
name: "zero value returns code-formatted fallback with code zero",
err: JSONRPCError{},
want: "json-rpc error 0",
},
{
name: "populated message ignores the code entirely",
err: JSONRPCError{Code: JSONRPCErrorInternal, Message: "tools/call handler unavailable"},
want: "tools/call handler unavailable",
},
}
for _, tc := range cases {
t.Run(tc.name, func(t *testing.T) {
got := tc.err.Error()
if got != tc.want {
t.Fatalf("JSONRPCError{Code: %d, Message: %q}.Error() = %q, want %q", tc.err.Code, tc.err.Message, got, tc.want)
}
})
}
}

View file

@ -0,0 +1,271 @@
package tools
import (
"testing"
"time"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
)
// TestDataTypesBranchcov0719lateDockerHostSummaryNormalize covers
// DockerHostSummary.NormalizeCollections. The method only nil-normalizes
// the Containers slice (it does not sort or dedup); tests assert the actual
// behavior: nil -> empty slice, populated -> unchanged passthrough, empty -> stable.
func TestDataTypesBranchcov0719lateDockerHostSummaryNormalize(t *testing.T) {
t.Run("NilContainersBecomesEmptySlice", func(t *testing.T) {
s := DockerHostSummary{ID: "host-1", Hostname: "dock-1"}
assert.Nil(t, s.Containers, "precondition: input Containers must be nil")
out := s.NormalizeCollections()
require.NotNil(t, out.Containers, "nil Containers must become a non-nil empty slice")
assert.Len(t, out.Containers, 0)
assert.Equal(t, "host-1", out.ID, "scalar fields must be preserved")
assert.Equal(t, "dock-1", out.Hostname)
})
t.Run("ZeroValueContainersBecomesEmptySlice", func(t *testing.T) {
var s DockerHostSummary
assert.Nil(t, s.Containers)
out := s.NormalizeCollections()
require.NotNil(t, out.Containers)
assert.Len(t, out.Containers, 0)
})
t.Run("PopulatedContainersPreservedUnchanged", func(t *testing.T) {
// Unsorted, duplicated, multi-element input — NormalizeCollections does
// not sort/dedup, so contents must pass through in original order.
original := []DockerContainerSummary{
{ID: "c2", Name: "zeta", State: "running"},
{ID: "c1", Name: "alpha", State: "stopped"},
{ID: "c1", Name: "alpha", State: "stopped"}, // intentional duplicate
}
s := DockerHostSummary{
ID: "host-1",
Hostname: "dock-1",
Containers: original,
}
out := s.NormalizeCollections()
require.Len(t, out.Containers, 3, "populated slice length must be unchanged")
assert.Equal(t, []DockerContainerSummary(original), out.Containers,
"contents and order must be preserved exactly when not nil")
// Same backing array (no copy expected): identity check on first element addr.
assert.True(t, &out.Containers[0] == &original[0],
"non-nil slice should keep the same backing array (no defensive copy in source)")
})
t.Run("EmptyContainersStable", func(t *testing.T) {
s := DockerHostSummary{Containers: []DockerContainerSummary{}}
out := s.NormalizeCollections()
require.NotNil(t, out.Containers)
assert.Len(t, out.Containers, 0)
})
}
// TestDataTypesBranchcov0719lateK8sNodeSummaryNormalize covers
// K8sNodeSummary.NormalizeCollections. Same shape as Docker: nil Roles
// becomes an empty slice; populated Roles passes through unchanged.
func TestDataTypesBranchcov0719lateK8sNodeSummaryNormalize(t *testing.T) {
t.Run("NilRolesBecomesEmptySlice", func(t *testing.T) {
s := K8sNodeSummary{Name: "n1", Cluster: "c1", Status: "Ready", Ready: true}
assert.Nil(t, s.Roles)
out := s.NormalizeCollections()
require.NotNil(t, out.Roles)
assert.Len(t, out.Roles, 0)
assert.Equal(t, "n1", out.Name)
assert.Equal(t, "c1", out.Cluster)
assert.True(t, out.Ready)
})
t.Run("ZeroValueRolesBecomesEmptySlice", func(t *testing.T) {
var s K8sNodeSummary
assert.Nil(t, s.Roles)
out := s.NormalizeCollections()
require.NotNil(t, out.Roles)
assert.Len(t, out.Roles, 0)
})
t.Run("PopulatedRolesPreservedUnchanged", func(t *testing.T) {
// Unsorted + duplicated input; method does not sort/dedup.
original := []string{"worker", "master", "worker", "etcd"}
s := K8sNodeSummary{Name: "n1", Roles: original}
out := s.NormalizeCollections()
require.Len(t, out.Roles, 4)
assert.Equal(t, original, out.Roles, "roles must pass through in original order")
})
t.Run("EmptyRolesStable", func(t *testing.T) {
s := K8sNodeSummary{Roles: []string{}}
out := s.NormalizeCollections()
require.NotNil(t, out.Roles)
assert.Len(t, out.Roles, 0)
})
}
// TestDataTypesBranchcov0719latePVEClusterStatusNormalize covers
// PVEClusterStatus.NormalizeCollections. Nil Nodes becomes empty slice;
// populated Nodes passes through unchanged.
func TestDataTypesBranchcov0719latePVEClusterStatusNormalize(t *testing.T) {
t.Run("NilNodesBecomesEmptySlice", func(t *testing.T) {
s := PVEClusterStatus{Instance: "inst-1", ClusterName: "clus-1", QuorumOK: true, TotalNodes: 3}
assert.Nil(t, s.Nodes)
out := s.NormalizeCollections()
require.NotNil(t, out.Nodes)
assert.Len(t, out.Nodes, 0)
assert.Equal(t, "inst-1", out.Instance)
assert.Equal(t, "clus-1", out.ClusterName)
assert.True(t, out.QuorumOK)
assert.Equal(t, 3, out.TotalNodes)
})
t.Run("ZeroValueNodesBecomesEmptySlice", func(t *testing.T) {
var s PVEClusterStatus
assert.Nil(t, s.Nodes)
out := s.NormalizeCollections()
require.NotNil(t, out.Nodes)
assert.Len(t, out.Nodes, 0)
})
t.Run("PopulatedNodesPreservedUnchanged", func(t *testing.T) {
// Multi-element, duplicated input — method does not sort/dedup.
original := []PVEClusterNodeStatus{
{Name: "node-b", Status: "online", IsClusterMember: true},
{Name: "node-a", Status: "online", IsClusterMember: true},
{Name: "node-b", Status: "online", IsClusterMember: true}, // duplicate
}
s := PVEClusterStatus{Instance: "inst-1", Nodes: original}
out := s.NormalizeCollections()
require.Len(t, out.Nodes, 3)
assert.Equal(t, original, out.Nodes, "nodes must pass through in original order")
})
t.Run("EmptyNodesStable", func(t *testing.T) {
s := PVEClusterStatus{Nodes: []PVEClusterNodeStatus{}}
out := s.NormalizeCollections()
require.NotNil(t, out.Nodes)
assert.Len(t, out.Nodes, 0)
})
}
// TestDataTypesBranchcov0719lateErrExecutionContextUnavailableError covers
// ErrExecutionContextUnavailable.Error(). It returns Message verbatim.
func TestDataTypesBranchcov0719lateErrExecutionContextUnavailableError(t *testing.T) {
t.Run("ReturnsMessageVerbatim", func(t *testing.T) {
const msg = "write would execute on the host node instead of inside the system-container"
err := &ErrExecutionContextUnavailable{
TargetHost: "homepage-docker",
ResolvedKind: "system-container",
ResolvedNode: "pve-node",
Transport: "direct",
Message: msg,
}
assert.Equal(t, msg, err.Error())
})
t.Run("EmptyMessageYieldsEmptyString", func(t *testing.T) {
err := &ErrExecutionContextUnavailable{}
assert.Equal(t, "", err.Error())
})
t.Run("SatisfiesErrorInterface", func(t *testing.T) {
var err error = &ErrExecutionContextUnavailable{Message: "boom"}
assert.Equal(t, "boom", err.Error())
})
}
// TestDataTypesBranchcov0719lateValidateCurrentResourceAvailable covers
// PulseToolExecutor.ValidateCurrentResourceAvailable across its nil/empty
// error arms and its single-resource OK arm.
func TestDataTypesBranchcov0719lateValidateCurrentResourceAvailable(t *testing.T) {
t.Run("NilResolvedContextReturnsContextError", func(t *testing.T) {
exec := NewPulseToolExecutor(ExecutorConfig{})
require.Nil(t, exec.GetResolvedContext(), "precondition: no context set")
err := exec.ValidateCurrentResourceAvailable()
require.Error(t, err)
assert.Contains(t, err.Error(), "current_resource")
assert.Contains(t, err.Error(), "no Pulse resource context is attached")
})
t.Run("EmptyResolvedContextReturnsNoSelectionError", func(t *testing.T) {
exec := NewPulseToolExecutor(ExecutorConfig{})
exec.SetResolvedContext(&mockResolvedContext{})
err := exec.ValidateCurrentResourceAvailable()
require.Error(t, err)
assert.Contains(t, err.Error(), "current_resource")
assert.Contains(t, err.Error(), "no single attached resource is selected")
})
t.Run("SingleResourceReturnsNil", func(t *testing.T) {
res := &mockResource{
resourceID: "vm:100",
kind: "vm",
targetHost: "vm100",
providerUID: "100",
aliases: []string{"vm100", "100"},
}
ctx := &mockResolvedContext{
resources: map[string]ResolvedResourceInfo{
"vm:100": res,
},
lastAccessed: map[string]time.Time{
"vm:100": time.Now(),
},
}
exec := NewPulseToolExecutor(ExecutorConfig{})
exec.SetResolvedContext(ctx)
err := exec.ValidateCurrentResourceAvailable()
assert.NoError(t, err, "a single attached resource must satisfy validation")
})
t.Run("MultipleResourcesReturnsAmbiguousError", func(t *testing.T) {
res1 := &mockResource{resourceID: "vm:100", kind: "vm"}
res2 := &mockResource{resourceID: "vm:101", kind: "vm"}
ctx := &mockResolvedContext{
resources: map[string]ResolvedResourceInfo{
"vm:100": res1,
"vm:101": res2,
},
lastAccessed: map[string]time.Time{
"vm:100": time.Now(),
"vm:101": time.Now(),
},
}
exec := NewPulseToolExecutor(ExecutorConfig{})
exec.SetResolvedContext(ctx)
err := exec.ValidateCurrentResourceAvailable()
require.Error(t, err)
assert.Contains(t, err.Error(), "current_resource")
assert.Contains(t, err.Error(), "ambiguous")
})
}

View file

@ -0,0 +1,382 @@
package unifiedresources
import "testing"
// Branch-coverage tests for the Ceph clone helpers in clone.go.
//
// These exercise the defensive nil/empty arms and the deep-copy
// independence guarantee for the seven Ceph-specific cloners:
//
// - cloneHostCephHealthMeta
// - cloneHostCephMonitorMapMeta
// - cloneHostCephMonitorMetaSlice
// - cloneHostCephPoolMetaSlice
// - cloneHostCephServiceMetaSlice
// - cloneCephPoolMetaSlice
// - cloneCephServiceMetaSlice
//
// For each cloner we assert (a) the nil/empty defensive arm produces a
// safe value without panic, and (b) a populated input clones equal-by-value
// AND remains fully independent when the clone (and any nested slice/map
// element) is mutated.
// --- cloneHostCephHealthMeta ---
func TestCloneCephBranchcov0719late_HealthMeta_Empty(t *testing.T) {
in := HostCephHealthMeta{}
out := cloneHostCephHealthMeta(in)
if out.Status != "" {
t.Errorf("empty input Status: got %q, want empty", out.Status)
}
// cloneHostCephHealthMeta defensively allocates empty maps/slices even
// when the input fields are nil, so callers never need nil-checks.
if out.Checks == nil {
t.Error("empty input should still produce non-nil Checks map")
}
if len(out.Checks) != 0 {
t.Errorf("empty input Checks len: got %d, want 0", len(out.Checks))
}
if out.Summary == nil {
t.Error("empty input should still produce non-nil Summary slice")
}
if len(out.Summary) != 0 {
t.Errorf("empty input Summary len: got %d, want 0", len(out.Summary))
}
}
func TestCloneCephBranchcov0719late_HealthMeta_Isolation(t *testing.T) {
in := HostCephHealthMeta{
Status: "HEALTH_WARN",
Checks: map[string]HostCephCheckMeta{
"POOL_NO_REDUNDANCY": {
Severity: "WARNING",
Message: "no redundancy",
Detail: []string{"pool=foo", "min_size=1"},
},
},
Summary: []HostCephHealthSummaryMeta{
{Severity: "WARNING", Message: "1 pool has no redundancy"},
},
}
cloned := cloneHostCephHealthMeta(in)
// Equal-by-value assertions.
if cloned.Status != "HEALTH_WARN" {
t.Errorf("Status: got %q, want HEALTH_WARN", cloned.Status)
}
if got := cloned.Checks["POOL_NO_REDUNDANCY"].Severity; got != "WARNING" {
t.Errorf("Checks[POOL_NO_REDUNDANCY].Severity: got %q, want WARNING", got)
}
if got := cloned.Checks["POOL_NO_REDUNDANCY"].Message; got != "no redundancy" {
t.Errorf("Checks[POOL_NO_REDUNDANCY].Message: got %q, want 'no redundancy'", got)
}
if got := len(cloned.Checks["POOL_NO_REDUNDANCY"].Detail); got != 2 {
t.Errorf("Checks[POOL_NO_REDUNDANCY].Detail len: got %d, want 2", got)
}
if got := cloned.Checks["POOL_NO_REDUNDANCY"].Detail[0]; got != "pool=foo" {
t.Errorf("Checks[POOL_NO_REDUNDANCY].Detail[0]: got %q, want 'pool=foo'", got)
}
if len(cloned.Summary) != 1 {
t.Fatalf("Summary len: got %d, want 1", len(cloned.Summary))
}
if cloned.Summary[0].Severity != "WARNING" || cloned.Summary[0].Message != "1 pool has no redundancy" {
t.Errorf("Summary[0]: got %+v, want WARNING/'1 pool has no redundancy'", cloned.Summary[0])
}
// Mutate clone's map (add entry) — must not affect original.
cloned.Checks["NEW_CHECK"] = HostCephCheckMeta{Severity: "NEW"}
if _, exists := in.Checks["NEW_CHECK"]; exists {
t.Error("adding key to cloned Checks must not propagate to original")
}
// Mutate clone's map entry field via copy-out / put-back (required
// because Go disallows direct assignment to a struct field in a map).
c := cloned.Checks["POOL_NO_REDUNDANCY"]
c.Severity = "MUTATED_SEV"
c.Message = "MUTATED_MSG"
c.Detail[0] = "MUTATED_DETAIL"
cloned.Checks["POOL_NO_REDUNDANCY"] = c
if in.Checks["POOL_NO_REDUNDANCY"].Severity == "MUTATED_SEV" {
t.Error("mutating cloned Checks entry Severity must not propagate to original")
}
if in.Checks["POOL_NO_REDUNDANCY"].Message == "MUTATED_MSG" {
t.Error("mutating cloned Checks entry Message must not propagate to original")
}
if in.Checks["POOL_NO_REDUNDANCY"].Detail[0] == "MUTATED_DETAIL" {
t.Error("mutating cloned Checks entry Detail slice element must not propagate to original")
}
// Mutate clone's Summary slice — must not affect original.
cloned.Summary[0].Severity = "MUTATED"
cloned.Summary[0].Message = "MUTATED"
if in.Summary[0].Severity == "MUTATED" || in.Summary[0].Message == "MUTATED" {
t.Error("mutating cloned Summary must not propagate to original")
}
}
// --- cloneHostCephMonitorMapMeta ---
func TestCloneCephBranchcov0719late_MonMap_Empty(t *testing.T) {
in := HostCephMonitorMapMeta{}
out := cloneHostCephMonitorMapMeta(in)
if out.Epoch != 0 || out.NumMons != 0 {
t.Errorf("empty input: got Epoch=%d NumMons=%d, want zeros", out.Epoch, out.NumMons)
}
if out.Monitors != nil {
t.Errorf("empty input Monitors: got %v, want nil", out.Monitors)
}
}
func TestCloneCephBranchcov0719late_MonMap_Isolation(t *testing.T) {
in := HostCephMonitorMapMeta{
Epoch: 3,
NumMons: 1,
Monitors: []HostCephMonitorMeta{
{Name: "mon.a", Rank: 0, Addr: "10.0.0.1:6789", Status: "ok"},
},
}
cloned := cloneHostCephMonitorMapMeta(in)
if cloned.Epoch != 3 || cloned.NumMons != 1 {
t.Errorf("scalar fields: got Epoch=%d NumMons=%d, want 3/1", cloned.Epoch, cloned.NumMons)
}
if len(cloned.Monitors) != 1 {
t.Fatalf("Monitors len: got %d, want 1", len(cloned.Monitors))
}
if cloned.Monitors[0].Name != "mon.a" || cloned.Monitors[0].Addr != "10.0.0.1:6789" {
t.Errorf("Monitors[0]: got %+v, want Name=mon.a Addr=10.0.0.1:6789", cloned.Monitors[0])
}
// Mutate clone's Monitors slice — must not affect original.
cloned.Monitors[0].Name = "MUTATED"
cloned.Monitors[0].Status = "DOWN"
if in.Monitors[0].Name == "MUTATED" || in.Monitors[0].Status == "DOWN" {
t.Error("mutating cloned Monitors entry must not propagate to original")
}
}
// --- cloneHostCephMonitorMetaSlice ---
func TestCloneCephBranchcov0719late_HostMonSlice_Nil(t *testing.T) {
if got := cloneHostCephMonitorMetaSlice(nil); got != nil {
t.Errorf("nil input: got %v, want nil", got)
}
}
func TestCloneCephBranchcov0719late_HostMonSlice_Empty(t *testing.T) {
in := []HostCephMonitorMeta{}
out := cloneHostCephMonitorMetaSlice(in)
if out == nil {
t.Error("empty (non-nil) input should produce non-nil empty slice")
}
if len(out) != 0 {
t.Errorf("empty input: got len=%d, want 0", len(out))
}
}
func TestCloneCephBranchcov0719late_HostMonSlice_Isolation(t *testing.T) {
in := []HostCephMonitorMeta{
{Name: "mon.a", Rank: 0, Addr: "10.0.0.1:6789", Status: "ok"},
{Name: "mon.b", Rank: 1, Addr: "10.0.0.2:6789", Status: "ok"},
}
cloned := cloneHostCephMonitorMetaSlice(in)
if len(cloned) != 2 {
t.Fatalf("len: got %d, want 2", len(cloned))
}
if cloned[0].Name != "mon.a" || cloned[1].Name != "mon.b" {
t.Errorf("values: got %q / %q, want mon.a / mon.b", cloned[0].Name, cloned[1].Name)
}
if cloned[0].Addr != "10.0.0.1:6789" || cloned[1].Rank != 1 {
t.Errorf(" Addr/Rank: got Addr=%q Rank=%d, want 10.0.0.1:6789 / 1", cloned[0].Addr, cloned[1].Rank)
}
cloned[0].Name = "MUTATED"
cloned[0].Rank = 99
if in[0].Name == "MUTATED" || in[0].Rank == 99 {
t.Error("mutating cloned element must not propagate to original")
}
}
// --- cloneHostCephPoolMetaSlice ---
func TestCloneCephBranchcov0719late_HostPoolSlice_Nil(t *testing.T) {
if got := cloneHostCephPoolMetaSlice(nil); got != nil {
t.Errorf("nil input: got %v, want nil", got)
}
}
func TestCloneCephBranchcov0719late_HostPoolSlice_Empty(t *testing.T) {
in := []HostCephPoolMeta{}
out := cloneHostCephPoolMetaSlice(in)
if out == nil {
t.Error("empty (non-nil) input should produce non-nil empty slice")
}
if len(out) != 0 {
t.Errorf("empty input: got len=%d, want 0", len(out))
}
}
func TestCloneCephBranchcov0719late_HostPoolSlice_Isolation(t *testing.T) {
in := []HostCephPoolMeta{
{ID: 1, Name: "pool-1", BytesUsed: 1024, BytesAvailable: 2048, Objects: 5, PercentUsed: 0.33},
{ID: 2, Name: "pool-2", BytesUsed: 4096, BytesAvailable: 8192, Objects: 7, PercentUsed: 0.5},
}
cloned := cloneHostCephPoolMetaSlice(in)
if len(cloned) != 2 {
t.Fatalf("len: got %d, want 2", len(cloned))
}
if cloned[0].Name != "pool-1" || cloned[1].Name != "pool-2" {
t.Errorf("names: got %q / %q, want pool-1 / pool-2", cloned[0].Name, cloned[1].Name)
}
if cloned[0].BytesUsed != 1024 || cloned[1].Objects != 7 {
t.Errorf("numeric values: got BytesUsed=%d Objects=%d, want 1024 / 7", cloned[0].BytesUsed, cloned[1].Objects)
}
cloned[0].Name = "MUTATED"
cloned[0].BytesUsed = 999
if in[0].Name == "MUTATED" || in[0].BytesUsed == 999 {
t.Error("mutating cloned element must not propagate to original")
}
}
// --- cloneHostCephServiceMetaSlice ---
func TestCloneCephBranchcov0719late_HostSvcSlice_Nil(t *testing.T) {
if got := cloneHostCephServiceMetaSlice(nil); got != nil {
t.Errorf("nil input: got %v, want nil", got)
}
}
func TestCloneCephBranchcov0719late_HostSvcSlice_Empty(t *testing.T) {
in := []HostCephServiceMeta{}
out := cloneHostCephServiceMetaSlice(in)
if out == nil {
t.Error("empty (non-nil) input should produce non-nil empty slice")
}
if len(out) != 0 {
t.Errorf("empty input: got len=%d, want 0", len(out))
}
}
func TestCloneCephBranchcov0719late_HostSvcSlice_Isolation(t *testing.T) {
in := []HostCephServiceMeta{
{Type: "mon", Running: 3, Total: 3, Daemons: []string{"mon.a", "mon.b", "mon.c"}},
{Type: "osd", Running: 5, Total: 6, Daemons: []string{"osd.0", "osd.1"}},
}
cloned := cloneHostCephServiceMetaSlice(in)
if len(cloned) != 2 {
t.Fatalf("len: got %d, want 2", len(cloned))
}
if cloned[0].Type != "mon" || cloned[1].Type != "osd" {
t.Errorf("Type: got %q / %q, want mon / osd", cloned[0].Type, cloned[1].Type)
}
if len(cloned[0].Daemons) != 3 || cloned[0].Daemons[0] != "mon.a" {
t.Errorf("Daemons[0]: got %+v, want [mon.a mon.b mon.c]", cloned[0].Daemons)
}
// Mutate scalar field — must not affect original.
cloned[0].Type = "MUTATED"
cloned[0].Running = 99
if in[0].Type == "MUTATED" || in[0].Running == 99 {
t.Error("mutating cloned scalar fields must not propagate to original")
}
// Mutate nested Daemons slice — must not affect original (this is the
// reason cloneHostCephServiceMetaSlice does a per-element Daemons clone).
cloned[0].Daemons[0] = "MUTATED_DAEMON"
if in[0].Daemons[0] == "MUTATED_DAEMON" {
t.Error("mutating cloned nested Daemons slice must not propagate to original")
}
}
// --- cloneCephPoolMetaSlice (non-Host variant) ---
func TestCloneCephBranchcov0719late_PoolSlice_Nil(t *testing.T) {
if got := cloneCephPoolMetaSlice(nil); got != nil {
t.Errorf("nil input: got %v, want nil", got)
}
}
func TestCloneCephBranchcov0719late_PoolSlice_Empty(t *testing.T) {
in := []CephPoolMeta{}
out := cloneCephPoolMetaSlice(in)
if out == nil {
t.Error("empty (non-nil) input should produce non-nil empty slice")
}
if len(out) != 0 {
t.Errorf("empty input: got len=%d, want 0", len(out))
}
}
func TestCloneCephBranchcov0719late_PoolSlice_Isolation(t *testing.T) {
in := []CephPoolMeta{
{Name: "pool-1", StoredBytes: 1024, AvailableBytes: 2048, Objects: 5, PercentUsed: 0.33},
{Name: "pool-2", StoredBytes: 4096, AvailableBytes: 8192, Objects: 7, PercentUsed: 0.5},
}
cloned := cloneCephPoolMetaSlice(in)
if len(cloned) != 2 {
t.Fatalf("len: got %d, want 2", len(cloned))
}
if cloned[0].Name != "pool-1" || cloned[1].Name != "pool-2" {
t.Errorf("names: got %q / %q, want pool-1 / pool-2", cloned[0].Name, cloned[1].Name)
}
if cloned[0].StoredBytes != 1024 || cloned[1].Objects != 7 {
t.Errorf("numeric values: got StoredBytes=%d Objects=%d, want 1024 / 7", cloned[0].StoredBytes, cloned[1].Objects)
}
cloned[0].Name = "MUTATED"
cloned[0].StoredBytes = 999
if in[0].Name == "MUTATED" || in[0].StoredBytes == 999 {
t.Error("mutating cloned element must not propagate to original")
}
}
// --- cloneCephServiceMetaSlice (non-Host variant) ---
func TestCloneCephBranchcov0719late_SvcSlice_Nil(t *testing.T) {
if got := cloneCephServiceMetaSlice(nil); got != nil {
t.Errorf("nil input: got %v, want nil", got)
}
}
func TestCloneCephBranchcov0719late_SvcSlice_Empty(t *testing.T) {
in := []CephServiceMeta{}
out := cloneCephServiceMetaSlice(in)
if out == nil {
t.Error("empty (non-nil) input should produce non-nil empty slice")
}
if len(out) != 0 {
t.Errorf("empty input: got len=%d, want 0", len(out))
}
}
func TestCloneCephBranchcov0719late_SvcSlice_Isolation(t *testing.T) {
in := []CephServiceMeta{
{Type: "mon", Running: 3, Total: 3},
{Type: "osd", Running: 5, Total: 6},
}
cloned := cloneCephServiceMetaSlice(in)
if len(cloned) != 2 {
t.Fatalf("len: got %d, want 2", len(cloned))
}
if cloned[0].Type != "mon" || cloned[1].Type != "osd" {
t.Errorf("Type: got %q / %q, want mon / osd", cloned[0].Type, cloned[1].Type)
}
if cloned[0].Running != 3 || cloned[1].Total != 6 {
t.Errorf("values: got Running=%d Total=%d, want 3 / 6", cloned[0].Running, cloned[1].Total)
}
cloned[0].Type = "MUTATED"
cloned[0].Running = 99
if in[0].Type == "MUTATED" || in[0].Running == 99 {
t.Error("mutating cloned element must not propagate to original")
}
}

View file

@ -0,0 +1,372 @@
package unifiedresources
import (
"reflect"
"testing"
"time"
)
// TestDockerContainerViewBranchcov0719late covers every requested
// DockerContainerView accessor across all three relevant arms:
// - the nil-receiver arm (v.r == nil)
// - the nil-nested arm (v.r != nil but v.r.Docker == nil)
// - the fully-populated arm (with cloned slice/map/ptr independence checks)
//
// The empty-nested arm additionally exercises the slice/map/ptr fields when
// the *DockerData payload exists but the nested collections are unset/empty.
func TestDockerContainerViewBranchcov0719late(t *testing.T) {
now := time.Date(2026, 7, 19, 12, 0, 0, 0, time.UTC)
parentID := "docker-host-1"
r := &Resource{
ID: "app-container-1",
Type: ResourceTypeAppContainer,
Name: "nextcloud",
Status: StatusOnline,
LastSeen: now,
Tags: []string{"app", "tier:web"},
ParentID: &parentID,
Docker: &DockerData{
HostSourceID: " docker-host-src-1 ",
ContainerID: "container-123",
Image: "docker.io/library/nextcloud:29",
ContainerState: "running",
Health: "healthy",
RestartCount: 3,
ExitCode: 137,
UptimeSeconds: 9999,
Ports: []DockerPortMeta{
{PrivatePort: 80, PublicPort: 8080, Protocol: "tcp", IP: "0.0.0.0"},
},
Labels: map[string]string{"com.example.stack": "web"},
Networks: []DockerNetworkMeta{{Name: "frontend", IPv4: "172.20.0.2", IPv6: "fd00::2"}},
Mounts: []DockerMountMeta{{Type: "volume", Source: "data", Destination: "/var/www/html", Mode: "rw", RW: true}},
UpdateStatus: &DockerUpdateStatusMeta{
UpdateAvailable: true,
CurrentDigest: "sha256:abc",
LatestDigest: "sha256:def",
LastChecked: now,
Error: "",
},
},
Metrics: &ResourceMetrics{
CPU: &MetricValue{Percent: 42.5},
Memory: &MetricValue{Used: ptrInt64(512), Total: ptrInt64(1024), Percent: 50},
Disk: &MetricValue{Percent: 11},
NetIn: &MetricValue{Value: 1234.5},
NetOut: &MetricValue{Value: 6789.0},
},
}
v := NewDockerContainerView(r)
t.Run("String_populated", func(t *testing.T) {
if got, want := v.String(), `DockerContainerView(app-container-1, "nextcloud")`; got != want {
t.Fatalf("expected %q, got %q", want, got)
}
})
t.Run("Status_populated", func(t *testing.T) {
if got := v.Status(); got != StatusOnline {
t.Fatalf("expected Status %q, got %q", StatusOnline, got)
}
})
t.Run("HostSourceID_populated_trims", func(t *testing.T) {
if got, want := v.HostSourceID(), "docker-host-src-1"; got != want {
t.Fatalf("expected HostSourceID %q, got %q", want, got)
}
})
t.Run("Image_populated", func(t *testing.T) {
if got, want := v.Image(), "docker.io/library/nextcloud:29"; got != want {
t.Fatalf("expected Image %q, got %q", want, got)
}
})
t.Run("ContainerState_populated", func(t *testing.T) {
if got, want := v.ContainerState(), "running"; got != want {
t.Fatalf("expected ContainerState %q, got %q", want, got)
}
})
t.Run("Health_populated", func(t *testing.T) {
if got, want := v.Health(), "healthy"; got != want {
t.Fatalf("expected Health %q, got %q", want, got)
}
})
t.Run("RestartCount_populated", func(t *testing.T) {
if got, want := v.RestartCount(), 3; got != want {
t.Fatalf("expected RestartCount %d, got %d", want, got)
}
})
t.Run("ExitCode_populated", func(t *testing.T) {
if got, want := v.ExitCode(), 137; got != want {
t.Fatalf("expected ExitCode %d, got %d", want, got)
}
})
t.Run("CPUPercent_populated", func(t *testing.T) {
if got, want := v.CPUPercent(), 42.5; got != want {
t.Fatalf("expected CPUPercent %v, got %v", want, got)
}
})
t.Run("MemoryUsed_populated", func(t *testing.T) {
if got, want := v.MemoryUsed(), int64(512); got != want {
t.Fatalf("expected MemoryUsed %d, got %d", want, got)
}
})
t.Run("MemoryTotal_populated", func(t *testing.T) {
if got, want := v.MemoryTotal(), int64(1024); got != want {
t.Fatalf("expected MemoryTotal %d, got %d", want, got)
}
})
t.Run("MemoryPercent_populated", func(t *testing.T) {
if got, want := v.MemoryPercent(), 50.0; got != want {
t.Fatalf("expected MemoryPercent %v, got %v", want, got)
}
})
t.Run("DiskPercent_populated", func(t *testing.T) {
if got, want := v.DiskPercent(), 11.0; got != want {
t.Fatalf("expected DiskPercent %v, got %v", want, got)
}
})
t.Run("NetInRate_populated", func(t *testing.T) {
if got, want := v.NetInRate(), 1234.5; got != want {
t.Fatalf("expected NetInRate %v, got %v", want, got)
}
})
t.Run("NetOutRate_populated", func(t *testing.T) {
if got, want := v.NetOutRate(), 6789.0; got != want {
t.Fatalf("expected NetOutRate %v, got %v", want, got)
}
})
t.Run("UptimeSeconds_populated", func(t *testing.T) {
if got, want := v.UptimeSeconds(), int64(9999); got != want {
t.Fatalf("expected UptimeSeconds %d, got %d", want, got)
}
})
t.Run("Ports_populated_and_cloned", func(t *testing.T) {
got := v.Ports()
if len(got) != 1 || got[0].PrivatePort != 80 || got[0].PublicPort != 8080 || got[0].Protocol != "tcp" || got[0].IP != "0.0.0.0" {
t.Fatalf("expected populated port meta, got %+v", got)
}
if !reflect.DeepEqual(got, r.Docker.Ports) {
t.Fatalf("Ports clone should equal source by value: got %+v want %+v", got, r.Docker.Ports)
}
got[0].PrivatePort = 9999
if again := v.Ports(); len(again) != 1 || again[0].PrivatePort != 80 {
t.Fatalf("Ports() must return an independent slice, got %+v", again)
}
})
t.Run("Labels_populated_and_cloned", func(t *testing.T) {
got := v.Labels()
if len(got) != 1 || got["com.example.stack"] != "web" {
t.Fatalf("expected populated labels, got %+v", got)
}
if !reflect.DeepEqual(got, r.Docker.Labels) {
t.Fatalf("Labels clone should equal source by value: got %+v want %+v", got, r.Docker.Labels)
}
got["com.example.stack"] = "mutated"
got["injected"] = "x"
if again := v.Labels(); len(again) != 1 || again["com.example.stack"] != "web" {
t.Fatalf("Labels() must return an independent map, got %+v", again)
}
})
t.Run("Networks_populated_and_cloned", func(t *testing.T) {
got := v.Networks()
if len(got) != 1 || got[0].Name != "frontend" || got[0].IPv4 != "172.20.0.2" || got[0].IPv6 != "fd00::2" {
t.Fatalf("expected populated network meta, got %+v", got)
}
if !reflect.DeepEqual(got, r.Docker.Networks) {
t.Fatalf("Networks clone should equal source by value: got %+v want %+v", got, r.Docker.Networks)
}
got[0].Name = "mutated"
if again := v.Networks(); len(again) != 1 || again[0].Name != "frontend" {
t.Fatalf("Networks() must return an independent slice, got %+v", again)
}
})
t.Run("Mounts_populated_and_cloned", func(t *testing.T) {
got := v.Mounts()
if len(got) != 1 || got[0].Type != "volume" || got[0].Source != "data" || got[0].Destination != "/var/www/html" || !got[0].RW {
t.Fatalf("expected populated mount meta, got %+v", got)
}
if !reflect.DeepEqual(got, r.Docker.Mounts) {
t.Fatalf("Mounts clone should equal source by value: got %+v want %+v", got, r.Docker.Mounts)
}
got[0].Source = "mutated"
if again := v.Mounts(); len(again) != 1 || again[0].Source != "data" {
t.Fatalf("Mounts() must return an independent slice, got %+v", again)
}
})
t.Run("UpdateStatus_populated_and_cloned", func(t *testing.T) {
got := v.UpdateStatus()
if got == nil || !got.UpdateAvailable || got.CurrentDigest != "sha256:abc" || got.LatestDigest != "sha256:def" || !got.LastChecked.Equal(now) {
t.Fatalf("expected populated update status, got %+v", got)
}
got.UpdateAvailable = false
got.CurrentDigest = "mutated"
if again := v.UpdateStatus(); again == nil || !again.UpdateAvailable || again.CurrentDigest != "sha256:abc" {
t.Fatalf("UpdateStatus() must return an independent copy, got %+v", again)
}
})
t.Run("Tags_populated_and_cloned", func(t *testing.T) {
got := v.Tags()
assertStringSlice(t, got, []string{"app", "tier:web"})
got[0] = "mutated"
if again := v.Tags(); len(again) != 2 || again[0] != "app" {
t.Fatalf("Tags() must return an independent slice, got %+v", again)
}
})
t.Run("LastSeen_populated", func(t *testing.T) {
if got := v.LastSeen(); !got.Equal(now) {
t.Fatalf("expected LastSeen %v, got %v", now, got)
}
})
t.Run("NilNestedDockerArm", func(t *testing.T) {
r2 := &Resource{
ID: "container-no-docker",
Type: ResourceTypeAppContainer,
Name: "stub",
Status: StatusOffline,
LastSeen: now,
Tags: []string{"t1"},
Docker: nil,
Metrics: &ResourceMetrics{
CPU: &MetricValue{Percent: 1},
Memory: &MetricValue{Used: ptrInt64(2), Total: ptrInt64(4), Percent: 50},
Disk: &MetricValue{Percent: 5},
NetIn: &MetricValue{Value: 6},
NetOut: &MetricValue{Value: 7},
},
}
v2 := NewDockerContainerView(r2)
if v2.ID() != "container-no-docker" || v2.Name() != "stub" || v2.Status() != StatusOffline {
t.Fatalf("basic accessors should still reflect resource fields, got id=%q name=%q status=%q", v2.ID(), v2.Name(), v2.Status())
}
if got := v2.String(); got != `DockerContainerView(container-no-docker, "stub")` {
t.Fatalf("expected String %q, got %q", `DockerContainerView(container-no-docker, "stub")`, got)
}
if v2.HostSourceID() != "" {
t.Fatalf("expected empty HostSourceID when Docker is nil, got %q", v2.HostSourceID())
}
if v2.Image() != "" {
t.Fatalf("expected empty Image when Docker is nil, got %q", v2.Image())
}
if v2.ContainerState() != "" {
t.Fatalf("expected empty ContainerState when Docker is nil, got %q", v2.ContainerState())
}
if v2.Health() != "" {
t.Fatalf("expected empty Health when Docker is nil, got %q", v2.Health())
}
if v2.RestartCount() != 0 {
t.Fatalf("expected zero RestartCount when Docker is nil, got %d", v2.RestartCount())
}
if v2.ExitCode() != 0 {
t.Fatalf("expected zero ExitCode when Docker is nil, got %d", v2.ExitCode())
}
if v2.UptimeSeconds() != 0 {
t.Fatalf("expected zero UptimeSeconds when Docker is nil, got %d", v2.UptimeSeconds())
}
if v2.Ports() != nil {
t.Fatalf("expected nil Ports when Docker is nil, got %+v", v2.Ports())
}
if v2.Labels() != nil {
t.Fatalf("expected nil Labels when Docker is nil, got %+v", v2.Labels())
}
if v2.Networks() != nil {
t.Fatalf("expected nil Networks when Docker is nil, got %+v", v2.Networks())
}
if v2.Mounts() != nil {
t.Fatalf("expected nil Mounts when Docker is nil, got %+v", v2.Mounts())
}
if v2.UpdateStatus() != nil {
t.Fatalf("expected nil UpdateStatus when Docker is nil, got %+v", v2.UpdateStatus())
}
if v2.CPUPercent() != 1 || v2.MemoryUsed() != 2 || v2.MemoryTotal() != 4 || v2.MemoryPercent() != 50 || v2.DiskPercent() != 5 || v2.NetInRate() != 6 || v2.NetOutRate() != 7 {
t.Fatalf("metric accessors must still resolve via r.Metrics when Docker is nil, got cpu=%v memUsed=%d memTotal=%d memPct=%v diskPct=%v netIn=%v netOut=%v", v2.CPUPercent(), v2.MemoryUsed(), v2.MemoryTotal(), v2.MemoryPercent(), v2.DiskPercent(), v2.NetInRate(), v2.NetOutRate())
}
if !v2.LastSeen().Equal(now) {
t.Fatalf("expected LastSeen %v, got %v", now, v2.LastSeen())
}
assertStringSlice(t, v2.Tags(), []string{"t1"})
})
t.Run("EmptyNestedCollections", func(t *testing.T) {
r3 := &Resource{
ID: "container-empty-collections",
Type: ResourceTypeAppContainer,
Name: "empty",
Status: StatusOnline,
Docker: &DockerData{
ContainerID: "container-456",
Ports: []DockerPortMeta{},
Labels: map[string]string{},
Networks: []DockerNetworkMeta{},
Mounts: []DockerMountMeta{},
UpdateStatus: nil,
},
}
v3 := NewDockerContainerView(r3)
if got := v3.Ports(); got == nil || len(got) != 0 {
t.Fatalf("expected non-nil empty Ports for empty input, got %+v", got)
}
if got := v3.Labels(); got == nil || len(got) != 0 {
t.Fatalf("expected non-nil empty Labels for empty input, got %+v", got)
}
if got := v3.Networks(); got == nil || len(got) != 0 {
t.Fatalf("expected non-nil empty Networks for empty input, got %+v", got)
}
if got := v3.Mounts(); got == nil || len(got) != 0 {
t.Fatalf("expected non-nil empty Mounts for empty input, got %+v", got)
}
if got := v3.UpdateStatus(); got != nil {
t.Fatalf("expected nil UpdateStatus when nested ptr is nil, got %+v", got)
}
})
t.Run("NilReceiverArm", func(t *testing.T) {
var zero DockerContainerView
if got := zero.String(); got != `DockerContainerView(, "")` {
t.Fatalf("expected String %q for nil receiver, got %q", `DockerContainerView(, "")`, got)
}
if zero.ID() != "" || zero.Name() != "" || zero.Status() != "" {
t.Fatalf("expected empty ID/Name/Status for nil receiver, got id=%q name=%q status=%q", zero.ID(), zero.Name(), zero.Status())
}
if zero.HostSourceID() != "" || zero.Image() != "" || zero.ContainerState() != "" || zero.Health() != "" || zero.RestartCount() != 0 || zero.ExitCode() != 0 || zero.UptimeSeconds() != 0 {
t.Fatalf("expected docker accessors to return zero values for nil receiver, got source=%q image=%q state=%q health=%q restarts=%d exit=%d uptime=%d", zero.HostSourceID(), zero.Image(), zero.ContainerState(), zero.Health(), zero.RestartCount(), zero.ExitCode(), zero.UptimeSeconds())
}
if zero.CPUPercent() != 0 || zero.MemoryUsed() != 0 || zero.MemoryTotal() != 0 || zero.MemoryPercent() != 0 || zero.DiskPercent() != 0 || zero.NetInRate() != 0 || zero.NetOutRate() != 0 {
t.Fatalf("expected metric accessors to return zero values for nil receiver, got cpu=%v memUsed=%d memTotal=%d memPct=%v diskPct=%v netIn=%v netOut=%v", zero.CPUPercent(), zero.MemoryUsed(), zero.MemoryTotal(), zero.MemoryPercent(), zero.DiskPercent(), zero.NetInRate(), zero.NetOutRate())
}
if zero.Ports() != nil || zero.Labels() != nil || zero.Networks() != nil || zero.Mounts() != nil || zero.UpdateStatus() != nil {
t.Fatalf("expected nil slice/map/ptr accessors for nil receiver, got ports=%v labels=%v networks=%v mounts=%v update=%v", zero.Ports(), zero.Labels(), zero.Networks(), zero.Mounts(), zero.UpdateStatus())
}
if zero.Tags() != nil {
t.Fatalf("expected nil Tags for nil receiver, got %v", zero.Tags())
}
if !zero.LastSeen().IsZero() {
t.Fatalf("expected zero LastSeen for nil receiver, got %v", zero.LastSeen())
}
})
}

View file

@ -0,0 +1,603 @@
package unifiedresources
import (
"reflect"
"testing"
"time"
"github.com/rcourtman/pulse-go-rewrite/internal/models"
"github.com/rcourtman/pulse-go-rewrite/internal/storagehealth"
)
// ptrTime is a small helper local to this branch-coverage file.
func ptrTime(v time.Time) *time.Time { return &v }
// =====================
// HostView accessors
// =====================
// HostView.TokenLastUsedAt has a triple nil-guard and returns an independent
// *time.Time when populated.
func TestHostViewsBranchcov0719late_HostTokenLastUsedAt(t *testing.T) {
// (a) nil receiver.
var zero HostView
if got := zero.TokenLastUsedAt(); got != nil {
t.Fatalf("nil receiver: expected nil, got %v", got)
}
// (a) nil Agent.
r := &Resource{ID: "h-tlu-1", Type: ResourceTypeAgent}
if got := NewHostView(r).TokenLastUsedAt(); got != nil {
t.Fatalf("nil Agent: expected nil, got %v", got)
}
// (a) Agent set but TokenLastUsedAt pointer nil.
r.Agent = &AgentData{}
if got := NewHostView(r).TokenLastUsedAt(); got != nil {
t.Fatalf("nil TokenLastUsedAt: expected nil, got %v", got)
}
// (b) Populated: equal value via an independent pointer.
used := time.Date(2026, 7, 19, 10, 0, 0, 0, time.UTC)
r.Agent.TokenLastUsedAt = ptrTime(used)
got := NewHostView(r).TokenLastUsedAt()
if got == nil {
t.Fatal("populated: expected non-nil")
}
if !got.Equal(used) {
t.Fatalf("expected %v, got %v", used, *got)
}
// Mutating the returned pointer's pointee must not leak back to the source.
*got = got.Add(time.Hour)
if !r.Agent.TokenLastUsedAt.Equal(used) {
t.Fatalf("mutation leaked to source: source=%v want=%v", *r.Agent.TokenLastUsedAt, used)
}
}
// HostView.PackageUpdates guards nil receiver / nil Agent / nil PackageUpdates
// and returns a clone with an independent Packages slice when populated.
func TestHostViewsBranchcov0719late_HostPackageUpdates(t *testing.T) {
// (a) nil receiver.
var zero HostView
if got := zero.PackageUpdates(); got != nil {
t.Fatalf("nil receiver: expected nil, got %+v", got)
}
// (a) nil Agent.
r := &Resource{ID: "h-pkg-1", Type: ResourceTypeAgent}
if got := NewHostView(r).PackageUpdates(); got != nil {
t.Fatalf("nil Agent: expected nil, got %+v", got)
}
// (a) Agent present but PackageUpdates pointer nil.
r.Agent = &AgentData{}
if got := NewHostView(r).PackageUpdates(); got != nil {
t.Fatalf("nil PackageUpdates: expected nil, got %+v", got)
}
// (b) Populated: value-equal copy with an independent Packages slice.
checked := time.Date(2026, 7, 19, 9, 0, 0, 0, time.UTC)
r.Agent.PackageUpdates = &AgentPackageUpdateMeta{
Supported: true,
Manager: "apt",
InventoryHash: "abc",
PendingCount: 2,
CheckedAt: checked,
Packages: []AgentPackageUpdate{
{Name: "curl", InstalledVersion: "1.0", AvailableVersion: "1.1"},
{Name: "wget", InstalledVersion: "2.0", AvailableVersion: "2.1"},
},
RebootRequired: true,
}
got := NewHostView(r).PackageUpdates()
if got == nil {
t.Fatal("populated: expected non-nil")
}
if !reflect.DeepEqual(*got, *r.Agent.PackageUpdates) {
t.Fatalf("expected value-equal clone, got %+v want %+v", *got, *r.Agent.PackageUpdates)
}
// Mutate scalar on the clone; source unaffected.
got.Manager = "yum"
if r.Agent.PackageUpdates.Manager != "apt" {
t.Fatalf("scalar mutation leaked to source: source.Manager=%q want %q", r.Agent.PackageUpdates.Manager, "apt")
}
// Mutate element of Packages; source unaffected.
got.Packages[0].Name = "mutated"
if r.Agent.PackageUpdates.Packages[0].Name != "curl" {
t.Fatalf("Packages element mutation leaked: source[0].Name=%q want %q", r.Agent.PackageUpdates.Packages[0].Name, "curl")
}
// Append to Packages; source length unchanged.
got.Packages = append(got.Packages, AgentPackageUpdate{Name: "extra"})
if len(r.Agent.PackageUpdates.Packages) != 2 {
t.Fatalf("Packages append leaked to source: source len=%d want 2", len(r.Agent.PackageUpdates.Packages))
}
}
// HostView.StorageCleanup guards nil receiver / nil Agent / nil StorageCleanup.
func TestHostViewsBranchcov0719late_HostStorageCleanup(t *testing.T) {
// (a) nil receiver.
var zero HostView
if got := zero.StorageCleanup(); got != nil {
t.Fatalf("nil receiver: expected nil, got %+v", got)
}
// (a) nil Agent.
r := &Resource{ID: "h-cln-1", Type: ResourceTypeAgent}
if got := NewHostView(r).StorageCleanup(); got != nil {
t.Fatalf("nil Agent: expected nil, got %+v", got)
}
// (a) Agent present but StorageCleanup pointer nil.
r.Agent = &AgentData{}
if got := NewHostView(r).StorageCleanup(); got != nil {
t.Fatalf("nil StorageCleanup: expected nil, got %+v", got)
}
// (b) Populated: value-equal shallow copy.
checked := time.Date(2026, 7, 19, 8, 0, 0, 0, time.UTC)
r.Agent.StorageCleanup = &AgentStorageCleanupMeta{
Supported: true,
Provider: "journal",
Fingerprint: "fp-1",
ReclaimableBytes: 1024,
CheckedAt: checked,
}
got := NewHostView(r).StorageCleanup()
if got == nil {
t.Fatal("populated: expected non-nil")
}
if !reflect.DeepEqual(*got, *r.Agent.StorageCleanup) {
t.Fatalf("expected value-equal clone, got %+v want %+v", *got, *r.Agent.StorageCleanup)
}
got.Provider = "apt"
if r.Agent.StorageCleanup.Provider != "journal" {
t.Fatalf("scalar mutation leaked to source: source.Provider=%q want %q", r.Agent.StorageCleanup.Provider, "journal")
}
}
// HostView.Capabilities appends into a fresh slice from r.Capabilities.
func TestHostViewsBranchcov0719late_HostCapabilities(t *testing.T) {
// (a) nil receiver.
var zero HostView
if got := zero.Capabilities(); got != nil {
t.Fatalf("nil receiver: expected nil, got %+v", got)
}
// (a) Resource present, no capabilities set: append of nil yields nil.
r := &Resource{ID: "h-cap-1", Type: ResourceTypeAgent}
if got := NewHostView(r).Capabilities(); got != nil {
t.Fatalf("empty source capabilities: expected nil, got %+v", got)
}
// (b) Populated: equal contents with an independent backing array.
r.Capabilities = []ResourceCapability{
{Name: "restart", InternalHandler: "agent.restart"},
{Name: "shell", InternalHandler: "agent.shell"},
}
got := NewHostView(r).Capabilities()
if len(got) != 2 || got[0].Name != "restart" || got[1].InternalHandler != "agent.shell" {
t.Fatalf("expected cloned capabilities, got %+v", got)
}
// Mutating element value fields on the clone must not affect the source.
got[0].Name = "mutated"
got[1].InternalHandler = "leaked"
if r.Capabilities[0].Name != "restart" || r.Capabilities[1].InternalHandler != "agent.shell" {
t.Fatalf("mutation leaked to source: %+v", r.Capabilities)
}
// Appending must not grow the source's backing array.
got = append(got, ResourceCapability{Name: "extra"})
if len(r.Capabilities) != 2 {
t.Fatalf("append leaked to source: source len=%d want 2", len(r.Capabilities))
}
}
// HostView.RAID clones a slice of HostRAIDMeta (with nested Devices + Risk).
func TestHostViewsBranchcov0719late_HostRAID(t *testing.T) {
// (a) nil receiver.
var zero HostView
if got := zero.RAID(); got != nil {
t.Fatalf("nil receiver: expected nil, got %+v", got)
}
// (a) nil Agent.
r := &Resource{ID: "h-raid-1", Type: ResourceTypeAgent}
if got := NewHostView(r).RAID(); got != nil {
t.Fatalf("nil Agent: expected nil, got %+v", got)
}
// (a) Agent present, RAID nil: cloneHostRAIDMetaSlice(nil) returns nil.
r.Agent = &AgentData{}
if got := NewHostView(r).RAID(); got != nil {
t.Fatalf("nil RAID slice: expected nil, got %+v", got)
}
// (b) Populated: deep clone with independent nested Devices/Risk.
r.Agent.RAID = []HostRAIDMeta{
{
Device: "md0",
Level: "raid1",
State: "active",
TotalDevices: 2,
ActiveDevices: 2,
Devices: []HostRAIDDeviceMeta{
{Device: "sda", State: "active", Slot: 0},
{Device: "sdb", State: "active", Slot: 1},
},
Risk: &StorageRisk{
Level: storagehealth.RiskWarning,
Reasons: []StorageRiskReason{{Code: "raid_degraded", Severity: storagehealth.RiskWarning, Summary: "RAID degraded"}},
},
},
}
got := NewHostView(r).RAID()
if len(got) != 1 || got[0].Device != "md0" || len(got[0].Devices) != 2 || got[0].Risk == nil {
t.Fatalf("expected deep-cloned RAID slice, got %+v", got)
}
// Mutating a nested Devices element must not leak to source.
got[0].Devices[0].Device = "mutated"
if r.Agent.RAID[0].Devices[0].Device != "sda" {
t.Fatalf("nested Devices mutation leaked: source[0].Devices[0].Device=%q want %q", r.Agent.RAID[0].Devices[0].Device, "sda")
}
// Truncating nested Devices on the clone must not affect source length.
got[0].Devices = got[0].Devices[:0]
if len(r.Agent.RAID[0].Devices) != 2 {
t.Fatalf("Devices truncation leaked: source len=%d want 2", len(r.Agent.RAID[0].Devices))
}
// Mutating nested Risk.Reasons must not leak to source.
got[0].Risk.Reasons[0].Code = "leaked"
if r.Agent.RAID[0].Risk.Reasons[0].Code != "raid_degraded" {
t.Fatalf("Risk.Reasons mutation leaked: source code=%q want %q", r.Agent.RAID[0].Risk.Reasons[0].Code, "raid_degraded")
}
// Re-clone to verify Risk pointer is a fresh allocation (not shared).
got2 := NewHostView(r).RAID()
if &got2[0].Risk == &r.Agent.RAID[0].Risk {
t.Fatal("expected Risk pointer to be a fresh allocation, not shared with source")
}
}
// HostView.DiskIO clones a slice of HostDiskIOMeta (flat struct).
func TestHostViewsBranchcov0719late_HostDiskIO(t *testing.T) {
// (a) nil receiver.
var zero HostView
if got := zero.DiskIO(); got != nil {
t.Fatalf("nil receiver: expected nil, got %+v", got)
}
// (a) nil Agent.
r := &Resource{ID: "h-dio-1", Type: ResourceTypeAgent}
if got := NewHostView(r).DiskIO(); got != nil {
t.Fatalf("nil Agent: expected nil, got %+v", got)
}
// (a) Agent present, DiskIO nil.
r.Agent = &AgentData{}
if got := NewHostView(r).DiskIO(); got != nil {
t.Fatalf("nil DiskIO slice: expected nil, got %+v", got)
}
// (b) Populated: fresh slice with equal contents.
r.Agent.DiskIO = []HostDiskIOMeta{
{Device: "sda", ReadBytes: 100, WriteBytes: 200, ReadOps: 1, WriteOps: 2},
{Device: "sdb", ReadBytes: 300, WriteBytes: 400, ReadOps: 3, WriteOps: 4},
}
got := NewHostView(r).DiskIO()
if len(got) != 2 || got[0].Device != "sda" || got[1].WriteOps != 4 {
t.Fatalf("expected cloned DiskIO slice, got %+v", got)
}
// Mutate element fields on clone; source unaffected (fresh backing array).
got[0].Device = "mutated"
got[0].ReadBytes = 999
if r.Agent.DiskIO[0].Device != "sda" || r.Agent.DiskIO[0].ReadBytes != 100 {
t.Fatalf("mutation leaked to source: %+v", r.Agent.DiskIO[0])
}
// Append on clone must not affect source.
got = append(got, HostDiskIOMeta{Device: "extra"})
if len(r.Agent.DiskIO) != 2 {
t.Fatalf("append leaked to source: source len=%d want 2", len(r.Agent.DiskIO))
}
}
// HostView.Ceph clones *HostCephMeta (with nested maps/slices).
func TestHostViewsBranchcov0719late_HostCeph(t *testing.T) {
// (a) nil receiver.
var zero HostView
if got := zero.Ceph(); got != nil {
t.Fatalf("nil receiver: expected nil, got %+v", got)
}
// (a) nil Agent.
r := &Resource{ID: "h-ceph-1", Type: ResourceTypeAgent}
if got := NewHostView(r).Ceph(); got != nil {
t.Fatalf("nil Agent: expected nil, got %+v", got)
}
// (a) Agent present, Ceph nil: cloneHostCephMeta(nil) returns nil.
r.Agent = &AgentData{}
if got := NewHostView(r).Ceph(); got != nil {
t.Fatalf("nil Ceph: expected nil, got %+v", got)
}
// (b) Populated: deep clone with independent nested maps/slices.
r.Agent.Ceph = &HostCephMeta{
FSID: "ceph-fsid-1",
HealthStatus: "HEALTH_WARN",
Health: HostCephHealthMeta{
Status: "HEALTH_WARN",
Checks: map[string]HostCephCheckMeta{
"POOL_NEAR_FULL": {Severity: "warning", Message: "pool near full", Detail: []string{"pool1"}},
},
Summary: []HostCephHealthSummaryMeta{{Severity: "warning", Message: "near full"}},
},
Pools: []HostCephPoolMeta{{ID: 1, Name: "pool1", PercentUsed: 0.9}},
Services: []HostCephServiceMeta{
{Type: "mon", Running: 1, Total: 1, Daemons: []string{"mon.a"}},
},
}
got := NewHostView(r).Ceph()
if got == nil || got.FSID != "ceph-fsid-1" || got.HealthStatus != "HEALTH_WARN" {
t.Fatalf("expected cloned ceph meta, got %+v", got)
}
if got.Health.Checks == nil || got.Health.Checks["POOL_NEAR_FULL"].Message != "pool near full" {
t.Fatalf("expected cloned checks map, got %+v", got.Health.Checks)
}
// Mutating the nested map on the clone must not leak to source.
got.Health.Checks["POOL_NEAR_FULL"] = HostCephCheckMeta{Severity: "error", Message: "mutated"}
if r.Agent.Ceph.Health.Checks["POOL_NEAR_FULL"].Message != "pool near full" {
t.Fatalf("Health.Checks mutation leaked: %q", r.Agent.Ceph.Health.Checks["POOL_NEAR_FULL"].Message)
}
// Adding a new key on clone must not affect source map.
got.Health.Checks["NEW"] = HostCephCheckMeta{}
if len(r.Agent.Ceph.Health.Checks) != 1 {
t.Fatalf("map addition leaked: source len=%d want 1", len(r.Agent.Ceph.Health.Checks))
}
// Mutating nested Detail slice via a fresh clone must not leak to source.
fresh := NewHostView(r).Ceph()
fresh.Health.Checks["POOL_NEAR_FULL"].Detail[0] = "leaked"
if r.Agent.Ceph.Health.Checks["POOL_NEAR_FULL"].Detail[0] != "pool1" {
t.Fatalf("Detail mutation leaked: %q", r.Agent.Ceph.Health.Checks["POOL_NEAR_FULL"].Detail[0])
}
// Mutating Pools slice element on clone must not affect source.
got.Pools[0].Name = "leaked"
if r.Agent.Ceph.Pools[0].Name != "pool1" {
t.Fatalf("Pools mutation leaked: %q", r.Agent.Ceph.Pools[0].Name)
}
// Mutating nested Services[].Daemons must not leak to source.
got.Services[0].Daemons[0] = "leaked"
if r.Agent.Ceph.Services[0].Daemons[0] != "mon.a" {
t.Fatalf("Services.Daemons mutation leaked: %q", r.Agent.Ceph.Services[0].Daemons[0])
}
}
// =====================
// DockerHostView accessors
// =====================
// dockerHostFixture returns a Docker host Resource with fully-populated swarm
// collections plus the security/hidden flags used by the accessors under test.
func dockerHostFixture() *Resource {
return &Resource{
ID: "dh-1",
Type: ResourceTypeAgent,
Name: "dh-name",
Docker: &DockerData{
Hidden: true,
Security: &models.DockerHostSecurity{
AuthorizationPlugins: []string{"authz1", "authz2"},
MutatingCommandsBlocked: true,
MutatingCommandsBlockedReason: "policy",
},
Services: []models.DockerService{{ID: "svc-1", Name: "nginx", Stack: "web"}},
Tasks: []models.DockerTask{{ID: "task-1", ServiceID: "svc-1", NodeID: "node-1"}},
Nodes: []models.DockerNode{{ID: "node-1", Hostname: "n1", Role: "manager"}},
Secrets: []models.DockerSecret{{ID: "sec-1", Name: "tls-cert"}},
Configs: []models.DockerConfig{{ID: "cfg-1", Name: "redis-config"}},
},
}
}
// DockerHostView.Services returns a fresh slice; nil-guards return nil.
func TestHostViewsBranchcov0719late_DockerServices(t *testing.T) {
// (a) nil receiver.
var zero DockerHostView
if got := zero.Services(); got != nil {
t.Fatalf("nil receiver: expected nil, got %+v", got)
}
// (a) nil Docker.
r := &Resource{ID: "dh-svc-1", Type: ResourceTypeAgent}
if got := NewDockerHostView(r).Services(); got != nil {
t.Fatalf("nil Docker: expected nil, got %+v", got)
}
// (a) Docker present, Services nil: append of nil yields nil.
r.Docker = &DockerData{}
if got := NewDockerHostView(r).Services(); got != nil {
t.Fatalf("nil Services slice: expected nil, got %+v", got)
}
// (b) Populated: fresh slice with equal contents.
r = dockerHostFixture()
got := NewDockerHostView(r).Services()
if len(got) != 1 || got[0].ID != "svc-1" || got[0].Stack != "web" {
t.Fatalf("expected cloned services, got %+v", got)
}
// Element value-field mutation on clone must not affect source.
got[0].ID = "mutated"
got[0].Stack = "leaked"
if r.Docker.Services[0].ID != "svc-1" || r.Docker.Services[0].Stack != "web" {
t.Fatalf("mutation leaked to source: %+v", r.Docker.Services[0])
}
// Appending to clone must not affect source.
got = append(got, models.DockerService{ID: "extra"})
if len(r.Docker.Services) != 1 {
t.Fatalf("append leaked to source: source len=%d want 1", len(r.Docker.Services))
}
}
// DockerHostView.Tasks returns a fresh slice (not deep-cloned per source comment).
func TestHostViewsBranchcov0719late_DockerTasks(t *testing.T) {
// (a) nil receiver.
var zero DockerHostView
if got := zero.Tasks(); got != nil {
t.Fatalf("nil receiver: expected nil, got %+v", got)
}
// (a) nil Docker.
r := &Resource{ID: "dh-task-1", Type: ResourceTypeAgent}
if got := NewDockerHostView(r).Tasks(); got != nil {
t.Fatalf("nil Docker: expected nil, got %+v", got)
}
// (a) Docker present, Tasks nil.
r.Docker = &DockerData{}
if got := NewDockerHostView(r).Tasks(); got != nil {
t.Fatalf("nil Tasks slice: expected nil, got %+v", got)
}
// (b) Populated: fresh slice with equal contents.
r = dockerHostFixture()
got := NewDockerHostView(r).Tasks()
if len(got) != 1 || got[0].ID != "task-1" || got[0].NodeID != "node-1" {
t.Fatalf("expected cloned tasks, got %+v", got)
}
got[0].ID = "mutated"
got[0].NodeID = "leaked"
if r.Docker.Tasks[0].ID != "task-1" || r.Docker.Tasks[0].NodeID != "node-1" {
t.Fatalf("mutation leaked to source: %+v", r.Docker.Tasks[0])
}
}
// DockerHostView.Nodes returns a fresh slice.
func TestHostViewsBranchcov0719late_DockerNodes(t *testing.T) {
// (a) nil receiver.
var zero DockerHostView
if got := zero.Nodes(); got != nil {
t.Fatalf("nil receiver: expected nil, got %+v", got)
}
// (a) nil Docker.
r := &Resource{ID: "dh-node-1", Type: ResourceTypeAgent}
if got := NewDockerHostView(r).Nodes(); got != nil {
t.Fatalf("nil Docker: expected nil, got %+v", got)
}
// (a) Docker present, Nodes nil.
r.Docker = &DockerData{}
if got := NewDockerHostView(r).Nodes(); got != nil {
t.Fatalf("nil Nodes slice: expected nil, got %+v", got)
}
// (b) Populated: fresh slice with equal contents.
r = dockerHostFixture()
got := NewDockerHostView(r).Nodes()
if len(got) != 1 || got[0].ID != "node-1" || got[0].Role != "manager" {
t.Fatalf("expected cloned nodes, got %+v", got)
}
got[0].ID = "mutated"
got[0].Role = "leaked"
if r.Docker.Nodes[0].ID != "node-1" || r.Docker.Nodes[0].Role != "manager" {
t.Fatalf("mutation leaked to source: %+v", r.Docker.Nodes[0])
}
}
// DockerHostView.Secrets returns a fresh slice.
func TestHostViewsBranchcov0719late_DockerSecrets(t *testing.T) {
// (a) nil receiver.
var zero DockerHostView
if got := zero.Secrets(); got != nil {
t.Fatalf("nil receiver: expected nil, got %+v", got)
}
// (a) nil Docker.
r := &Resource{ID: "dh-sec-1", Type: ResourceTypeAgent}
if got := NewDockerHostView(r).Secrets(); got != nil {
t.Fatalf("nil Docker: expected nil, got %+v", got)
}
// (a) Docker present, Secrets nil.
r.Docker = &DockerData{}
if got := NewDockerHostView(r).Secrets(); got != nil {
t.Fatalf("nil Secrets slice: expected nil, got %+v", got)
}
// (b) Populated: fresh slice with equal contents.
r = dockerHostFixture()
got := NewDockerHostView(r).Secrets()
if len(got) != 1 || got[0].ID != "sec-1" || got[0].Name != "tls-cert" {
t.Fatalf("expected cloned secrets, got %+v", got)
}
got[0].ID = "mutated"
got[0].Name = "leaked"
if r.Docker.Secrets[0].ID != "sec-1" || r.Docker.Secrets[0].Name != "tls-cert" {
t.Fatalf("mutation leaked to source: %+v", r.Docker.Secrets[0])
}
}
// DockerHostView.Configs returns a fresh slice.
func TestHostViewsBranchcov0719late_DockerConfigs(t *testing.T) {
// (a) nil receiver.
var zero DockerHostView
if got := zero.Configs(); got != nil {
t.Fatalf("nil receiver: expected nil, got %+v", got)
}
// (a) nil Docker.
r := &Resource{ID: "dh-cfg-1", Type: ResourceTypeAgent}
if got := NewDockerHostView(r).Configs(); got != nil {
t.Fatalf("nil Docker: expected nil, got %+v", got)
}
// (a) Docker present, Configs nil.
r.Docker = &DockerData{}
if got := NewDockerHostView(r).Configs(); got != nil {
t.Fatalf("nil Configs slice: expected nil, got %+v", got)
}
// (b) Populated: fresh slice with equal contents.
r = dockerHostFixture()
got := NewDockerHostView(r).Configs()
if len(got) != 1 || got[0].ID != "cfg-1" || got[0].Name != "redis-config" {
t.Fatalf("expected cloned configs, got %+v", got)
}
got[0].ID = "mutated"
got[0].Name = "leaked"
if r.Docker.Configs[0].ID != "cfg-1" || r.Docker.Configs[0].Name != "redis-config" {
t.Fatalf("mutation leaked to source: %+v", r.Docker.Configs[0])
}
}
// DockerHostView.Hidden is a three-way short-circuit boolean.
func TestHostViewsBranchcov0719late_DockerHidden(t *testing.T) {
// (a) nil receiver.
var zero DockerHostView
if zero.Hidden() {
t.Fatal("nil receiver: expected false")
}
// (a) nil Docker.
r := &Resource{ID: "dh-hid-1", Type: ResourceTypeAgent}
if NewDockerHostView(r).Hidden() {
t.Fatal("nil Docker: expected false")
}
// (b) Docker present, Hidden=false.
r.Docker = &DockerData{Hidden: false}
if NewDockerHostView(r).Hidden() {
t.Fatal("Hidden=false: expected false")
}
// (b) Docker present, Hidden=true.
r.Docker.Hidden = true
if !NewDockerHostView(r).Hidden() {
t.Fatal("Hidden=true: expected true")
}
}
// DockerHostView.Security guards nil receiver / nil Docker / nil Security and
// returns a shallow copy with an independent AuthorizationPlugins slice.
func TestHostViewsBranchcov0719late_DockerSecurity(t *testing.T) {
// (a) nil receiver.
var zero DockerHostView
if got := zero.Security(); got != nil {
t.Fatalf("nil receiver: expected nil, got %+v", got)
}
// (a) nil Docker.
r := &Resource{ID: "dh-sec-1", Type: ResourceTypeAgent}
if got := NewDockerHostView(r).Security(); got != nil {
t.Fatalf("nil Docker: expected nil, got %+v", got)
}
// (a) Docker present, Security nil.
r.Docker = &DockerData{}
if got := NewDockerHostView(r).Security(); got != nil {
t.Fatalf("nil Security: expected nil, got %+v", got)
}
// (b) Populated: value-equal clone with independent AuthorizationPlugins.
r = dockerHostFixture()
got := NewDockerHostView(r).Security()
if got == nil {
t.Fatal("populated: expected non-nil")
}
if !reflect.DeepEqual(*got, *r.Docker.Security) {
t.Fatalf("expected value-equal clone, got %+v want %+v", *got, *r.Docker.Security)
}
// Mutate scalar on clone; source unaffected.
got.MutatingCommandsBlocked = false
if r.Docker.Security.MutatingCommandsBlocked != true {
t.Fatalf("scalar mutation leaked to source: %+v", r.Docker.Security)
}
// Mutate AuthorizationPlugins element; source unaffected.
got.AuthorizationPlugins[0] = "leaked"
if r.Docker.Security.AuthorizationPlugins[0] != "authz1" {
t.Fatalf("AuthorizationPlugins mutation leaked: %+v", r.Docker.Security.AuthorizationPlugins)
}
// Append to AuthorizationPlugins; source length unchanged.
got.AuthorizationPlugins = append(got.AuthorizationPlugins, "authz3")
if len(r.Docker.Security.AuthorizationPlugins) != 2 {
t.Fatalf("AuthorizationPlugins append leaked: source len=%d want 2", len(r.Docker.Security.AuthorizationPlugins))
}
}

View file

@ -0,0 +1,253 @@
package unifiedresources
import (
"reflect"
"testing"
"time"
)
// TestK8sDeploymentViewBranchcov0719late_NilReceiver exercises the nil-receiver
// arm of every K8sDeploymentView accessor. A zero-value view (no backing
// *Resource) must return zero values without panicking.
func TestK8sDeploymentViewBranchcov0719late_NilReceiver(t *testing.T) {
var v K8sDeploymentView
if got := v.ID(); got != "" {
t.Fatalf("nil-receiver ID: expected %q, got %q", "", got)
}
if got := v.Status(); got != "" {
t.Fatalf("nil-receiver Status: expected %q, got %q", "", got)
}
if got := v.ClusterName(); got != "" {
t.Fatalf("nil-receiver ClusterName: expected %q, got %q", "", got)
}
if got := v.DeploymentUID(); got != "" {
t.Fatalf("nil-receiver DeploymentUID: expected %q, got %q", "", got)
}
if got := v.DesiredReplicas(); got != 0 {
t.Fatalf("nil-receiver DesiredReplicas: expected 0, got %d", got)
}
if got := v.UpdatedReplicas(); got != 0 {
t.Fatalf("nil-receiver UpdatedReplicas: expected 0, got %d", got)
}
if got := v.ReadyReplicas(); got != 0 {
t.Fatalf("nil-receiver ReadyReplicas: expected 0, got %d", got)
}
if got := v.AvailableReplicas(); got != 0 {
t.Fatalf("nil-receiver AvailableReplicas: expected 0, got %d", got)
}
if got := v.Labels(); got != nil {
t.Fatalf("nil-receiver Labels: expected nil, got %+v", got)
}
if got := v.Tags(); got != nil {
t.Fatalf("nil-receiver Tags: expected nil, got %+v", got)
}
if got := v.LastSeen(); !got.IsZero() {
t.Fatalf("nil-receiver LastSeen: expected zero time, got %v", got)
}
if got, want := v.String(), `K8sDeploymentView(, "")`; got != want {
t.Fatalf("nil-receiver String: expected %q, got %q", want, got)
}
}
// TestK8sDeploymentViewBranchcov0719late_NilKubernetesNested exercises the
// nil-nested arm of accessors that dereference v.r.Kubernetes. With a populated
// *Resource but nil Kubernetes payload, Kubernetes-backed accessors must return
// their zero values, while the resource-level accessors (ID/Status/Tags/LastSeen)
// still project the underlying value.
func TestK8sDeploymentViewBranchcov0719late_NilKubernetesNested(t *testing.T) {
now := time.Date(2026, 7, 19, 9, 30, 0, 0, time.UTC)
r := &Resource{
ID: "k8sdep-no-k8s",
Type: ResourceTypeK8sDeployment,
Name: "orphan-deploy",
Status: StatusOnline,
LastSeen: now,
Tags: []string{"k8s", "app:orphan"},
// Kubernetes deliberately nil.
}
v := NewK8sDeploymentView(r)
// Kubernetes-backed accessors -> zero values (nil-nested arm).
if got := v.ClusterName(); got != "" {
t.Fatalf("nil-nested ClusterName: expected %q, got %q", "", got)
}
if got := v.DeploymentUID(); got != "" {
t.Fatalf("nil-nested DeploymentUID: expected %q, got %q", "", got)
}
if got := v.DesiredReplicas(); got != 0 {
t.Fatalf("nil-nested DesiredReplicas: expected 0, got %d", got)
}
if got := v.UpdatedReplicas(); got != 0 {
t.Fatalf("nil-nested UpdatedReplicas: expected 0, got %d", got)
}
if got := v.ReadyReplicas(); got != 0 {
t.Fatalf("nil-nested ReadyReplicas: expected 0, got %d", got)
}
if got := v.AvailableReplicas(); got != 0 {
t.Fatalf("nil-nested AvailableReplicas: expected 0, got %d", got)
}
if got := v.Labels(); got != nil {
t.Fatalf("nil-nested Labels: expected nil, got %+v", got)
}
// Resource-backed accessors still project the underlying value (only nil-r
// guard, which is non-nil here).
if got := v.ID(); got != "k8sdep-no-k8s" {
t.Fatalf("nil-nested ID: expected %q, got %q", "k8sdep-no-k8s", got)
}
if got := v.Status(); got != StatusOnline {
t.Fatalf("nil-nested Status: expected %q, got %q", StatusOnline, got)
}
assertStringSlice(t, v.Tags(), []string{"k8s", "app:orphan"})
if got := v.LastSeen(); !got.Equal(now) {
t.Fatalf("nil-nested LastSeen: expected %v, got %v", now, got)
}
}
// TestK8sDeploymentViewBranchcov0719late_Populated exercises the populated arm
// of every accessor with a fully-populated Kubernetes payload, including
// clone-independence for Labels and Tags (mutating the returned value must not
// affect the backing resource).
func TestK8sDeploymentViewBranchcov0719late_Populated(t *testing.T) {
now := time.Date(2026, 7, 19, 10, 0, 0, 0, time.UTC)
r := &Resource{
ID: "k8sdep-1",
Type: ResourceTypeK8sDeployment,
Name: "frontend",
Status: StatusOnline,
LastSeen: now,
Tags: []string{"k8s", "app:frontend"},
Kubernetes: &K8sData{
ClusterName: "prod-k8s",
Namespace: "web",
DeploymentUID: "deploy-uid-123",
DesiredReplicas: 3,
UpdatedReplicas: 2,
ReadyReplicas: 2,
AvailableReplicas: 1,
Labels: map[string]string{"app": "nginx", "tier": "web"},
},
}
v := NewK8sDeploymentView(r)
if got := v.ID(); got != "k8sdep-1" {
t.Fatalf("populated ID: expected %q, got %q", "k8sdep-1", got)
}
if got := v.Status(); got != StatusOnline {
t.Fatalf("populated Status: expected %q, got %q", StatusOnline, got)
}
if got := v.ClusterName(); got != "prod-k8s" {
t.Fatalf("populated ClusterName: expected %q, got %q", "prod-k8s", got)
}
if got := v.DeploymentUID(); got != "deploy-uid-123" {
t.Fatalf("populated DeploymentUID: expected %q, got %q", "deploy-uid-123", got)
}
if got := v.DesiredReplicas(); got != 3 {
t.Fatalf("populated DesiredReplicas: expected 3, got %d", got)
}
if got := v.UpdatedReplicas(); got != 2 {
t.Fatalf("populated UpdatedReplicas: expected 2, got %d", got)
}
if got := v.ReadyReplicas(); got != 2 {
t.Fatalf("populated ReadyReplicas: expected 2, got %d", got)
}
if got := v.AvailableReplicas(); got != 1 {
t.Fatalf("populated AvailableReplicas: expected 1, got %d", got)
}
wantLabels := map[string]string{"app": "nginx", "tier": "web"}
if got := v.Labels(); !reflect.DeepEqual(got, wantLabels) {
t.Fatalf("populated Labels: expected %+v, got %+v", wantLabels, got)
}
// Clone independence: mutating the returned map must not affect the source.
labelsClone := v.Labels()
labelsClone["app"] = "mutated"
delete(labelsClone, "tier")
labelsClone["new"] = "value"
if got := v.Labels(); !reflect.DeepEqual(got, wantLabels) {
t.Fatalf("populated Labels independence broken: source mutated to %+v", got)
}
assertStringSlice(t, v.Tags(), []string{"k8s", "app:frontend"})
// Clone independence: mutating the returned slice must not affect the source.
tagsClone := v.Tags()
if len(tagsClone) > 0 {
tagsClone[0] = "mutated"
}
if got, want := v.Tags(), ([]string{"k8s", "app:frontend"}); !reflect.DeepEqual(got, want) {
t.Fatalf("populated Tags independence broken: source mutated to %+v", got)
}
if got := v.LastSeen(); !got.Equal(now) {
t.Fatalf("populated LastSeen: expected %v, got %v", now, got)
}
if got, want := v.String(), `K8sDeploymentView(k8sdep-1, "frontend")`; got != want {
t.Fatalf("populated String: expected %q, got %q", want, got)
}
}
// TestK8sClusterViewBranchcov0719late_SourceStatusAgentVersionInterval
// exercises the nil-receiver, nil-Kubernetes-nested, and populated arms of the
// three K8sClusterView accessors delegated to the prompt.
func TestK8sClusterViewBranchcov0719late_SourceStatusAgentVersionInterval(t *testing.T) {
t.Run("NilReceiver", func(t *testing.T) {
var v K8sClusterView
if got := v.SourceStatus(); got != "" {
t.Fatalf("nil-receiver SourceStatus: expected %q, got %q", "", got)
}
if got := v.AgentVersion(); got != "" {
t.Fatalf("nil-receiver AgentVersion: expected %q, got %q", "", got)
}
if got := v.IntervalSeconds(); got != 0 {
t.Fatalf("nil-receiver IntervalSeconds: expected 0, got %d", got)
}
})
t.Run("NilKubernetesNested", func(t *testing.T) {
r := &Resource{
ID: "k8s-no-payload",
Type: ResourceTypeK8sCluster,
Name: "orphan-cluster",
Status: StatusOnline,
LastSeen: time.Date(2026, 7, 19, 10, 30, 0, 0, time.UTC),
// Kubernetes deliberately nil.
}
v := NewK8sClusterView(r)
if got := v.SourceStatus(); got != "" {
t.Fatalf("nil-nested SourceStatus: expected %q, got %q", "", got)
}
if got := v.AgentVersion(); got != "" {
t.Fatalf("nil-nested AgentVersion: expected %q, got %q", "", got)
}
if got := v.IntervalSeconds(); got != 0 {
t.Fatalf("nil-nested IntervalSeconds: expected 0, got %d", got)
}
})
t.Run("Populated", func(t *testing.T) {
r := &Resource{
ID: "k8s-1",
Type: ResourceTypeK8sCluster,
Name: "prod-k8s",
Status: StatusOnline,
LastSeen: time.Date(2026, 7, 19, 11, 0, 0, 0, time.UTC),
Kubernetes: &K8sData{
ClusterName: "prod-k8s",
SourceStatus: "online",
AgentVersion: "1.5.0",
IntervalSeconds: 30,
},
}
v := NewK8sClusterView(r)
if got := v.SourceStatus(); got != "online" {
t.Fatalf("populated SourceStatus: expected %q, got %q", "online", got)
}
if got := v.AgentVersion(); got != "1.5.0" {
t.Fatalf("populated AgentVersion: expected %q, got %q", "1.5.0", got)
}
if got := v.IntervalSeconds(); got != 30 {
t.Fatalf("populated IntervalSeconds: expected 30, got %d", got)
}
})
}

View file

@ -0,0 +1,430 @@
package unifiedresources
import (
"testing"
"time"
)
// This file is a mechanical branch-coverage test for the K8sNodeView accessors
// in views.go. It exercises the nil-receiver arm, the nil-nested-Kubernetes
// arm (where present), and the fully-populated arm of every listed method.
// It deliberately does not touch any source file or pre-existing test.
// k8sNodeBranchcov0719lateResource builds a fully-populated K8sNode *Resource
// exercising every field surfaced by K8sNodeView's accessors.
func k8sNodeBranchcov0719lateResource(now time.Time, parentID string) *Resource {
return &Resource{
ID: "k8snode-1",
Type: ResourceTypeK8sNode,
Name: "worker-1",
Status: StatusOnline,
LastSeen: now,
Tags: []string{"k8s", "role:worker"},
ParentID: &parentID,
Kubernetes: &K8sData{
ClusterName: "prod-cluster",
NodeUID: "uid-node-1",
NodeName: "worker-1",
Ready: true,
Unschedulable: true,
Roles: []string{"control-plane", "worker"},
KubeletVersion: "v1.31.0",
ContainerRuntimeVersion: "containerd://1.7.20",
OSImage: "Ubuntu 24.04 LTS",
KernelVersion: "6.8.0-45-generic",
Architecture: "amd64",
CapacityCPU: 16,
CapacityMemoryBytes: 32 * 1024 * 1024 * 1024,
CapacityPods: 110,
AllocCPU: 15,
AllocMemoryBytes: 30 * 1024 * 1024 * 1024,
AllocPods: 100,
},
Metrics: &ResourceMetrics{
CPU: &MetricValue{Percent: 42.5},
Memory: &MetricValue{Percent: 67.25},
},
}
}
// TestK8sNodeViewBranchcov0719late_NilReceiver covers the v.r == nil arm of
// every accessor plus the String() formatter and the NewK8sNodeView ctor
// (called with a nil *Resource).
func TestK8sNodeViewBranchcov0719late_NilReceiver(t *testing.T) {
v := NewK8sNodeView(nil)
if got := v.ID(); got != "" {
t.Fatalf("ID() nil-receiver: want %q, got %q", "", got)
}
if got := v.Name(); got != "" {
t.Fatalf("Name() nil-receiver: want %q, got %q", "", got)
}
if got := v.Status(); got != ResourceStatus("") {
t.Fatalf("Status() nil-receiver: want empty, got %q", got)
}
if got := v.ClusterName(); got != "" {
t.Fatalf("ClusterName() nil-receiver: want %q, got %q", "", got)
}
if got := v.NodeUID(); got != "" {
t.Fatalf("NodeUID() nil-receiver: want %q, got %q", "", got)
}
if got := v.NodeName(); got != "" {
t.Fatalf("NodeName() nil-receiver: want %q, got %q", "", got)
}
if v.Ready() {
t.Fatalf("Ready() nil-receiver: want false, got true")
}
if v.Unschedulable() {
t.Fatalf("Unschedulable() nil-receiver: want false, got true")
}
if got := v.Roles(); got != nil {
t.Fatalf("Roles() nil-receiver: want nil, got %v", got)
}
if got := v.KubeletVersion(); got != "" {
t.Fatalf("KubeletVersion() nil-receiver: want %q, got %q", "", got)
}
if got := v.ContainerRuntimeVersion(); got != "" {
t.Fatalf("ContainerRuntimeVersion() nil-receiver: want %q, got %q", "", got)
}
if got := v.OSImage(); got != "" {
t.Fatalf("OSImage() nil-receiver: want %q, got %q", "", got)
}
if got := v.KernelVersion(); got != "" {
t.Fatalf("KernelVersion() nil-receiver: want %q, got %q", "", got)
}
if got := v.Architecture(); got != "" {
t.Fatalf("Architecture() nil-receiver: want %q, got %q", "", got)
}
if got := v.CapacityCPU(); got != 0 {
t.Fatalf("CapacityCPU() nil-receiver: want 0, got %d", got)
}
if got := v.CapacityMemoryBytes(); got != 0 {
t.Fatalf("CapacityMemoryBytes() nil-receiver: want 0, got %d", got)
}
if got := v.CapacityPods(); got != 0 {
t.Fatalf("CapacityPods() nil-receiver: want 0, got %d", got)
}
if got := v.AllocCPU(); got != 0 {
t.Fatalf("AllocCPU() nil-receiver: want 0, got %d", got)
}
if got := v.AllocMemoryBytes(); got != 0 {
t.Fatalf("AllocMemoryBytes() nil-receiver: want 0, got %d", got)
}
if got := v.AllocPods(); got != 0 {
t.Fatalf("AllocPods() nil-receiver: want 0, got %d", got)
}
if got := v.CPUPercent(); got != 0 {
t.Fatalf("CPUPercent() nil-receiver: want 0, got %v", got)
}
if got := v.MemoryPercent(); got != 0 {
t.Fatalf("MemoryPercent() nil-receiver: want 0, got %v", got)
}
if got := v.Tags(); got != nil {
t.Fatalf("Tags() nil-receiver: want nil, got %v", got)
}
if got := v.LastSeen(); !got.IsZero() {
t.Fatalf("LastSeen() nil-receiver: want zero time, got %v", got)
}
if got := v.ParentID(); got != "" {
t.Fatalf("ParentID() nil-receiver: want %q, got %q", "", got)
}
// String() must not panic on a nil-receiver and must report empty id/name.
if got := v.String(); got != `K8sNodeView(, "")` {
t.Fatalf("String() nil-receiver: want %q, got %q", `K8sNodeView(, "")`, got)
}
}
// TestK8sNodeViewBranchcov0719late_NilKubernetesNested covers the
// v.r.Kubernetes == nil arm of every Kubernetes-backed accessor. The
// non-Kubernetes accessors (ID/Name/Status/Tags/LastSeen/CPUPercent/
// MemoryPercent/ParentID) are also exercised to confirm they still project
// from the outer Resource when Kubernetes is nil.
func TestK8sNodeViewBranchcov0719late_NilKubernetesNested(t *testing.T) {
now := time.Date(2026, 7, 19, 9, 30, 0, 0, time.UTC)
parentID := "cluster-parent-1"
r := &Resource{
ID: "k8snode-no-k8s",
Type: ResourceTypeK8sNode,
Name: "worker-bare",
Status: StatusOffline,
LastSeen: now,
Tags: []string{"bare"},
ParentID: &parentID,
// Kubernetes intentionally nil.
// Metrics intentionally nil so CPUPercent/MemoryPercent go through
// their nil-receiver-equivalent path via viewMetricPercent(nil, ...).
}
v := NewK8sNodeView(r)
// Kubernetes-backed accessors: all should return their zero value.
if got := v.ClusterName(); got != "" {
t.Fatalf("ClusterName() Kubernetes==nil: want %q, got %q", "", got)
}
if got := v.NodeUID(); got != "" {
t.Fatalf("NodeUID() Kubernetes==nil: want %q, got %q", "", got)
}
if got := v.NodeName(); got != "" {
t.Fatalf("NodeName() Kubernetes==nil: want %q, got %q", "", got)
}
if v.Ready() {
t.Fatalf("Ready() Kubernetes==nil: want false, got true")
}
if v.Unschedulable() {
t.Fatalf("Unschedulable() Kubernetes==nil: want false, got true")
}
if got := v.Roles(); got != nil {
t.Fatalf("Roles() Kubernetes==nil: want nil, got %v", got)
}
if got := v.KubeletVersion(); got != "" {
t.Fatalf("KubeletVersion() Kubernetes==nil: want %q, got %q", "", got)
}
if got := v.ContainerRuntimeVersion(); got != "" {
t.Fatalf("ContainerRuntimeVersion() Kubernetes==nil: want %q, got %q", "", got)
}
if got := v.OSImage(); got != "" {
t.Fatalf("OSImage() Kubernetes==nil: want %q, got %q", "", got)
}
if got := v.KernelVersion(); got != "" {
t.Fatalf("KernelVersion() Kubernetes==nil: want %q, got %q", "", got)
}
if got := v.Architecture(); got != "" {
t.Fatalf("Architecture() Kubernetes==nil: want %q, got %q", "", got)
}
if got := v.CapacityCPU(); got != 0 {
t.Fatalf("CapacityCPU() Kubernetes==nil: want 0, got %d", got)
}
if got := v.CapacityMemoryBytes(); got != 0 {
t.Fatalf("CapacityMemoryBytes() Kubernetes==nil: want 0, got %d", got)
}
if got := v.CapacityPods(); got != 0 {
t.Fatalf("CapacityPods() Kubernetes==nil: want 0, got %d", got)
}
if got := v.AllocCPU(); got != 0 {
t.Fatalf("AllocCPU() Kubernetes==nil: want 0, got %d", got)
}
if got := v.AllocMemoryBytes(); got != 0 {
t.Fatalf("AllocMemoryBytes() Kubernetes==nil: want 0, got %d", got)
}
if got := v.AllocPods(); got != 0 {
t.Fatalf("AllocPods() Kubernetes==nil: want 0, got %d", got)
}
// Non-Kubernetes accessors must still project the outer Resource values.
if got := v.ID(); got != "k8snode-no-k8s" {
t.Fatalf("ID() Kubernetes==nil: want %q, got %q", "k8snode-no-k8s", got)
}
if got := v.Name(); got != "worker-bare" {
t.Fatalf("Name() Kubernetes==nil: want %q, got %q", "worker-bare", got)
}
if got := v.Status(); got != StatusOffline {
t.Fatalf("Status() Kubernetes==nil: want %q, got %q", StatusOffline, got)
}
if got := v.CPUPercent(); got != 0 {
t.Fatalf("CPUPercent() Metrics==nil: want 0, got %v", got)
}
if got := v.MemoryPercent(); got != 0 {
t.Fatalf("MemoryPercent() Metrics==nil: want 0, got %v", got)
}
assertStringSlice(t, v.Tags(), []string{"bare"})
if got := v.LastSeen(); !got.Equal(now) {
t.Fatalf("LastSeen() Kubernetes==nil: want %v, got %v", now, got)
}
if got := v.ParentID(); got != parentID {
t.Fatalf("ParentID() Kubernetes==nil: want %q, got %q", parentID, got)
}
}
// TestK8sNodeViewBranchcov0719late_Populated covers the fully-populated arm of
// every accessor and verifies that slice-returning accessors (Roles, Tags)
// produce independent copies (defensive clone contract).
func TestK8sNodeViewBranchcov0719late_Populated(t *testing.T) {
now := time.Date(2026, 7, 19, 10, 0, 0, 0, time.UTC)
parentID := "cluster-parent-1"
r := k8sNodeBranchcov0719lateResource(now, parentID)
v := NewK8sNodeView(r)
if got := v.ID(); got != "k8snode-1" {
t.Fatalf("ID(): want %q, got %q", "k8snode-1", got)
}
if got := v.Name(); got != "worker-1" {
t.Fatalf("Name(): want %q, got %q", "worker-1", got)
}
if got := v.Status(); got != StatusOnline {
t.Fatalf("Status(): want %q, got %q", StatusOnline, got)
}
if got := v.ClusterName(); got != "prod-cluster" {
t.Fatalf("ClusterName(): want %q, got %q", "prod-cluster", got)
}
if got := v.NodeUID(); got != "uid-node-1" {
t.Fatalf("NodeUID(): want %q, got %q", "uid-node-1", got)
}
if got := v.NodeName(); got != "worker-1" {
t.Fatalf("NodeName(): want %q, got %q", "worker-1", got)
}
if !v.Ready() {
t.Fatalf("Ready(): want true, got false")
}
if !v.Unschedulable() {
t.Fatalf("Unschedulable(): want true, got false")
}
assertStringSlice(t, v.Roles(), []string{"control-plane", "worker"})
if got := v.KubeletVersion(); got != "v1.31.0" {
t.Fatalf("KubeletVersion(): want %q, got %q", "v1.31.0", got)
}
if got := v.ContainerRuntimeVersion(); got != "containerd://1.7.20" {
t.Fatalf("ContainerRuntimeVersion(): want %q, got %q", "containerd://1.7.20", got)
}
if got := v.OSImage(); got != "Ubuntu 24.04 LTS" {
t.Fatalf("OSImage(): want %q, got %q", "Ubuntu 24.04 LTS", got)
}
if got := v.KernelVersion(); got != "6.8.0-45-generic" {
t.Fatalf("KernelVersion(): want %q, got %q", "6.8.0-45-generic", got)
}
if got := v.Architecture(); got != "amd64" {
t.Fatalf("Architecture(): want %q, got %q", "amd64", got)
}
if got := v.CapacityCPU(); got != 16 {
t.Fatalf("CapacityCPU(): want 16, got %d", got)
}
const capMem = int64(32) * 1024 * 1024 * 1024
if got := v.CapacityMemoryBytes(); got != capMem {
t.Fatalf("CapacityMemoryBytes(): want %d, got %d", capMem, got)
}
if got := v.CapacityPods(); got != 110 {
t.Fatalf("CapacityPods(): want 110, got %d", got)
}
if got := v.AllocCPU(); got != 15 {
t.Fatalf("AllocCPU(): want 15, got %d", got)
}
const allocMem = int64(30) * 1024 * 1024 * 1024
if got := v.AllocMemoryBytes(); got != allocMem {
t.Fatalf("AllocMemoryBytes(): want %d, got %d", allocMem, got)
}
if got := v.AllocPods(); got != 100 {
t.Fatalf("AllocPods(): want 100, got %d", got)
}
if got := v.CPUPercent(); got != 42.5 {
t.Fatalf("CPUPercent(): want %v, got %v", 42.5, got)
}
if got := v.MemoryPercent(); got != 67.25 {
t.Fatalf("MemoryPercent(): want %v, got %v", 67.25, got)
}
assertStringSlice(t, v.Tags(), []string{"k8s", "role:worker"})
if got := v.LastSeen(); !got.Equal(now) {
t.Fatalf("LastSeen(): want %v, got %v", now, got)
}
if got := v.ParentID(); got != parentID {
t.Fatalf("ParentID(): want %q, got %q", parentID, got)
}
// Defensive-clone contract: mutating returned slices must not leak back
// into the backing *Resource.
roles := v.Roles()
if len(roles) != 2 {
t.Fatalf("Roles(): want len 2, got %d", len(roles))
}
roles[0] = "MUTATED"
roles = append(roles, "extra")
if got := v.Roles(); len(got) != 2 || got[0] != "control-plane" || got[2-1] != "worker" {
t.Fatalf("Roles() independence: want [control-plane worker], got %v", got)
}
if r.Kubernetes.Roles[0] != "control-plane" {
t.Fatalf("Roles() mutation leaked into backing Resource: got %v", r.Kubernetes.Roles)
}
tags := v.Tags()
if len(tags) != 2 {
t.Fatalf("Tags(): want len 2, got %d", len(tags))
}
tags[0] = "MUTATED"
tags = append(tags, "extra")
if got := v.Tags(); len(got) != 2 || got[0] != "k8s" || got[1] != "role:worker" {
t.Fatalf("Tags() independence: want [k8s role:worker], got %v", got)
}
if r.Tags[0] != "k8s" {
t.Fatalf("Tags() mutation leaked into backing Resource: got %v", r.Tags)
}
}
// TestK8sNodeViewBranchcov0719late_NilParentID covers the v.r.ParentID == nil
// arm of ParentID() specifically (r is non-nil, Kubernetes is populated, but
// ParentID is nil).
func TestK8sNodeViewBranchcov0719late_NilParentID(t *testing.T) {
now := time.Date(2026, 7, 19, 11, 0, 0, 0, time.UTC)
r := &Resource{
ID: "k8snode-no-parent",
Type: ResourceTypeK8sNode,
Name: "orphan-node",
Status: StatusOnline,
LastSeen: now,
Kubernetes: &K8sData{
NodeName: "orphan-node",
Ready: true,
},
}
v := NewK8sNodeView(r)
if got := v.ParentID(); got != "" {
t.Fatalf("ParentID() ParentID==nil: want %q, got %q", "", got)
}
if got := v.NodeName(); got != "orphan-node" {
t.Fatalf("NodeName() populated arm: want %q, got %q", "orphan-node", got)
}
}
// TestK8sNodeViewBranchcov0719late_StringAndCtor covers the String() formatter
// and the NewK8sNodeView constructor wrapping behavior on a populated
// resource.
func TestK8sNodeViewBranchcov0719late_StringAndCtor(t *testing.T) {
now := time.Date(2026, 7, 19, 12, 0, 0, 0, time.UTC)
parentID := "cluster-parent-1"
r := k8sNodeBranchcov0719lateResource(now, parentID)
v := NewK8sNodeView(r)
want := `K8sNodeView(k8snode-1, "worker-1")`
if got := v.String(); got != want {
t.Fatalf("String(): want %q, got %q", want, got)
}
// NewK8sNodeView must wrap the provided *Resource (ID() round-trips the
// same value the Resource carries).
if v.ID() != r.ID {
t.Fatalf("NewK8sNodeView wrap: want ID %q, got %q", r.ID, v.ID())
}
}
// TestK8sNodeViewBranchcov0719late_EmptyRolesAndTags covers the edge case
// where Kubernetes is non-nil but Roles is empty/nil, and Tags is empty/nil.
// cloneStringSlice(nil) returns nil; cloneStringSlice([]string{}) returns an
// empty (non-nil) slice — both must be handled without panic.
func TestK8sNodeViewBranchcov0719late_EmptyRolesAndTags(t *testing.T) {
r := &Resource{
ID: "k8snode-empty-slices",
Type: ResourceTypeK8sNode,
Name: "empty-node",
Status: StatusOnline,
LastSeen: time.Date(2026, 7, 19, 13, 0, 0, 0, time.UTC),
Kubernetes: &K8sData{
NodeName: "empty-node",
// Roles intentionally nil.
},
// Tags intentionally nil.
}
v := NewK8sNodeView(r)
if got := v.Roles(); got != nil {
t.Fatalf("Roles() nil-slice: want nil, got %v", got)
}
if got := v.Tags(); got != nil {
t.Fatalf("Tags() nil-slice: want nil, got %v", got)
}
// And the empty (non-nil) slice variant for both.
r.Kubernetes.Roles = []string{}
r.Tags = []string{}
if got := v.Roles(); len(got) != 0 {
t.Fatalf("Roles() empty-slice: want len 0, got %d (%v)", len(got), got)
}
if got := v.Tags(); len(got) != 0 {
t.Fatalf("Tags() empty-slice: want len 0, got %d (%v)", len(got), got)
}
}

View file

@ -0,0 +1,204 @@
package unifiedresources
import (
"reflect"
"testing"
)
// These tests augment views_test.go with branch-coverage assertions for the
// misc-view accessors and String() formatters requested for the 0719late
// coverage pass. They reuse the package's existing testResource helper and
// table-driven style, and they intentionally never mutate source under test.
func TestContainerViewPool_MiscViewsBranchcov0719late(t *testing.T) {
// Arm: nil receiver must return "" (v.r == nil branch).
var zero ContainerView
if got := zero.Pool(); got != "" {
t.Fatalf("nil receiver Pool: expected %q, got %q", "", got)
}
// Arm: resource present but Proxmox payload nil must return "" (v.r.Proxmox == nil branch).
rNoProx := testResource(ResourceTypeSystemContainer)
rNoProx.Proxmox = nil
if got := NewContainerView(rNoProx).Pool(); got != "" {
t.Fatalf("nil Proxmox Pool: expected %q, got %q", "", got)
}
// Arm: populated exercises strings.TrimSpace(" production ").
rPop := testResource(ResourceTypeSystemContainer)
rPop.Proxmox = &ProxmoxData{Pool: " production "}
if got, want := NewContainerView(rPop).Pool(), "production"; got != want {
t.Fatalf("populated Pool: expected %q, got %q", want, got)
}
}
func TestNodeViewIsClusterMember_MiscViewsBranchcov0719late(t *testing.T) {
// Arm: nil receiver must return false (v.r == nil branch).
var zero NodeView
if zero.IsClusterMember() {
t.Fatalf("nil receiver IsClusterMember: expected %v, got %v", false, true)
}
// Arm: resource present but Proxmox nil must return false (v.r.Proxmox == nil branch).
rNoProx := testResource(ResourceTypeAgent)
rNoProx.Proxmox = nil
if NewNodeView(rNoProx).IsClusterMember() {
t.Fatalf("nil Proxmox IsClusterMember: expected %v, got %v", false, true)
}
// Arm: populated true projects the underlying flag.
rTrue := testResource(ResourceTypeAgent)
rTrue.Proxmox = &ProxmoxData{IsClusterMember: true}
if !NewNodeView(rTrue).IsClusterMember() {
t.Fatalf("populated IsClusterMember=true: expected %v, got %v", true, false)
}
// Arm: populated false projects the underlying flag (explicit boundary).
rFalse := testResource(ResourceTypeAgent)
rFalse.Proxmox = &ProxmoxData{IsClusterMember: false}
if NewNodeView(rFalse).IsClusterMember() {
t.Fatalf("populated IsClusterMember=false: expected %v, got %v", false, true)
}
}
func TestPhysicalDiskViewMetricResourceID_MiscViewsBranchcov0719late(t *testing.T) {
// Arm: nil receiver must return "" (v.r == nil branch).
var zero PhysicalDiskView
if got := zero.MetricResourceID(); got != "" {
t.Fatalf("nil receiver MetricResourceID: expected %q, got %q", "", got)
}
// Arm: MetricsTarget non-nil wins, even when PhysicalDisk would otherwise resolve.
rTarget := testResource(ResourceTypePhysicalDisk)
rTarget.MetricsTarget = &MetricsTarget{ResourceID: "vc-1:disk:serial-abc"}
rTarget.PhysicalDisk = &PhysicalDiskMeta{Serial: "should-not-win"}
if got, want := NewPhysicalDiskView(rTarget).MetricResourceID(), "vc-1:disk:serial-abc"; got != want {
t.Fatalf("MetricsTarget arm: expected %q, got %q", want, got)
}
// Arm: MetricsTarget nil and PhysicalDisk has Serial → PhysicalDiskMetaMetricID returns trimmed serial.
rSerial := testResource(ResourceTypePhysicalDisk)
rSerial.PhysicalDisk = &PhysicalDiskMeta{Serial: " SER123 "}
if got, want := NewPhysicalDiskView(rSerial).MetricResourceID(), "SER123"; got != want {
t.Fatalf("PhysicalDiskMetaMetricID serial fallback arm: expected %q, got %q", want, got)
}
// Arm: MetricsTarget nil and PhysicalDisk nil → fallback to trimmed resource ID.
rFallback := testResource(ResourceTypePhysicalDisk)
rFallback.ID = " disk-id-1 "
rFallback.PhysicalDisk = nil
if got, want := NewPhysicalDiskView(rFallback).MetricResourceID(), "disk-id-1"; got != want {
t.Fatalf("PhysicalDiskMetaMetricID nil-disk fallback arm: expected %q, got %q", want, got)
}
}
func TestPBSInstanceViewDatastores_MiscViewsBranchcov0719late(t *testing.T) {
// Arm: nil receiver must return nil (v.r == nil branch).
var zero PBSInstanceView
if got := zero.Datastores(); got != nil {
t.Fatalf("nil receiver Datastores: expected nil, got %+v", got)
}
// Arm: resource present but PBS nil must return nil (v.r.PBS == nil branch).
rNoPBS := testResource(ResourceTypePBS)
rNoPBS.PBS = nil
if got := NewPBSInstanceView(rNoPBS).Datastores(); got != nil {
t.Fatalf("nil PBS Datastores: expected nil, got %+v", got)
}
// Arm: PBS present but Datastores slice itself nil must still return nil.
rNilSlice := testResource(ResourceTypePBS)
rNilSlice.PBS = &PBSData{}
if got := NewPBSInstanceView(rNilSlice).Datastores(); got != nil {
t.Fatalf("nil Datastores slice: expected nil, got %+v", got)
}
// Arm: populated multiple datastores project correctly AND the clone is independent.
want := []PBSDatastoreMeta{
{Name: "fast", Total: 100, Used: 96, Available: 4, UsagePercent: 96, Status: "online", DeduplicationFactor: 1.6},
{Name: "archive", Total: 1000, Used: 500, Available: 500, UsagePercent: 50, Status: "online"},
}
rPop := testResource(ResourceTypePBS)
rPop.PBS = &PBSData{Datastores: want}
got := NewPBSInstanceView(rPop).Datastores()
if !reflect.DeepEqual(got, want) {
t.Fatalf("populated Datastores: expected %+v, got %+v", want, got)
}
// Mutating the returned slice (and its elements) must not affect the backing resource.
got[0].Name = "mutated"
got[0].Total = 9999
again := NewPBSInstanceView(rPop).Datastores()
if !reflect.DeepEqual(again, want) {
t.Fatalf("Datastores independence: expected clone to remain %+v, got %+v", want, again)
}
}
func TestPMGInstanceViewInstanceID_MiscViewsBranchcov0719late(t *testing.T) {
// Arm: nil receiver must return "" (v.r == nil branch).
var zero PMGInstanceView
if got := zero.InstanceID(); got != "" {
t.Fatalf("nil receiver InstanceID: expected %q, got %q", "", got)
}
// Arm: resource present but PMG nil must return "" (v.r.PMG == nil branch).
rNoPMG := testResource(ResourceTypePMG)
rNoPMG.PMG = nil
if got := NewPMGInstanceView(rNoPMG).InstanceID(); got != "" {
t.Fatalf("nil PMG InstanceID: expected %q, got %q", "", got)
}
// Arm: populated projects the underlying InstanceID verbatim.
rPop := testResource(ResourceTypePMG)
rPop.PMG = &PMGData{InstanceID: "pmg-instance-1"}
if got, want := NewPMGInstanceView(rPop).InstanceID(), "pmg-instance-1"; got != want {
t.Fatalf("populated InstanceID: expected %q, got %q", want, got)
}
}
func TestViewsStringMethods_MiscViewsBranchcov0719late(t *testing.T) {
// Populated arm: each formatter must compose ID()/Name() as `<Type>(<id>, "<name>")`.
populatedCases := []struct {
label string
got string
want string
}{
{"VMView", NewVMView(&Resource{ID: "vm-1", Type: ResourceTypeVM, Name: "app-vm"}).String(), `VMView(vm-1, "app-vm")`},
{"ContainerView", NewContainerView(&Resource{ID: "ct-1", Type: ResourceTypeSystemContainer, Name: "db-ct"}).String(), `ContainerView(ct-1, "db-ct")`},
{"NodeView", NewNodeView(&Resource{ID: "node-1", Type: ResourceTypeAgent, Name: "pve-node-1"}).String(), `NodeView(node-1, "pve-node-1")`},
{"StoragePoolView", NewStoragePoolView(&Resource{ID: "storage-1", Type: ResourceTypeStorage, Name: "local-zfs"}).String(), `StoragePoolView(storage-1, "local-zfs")`},
{"PhysicalDiskView", NewPhysicalDiskView(&Resource{ID: "disk-1", Type: ResourceTypePhysicalDisk, Name: "Samsung 990 PRO"}).String(), `PhysicalDiskView(disk-1, "Samsung 990 PRO")`},
{"PBSInstanceView", NewPBSInstanceView(&Resource{ID: "pbs-1", Type: ResourceTypePBS, Name: "pbs-a"}).String(), `PBSInstanceView(pbs-1, "pbs-a")`},
{"PMGInstanceView", NewPMGInstanceView(&Resource{ID: "pmg-1", Type: ResourceTypePMG, Name: "pmg-a"}).String(), `PMGInstanceView(pmg-1, "pmg-a")`},
{"WorkloadView", NewWorkloadView(&Resource{ID: "vm-2", Type: ResourceTypeVM, Name: "web-vm"}).String(), `WorkloadView(vm-2, "web-vm")`},
{"InfrastructureView", NewInfrastructureView(&Resource{ID: "host-1", Type: ResourceTypeAgent, Name: "agent-host-1"}).String(), `InfrastructureView(host-1, "agent-host-1")`},
}
for _, c := range populatedCases {
if c.got != c.want {
t.Errorf("%s populated String(): expected %q, got %q", c.label, c.want, c.got)
}
}
// Nil-receiver arm: every String() must not panic and must render the empty-id/empty-name form.
nilCases := []struct {
label string
got string
want string
}{
{"VMView nil", VMView{}.String(), `VMView(, "")`},
{"ContainerView nil", ContainerView{}.String(), `ContainerView(, "")`},
{"NodeView nil", NodeView{}.String(), `NodeView(, "")`},
{"StoragePoolView nil", StoragePoolView{}.String(), `StoragePoolView(, "")`},
{"PhysicalDiskView nil", PhysicalDiskView{}.String(), `PhysicalDiskView(, "")`},
{"PBSInstanceView nil", PBSInstanceView{}.String(), `PBSInstanceView(, "")`},
{"PMGInstanceView nil", PMGInstanceView{}.String(), `PMGInstanceView(, "")`},
{"WorkloadView nil", WorkloadView{}.String(), `WorkloadView(, "")`},
{"InfrastructureView nil", InfrastructureView{}.String(), `InfrastructureView(, "")`},
}
for _, c := range nilCases {
if c.got != c.want {
t.Errorf("%s String(): expected %q, got %q", c.label, c.want, c.got)
}
}
}

View file

@ -0,0 +1,388 @@
package unifiedresources
import (
"testing"
"time"
)
// branchcov0719latePodResource builds a fully-populated Pod resource used to
// exercise the populated arm of every PodView accessor. The nil-receiver and
// nil-Kubernetes arms are covered separately in each test below.
func branchcov0719latePodResource(now time.Time) *Resource {
return &Resource{
ID: "pod-id-1",
Type: ResourceTypePod,
Name: "pod-name-1",
Status: StatusOnline,
LastSeen: now,
Tags: []string{"app:web", "tier:frontend"},
Kubernetes: &K8sData{
ClusterID: "cluster-id-1",
ClusterName: "prod-cluster",
NodeName: "node-a",
Namespace: "checkout",
PodUID: "uid-1234",
PodPhase: "Running",
PodReason: "OutOfcpu",
PodMessage: "Pod was terminated due to cpu limit.",
Restarts: 3,
OwnerKind: "ReplicaSet",
OwnerName: "checkout-abc",
Image: "ghcr.io/example/checkout:v1.2.3",
PodContainers: []K8sPodContainer{
{Name: "app", Image: "ghcr.io/example/checkout:v1.2.3", Ready: true, RestartCount: 1, State: "running"},
{Name: "sidecar", Image: "busybox:1.36", Ready: false, RestartCount: 2, State: "waiting", Reason: "CrashLoopBackOff", Message: "Back-off pulling image"},
},
},
Metrics: &ResourceMetrics{
CPU: &MetricValue{Percent: 42.5},
Memory: &MetricValue{Percent: 55.0},
Disk: &MetricValue{Percent: 12.0},
NetIn: &MetricValue{Value: 1024.5},
NetOut: &MetricValue{Value: 2048.0},
},
}
}
// TestPodViewBranchcov0719late_StringIDStatus covers String, ID and Status
// across the nil-receiver and populated arms.
func TestPodViewBranchcov0719late_StringIDStatus(t *testing.T) {
now := time.Date(2026, 7, 19, 12, 0, 0, 0, time.UTC)
// Nil-receiver arm: every accessor must return its zero value without panic.
t.Run("NilReceiver", func(t *testing.T) {
var zero PodView
if got := zero.String(); got != `PodView(, "")` {
t.Fatalf("nil String(): got %q want %q", got, `PodView(, "")`)
}
if zero.ID() != "" {
t.Fatalf("nil ID(): got %q want empty", zero.ID())
}
if zero.Status() != ResourceStatus("") {
t.Fatalf("nil Status(): got %q want empty", zero.Status())
}
})
// Populated arm.
t.Run("Populated", func(t *testing.T) {
v := NewPodView(branchcov0719latePodResource(now))
if got, want := v.String(), `PodView(pod-id-1, "pod-name-1")`; got != want {
t.Fatalf("String(): got %q want %q", got, want)
}
if v.ID() != "pod-id-1" {
t.Fatalf("ID(): got %q want %q", v.ID(), "pod-id-1")
}
if v.Status() != StatusOnline {
t.Fatalf("Status(): got %q want %q", v.Status(), StatusOnline)
}
})
}
// TestPodViewBranchcov0719late_KubernetesFields covers the Kubernetes-backed
// accessors: ClusterName, ClusterID, NodeName, PodUID, PodPhase, Restarts,
// OwnerKind, OwnerName, Image, PodReason, PodMessage. Each has both a
// nil-receiver arm and a nil-Kubernetes-nested arm, plus the populated arm.
func TestPodViewBranchcov0719late_KubernetesFields(t *testing.T) {
now := time.Date(2026, 7, 19, 12, 0, 0, 0, time.UTC)
t.Run("NilReceiver", func(t *testing.T) {
var zero PodView
if zero.ClusterName() != "" {
t.Fatalf("nil ClusterName(): got %q want empty", zero.ClusterName())
}
if zero.ClusterID() != "" {
t.Fatalf("nil ClusterID(): got %q want empty", zero.ClusterID())
}
if zero.NodeName() != "" {
t.Fatalf("nil NodeName(): got %q want empty", zero.NodeName())
}
if zero.PodUID() != "" {
t.Fatalf("nil PodUID(): got %q want empty", zero.PodUID())
}
if zero.PodPhase() != "" {
t.Fatalf("nil PodPhase(): got %q want empty", zero.PodPhase())
}
if zero.Restarts() != 0 {
t.Fatalf("nil Restarts(): got %d want 0", zero.Restarts())
}
if zero.OwnerKind() != "" {
t.Fatalf("nil OwnerKind(): got %q want empty", zero.OwnerKind())
}
if zero.OwnerName() != "" {
t.Fatalf("nil OwnerName(): got %q want empty", zero.OwnerName())
}
if zero.Image() != "" {
t.Fatalf("nil Image(): got %q want empty", zero.Image())
}
if zero.PodReason() != "" {
t.Fatalf("nil PodReason(): got %q want empty", zero.PodReason())
}
if zero.PodMessage() != "" {
t.Fatalf("nil PodMessage(): got %q want empty", zero.PodMessage())
}
})
// Nested-nil arm: Resource is present but Kubernetes is nil.
t.Run("NilKubernetes", func(t *testing.T) {
r := testResource(ResourceTypePod)
r.Kubernetes = nil
v := NewPodView(r)
if v.ClusterName() != "" {
t.Fatalf("ClusterName() with nil Kubernetes: got %q want empty", v.ClusterName())
}
if v.ClusterID() != "" {
t.Fatalf("ClusterID() with nil Kubernetes: got %q want empty", v.ClusterID())
}
if v.NodeName() != "" {
t.Fatalf("NodeName() with nil Kubernetes: got %q want empty", v.NodeName())
}
if v.PodUID() != "" {
t.Fatalf("PodUID() with nil Kubernetes: got %q want empty", v.PodUID())
}
if v.PodPhase() != "" {
t.Fatalf("PodPhase() with nil Kubernetes: got %q want empty", v.PodPhase())
}
if v.Restarts() != 0 {
t.Fatalf("Restarts() with nil Kubernetes: got %d want 0", v.Restarts())
}
if v.OwnerKind() != "" {
t.Fatalf("OwnerKind() with nil Kubernetes: got %q want empty", v.OwnerKind())
}
if v.OwnerName() != "" {
t.Fatalf("OwnerName() with nil Kubernetes: got %q want empty", v.OwnerName())
}
if v.Image() != "" {
t.Fatalf("Image() with nil Kubernetes: got %q want empty", v.Image())
}
if v.PodReason() != "" {
t.Fatalf("PodReason() with nil Kubernetes: got %q want empty", v.PodReason())
}
if v.PodMessage() != "" {
t.Fatalf("PodMessage() with nil Kubernetes: got %q want empty", v.PodMessage())
}
})
// Populated arm: each accessor projects its backing field verbatim.
t.Run("Populated", func(t *testing.T) {
v := NewPodView(branchcov0719latePodResource(now))
if v.ClusterName() != "prod-cluster" {
t.Fatalf("ClusterName(): got %q want %q", v.ClusterName(), "prod-cluster")
}
if v.ClusterID() != "cluster-id-1" {
t.Fatalf("ClusterID(): got %q want %q", v.ClusterID(), "cluster-id-1")
}
if v.NodeName() != "node-a" {
t.Fatalf("NodeName(): got %q want %q", v.NodeName(), "node-a")
}
if v.PodUID() != "uid-1234" {
t.Fatalf("PodUID(): got %q want %q", v.PodUID(), "uid-1234")
}
if v.PodPhase() != "Running" {
t.Fatalf("PodPhase(): got %q want %q", v.PodPhase(), "Running")
}
if v.Restarts() != 3 {
t.Fatalf("Restarts(): got %d want 3", v.Restarts())
}
if v.OwnerKind() != "ReplicaSet" {
t.Fatalf("OwnerKind(): got %q want %q", v.OwnerKind(), "ReplicaSet")
}
if v.OwnerName() != "checkout-abc" {
t.Fatalf("OwnerName(): got %q want %q", v.OwnerName(), "checkout-abc")
}
if v.Image() != "ghcr.io/example/checkout:v1.2.3" {
t.Fatalf("Image(): got %q want %q", v.Image(), "ghcr.io/example/checkout:v1.2.3")
}
if v.PodReason() != "OutOfcpu" {
t.Fatalf("PodReason(): got %q want %q", v.PodReason(), "OutOfcpu")
}
if v.PodMessage() != "Pod was terminated due to cpu limit." {
t.Fatalf("PodMessage(): got %q want %q", v.PodMessage(), "Pod was terminated due to cpu limit.")
}
})
}
// TestPodViewBranchcov0719late_Metrics covers CPUPercent, MemoryPercent,
// DiskPercent, NetInRate and NetOutRate. The defensive nil-receiver arm
// returns 0; the nil-Metrics nested arm also routes through
// viewMetricPercent/viewMetricValue and returns 0.
func TestPodViewBranchcov0719late_Metrics(t *testing.T) {
now := time.Date(2026, 7, 19, 12, 0, 0, 0, time.UTC)
t.Run("NilReceiver", func(t *testing.T) {
var zero PodView
if zero.CPUPercent() != 0 {
t.Fatalf("nil CPUPercent(): got %v want 0", zero.CPUPercent())
}
if zero.MemoryPercent() != 0 {
t.Fatalf("nil MemoryPercent(): got %v want 0", zero.MemoryPercent())
}
if zero.DiskPercent() != 0 {
t.Fatalf("nil DiskPercent(): got %v want 0", zero.DiskPercent())
}
if zero.NetInRate() != 0 {
t.Fatalf("nil NetInRate(): got %v want 0", zero.NetInRate())
}
if zero.NetOutRate() != 0 {
t.Fatalf("nil NetOutRate(): got %v want 0", zero.NetOutRate())
}
})
t.Run("NilMetrics", func(t *testing.T) {
r := testResource(ResourceTypePod)
r.Metrics = nil
v := NewPodView(r)
if v.CPUPercent() != 0 || v.MemoryPercent() != 0 || v.DiskPercent() != 0 || v.NetInRate() != 0 || v.NetOutRate() != 0 {
t.Fatalf("metric accessors with nil Metrics: got cpu=%v mem=%v disk=%v netIn=%v netOut=%v, all want 0",
v.CPUPercent(), v.MemoryPercent(), v.DiskPercent(), v.NetInRate(), v.NetOutRate())
}
})
t.Run("NilNestedMetricValues", func(t *testing.T) {
// ResourceMetrics present but the individual MetricValue pointers nil.
r := testResource(ResourceTypePod)
r.Metrics = &ResourceMetrics{}
v := NewPodView(r)
if v.CPUPercent() != 0 || v.MemoryPercent() != 0 || v.DiskPercent() != 0 || v.NetInRate() != 0 || v.NetOutRate() != 0 {
t.Fatalf("metric accessors with nil nested MetricValue: got cpu=%v mem=%v disk=%v netIn=%v netOut=%v",
v.CPUPercent(), v.MemoryPercent(), v.DiskPercent(), v.NetInRate(), v.NetOutRate())
}
})
t.Run("Populated", func(t *testing.T) {
v := NewPodView(branchcov0719latePodResource(now))
if v.CPUPercent() != 42.5 {
t.Fatalf("CPUPercent(): got %v want 42.5", v.CPUPercent())
}
if v.MemoryPercent() != 55.0 {
t.Fatalf("MemoryPercent(): got %v want 55", v.MemoryPercent())
}
if v.DiskPercent() != 12.0 {
t.Fatalf("DiskPercent(): got %v want 12", v.DiskPercent())
}
if v.NetInRate() != 1024.5 {
t.Fatalf("NetInRate(): got %v want 1024.5", v.NetInRate())
}
if v.NetOutRate() != 2048.0 {
t.Fatalf("NetOutRate(): got %v want 2048", v.NetOutRate())
}
})
}
// TestPodViewBranchcov0719late_Tags covers Tags: nil-receiver, nil field, and
// populated arms, plus clone independence.
func TestPodViewBranchcov0719late_Tags(t *testing.T) {
now := time.Date(2026, 7, 19, 12, 0, 0, 0, time.UTC)
t.Run("NilReceiver", func(t *testing.T) {
var zero PodView
if got := zero.Tags(); got != nil {
t.Fatalf("nil Tags(): got %v want nil", got)
}
})
t.Run("NilField", func(t *testing.T) {
r := testResource(ResourceTypePod)
r.Tags = nil
v := NewPodView(r)
if got := v.Tags(); got != nil {
t.Fatalf("Tags() with nil Tags field: got %v want nil", got)
}
})
t.Run("Populated", func(t *testing.T) {
v := NewPodView(branchcov0719latePodResource(now))
assertStringSlice(t, v.Tags(), []string{"app:web", "tier:frontend"})
})
t.Run("CloneIsIndependent", func(t *testing.T) {
src := branchcov0719latePodResource(now)
v := NewPodView(src)
got := v.Tags()
got[0] = "mutated"
if src.Tags[0] != "app:web" {
t.Fatalf("Tags() did not return an independent copy; underlying slice mutated to %q", src.Tags[0])
}
})
}
// TestPodViewBranchcov0719late_LastSeen covers LastSeen nil-receiver and
// populated arms.
func TestPodViewBranchcov0719late_LastSeen(t *testing.T) {
now := time.Date(2026, 7, 19, 12, 0, 0, 0, time.UTC)
t.Run("NilReceiver", func(t *testing.T) {
var zero PodView
if !zero.LastSeen().IsZero() {
t.Fatalf("nil LastSeen(): got %v want zero time", zero.LastSeen())
}
})
t.Run("Populated", func(t *testing.T) {
v := NewPodView(branchcov0719latePodResource(now))
if !v.LastSeen().Equal(now) {
t.Fatalf("LastSeen(): got %v want %v", v.LastSeen(), now)
}
})
}
// TestPodViewBranchcov0719late_PodContainers covers PodContainers: nil
// receiver, nil Kubernetes facet, empty backing slice, populated, and clone
// independence.
func TestPodViewBranchcov0719late_PodContainers(t *testing.T) {
now := time.Date(2026, 7, 19, 12, 0, 0, 0, time.UTC)
t.Run("NilReceiver", func(t *testing.T) {
var zero PodView
if got := zero.PodContainers(); got != nil {
t.Fatalf("nil PodContainers(): got %v want nil", got)
}
})
t.Run("NilKubernetes", func(t *testing.T) {
r := testResource(ResourceTypePod)
r.Kubernetes = nil
v := NewPodView(r)
if got := v.PodContainers(); got != nil {
t.Fatalf("PodContainers() with nil Kubernetes: got %v want nil", got)
}
})
t.Run("EmptySliceReturnsNil", func(t *testing.T) {
// Backing slice is empty/nil — the len==0 guard must return nil.
r := testResource(ResourceTypePod)
r.Kubernetes = &K8sData{}
v := NewPodView(r)
if got := v.PodContainers(); got != nil {
t.Fatalf("PodContainers() with empty backing slice: got %v want nil", got)
}
})
t.Run("Populated", func(t *testing.T) {
v := NewPodView(branchcov0719latePodResource(now))
got := v.PodContainers()
if len(got) != 2 {
t.Fatalf("PodContainers(): got %d items want 2: %+v", len(got), got)
}
if got[0].Name != "app" || got[0].Image != "ghcr.io/example/checkout:v1.2.3" || got[0].Ready != true || got[0].RestartCount != 1 || got[0].State != "running" {
t.Fatalf("PodContainers()[0] mismatch: got %+v", got[0])
}
if got[1].Name != "sidecar" || got[1].Reason != "CrashLoopBackOff" || got[1].State != "waiting" || got[1].Message != "Back-off pulling image" {
t.Fatalf("PodContainers()[1] mismatch: got %+v", got[1])
}
})
t.Run("CloneIsIndependent", func(t *testing.T) {
src := branchcov0719latePodResource(now)
v := NewPodView(src)
got := v.PodContainers()
got[0].Name = "mutated"
got[1].RestartCount = 99
if src.Kubernetes.PodContainers[0].Name != "app" {
t.Fatalf("PodContainers() did not return an independent copy; element[0].Name mutated to %q", src.Kubernetes.PodContainers[0].Name)
}
if src.Kubernetes.PodContainers[1].RestartCount != 2 {
t.Fatalf("PodContainers() did not return an independent copy; element[1].RestartCount mutated to %d", src.Kubernetes.PodContainers[1].RestartCount)
}
})
}