| OLD | NEW |
| 1 // Copyright 2015 The Chromium Authors. All rights reserved. | 1 // Copyright 2015 The Chromium Authors. All rights reserved. |
| 2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 package memory | 5 package memory |
| 6 | 6 |
| 7 import ( | 7 import ( |
| 8 "fmt" | 8 "fmt" |
| 9 "testing" | 9 "testing" |
| 10 | 10 |
| (...skipping 283 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 294 So(txnDS.Get(f), ShouldBeNil) | 294 So(txnDS.Get(f), ShouldBeNil) |
| 295 So(f.Val, ShouldEqual, 10) | 295 So(f.Val, ShouldEqual, 10) |
| 296 | 296 |
| 297 f.Val = 20 | 297 f.Val = 20 |
| 298 So(txnDS.Put(f), ShouldBeNil) | 298 So(txnDS.Put(f), ShouldBeNil) |
| 299 | 299 |
| 300 So(txnDS.Get(f), ShouldBeNil) | 300 So(txnDS.Get(f), ShouldBeNil) |
| 301 So(f.Val, ShouldEqual, 10) // st
ill gets 10 | 301 So(f.Val, ShouldEqual, 10) // st
ill gets 10 |
| 302 | 302 |
| 303 return nil | 303 return nil |
| 304 » » » » » }, nil) | 304 » » » » » }, &dsS.TransactionOptions{Attempts: 1}) |
| 305 So(err.Error(), ShouldContainSubstring,
"concurrent") | 305 So(err.Error(), ShouldContainSubstring,
"concurrent") |
| 306 | 306 |
| 307 f := &Foo{Id: 1} | 307 f := &Foo{Id: 1} |
| 308 So(ds.Get(f), ShouldBeNil) | 308 So(ds.Get(f), ShouldBeNil) |
| 309 So(f.Val, ShouldEqual, 11) | 309 So(f.Val, ShouldEqual, 11) |
| 310 }) | 310 }) |
| 311 | 311 |
| 312 Convey("Reusing a transaction context is bad new
s", func() { | 312 Convey("Reusing a transaction context is bad new
s", func() { |
| 313 txnDS := dsS.Interface(nil) | 313 txnDS := dsS.Interface(nil) |
| 314 err := ds.RunInTransaction(func(c contex
t.Context) error { | 314 err := ds.RunInTransaction(func(c contex
t.Context) error { |
| (...skipping 11 matching lines...) Expand all Loading... |
| 326 panic("noooo") | 326 panic("noooo") |
| 327 }, nil) | 327 }, nil) |
| 328 So(err.Error(), ShouldContainSub
string, "nested transactions") | 328 So(err.Error(), ShouldContainSub
string, "nested transactions") |
| 329 return nil | 329 return nil |
| 330 }, nil) | 330 }, nil) |
| 331 So(err, ShouldBeNil) | 331 So(err, ShouldBeNil) |
| 332 }) | 332 }) |
| 333 | 333 |
| 334 Convey("Concurrent transactions only accept one
set of changes", func() { | 334 Convey("Concurrent transactions only accept one
set of changes", func() { |
| 335 // Note: I think this implementation is
actually /slightly/ wrong. | 335 // Note: I think this implementation is
actually /slightly/ wrong. |
| 336 » » » » » // Accorting to my read of the docs for
appengine, when you open a | 336 » » » » » // According to my read of the docs for
appengine, when you open a |
| 337 // transaction it actually (essentially)
holds a reference to the | 337 // transaction it actually (essentially)
holds a reference to the |
| 338 // entire datastore. Our implementation
takes a snapshot of the | 338 // entire datastore. Our implementation
takes a snapshot of the |
| 339 // entity group as soon as something obs
erves/affects it. | 339 // entity group as soon as something obs
erves/affects it. |
| 340 // | 340 // |
| 341 // That said... I'm not sure if there's
really a semantic difference. | 341 // That said... I'm not sure if there's
really a semantic difference. |
| 342 err := ds.RunInTransaction(func(c contex
t.Context) error { | 342 err := ds.RunInTransaction(func(c contex
t.Context) error { |
| 343 So(dsS.Get(c).Put(&Foo{Id: 1, Va
l: 21}), ShouldBeNil) | 343 So(dsS.Get(c).Put(&Foo{Id: 1, Va
l: 21}), ShouldBeNil) |
| 344 | 344 |
| 345 err := ds.RunInTransaction(func(
c context.Context) error { | 345 err := ds.RunInTransaction(func(
c context.Context) error { |
| 346 So(dsS.Get(c).Put(&Foo{I
d: 1, Val: 27}), ShouldBeNil) | 346 So(dsS.Get(c).Put(&Foo{I
d: 1, Val: 27}), ShouldBeNil) |
| (...skipping 63 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 410 So(ds.Put(&Foo{V
al: 200}), ShouldBeNil) | 410 So(ds.Put(&Foo{V
al: 200}), ShouldBeNil) |
| 411 panic("wheeeeee"
) | 411 panic("wheeeeee"
) |
| 412 }, nil) | 412 }, nil) |
| 413 }, ShouldPanic) | 413 }, ShouldPanic) |
| 414 | 414 |
| 415 f := &Foo{Id: 1} | 415 f := &Foo{Id: 1} |
| 416 So(ds.Get(f), ShouldBeNil) | 416 So(ds.Get(f), ShouldBeNil) |
| 417 So(f.Val, ShouldEqual, 10) | 417 So(f.Val, ShouldEqual, 10) |
| 418 }) | 418 }) |
| 419 }) | 419 }) |
| 420 |
| 421 Convey("Transaction retries", func() { |
| 422 tst := ds.Raw().Testable() |
| 423 Reset(func() { tst.SetTransactionRetryCo
unt(0) }) |
| 424 |
| 425 Convey("SetTransactionRetryCount set to
zere", func() { |
| 426 tst.SetTransactionRetryCount(0) |
| 427 calls := 0 |
| 428 So(ds.RunInTransaction(func(c co
ntext.Context) error { |
| 429 calls++ |
| 430 return nil |
| 431 }, nil), ShouldBeNil) |
| 432 So(calls, ShouldEqual, 1) |
| 433 }) |
| 434 |
| 435 Convey("default TransactionOptions is 3
attempts", func() { |
| 436 tst.SetTransactionRetryCount(100
) // more than 3 |
| 437 calls := 0 |
| 438 So(ds.RunInTransaction(func(c co
ntext.Context) error { |
| 439 calls++ |
| 440 return nil |
| 441 }, nil), ShouldEqual, dsS.ErrCon
currentTransaction) |
| 442 So(calls, ShouldEqual, 3) |
| 443 }) |
| 444 |
| 445 Convey("non-default TransactionOptions "
, func() { |
| 446 tst.SetTransactionRetryCount(100
) // more than 20 |
| 447 calls := 0 |
| 448 So(ds.RunInTransaction(func(c co
ntext.Context) error { |
| 449 calls++ |
| 450 return nil |
| 451 }, &dsS.TransactionOptions{Attem
pts: 20}), ShouldEqual, dsS.ErrConcurrentTransaction) |
| 452 So(calls, ShouldEqual, 20) |
| 453 }) |
| 454 |
| 455 Convey("SetTransactionRetryCount is resp
ected", func() { |
| 456 tst.SetTransactionRetryCount(1)
// less than 3 |
| 457 calls := 0 |
| 458 So(ds.RunInTransaction(func(c co
ntext.Context) error { |
| 459 calls++ |
| 460 return nil |
| 461 }, nil), ShouldBeNil) |
| 462 So(calls, ShouldEqual, 2) |
| 463 }) |
| 464 |
| 465 Convey("fatal errors are not retried", f
unc() { |
| 466 tst.SetTransactionRetryCount(1) |
| 467 calls := 0 |
| 468 So(ds.RunInTransaction(func(c co
ntext.Context) error { |
| 469 calls++ |
| 470 return fmt.Errorf("omg") |
| 471 }, nil).Error(), ShouldEqual, "o
mg") |
| 472 So(calls, ShouldEqual, 1) |
| 473 }) |
| 474 }) |
| 420 }) | 475 }) |
| 421 }) | 476 }) |
| 422 | |
| 423 }) | 477 }) |
| 424 } | 478 } |
| 425 | 479 |
| 426 func TestCompoundIndexes(t *testing.T) { | 480 func TestCompoundIndexes(t *testing.T) { |
| 427 t.Parallel() | 481 t.Parallel() |
| 428 | 482 |
| 429 idxKey := func(def dsS.IndexDefinition) string { | 483 idxKey := func(def dsS.IndexDefinition) string { |
| 430 So(def, ShouldNotBeNil) | 484 So(def, ShouldNotBeNil) |
| 431 return "idx::" + string(serialize.ToBytes(*def.PrepForIdxTable()
)) | 485 return "idx::" + string(serialize.ToBytes(*def.PrepForIdxTable()
)) |
| 432 } | 486 } |
| (...skipping 36 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 469 | 523 |
| 470 idx.SortBy = append(idx.SortBy, dsS.IndexColumn{Property: "Field
1"}) | 524 idx.SortBy = append(idx.SortBy, dsS.IndexColumn{Property: "Field
1"}) |
| 471 So(head.GetCollection(idxKey(idx)), ShouldBeNil) | 525 So(head.GetCollection(idxKey(idx)), ShouldBeNil) |
| 472 | 526 |
| 473 t.AddIndexes(&idx) | 527 t.AddIndexes(&idx) |
| 474 coll = head.GetCollection(idxKey(idx)) | 528 coll = head.GetCollection(idxKey(idx)) |
| 475 So(coll, ShouldNotBeNil) | 529 So(coll, ShouldNotBeNil) |
| 476 So(numItms(coll), ShouldEqual, 4) | 530 So(numItms(coll), ShouldEqual, 4) |
| 477 }) | 531 }) |
| 478 } | 532 } |
| OLD | NEW |