github.com/axw/juju@v0.0.0-20161005053422-4bd6544d08d4/worker/lease/util_test.go (about) 1 // Copyright 2015 Canonical Ltd. 2 // Licensed under the AGPLv3, see LICENCE file for details. 3 4 package lease_test 5 6 import ( 7 "fmt" 8 "time" 9 10 "github.com/juju/errors" 11 jc "github.com/juju/testing/checkers" 12 gc "gopkg.in/check.v1" 13 14 "github.com/juju/juju/core/lease" 15 ) 16 17 // Secretary implements lease.Secretary for testing purposes. 18 type Secretary struct{} 19 20 // CheckLease is part of the lease.Secretary interface. 21 func (Secretary) CheckLease(name string) error { 22 return checkName(name) 23 } 24 25 // CheckHolder is part of the lease.Secretary interface. 26 func (Secretary) CheckHolder(name string) error { 27 return checkName(name) 28 } 29 30 func checkName(name string) error { 31 if name == "INVALID" { 32 return errors.NotValidf("name") 33 } 34 return nil 35 } 36 37 // CheckDuration is part of the lease.Secretary interface. 38 func (Secretary) CheckDuration(duration time.Duration) error { 39 if duration != time.Minute { 40 return errors.NotValidf("time") 41 } 42 return nil 43 } 44 45 // Client implements corelease.Client for testing purposes. 46 type Client struct { 47 leases map[string]lease.Info 48 expect []call 49 failed string 50 done chan struct{} 51 } 52 53 // NewClient initializes and returns a new client configured to report 54 // the supplied leases and expect the supplied calls. 55 func NewClient(leases map[string]lease.Info, expect []call) *Client { 56 if leases == nil { 57 leases = make(map[string]lease.Info) 58 } 59 done := make(chan struct{}) 60 if len(expect) == 0 { 61 close(done) 62 } 63 return &Client{ 64 leases: leases, 65 expect: expect, 66 done: done, 67 } 68 } 69 70 // Wait will return when all expected calls have been made, or fail the test 71 // if they don't happen within a second. (You control the clock; your tests 72 // should pass in *way* less than a second of wall-clock time.) 73 func (client *Client) Wait(c *gc.C) { 74 select { 75 case <-client.done: 76 if client.failed != "" { 77 c.Fatalf(client.failed) 78 } 79 case <-time.After(time.Second): 80 c.Fatalf("Client test took way too long") 81 } 82 } 83 84 // Leases is part of the lease.Client interface. 85 func (client *Client) Leases() map[string]lease.Info { 86 result := make(map[string]lease.Info) 87 for k, v := range client.leases { 88 result[k] = v 89 } 90 return result 91 } 92 93 // call implements the bulk of the lease.Client interface. 94 func (client *Client) call(method string, args []interface{}) error { 95 select { 96 case <-client.done: 97 return errors.Errorf("Client method called after test complete: %s %v", method, args) 98 default: 99 defer func() { 100 if len(client.expect) == 0 || client.failed != "" { 101 close(client.done) 102 } 103 }() 104 } 105 106 expect := client.expect[0] 107 client.expect = client.expect[1:] 108 if expect.callback != nil { 109 expect.callback(client.leases) 110 } 111 112 if method == expect.method { 113 if ok, _ := jc.DeepEqual(args, expect.args); ok { 114 return expect.err 115 } 116 } 117 client.failed = fmt.Sprintf("unexpected Client call:\n actual: %s %v\n expect: %s %v", 118 method, args, expect.method, expect.args, 119 ) 120 return errors.New(client.failed) 121 } 122 123 // ClaimLease is part of the corelease.Client interface. 124 func (client *Client) ClaimLease(name string, request lease.Request) error { 125 return client.call("ClaimLease", []interface{}{name, request}) 126 } 127 128 // ExtendLease is part of the corelease.Client interface. 129 func (client *Client) ExtendLease(name string, request lease.Request) error { 130 return client.call("ExtendLease", []interface{}{name, request}) 131 } 132 133 // ExpireLease is part of the corelease.Client interface. 134 func (client *Client) ExpireLease(name string) error { 135 return client.call("ExpireLease", []interface{}{name}) 136 } 137 138 // Refresh is part of the lease.Client interface. 139 func (client *Client) Refresh() error { 140 return client.call("Refresh", nil) 141 } 142 143 // call defines a expected method call on a Client; it encodes: 144 type call struct { 145 146 // method is the name of the method. 147 method string 148 149 // args is the expected arguments. 150 args []interface{} 151 152 // err is the error to return. 153 err error 154 155 // callback, if non-nil, will be passed the internal leases dict; for 156 // modification, if desired. Otherwise you can use it to, e.g., assert 157 // clock time. 158 callback func(leases map[string]lease.Info) 159 }