Files
qb/worker/snapshot_test.go

156 lines
4.1 KiB
Go
Raw Normal View History

2026-06-14 07:57:01 +03:00
package worker
import (
2026-06-14 23:12:03 +03:00
"bytes"
2026-06-14 07:57:01 +03:00
"fmt"
2026-06-14 23:12:03 +03:00
"os"
"reflect"
2026-06-14 07:57:01 +03:00
"slices"
"testing"
"gordenko.dev/dima/qb"
2026-06-14 23:12:03 +03:00
"gordenko.dev/dima/qb/enc"
2026-06-14 07:57:01 +03:00
"gordenko.dev/dima/qb/storage"
)
func TestWriteReadSnapshot(t *testing.T) {
2026-06-14 23:12:03 +03:00
storage.DataPageSize = 32
storage.DataPagePayloadSize = 20
storage.IndexPageSize = 16
buf := []byte{
// values
0x8f, // base value
0x80, // delta 0
0x01, // run (len = 3)
0x81, // delta 1
0x81, // literal (len = 2)
// empty space
0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00,
// timestamps
0x80, // h-byte (literal, len=1)
0x94, // delta 20
0x01, // h-byte (run, len=3)
0xbc, // delta 60
0x28, 0x80, 0x24, 0x6a, // since
// footer
0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00,
}
databuf := buf[:storage.DataPagePayloadSize]
timestampsSize := 8
valuesSize := 5
metrics := map[uint32]*Metric{
1: {
metricType: qb.Cumulative,
fracDigits: 3,
lastPageNo: 1000,
buffer: buf,
timestamps: enc.NewTimeDeltaCompressor(databuf, timestampsSize),
values: enc.NewValueDeltaCompressor(qb.Cumulative, 3, databuf, valuesSize),
indexLevelTails: []storage.IndexLevelTail{
{
Buffer: []byte{
0x01, 0x01, 0x01, 0x01,
0x02, 0x02, 0x02, 0x02,
0x00,
// footer
0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00,
},
RecordsCount: 1,
},
},
},
2026-06-14 07:57:01 +03:00
}
in := WriteSnapshotIn{
SnapshotNumber: 1,
WriteBufferSize: 8 * 1024 * 1024,
Metrics: metrics,
FrozenIndexPagesCount: 7,
IndexPageNumbers: []uint32{
1, 2, 3, 4, 5,
},
FrozenDataPagesCount: 8,
DataPageNumbers: []uint32{
6, 7, 8,
},
}
2026-06-14 23:12:03 +03:00
fileName := "test.snapshot"
err := writeSnapshot(fileName, in)
2026-06-14 07:57:01 +03:00
if err != nil {
t.Fatalf("writeSnapshot: %s", err)
}
2026-06-14 23:12:03 +03:00
out, err := ReadSnapshot(fileName)
2026-06-14 07:57:01 +03:00
if err != nil {
2026-06-14 23:12:03 +03:00
t.Fatal(err)
2026-06-14 07:57:01 +03:00
}
if out.FrozenIndexPagesCount != in.FrozenIndexPagesCount {
t.Fatalf("FrozenIndexPagesCount: got %d are not equal expected %d",
out.FrozenIndexPagesCount, in.FrozenIndexPagesCount)
}
if out.FrozenDataPagesCount != in.FrozenDataPagesCount {
t.Fatalf("FrozenDataPagesCount: got %d are not equal expected %d",
out.FrozenDataPagesCount, in.FrozenDataPagesCount)
}
if !slices.Equal(out.IndexPageNumbers, in.IndexPageNumbers) {
t.Fatalf("IndexPageNumbers: got %v are not equal expected %v",
out.IndexPageNumbers, in.IndexPageNumbers)
}
if !slices.Equal(out.DataPageNumbers, in.DataPageNumbers) {
t.Fatalf("DataPageNumbers: got %v are not equal expected %v",
out.DataPageNumbers, in.DataPageNumbers)
}
for metricID, replay := range out.Metrics {
origin, ok := metrics[metricID]
if !ok {
t.Fatalf("decoded metricID %d not found in metrics", metricID)
}
err = cmpMetric(replay, origin)
if err != nil {
t.Fatalf("metric %d: %s", metricID, err)
}
}
2026-06-14 23:12:03 +03:00
os.Remove(fileName)
2026-06-14 07:57:01 +03:00
}
func cmpMetric(replay *storage.ReplayMetric, origin *Metric) error {
if replay.MetricType != origin.metricType {
return fmt.Errorf("metricType: got %d are not equal expected %d",
replay.MetricType, origin.metricType)
}
if replay.FracDigits != origin.fracDigits {
return fmt.Errorf("fracDigits: got %d are not equal expected %d",
replay.FracDigits, origin.fracDigits)
}
if replay.LastPageNo != origin.lastPageNo {
return fmt.Errorf("lastPageNo: got %d are not equal expected %d",
replay.LastPageNo, origin.lastPageNo)
}
2026-06-14 23:12:03 +03:00
if !reflect.DeepEqual(replay.IndexLevelTails, origin.indexLevelTails) {
return fmt.Errorf("indexLevelTails: got %#v are not equal expected %#v",
replay.IndexLevelTails, origin.indexLevelTails)
}
if !bytes.Equal(replay.Buf, origin.buffer) {
return fmt.Errorf("buffer: got % x are not equal expected % x",
replay.Buf, origin.buffer)
}
if replay.TimestampsSize != origin.timestamps.Size() {
return fmt.Errorf("timestampsSize: got %d are not equal expected %d",
replay.TimestampsSize, origin.timestamps.Size())
}
if replay.ValuesSize != origin.values.Size() {
return fmt.Errorf("valuesSize: got %d are not equal expected %d",
replay.ValuesSize, origin.values.Size())
}
2026-06-14 07:57:01 +03:00
return nil
}