1// Copyright 2019 The Go Cloud Development Kit Authors
2//
3// Licensed under the Apache License, Version 2.0 (the "License");
4// you may not use this file except in compliance with the License.
5// You may obtain a copy of the License at
6//
7//     https://www.apache.org/licenses/LICENSE-2.0
8//
9// Unless required by applicable law or agreed to in writing, software
10// distributed under the License is distributed on an "AS IS" BASIS,
11// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12// See the License for the specific language governing permissions and
13// limitations under the License.
14
15package docstore
16
17import (
18	"context"
19	"strings"
20	"testing"
21
22	"gocloud.dev/docstore/driver"
23	"gocloud.dev/gcerrors"
24)
25
26func TestQueryValidFilter(t *testing.T) {
27	for _, fp := range []FieldPath{"", ".a", "a..b", "b."} {
28		q := Query{dq: &driver.Query{}}
29		q.Where(fp, ">", 1)
30		if got := gcerrors.Code(q.err); got != gcerrors.InvalidArgument {
31			t.Errorf("fieldpath %q: got %s, want InvalidArgument", fp, got)
32		}
33	}
34	for _, op := range []string{"==", "!="} {
35		q := Query{dq: &driver.Query{}}
36		q.Where("a", op, 1)
37		if got := gcerrors.Code(q.err); got != gcerrors.InvalidArgument {
38			t.Errorf("op %s: got %s, want InvalidArgument", op, got)
39		}
40	}
41	for _, v := range []interface{}{nil, 5 + 2i, []byte("x"), func() {}, []int{}, map[string]bool{}} {
42		q := Query{dq: &driver.Query{}}
43		q.Where("a", "=", v)
44		if got := gcerrors.Code(q.err); got != gcerrors.InvalidArgument {
45			t.Errorf("value %+v: got %s, want InvalidArgument", v, got)
46		}
47	}
48}
49
50func TestInvalidQuery(t *testing.T) {
51	ctx := context.Background()
52	// We detect that these queries are invalid before they reach the driver.
53	c := &Collection{}
54
55	for _, test := range []struct {
56		desc         string
57		appliesToGet bool
58		q            *Query
59		contains     string // error text must contain this string
60	}{
61		{"negative Limit", true, c.Query().Limit(-1), "limit"},
62		{"zero Limit", true, c.Query().Limit(0), "limit"},
63		{"two Limits", true, c.Query().Limit(1).Limit(2), "limit"},
64		{"empty OrderBy field", true, c.Query().OrderBy("", Ascending), "empty field"},
65		{"bad OrderBy direction", true, c.Query().OrderBy("x", "y"), "direction"},
66		{"two OrderBys", true, c.Query().OrderBy("x", Ascending).OrderBy("y", Descending), "orderby"},
67		{"OrderBy not in Where", true, c.Query().OrderBy("x", Ascending).Where("y", ">", 1), "orderby"},
68		{"any Limit", false, c.Query().Limit(1), "limit"},
69		{"any OrderBy", false, c.Query().OrderBy("x", Descending), "orderby"},
70	} {
71		check := func(err error) {
72			if gcerrors.Code(err) != gcerrors.InvalidArgument {
73				t.Errorf("%s: got %v, want InvalidArgument", test.desc, err)
74				return
75			}
76			if !strings.Contains(strings.ToLower(err.Error()), test.contains) {
77				t.Errorf("%s: got %q, wanted it to contain %q", test.desc, err.Error(), test.contains)
78			}
79		}
80		if test.appliesToGet {
81			check(test.q.Get(ctx).Next(ctx, nil))
82		}
83	}
84}
85