blob: 07aa4a5b6042669397c22578b152ba6ebcbb46bc [file] [log] [blame]
// Copyright 2018 Google Inc. All rights reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
package zoekt
import (
"reflect"
"testing"
"github.com/google/zoekt/query"
)
func Test_breakOnNewlines(t *testing.T) {
type args struct {
cm *candidateMatch
text []byte
}
tests := []struct {
name string
args args
want []*candidateMatch
}{
{
name: "trivial case",
args: args{
cm: &candidateMatch{
byteOffset: 0,
byteMatchSz: 0,
},
text: nil,
},
want: nil,
},
{
name: "no newlines",
args: args{
cm: &candidateMatch{
byteOffset: 0,
byteMatchSz: 1,
},
text: []byte("a"),
},
want: []*candidateMatch{
{
byteOffset: 0,
byteMatchSz: 1,
},
},
},
{
name: "newline at start",
args: args{
cm: &candidateMatch{
byteOffset: 0,
byteMatchSz: 2,
},
text: []byte("\na"),
},
want: []*candidateMatch{
{
byteOffset: 1,
byteMatchSz: 1,
},
},
},
{
name: "newline at end",
args: args{
cm: &candidateMatch{
byteOffset: 0,
byteMatchSz: 2,
},
text: []byte("a\n"),
},
want: []*candidateMatch{
{
byteOffset: 0,
byteMatchSz: 1,
},
},
},
{
name: "newline in middle",
args: args{
cm: &candidateMatch{
byteOffset: 0,
byteMatchSz: 3,
},
text: []byte("a\nb"),
},
want: []*candidateMatch{
{
byteOffset: 0,
byteMatchSz: 1,
},
{
byteOffset: 2,
byteMatchSz: 1,
},
},
},
{
name: "two newlines",
args: args{
cm: &candidateMatch{
byteOffset: 0,
byteMatchSz: 5,
},
text: []byte("a\nb\nc"),
},
want: []*candidateMatch{
{
byteOffset: 0,
byteMatchSz: 1,
},
{
byteOffset: 2,
byteMatchSz: 1,
},
{
byteOffset: 4,
byteMatchSz: 1,
},
},
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
if got := breakOnNewlines(tt.args.cm, tt.args.text); !reflect.DeepEqual(got, tt.want) {
type PrintableCm struct {
byteOffset uint32
byteMatchSz uint32
}
var got2, want2 []PrintableCm
for _, g := range got {
got2 = append(got2, PrintableCm{byteOffset: g.byteOffset, byteMatchSz: g.byteMatchSz})
}
for _, w := range tt.want {
want2 = append(want2, PrintableCm{byteOffset: w.byteOffset, byteMatchSz: w.byteMatchSz})
}
t.Errorf("breakMatchOnNewlines() = %+v, want %+v", got2, want2)
}
})
}
}
func TestEquivalentQuerySkipRegexpTree(t *testing.T) {
tests := []struct {
query string
skip bool
}{
{query: "^foo", skip: false},
{query: "foo", skip: true},
{query: "thread|needle|haystack", skip: true},
{query: "contain(er|ing)", skip: false},
{query: "thread (needle|haystack)", skip: true},
{query: "thread (needle|)", skip: false},
}
for _, tt := range tests {
q, err := query.Parse(tt.query)
if err != nil {
t.Errorf("Error parsing query: %s", "sym:"+tt.query)
continue
}
d := &indexData{}
mt, err := d.newMatchTree(q)
if err != nil {
t.Errorf("Error creating match tree from query: %s", q)
continue
}
visitMatchTree(mt, func(m matchTree) {
if _, ok := m.(*regexpMatchTree); ok && tt.skip {
t.Errorf("Expected regexpMatchTree to be skipped for query: %s", q)
}
})
}
}