You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

109 lines
3.6 KiB

package logservice
import (
"errors"
"net"
"os"
"path/filepath"
"testing"
"time"
"tera-clone/services/tera-api/internal/logstorage"
)
func TestClientServerRoundTripAndRetention(t *testing.T) {
root := t.TempDir()
now := time.Date(2026, 7, 29, 0, 0, 0, 0, time.UTC)
store, err := logstorage.Open(logstorage.Options{
Root: root, SegmentBytes: 1 << 20, Clock: func() time.Time { return now },
FreeBytes: func(string) (int64, error) { return 1 << 40, nil },
})
if err != nil {
t.Fatal(err)
}
socketPath := filepath.Join(t.TempDir(), "log.sock")
listener, err := net.Listen("unix", socketPath)
if err != nil {
if errors.Is(err, os.ErrPermission) {
t.Skipf("Unix sockets unavailable: %v", err)
}
t.Fatal(err)
}
defer listener.Close()
done := make(chan error, 1)
go func() { done <- (Server{Store: store}).Serve(listener) }()
defer func() {
_ = listener.Close()
<-done
}()
client := NewClient(socketPath)
for _, channel := range []string{"CH01", "CH02"} {
if err := client.Append(logstorage.ClassPort, now, map[string]string{"channel": channel}); err != nil {
t.Fatal(err)
}
}
if _, err := client.call(command{Action: "clear_port", Class: logstorage.ClassAudit, Channel: "CH01"}); err == nil {
t.Fatal("protected class deletion accepted")
}
if n, err := client.ClearPort("CH01"); err != nil || n != 1 {
t.Fatalf("clear socket = %d, %v", n, err)
}
if revision, err := client.PortClearRevision(); err != nil || revision != 1 {
t.Fatalf("clear revision = %d, %v", revision, err)
}
if rows, err := client.Read(logstorage.ClassPort); err != nil || len(rows) != 1 {
t.Fatalf("clear survivors = %d, %v", len(rows), err)
}
sequence, err := client.AppendSequence(logstorage.ClassSystem, now.Add(-48*time.Hour), map[string]string{"message": "expired"})
if err != nil {
t.Fatalf("Append: %v", err)
}
if sequence != 1 {
t.Fatalf("Append sequence = %d, want 1", sequence)
}
after, err := client.ReadAfter(logstorage.ClassSystem, sequence)
if err != nil || len(after) != 0 {
t.Fatalf("ReadAfter = %d, %v", len(after), err)
}
records, err := client.Read(logstorage.ClassSystem)
if err != nil || len(records) != 1 {
t.Fatalf("Read = %d, %v", len(records), err)
}
if err := client.ApplyRetention(logstorage.Retention{AuditDays: 365, SystemDays: 1, PortDays: 365}); err != nil {
t.Fatalf("ApplyRetention: %v", err)
}
records, err = client.Read(logstorage.ClassSystem)
if err != nil || len(records) != 0 {
t.Fatalf("Read after retention = %d, %v", len(records), err)
}
snapshot, err := client.Snapshot()
for _, class := range []string{logstorage.ClassAudit, logstorage.ClassPort, logstorage.ClassLink, ""} {
if _, err := client.call(command{Action: "clear_system", Class: class}); err == nil {
t.Fatalf("accepted protected class %s", class)
}
}
if err := client.Append(logstorage.ClassSystem, now, map[string]string{"message": "delete"}); err != nil {
t.Fatal(err)
}
if n, err := client.ClearSystem(); err != nil || n != 1 {
t.Fatalf("system clear=%d,%v", n, err)
}
if revision, err := client.SystemClearRevision(); err != nil || revision != 1 {
t.Fatalf("system revision=%d,%v", revision, err)
}
if rows, err := client.Read(logstorage.ClassPort); err != nil || len(rows) != 1 {
t.Fatal("port log affected", err)
}
if err != nil || snapshot.Root != root || snapshot.GlobalFreeFloor != 0 {
t.Fatalf("Snapshot = %+v, %v", snapshot, err)
}
}
func TestClientReportsUnavailableSocket(t *testing.T) {
client := NewClient(filepath.Join(t.TempDir(), "missing.sock"))
if _, err := client.Read(logstorage.ClassAudit); !errors.Is(err, ErrUnavailable) {
t.Fatalf("Read error = %v, want unavailable", err)
}
}