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.
117 lines
3.4 KiB
117 lines
3.4 KiB
|
2 months ago
|
package logstorage
|
||
|
|
|
||
|
|
import (
|
||
|
|
"bytes"
|
||
|
|
"os"
|
||
|
|
"strings"
|
||
|
|
"testing"
|
||
|
|
"time"
|
||
|
|
)
|
||
|
|
|
||
|
|
func TestClearSystemPreservesOtherClassesAndReclaimsStoredData(t *testing.T) {
|
||
|
|
root := t.TempDir()
|
||
|
|
s := openTestStore(t, Options{Root: root})
|
||
|
|
now := time.Now()
|
||
|
|
for i := 0; i < 2; i++ {
|
||
|
|
if _, err := s.Append(ClassSystem, now, map[string]string{"message": strings.Repeat("old-system", 1000)}); err != nil {
|
||
|
|
t.Fatal(err)
|
||
|
|
}
|
||
|
|
}
|
||
|
|
for _, class := range []string{ClassAudit, ClassPort, ClassLink} {
|
||
|
|
if _, err := s.Append(class, now, map[string]string{"message": "keep"}); err != nil {
|
||
|
|
t.Fatal(err)
|
||
|
|
}
|
||
|
|
}
|
||
|
|
if err := s.ApplyRetention(Retention{365, 365, 365}); err != nil {
|
||
|
|
t.Fatal(err)
|
||
|
|
}
|
||
|
|
if _, err := s.Append(ClassSystem, now, map[string]string{"message": "active-system"}); err != nil {
|
||
|
|
t.Fatal(err)
|
||
|
|
}
|
||
|
|
before, err := s.Snapshot()
|
||
|
|
if err != nil {
|
||
|
|
t.Fatal(err)
|
||
|
|
}
|
||
|
|
if n, err := s.ClearSystem(); err != nil || n != 3 {
|
||
|
|
t.Fatalf("clear=%d,%v", n, err)
|
||
|
|
}
|
||
|
|
after, err := s.Snapshot()
|
||
|
|
if err != nil {
|
||
|
|
t.Fatal(err)
|
||
|
|
}
|
||
|
|
if after.UsageBytes["system"] >= before.UsageBytes["system"] {
|
||
|
|
t.Fatal("physical storage did not decrease")
|
||
|
|
}
|
||
|
|
paths, _ := s.closedSegmentsLocked(ClassSystem)
|
||
|
|
paths = append(paths, s.activePath(ClassSystem))
|
||
|
|
for _, path := range paths {
|
||
|
|
data, err := os.ReadFile(path)
|
||
|
|
if err != nil || bytes.Contains(data, []byte("system")) {
|
||
|
|
t.Fatalf("cleared bytes remain: %s,%v", path, err)
|
||
|
|
}
|
||
|
|
}
|
||
|
|
s = openTestStore(t, Options{Root: root})
|
||
|
|
for _, class := range []string{ClassAudit, ClassPort, ClassLink} {
|
||
|
|
rows, err := s.Read(class)
|
||
|
|
if err != nil || len(rows) != 1 {
|
||
|
|
t.Fatalf("%s changed: %s,%v", class, rows, err)
|
||
|
|
}
|
||
|
|
}
|
||
|
|
page, err := s.Page(ClassSystem, 0, 500)
|
||
|
|
if err != nil || len(page) != 0 {
|
||
|
|
t.Fatalf("deleted data returned: %v,%v", page, err)
|
||
|
|
}
|
||
|
|
event, err := s.Append(ClassSystem, now, map[string]string{"message": "new"})
|
||
|
|
if err != nil || event.Sequence != 4 {
|
||
|
|
t.Fatalf("sequence=%v,%v", event, err)
|
||
|
|
}
|
||
|
|
var output bytes.Buffer
|
||
|
|
if err := s.Export(ClassSystem, &output); err != nil || strings.Contains(output.String(), "old-system") {
|
||
|
|
t.Fatal("export resurrected data", err)
|
||
|
|
}
|
||
|
|
if n, err := s.ClearSystem(); err != nil || n != 1 {
|
||
|
|
t.Fatalf("second clear=%d,%v", n, err)
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
func TestClearSystemRecoversCheckpointBeforeCompaction(t *testing.T) {
|
||
|
|
root := t.TempDir()
|
||
|
|
s := openTestStore(t, Options{Root: root})
|
||
|
|
if _, err := s.Append(ClassSystem, time.Now(), map[string]string{"message": "old"}); err != nil {
|
||
|
|
t.Fatal(err)
|
||
|
|
}
|
||
|
|
original, err := os.ReadFile(s.activePath(ClassSystem))
|
||
|
|
if err != nil {
|
||
|
|
t.Fatal(err)
|
||
|
|
}
|
||
|
|
if _, err := s.ClearSystem(); err != nil {
|
||
|
|
t.Fatal(err)
|
||
|
|
}
|
||
|
|
if err := os.WriteFile(s.activePath(ClassSystem), original, 0o600); err != nil {
|
||
|
|
t.Fatal(err)
|
||
|
|
}
|
||
|
|
s = openTestStore(t, Options{Root: root})
|
||
|
|
rows, err := s.Read(ClassSystem)
|
||
|
|
if err != nil || len(rows) != 0 {
|
||
|
|
t.Fatal("crash resurrected records", err)
|
||
|
|
}
|
||
|
|
next, err := s.Append(ClassSystem, time.Now(), map[string]string{"message": "new"})
|
||
|
|
if err != nil || next.Sequence != 2 {
|
||
|
|
t.Fatal("sequence reused", err)
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
func TestSystemClearFailsClosedOnInvalidCheckpoint(t *testing.T) {
|
||
|
|
root := t.TempDir()
|
||
|
|
s := openTestStore(t, Options{Root: root})
|
||
|
|
if err := os.Mkdir(s.systemClearPath(), 0o700); err != nil {
|
||
|
|
t.Fatal(err)
|
||
|
|
}
|
||
|
|
if _, err := s.ClearSystem(); err == nil {
|
||
|
|
t.Fatal("unwritable checkpoint accepted")
|
||
|
|
}
|
||
|
|
if _, err := Open(Options{Root: root}); err == nil {
|
||
|
|
t.Fatal("invalid checkpoint accepted on restart")
|
||
|
|
}
|
||
|
|
}
|