276 lines
5.0 KiB
Go
276 lines
5.0 KiB
Go
package tsm1_test
|
|
|
|
import (
|
|
"math"
|
|
"reflect"
|
|
"testing"
|
|
"testing/quick"
|
|
|
|
"github.com/influxdata/influxdb/tsdb/engine/tsm1"
|
|
)
|
|
|
|
func TestFloatEncoder_Simple(t *testing.T) {
|
|
// Example from the paper
|
|
s := tsm1.NewFloatEncoder()
|
|
|
|
s.Push(12)
|
|
s.Push(12)
|
|
s.Push(24)
|
|
|
|
// extra tests
|
|
|
|
// floating point masking/shifting bug
|
|
s.Push(13)
|
|
s.Push(24)
|
|
|
|
// delta-of-delta sizes
|
|
s.Push(24)
|
|
s.Push(24)
|
|
s.Push(24)
|
|
|
|
s.Finish()
|
|
|
|
b, err := s.Bytes()
|
|
if err != nil {
|
|
t.Fatalf("unexpected error: %v", err)
|
|
}
|
|
|
|
it, err := tsm1.NewFloatDecoder(b)
|
|
if 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.Push(v)
|
|
}
|
|
|
|
s.Finish()
|
|
|
|
b, err := s.Bytes()
|
|
if err != nil {
|
|
t.Fatalf("unexpected error: %v", err)
|
|
}
|
|
|
|
it, err := tsm1.NewFloatDecoder(b)
|
|
if 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 = []struct {
|
|
v float64
|
|
}{
|
|
// 2h of data
|
|
{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.Push(p.v)
|
|
}
|
|
s.Finish()
|
|
|
|
b, err := s.Bytes()
|
|
if err != nil {
|
|
t.Fatalf("unexpected error: %v", err)
|
|
}
|
|
|
|
it, err := tsm1.NewFloatDecoder(b)
|
|
if 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.v != vv {
|
|
t.Errorf("Values()=(%v), want (%v)\n", vv, w.v)
|
|
}
|
|
}
|
|
|
|
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.Push(1.0)
|
|
s.Push(math.NaN())
|
|
s.Push(2.0)
|
|
s.Finish()
|
|
|
|
_, 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.Push(v)
|
|
}
|
|
enc.Finish()
|
|
|
|
// Read values out of decoder.
|
|
got := make([]float64, 0, len(values))
|
|
b, err := enc.Bytes()
|
|
if err != nil {
|
|
t.Fatalf("unexpected error: %v", err)
|
|
}
|
|
|
|
dec, err := tsm1.NewFloatDecoder(b)
|
|
if 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 BenchmarkFloatEncoder(b *testing.B) {
|
|
for i := 0; i < b.N; i++ {
|
|
s := tsm1.NewFloatEncoder()
|
|
for _, tt := range TwoHoursData {
|
|
s.Push(tt.v)
|
|
}
|
|
s.Finish()
|
|
}
|
|
}
|
|
|
|
func BenchmarkFloatDecoder(b *testing.B) {
|
|
s := tsm1.NewFloatEncoder()
|
|
for _, tt := range TwoHoursData {
|
|
s.Push(tt.v)
|
|
}
|
|
s.Finish()
|
|
bytes, err := s.Bytes()
|
|
if err != nil {
|
|
b.Fatalf("unexpected error: %v", err)
|
|
}
|
|
|
|
b.ResetTimer()
|
|
|
|
for i := 0; i < b.N; i++ {
|
|
it, err := tsm1.NewFloatDecoder(bytes)
|
|
if err != nil {
|
|
b.Fatalf("unexpected error creating float decoder: %v", err)
|
|
}
|
|
|
|
for j := 0; j < len(TwoHoursData); it.Next() {
|
|
j++
|
|
}
|
|
}
|
|
}
|