2016-12-14 15:47:05 +01:00
package tsdb
import (
2016-12-19 11:44:11 +01:00
"sort"
2016-12-14 15:47:05 +01:00
"testing"
2016-12-21 15:12:26 +01:00
"github.com/fabxc/tsdb/labels"
2016-12-14 15:47:05 +01:00
"github.com/stretchr/testify/require"
)
2016-12-19 11:44:11 +01:00
type mockSeriesIterator struct {
2017-01-02 13:27:52 +01:00
seek func ( int64 ) bool
at func ( ) ( int64 , float64 )
next func ( ) bool
err func ( ) error
2016-12-19 11:44:11 +01:00
}
2017-01-02 13:27:52 +01:00
func ( m * mockSeriesIterator ) Seek ( t int64 ) bool { return m . seek ( t ) }
func ( m * mockSeriesIterator ) At ( ) ( int64 , float64 ) { return m . at ( ) }
func ( m * mockSeriesIterator ) Next ( ) bool { return m . next ( ) }
func ( m * mockSeriesIterator ) Err ( ) error { return m . err ( ) }
2016-12-19 11:44:11 +01:00
type mockSeries struct {
2016-12-21 15:12:26 +01:00
labels func ( ) labels . Labels
2016-12-19 11:44:11 +01:00
iterator func ( ) SeriesIterator
}
2016-12-21 15:12:26 +01:00
func ( m * mockSeries ) Labels ( ) labels . Labels { return m . labels ( ) }
2016-12-19 11:44:11 +01:00
func ( m * mockSeries ) Iterator ( ) SeriesIterator { return m . iterator ( ) }
type listSeriesIterator struct {
list [ ] sample
idx int
}
func newListSeriesIterator ( list [ ] sample ) * listSeriesIterator {
return & listSeriesIterator { list : list , idx : - 1 }
}
2017-01-02 13:27:52 +01:00
func ( it * listSeriesIterator ) At ( ) ( int64 , float64 ) {
2016-12-19 11:44:11 +01:00
s := it . list [ it . idx ]
return s . t , s . v
}
func ( it * listSeriesIterator ) Next ( ) bool {
it . idx ++
return it . idx < len ( it . list )
}
func ( it * listSeriesIterator ) Seek ( t int64 ) bool {
2016-12-21 16:06:33 +01:00
if it . idx == - 1 {
it . idx = 0
}
2016-12-19 11:44:11 +01:00
// Do binary search between current position and end.
it . idx = sort . Search ( len ( it . list ) - it . idx , func ( i int ) bool {
s := it . list [ i + it . idx ]
return s . t >= t
} )
2016-12-21 16:06:33 +01:00
2016-12-19 11:44:11 +01:00
return it . idx < len ( it . list )
}
func ( it * listSeriesIterator ) Err ( ) error {
return nil
}
2017-03-14 15:24:08 +01:00
func TestMergedSeriesSet ( t * testing . T ) {
2016-12-19 11:44:11 +01:00
newSeries := func ( l map [ string ] string , s [ ] sample ) Series {
return & mockSeries {
2016-12-21 15:12:26 +01:00
labels : func ( ) labels . Labels { return labels . FromMap ( l ) } ,
2016-12-19 11:44:11 +01:00
iterator : func ( ) SeriesIterator { return newListSeriesIterator ( s ) } ,
}
}
cases := [ ] struct {
// The input sets in order (samples in series in b are strictly
// after those in a).
a , b SeriesSet
2017-01-06 08:08:02 +01:00
// The composition of a and b in the partition series set must yield
2016-12-19 11:44:11 +01:00
// results equivalent to the result series set.
exp SeriesSet
} {
{
a : newListSeriesSet ( [ ] Series {
newSeries ( map [ string ] string {
"a" : "a" ,
} , [ ] sample {
{ t : 1 , v : 1 } ,
} ) ,
} ) ,
b : newListSeriesSet ( [ ] Series {
newSeries ( map [ string ] string {
"a" : "a" ,
} , [ ] sample {
{ t : 2 , v : 2 } ,
} ) ,
newSeries ( map [ string ] string {
"b" : "b" ,
} , [ ] sample {
{ t : 1 , v : 1 } ,
} ) ,
} ) ,
exp : newListSeriesSet ( [ ] Series {
newSeries ( map [ string ] string {
"a" : "a" ,
} , [ ] sample {
{ t : 1 , v : 1 } ,
{ t : 2 , v : 2 } ,
} ) ,
newSeries ( map [ string ] string {
"b" : "b" ,
} , [ ] sample {
{ t : 1 , v : 1 } ,
} ) ,
} ) ,
} ,
2017-01-03 19:02:42 +01:00
{
a : newListSeriesSet ( [ ] Series {
newSeries ( map [ string ] string {
"handler" : "prometheus" ,
"instance" : "127.0.0.1:9090" ,
} , [ ] sample {
{ t : 1 , v : 1 } ,
} ) ,
newSeries ( map [ string ] string {
"handler" : "prometheus" ,
"instance" : "localhost:9090" ,
} , [ ] sample {
{ t : 1 , v : 2 } ,
} ) ,
} ) ,
b : newListSeriesSet ( [ ] Series {
newSeries ( map [ string ] string {
"handler" : "prometheus" ,
"instance" : "127.0.0.1:9090" ,
} , [ ] sample {
{ t : 2 , v : 1 } ,
} ) ,
newSeries ( map [ string ] string {
"handler" : "query" ,
"instance" : "localhost:9090" ,
} , [ ] sample {
{ t : 2 , v : 2 } ,
} ) ,
} ) ,
exp : newListSeriesSet ( [ ] Series {
newSeries ( map [ string ] string {
"handler" : "prometheus" ,
"instance" : "127.0.0.1:9090" ,
} , [ ] sample {
{ t : 1 , v : 1 } ,
{ t : 2 , v : 1 } ,
} ) ,
newSeries ( map [ string ] string {
"handler" : "prometheus" ,
"instance" : "localhost:9090" ,
} , [ ] sample {
{ t : 1 , v : 2 } ,
} ) ,
newSeries ( map [ string ] string {
"handler" : "query" ,
"instance" : "localhost:9090" ,
} , [ ] sample {
{ t : 2 , v : 2 } ,
} ) ,
} ) ,
} ,
2016-12-19 11:44:11 +01:00
}
Outer :
for _ , c := range cases {
2017-03-14 15:24:08 +01:00
res := newMergedSeriesSet ( c . a , c . b )
2016-12-19 11:44:11 +01:00
for {
eok , rok := c . exp . Next ( ) , res . Next ( )
require . Equal ( t , eok , rok , "next" )
if ! eok {
continue Outer
}
2017-01-02 13:27:52 +01:00
sexp := c . exp . At ( )
sres := res . At ( )
2016-12-19 11:44:11 +01:00
require . Equal ( t , sexp . Labels ( ) , sres . Labels ( ) , "labels" )
smplExp , errExp := expandSeriesIterator ( sexp . Iterator ( ) )
smplRes , errRes := expandSeriesIterator ( sres . Iterator ( ) )
require . Equal ( t , errExp , errRes , "samples error" )
require . Equal ( t , smplExp , smplRes , "samples" )
}
}
}
func expandSeriesIterator ( it SeriesIterator ) ( r [ ] sample , err error ) {
for it . Next ( ) {
2017-01-02 13:27:52 +01:00
t , v := it . At ( )
2016-12-19 11:44:11 +01:00
r = append ( r , sample { t : t , v : v } )
}
return r , it . Err ( )
}