84 lines
2.6 KiB
Go
84 lines
2.6 KiB
Go
package deployment
|
|
|
|
import (
|
|
"context"
|
|
"encoding/json"
|
|
"errors"
|
|
"fmt"
|
|
"reflect"
|
|
"strings"
|
|
"testing"
|
|
)
|
|
|
|
func TestRecoveryListPaginationAndRedaction(t *testing.T) {
|
|
journal := &memoryTransactionJournal{}
|
|
for i := 12; i > 0; i-- {
|
|
journal.pending = append(journal.pending, TransactionRecord{
|
|
ID: fmt.Sprintf("tx-%02d", i), ServerID: "server-1", Phase: TransactionPhaseInstalled,
|
|
Status: TransactionStatusRecoveryRequired, Message: "secret-message", ServerName: "secret-name",
|
|
Paths: []string{"secret-path"}, Evidence: &RecoveryEvidence{},
|
|
})
|
|
}
|
|
factory := &inspectionFactory{}
|
|
service := NewServiceWithJournal(factory, journal)
|
|
cursor := ""
|
|
var ids []string
|
|
for _, size := range []int{5, 5, 2} {
|
|
page, err := service.ListPendingRecoveries(t.Context(), cursor)
|
|
if err != nil || len(page.Items) != size {
|
|
t.Fatalf("page: %+v, %v", page, err)
|
|
}
|
|
data, _ := json.Marshal(page)
|
|
if strings.Contains(string(data), "secret-") || len(data) > 16<<10 {
|
|
t.Fatal("summary leaked data or exceeded frame")
|
|
}
|
|
for _, item := range page.Items {
|
|
ids = append(ids, item.ID)
|
|
if !item.HistoricalEvidence {
|
|
t.Fatal("evidence presence lost")
|
|
}
|
|
}
|
|
cursor = page.NextCursor
|
|
}
|
|
if cursor != "" || len(ids) != 12 || ids[0] != "tx-01" || ids[11] != "tx-12" ||
|
|
factory.calls != 0 || len(journal.updated) != 0 || len(journal.finished) != 0 {
|
|
t.Fatalf("list mutated state, connected, or lost ordering: %v", ids)
|
|
}
|
|
}
|
|
|
|
func TestRecoveryListRejectsInvalidRecords(t *testing.T) {
|
|
for _, scenario := range []string{"duplicate", "id", "server", "phase", "status", "cursor", "cancelled"} {
|
|
t.Run(scenario, func(t *testing.T) {
|
|
record := TransactionRecord{ID: "tx-1", ServerID: "server-1", Phase: TransactionPhaseInstalled, Status: TransactionStatusPending}
|
|
journal := &memoryTransactionJournal{}
|
|
ctx, cancel := context.WithCancel(t.Context())
|
|
defer cancel()
|
|
cursor := ""
|
|
switch scenario {
|
|
case "duplicate":
|
|
journal.pending = append(journal.pending, record)
|
|
case "id":
|
|
record.ID = "../bad"
|
|
case "server":
|
|
record.ServerID = strings.Repeat("x", 161)
|
|
case "phase":
|
|
record.Phase = "\x1b[2J"
|
|
case "status":
|
|
record.Status = TransactionStatusCommitted
|
|
case "cursor":
|
|
cursor = "../bad"
|
|
case "cancelled":
|
|
cancel()
|
|
}
|
|
journal.pending = append(journal.pending, record)
|
|
page, err := NewServiceWithJournal(nil, journal).ListPendingRecoveries(ctx, cursor)
|
|
if err == nil || !reflect.DeepEqual(page, PendingRecoveryPage{}) {
|
|
t.Fatal("invalid list returned data")
|
|
}
|
|
if scenario == "cancelled" && !errors.Is(err, context.Canceled) {
|
|
t.Fatal(err)
|
|
}
|
|
})
|
|
}
|
|
}
|