package db import ( "testing" ) func TestDecodeTagsEdgeCases(t *testing.T) { tests := []struct { name string raw string want int }{ {"empty", "", 0}, {"brackets", "[]", 0}, {"whitespace", " [] ", 0}, {"valid", `["a","b"]`, 2}, {"invalid json", "{not-json", 0}, } for _, tc := range tests { t.Run(tc.name, func(t *testing.T) { got := decodeTags(tc.raw) if len(got) != tc.want { t.Fatalf("decodeTags(%q) len=%d want %d (%v)", tc.raw, len(got), tc.want, got) } }) } } func TestEncodeTagsEmpty(t *testing.T) { if got := encodeTags(nil); got != "[]" { t.Fatalf("encodeTags(nil) = %q want []", got) } if got := encodeTags([]string{}); got != "[]" { t.Fatalf("encodeTags(empty) = %q want []", got) } } func TestGetAgentInvalidTagsInDB(t *testing.T) { d := openTestDB(t) seedAgent(t, d, "bad-tags") if _, err := d.Exec(`UPDATE agents SET tags = ? WHERE id = ?`, "{invalid", "bad-tags"); err != nil { t.Fatal(err) } got, err := d.GetAgent("bad-tags") if err != nil { t.Fatal(err) } if len(got.Tags) != 0 { t.Fatalf("invalid tags should decode to empty slice, got %v", got.Tags) } } func TestUpdateAgentMetaClearsTags(t *testing.T) { d := openTestDB(t) seedAgent(t, d, "meta-clear") if err := d.UpdateAgentMeta("meta-clear", "note", []string{"x"}); err != nil { t.Fatal(err) } if err := d.UpdateAgentMeta("meta-clear", "", nil); err != nil { t.Fatal(err) } got, err := d.GetAgent("meta-clear") if err != nil { t.Fatal(err) } if got.Notes != "" { t.Fatalf("notes not cleared: %q", got.Notes) } if len(got.Tags) != 0 { t.Fatalf("tags not cleared: %v", got.Tags) } } func TestUpdateAgentGPUStatsRoundTrip(t *testing.T) { d := openTestDB(t) seedAgent(t, d, "gpu-roundtrip") if err := d.UpdateAgentGPUStats("gpu-roundtrip", 12.5, "RTX 4090", true); err != nil { t.Fatal(err) } got, err := d.GetAgent("gpu-roundtrip") if err != nil { t.Fatal(err) } if got.GPUHashrate15m != 12.5 { t.Fatalf("gpu_hashrate_15m = %v want 12.5", got.GPUHashrate15m) } if got.GPUModel != "RTX 4090" { t.Fatalf("gpu_model = %q want RTX 4090", got.GPUModel) } if got.GPUMinerActive == nil || !*got.GPUMinerActive { t.Fatalf("gpu_miner_active = %v want true", got.GPUMinerActive) } list, err := d.ListAgents() if err != nil { t.Fatal(err) } if len(list) != 1 || list[0].GPUHashrate15m != 12.5 { t.Fatalf("ListAgents GPU: %+v", list) } }