// Copyright (C) 2018 Marius Schellenberger package filter import "testing" type Example struct { String string Int int Bool bool Struct Struct1 } type Struct1 struct { String string Struct Struct2 } type Struct2 struct { Int int } type filter []Example func makefilter(v filter) (f filter) { f = make(filter, len(v)) copy(f, v) return } func (v filter) Len() int { return len(v) } func (v filter) Index(i int) interface{} { return v[i] } func (v *filter) Remove(i, j int) { *v = append((*v)[:i], (*v)[j:]...) } var ( data = filter{ {"str1", 42, true, Struct1{"s1", Struct2{1}}}, {"2str", 42, true, Struct1{"s2", Struct2{2}}}, {"str3", 42, false, Struct1{"s3", Struct2{3}}}, } benchData = filter{ {"str1", 41, true, Struct1{"s1", Struct2{1}}}, {"2str", 42, true, Struct1{"s2", Struct2{1}}}, {"str3", 43, false, Struct1{"s3", Struct2{1}}}, {"str4", 44, false, Struct1{"s4", Struct2{1}}}, {"str5", 45, false, Struct1{"s5", Struct2{1}}}, {"str6", 46, false, Struct1{"s6", Struct2{1}}}, {"str7", 47, true, Struct1{"s7", Struct2{1}}}, {"str8", 48, true, Struct1{"s8", Struct2{1}}}, {"str9", 49, true, Struct1{"s9", Struct2{1}}}, {"str10", 50, true, Struct1{"s10", Struct2{1}}}, {"str11", 51, false, Struct1{"s11", Struct2{1}}}, {"str12", 52, false, Struct1{"s12", Struct2{1}}}, } ) func TestNewQuery(t *testing.T) { _, err := NewQuery("String:1 String:2") if err == nil { t.Error("multiple AND fields") } _, err = NewQuery("String:1 sdcs Int:1") if err == nil { t.Error("invalid match") } _, err = NewQuery("String:1 sort:Bool:ASC") if err == nil { t.Error("invalid sort") } _, err = NewQuery(" ") if err == nil { t.Error("empty query") } _, err = NewQuery("OR") if err == nil { t.Error("empty query") } } const ( filter1 = "String:*st* Bool:true" filter2 = "Struct.Struct.Int:2 Struct.Struct.Int:3" ) func TestFilter(t *testing.T) { f1 := makefilter(data) q1, err := NewQuery("AND " + filter1) if err != nil { t.Error(err) } q1.Filter(&f1) if len(f1) != 2 { t.Error("f1 len is:", len(f1)) } if f1[0] != data[0] { t.Error("f1[0] != data[0]") } if f1[1] != data[1] { t.Error("f1[1] != data[1]") } f2 := makefilter(data) q2, err := NewQuery("OR " + filter2) if err != nil { t.Error(err) } q2.Filter(&f2) if len(f2) != 2 { t.Error("f2 len is:", len(f2)) } if f2[0] != data[1] { t.Error("f2[0] != data[1]") } if f2[1] != data[2] { t.Error("f2[1] != data[2]") } f3 := makefilter(data) q3, err := NewQuery("NOT " + filter2) if err != nil { t.Error(err) } q3.Filter(&f3) if len(f3) != 1 { t.Error("f3 len is:", len(f3)) } if f3[0] != data[0] { t.Error("f3[0] != data[0]") } } const ( sort1 = "sort:Int:desc" sort2 = "sort:Int:desc Bool:true" ) func TestSortFilter(t *testing.T) { f1 := makefilter(benchData) q1, err := NewQuery(sort1) if err != nil { t.Error(err) } q1.Filter(&f1) if len(f1) != 12 { t.Error("f1 len is:", len(f1)) } if f1[0] != benchData[11] { t.Error("f1[0] != benchData[11]") } if f1[11] != benchData[0] { t.Error("f1[11] != benchData[0]") } f2 := makefilter(benchData) q2, err := NewQuery("OR " + sort2) if err != nil { t.Error(err) } q2.Filter(&f2) if len(f2) != 6 { t.Error("f2 len is:", len(f2)) } if f2[0] != benchData[9] { t.Error("f2[0] != benchData[9]") } if f2[5] != benchData[0] { t.Error("f2[5] != benchData[0]") } f3 := makefilter(benchData) q3, err := NewQuery("NOT " + sort2) if err != nil { t.Error(err) } q3.Filter(&f3) if len(f3) != 6 { t.Error("f3 len is:", len(f3)) } if f3[0] != benchData[11] { t.Error("f3[0] != benchData[11]") } if f3[5] != benchData[2] { t.Error("f3[5] != benchData[2]") } } func TestGenericFilter(t *testing.T) { q1, err := NewQuery(filter1) if err != nil { t.Error(err) } a1 := q1.GenericFilter(data) if a1 == nil { t.Error("a1 is nil") } f1 := a1.(filter) if len(f1) != 2 { t.Error("f1 len is:", len(f1)) } if f1[0] != data[0] { t.Error("f1[0] != data[0]") } if f1[1] != data[1] { t.Error("f1[1] != data[1]") } q2, err := NewQuery("OR " + filter2) if err != nil { t.Error(err) } a2 := q2.GenericFilter(data) if a2 == nil { t.Error("a2 is nil") } f2 := a2.(filter) if len(f2) != 2 { t.Error("f2 len is:", len(f2)) } if f2[0] != data[1] { t.Error("f2[0] != data[1]") } if f2[1] != data[2] { t.Error("f2[1] != data[2]") } q3, err := NewQuery("NOT " + filter2) if err != nil { t.Error(err) } a3 := q3.GenericFilter(data) if a3 == nil { t.Error("a3 is nil") } f3 := a3.(filter) if len(f3) != 1 { t.Error("f3 len is:", len(f3)) } if f3[0] != data[0] { t.Error("f3[0] != data[0]") } } const ( simple = "OR Bool:true" comp = "String:*st* Bool:false Struct.Struct.Int:1" compOr = "OR Int:47 Bool:false Struct.String:s1*" sortOnly = "OR sort:Int:desc" simpleSort = "OR sort:Int:desc Bool:true" compSort = "sort:Int:desc String:*st* Bool:false Struct.Struct.Int:1" compOrSort = "OR sort:Int:desc Int:47 Bool:false Struct.String:s1*" ) func BenchmarkNewQuerySimple(b *testing.B) { b.ReportAllocs() for i := 0; i < b.N; i++ { NewQuery(simple) } } func BenchmarkNewQueryComplex(b *testing.B) { b.ReportAllocs() for i := 0; i < b.N; i++ { NewQuery(comp) } } func BenchmarkNewQueryComplexOr(b *testing.B) { b.ReportAllocs() for i := 0; i < b.N; i++ { NewQuery(compOr) } } func BenchmarkNewQueryCacheComplexOr(b *testing.B) { c := NewQueryCache(1) b.ReportAllocs() for i := 0; i < b.N; i++ { c.NewQuery(compOr) } } func BenchmarkNewQuerySort(b *testing.B) { b.ReportAllocs() for i := 0; i < b.N; i++ { NewQuery(sortOnly) } } func BenchmarkNewQuerySortSimple(b *testing.B) { b.ReportAllocs() for i := 0; i < b.N; i++ { NewQuery(simpleSort) } } func BenchmarkNewQuerySortComplex(b *testing.B) { b.ReportAllocs() for i := 0; i < b.N; i++ { NewQuery(compSort) } } func BenchmarkNewQuerySortComplexOr(b *testing.B) { b.ReportAllocs() for i := 0; i < b.N; i++ { NewQuery(compOrSort) } } func BenchmarkNewQueryCacheSortComplexOr(b *testing.B) { c := NewQueryCache(1) b.ReportAllocs() for i := 0; i < b.N; i++ { c.NewQuery(compOrSort) } } func BenchmarkFilterSimple(b *testing.B) { b.ReportAllocs() q, err := NewQuery(simple) if err != nil { b.Error(err) } fd := makefilter(benchData) for i := 0; i < b.N; i++ { q.Filter(&fd) } } func BenchmarkFilterComplex(b *testing.B) { b.ReportAllocs() q, err := NewQuery(comp) if err != nil { b.Error(err) } fd := makefilter(benchData) for i := 0; i < b.N; i++ { q.Filter(&fd) } } func BenchmarkFilterComplexOr(b *testing.B) { b.ReportAllocs() q, err := NewQuery(compOr) if err != nil { b.Error(err) } fd := makefilter(benchData) for i := 0; i < b.N; i++ { q.Filter(&fd) } } func BenchmarkSort(b *testing.B) { b.ReportAllocs() q, err := NewQuery(sortOnly) if err != nil { b.Error(err) } fd := makefilter(benchData) for i := 0; i < b.N; i++ { q.Filter(&fd) } } func BenchmarkSortFilterSimple(b *testing.B) { b.ReportAllocs() q, err := NewQuery(simpleSort) if err != nil { b.Error(err) } fd := makefilter(benchData) for i := 0; i < b.N; i++ { q.Filter(&fd) } } func BenchmarkSortFilterComplex(b *testing.B) { b.ReportAllocs() q, err := NewQuery(compSort) if err != nil { b.Error(err) } fd := makefilter(benchData) for i := 0; i < b.N; i++ { q.Filter(&fd) } } func BenchmarkSortFilterComplexOr(b *testing.B) { b.ReportAllocs() q, err := NewQuery(compOrSort) if err != nil { b.Error(err) } fd := makefilter(benchData) for i := 0; i < b.N; i++ { q.Filter(&fd) } } func BenchmarkGenericFilterSimple(b *testing.B) { b.ReportAllocs() q, err := NewQuery(simple) if err != nil { b.Error(err) } for i := 0; i < b.N; i++ { q.GenericFilter(benchData) } } func BenchmarkGenericFilterComplex(b *testing.B) { b.ReportAllocs() q, err := NewQuery(comp) if err != nil { b.Error(err) } for i := 0; i < b.N; i++ { q.GenericFilter(benchData) } } func BenchmarkGenericFilterComplexOr(b *testing.B) { b.ReportAllocs() q, err := NewQuery(compOr) if err != nil { b.Error(err) } for i := 0; i < b.N; i++ { q.GenericFilter(benchData) } }