~nskaggs/+junk/xenial-test

« back to all changes in this revision

Viewing changes to src/google.golang.org/cloud/datastore/integration_test.go

  • Committer: Nicholas Skaggs
  • Date: 2016-10-24 20:56:05 UTC
  • Revision ID: nicholas.skaggs@canonical.com-20161024205605-z8lta0uvuhtxwzwl
Initi with beta15

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
// Copyright 2014 Google Inc. All Rights Reserved.
 
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
//      http://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
 
 
15
// +build integration
 
16
 
 
17
package datastore
 
18
 
 
19
import (
 
20
        "fmt"
 
21
 
 
22
        "reflect"
 
23
        "sort"
 
24
        "strings"
 
25
        "testing"
 
26
        "time"
 
27
 
 
28
        "golang.org/x/net/context"
 
29
        "google.golang.org/cloud/internal/testutil"
 
30
)
 
31
 
 
32
func TestBasics(t *testing.T) {
 
33
        type X struct {
 
34
                I int
 
35
                S string
 
36
                T time.Time
 
37
        }
 
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)
 
41
        if err != nil {
 
42
                t.Fatalf("Put: %v", err)
 
43
        }
 
44
        x1 := X{}
 
45
        err = Get(c, k, &x1)
 
46
        if err != nil {
 
47
                t.Errorf("Get: %v", err)
 
48
        }
 
49
        err = Delete(c, k)
 
50
        if err != nil {
 
51
                t.Errorf("Delete: %v", err)
 
52
        }
 
53
        if !reflect.DeepEqual(x0, x1) {
 
54
                t.Errorf("compare: x0=%v, x1=%v", x0, x1)
 
55
        }
 
56
}
 
57
 
 
58
func TestListValues(t *testing.T) {
 
59
        p0 := PropertyList{
 
60
                {Name: "L", Value: int64(12), Multiple: true},
 
61
                {Name: "L", Value: "string", Multiple: true},
 
62
                {Name: "L", Value: true, Multiple: true},
 
63
        }
 
64
        c := testutil.Context(ScopeDatastore, ScopeUserEmail)
 
65
        k, err := Put(c, NewIncompleteKey(c, "ListValue", nil), &p0)
 
66
        if err != nil {
 
67
                t.Fatalf("Put: %v", err)
 
68
        }
 
69
        var p1 PropertyList
 
70
        if err := Get(c, k, &p1); err != nil {
 
71
                t.Errorf("Get: %v", err)
 
72
        }
 
73
        if !reflect.DeepEqual(p0, p1) {
 
74
                t.Errorf("compare:\np0=%v\np1=%#v", p0, p1)
 
75
        }
 
76
        if err = Delete(c, k); err != nil {
 
77
                t.Errorf("Delete: %v", err)
 
78
        }
 
79
}
 
80
 
 
81
func TestGetMulti(t *testing.T) {
 
82
        type X struct {
 
83
                I int
 
84
        }
 
85
        c := testutil.Context(ScopeDatastore, ScopeUserEmail)
 
86
        p := NewKey(c, "X", "", time.Now().Unix(), nil)
 
87
 
 
88
        cases := []struct {
 
89
                key *Key
 
90
                put bool
 
91
        }{
 
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},
 
96
        }
 
97
 
 
98
        var src, dst []*X
 
99
        var srcKeys, dstKeys []*Key
 
100
        for _, c := range cases {
 
101
                dst = append(dst, &X{})
 
102
                dstKeys = append(dstKeys, c.key)
 
103
                if c.put {
 
104
                        src = append(src, &X{})
 
105
                        srcKeys = append(srcKeys, c.key)
 
106
                }
 
107
        }
 
108
        if _, err := PutMulti(c, srcKeys, src); err != nil {
 
109
                t.Error(err)
 
110
        }
 
111
        err := GetMulti(c, dstKeys, dst)
 
112
        if err == nil {
 
113
                t.Errorf("GetMulti got %v, expected error", err)
 
114
        }
 
115
        e, ok := err.(MultiError)
 
116
        if !ok {
 
117
                t.Errorf("GetMulti got %t, expected MultiError", err)
 
118
        }
 
119
        for i, err := range e {
 
120
                got, want := err, (error)(nil)
 
121
                if !cases[i].put {
 
122
                        got, want = err, ErrNoSuchEntity
 
123
                }
 
124
                if got != want {
 
125
                        t.Errorf("MultiError[%d] == %v, want %v", i, got, want)
 
126
                }
 
127
        }
 
128
}
 
129
 
 
130
type Z struct {
 
131
        S string
 
132
        T string `datastore:",noindex"`
 
133
        P []byte
 
134
        K []byte `datastore:",noindex"`
 
135
}
 
136
 
 
137
func (z Z) String() string {
 
138
        var lens []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))
 
143
                }
 
144
        }
 
145
        return fmt.Sprintf("Z{ %s }", strings.Join(lens, ","))
 
146
}
 
147
 
 
148
func TestUnindexableValues(t *testing.T) {
 
149
        x500 := strings.Repeat("x", 500)
 
150
        x501 := strings.Repeat("x", 501)
 
151
        testCases := []struct {
 
152
                in      Z
 
153
                wantErr bool
 
154
        }{
 
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},
 
163
        }
 
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)
 
169
                }
 
170
        }
 
171
}
 
172
 
 
173
type SQChild struct {
 
174
        I, J int
 
175
        T, U int64
 
176
}
 
177
 
 
178
type SQTestCase struct {
 
179
        desc      string
 
180
        q         *Query
 
181
        wantCount int
 
182
        wantSum   int
 
183
}
 
184
 
 
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)
 
190
        }
 
191
        keys, err := PutMulti(c, keys, children)
 
192
        if err != nil {
 
193
                t.Fatalf("PutMulti: %v", err)
 
194
        }
 
195
        defer func() {
 
196
                err := DeleteMulti(c, keys)
 
197
                if err != nil {
 
198
                        t.Errorf("DeleteMulti: %v", err)
 
199
                }
 
200
        }()
 
201
 
 
202
        for _, tc := range testCases {
 
203
                count, err := tc.q.Count(c)
 
204
                if err != nil {
 
205
                        t.Errorf("Count %q: %v", tc.desc, err)
 
206
                        continue
 
207
                }
 
208
                if count != tc.wantCount {
 
209
                        t.Errorf("Count %q: got %d want %d", tc.desc, count, tc.wantCount)
 
210
                        continue
 
211
                }
 
212
        }
 
213
 
 
214
        for _, tc := range testCases {
 
215
                var got []SQChild
 
216
                _, err := tc.q.GetAll(c, &got)
 
217
                if err != nil {
 
218
                        t.Errorf("GetAll %q: %v", tc.desc, err)
 
219
                        continue
 
220
                }
 
221
                sum := 0
 
222
                for _, c := range got {
 
223
                        sum += c.I + c.J
 
224
                }
 
225
                if sum != tc.wantSum {
 
226
                        t.Errorf("sum %q: got %d want %d", tc.desc, sum, tc.wantSum)
 
227
                        continue
 
228
                }
 
229
        }
 
230
        for _, x := range extraTests {
 
231
                x()
 
232
        }
 
233
}
 
234
 
 
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},
 
248
        }
 
249
        baseQuery := NewQuery("SQChild").Ancestor(parent).Filter("T=", now)
 
250
        testSmallQueries(t, c, parent, children, []SQTestCase{
 
251
                {
 
252
                        "I>1",
 
253
                        baseQuery.Filter("I>", 1),
 
254
                        6,
 
255
                        2 + 3 + 4 + 5 + 6 + 7,
 
256
                },
 
257
                {
 
258
                        "I>2 AND I<=5",
 
259
                        baseQuery.Filter("I>", 2).Filter("I<=", 5),
 
260
                        3,
 
261
                        3 + 4 + 5,
 
262
                },
 
263
                {
 
264
                        "I>=3 AND I<3",
 
265
                        baseQuery.Filter("I>=", 3).Filter("I<", 3),
 
266
                        0,
 
267
                        0,
 
268
                },
 
269
                {
 
270
                        "I=4",
 
271
                        baseQuery.Filter("I=", 4),
 
272
                        1,
 
273
                        4,
 
274
                },
 
275
        }, func() {
 
276
                got := []*SQChild{}
 
277
                want := []*SQChild{
 
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},
 
286
                }
 
287
                _, err := baseQuery.Order("I").GetAll(c, &got)
 
288
                if err != nil {
 
289
                        t.Errorf("GetAll: %v", err)
 
290
                }
 
291
                if !reflect.DeepEqual(got, want) {
 
292
                        t.Errorf("compare: got=%v, want=%v", got, want)
 
293
                }
 
294
        }, func() {
 
295
                got := []*SQChild{}
 
296
                want := []*SQChild{
 
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},
 
305
                }
 
306
                _, err := baseQuery.Order("-I").GetAll(c, &got)
 
307
                if err != nil {
 
308
                        t.Errorf("GetAll: %v", err)
 
309
                }
 
310
                if !reflect.DeepEqual(got, want) {
 
311
                        t.Errorf("compare: got=%v, want=%v", got, want)
 
312
                }
 
313
        })
 
314
}
 
315
 
 
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},
 
324
        }
 
325
        query := NewQuery("SQChild").Ancestor(parent).Filter("T =", now).EventualConsistency()
 
326
        testSmallQueries(t, c, parent, children, nil, func() {
 
327
                got, err := query.Count(c)
 
328
                if err != nil {
 
329
                        t.Fatalf("Count: %v", err)
 
330
                }
 
331
                if got < 0 || 3 < got {
 
332
                        t.Errorf("Count: got %d, want [0,3]", got)
 
333
                }
 
334
        })
 
335
}
 
336
 
 
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},
 
347
        }
 
348
        baseQuery := NewQuery("SQChild").Ancestor(parent).Filter("T=", now).Filter("J>", 150)
 
349
        testSmallQueries(t, c, parent, children, []SQTestCase{
 
350
                {
 
351
                        "project",
 
352
                        baseQuery.Project("J"),
 
353
                        3,
 
354
                        200 + 300 + 300,
 
355
                },
 
356
                {
 
357
                        "distinct",
 
358
                        baseQuery.Project("J").Distinct(),
 
359
                        2,
 
360
                        200 + 300,
 
361
                },
 
362
                {
 
363
                        "project on meaningful (GD_WHEN) field",
 
364
                        baseQuery.Project("U"),
 
365
                        3,
 
366
                        0,
 
367
                },
 
368
        })
 
369
}
 
370
 
 
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)
 
376
        }
 
377
        keys, err := AllocateIDs(c, keys)
 
378
        if err != nil {
 
379
                t.Errorf("AllocID #0 failed: %v", err)
 
380
        }
 
381
        if want := len(keys); want != 5 {
 
382
                t.Errorf("Expected to allocate 5 keys, %d keys are found", want)
 
383
        }
 
384
        for _, k := range keys {
 
385
                if k.Incomplete() {
 
386
                        t.Errorf("Unexpeceted incomplete key found: %v", k)
 
387
                }
 
388
        }
 
389
}
 
390
 
 
391
func TestGetAllWithFieldMismatch(t *testing.T) {
 
392
        type Fat struct {
 
393
                X, Y int
 
394
        }
 
395
        type Thin struct {
 
396
                X int
 
397
        }
 
398
 
 
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})
 
404
                if err != nil {
 
405
                        t.Fatalf("Put: %v", err)
 
406
                }
 
407
        }
 
408
 
 
409
        var got []Thin
 
410
        want := []Thin{
 
411
                {X: 20},
 
412
                {X: 21},
 
413
                {X: 22},
 
414
        }
 
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)
 
418
        }
 
419
        if !reflect.DeepEqual(got, want) {
 
420
                t.Errorf("GetAll: entities differ\ngot =%v\nwant=%v", got, want)
 
421
        }
 
422
        if _, ok := err.(*ErrFieldMismatch); !ok {
 
423
                t.Errorf("GetAll: got err=%v, want ErrFieldMismatch", err)
 
424
        }
 
425
}
 
426
 
 
427
func TestKindlessQueries(t *testing.T) {
 
428
        type Dee struct {
 
429
                I   int
 
430
                Why string
 
431
        }
 
432
        type Dum struct {
 
433
                I     int
 
434
                Pling string
 
435
        }
 
436
 
 
437
        c := testutil.Context(ScopeDatastore, ScopeUserEmail)
 
438
        parent := NewKey(c, "Tweedle", "tweedle", 0, nil)
 
439
 
 
440
        keys := []*Key{
 
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),
 
445
        }
 
446
        src := []interface{}{
 
447
                &Dee{1, "binary0001"},
 
448
                &Dum{2, "binary0010"},
 
449
                &Dum{4, "binary0100"},
 
450
                &Dum{8, "binary1000"},
 
451
        }
 
452
        keys, err := PutMulti(c, keys, src)
 
453
        if err != nil {
 
454
                t.Fatalf("put: %v", err)
 
455
        }
 
456
 
 
457
        testCases := []struct {
 
458
                desc    string
 
459
                query   *Query
 
460
                want    []int
 
461
                wantErr string
 
462
        }{
 
463
                {
 
464
                        desc:  "Dee",
 
465
                        query: NewQuery("Dee"),
 
466
                        want:  []int{1},
 
467
                },
 
468
                {
 
469
                        desc:  "Doh",
 
470
                        query: NewQuery("Doh"),
 
471
                        want:  nil},
 
472
                {
 
473
                        desc:  "Dum",
 
474
                        query: NewQuery("Dum"),
 
475
                        want:  []int{2, 4, 8},
 
476
                },
 
477
                {
 
478
                        desc:  "",
 
479
                        query: NewQuery(""),
 
480
                        want:  []int{1, 2, 4, 8},
 
481
                },
 
482
                {
 
483
                        desc:  "Kindless filter",
 
484
                        query: NewQuery("").Filter("__key__ =", keys[2]),
 
485
                        want:  []int{4},
 
486
                },
 
487
                {
 
488
                        desc:  "Kindless order",
 
489
                        query: NewQuery("").Order("__key__"),
 
490
                        want:  []int{1, 2, 4, 8},
 
491
                },
 
492
                {
 
493
                        desc:    "Kindless bad filter",
 
494
                        query:   NewQuery("").Filter("I =", 4),
 
495
                        wantErr: "kind is required for filter: I",
 
496
                },
 
497
                {
 
498
                        desc:    "Kindless bad order",
 
499
                        query:   NewQuery("").Order("-__key__"),
 
500
                        wantErr: "kind is required for all orders except __key__ ascending",
 
501
                },
 
502
        }
 
503
loop:
 
504
        for _, tc := range testCases {
 
505
                q := tc.query.Ancestor(parent)
 
506
                gotCount, err := q.Count(c)
 
507
                if err != nil {
 
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)
 
510
                        }
 
511
                        continue
 
512
                }
 
513
                if tc.wantErr != "" {
 
514
                        t.Errorf("count %q: want err %q", tc.desc, tc.wantErr)
 
515
                        continue
 
516
                }
 
517
                if gotCount != len(tc.want) {
 
518
                        t.Errorf("count %q: got %d want %d", tc.desc, gotCount, len(tc.want))
 
519
                        continue
 
520
                }
 
521
                var got []int
 
522
                for iter := q.Run(c); ; {
 
523
                        var dst struct {
 
524
                                I          int
 
525
                                Why, Pling string
 
526
                        }
 
527
                        _, err := iter.Next(&dst)
 
528
                        if err == Done {
 
529
                                break
 
530
                        }
 
531
                        if err != nil {
 
532
                                t.Errorf("iter.Next %q: %v", tc.desc, err)
 
533
                                continue loop
 
534
                        }
 
535
                        got = append(got, dst.I)
 
536
                }
 
537
                sort.Ints(got)
 
538
                if !reflect.DeepEqual(got, tc.want) {
 
539
                        t.Errorf("elems %q: got %+v want %+v", tc.desc, got, tc.want)
 
540
                        continue
 
541
                }
 
542
        }
 
543
}