kvtests

package
v0.0.0-...-c2b9891 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Mar 23, 2024 License: MIT Imports: 12 Imported by: 0

Documentation

Index

Constants

This section is empty.

Variables

View Source
var BasicOpsTemplateMap = map[string]string{
	"GetSetDelete": `
  db:db1  new-transaction       => tx:tx1

  tx:tx1  delete key:0          => error:nil|ErrNotExist

  tx:tx1  get key:0             => error:ErrNotExist
  tx:tx1  set key:0 value:zero
  tx:tx1  get key:0             => value:zero

  tx:tx1  delete key:0
  tx:tx1  get key:0             => error:ErrNotExist

  tx:tx1  commit
`,

	"ScanKeys": `
  db:db1  new-transaction       => tx:tx1
  tx:tx1  set key:0 value:zero
  tx:tx1  set key:1 value:one
  tx:tx1  set key:2 value:two

  tx:tx1  scan                  => it:it1
  it:it1  fetch next:false
  it:it1  fetch next:true
  it:it1  fetch next:true
  it:it1  fetch next:true       => error:EOF
  tx:tx1  rollback
`,

	"AscendDescendScanEmpty": `
  db:db1  new-transaction       => tx:tx1

  tx:tx1  ascend begin: end:    => it:it1
  it:it1  fetch next:true       => key: value: error:EOF
  it:it1  fetch next:false      => key: value: error:EOF
  it:it1  fetch next:true       => key: value: error:EOF

  tx:tx1  descend begin: end:   => it:it2
  it:it2  fetch next:true       => key: value: error:EOF
  it:it2  fetch next:false      => key: value: error:EOF
  it:it2  fetch next:true       => key: value: error:EOF

  tx:tx1  scan                  => it:it3
  it:it3  fetch next:true       => key: value: error:EOF
  it:it3  fetch next:false      => key: value: error:EOF
  it:it3  fetch next:true       => key: value: error:EOF

  tx:tx1  commit
`,

	"AscendDescendInvalid": `
  db:db1  new-transaction       => tx:tx1

  tx:tx1  set key:0 value:zero
  tx:tx1  set key:1 value:one
  tx:tx1  set key:2 value:two

  tx:tx1  ascend begin:2 end:1    => error:ErrInvalid
  tx:tx1  descend begin:2 end:1   => error:ErrInvalid

  tx:tx1  ascend begin:2 end:0    => error:ErrInvalid
  tx:tx1  descend begin:2 end:0   => error:ErrInvalid

  tx:tx1  ascend begin:1 end:0    => error:ErrInvalid
  tx:tx1  descend begin:1 end:0   => error:ErrInvalid

  tx:tx1  rollback
`,

	"AscendEmpty": `
  db:db1  new-transaction       => tx:tx1

  tx:tx1  set key:0 value:zero
  tx:tx1  set key:1 value:one
  tx:tx1  set key:2 value:two

  tx:tx1  ascend begin:0 end:0  => it:it1
  it:it1  fetch next:true       => key: value: error:EOF
  it:it1  fetch next:false      => key: value: error:EOF

  tx:tx1  ascend begin:1 end:1  => it:it2
  it:it2  fetch next:false      => key: value: error:EOF
  it:it2  fetch next:true       => key: value: error:EOF

  tx:tx1  ascend begin:2 end:2  => it:it3
  it:it3  fetch next:true       => key: value: error:EOF
  it:it3  fetch next:true       => key: value: error:EOF

  tx:tx1  rollback
`,

	"DescendEmpty": `
  db:db1  new-transaction         => tx:tx1

  tx:tx1  set key:0 value:zero
  tx:tx1  set key:1 value:one
  tx:tx1  set key:2 value:two

  tx:tx1  descend begin:0 end:0  => it:it1
  it:it1  fetch next:false       => key: value: error:EOF
  it:it1  fetch next:true        => key: value: error:EOF

  tx:tx1  descend begin:1 end:1  => it:it2
  it:it2  fetch next:false       => key: value: error:EOF
  it:it2  fetch next:true        => key: value: error:EOF

  tx:tx1  descend begin:2 end:2  => it:it3
  it:it3  fetch next:false       => key: value: error:EOF
  it:it3  fetch next:true        => key: value: error:EOF

  tx:tx1  rollback
`,

	"AscendNonEmptyRange": `
  db:db1  new-transaction         => tx:tx1

  tx:tx1  set key:0 value:zero
  tx:tx1  set key:1 value:one
  tx:tx1  set key:2 value:two
  tx:tx1  set key:3 value:three
  tx:tx1  set key:4 value:four

  tx:tx1  ascend begin:0 end:5  => it:it1
  it:it1  fetch next:false      => key:0 value:zero
  it:it1  fetch next:true       => key:1 value:one
  it:it1  fetch next:true       => key:2 value:two
  it:it1  fetch next:true       => key:3 value:three
  it:it1  fetch next:true       => key:4 value:four
  it:it1  fetch next:true       => key: value: error:EOF
  it:it1  fetch next:false      => key: value: error:EOF

  tx:tx1  ascend begin:0 end:4  => it:it2
  it:it2  fetch next:false      => key:0 value:zero
  it:it2  fetch next:true       => key:1 value:one
  it:it2  fetch next:true       => key:2 value:two
  it:it2  fetch next:true       => key:3 value:three
  it:it2  fetch next:true       => key: value: error:EOF
  it:it2  fetch next:false      => key: value: error:EOF

  tx:tx1  ascend begin:0 end:1  => it:it3
  it:it3  fetch next:false      => key:0 value:zero
  it:it3  fetch next:true       => key: value: error:EOF

  tx:tx1  ascend begin:1 end:2  => it:it4
  it:it4  fetch next:false      => key:1 value:one
  it:it4  fetch next:true       => key: value: error:EOF

  tx:tx1  ascend begin:2 end:25  => it:it5
  it:it5  fetch next:false       => key:2 value:two
  it:it5  fetch next:true        => key: value: error:EOF

  tx:tx1  ascend begin:25 end:35  => it:it6
  it:it6  fetch next:false        => key:3 value:three
  it:it6  fetch next:true         => key: value: error:EOF

  tx:tx1  rollback
`,

	"DescendNonEmptyRange": `
  db:db1  new-transaction         => tx:tx1

  tx:tx1  set key:0 value:zero
  tx:tx1  set key:1 value:one
  tx:tx1  set key:2 value:two
  tx:tx1  set key:3 value:three
  tx:tx1  set key:4 value:four

  tx:tx1  descend begin:0 end:5  => it:it1
  it:it1  fetch next:false       => key:4 value:four
  it:it1  fetch next:true        => key:3 value:three
  it:it1  fetch next:true        => key:2 value:two
  it:it1  fetch next:true        => key:1 value:one
  it:it1  fetch next:true        => key:0 value:zero
  it:it1  fetch next:true        => key: value: error:EOF
  it:it1  fetch next:false       => key: value: error:EOF

  tx:tx1  descend begin:0 end:4  => it:it2
  it:it2  fetch next:false       => key:3 value:three
  it:it2  fetch next:true        => key:2 value:two
  it:it2  fetch next:true        => key:1 value:one
  it:it2  fetch next:true        => key:0 value:zero
  it:it2  fetch next:true        => key: value: error:EOF

  tx:tx1  descend begin:0 end:1  => it:it3
  it:it3  fetch next:false       => key:0 value:zero
  it:it3  fetch next:true        => key: value: error:EOF

  tx:tx1  descend begin:1 end:2  => it:it4
  it:it4  fetch next:false       => key:1 value:one
  it:it4  fetch next:true        => key: value: error:EOF

  tx:tx1  descend begin:2 end:25  => it:it5
  it:it5  fetch next:false        => key:2 value:two
  it:it5  fetch next:true         => key: value: error:EOF

  tx:tx1  descend begin:25 end:35  => it:it6
  it:it6  fetch next:false         => key:3 value:three
  it:it6  fetch next:true          => key: value: error:EOF

  tx:tx1  rollback
`,

	"AscendOneEmptyRange": `
  db:db1  new-transaction         => tx:tx1

  tx:tx1  set key:0 value:zero
  tx:tx1  set key:1 value:one
  tx:tx1  set key:2 value:two
  tx:tx1  set key:3 value:three
  tx:tx1  set key:4 value:four

  tx:tx1  ascend begin: end:5     => it:it1
  it:it1  fetch next:false        => key:0 value:zero
  it:it1  fetch next:true         => key:1 value:one
  it:it1  fetch next:true         => key:2 value:two
  it:it1  fetch next:true         => key:3 value:three
  it:it1  fetch next:true         => key:4 value:four
  it:it1  fetch next:true         => key: value: error:EOF

  tx:tx1  ascend begin: end:4     => it:it2
  it:it2  fetch next:false        => key:0 value:zero
  it:it2  fetch next:true         => key:1 value:one
  it:it2  fetch next:true         => key:2 value:two
  it:it2  fetch next:true         => key:3 value:three
  it:it2  fetch next:true         => key: value: error:EOF

  tx:tx1  ascend begin: end:2     => it:it3
  it:it3  fetch next:false        => key:0 value:zero
  it:it3  fetch next:true         => key:1 value:one
  it:it3  fetch next:true         => key: value: error:EOF

  tx:tx1  ascend begin:0 end:     => it:it4
  it:it4  fetch next:false        => key:0 value:zero
  it:it4  fetch next:true         => key:1 value:one
  it:it4  fetch next:true         => key:2 value:two
  it:it4  fetch next:true         => key:3 value:three
  it:it4  fetch next:true         => key:4 value:four
  it:it4  fetch next:true         => key: value: error:EOF

  tx:tx1  ascend begin:2 end:     => it:it4
  it:it4  fetch next:false        => key:2 value:two
  it:it4  fetch next:true         => key:3 value:three
  it:it4  fetch next:true         => key:4 value:four
  it:it4  fetch next:true         => key: value: error:EOF

  tx:tx1  rollback
`,

	"DescendOneEmptyRange": `
  db:db1  new-transaction         => tx:tx1

  tx:tx1  set key:0 value:zero
  tx:tx1  set key:1 value:one
  tx:tx1  set key:2 value:two
  tx:tx1  set key:3 value:three
  tx:tx1  set key:4 value:four

  tx:tx1  descend begin: end:5     => it:it1
  it:it1  fetch next:false         => key:4 value:four
  it:it1  fetch next:true          => key:3 value:three
  it:it1  fetch next:true          => key:2 value:two
  it:it1  fetch next:true          => key:1 value:one
  it:it1  fetch next:true          => key:0 value:zero
  it:it1  fetch next:true          => key: value: error:EOF

  tx:tx1  descend begin: end:4     => it:it2
  it:it2  fetch next:false         => key:3 value:three
  it:it2  fetch next:true          => key:2 value:two
  it:it2  fetch next:true          => key:1 value:one
  it:it2  fetch next:true          => key:0 value:zero
  it:it2  fetch next:true          => key: value: error:EOF

  tx:tx1  descend begin: end:2     => it:it3
  it:it3  fetch next:false         => key:1 value:one
  it:it3  fetch next:true          => key:0 value:zero
  it:it3  fetch next:true          => key: value: error:EOF

  tx:tx1  descend begin:0 end:     => it:it4
  it:it4  fetch next:false         => key:4 value:four
  it:it4  fetch next:true          => key:3 value:three
  it:it4  fetch next:true          => key:2 value:two
  it:it4  fetch next:true          => key:1 value:one
  it:it4  fetch next:true          => key:0 value:zero
  it:it4  fetch next:true          => key: value: error:EOF

  tx:tx1  descend begin:2 end:     => it:it4
  it:it4  fetch next:false         => key:4 value:four
  it:it4  fetch next:true          => key:3 value:three
  it:it4  fetch next:true          => key:2 value:two
  it:it4  fetch next:true          => key: value: error:EOF

  tx:tx1  rollback
`,
}
View Source
var TxOpsTemplateMap = map[string]string{
	"SerializedTxCommits": `
  db:db1  new-transaction                => tx:tx1
  tx:tx1  set key:0 value:zero
  tx:tx1  commit

  db:db1  new-transaction                => tx:tx2
  tx:tx2  get key:0                      => value:zero
  tx:tx2  set key:0 value:ZERO
  tx:tx2  commit

  db:db1  new-transaction                => tx:tx3
  tx:tx3  get key:0                      => value:ZERO
  tx:tx3  delete key:0
  tx:tx3  commit

  db:db1  new-transaction                => tx:tx4
  tx:tx4  get key:0                      => error:ErrNotExist
  tx:tx4  commit
`,

	"SerializedTxCommitsAndRollbacks": `
  db:db1  new-transaction                => tx:tx1
  tx:tx1  set key:0 value:zero
  tx:tx1  commit

  db:db1  new-transaction                => tx:tx2
  tx:tx2  get key:0                      => value:zero
  tx:tx2  set key:0 value:ZERO
  tx:tx2  rollback

  db:db1  new-transaction                => tx:tx3
  tx:tx3  get key:0                      => value:zero
  tx:tx3  delete key:0
  tx:tx3  rollback

  db:db1  new-transaction                => tx:tx4
  tx:tx4  get key:0                      => value:zero
  tx:tx4  delete key:0
  tx:tx4  commit

  db:db1  new-transaction                => tx:tx5
  tx:tx5  get key:0                      => error:ErrNotExist
  tx:tx5  set key:0 value:ZERO
  tx:tx5  commit

  db:db1  new-transaction                => tx:tx6
  tx:tx6  get key:0                      => value:ZERO
  tx:tx6  commit
`,

	"NonConflictingTxes": `
  db:db1  new-transaction               => tx:tx1
  db:db1  new-transaction               => tx:tx2
  db:db1  new-transaction               => tx:tx3

  tx:tx1  set key:1 value:one
  tx:tx2  set key:2 value:two
  tx:tx3  set key:3 value:three

  tx:tx1  commit
  tx:tx2  commit
  tx:tx3  commit
`,

	"ConflictingReadOnlyTxes": `
  db:db1  new-transaction               => tx:init
  tx:init set key:0 value:zero
  tx:init commit

  db:db1  new-transaction               => tx:tx1
  db:db1  new-transaction               => tx:tx2
  db:db1  new-transaction               => tx:tx3

  tx:tx1  get key:0                     => value:zero
  tx:tx2  get key:0                     => value:zero
  tx:tx3  get key:0                     => value:zero

  tx:tx1  commit
  tx:tx2  commit
  tx:tx3  commit
`,

	"SerializableConflictingReadWriteTxes": `
  db:db1  new-transaction               => tx:init
  tx:init set key:0 value:zero
  tx:init commit

  db:db1  new-transaction               => tx:tx1
  db:db1  new-transaction               => tx:tx2

  tx:tx1  set key:0 value:ZERO
  tx:tx2  get key:0                     => value:zero

  tx:tx1  commit
  tx:tx2  commit                        => error:nil|non-nil
`,

	"SerializableConflictingDeletes": `
  db:db1  new-transaction               => tx:init
  tx:init set key:0 value:zero
  tx:init commit

  db:db1  new-transaction               => tx:tx1
  db:db1  new-transaction               => tx:tx2

  tx:tx1  delete key:0
  tx:tx1  set key:1 value:one

  tx:tx2  delete key:0
  tx:tx2  set key:2 value:two

  tx:tx1  commit
  tx:tx2  commit                        => error:nil|non-nil
`,

	"NonConflictingDeletes": `
  db:db1  new-transaction               => tx:init
  tx:init set key:1 value:one
  tx:init set key:2 value:two
  tx:init commit

  db:db1  new-transaction               => tx:tx1
  db:db1  new-transaction               => tx:tx2

  tx:tx1  delete key:1
  tx:tx2  delete key:2

  tx:tx1  commit
  tx:tx2  commit
`,

	"AbortedReads": `
  db:db1  new-transaction               => tx:init
  tx:init set key:key value:value
  tx:init commit

  db:db1  new-transaction               => tx:tx1
  tx:tx1  set key:key value:VALUE
  tx:tx1  rollback

  db:db1  new-transaction               => tx:tx2
  tx:tx2  get key:key                   => value:value
  tx:tx2  commit
`,

	"RepeatedReads": `
  db:db1  new-transaction               => tx:init
  tx:init set key:key value:value
  tx:init commit

  db:db1  new-transaction               => tx:tx1
  db:db1  new-transaction               => tx:tx2

  tx:tx1  set key:key value:VALUE
  tx:tx1  commit

  tx:tx2  get key:key                   => value:value
  tx:tx2  commit                        => error:nil|non-nil

  db:db1  new-transaction               => tx:tx3
  tx:tx3  get key:key                   => value:VALUE
  tx:tx3  commit
`,

	"WriteSkewAnamoly": `
  db:db1  new-transaction               => tx:init
  tx:init set key:account1 value:100
  tx:init set key:account2 value:100
  tx:init commit

  # Invariant: Balances of account1 and account2 can go -ve, but their sum must
  # never go below -$100.

  db:db1  new-transaction               => tx:tx1
  db:db1  new-transaction               => tx:tx2

  # tx1 checks that sum is $200, so withdraws $200 from "account1" thinking
  # remaining balance is still above -$100. tx2 does the same, but withdraws
  # $200 from "account2" instead.

  tx:tx1  get key:account1              => value:100
  tx:tx1  get key:account2              => value:100
  tx:tx1  set key:account1 value:-100
  tx:tx1  commit

  tx:tx2  get key:account1              => value:100
  tx:tx2  get key:account2              => value:100
  tx:tx2  set key:account2 value:-100
  tx:tx2  commit                        => error:non-nil
`,
}

Functions

func Clear

func Clear(ctx context.Context, db kv.Database) error

ClearDatabase deletes all key-value pairs in the database.

func RunBasicOps

func RunBasicOps(ctx context.Context, db kv.Database) error

func RunTemplate

func RunTemplate(ctx context.Context, template string, db ...kv.Database) error

func RunTxOps

func RunTxOps(ctx context.Context, db kv.Database) error

Types

type BankTest

type BankTest struct {
	DB kv.Database

	// InitializeDB when true clears the database and initializes it with random
	// accounts.
	InitializeDB bool
	// contains filtered or unexported fields
}

BankTest uses multiple goroutines to perform transactions simultaneously while verifying that expected invariant holds true at every snapshot. This test runs till input context is canceled or verification check has failed.

Multiple goroutines randomly transfer amounts between the accounts in parallel. The goroutine that is running the tests will take repeated snapshots of the database and verifies that sum of balances across all accounts doesn't change over time.

func (*BankTest) FindTotalBalance

func (b *BankTest) FindTotalBalance(ctx context.Context) (int64, error)

func (*BankTest) Run

func (b *BankTest) Run(ctx context.Context, nclients int) error

Run executes the test with nclient goroutines performing database transactions simultaneously.

func (*BankTest) TotalBalance

func (b *BankTest) TotalBalance() int64

Directories

Path Synopsis

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL