317 lines
5.9 KiB
Go
317 lines
5.9 KiB
Go
package tsm1_test
|
|
|
|
import (
|
|
"fmt"
|
|
"math"
|
|
"reflect"
|
|
"testing"
|
|
"testing/quick"
|
|
|
|
"github.com/google/go-cmp/cmp"
|
|
"github.com/influxdata/platform/tsdb/tsm1"
|
|
)
|
|
|
|
func TestFloatEncoder_Simple(t *testing.T) {
|
|
// Example from the paper
|
|
s := tsm1.NewFloatEncoder()
|
|
|
|
s.Write(12)
|
|
s.Write(12)
|
|
s.Write(24)
|
|
|
|
// extra tests
|
|
|
|
// floating point masking/shifting bug
|
|
s.Write(13)
|
|
s.Write(24)
|
|
|
|
// delta-of-delta sizes
|
|
s.Write(24)
|
|
s.Write(24)
|
|
s.Write(24)
|
|
|
|
s.Flush()
|
|
|
|
b, err := s.Bytes()
|
|
if err != nil {
|
|
t.Fatalf("unexpected error: %v", err)
|
|
}
|
|
|
|
var it tsm1.FloatDecoder
|
|
if err := it.SetBytes(b); err != nil {
|
|
t.Fatalf("unexpected error creating float decoder: %v", err)
|
|
}
|
|
|
|
want := []float64{
|
|
12,
|
|
12,
|
|
24,
|
|
|
|
13,
|
|
24,
|
|
|
|
24,
|
|
24,
|
|
24,
|
|
}
|
|
|
|
for _, w := range want {
|
|
if !it.Next() {
|
|
t.Fatalf("Next()=false, want true")
|
|
}
|
|
vv := it.Values()
|
|
if w != vv {
|
|
t.Errorf("Values()=(%v), want (%v)\n", vv, w)
|
|
}
|
|
}
|
|
|
|
if it.Next() {
|
|
t.Fatalf("Next()=true, want false")
|
|
}
|
|
|
|
if err := it.Error(); err != nil {
|
|
t.Errorf("it.Error()=%v, want nil", err)
|
|
}
|
|
}
|
|
|
|
func TestFloatEncoder_SimilarFloats(t *testing.T) {
|
|
s := tsm1.NewFloatEncoder()
|
|
want := []float64{
|
|
6.00065e+06,
|
|
6.000656e+06,
|
|
6.000657e+06,
|
|
|
|
6.000659e+06,
|
|
6.000661e+06,
|
|
}
|
|
|
|
for _, v := range want {
|
|
s.Write(v)
|
|
}
|
|
|
|
s.Flush()
|
|
|
|
b, err := s.Bytes()
|
|
if err != nil {
|
|
t.Fatalf("unexpected error: %v", err)
|
|
}
|
|
|
|
var it tsm1.FloatDecoder
|
|
if err := it.SetBytes(b); err != nil {
|
|
t.Fatalf("unexpected error creating float decoder: %v", err)
|
|
}
|
|
|
|
for _, w := range want {
|
|
if !it.Next() {
|
|
t.Fatalf("Next()=false, want true")
|
|
}
|
|
vv := it.Values()
|
|
if w != vv {
|
|
t.Errorf("Values()=(%v), want (%v)\n", vv, w)
|
|
}
|
|
}
|
|
|
|
if it.Next() {
|
|
t.Fatalf("Next()=true, want false")
|
|
}
|
|
|
|
if err := it.Error(); err != nil {
|
|
t.Errorf("it.Error()=%v, want nil", err)
|
|
}
|
|
}
|
|
|
|
var twoHoursData = []float64{
|
|
// 2h of data, rows of 10 values
|
|
761, 727, 763, 706, 700, 679, 757, 708, 739, 707,
|
|
699, 740, 729, 766, 730, 715, 705, 693, 765, 724,
|
|
799, 761, 737, 766, 756, 719, 722, 801, 747, 731,
|
|
742, 744, 791, 750, 759, 809, 751, 705, 770, 792,
|
|
727, 762, 772, 721, 748, 753, 744, 716, 776, 659,
|
|
789, 766, 758, 690, 795, 770, 758, 723, 767, 765,
|
|
693, 706, 681, 727, 724, 780, 678, 696, 758, 740,
|
|
735, 700, 742, 747, 752, 734, 743, 732, 746, 770,
|
|
780, 710, 731, 712, 712, 741, 770, 770, 754, 718,
|
|
670, 775, 749, 795, 756, 741, 787, 721, 745, 782,
|
|
765, 780, 811, 790, 836, 743, 858, 739, 762, 770,
|
|
752, 763, 795, 792, 746, 786, 785, 774, 786, 718,
|
|
}
|
|
|
|
func TestFloatEncoder_Roundtrip(t *testing.T) {
|
|
s := tsm1.NewFloatEncoder()
|
|
for _, p := range twoHoursData {
|
|
s.Write(p)
|
|
}
|
|
s.Flush()
|
|
|
|
b, err := s.Bytes()
|
|
if err != nil {
|
|
t.Fatalf("unexpected error: %v", err)
|
|
}
|
|
|
|
var it tsm1.FloatDecoder
|
|
if err := it.SetBytes(b); err != nil {
|
|
t.Fatalf("unexpected error creating float decoder: %v", err)
|
|
}
|
|
|
|
for _, w := range twoHoursData {
|
|
if !it.Next() {
|
|
t.Fatalf("Next()=false, want true")
|
|
}
|
|
vv := it.Values()
|
|
// t.Logf("it.Values()=(%+v, %+v)\n", time.Unix(int64(tt), 0), vv)
|
|
if w != vv {
|
|
t.Errorf("Values()=(%v), want (%v)\n", vv, w)
|
|
}
|
|
}
|
|
|
|
if it.Next() {
|
|
t.Fatalf("Next()=true, want false")
|
|
}
|
|
|
|
if err := it.Error(); err != nil {
|
|
t.Errorf("it.Error()=%v, want nil", err)
|
|
}
|
|
}
|
|
|
|
func TestFloatEncoder_Roundtrip_NaN(t *testing.T) {
|
|
|
|
s := tsm1.NewFloatEncoder()
|
|
s.Write(1.0)
|
|
s.Write(math.NaN())
|
|
s.Write(2.0)
|
|
s.Flush()
|
|
|
|
_, err := s.Bytes()
|
|
|
|
if err == nil {
|
|
t.Fatalf("expected error. got nil")
|
|
}
|
|
}
|
|
|
|
func Test_FloatEncoder_Quick(t *testing.T) {
|
|
quick.Check(func(values []float64) bool {
|
|
|
|
expected := values
|
|
if values == nil {
|
|
expected = []float64{}
|
|
}
|
|
|
|
// Write values to encoder.
|
|
enc := tsm1.NewFloatEncoder()
|
|
for _, v := range values {
|
|
enc.Write(v)
|
|
}
|
|
enc.Flush()
|
|
|
|
// Read values out of decoder.
|
|
got := make([]float64, 0, len(values))
|
|
b, err := enc.Bytes()
|
|
if err != nil {
|
|
t.Fatalf("unexpected error: %v", err)
|
|
}
|
|
|
|
var dec tsm1.FloatDecoder
|
|
if err := dec.SetBytes(b); err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
for dec.Next() {
|
|
got = append(got, dec.Values())
|
|
}
|
|
|
|
// Verify that input and output values match.
|
|
if !reflect.DeepEqual(expected, got) {
|
|
t.Fatalf("mismatch:\n\nexp=%#v\n\ngot=%#v\n\n", expected, got)
|
|
}
|
|
|
|
return true
|
|
}, nil)
|
|
}
|
|
|
|
func TestFloatDecoder_Empty(t *testing.T) {
|
|
var dec tsm1.FloatDecoder
|
|
if err := dec.SetBytes([]byte{}); err != nil {
|
|
t.Fatalf("unexpected error: %v", err)
|
|
}
|
|
|
|
if dec.Next() {
|
|
t.Fatalf("exp next == false, got true")
|
|
}
|
|
}
|
|
|
|
func BenchmarkFloatEncoder(b *testing.B) {
|
|
for i := 0; i < b.N; i++ {
|
|
s := tsm1.NewFloatEncoder()
|
|
for _, tt := range twoHoursData {
|
|
s.Write(tt)
|
|
}
|
|
s.Flush()
|
|
}
|
|
}
|
|
|
|
func BenchmarkFloatDecoder(b *testing.B) {
|
|
s := tsm1.NewFloatEncoder()
|
|
for _, tt := range twoHoursData {
|
|
s.Write(tt)
|
|
}
|
|
s.Flush()
|
|
bytes, err := s.Bytes()
|
|
if err != nil {
|
|
b.Fatalf("unexpected error: %v", err)
|
|
}
|
|
|
|
b.ResetTimer()
|
|
|
|
for i := 0; i < b.N; i++ {
|
|
var it tsm1.FloatDecoder
|
|
if err := it.SetBytes(bytes); err != nil {
|
|
b.Fatalf("unexpected error creating float decoder: %v", err)
|
|
}
|
|
|
|
for j := 0; j < len(twoHoursData); it.Next() {
|
|
j++
|
|
}
|
|
}
|
|
}
|
|
|
|
func BenchmarkFloatDecoder_DecodeAll(b *testing.B) {
|
|
benchmarks := []int{
|
|
1,
|
|
55,
|
|
550,
|
|
1000,
|
|
}
|
|
for _, size := range benchmarks {
|
|
s := tsm1.NewFloatEncoder()
|
|
for c := 0; c < size; c++ {
|
|
s.Write(twoHoursData[c%len(twoHoursData)])
|
|
}
|
|
s.Flush()
|
|
bytes, err := s.Bytes()
|
|
if err != nil {
|
|
b.Fatalf("unexpected error: %v", err)
|
|
}
|
|
|
|
b.Run(fmt.Sprintf("%d", size), func(b *testing.B) {
|
|
b.SetBytes(int64(len(bytes)))
|
|
|
|
dst := make([]float64, size)
|
|
for i := 0; i < b.N; i++ {
|
|
var it tsm1.FloatDecoder
|
|
if err := it.SetBytes(bytes); err != nil {
|
|
b.Fatalf("unexpected error creating float decoder: %v", err)
|
|
}
|
|
|
|
i := 0
|
|
for it.Next() {
|
|
dst[i] = it.Values()
|
|
i++
|
|
}
|
|
|
|
if len(dst) != size {
|
|
b.Fatalf("unexpected length -got/+exp\n%s", cmp.Diff(len(dst), size))
|
|
}
|
|
}
|
|
})
|
|
}
|
|
}
|