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  }