// // Tests that a multiple WAL segment can be read and iterated over func TestKeyIterator_WALSegment_Multiple(t *testing.T) { dir := MustTempDir() defer os.RemoveAll(dir) v1 := tsm1.NewValue(time.Unix(1, 0), int64(1)) points1 := map[string][]tsm1.Value{ "cpu,host=A#!~#value": []tsm1.Value{v1}, } entries := []tsm1.WALEntry{ &tsm1.WriteWALEntry{ Values: points1, }, } r1 := MustWALSegment(dir, entries) v2 := tsm1.NewValue(time.Unix(2, 0), int64(2)) points2 := map[string][]tsm1.Value{ "cpu,host=A#!~#value": []tsm1.Value{v2}, } entries = []tsm1.WALEntry{ &tsm1.WriteWALEntry{ Values: points2, }, } r2 := MustWALSegment(dir, entries) iter, err := tsm1.NewWALKeyIterator(r1, r2) if err != nil { t.Fatalf("unexpected error creating WALKeyIterator: %v", err) } var readValues bool for iter.Next() { key, values, err := iter.Read() if err != nil { t.Fatalf("unexpected error read: %v", err) } if got, exp := key, "cpu,host=A#!~#value"; got != exp { t.Fatalf("key mismatch: got %v, exp %v", got, exp) } if got, exp := len(values), 2; got != exp { t.Fatalf("values length mismatch: got %v, exp %v", got, exp) } readValues = true assertValueEqual(t, values[0], v1) assertValueEqual(t, values[1], v2) } if !readValues { t.Fatalf("failed to read any values") } }
// // Tests that merge iterator over a wal returns points order correctly. func TestMergeIteragor_Single(t *testing.T) { dir := MustTempDir() defer os.RemoveAll(dir) v1 := tsm1.NewValue(time.Unix(1, 0), float64(1)) v2 := tsm1.NewValue(time.Unix(2, 0), float64(2)) points := map[string][]tsm1.Value{ "cpu,host=A#!~#value": []tsm1.Value{v1, v2}, } entries := []tsm1.WALEntry{ &tsm1.WriteWALEntry{ Values: points, }, } r := MustWALSegment(dir, entries) iter, err := tsm1.NewWALKeyIterator(r) if err != nil { t.Fatalf("unexpected error creating WALKeyIterator: %v", err) } // Read should return a chunk of 1 value m := tsm1.NewMergeIterator(iter, 1) var readValues bool for _, p := range points { if !m.Next() { t.Fatalf("expected next, got false") } key, values, err := m.Read() if err != nil { t.Fatalf("unexpected error reading: %v", err) } if got, exp := key, "cpu,host=A#!~#value"; got != exp { t.Fatalf("key mismatch: got %v, exp %v", got, exp) } if got, exp := len(values), 1; got != exp { t.Fatalf("values length mismatch: got %v, exp %v", got, exp) } readValues = true assertValueEqual(t, values[0], p[0]) } if !readValues { t.Fatalf("failed to read any values") } }
// Tests that a single WAL segment can be read and iterated over func TestKeyIterator_WALSegment_Single(t *testing.T) { dir := MustTempDir() defer os.RemoveAll(dir) v1 := tsm1.NewValue(time.Unix(1, 0), 1.1) writes := map[string][]tsm1.Value{ "cpu,host=A#!~#value": []tsm1.Value{v1}, } entries := []tsm1.WALEntry{ &tsm1.WriteWALEntry{ Values: writes, }, } r := MustWALSegment(dir, entries) iter, err := tsm1.NewWALKeyIterator(r) if err != nil { t.Fatalf("unexpected error creating WALKeyIterator: %v", err) } var readValues bool for iter.Next() { key, values, err := iter.Read() if err != nil { t.Fatalf("unexpected error read: %v", err) } if got, exp := key, "cpu,host=A#!~#value"; got != exp { t.Fatalf("key mismatch: got %v, exp %v", got, exp) } if got, exp := len(values), len(writes); got != exp { t.Fatalf("values length mismatch: got %v, exp %v", got, exp) } for _, v := range values { readValues = true assertValueEqual(t, v, v1) } } if !readValues { t.Fatalf("failed to read any values") } }
// // Tests that the merge iterator does not pull in deleted WAL entries. func TestMergeIteragor_DeletedKeys(t *testing.T) { dir := MustTempDir() defer os.RemoveAll(dir) v1 := tsm1.NewValue(time.Unix(1, 0), float64(1)) v2 := tsm1.NewValue(time.Unix(1, 0), float64(1)) v3 := tsm1.NewValue(time.Unix(2, 0), float64(2)) v4 := tsm1.NewValue(time.Unix(2, 0), float64(2)) v5 := tsm1.NewValue(time.Unix(1, 0), float64(3)) // overwrites p1 points1 := map[string][]tsm1.Value{ "cpu,host=A#!~#value": []tsm1.Value{v1, v3}, "cpu,host=B#!~#value": []tsm1.Value{v2}, } points2 := map[string][]tsm1.Value{ "cpu,host=A#!~#value": []tsm1.Value{v5}, "cpu,host=B#!~#value": []tsm1.Value{v4}, } entries := []tsm1.WALEntry{ &tsm1.WriteWALEntry{ Values: points1, }, &tsm1.WriteWALEntry{ Values: points2, }, &tsm1.DeleteWALEntry{ Keys: []string{"cpu,host=A#!~#value"}, }, } r := MustWALSegment(dir, entries) iter, err := tsm1.NewWALKeyIterator(r) if err != nil { t.Fatalf("unexpected error creating WALKeyIterator: %v", err) } m := tsm1.NewMergeIterator(iter, 2) var data = []struct { key string points []tsm1.Value }{ {"cpu,host=B#!~#value", []tsm1.Value{v2, v4}}, } for _, p := range data { if !m.Next() { t.Fatalf("expected next, got false") } key, values, err := m.Read() if err != nil { t.Fatalf("unexpected error reading: %v", err) } if got, exp := key, p.key; got != exp { t.Fatalf("key mismatch: got %v, exp %v", got, exp) } if got, exp := len(values), len(p.points); got != exp { t.Fatalf("values length mismatch: got %v, exp %v", got, exp) } for i, point := range p.points { assertValueEqual(t, values[i], point) } } }
// // Tests that writes, deletes followed by more writes returns the the // // correct values. func TestKeyIterator_WALSegment_WriteAfterDelete(t *testing.T) { dir := MustTempDir() defer os.RemoveAll(dir) v1 := tsm1.NewValue(time.Unix(1, 0), float64(1)) points1 := map[string][]tsm1.Value{ "cpu,host=A#!~#value": []tsm1.Value{v1}, } entries := []tsm1.WALEntry{ &tsm1.WriteWALEntry{ Values: points1, }, } r1 := MustWALSegment(dir, entries) v2 := tsm1.NewValue(time.Unix(1, 0), float64(1)) v3 := tsm1.NewValue(time.Unix(1, 0), float64(1)) points2 := map[string][]tsm1.Value{ "cpu,host=A#!~#count": []tsm1.Value{v2}, "cpu,host=B#!~#value": []tsm1.Value{v3}, } entries = []tsm1.WALEntry{ &tsm1.DeleteWALEntry{ Keys: []string{ "cpu,host=A#!~#count", "cpu,host=A#!~#value", }, }, &tsm1.WriteWALEntry{ Values: points2, }, } r2 := MustWALSegment(dir, entries) iter, err := tsm1.NewWALKeyIterator(r1, r2) if err != nil { t.Fatalf("unexpected error creating WALKeyIterator: %v", err) } var readValues bool var data = []struct { key string value tsm1.Value }{ {"cpu,host=A#!~#count", v2}, {"cpu,host=B#!~#value", v3}, } for iter.Next() { key, values, err := iter.Read() if err != nil { t.Fatalf("unexpected error read: %v", err) } if got, exp := key, data[0].key; got != exp { t.Fatalf("key mismatch: got %v, exp %v", got, exp) } if got, exp := len(values), 1; got != exp { t.Fatalf("values length mismatch: got %v, exp %v", got, exp) } readValues = true assertValueEqual(t, values[0], data[0].value) data = data[1:] } if !readValues { t.Fatalf("failed to read any values") } }