You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 

1290 lines
31 KiB

  1. // Copyright 2014 Google LLC
  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. package datastore
  15. import (
  16. "context"
  17. "encoding/json"
  18. "errors"
  19. "flag"
  20. "fmt"
  21. "log"
  22. "os"
  23. "reflect"
  24. "sort"
  25. "strings"
  26. "sync"
  27. "testing"
  28. "time"
  29. "cloud.google.com/go/internal/testutil"
  30. "cloud.google.com/go/rpcreplay"
  31. "golang.org/x/oauth2"
  32. "google.golang.org/api/iterator"
  33. "google.golang.org/api/option"
  34. "google.golang.org/grpc"
  35. "google.golang.org/grpc/codes"
  36. "google.golang.org/grpc/status"
  37. )
  38. // TODO(djd): Make test entity clean up more robust: some test entities may
  39. // be left behind if tests are aborted, the transport fails, etc.
  40. var timeNow = time.Now()
  41. // suffix is a timestamp-based suffix which is appended to key names,
  42. // particularly for the root keys of entity groups. This reduces flakiness
  43. // when the tests are run in parallel.
  44. var suffix string
  45. const replayFilename = "datastore.replay"
  46. type replayInfo struct {
  47. ProjectID string
  48. Time time.Time
  49. }
  50. var (
  51. record = flag.Bool("record", false, "record RPCs")
  52. newTestClient = func(ctx context.Context, t *testing.T) *Client {
  53. return newClient(ctx, t, nil)
  54. }
  55. )
  56. func TestMain(m *testing.M) {
  57. os.Exit(testMain(m))
  58. }
  59. func testMain(m *testing.M) int {
  60. flag.Parse()
  61. if testing.Short() {
  62. if *record {
  63. log.Fatal("cannot combine -short and -record")
  64. }
  65. if testutil.CanReplay(replayFilename) {
  66. initReplay()
  67. }
  68. } else if *record {
  69. if testutil.ProjID() == "" {
  70. log.Fatal("must record with a project ID")
  71. }
  72. b, err := json.Marshal(replayInfo{
  73. ProjectID: testutil.ProjID(),
  74. Time: timeNow,
  75. })
  76. if err != nil {
  77. log.Fatal(err)
  78. }
  79. rec, err := rpcreplay.NewRecorder(replayFilename, b)
  80. if err != nil {
  81. log.Fatal(err)
  82. }
  83. defer func() {
  84. if err := rec.Close(); err != nil {
  85. log.Fatalf("closing recorder: %v", err)
  86. }
  87. }()
  88. newTestClient = func(ctx context.Context, t *testing.T) *Client {
  89. return newClient(ctx, t, rec.DialOptions())
  90. }
  91. log.Printf("recording to %s", replayFilename)
  92. }
  93. suffix = fmt.Sprintf("-t%d", timeNow.UnixNano())
  94. return m.Run()
  95. }
  96. func initReplay() {
  97. rep, err := rpcreplay.NewReplayer(replayFilename)
  98. if err != nil {
  99. log.Fatal(err)
  100. }
  101. defer rep.Close()
  102. var ri replayInfo
  103. if err := json.Unmarshal(rep.Initial(), &ri); err != nil {
  104. log.Fatalf("unmarshaling initial replay info: %v", err)
  105. }
  106. timeNow = ri.Time.In(time.Local)
  107. conn, err := rep.Connection()
  108. if err != nil {
  109. log.Fatal(err)
  110. }
  111. newTestClient = func(ctx context.Context, t *testing.T) *Client {
  112. client, err := NewClient(ctx, ri.ProjectID, option.WithGRPCConn(conn))
  113. if err != nil {
  114. t.Fatalf("NewClient: %v", err)
  115. }
  116. return client
  117. }
  118. log.Printf("replaying from %s", replayFilename)
  119. }
  120. func newClient(ctx context.Context, t *testing.T, dialOpts []grpc.DialOption) *Client {
  121. if testing.Short() {
  122. t.Skip("Integration tests skipped in short mode")
  123. }
  124. ts := testutil.TokenSource(ctx, ScopeDatastore)
  125. if ts == nil {
  126. t.Skip("Integration tests skipped. See CONTRIBUTING.md for details")
  127. }
  128. opts := []option.ClientOption{option.WithTokenSource(ts)}
  129. for _, opt := range dialOpts {
  130. opts = append(opts, option.WithGRPCDialOption(opt))
  131. }
  132. client, err := NewClient(ctx, testutil.ProjID(), opts...)
  133. if err != nil {
  134. t.Fatalf("NewClient: %v", err)
  135. }
  136. return client
  137. }
  138. func TestBasics(t *testing.T) {
  139. ctx, _ := context.WithTimeout(context.Background(), time.Second*20)
  140. client := newTestClient(ctx, t)
  141. defer client.Close()
  142. type X struct {
  143. I int
  144. S string
  145. T time.Time
  146. }
  147. x0 := X{66, "99", timeNow.Truncate(time.Millisecond)}
  148. k, err := client.Put(ctx, IncompleteKey("BasicsX", nil), &x0)
  149. if err != nil {
  150. t.Fatalf("client.Put: %v", err)
  151. }
  152. x1 := X{}
  153. err = client.Get(ctx, k, &x1)
  154. if err != nil {
  155. t.Errorf("client.Get: %v", err)
  156. }
  157. err = client.Delete(ctx, k)
  158. if err != nil {
  159. t.Errorf("client.Delete: %v", err)
  160. }
  161. if !testutil.Equal(x0, x1) {
  162. t.Errorf("compare: x0=%v, x1=%v", x0, x1)
  163. }
  164. }
  165. func TestTopLevelKeyLoaded(t *testing.T) {
  166. ctx, _ := context.WithTimeout(context.Background(), time.Second*20)
  167. client := newTestClient(ctx, t)
  168. defer client.Close()
  169. completeKey := NameKey("EntityWithKey", "myent", nil)
  170. type EntityWithKey struct {
  171. I int
  172. S string
  173. K *Key `datastore:"__key__"`
  174. }
  175. in := &EntityWithKey{
  176. I: 12,
  177. S: "abcd",
  178. }
  179. k, err := client.Put(ctx, completeKey, in)
  180. if err != nil {
  181. t.Fatalf("client.Put: %v", err)
  182. }
  183. var e EntityWithKey
  184. err = client.Get(ctx, k, &e)
  185. if err != nil {
  186. t.Fatalf("client.Get: %v", err)
  187. }
  188. // The two keys should be absolutely identical.
  189. if !testutil.Equal(e.K, k) {
  190. t.Fatalf("e.K not equal to k; got %#v, want %#v", e.K, k)
  191. }
  192. }
  193. func TestListValues(t *testing.T) {
  194. ctx := context.Background()
  195. client := newTestClient(ctx, t)
  196. defer client.Close()
  197. p0 := PropertyList{
  198. {Name: "L", Value: []interface{}{int64(12), "string", true}},
  199. }
  200. k, err := client.Put(ctx, IncompleteKey("ListValue", nil), &p0)
  201. if err != nil {
  202. t.Fatalf("client.Put: %v", err)
  203. }
  204. var p1 PropertyList
  205. if err := client.Get(ctx, k, &p1); err != nil {
  206. t.Errorf("client.Get: %v", err)
  207. }
  208. if !testutil.Equal(p0, p1) {
  209. t.Errorf("compare:\np0=%v\np1=%#v", p0, p1)
  210. }
  211. if err = client.Delete(ctx, k); err != nil {
  212. t.Errorf("client.Delete: %v", err)
  213. }
  214. }
  215. func TestGetMulti(t *testing.T) {
  216. ctx := context.Background()
  217. client := newTestClient(ctx, t)
  218. defer client.Close()
  219. type X struct {
  220. I int
  221. }
  222. p := NameKey("X", "x"+suffix, nil)
  223. cases := []struct {
  224. key *Key
  225. put bool
  226. }{
  227. {key: NameKey("X", "item1", p), put: true},
  228. {key: NameKey("X", "item2", p), put: false},
  229. {key: NameKey("X", "item3", p), put: false},
  230. {key: NameKey("X", "item3", p), put: false},
  231. {key: NameKey("X", "item4", p), put: true},
  232. }
  233. var src, dst []*X
  234. var srcKeys, dstKeys []*Key
  235. for _, c := range cases {
  236. dst = append(dst, &X{})
  237. dstKeys = append(dstKeys, c.key)
  238. if c.put {
  239. src = append(src, &X{})
  240. srcKeys = append(srcKeys, c.key)
  241. }
  242. }
  243. if _, err := client.PutMulti(ctx, srcKeys, src); err != nil {
  244. t.Error(err)
  245. }
  246. err := client.GetMulti(ctx, dstKeys, dst)
  247. if err == nil {
  248. t.Errorf("client.GetMulti got %v, expected error", err)
  249. }
  250. e, ok := err.(MultiError)
  251. if !ok {
  252. t.Errorf("client.GetMulti got %T, expected MultiError", err)
  253. }
  254. for i, err := range e {
  255. got, want := err, (error)(nil)
  256. if !cases[i].put {
  257. got, want = err, ErrNoSuchEntity
  258. }
  259. if got != want {
  260. t.Errorf("MultiError[%d] == %v, want %v", i, got, want)
  261. }
  262. }
  263. }
  264. type Z struct {
  265. S string
  266. T string `datastore:",noindex"`
  267. P []byte
  268. K []byte `datastore:",noindex"`
  269. }
  270. func (z Z) String() string {
  271. var lens []string
  272. v := reflect.ValueOf(z)
  273. for i := 0; i < v.NumField(); i++ {
  274. if l := v.Field(i).Len(); l > 0 {
  275. lens = append(lens, fmt.Sprintf("len(%s)=%d", v.Type().Field(i).Name, l))
  276. }
  277. }
  278. return fmt.Sprintf("Z{ %s }", strings.Join(lens, ","))
  279. }
  280. func TestUnindexableValues(t *testing.T) {
  281. ctx := context.Background()
  282. client := newTestClient(ctx, t)
  283. defer client.Close()
  284. x1500 := strings.Repeat("x", 1500)
  285. x1501 := strings.Repeat("x", 1501)
  286. testCases := []struct {
  287. in Z
  288. wantErr bool
  289. }{
  290. {in: Z{S: x1500}, wantErr: false},
  291. {in: Z{S: x1501}, wantErr: true},
  292. {in: Z{T: x1500}, wantErr: false},
  293. {in: Z{T: x1501}, wantErr: false},
  294. {in: Z{P: []byte(x1500)}, wantErr: false},
  295. {in: Z{P: []byte(x1501)}, wantErr: true},
  296. {in: Z{K: []byte(x1500)}, wantErr: false},
  297. {in: Z{K: []byte(x1501)}, wantErr: false},
  298. }
  299. for _, tt := range testCases {
  300. _, err := client.Put(ctx, IncompleteKey("BasicsZ", nil), &tt.in)
  301. if (err != nil) != tt.wantErr {
  302. t.Errorf("client.Put %s got err %v, want err %t", tt.in, err, tt.wantErr)
  303. }
  304. }
  305. }
  306. func TestNilKey(t *testing.T) {
  307. ctx := context.Background()
  308. client := newTestClient(ctx, t)
  309. defer client.Close()
  310. testCases := []struct {
  311. in K0
  312. wantErr bool
  313. }{
  314. {in: K0{K: testKey0}, wantErr: false},
  315. {in: K0{}, wantErr: false},
  316. }
  317. for _, tt := range testCases {
  318. _, err := client.Put(ctx, IncompleteKey("NilKey", nil), &tt.in)
  319. if (err != nil) != tt.wantErr {
  320. t.Errorf("client.Put %s got err %v, want err %t", tt.in, err, tt.wantErr)
  321. }
  322. }
  323. }
  324. type SQChild struct {
  325. I, J int
  326. T, U int64
  327. }
  328. type SQTestCase struct {
  329. desc string
  330. q *Query
  331. wantCount int
  332. wantSum int
  333. }
  334. func testSmallQueries(ctx context.Context, t *testing.T, client *Client, parent *Key, children []*SQChild,
  335. testCases []SQTestCase, extraTests ...func()) {
  336. keys := make([]*Key, len(children))
  337. for i := range keys {
  338. keys[i] = IncompleteKey("SQChild", parent)
  339. }
  340. keys, err := client.PutMulti(ctx, keys, children)
  341. if err != nil {
  342. t.Fatalf("client.PutMulti: %v", err)
  343. }
  344. defer func() {
  345. err := client.DeleteMulti(ctx, keys)
  346. if err != nil {
  347. t.Errorf("client.DeleteMulti: %v", err)
  348. }
  349. }()
  350. for _, tc := range testCases {
  351. count, err := client.Count(ctx, tc.q)
  352. if err != nil {
  353. t.Errorf("Count %q: %v", tc.desc, err)
  354. continue
  355. }
  356. if count != tc.wantCount {
  357. t.Errorf("Count %q: got %d want %d", tc.desc, count, tc.wantCount)
  358. continue
  359. }
  360. }
  361. for _, tc := range testCases {
  362. var got []SQChild
  363. _, err := client.GetAll(ctx, tc.q, &got)
  364. if err != nil {
  365. t.Errorf("client.GetAll %q: %v", tc.desc, err)
  366. continue
  367. }
  368. sum := 0
  369. for _, c := range got {
  370. sum += c.I + c.J
  371. }
  372. if sum != tc.wantSum {
  373. t.Errorf("sum %q: got %d want %d", tc.desc, sum, tc.wantSum)
  374. continue
  375. }
  376. }
  377. for _, x := range extraTests {
  378. x()
  379. }
  380. }
  381. func TestFilters(t *testing.T) {
  382. ctx := context.Background()
  383. client := newTestClient(ctx, t)
  384. defer client.Close()
  385. parent := NameKey("SQParent", "TestFilters"+suffix, nil)
  386. now := timeNow.Truncate(time.Millisecond).Unix()
  387. children := []*SQChild{
  388. {I: 0, T: now, U: now},
  389. {I: 1, T: now, U: now},
  390. {I: 2, T: now, U: now},
  391. {I: 3, T: now, U: now},
  392. {I: 4, T: now, U: now},
  393. {I: 5, T: now, U: now},
  394. {I: 6, T: now, U: now},
  395. {I: 7, T: now, U: now},
  396. }
  397. baseQuery := NewQuery("SQChild").Ancestor(parent).Filter("T=", now)
  398. testSmallQueries(ctx, t, client, parent, children, []SQTestCase{
  399. {
  400. "I>1",
  401. baseQuery.Filter("I>", 1),
  402. 6,
  403. 2 + 3 + 4 + 5 + 6 + 7,
  404. },
  405. {
  406. "I>2 AND I<=5",
  407. baseQuery.Filter("I>", 2).Filter("I<=", 5),
  408. 3,
  409. 3 + 4 + 5,
  410. },
  411. {
  412. "I>=3 AND I<3",
  413. baseQuery.Filter("I>=", 3).Filter("I<", 3),
  414. 0,
  415. 0,
  416. },
  417. {
  418. "I=4",
  419. baseQuery.Filter("I=", 4),
  420. 1,
  421. 4,
  422. },
  423. }, func() {
  424. got := []*SQChild{}
  425. want := []*SQChild{
  426. {I: 0, T: now, U: now},
  427. {I: 1, T: now, U: now},
  428. {I: 2, T: now, U: now},
  429. {I: 3, T: now, U: now},
  430. {I: 4, T: now, U: now},
  431. {I: 5, T: now, U: now},
  432. {I: 6, T: now, U: now},
  433. {I: 7, T: now, U: now},
  434. }
  435. _, err := client.GetAll(ctx, baseQuery.Order("I"), &got)
  436. if err != nil {
  437. t.Errorf("client.GetAll: %v", err)
  438. }
  439. if !testutil.Equal(got, want) {
  440. t.Errorf("compare: got=%v, want=%v", got, want)
  441. }
  442. }, func() {
  443. got := []*SQChild{}
  444. want := []*SQChild{
  445. {I: 7, T: now, U: now},
  446. {I: 6, T: now, U: now},
  447. {I: 5, T: now, U: now},
  448. {I: 4, T: now, U: now},
  449. {I: 3, T: now, U: now},
  450. {I: 2, T: now, U: now},
  451. {I: 1, T: now, U: now},
  452. {I: 0, T: now, U: now},
  453. }
  454. _, err := client.GetAll(ctx, baseQuery.Order("-I"), &got)
  455. if err != nil {
  456. t.Errorf("client.GetAll: %v", err)
  457. }
  458. if !testutil.Equal(got, want) {
  459. t.Errorf("compare: got=%v, want=%v", got, want)
  460. }
  461. })
  462. }
  463. type ckey struct{}
  464. func TestLargeQuery(t *testing.T) {
  465. ctx := context.Background()
  466. client := newTestClient(ctx, t)
  467. defer client.Close()
  468. parent := NameKey("LQParent", "TestFilters"+suffix, nil)
  469. now := timeNow.Truncate(time.Millisecond).Unix()
  470. // Make a large number of children entities.
  471. const n = 800
  472. children := make([]*SQChild, 0, n)
  473. keys := make([]*Key, 0, n)
  474. for i := 0; i < n; i++ {
  475. children = append(children, &SQChild{I: i, T: now, U: now})
  476. keys = append(keys, IncompleteKey("SQChild", parent))
  477. }
  478. // Store using PutMulti in batches.
  479. const batchSize = 500
  480. for i := 0; i < n; i = i + 500 {
  481. j := i + batchSize
  482. if j > n {
  483. j = n
  484. }
  485. fullKeys, err := client.PutMulti(ctx, keys[i:j], children[i:j])
  486. if err != nil {
  487. t.Fatalf("PutMulti(%d, %d): %v", i, j, err)
  488. }
  489. defer func() {
  490. err := client.DeleteMulti(ctx, fullKeys)
  491. if err != nil {
  492. t.Errorf("client.DeleteMulti: %v", err)
  493. }
  494. }()
  495. }
  496. q := NewQuery("SQChild").Ancestor(parent).Filter("T=", now).Order("I")
  497. // Wait group to allow us to run query tests in parallel below.
  498. var wg sync.WaitGroup
  499. // Check we get the expected count and results for various limits/offsets.
  500. queryTests := []struct {
  501. limit, offset, want int
  502. }{
  503. // Just limit.
  504. {limit: 0, want: 0},
  505. {limit: 100, want: 100},
  506. {limit: 501, want: 501},
  507. {limit: n, want: n},
  508. {limit: n * 2, want: n},
  509. {limit: -1, want: n},
  510. // Just offset.
  511. {limit: -1, offset: 100, want: n - 100},
  512. {limit: -1, offset: 500, want: n - 500},
  513. {limit: -1, offset: n, want: 0},
  514. // Limit and offset.
  515. {limit: 100, offset: 100, want: 100},
  516. {limit: 1000, offset: 100, want: n - 100},
  517. {limit: 500, offset: 500, want: n - 500},
  518. }
  519. for _, tt := range queryTests {
  520. q := q.Limit(tt.limit).Offset(tt.offset)
  521. wg.Add(1)
  522. go func(limit, offset, want int) {
  523. defer wg.Done()
  524. // Check Count returns the expected number of results.
  525. count, err := client.Count(ctx, q)
  526. if err != nil {
  527. t.Errorf("client.Count(limit=%d offset=%d): %v", limit, offset, err)
  528. return
  529. }
  530. if count != want {
  531. t.Errorf("Count(limit=%d offset=%d) returned %d, want %d", limit, offset, count, want)
  532. }
  533. var got []SQChild
  534. _, err = client.GetAll(ctx, q, &got)
  535. if err != nil {
  536. t.Errorf("client.GetAll(limit=%d offset=%d): %v", limit, offset, err)
  537. return
  538. }
  539. if len(got) != want {
  540. t.Errorf("GetAll(limit=%d offset=%d) returned %d, want %d", limit, offset, len(got), want)
  541. }
  542. for i, child := range got {
  543. if got, want := child.I, i+offset; got != want {
  544. t.Errorf("GetAll(limit=%d offset=%d) got[%d].I == %d; want %d", limit, offset, i, got, want)
  545. break
  546. }
  547. }
  548. }(tt.limit, tt.offset, tt.want)
  549. }
  550. // Also check iterator cursor behaviour.
  551. cursorTests := []struct {
  552. limit, offset int // Query limit and offset.
  553. count int // The number of times to call "next"
  554. want int // The I value of the desired element, -1 for "Done".
  555. }{
  556. // No limits.
  557. {count: 0, limit: -1, want: 0},
  558. {count: 5, limit: -1, want: 5},
  559. {count: 500, limit: -1, want: 500},
  560. {count: 1000, limit: -1, want: -1}, // No more results.
  561. // Limits.
  562. {count: 5, limit: 5, want: 5},
  563. {count: 500, limit: 5, want: 5},
  564. {count: 1000, limit: 1000, want: -1}, // No more results.
  565. // Offsets.
  566. {count: 0, offset: 5, limit: -1, want: 5},
  567. {count: 5, offset: 5, limit: -1, want: 10},
  568. {count: 200, offset: 500, limit: -1, want: 700},
  569. {count: 200, offset: 1000, limit: -1, want: -1}, // No more results.
  570. }
  571. for _, tt := range cursorTests {
  572. wg.Add(1)
  573. go func(count, limit, offset, want int) {
  574. defer wg.Done()
  575. ctx := context.WithValue(ctx, ckey{}, fmt.Sprintf("c=%d,l=%d,o=%d", count, limit, offset))
  576. // Run iterator through count calls to Next.
  577. it := client.Run(ctx, q.Limit(limit).Offset(offset).KeysOnly())
  578. for i := 0; i < count; i++ {
  579. _, err := it.Next(nil)
  580. if err == iterator.Done {
  581. break
  582. }
  583. if err != nil {
  584. t.Errorf("count=%d, limit=%d, offset=%d: it.Next failed at i=%d", count, limit, offset, i)
  585. return
  586. }
  587. }
  588. // Grab the cursor.
  589. cursor, err := it.Cursor()
  590. if err != nil {
  591. t.Errorf("count=%d, limit=%d, offset=%d: it.Cursor: %v", count, limit, offset, err)
  592. return
  593. }
  594. // Make a request for the next element.
  595. it = client.Run(ctx, q.Limit(1).Start(cursor))
  596. var entity SQChild
  597. _, err = it.Next(&entity)
  598. switch {
  599. case want == -1:
  600. if err != iterator.Done {
  601. t.Errorf("count=%d, limit=%d, offset=%d: it.Next from cursor %v, want Done", count, limit, offset, err)
  602. }
  603. case err != nil:
  604. t.Errorf("count=%d, limit=%d, offset=%d: it.Next from cursor: %v, want nil", count, limit, offset, err)
  605. case entity.I != want:
  606. t.Errorf("count=%d, limit=%d, offset=%d: got.I = %d, want %d", count, limit, offset, entity.I, want)
  607. }
  608. }(tt.count, tt.limit, tt.offset, tt.want)
  609. }
  610. wg.Wait()
  611. }
  612. func TestEventualConsistency(t *testing.T) {
  613. // TODO(jba): either make this actually test eventual consistency, or
  614. // delete it. Currently it behaves the same with or without the
  615. // EventualConsistency call.
  616. ctx := context.Background()
  617. client := newTestClient(ctx, t)
  618. defer client.Close()
  619. parent := NameKey("SQParent", "TestEventualConsistency"+suffix, nil)
  620. now := timeNow.Truncate(time.Millisecond).Unix()
  621. children := []*SQChild{
  622. {I: 0, T: now, U: now},
  623. {I: 1, T: now, U: now},
  624. {I: 2, T: now, U: now},
  625. }
  626. query := NewQuery("SQChild").Ancestor(parent).Filter("T =", now).EventualConsistency()
  627. testSmallQueries(ctx, t, client, parent, children, nil, func() {
  628. got, err := client.Count(ctx, query)
  629. if err != nil {
  630. t.Fatalf("Count: %v", err)
  631. }
  632. if got < 0 || 3 < got {
  633. t.Errorf("Count: got %d, want [0,3]", got)
  634. }
  635. })
  636. }
  637. func TestProjection(t *testing.T) {
  638. ctx := context.Background()
  639. client := newTestClient(ctx, t)
  640. defer client.Close()
  641. parent := NameKey("SQParent", "TestProjection"+suffix, nil)
  642. now := timeNow.Truncate(time.Millisecond).Unix()
  643. children := []*SQChild{
  644. {I: 1 << 0, J: 100, T: now, U: now},
  645. {I: 1 << 1, J: 100, T: now, U: now},
  646. {I: 1 << 2, J: 200, T: now, U: now},
  647. {I: 1 << 3, J: 300, T: now, U: now},
  648. {I: 1 << 4, J: 300, T: now, U: now},
  649. }
  650. baseQuery := NewQuery("SQChild").Ancestor(parent).Filter("T=", now).Filter("J>", 150)
  651. testSmallQueries(ctx, t, client, parent, children, []SQTestCase{
  652. {
  653. "project",
  654. baseQuery.Project("J"),
  655. 3,
  656. 200 + 300 + 300,
  657. },
  658. {
  659. "distinct",
  660. baseQuery.Project("J").Distinct(),
  661. 2,
  662. 200 + 300,
  663. },
  664. {
  665. "distinct on",
  666. baseQuery.Project("J").DistinctOn("J"),
  667. 2,
  668. 200 + 300,
  669. },
  670. {
  671. "project on meaningful (GD_WHEN) field",
  672. baseQuery.Project("U"),
  673. 3,
  674. 0,
  675. },
  676. })
  677. }
  678. func TestAllocateIDs(t *testing.T) {
  679. ctx := context.Background()
  680. client := newTestClient(ctx, t)
  681. defer client.Close()
  682. keys := make([]*Key, 5)
  683. for i := range keys {
  684. keys[i] = IncompleteKey("AllocID", nil)
  685. }
  686. keys, err := client.AllocateIDs(ctx, keys)
  687. if err != nil {
  688. t.Errorf("AllocID #0 failed: %v", err)
  689. }
  690. if want := len(keys); want != 5 {
  691. t.Errorf("Expected to allocate 5 keys, %d keys are found", want)
  692. }
  693. for _, k := range keys {
  694. if k.Incomplete() {
  695. t.Errorf("Unexpeceted incomplete key found: %v", k)
  696. }
  697. }
  698. }
  699. func TestGetAllWithFieldMismatch(t *testing.T) {
  700. ctx := context.Background()
  701. client := newTestClient(ctx, t)
  702. defer client.Close()
  703. type Fat struct {
  704. X, Y int
  705. }
  706. type Thin struct {
  707. X int
  708. }
  709. // Ancestor queries (those within an entity group) are strongly consistent
  710. // by default, which prevents a test from being flaky.
  711. // See https://cloud.google.com/appengine/docs/go/datastore/queries#Go_Data_consistency
  712. // for more information.
  713. parent := NameKey("SQParent", "TestGetAllWithFieldMismatch"+suffix, nil)
  714. putKeys := make([]*Key, 3)
  715. for i := range putKeys {
  716. putKeys[i] = IDKey("GetAllThing", int64(10+i), parent)
  717. _, err := client.Put(ctx, putKeys[i], &Fat{X: 20 + i, Y: 30 + i})
  718. if err != nil {
  719. t.Fatalf("client.Put: %v", err)
  720. }
  721. }
  722. var got []Thin
  723. want := []Thin{
  724. {X: 20},
  725. {X: 21},
  726. {X: 22},
  727. }
  728. getKeys, err := client.GetAll(ctx, NewQuery("GetAllThing").Ancestor(parent), &got)
  729. if len(getKeys) != 3 && !testutil.Equal(getKeys, putKeys) {
  730. t.Errorf("client.GetAll: keys differ\ngetKeys=%v\nputKeys=%v", getKeys, putKeys)
  731. }
  732. if !testutil.Equal(got, want) {
  733. t.Errorf("client.GetAll: entities differ\ngot =%v\nwant=%v", got, want)
  734. }
  735. if _, ok := err.(*ErrFieldMismatch); !ok {
  736. t.Errorf("client.GetAll: got err=%v, want ErrFieldMismatch", err)
  737. }
  738. }
  739. func TestKindlessQueries(t *testing.T) {
  740. ctx := context.Background()
  741. client := newTestClient(ctx, t)
  742. defer client.Close()
  743. type Dee struct {
  744. I int
  745. Why string
  746. }
  747. type Dum struct {
  748. I int
  749. Pling string
  750. }
  751. parent := NameKey("Tweedle", "tweedle"+suffix, nil)
  752. keys := []*Key{
  753. NameKey("Dee", "dee0", parent),
  754. NameKey("Dum", "dum1", parent),
  755. NameKey("Dum", "dum2", parent),
  756. NameKey("Dum", "dum3", parent),
  757. }
  758. src := []interface{}{
  759. &Dee{1, "binary0001"},
  760. &Dum{2, "binary0010"},
  761. &Dum{4, "binary0100"},
  762. &Dum{8, "binary1000"},
  763. }
  764. keys, err := client.PutMulti(ctx, keys, src)
  765. if err != nil {
  766. t.Fatalf("put: %v", err)
  767. }
  768. testCases := []struct {
  769. desc string
  770. query *Query
  771. want []int
  772. wantErr string
  773. }{
  774. {
  775. desc: "Dee",
  776. query: NewQuery("Dee"),
  777. want: []int{1},
  778. },
  779. {
  780. desc: "Doh",
  781. query: NewQuery("Doh"),
  782. want: nil},
  783. {
  784. desc: "Dum",
  785. query: NewQuery("Dum"),
  786. want: []int{2, 4, 8},
  787. },
  788. {
  789. desc: "",
  790. query: NewQuery(""),
  791. want: []int{1, 2, 4, 8},
  792. },
  793. {
  794. desc: "Kindless filter",
  795. query: NewQuery("").Filter("__key__ =", keys[2]),
  796. want: []int{4},
  797. },
  798. {
  799. desc: "Kindless order",
  800. query: NewQuery("").Order("__key__"),
  801. want: []int{1, 2, 4, 8},
  802. },
  803. {
  804. desc: "Kindless bad filter",
  805. query: NewQuery("").Filter("I =", 4),
  806. wantErr: "kind is required",
  807. },
  808. {
  809. desc: "Kindless bad order",
  810. query: NewQuery("").Order("-__key__"),
  811. wantErr: "kind is required for all orders except __key__ ascending",
  812. },
  813. }
  814. loop:
  815. for _, tc := range testCases {
  816. q := tc.query.Ancestor(parent)
  817. gotCount, err := client.Count(ctx, q)
  818. if err != nil {
  819. if tc.wantErr == "" || !strings.Contains(err.Error(), tc.wantErr) {
  820. t.Errorf("count %q: err %v, want err %q", tc.desc, err, tc.wantErr)
  821. }
  822. continue
  823. }
  824. if tc.wantErr != "" {
  825. t.Errorf("count %q: want err %q", tc.desc, tc.wantErr)
  826. continue
  827. }
  828. if gotCount != len(tc.want) {
  829. t.Errorf("count %q: got %d want %d", tc.desc, gotCount, len(tc.want))
  830. continue
  831. }
  832. var got []int
  833. for iter := client.Run(ctx, q); ; {
  834. var dst struct {
  835. I int
  836. Why, Pling string
  837. }
  838. _, err := iter.Next(&dst)
  839. if err == iterator.Done {
  840. break
  841. }
  842. if err != nil {
  843. t.Errorf("iter.Next %q: %v", tc.desc, err)
  844. continue loop
  845. }
  846. got = append(got, dst.I)
  847. }
  848. sort.Ints(got)
  849. if !testutil.Equal(got, tc.want) {
  850. t.Errorf("elems %q: got %+v want %+v", tc.desc, got, tc.want)
  851. continue
  852. }
  853. }
  854. }
  855. func TestTransaction(t *testing.T) {
  856. ctx := context.Background()
  857. client := newTestClient(ctx, t)
  858. defer client.Close()
  859. type Counter struct {
  860. N int
  861. T time.Time
  862. }
  863. bangErr := errors.New("bang")
  864. tests := []struct {
  865. desc string
  866. causeConflict []bool
  867. retErr []error
  868. want int
  869. wantErr error
  870. }{
  871. {
  872. desc: "3 attempts, no conflicts",
  873. causeConflict: []bool{false},
  874. retErr: []error{nil},
  875. want: 11,
  876. },
  877. {
  878. desc: "1 attempt, user error",
  879. causeConflict: []bool{false},
  880. retErr: []error{bangErr},
  881. wantErr: bangErr,
  882. },
  883. {
  884. desc: "2 attempts, 1 conflict",
  885. causeConflict: []bool{true, false},
  886. retErr: []error{nil, nil},
  887. want: 13, // Each conflict increments by 2.
  888. },
  889. {
  890. desc: "3 attempts, 3 conflicts",
  891. causeConflict: []bool{true, true, true},
  892. retErr: []error{nil, nil, nil},
  893. wantErr: ErrConcurrentTransaction,
  894. },
  895. }
  896. for i, tt := range tests {
  897. // Put a new counter.
  898. c := &Counter{N: 10, T: timeNow}
  899. key, err := client.Put(ctx, IncompleteKey("TransCounter", nil), c)
  900. if err != nil {
  901. t.Errorf("%s: client.Put: %v", tt.desc, err)
  902. continue
  903. }
  904. defer client.Delete(ctx, key)
  905. // Increment the counter in a transaction.
  906. // The test case can manually cause a conflict or return an
  907. // error at each attempt.
  908. var attempts int
  909. _, err = client.RunInTransaction(ctx, func(tx *Transaction) error {
  910. attempts++
  911. if attempts > len(tt.causeConflict) {
  912. return fmt.Errorf("too many attempts. Got %d, max %d", attempts, len(tt.causeConflict))
  913. }
  914. var c Counter
  915. if err := tx.Get(key, &c); err != nil {
  916. return err
  917. }
  918. c.N++
  919. if _, err := tx.Put(key, &c); err != nil {
  920. return err
  921. }
  922. if tt.causeConflict[attempts-1] {
  923. c.N++
  924. if _, err := client.Put(ctx, key, &c); err != nil {
  925. return err
  926. }
  927. }
  928. return tt.retErr[attempts-1]
  929. }, MaxAttempts(i))
  930. // Check the error returned by RunInTransaction.
  931. if err != tt.wantErr {
  932. t.Errorf("%s: got err %v, want %v", tt.desc, err, tt.wantErr)
  933. continue
  934. }
  935. if err != nil {
  936. continue
  937. }
  938. // Check the final value of the counter.
  939. if err := client.Get(ctx, key, c); err != nil {
  940. t.Errorf("%s: client.Get: %v", tt.desc, err)
  941. continue
  942. }
  943. if c.N != tt.want {
  944. t.Errorf("%s: counter N=%d, want N=%d", tt.desc, c.N, tt.want)
  945. }
  946. }
  947. }
  948. func TestReadOnlyTransaction(t *testing.T) {
  949. if testing.Short() {
  950. t.Skip("Integration tests skipped in short mode")
  951. }
  952. ctx := context.Background()
  953. client := newClient(ctx, t, nil)
  954. defer client.Close()
  955. type value struct{ N int }
  956. // Put a value.
  957. const n = 5
  958. v := &value{N: n}
  959. key, err := client.Put(ctx, IncompleteKey("roTxn", nil), v)
  960. if err != nil {
  961. t.Fatal(err)
  962. }
  963. defer client.Delete(ctx, key)
  964. // Read it from a read-only transaction.
  965. _, err = client.RunInTransaction(ctx, func(tx *Transaction) error {
  966. if err := tx.Get(key, v); err != nil {
  967. return err
  968. }
  969. return nil
  970. }, ReadOnly)
  971. if err != nil {
  972. t.Fatal(err)
  973. }
  974. if v.N != n {
  975. t.Fatalf("got %d, want %d", v.N, n)
  976. }
  977. // Attempting to write from a read-only transaction is an error.
  978. _, err = client.RunInTransaction(ctx, func(tx *Transaction) error {
  979. if _, err := tx.Put(key, v); err != nil {
  980. return err
  981. }
  982. return nil
  983. }, ReadOnly)
  984. if err == nil {
  985. t.Fatal("got nil, want error")
  986. }
  987. }
  988. func TestNilPointers(t *testing.T) {
  989. ctx := context.Background()
  990. client := newTestClient(ctx, t)
  991. defer client.Close()
  992. type X struct {
  993. S string
  994. }
  995. src := []*X{{"zero"}, {"one"}}
  996. keys := []*Key{IncompleteKey("NilX", nil), IncompleteKey("NilX", nil)}
  997. keys, err := client.PutMulti(ctx, keys, src)
  998. if err != nil {
  999. t.Fatalf("PutMulti: %v", err)
  1000. }
  1001. // It's okay to store into a slice of nil *X.
  1002. xs := make([]*X, 2)
  1003. if err := client.GetMulti(ctx, keys, xs); err != nil {
  1004. t.Errorf("GetMulti: %v", err)
  1005. } else if !testutil.Equal(xs, src) {
  1006. t.Errorf("GetMulti fetched %v, want %v", xs, src)
  1007. }
  1008. // It isn't okay to store into a single nil *X.
  1009. var x0 *X
  1010. if err, want := client.Get(ctx, keys[0], x0), ErrInvalidEntityType; err != want {
  1011. t.Errorf("Get: err %v; want %v", err, want)
  1012. }
  1013. // Test that deleting with duplicate keys work.
  1014. keys = append(keys, keys...)
  1015. if err := client.DeleteMulti(ctx, keys); err != nil {
  1016. t.Errorf("Delete: %v", err)
  1017. }
  1018. }
  1019. func TestNestedRepeatedElementNoIndex(t *testing.T) {
  1020. ctx := context.Background()
  1021. client := newTestClient(ctx, t)
  1022. defer client.Close()
  1023. type Inner struct {
  1024. Name string
  1025. Value string `datastore:",noindex"`
  1026. }
  1027. type Outer struct {
  1028. Config []Inner
  1029. }
  1030. m := &Outer{
  1031. Config: []Inner{
  1032. {Name: "short", Value: "a"},
  1033. {Name: "long", Value: strings.Repeat("a", 2000)},
  1034. },
  1035. }
  1036. key := NameKey("Nested", "Nested"+suffix, nil)
  1037. if _, err := client.Put(ctx, key, m); err != nil {
  1038. t.Fatalf("client.Put: %v", err)
  1039. }
  1040. if err := client.Delete(ctx, key); err != nil {
  1041. t.Fatalf("client.Delete: %v", err)
  1042. }
  1043. }
  1044. func TestPointerFields(t *testing.T) {
  1045. ctx := context.Background()
  1046. client := newTestClient(ctx, t)
  1047. defer client.Close()
  1048. want := populatedPointers()
  1049. key, err := client.Put(ctx, IncompleteKey("pointers", nil), want)
  1050. if err != nil {
  1051. t.Fatal(err)
  1052. }
  1053. var got Pointers
  1054. if err := client.Get(ctx, key, &got); err != nil {
  1055. t.Fatal(err)
  1056. }
  1057. if got.Pi == nil || *got.Pi != *want.Pi {
  1058. t.Errorf("Pi: got %v, want %v", got.Pi, *want.Pi)
  1059. }
  1060. if got.Ps == nil || *got.Ps != *want.Ps {
  1061. t.Errorf("Ps: got %v, want %v", got.Ps, *want.Ps)
  1062. }
  1063. if got.Pb == nil || *got.Pb != *want.Pb {
  1064. t.Errorf("Pb: got %v, want %v", got.Pb, *want.Pb)
  1065. }
  1066. if got.Pf == nil || *got.Pf != *want.Pf {
  1067. t.Errorf("Pf: got %v, want %v", got.Pf, *want.Pf)
  1068. }
  1069. if got.Pg == nil || *got.Pg != *want.Pg {
  1070. t.Errorf("Pg: got %v, want %v", got.Pg, *want.Pg)
  1071. }
  1072. if got.Pt == nil || !got.Pt.Equal(*want.Pt) {
  1073. t.Errorf("Pt: got %v, want %v", got.Pt, *want.Pt)
  1074. }
  1075. }
  1076. func TestMutate(t *testing.T) {
  1077. // test Client.Mutate
  1078. testMutate(t, func(ctx context.Context, client *Client, muts ...*Mutation) ([]*Key, error) {
  1079. return client.Mutate(ctx, muts...)
  1080. })
  1081. // test Transaction.Mutate
  1082. testMutate(t, func(ctx context.Context, client *Client, muts ...*Mutation) ([]*Key, error) {
  1083. var pkeys []*PendingKey
  1084. commit, err := client.RunInTransaction(ctx, func(tx *Transaction) error {
  1085. var err error
  1086. pkeys, err = tx.Mutate(muts...)
  1087. return err
  1088. })
  1089. if err != nil {
  1090. return nil, err
  1091. }
  1092. var keys []*Key
  1093. for _, pk := range pkeys {
  1094. keys = append(keys, commit.Key(pk))
  1095. }
  1096. return keys, nil
  1097. })
  1098. }
  1099. func testMutate(t *testing.T, mutate func(ctx context.Context, client *Client, muts ...*Mutation) ([]*Key, error)) {
  1100. ctx := context.Background()
  1101. client := newTestClient(ctx, t)
  1102. defer client.Close()
  1103. type T struct{ I int }
  1104. check := func(k *Key, want interface{}) {
  1105. var x T
  1106. err := client.Get(ctx, k, &x)
  1107. switch want := want.(type) {
  1108. case error:
  1109. if err != want {
  1110. t.Errorf("key %s: got error %v, want %v", k, err, want)
  1111. }
  1112. case int:
  1113. if err != nil {
  1114. t.Fatalf("key %s: %v", k, err)
  1115. }
  1116. if x.I != want {
  1117. t.Errorf("key %s: got %d, want %d", k, x.I, want)
  1118. }
  1119. default:
  1120. panic("check: bad arg")
  1121. }
  1122. }
  1123. keys, err := mutate(ctx, client,
  1124. NewInsert(IncompleteKey("t", nil), &T{1}),
  1125. NewUpsert(IncompleteKey("t", nil), &T{2}),
  1126. )
  1127. if err != nil {
  1128. t.Fatal(err)
  1129. }
  1130. check(keys[0], 1)
  1131. check(keys[1], 2)
  1132. _, err = mutate(ctx, client,
  1133. NewUpdate(keys[0], &T{3}),
  1134. NewDelete(keys[1]),
  1135. )
  1136. if err != nil {
  1137. t.Fatal(err)
  1138. }
  1139. check(keys[0], 3)
  1140. check(keys[1], ErrNoSuchEntity)
  1141. _, err = mutate(ctx, client, NewInsert(keys[0], &T{4}))
  1142. if got, want := status.Code(err), codes.AlreadyExists; got != want {
  1143. t.Errorf("Insert existing key: got %s, want %s", got, want)
  1144. }
  1145. _, err = mutate(ctx, client, NewUpdate(keys[1], &T{4}))
  1146. if got, want := status.Code(err), codes.NotFound; got != want {
  1147. t.Errorf("Update non-existing key: got %s, want %s", got, want)
  1148. }
  1149. }
  1150. func TestDetectProjectID(t *testing.T) {
  1151. if testing.Short() {
  1152. t.Skip("Integration tests skipped in short mode")
  1153. }
  1154. ctx := context.Background()
  1155. creds := testutil.Credentials(ctx, ScopeDatastore)
  1156. ts := fakets{}
  1157. if creds == nil {
  1158. t.Skip("Integration tests skipped. See CONTRIBUTING.md for details")
  1159. }
  1160. // Use creds with project ID.
  1161. if _, err := NewClient(ctx, DetectProjectID, option.WithCredentials(creds)); err != nil {
  1162. t.Errorf("NewClient: %v", err)
  1163. }
  1164. // Try to use creds without project ID.
  1165. _, err := NewClient(ctx, DetectProjectID, option.WithTokenSource(ts))
  1166. if err == nil && err.Error() != "datastore: see the docs on DetectProjectID" {
  1167. t.Errorf("expected an error while using TokenSource that does not have a project ID")
  1168. }
  1169. }
  1170. type fakets struct{}
  1171. func (f fakets) Token() (*oauth2.Token, error) {
  1172. return nil, errors.New("shouldn't see this")
  1173. }