Files
story/internal/saas/ops_firmware_service_integration_test.go
T
Codex Local 0c2151ace9
ci / verify (push) Canceled after 0s
chore: checkpoint 第一版
2026-09-06 17:04:11 +08:00

120 lines
5.6 KiB
Go

package saas
import (
"context"
"crypto/ed25519"
"crypto/rand"
"crypto/sha256"
"encoding/base64"
"encoding/hex"
"errors"
"os"
"testing"
"time"
"data-terminal-cloud/internal/audit"
"data-terminal-cloud/internal/identity"
"github.com/google/uuid"
"github.com/jackc/pgx/v5/pgxpool"
)
func TestOpsFirmwareReleaseLifecycle(t *testing.T) {
databaseURL := os.Getenv("TEST_DATABASE_URL")
if databaseURL == "" {
t.Skip("TEST_DATABASE_URL is not set")
}
ctx := context.Background()
pool, err := pgxpool.New(ctx, databaseURL)
if err != nil {
t.Fatal(err)
}
defer pool.Close()
store := &firmwareIntegrationStore{}
service := NewService(pool, audit.NewRepository(), nil, nil)
service.ConfigureFirmwareStore(store, 4*time.Minute)
var operator identity.Principal
if err := pool.QueryRow(ctx, `SELECT oidc_issuer,oidc_subject FROM user_account WHERE public_id='10000000-0000-0000-0000-000000000114'::uuid AND status='active' AND account_kind='operator'`).Scan(&operator.Issuer, &operator.Subject); err != nil {
t.Fatal(err)
}
const tenantID = "10000000-0000-0000-0000-000000000010"
keyID := "ops-firmware-" + uuid.NewString()
version := "ops-" + uuid.NewString()
var releaseID, rolloutID string
defer func() {
_, _ = pool.Exec(ctx, `DELETE FROM audit_event WHERE request_id LIKE 'ops-firmware-integration-%'`)
if rolloutID != "" {
_, _ = pool.Exec(ctx, `DELETE FROM firmware_rollout WHERE public_id=$1::uuid`, rolloutID)
}
if releaseID != "" {
_, _ = pool.Exec(ctx, `DELETE FROM device_command WHERE payload->>'release_id'=$1`, releaseID)
}
if releaseID != "" {
_, _ = pool.Exec(ctx, `DELETE FROM firmware_release WHERE public_id=$1::uuid`, releaseID)
}
_, _ = pool.Exec(ctx, `DELETE FROM firmware_signing_key WHERE key_id=$1`, keyID)
}()
publicKey, privateKey, err := ed25519.GenerateKey(rand.Reader)
if err != nil {
t.Fatal(err)
}
if err := service.RegisterOpsFirmwareSigningKey(ctx, operator, tenantID, "ops-firmware-integration-key", keyID, base64.StdEncoding.EncodeToString(publicKey)); err != nil {
t.Fatal(err)
}
firmware := []byte("synthetic operations firmware")
digestBytes := sha256.Sum256(firmware)
digest := hex.EncodeToString(digestBytes[:])
model, hardware := "simulated-terminal", "sim-rev-a"
signature := base64.StdEncoding.EncodeToString(ed25519.Sign(privateKey, []byte(firmwareManifest(model, hardware, version, digest, int64(len(firmware))))))
prepared, err := service.PrepareOpsFirmwareRelease(ctx, operator, tenantID, "ops-firmware-integration-prepare", PrepareFirmwareInput{
Model: model, HardwareRevision: hardware, Version: version, ExpectedSize: int64(len(firmware)), ExpectedDigest: digest,
Signature: signature, SigningKeyID: keyID, ReleaseChannel: "BETA", Mandatory: true, ReleaseNotes: "维护端集成测试",
})
if err != nil || prepared.Status != "UPLOADING" || prepared.HouseholdID != "" || prepared.CreatedSource != "OPS" || prepared.ReleaseChannel != "BETA" || !prepared.Mandatory || prepared.UploadURL == "" {
t.Fatalf("prepared=%+v err=%v", prepared, err)
}
releaseID = prepared.ID
ready, err := service.FinalizeOpsFirmwareRelease(ctx, operator, tenantID, releaseID, "ops-firmware-integration-finalize")
if err != nil || ready.Status != "READY" || ready.VerifiedAt == nil || ready.PublishedAt == nil || store.verifiedDigest != digest {
t.Fatalf("ready=%+v store=%+v err=%v", ready, store, err)
}
items, err := service.ListOpsFirmwareReleases(ctx, operator, tenantID, model, "READY")
if err != nil || len(items) != 1 || items[0].ID != releaseID {
t.Fatalf("items=%+v err=%v", items, err)
}
download, err := service.OpsFirmwareDownload(ctx, operator, tenantID, releaseID, "ops-firmware-integration-download")
if err != nil || download.ReleaseID != releaseID || download.SHA256 != digest || download.DownloadURL == "" {
t.Fatalf("download=%+v err=%v", download, err)
}
rollout, err := service.StartOpsFirmwareRollout(ctx, operator, tenantID, releaseID, "ops-firmware-integration-rollout", "维护端OTA", 100, []string{"10000000-0000-0000-0000-000000000511"})
if err != nil || rollout.Targeted != 1 || rollout.HouseholdID != "" || rollout.Status != "RUNNING" {
t.Fatalf("rollout=%+v err=%v", rollout, err)
}
rolloutID = rollout.ID
detail, err := service.GetOpsFirmwareRollout(ctx, operator, tenantID, rolloutID)
if err != nil || len(detail.Assignments) != 1 || detail.Assignments[0].Status != "ASSIGNED" {
t.Fatalf("rollout detail=%+v err=%v", detail, err)
}
pausedRollout, err := service.PauseOpsFirmwareRollout(ctx, operator, tenantID, rolloutID, "ops-firmware-integration-rollout-pause")
if err != nil || pausedRollout.Status != "PAUSED" {
t.Fatalf("paused rollout=%+v err=%v", pausedRollout, err)
}
paused, err := service.PauseOpsFirmwareRelease(ctx, operator, tenantID, releaseID, "ops-firmware-integration-pause")
if err != nil || paused.Status != "PAUSED" {
t.Fatalf("paused=%+v err=%v", paused, err)
}
resumed, err := service.ResumeOpsFirmwareRelease(ctx, operator, tenantID, releaseID, "ops-firmware-integration-resume")
if err != nil || resumed.Status != "READY" {
t.Fatalf("resumed=%+v err=%v", resumed, err)
}
retired, err := service.RetireOpsFirmwareRelease(ctx, operator, tenantID, releaseID, "ops-firmware-integration-retire")
if err != nil || retired.Status != "RETIRED" || len(store.removed) != 0 {
t.Fatalf("retired=%+v removed=%v err=%v", retired, store.removed, err)
}
customer := identity.Principal{Issuer: testIssuer, Subject: testOwnerSubject}
if _, err := service.ListOpsFirmwareReleases(ctx, customer, tenantID, "", ""); !errors.Is(err, ErrAccessDenied) {
t.Fatalf("customer ops access error=%v", err)
}
}