package worker import ( "bytes" "fmt" "os" "reflect" "slices" "testing" "gordenko.dev/dima/qb" "gordenko.dev/dima/qb/enc" "gordenko.dev/dima/qb/storage" ) func TestWriteReadSnapshot(t *testing.T) { 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, }, }, }, } 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, }, } fileName := "test.snapshot" err := writeSnapshot(fileName, in) if err != nil { t.Fatalf("writeSnapshot: %s", err) } out, err := ReadSnapshot(fileName) if err != nil { t.Fatal(err) } 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) } } os.Remove(fileName) } 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) } 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()) } return nil }