1
// Copyright 2014 Google Inc. All Rights Reserved.
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
7
// http://www.apache.org/licenses/LICENSE-2.0
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.
28
"golang.org/x/net/context"
29
"google.golang.org/cloud/internal/testutil"
32
func TestBasics(t *testing.T) {
38
c := testutil.Context(ScopeDatastore, ScopeUserEmail)
39
x0 := X{66, "99", time.Now().Truncate(time.Millisecond)}
40
k, err := Put(c, NewIncompleteKey(c, "BasicsX", nil), &x0)
42
t.Fatalf("Put: %v", err)
47
t.Errorf("Get: %v", err)
51
t.Errorf("Delete: %v", err)
53
if !reflect.DeepEqual(x0, x1) {
54
t.Errorf("compare: x0=%v, x1=%v", x0, x1)
58
func TestListValues(t *testing.T) {
60
{Name: "L", Value: int64(12), Multiple: true},
61
{Name: "L", Value: "string", Multiple: true},
62
{Name: "L", Value: true, Multiple: true},
64
c := testutil.Context(ScopeDatastore, ScopeUserEmail)
65
k, err := Put(c, NewIncompleteKey(c, "ListValue", nil), &p0)
67
t.Fatalf("Put: %v", err)
70
if err := Get(c, k, &p1); err != nil {
71
t.Errorf("Get: %v", err)
73
if !reflect.DeepEqual(p0, p1) {
74
t.Errorf("compare:\np0=%v\np1=%#v", p0, p1)
76
if err = Delete(c, k); err != nil {
77
t.Errorf("Delete: %v", err)
81
func TestGetMulti(t *testing.T) {
85
c := testutil.Context(ScopeDatastore, ScopeUserEmail)
86
p := NewKey(c, "X", "", time.Now().Unix(), nil)
92
{key: NewKey(c, "X", "item1", 0, p), put: true},
93
{key: NewKey(c, "X", "item2", 0, p), put: false},
94
{key: NewKey(c, "X", "item3", 0, p), put: false},
95
{key: NewKey(c, "X", "item4", 0, p), put: true},
99
var srcKeys, dstKeys []*Key
100
for _, c := range cases {
101
dst = append(dst, &X{})
102
dstKeys = append(dstKeys, c.key)
104
src = append(src, &X{})
105
srcKeys = append(srcKeys, c.key)
108
if _, err := PutMulti(c, srcKeys, src); err != nil {
111
err := GetMulti(c, dstKeys, dst)
113
t.Errorf("GetMulti got %v, expected error", err)
115
e, ok := err.(MultiError)
117
t.Errorf("GetMulti got %t, expected MultiError", err)
119
for i, err := range e {
120
got, want := err, (error)(nil)
122
got, want = err, ErrNoSuchEntity
125
t.Errorf("MultiError[%d] == %v, want %v", i, got, want)
132
T string `datastore:",noindex"`
134
K []byte `datastore:",noindex"`
137
func (z Z) String() string {
139
v := reflect.ValueOf(z)
140
for i := 0; i < v.NumField(); i++ {
141
if l := v.Field(i).Len(); l > 0 {
142
lens = append(lens, fmt.Sprintf("len(%s)=%d", v.Type().Field(i).Name, l))
145
return fmt.Sprintf("Z{ %s }", strings.Join(lens, ","))
148
func TestUnindexableValues(t *testing.T) {
149
x500 := strings.Repeat("x", 500)
150
x501 := strings.Repeat("x", 501)
151
testCases := []struct {
155
{in: Z{S: x500}, wantErr: false},
156
{in: Z{S: x501}, wantErr: true},
157
{in: Z{T: x500}, wantErr: false},
158
{in: Z{T: x501}, wantErr: false},
159
{in: Z{P: []byte(x500)}, wantErr: false},
160
{in: Z{P: []byte(x501)}, wantErr: true},
161
{in: Z{K: []byte(x500)}, wantErr: false},
162
{in: Z{K: []byte(x501)}, wantErr: false},
164
c := testutil.Context(ScopeDatastore, ScopeUserEmail)
165
for _, tt := range testCases {
166
_, err := Put(c, NewIncompleteKey(c, "BasicsZ", nil), &tt.in)
167
if (err != nil) != tt.wantErr {
168
t.Errorf("Put %s got err %v, want err %t", tt.in, err, tt.wantErr)
173
type SQChild struct {
178
type SQTestCase struct {
185
func testSmallQueries(t *testing.T, c context.Context, parent *Key, children []*SQChild,
186
testCases []SQTestCase, extraTests ...func()) {
187
keys := make([]*Key, len(children))
188
for i := range keys {
189
keys[i] = NewIncompleteKey(c, "SQChild", parent)
191
keys, err := PutMulti(c, keys, children)
193
t.Fatalf("PutMulti: %v", err)
196
err := DeleteMulti(c, keys)
198
t.Errorf("DeleteMulti: %v", err)
202
for _, tc := range testCases {
203
count, err := tc.q.Count(c)
205
t.Errorf("Count %q: %v", tc.desc, err)
208
if count != tc.wantCount {
209
t.Errorf("Count %q: got %d want %d", tc.desc, count, tc.wantCount)
214
for _, tc := range testCases {
216
_, err := tc.q.GetAll(c, &got)
218
t.Errorf("GetAll %q: %v", tc.desc, err)
222
for _, c := range got {
225
if sum != tc.wantSum {
226
t.Errorf("sum %q: got %d want %d", tc.desc, sum, tc.wantSum)
230
for _, x := range extraTests {
235
func TestFilters(t *testing.T) {
236
c := testutil.Context(ScopeDatastore, ScopeUserEmail)
237
parent := NewKey(c, "SQParent", "TestFilters", 0, nil)
238
now := time.Now().Truncate(time.Millisecond).Unix()
239
children := []*SQChild{
240
{I: 0, T: now, U: now},
241
{I: 1, T: now, U: now},
242
{I: 2, T: now, U: now},
243
{I: 3, T: now, U: now},
244
{I: 4, T: now, U: now},
245
{I: 5, T: now, U: now},
246
{I: 6, T: now, U: now},
247
{I: 7, T: now, U: now},
249
baseQuery := NewQuery("SQChild").Ancestor(parent).Filter("T=", now)
250
testSmallQueries(t, c, parent, children, []SQTestCase{
253
baseQuery.Filter("I>", 1),
255
2 + 3 + 4 + 5 + 6 + 7,
259
baseQuery.Filter("I>", 2).Filter("I<=", 5),
265
baseQuery.Filter("I>=", 3).Filter("I<", 3),
271
baseQuery.Filter("I=", 4),
278
{I: 0, T: now, U: now},
279
{I: 1, T: now, U: now},
280
{I: 2, T: now, U: now},
281
{I: 3, T: now, U: now},
282
{I: 4, T: now, U: now},
283
{I: 5, T: now, U: now},
284
{I: 6, T: now, U: now},
285
{I: 7, T: now, U: now},
287
_, err := baseQuery.Order("I").GetAll(c, &got)
289
t.Errorf("GetAll: %v", err)
291
if !reflect.DeepEqual(got, want) {
292
t.Errorf("compare: got=%v, want=%v", got, want)
297
{I: 7, T: now, U: now},
298
{I: 6, T: now, U: now},
299
{I: 5, T: now, U: now},
300
{I: 4, T: now, U: now},
301
{I: 3, T: now, U: now},
302
{I: 2, T: now, U: now},
303
{I: 1, T: now, U: now},
304
{I: 0, T: now, U: now},
306
_, err := baseQuery.Order("-I").GetAll(c, &got)
308
t.Errorf("GetAll: %v", err)
310
if !reflect.DeepEqual(got, want) {
311
t.Errorf("compare: got=%v, want=%v", got, want)
316
func TestEventualConsistency(t *testing.T) {
317
c := testutil.Context(ScopeDatastore, ScopeUserEmail)
318
parent := NewKey(c, "SQParent", "TestEventualConsistency", 0, nil)
319
now := time.Now().Truncate(time.Millisecond).Unix()
320
children := []*SQChild{
321
{I: 0, T: now, U: now},
322
{I: 1, T: now, U: now},
323
{I: 2, T: now, U: now},
325
query := NewQuery("SQChild").Ancestor(parent).Filter("T =", now).EventualConsistency()
326
testSmallQueries(t, c, parent, children, nil, func() {
327
got, err := query.Count(c)
329
t.Fatalf("Count: %v", err)
331
if got < 0 || 3 < got {
332
t.Errorf("Count: got %d, want [0,3]", got)
337
func TestProjection(t *testing.T) {
338
c := testutil.Context(ScopeDatastore, ScopeUserEmail)
339
parent := NewKey(c, "SQParent", "TestProjection", 0, nil)
340
now := time.Now().Truncate(time.Millisecond).Unix()
341
children := []*SQChild{
342
{I: 1 << 0, J: 100, T: now, U: now},
343
{I: 1 << 1, J: 100, T: now, U: now},
344
{I: 1 << 2, J: 200, T: now, U: now},
345
{I: 1 << 3, J: 300, T: now, U: now},
346
{I: 1 << 4, J: 300, T: now, U: now},
348
baseQuery := NewQuery("SQChild").Ancestor(parent).Filter("T=", now).Filter("J>", 150)
349
testSmallQueries(t, c, parent, children, []SQTestCase{
352
baseQuery.Project("J"),
358
baseQuery.Project("J").Distinct(),
363
"project on meaningful (GD_WHEN) field",
364
baseQuery.Project("U"),
371
func TestAllocateIDs(t *testing.T) {
372
c := testutil.Context(ScopeDatastore, ScopeUserEmail)
373
keys := make([]*Key, 5)
374
for i := range keys {
375
keys[i] = NewIncompleteKey(c, "AllocID", nil)
377
keys, err := AllocateIDs(c, keys)
379
t.Errorf("AllocID #0 failed: %v", err)
381
if want := len(keys); want != 5 {
382
t.Errorf("Expected to allocate 5 keys, %d keys are found", want)
384
for _, k := range keys {
386
t.Errorf("Unexpeceted incomplete key found: %v", k)
391
func TestGetAllWithFieldMismatch(t *testing.T) {
399
c := testutil.Context(ScopeDatastore, ScopeUserEmail)
400
putKeys := make([]*Key, 3)
401
for i := range putKeys {
402
putKeys[i] = NewKey(c, "GetAllThing", "", int64(10+i), nil)
403
_, err := Put(c, putKeys[i], &Fat{X: 20 + i, Y: 30 + i})
405
t.Fatalf("Put: %v", err)
415
getKeys, err := NewQuery("GetAllThing").GetAll(c, &got)
416
if len(getKeys) != 3 && !reflect.DeepEqual(getKeys, putKeys) {
417
t.Errorf("GetAll: keys differ\ngetKeys=%v\nputKeys=%v", getKeys, putKeys)
419
if !reflect.DeepEqual(got, want) {
420
t.Errorf("GetAll: entities differ\ngot =%v\nwant=%v", got, want)
422
if _, ok := err.(*ErrFieldMismatch); !ok {
423
t.Errorf("GetAll: got err=%v, want ErrFieldMismatch", err)
427
func TestKindlessQueries(t *testing.T) {
437
c := testutil.Context(ScopeDatastore, ScopeUserEmail)
438
parent := NewKey(c, "Tweedle", "tweedle", 0, nil)
441
NewKey(c, "Dee", "dee0", 0, parent),
442
NewKey(c, "Dum", "dum1", 0, parent),
443
NewKey(c, "Dum", "dum2", 0, parent),
444
NewKey(c, "Dum", "dum3", 0, parent),
446
src := []interface{}{
447
&Dee{1, "binary0001"},
448
&Dum{2, "binary0010"},
449
&Dum{4, "binary0100"},
450
&Dum{8, "binary1000"},
452
keys, err := PutMulti(c, keys, src)
454
t.Fatalf("put: %v", err)
457
testCases := []struct {
465
query: NewQuery("Dee"),
470
query: NewQuery("Doh"),
474
query: NewQuery("Dum"),
475
want: []int{2, 4, 8},
480
want: []int{1, 2, 4, 8},
483
desc: "Kindless filter",
484
query: NewQuery("").Filter("__key__ =", keys[2]),
488
desc: "Kindless order",
489
query: NewQuery("").Order("__key__"),
490
want: []int{1, 2, 4, 8},
493
desc: "Kindless bad filter",
494
query: NewQuery("").Filter("I =", 4),
495
wantErr: "kind is required for filter: I",
498
desc: "Kindless bad order",
499
query: NewQuery("").Order("-__key__"),
500
wantErr: "kind is required for all orders except __key__ ascending",
504
for _, tc := range testCases {
505
q := tc.query.Ancestor(parent)
506
gotCount, err := q.Count(c)
508
if tc.wantErr == "" || !strings.Contains(err.Error(), tc.wantErr) {
509
t.Errorf("count %q: err %v, want err %q", tc.desc, err, tc.wantErr)
513
if tc.wantErr != "" {
514
t.Errorf("count %q: want err %q", tc.desc, tc.wantErr)
517
if gotCount != len(tc.want) {
518
t.Errorf("count %q: got %d want %d", tc.desc, gotCount, len(tc.want))
522
for iter := q.Run(c); ; {
527
_, err := iter.Next(&dst)
532
t.Errorf("iter.Next %q: %v", tc.desc, err)
535
got = append(got, dst.I)
538
if !reflect.DeepEqual(got, tc.want) {
539
t.Errorf("elems %q: got %+v want %+v", tc.desc, got, tc.want)