~nskaggs/+junk/xenial-test

« back to all changes in this revision

Viewing changes to src/github.com/juju/txn/testing/testing.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 Canonical Ltd.
 
2
// Licensed under the LGPLv3, see LICENCE file for details.
 
3
 
 
4
package testing
 
5
 
 
6
import (
 
7
        gc "gopkg.in/check.v1"
 
8
 
 
9
        "github.com/juju/txn"
 
10
)
 
11
 
 
12
// TransactionChecker values are returned from the various Set*Hooks calls,
 
13
// and should be run after the code under test has been executed to check
 
14
// that the expected number of transactions were run.
 
15
type TransactionChecker func()
 
16
 
 
17
func (c TransactionChecker) Check() {
 
18
        c()
 
19
}
 
20
 
 
21
// SetBeforeHooks uses Settxn.TestHooks to queue N functions to be run
 
22
// immediately before the next N transactions. The first function is executed
 
23
// before the first transaction, the second function before the second
 
24
// transaction and so on. Nil values are accepted, and useful, in that they can
 
25
// be used to ensure that a transaction is run at the expected time, without
 
26
// having to make any changes or assert any state.
 
27
func SetBeforeHooks(c *gc.C, runner txn.Runner, fs ...func()) TransactionChecker {
 
28
        transactionHooks := make([]txn.TestHook, len(fs))
 
29
        for i, f := range fs {
 
30
                transactionHooks[i] = txn.TestHook{Before: f}
 
31
        }
 
32
        return SetTestHooks(c, runner, transactionHooks...)
 
33
}
 
34
 
 
35
// SetAfterHooks uses Settxn.TestHooks to queue N functions to be run
 
36
// immediately after the next N transactions. The first function is executed
 
37
// after the first transaction, the second function after the second
 
38
// transaction and so on.
 
39
func SetAfterHooks(c *gc.C, runner txn.Runner, fs ...func()) TransactionChecker {
 
40
        transactionHooks := make([]txn.TestHook, len(fs))
 
41
        for i, f := range fs {
 
42
                transactionHooks[i] = txn.TestHook{After: f}
 
43
        }
 
44
        return SetTestHooks(c, runner, transactionHooks...)
 
45
}
 
46
 
 
47
// SetRetryHooks uses txn.TestHooks to inject a block function designed
 
48
// to disrupt a transaction built against recent state, and a check function
 
49
// designed to verify that the replacement transaction against the new state
 
50
// has been applied as expected.
 
51
func SetRetryHooks(c *gc.C, runner txn.Runner, block, check func()) TransactionChecker {
 
52
        return SetTestHooks(c, runner, txn.TestHook{
 
53
                Before: block,
 
54
        }, txn.TestHook{
 
55
                After: check,
 
56
        })
 
57
}
 
58
 
 
59
// SetTestHooks queues up hooks to be applied to the next transactions,
 
60
// and returns a function that asserts all hooks have been run (and removes any
 
61
// that have not). Each hook function can freely execute its own transactions
 
62
// without causing other hooks to be triggered.
 
63
// It returns a function that asserts that all hooks have been run, and removes
 
64
// any that have not. It is an error to set transaction hooks when any are
 
65
// already queued; and setting transaction hooks renders the *State goroutine-
 
66
// unsafe.
 
67
func SetTestHooks(c *gc.C, runner txn.Runner, hooks ...txn.TestHook) TransactionChecker {
 
68
        transactionHooks := txn.TestHooks(runner)
 
69
        original := <-transactionHooks
 
70
        transactionHooks <- hooks
 
71
        c.Assert(original, gc.HasLen, 0)
 
72
        return func() {
 
73
                remaining := <-transactionHooks
 
74
                transactionHooks <- nil
 
75
                c.Assert(remaining, gc.HasLen, 0)
 
76
        }
 
77
}