0
0
Fork 0

added tests to top level

This commit is contained in:
Marty Schoch 2014-08-15 15:49:35 -04:00
parent c33f1668f7
commit b0153cecb4
8 changed files with 319 additions and 20 deletions

View File

@ -11,6 +11,11 @@ package bleve
const (
ERROR_INDEX_EXISTS Error = iota
ERROR_INDEX_DOES_NOT_EXIST
ERROR_DISJUNCTION_FEWER_THAN_MIN_CLAUSES
ERROR_BOOLEAN_QUERY_NEEDS_MUST_OR_SHOULD
ERROR_NUMERIC_QUERY_NO_BOUNDS
ERROR_PHRASE_QUERY_NO_TERMS
ERROR_UNKNOWN_QUERY_TYPE
)
type Error int
@ -20,6 +25,11 @@ func (e Error) Error() string {
}
var errorMessages = map[int]string{
int(ERROR_INDEX_EXISTS): "cannot create new index, it already exists",
int(ERROR_INDEX_DOES_NOT_EXIST): "cannot open index, it does not exist",
int(ERROR_INDEX_EXISTS): "cannot create new index, it already exists",
int(ERROR_INDEX_DOES_NOT_EXIST): "cannot open index, it does not exist",
int(ERROR_DISJUNCTION_FEWER_THAN_MIN_CLAUSES): "disjunction query has fewer than the minimum number of clauses to satisfy",
int(ERROR_BOOLEAN_QUERY_NEEDS_MUST_OR_SHOULD): "boolean query must contain at least one must or should clause",
int(ERROR_NUMERIC_QUERY_NO_BOUNDS): "numeric range query must specify min or max",
int(ERROR_PHRASE_QUERY_NO_TERMS): "phrase query must contain at least one term",
int(ERROR_UNKNOWN_QUERY_TYPE): "unknown query type",
}

View File

@ -10,8 +10,6 @@ package bleve
import (
"encoding/json"
"fmt"
"log"
"github.com/couchbaselabs/bleve/search"
)
@ -35,26 +33,33 @@ func ParseQuery(input []byte) (Query, error) {
if err != nil {
return nil, err
}
if rv.Boost() == 0 {
rv.SetBoost(1)
}
return &rv, nil
}
_, isMatchQuery := tmp["match"]
if isMatchQuery {
log.Printf("detected match query")
var rv MatchQuery
err := json.Unmarshal(input, &rv)
if err != nil {
return nil, err
}
if rv.Boost() == 0 {
rv.SetBoost(1)
}
return &rv, nil
}
_, isMatchPhraseQuery := tmp["match_phrase"]
if isMatchPhraseQuery {
log.Printf("detected match phrase query")
var rv MatchPhraseQuery
err := json.Unmarshal(input, &rv)
if err != nil {
return nil, err
}
if rv.Boost() == 0 {
rv.SetBoost(1)
}
return &rv, nil
}
_, hasMust := tmp["must"]
@ -66,6 +71,9 @@ func ParseQuery(input []byte) (Query, error) {
if err != nil {
return nil, err
}
if rv.Boost() == 0 {
rv.SetBoost(1)
}
return &rv, nil
}
_, hasTerms := tmp["terms"]
@ -75,6 +83,14 @@ func ParseQuery(input []byte) (Query, error) {
if err != nil {
return nil, err
}
if rv.Boost() == 0 {
rv.SetBoost(1)
}
for _, tq := range rv.Terms {
if tq.Boost() == 0 {
tq.SetBoost(1)
}
}
return &rv, nil
}
_, hasSyntaxQuery := tmp["query"]
@ -84,6 +100,9 @@ func ParseQuery(input []byte) (Query, error) {
if err != nil {
return nil, err
}
if rv.Boost() == 0 {
rv.SetBoost(1)
}
return &rv, nil
}
_, hasMin := tmp["min"]
@ -94,6 +113,9 @@ func ParseQuery(input []byte) (Query, error) {
if err != nil {
return nil, err
}
if rv.Boost() == 0 {
rv.SetBoost(1)
}
return &rv, nil
}
_, hasStart := tmp["start"]
@ -104,6 +126,9 @@ func ParseQuery(input []byte) (Query, error) {
if err != nil {
return nil, err
}
if rv.Boost() == 0 {
rv.SetBoost(1)
}
return &rv, nil
}
_, hasPrefix := tmp["prefix"]
@ -113,7 +138,10 @@ func ParseQuery(input []byte) (Query, error) {
if err != nil {
return nil, err
}
if rv.Boost() == 0 {
rv.SetBoost(1)
}
return &rv, nil
}
return nil, fmt.Errorf("Unrecognized query")
return nil, ERROR_UNKNOWN_QUERY_TYPE
}

View File

@ -9,8 +9,6 @@
package bleve
import (
"fmt"
"github.com/couchbaselabs/bleve/search"
)
@ -70,11 +68,29 @@ func (q *BooleanQuery) Searcher(i *indexImpl, explain bool) (search.Searcher, er
}
func (q *BooleanQuery) Validate() error {
if q.Must != nil {
err := q.Must.Validate()
if err != nil {
return err
}
}
if q.Should != nil {
err := q.Should.Validate()
if err != nil {
return err
}
}
if q.MustNot != nil {
err := q.MustNot.Validate()
if err != nil {
return err
}
}
if q.Must == nil && q.Should == nil {
return fmt.Errorf("Boolean query must contain at least one MUST or SHOULD clause")
return ERROR_BOOLEAN_QUERY_NEEDS_MUST_OR_SHOULD
}
if q.Must != nil && len(q.Must.Conjuncts) == 0 && q.Should != nil && len(q.Should.Disjuncts) == 0 {
return fmt.Errorf("Boolean query must contain at least one MUST or SHOULD clause")
return ERROR_BOOLEAN_QUERY_NEEDS_MUST_OR_SHOULD
}
return nil
}

View File

@ -74,5 +74,8 @@ func (q *ConjunctionQuery) UnmarshalJSON(data []byte) error {
q.Conjuncts[i] = query
}
q.BoostVal = tmp.BoostVal
if q.BoostVal == 0 {
q.BoostVal = 1
}
return nil
}

View File

@ -10,7 +10,6 @@ package bleve
import (
"encoding/json"
"fmt"
"github.com/couchbaselabs/bleve/search"
)
@ -65,7 +64,7 @@ func (q *DisjunctionQuery) Searcher(i *indexImpl, explain bool) (*search.Disjunc
func (q *DisjunctionQuery) Validate() error {
if int(q.MinVal) > len(q.Disjuncts) {
return fmt.Errorf("Minimum clauses in disjunction exceeds total number of clauses")
return ERROR_DISJUNCTION_FEWER_THAN_MIN_CLAUSES
}
return nil
}
@ -89,6 +88,9 @@ func (q *DisjunctionQuery) UnmarshalJSON(data []byte) error {
q.Disjuncts[i] = query
}
q.BoostVal = tmp.BoostVal
if q.BoostVal == 0 {
q.BoostVal = 1
}
q.MinVal = tmp.MinVal
return nil
}

View File

@ -9,8 +9,6 @@
package bleve
import (
"fmt"
"github.com/couchbaselabs/bleve/search"
)
@ -57,7 +55,7 @@ func (q *NumericRangeQuery) Searcher(i *indexImpl, explain bool) (search.Searche
func (q *NumericRangeQuery) Validate() error {
if q.Min == nil && q.Min == q.Max {
return fmt.Errorf("must specify min or max")
return ERROR_NUMERIC_QUERY_NO_BOUNDS
}
return nil
}

View File

@ -9,8 +9,6 @@
package bleve
import (
"fmt"
"github.com/couchbaselabs/bleve/search"
)
@ -53,8 +51,8 @@ func (q *PhraseQuery) Searcher(i *indexImpl, explain bool) (search.Searcher, err
}
func (q *PhraseQuery) Validate() error {
if q.Terms == nil {
return fmt.Errorf("Phrase query must contain at least one term")
if len(q.Terms) < 1 {
return ERROR_PHRASE_QUERY_NO_TERMS
}
return nil
}

244
query_test.go Normal file
View File

@ -0,0 +1,244 @@
// Copyright (c) 2014 Couchbase, Inc.
// 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 bleve
import (
"reflect"
"testing"
)
var minNum = 5.1
var maxNum = 7.1
var startDate = "2011-01-01"
var endDate = "2012-01-01"
func TestParseQuery(t *testing.T) {
tests := []struct {
input []byte
output Query
err error
}{
{
input: []byte(`{"term":"water","field":"desc"}`),
output: NewTermQuery("water").SetField("desc"),
},
{
input: []byte(`{"match":"beer","field":"desc"}`),
output: NewMatchQuery("beer").SetField("desc"),
},
{
input: []byte(`{"match_phrase":"light beer","field":"desc"}`),
output: NewMatchPhraseQuery("light beer").SetField("desc"),
},
{
input: []byte(`{"must":{"terms": [{"match":"beer","field":"desc"}]},"should":{"terms": [{"match":"water","field":"desc"}]},"must_not":{"terms": [{"match":"devon","field":"desc"}]}}`),
output: NewBooleanQuery(
NewConjunctionQuery([]Query{NewMatchQuery("beer").SetField("desc")}),
NewDisjunctionQuery([]Query{NewMatchQuery("water").SetField("desc")}).SetMin(0),
NewDisjunctionQuery([]Query{NewMatchQuery("devon").SetField("desc")}).SetMin(0)),
},
{
input: []byte(`{"terms":[{"term":"watered","field":"desc"},{"term":"down","field":"desc"}]}`),
output: NewPhraseQuery([]*TermQuery{
NewTermQuery("watered").SetField("desc"),
NewTermQuery("down").SetField("desc")}),
},
{
input: []byte(`{"query":"+beer \"light beer\" -devon"}`),
output: NewSyntaxQuery(`+beer "light beer" -devon`),
},
{
input: []byte(`{"min":5.1,"max":7.1,"field":"desc"}`),
output: NewNumericRangeQuery(&minNum, &maxNum).SetField("desc"),
},
{
input: []byte(`{"start":"` + startDate + `","end":"` + endDate + `","field":"desc"}`),
output: NewDateRangeQuery(&startDate, &endDate).SetField("desc"),
},
{
input: []byte(`{"prefix":"budwei","field":"desc"}`),
output: NewPrefixQuery("budwei").SetField("desc"),
},
{
input: []byte(`{"madeitup":"queryhere"}`),
output: nil,
err: ERROR_UNKNOWN_QUERY_TYPE,
},
}
for _, test := range tests {
actual, err := ParseQuery(test.input)
if err != nil && test.err == nil {
t.Error(err)
} else if test.err != nil {
if !reflect.DeepEqual(err, test.err) {
t.Errorf("expected error: %#v, got: %#v", test.err, err)
}
}
if !reflect.DeepEqual(test.output, actual) {
t.Errorf("expected: %#v, got: %#v", test.output, actual)
// t.Errorf("expected: %#v, got: %#v", test.output.(*BooleanQuery).Should, actual.(*BooleanQuery).Should)
}
}
}
func TestSetGetField(t *testing.T) {
tests := []struct {
query Query
field string
}{
{
query: NewTermQuery("water").SetField("desc"),
field: "desc",
},
{
query: NewMatchQuery("beer").SetField("desc"),
field: "desc",
},
{
query: NewMatchPhraseQuery("light beer").SetField("desc"),
field: "desc",
},
{
query: NewNumericRangeQuery(&minNum, &maxNum).SetField("desc"),
field: "desc",
},
{
query: NewDateRangeQuery(&startDate, &endDate).SetField("desc"),
field: "desc",
},
{
query: NewPrefixQuery("budwei").SetField("desc"),
field: "desc",
},
}
for _, test := range tests {
switch query := test.query.(type) {
case *TermQuery:
if query.Field() != test.field {
t.Errorf("expected field '%s', got '%s'", test.field, query.Field())
}
case *MatchQuery:
if query.Field() != test.field {
t.Errorf("expected field '%s', got '%s'", test.field, query.Field())
}
case *MatchPhraseQuery:
if query.Field() != test.field {
t.Errorf("expected field '%s', got '%s'", test.field, query.Field())
}
case *NumericRangeQuery:
if query.Field() != test.field {
t.Errorf("expected field '%s', got '%s'", test.field, query.Field())
}
case *DateRangeQuery:
if query.Field() != test.field {
t.Errorf("expected field '%s', got '%s'", test.field, query.Field())
}
case *PrefixQuery:
if query.Field() != test.field {
t.Errorf("expected field '%s', got '%s'", test.field, query.Field())
}
}
}
}
func TestQueryValidate(t *testing.T) {
tests := []struct {
query Query
err error
}{
{
query: NewTermQuery("water").SetField("desc"),
err: nil,
},
{
query: NewMatchQuery("beer").SetField("desc"),
err: nil,
},
{
query: NewMatchPhraseQuery("light beer").SetField("desc"),
err: nil,
},
{
query: NewNumericRangeQuery(&minNum, &maxNum).SetField("desc"),
err: nil,
},
{
query: NewNumericRangeQuery(nil, nil).SetField("desc"),
err: ERROR_NUMERIC_QUERY_NO_BOUNDS,
},
{
query: NewDateRangeQuery(&startDate, &endDate).SetField("desc"),
err: nil,
},
{
query: NewPrefixQuery("budwei").SetField("desc"),
err: nil,
},
{
query: NewSyntaxQuery(`+beer "light beer" -devon`),
err: nil,
},
{
query: NewPhraseQuery([]*TermQuery{
NewTermQuery("watered").SetField("desc"),
NewTermQuery("down").SetField("desc")}),
err: nil,
},
{
query: NewPhraseQuery([]*TermQuery{}),
err: ERROR_PHRASE_QUERY_NO_TERMS,
},
{
query: NewMatchNoneQuery().SetBoost(25),
err: nil,
},
{
query: NewMatchAllQuery().SetBoost(25),
err: nil,
},
{
query: NewBooleanQuery(
NewConjunctionQuery([]Query{NewMatchQuery("beer").SetField("desc")}),
NewDisjunctionQuery([]Query{NewMatchQuery("water").SetField("desc")}).SetMin(0),
NewDisjunctionQuery([]Query{NewMatchQuery("devon").SetField("desc")}).SetMin(0)),
err: nil,
},
{
query: NewBooleanQuery(
nil,
nil,
NewDisjunctionQuery([]Query{NewMatchQuery("devon").SetField("desc")}).SetMin(0)),
err: ERROR_BOOLEAN_QUERY_NEEDS_MUST_OR_SHOULD,
},
{
query: NewBooleanQuery(
NewConjunctionQuery([]Query{}),
NewDisjunctionQuery([]Query{}).SetMin(0),
NewDisjunctionQuery([]Query{NewMatchQuery("devon").SetField("desc")}).SetMin(0)),
err: ERROR_BOOLEAN_QUERY_NEEDS_MUST_OR_SHOULD,
},
{
query: NewBooleanQuery(
NewConjunctionQuery([]Query{NewMatchQuery("beer").SetField("desc")}),
NewDisjunctionQuery([]Query{NewMatchQuery("water").SetField("desc")}).SetMin(2),
NewDisjunctionQuery([]Query{NewMatchQuery("devon").SetField("desc")}).SetMin(0)),
err: ERROR_DISJUNCTION_FEWER_THAN_MIN_CLAUSES,
},
}
for _, test := range tests {
actual := test.query.Validate()
if !reflect.DeepEqual(actual, test.err) {
t.Errorf("expected error: %#v got %#v", test.err, actual)
}
}
}