feat: Tenable-style patch_status - pending_updates, last_patch, reboot_pending across full stack
This commit is contained in:
191
server/internal/db/builds_test.go
Normal file
191
server/internal/db/builds_test.go
Normal file
@@ -0,0 +1,191 @@
|
||||
package db
|
||||
|
||||
import (
|
||||
"database/sql"
|
||||
"errors"
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
"crypto-miner-server/internal/models"
|
||||
)
|
||||
|
||||
func insertBuild(t *testing.T, d *Database, b *models.BuildRecord) {
|
||||
t.Helper()
|
||||
if err := d.InsertBuild(b); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
}
|
||||
|
||||
func TestBuildCRUDAndList(t *testing.T) {
|
||||
d := openTestDB(t)
|
||||
|
||||
created := time.Now().UTC().Truncate(time.Second)
|
||||
build := &models.BuildRecord{
|
||||
ID: "build-001",
|
||||
WorkerName: "rig1",
|
||||
ServerURL: "http://localhost:8080",
|
||||
Wallet: "48xyz",
|
||||
Threads: 4,
|
||||
FileSize: 1024,
|
||||
BundleSize: 2048,
|
||||
FilePath: "/data/builds/build-001.zip",
|
||||
FileName: "agent.zip",
|
||||
DownloadURL: "/api/v1/builds/build-001/download",
|
||||
Platform: "windows",
|
||||
CreatedAt: created,
|
||||
PoolHost: "pool.example.com",
|
||||
PoolPort: 443,
|
||||
PoolTLS: true,
|
||||
PoolPass: "x",
|
||||
}
|
||||
insertBuild(t, d, build)
|
||||
|
||||
got, err := d.GetBuild("build-001")
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if got.WorkerName != "rig1" || got.Platform != "windows" || got.BundleSize != 2048 {
|
||||
t.Fatalf("build mismatch: %+v", got)
|
||||
}
|
||||
if got.Pinned {
|
||||
t.Fatal("new build should not be pinned")
|
||||
}
|
||||
|
||||
list, err := d.ListBuilds(10)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if len(list) != 1 || list[0].ID != "build-001" {
|
||||
t.Fatalf("list builds: %+v", list)
|
||||
}
|
||||
}
|
||||
|
||||
func TestGetBuildNotFound(t *testing.T) {
|
||||
d := openTestDB(t)
|
||||
_, err := d.GetBuild("missing")
|
||||
if !errors.Is(err, sql.ErrNoRows) {
|
||||
t.Fatalf("expected sql.ErrNoRows, got %v", err)
|
||||
}
|
||||
}
|
||||
|
||||
func TestSetPinnedBuild(t *testing.T) {
|
||||
d := openTestDB(t)
|
||||
now := time.Now()
|
||||
insertBuild(t, d, &models.BuildRecord{ID: "b1", WorkerName: "w", ServerURL: "u", Wallet: "w", CreatedAt: now})
|
||||
insertBuild(t, d, &models.BuildRecord{ID: "b2", WorkerName: "w", ServerURL: "u", Wallet: "w", CreatedAt: now.Add(time.Second)})
|
||||
|
||||
if err := d.SetPinnedBuild("b1"); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
b1, _ := d.GetBuild("b1")
|
||||
b2, _ := d.GetBuild("b2")
|
||||
if !b1.Pinned || b2.Pinned {
|
||||
t.Fatalf("pin state wrong: b1=%v b2=%v", b1.Pinned, b2.Pinned)
|
||||
}
|
||||
|
||||
if err := d.SetPinnedBuild(""); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
b1, _ = d.GetBuild("b1")
|
||||
if b1.Pinned {
|
||||
t.Fatal("empty id should unpin all builds")
|
||||
}
|
||||
}
|
||||
|
||||
func TestGetLatestBuildForPlatform(t *testing.T) {
|
||||
d := openTestDB(t)
|
||||
base := time.Now().UTC().Truncate(time.Second)
|
||||
|
||||
insertBuild(t, d, &models.BuildRecord{
|
||||
ID: "old-linux", WorkerName: "w", ServerURL: "u", Wallet: "w",
|
||||
Platform: "linux", CreatedAt: base,
|
||||
})
|
||||
insertBuild(t, d, &models.BuildRecord{
|
||||
ID: "new-linux", WorkerName: "w", ServerURL: "u", Wallet: "w",
|
||||
Platform: "linux", CreatedAt: base.Add(time.Minute),
|
||||
})
|
||||
insertBuild(t, d, &models.BuildRecord{
|
||||
ID: "new-windows", WorkerName: "w", ServerURL: "u", Wallet: "w",
|
||||
Platform: "windows", CreatedAt: base.Add(2 * time.Minute),
|
||||
})
|
||||
|
||||
latestLinux, err := d.GetLatestBuildForPlatform("linux")
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if latestLinux.ID != "new-linux" {
|
||||
t.Fatalf("latest linux: got %q", latestLinux.ID)
|
||||
}
|
||||
|
||||
if err := d.SetPinnedBuild("old-linux"); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
pinnedLinux, err := d.GetLatestBuildForPlatform("linux")
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if pinnedLinux.ID != "old-linux" {
|
||||
t.Fatalf("pinned linux: got %q", pinnedLinux.ID)
|
||||
}
|
||||
|
||||
anyLatest, err := d.GetLatestBuildForPlatform("any")
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if anyLatest.ID != "old-linux" {
|
||||
t.Fatalf("any with pinned: got %q want old-linux", anyLatest.ID)
|
||||
}
|
||||
|
||||
if err := d.SetPinnedBuild(""); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
emptyPlatform, err := d.GetLatestBuildForPlatform("")
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if emptyPlatform.ID != "new-windows" {
|
||||
t.Fatalf("empty platform latest: got %q", emptyPlatform.ID)
|
||||
}
|
||||
}
|
||||
|
||||
func TestGetLatestBuildForPlatformEmpty(t *testing.T) {
|
||||
d := openTestDB(t)
|
||||
_, err := d.GetLatestBuildForPlatform("linux")
|
||||
if !errors.Is(err, sql.ErrNoRows) {
|
||||
t.Fatalf("expected sql.ErrNoRows on empty db, got %v", err)
|
||||
}
|
||||
}
|
||||
|
||||
func TestListBuildsOlderThanAndDeleteBuild(t *testing.T) {
|
||||
d := openTestDB(t)
|
||||
cutoff := time.Now().UTC().Truncate(time.Second)
|
||||
oldTime := cutoff.Add(-time.Hour)
|
||||
newTime := cutoff.Add(time.Hour)
|
||||
|
||||
insertBuild(t, d, &models.BuildRecord{
|
||||
ID: "old-build", WorkerName: "w", ServerURL: "u", Wallet: "w", CreatedAt: oldTime,
|
||||
})
|
||||
insertBuild(t, d, &models.BuildRecord{
|
||||
ID: "new-build", WorkerName: "w", ServerURL: "u", Wallet: "w", CreatedAt: newTime,
|
||||
})
|
||||
|
||||
older, err := d.ListBuildsOlderThan(cutoff)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if len(older) != 1 || older[0].ID != "old-build" {
|
||||
t.Fatalf("ListBuildsOlderThan: %+v", older)
|
||||
}
|
||||
|
||||
if err := d.DeleteBuild("old-build"); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
_, err = d.GetBuild("old-build")
|
||||
if !errors.Is(err, sql.ErrNoRows) {
|
||||
t.Fatalf("expected deleted build missing, got %v", err)
|
||||
}
|
||||
|
||||
if err := d.DeleteBuild("never-existed"); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user