func TestFileStore_SeekToAsc_Duplicate(t *testing.T) { fs := tsm1.NewFileStore("") // Setup 3 files data := []keyValues{ keyValues{"cpu", []tsm1.Value{tsm1.NewValue(0, 1.0)}}, keyValues{"cpu", []tsm1.Value{tsm1.NewValue(0, 2.0)}}, keyValues{"cpu", []tsm1.Value{tsm1.NewValue(2, 3.0)}}, keyValues{"cpu", []tsm1.Value{tsm1.NewValue(2, 4.0)}}, } files, err := newFiles(data...) if err != nil { t.Fatalf("unexpected error creating files: %v", err) } fs.Add(files...) buf := make([]tsm1.FloatValue, 1000) c := fs.KeyCursor("cpu", 0, true) // Search for an entry that exists in the second file values, err := c.ReadFloatBlock(tsm1.NewTimeDecoder(), &tsm1.FloatDecoder{}, &buf) if err != nil { t.Fatalf("unexpected error reading values: %v", err) } exp := []tsm1.Value{ data[1].values[0], data[3].values[0], } if got, exp := len(values), len(exp); got != exp { t.Fatalf("value length mismatch: got %v, exp %v", got, exp) } for i, v := range exp { if got, exp := values[i].Value(), v.Value(); got != exp { t.Fatalf("read value mismatch(%d): got %v, exp %v", i, got, exp) } } // Check that calling Next will dedupe points c.Next() values, err = c.ReadFloatBlock(tsm1.NewTimeDecoder(), &tsm1.FloatDecoder{}, &buf) if err != nil { t.Fatalf("unexpected error reading values: %v", err) } exp = nil if got, exp := len(values), len(exp); got != exp { t.Fatalf("value length mismatch: got %v, exp %v", got, exp) } }
func TestFileStore_SeekToDesc_End(t *testing.T) { fs := tsm1.NewFileStore("") // Setup 3 files data := []keyValues{ keyValues{"cpu", []tsm1.Value{tsm1.NewValue(0, 1.0)}}, keyValues{"cpu", []tsm1.Value{tsm1.NewValue(1, 2.0)}}, keyValues{"cpu", []tsm1.Value{tsm1.NewValue(2, 3.0)}}, } files, err := newFiles(data...) if err != nil { t.Fatalf("unexpected error creating files: %v", err) } fs.Add(files...) buf := make([]tsm1.FloatValue, 1000) c := fs.KeyCursor("cpu", 2, false) values, err := c.ReadFloatBlock(tsm1.NewTimeDecoder(), &tsm1.FloatDecoder{}, &buf) if err != nil { t.Fatalf("unexpected error reading values: %v", err) } exp := data[2] if got, exp := len(values), len(exp.values); got != exp { t.Fatalf("value length mismatch: got %v, exp %v", got, exp) } for i, v := range exp.values { if got, exp := values[i].Value(), v.Value(); got != exp { t.Fatalf("read value mismatch(%d): got %v, exp %d", i, got, exp) } } }
func TestFileStore_SeekToDesc_AfterEnd_OverlapString(t *testing.T) { fs := tsm1.NewFileStore("") // Setup 3 files data := []keyValues{ keyValues{"cpu", []tsm1.Value{tsm1.NewValue(8, "eight"), tsm1.NewValue(9, "nine")}}, keyValues{"cpu", []tsm1.Value{tsm1.NewValue(2, "two")}}, keyValues{"cpu", []tsm1.Value{tsm1.NewValue(3, "three")}}, keyValues{"cpu", []tsm1.Value{tsm1.NewValue(3, "four"), tsm1.NewValue(7, "seven")}}, } files, err := newFiles(data...) if err != nil { t.Fatalf("unexpected error creating files: %v", err) } fs.Add(files...) buf := make([]tsm1.StringValue, 1000) c := fs.KeyCursor("cpu", 8, false) values, err := c.ReadStringBlock(tsm1.NewTimeDecoder(), &tsm1.StringDecoder{}, &buf) if err != nil { t.Fatalf("unexpected error reading values: %v", err) } exp := []tsm1.Value{ data[1].values[0], data[3].values[0], data[3].values[1], data[0].values[0], data[0].values[1], } if got, exp := len(values), len(exp); got != exp { t.Fatalf("value length mismatch: got %v, exp %v", got, exp) } for i, v := range exp { if got, exp := values[i].Value(), v.Value(); got != exp { t.Fatalf("read value mismatch(%d): got %v, exp %v", i, got, exp) } } }
func TestFileStore_SeekToDesc_AfterEnd_OverlapInteger(t *testing.T) { fs := tsm1.NewFileStore("") // Setup 3 files data := []keyValues{ keyValues{"cpu", []tsm1.Value{tsm1.NewValue(8, int64(0)), tsm1.NewValue(9, int64(1))}}, keyValues{"cpu", []tsm1.Value{tsm1.NewValue(2, int64(2))}}, keyValues{"cpu", []tsm1.Value{tsm1.NewValue(3, int64(3))}}, keyValues{"cpu", []tsm1.Value{tsm1.NewValue(3, int64(4)), tsm1.NewValue(7, int64(7))}}, } files, err := newFiles(data...) if err != nil { t.Fatalf("unexpected error creating files: %v", err) } fs.Add(files...) buf := make([]tsm1.IntegerValue, 1000) c := fs.KeyCursor("cpu", 8, false) values, err := c.ReadIntegerBlock(tsm1.NewTimeDecoder(), &tsm1.IntegerDecoder{}, &buf) if err != nil { t.Fatalf("unexpected error reading values: %v", err) } exp := []tsm1.Value{ data[1].values[0], data[3].values[0], data[3].values[1], data[0].values[0], data[0].values[1], } if got, exp := len(values), len(exp); got != exp { t.Fatalf("value length mismatch: got %v, exp %v", got, exp) } for i, v := range exp { if got, exp := values[i].Value(), v.Value(); got != exp { t.Fatalf("read value mismatch(%d): got %v, exp %v", i, got, exp) } } }
// Tests that seeking and reading all blocks that contain overlapping points does // not skip any blocks. func TestFileStore_SeekToAsc_BeforeStart_OverlapString(t *testing.T) { fs := tsm1.NewFileStore("") // Setup 3 files data := []keyValues{ keyValues{"cpu", []tsm1.Value{tsm1.NewValue(0, "zero"), tsm1.NewValue(1, "one")}}, keyValues{"cpu", []tsm1.Value{tsm1.NewValue(2, "two")}}, keyValues{"cpu", []tsm1.Value{tsm1.NewValue(3, "three")}}, keyValues{"cpu", []tsm1.Value{tsm1.NewValue(0, "four"), tsm1.NewValue(7, "seven")}}, } files, err := newFiles(data...) if err != nil { t.Fatalf("unexpected error creating files: %v", err) } fs.Add(files...) // Search for an entry that exists in the second file buf := make([]tsm1.StringValue, 1000) c := fs.KeyCursor("cpu", 0, true) values, err := c.ReadStringBlock(tsm1.NewTimeDecoder(), &tsm1.StringDecoder{}, &buf) if err != nil { t.Fatalf("unexpected error reading values: %v", err) } exp := []tsm1.Value{ data[3].values[0], data[0].values[1], data[1].values[0], data[2].values[0], data[3].values[1], } if got, exp := len(values), len(exp); got != exp { t.Fatalf("value length mismatch: got %v, exp %v", got, exp) } for i, v := range exp { if got, exp := values[i].Value(), v.Value(); got != exp { t.Fatalf("read value mismatch(%d): got %v, exp %v", i, got, exp) } } }
func BenchmarkDecodeBlock_String_TypeSpecific(b *testing.B) { valueCount := 1000 times := getTimes(valueCount, 60, time.Second) values := make([]tsm1.Value, len(times)) for i, t := range times { values[i] = tsm1.NewValue(t, fmt.Sprintf("value %d", i)) } bytes, err := tsm1.Values(values).Encode(nil) if err != nil { b.Fatalf("unexpected error: %v", err) } decodedValues := make([]tsm1.StringValue, len(values)) b.ResetTimer() for i := 0; i < b.N; i++ { _, err = tsm1.DecodeStringBlock(bytes, tsm1.NewTimeDecoder(), &tsm1.StringDecoder{}, &decodedValues) if err != nil { b.Fatalf("unexpected error decoding block: %v", err) } } }