github.com/rohankumardubey/proxyfs@v0.0.0-20210108201508-653efa9ab00e/jrpcfs/lease_test.go (about)

     1  package jrpcfs
     2  
     3  import (
     4  	"encoding/json"
     5  	"fmt"
     6  	"os"
     7  	"runtime"
     8  	"strings"
     9  	"sync"
    10  	"testing"
    11  	"time"
    12  
    13  	"github.com/swiftstack/ProxyFS/retryrpc"
    14  )
    15  
    16  const (
    17  	testRpcLeaseDelayAfterSendingRequest        = 10 * time.Millisecond
    18  	testRpcLeaseDelayBeforeSendingRequest       = 10 * time.Millisecond
    19  	testRpcLeaseRetryRPCDeadlineIO              = "60s"
    20  	testRpcLeaseRetryRPCKeepAlivePeriod         = "60s"
    21  	testRpcLeaseMultiFirstInodeNumber     int64 = 1
    22  	testRpcLeaseMultiNumInstances         int   = 5
    23  	testRpcLeaseSingleInodeNumber         int64 = 1
    24  	testRpcLeaseSingleNumInstances        int   = 100 // Must be >= 4
    25  	testRpcLeaseTimeFormatASDF                  = time.StampMilli
    26  	testRpcLeaseTimeFormat                      = "15:04:05.000"
    27  )
    28  
    29  var (
    30  	testRpcLeaseRequestLetters   = [5]string{"S", "P", "E", "D", "R"}
    31  	testRpcLeaseReplyLetters     = [6]string{"D", "S", "P", "E", "D", "R"}
    32  	testRpcLeaseInterruptLetters = [3]string{"U", "D", "R"}
    33  	testRpcLeaseLogVerbosely     bool
    34  )
    35  
    36  type testRpcLeaseClientStruct struct {
    37  	instance    int
    38  	inodeNumber int64
    39  	chIn        chan LeaseRequestType // close it to terminate testRpcLeaseClient instance
    40  	chOut       chan interface{}      // either a LeaseReplyType or an RPCInterruptType
    41  	wg          *sync.WaitGroup       // signaled when testRpcLeaseClient instance exits
    42  	t           *testing.T
    43  }
    44  
    45  func TestRpcLease(t *testing.T) {
    46  	var (
    47  		instance           int
    48  		testRpcLeaseClient []*testRpcLeaseClientStruct
    49  		wg                 sync.WaitGroup
    50  	)
    51  
    52  	// Setup Single Lease instances
    53  
    54  	wg.Add(testRpcLeaseSingleNumInstances)
    55  
    56  	testRpcLeaseClient = make([]*testRpcLeaseClientStruct, testRpcLeaseSingleNumInstances)
    57  
    58  	for instance = 0; instance < testRpcLeaseSingleNumInstances; instance++ {
    59  		testRpcLeaseClient[instance] = &testRpcLeaseClientStruct{
    60  			instance:    instance,
    61  			inodeNumber: testRpcLeaseSingleInodeNumber,
    62  			chIn:        make(chan LeaseRequestType),
    63  			chOut:       make(chan interface{}),
    64  			wg:          &wg,
    65  			t:           t,
    66  		}
    67  
    68  		go testRpcLeaseClient[instance].instanceGoroutine()
    69  	}
    70  
    71  	// Perform Single Lease test cases
    72  
    73  	testRpcLeaseLogTestCase("1 Shared", true)
    74  
    75  	testRpcLeaseClient[0].sendLeaseRequest(LeaseRequestTypeShared)
    76  	testRpcLeaseClient[0].validateChOutValueIsLeaseReplyType(LeaseReplyTypeExclusive)
    77  	testRpcLeaseClient[0].sendLeaseRequest(LeaseRequestTypeRelease)
    78  	testRpcLeaseClient[0].validateChOutValueIsLeaseReplyType(LeaseReplyTypeReleased)
    79  
    80  	testRpcLeaseLogTestCase("1 Exclusive", true)
    81  
    82  	testRpcLeaseClient[0].sendLeaseRequest(LeaseRequestTypeExclusive)
    83  	testRpcLeaseClient[0].validateChOutValueIsLeaseReplyType(LeaseReplyTypeExclusive)
    84  	testRpcLeaseClient[0].sendLeaseRequest(LeaseRequestTypeRelease)
    85  	testRpcLeaseClient[0].validateChOutValueIsLeaseReplyType(LeaseReplyTypeReleased)
    86  
    87  	testRpcLeaseLogTestCase("1 Exclusive then Demote", true)
    88  
    89  	testRpcLeaseClient[0].sendLeaseRequest(LeaseRequestTypeExclusive)
    90  	testRpcLeaseClient[0].validateChOutValueIsLeaseReplyType(LeaseReplyTypeExclusive)
    91  	testRpcLeaseClient[0].sendLeaseRequest(LeaseRequestTypeDemote)
    92  	testRpcLeaseClient[0].validateChOutValueIsLeaseReplyType(LeaseReplyTypeDemoted)
    93  	testRpcLeaseClient[0].sendLeaseRequest(LeaseRequestTypeRelease)
    94  	testRpcLeaseClient[0].validateChOutValueIsLeaseReplyType(LeaseReplyTypeReleased)
    95  
    96  	testRpcLeaseLogTestCase("1 Exclusive then 1 Shared leading to Demotion", true)
    97  
    98  	testRpcLeaseClient[0].sendLeaseRequest(LeaseRequestTypeExclusive)
    99  	testRpcLeaseClient[0].validateChOutValueIsLeaseReplyType(LeaseReplyTypeExclusive)
   100  	testRpcLeaseClient[1].sendLeaseRequest(LeaseRequestTypeShared)
   101  	testRpcLeaseClient[0].validateChOutValueIsRPCInterruptType(RPCInterruptTypeDemote)
   102  	testRpcLeaseClient[0].sendLeaseRequest(LeaseRequestTypeDemote)
   103  	testRpcLeaseClient[0].validateChOutValueIsLeaseReplyTypeIgnoringRPCInterruptType(LeaseReplyTypeDemoted, RPCInterruptTypeDemote)
   104  	testRpcLeaseClient[1].validateChOutValueIsLeaseReplyType(LeaseReplyTypeShared)
   105  	testRpcLeaseClient[0].sendLeaseRequest(LeaseRequestTypeRelease)
   106  	testRpcLeaseClient[0].validateChOutValueIsLeaseReplyType(LeaseReplyTypeReleased)
   107  	testRpcLeaseClient[1].sendLeaseRequest(LeaseRequestTypeRelease)
   108  	testRpcLeaseClient[1].validateChOutValueIsLeaseReplyType(LeaseReplyTypeReleased)
   109  
   110  	testRpcLeaseLogTestCase("1 Exclusive, 1 Shared (causing Demotion), then Promotion", true)
   111  
   112  	testRpcLeaseClient[0].sendLeaseRequest(LeaseRequestTypeExclusive)
   113  	testRpcLeaseClient[0].validateChOutValueIsLeaseReplyType(LeaseReplyTypeExclusive)
   114  	testRpcLeaseClient[1].sendLeaseRequest(LeaseRequestTypeShared)
   115  	testRpcLeaseClient[0].validateChOutValueIsRPCInterruptType(RPCInterruptTypeDemote)
   116  	testRpcLeaseClient[0].sendLeaseRequest(LeaseRequestTypeDemote)
   117  	testRpcLeaseClient[0].validateChOutValueIsLeaseReplyTypeIgnoringRPCInterruptType(LeaseReplyTypeDemoted, RPCInterruptTypeDemote)
   118  	testRpcLeaseClient[1].validateChOutValueIsLeaseReplyType(LeaseReplyTypeShared)
   119  	testRpcLeaseClient[0].sendLeaseRequest(LeaseRequestTypePromote)
   120  	testRpcLeaseClient[1].validateChOutValueIsRPCInterruptType(RPCInterruptTypeRelease)
   121  	testRpcLeaseClient[1].sendLeaseRequest(LeaseRequestTypeRelease)
   122  	testRpcLeaseClient[1].validateChOutValueIsLeaseReplyTypeIgnoringRPCInterruptType(LeaseReplyTypeReleased, RPCInterruptTypeRelease)
   123  	testRpcLeaseClient[0].validateChOutValueIsLeaseReplyType(LeaseReplyTypePromoted)
   124  	testRpcLeaseClient[0].sendLeaseRequest(LeaseRequestTypeRelease)
   125  	testRpcLeaseClient[0].validateChOutValueIsLeaseReplyType(LeaseReplyTypeReleased)
   126  
   127  	testRpcLeaseLogTestCase("1 Exclusive Demoted to Shared then 1 Exclusive", true)
   128  
   129  	testRpcLeaseClient[0].sendLeaseRequest(LeaseRequestTypeExclusive)
   130  	testRpcLeaseClient[0].validateChOutValueIsLeaseReplyType(LeaseReplyTypeExclusive)
   131  	testRpcLeaseClient[0].sendLeaseRequest(LeaseRequestTypeDemote)
   132  	testRpcLeaseClient[0].validateChOutValueIsLeaseReplyType(LeaseReplyTypeDemoted)
   133  	testRpcLeaseClient[1].sendLeaseRequest(LeaseRequestTypeExclusive)
   134  	testRpcLeaseClient[0].validateChOutValueIsRPCInterruptType(RPCInterruptTypeRelease)
   135  	testRpcLeaseClient[0].sendLeaseRequest(LeaseRequestTypeRelease)
   136  	testRpcLeaseClient[0].validateChOutValueIsLeaseReplyTypeIgnoringRPCInterruptType(LeaseReplyTypeReleased, RPCInterruptTypeRelease)
   137  	testRpcLeaseClient[1].validateChOutValueIsLeaseReplyType(LeaseReplyTypeExclusive)
   138  	testRpcLeaseClient[1].sendLeaseRequest(LeaseRequestTypeRelease)
   139  	testRpcLeaseClient[1].validateChOutValueIsLeaseReplyType(LeaseReplyTypeReleased)
   140  
   141  	testRpcLeaseLogTestCase("2 Shared", true)
   142  
   143  	testRpcLeaseClient[0].sendLeaseRequest(LeaseRequestTypeShared)
   144  	testRpcLeaseClient[0].validateChOutValueIsLeaseReplyType(LeaseReplyTypeExclusive)
   145  	testRpcLeaseClient[1].sendLeaseRequest(LeaseRequestTypeShared)
   146  	testRpcLeaseClient[0].validateChOutValueIsRPCInterruptType(RPCInterruptTypeDemote)
   147  	testRpcLeaseClient[0].sendLeaseRequest(LeaseRequestTypeRelease)
   148  	testRpcLeaseClient[0].validateChOutValueIsLeaseReplyTypeIgnoringRPCInterruptType(LeaseReplyTypeReleased, RPCInterruptTypeDemote)
   149  	testRpcLeaseClient[1].validateChOutValueIsLeaseReplyType(LeaseReplyTypeExclusive)
   150  	testRpcLeaseClient[1].sendLeaseRequest(LeaseRequestTypeRelease)
   151  	testRpcLeaseClient[1].validateChOutValueIsLeaseReplyType(LeaseReplyTypeReleased)
   152  
   153  	testRpcLeaseLogTestCase("3 Shared", true)
   154  
   155  	testRpcLeaseClient[0].sendLeaseRequest(LeaseRequestTypeShared)
   156  	testRpcLeaseClient[0].validateChOutValueIsLeaseReplyType(LeaseReplyTypeExclusive)
   157  	testRpcLeaseClient[1].sendLeaseRequest(LeaseRequestTypeShared)
   158  	testRpcLeaseClient[2].sendLeaseRequest(LeaseRequestTypeShared)
   159  	testRpcLeaseClient[0].validateChOutValueIsRPCInterruptType(RPCInterruptTypeDemote)
   160  	testRpcLeaseClient[0].sendLeaseRequest(LeaseRequestTypeRelease)
   161  	testRpcLeaseClient[0].validateChOutValueIsLeaseReplyTypeIgnoringRPCInterruptType(LeaseReplyTypeReleased, RPCInterruptTypeDemote)
   162  	testRpcLeaseClient[1].validateChOutValueIsLeaseReplyType(LeaseReplyTypeShared)
   163  	testRpcLeaseClient[2].validateChOutValueIsLeaseReplyType(LeaseReplyTypeShared)
   164  	testRpcLeaseClient[1].sendLeaseRequest(LeaseRequestTypeRelease)
   165  	testRpcLeaseClient[1].validateChOutValueIsLeaseReplyType(LeaseReplyTypeReleased)
   166  	testRpcLeaseClient[2].sendLeaseRequest(LeaseRequestTypeRelease)
   167  	testRpcLeaseClient[2].validateChOutValueIsLeaseReplyType(LeaseReplyTypeReleased)
   168  
   169  	testRpcLeaseLogTestCase("1 Exclusive, 2 Shared (leading to Demotion)", true)
   170  
   171  	testRpcLeaseClient[0].sendLeaseRequest(LeaseRequestTypeExclusive)
   172  	testRpcLeaseClient[1].sendLeaseRequest(LeaseRequestTypeShared)
   173  	testRpcLeaseClient[2].sendLeaseRequest(LeaseRequestTypeShared)
   174  	testRpcLeaseClient[0].validateChOutValueIsLeaseReplyType(LeaseReplyTypeExclusive)
   175  	testRpcLeaseClient[0].validateChOutValueIsRPCInterruptType(RPCInterruptTypeDemote)
   176  	testRpcLeaseClient[0].sendLeaseRequest(LeaseRequestTypeDemote)
   177  	testRpcLeaseClient[0].validateChOutValueIsLeaseReplyTypeIgnoringRPCInterruptType(LeaseReplyTypeDemoted, RPCInterruptTypeDemote)
   178  	testRpcLeaseClient[1].validateChOutValueIsLeaseReplyType(LeaseReplyTypeShared)
   179  	testRpcLeaseClient[2].validateChOutValueIsLeaseReplyType(LeaseReplyTypeShared)
   180  	testRpcLeaseClient[0].sendLeaseRequest(LeaseRequestTypeRelease)
   181  	testRpcLeaseClient[1].sendLeaseRequest(LeaseRequestTypeRelease)
   182  	testRpcLeaseClient[2].sendLeaseRequest(LeaseRequestTypeRelease)
   183  	testRpcLeaseClient[0].validateChOutValueIsLeaseReplyType(LeaseReplyTypeReleased)
   184  	testRpcLeaseClient[1].validateChOutValueIsLeaseReplyType(LeaseReplyTypeReleased)
   185  	testRpcLeaseClient[2].validateChOutValueIsLeaseReplyType(LeaseReplyTypeReleased)
   186  
   187  	testRpcLeaseLogTestCase("1 Exclusive, 2 Shared (leading to Demotion), and another Exclusive", true)
   188  
   189  	testRpcLeaseClient[0].sendLeaseRequest(LeaseRequestTypeExclusive)
   190  	testRpcLeaseClient[1].sendLeaseRequest(LeaseRequestTypeShared)
   191  	testRpcLeaseClient[2].sendLeaseRequest(LeaseRequestTypeShared)
   192  	testRpcLeaseClient[3].sendLeaseRequest(LeaseRequestTypeExclusive)
   193  	testRpcLeaseClient[0].validateChOutValueIsLeaseReplyType(LeaseReplyTypeExclusive)
   194  	testRpcLeaseClient[0].validateChOutValueIsRPCInterruptType(RPCInterruptTypeDemote)
   195  	testRpcLeaseClient[0].sendLeaseRequest(LeaseRequestTypeDemote)
   196  	testRpcLeaseClient[0].validateChOutValueIsLeaseReplyTypeIgnoringRPCInterruptType(LeaseReplyTypeDemoted, RPCInterruptTypeDemote)
   197  	testRpcLeaseClient[1].validateChOutValueIsLeaseReplyType(LeaseReplyTypeShared)
   198  	testRpcLeaseClient[2].validateChOutValueIsLeaseReplyType(LeaseReplyTypeShared)
   199  	testRpcLeaseClient[0].validateChOutValueIsRPCInterruptType(RPCInterruptTypeRelease)
   200  	testRpcLeaseClient[1].validateChOutValueIsRPCInterruptType(RPCInterruptTypeRelease)
   201  	testRpcLeaseClient[2].validateChOutValueIsRPCInterruptType(RPCInterruptTypeRelease)
   202  	testRpcLeaseClient[0].sendLeaseRequest(LeaseRequestTypeRelease)
   203  	testRpcLeaseClient[1].sendLeaseRequest(LeaseRequestTypeRelease)
   204  	testRpcLeaseClient[2].sendLeaseRequest(LeaseRequestTypeRelease)
   205  	testRpcLeaseClient[0].validateChOutValueIsLeaseReplyTypeIgnoringRPCInterruptType(LeaseReplyTypeReleased, RPCInterruptTypeRelease)
   206  	testRpcLeaseClient[1].validateChOutValueIsLeaseReplyTypeIgnoringRPCInterruptType(LeaseReplyTypeReleased, RPCInterruptTypeRelease)
   207  	testRpcLeaseClient[2].validateChOutValueIsLeaseReplyTypeIgnoringRPCInterruptType(LeaseReplyTypeReleased, RPCInterruptTypeRelease)
   208  	testRpcLeaseClient[3].validateChOutValueIsLeaseReplyType(LeaseReplyTypeExclusive)
   209  	testRpcLeaseClient[3].sendLeaseRequest(LeaseRequestTypeRelease)
   210  	testRpcLeaseClient[3].validateChOutValueIsLeaseReplyType(LeaseReplyTypeReleased)
   211  
   212  	testRpcLeaseLogTestCase("2 Exclusives leading to Release that Expires", true)
   213  
   214  	testRpcLeaseClient[0].sendLeaseRequest(LeaseRequestTypeExclusive)
   215  	testRpcLeaseClient[1].sendLeaseRequest(LeaseRequestTypeExclusive)
   216  	testRpcLeaseClient[0].validateChOutValueIsLeaseReplyType(LeaseReplyTypeExclusive)
   217  	testRpcLeaseClient[0].validateChOutValueIsRPCInterruptType(RPCInterruptTypeRelease)
   218  	testRpcLeaseClient[0].validateChOutValueIsRPCInterruptType(RPCInterruptTypeRelease)
   219  	testRpcLeaseClient[0].validateChOutValueIsRPCInterruptType(RPCInterruptTypeRelease)
   220  	testRpcLeaseClient[0].validateChOutValueIsRPCInterruptType(RPCInterruptTypeRelease)
   221  	testRpcLeaseClient[0].validateChOutValueIsRPCInterruptType(RPCInterruptTypeRelease)
   222  	testRpcLeaseClient[1].validateChOutValueIsLeaseReplyType(LeaseReplyTypeExclusive)
   223  	testRpcLeaseClient[1].sendLeaseRequest(LeaseRequestTypeRelease)
   224  	testRpcLeaseClient[1].validateChOutValueIsLeaseReplyType(LeaseReplyTypeReleased)
   225  
   226  	testRpcLeaseLogTestCase("2 Shared, 2 Promotions (leading to one Release)", true)
   227  
   228  	testRpcLeaseClient[0].sendLeaseRequest(LeaseRequestTypeShared)
   229  	testRpcLeaseClient[0].validateChOutValueIsLeaseReplyType(LeaseReplyTypeExclusive)
   230  	testRpcLeaseClient[0].sendLeaseRequest(LeaseRequestTypeDemote)
   231  	testRpcLeaseClient[0].validateChOutValueIsLeaseReplyType(LeaseReplyTypeDemoted)
   232  	testRpcLeaseClient[1].sendLeaseRequest(LeaseRequestTypeShared)
   233  	testRpcLeaseClient[1].validateChOutValueIsLeaseReplyType(LeaseReplyTypeShared)
   234  	testRpcLeaseClient[0].sendLeaseRequest(LeaseRequestTypePromote)
   235  	testRpcLeaseClient[1].validateChOutValueIsRPCInterruptType(RPCInterruptTypeRelease)
   236  	testRpcLeaseClient[1].sendLeaseRequest(LeaseRequestTypePromote)
   237  	testRpcLeaseClient[1].validateChOutValueIsLeaseReplyTypeIgnoringRPCInterruptType(LeaseReplyTypeDenied, RPCInterruptTypeRelease)
   238  	testRpcLeaseClient[1].sendLeaseRequest(LeaseRequestTypeRelease)
   239  	testRpcLeaseClient[1].validateChOutValueIsLeaseReplyTypeIgnoringRPCInterruptType(LeaseReplyTypeReleased, RPCInterruptTypeRelease)
   240  	testRpcLeaseClient[0].validateChOutValueIsLeaseReplyType(LeaseReplyTypePromoted)
   241  	testRpcLeaseClient[0].sendLeaseRequest(LeaseRequestTypeRelease)
   242  	testRpcLeaseClient[0].validateChOutValueIsLeaseReplyType(LeaseReplyTypeReleased)
   243  
   244  	testRpcLeaseLogTestCase(fmt.Sprintf("%v Shares (first one to be Demoted)", testRpcLeaseSingleNumInstances), false)
   245  
   246  	testRpcLeaseClient[0].sendLeaseRequest(LeaseRequestTypeShared)
   247  	testRpcLeaseClient[0].validateChOutValueIsLeaseReplyType(LeaseReplyTypeExclusive)
   248  	testRpcLeaseClient[1].sendLeaseRequest(LeaseRequestTypeShared)
   249  	testRpcLeaseClient[0].validateChOutValueIsRPCInterruptType(RPCInterruptTypeDemote)
   250  	testRpcLeaseClient[0].sendLeaseRequest(LeaseRequestTypeDemote)
   251  	testRpcLeaseClient[0].validateChOutValueIsLeaseReplyTypeIgnoringRPCInterruptType(LeaseReplyTypeDemoted, RPCInterruptTypeDemote)
   252  	testRpcLeaseClient[1].validateChOutValueIsLeaseReplyType(LeaseReplyTypeShared)
   253  	for instance = 2; instance < testRpcLeaseSingleNumInstances; instance++ {
   254  		testRpcLeaseClient[instance].sendLeaseRequest(LeaseRequestTypeShared)
   255  		testRpcLeaseClient[instance].validateChOutValueIsLeaseReplyType(LeaseReplyTypeShared)
   256  	}
   257  	for instance = 0; instance < testRpcLeaseSingleNumInstances; instance++ {
   258  		testRpcLeaseClient[instance].sendLeaseRequest(LeaseRequestTypeRelease)
   259  		testRpcLeaseClient[instance].validateChOutValueIsLeaseReplyType(LeaseReplyTypeReleased)
   260  	}
   261  
   262  	testRpcLeaseLogTestCase(fmt.Sprintf("%v Exclusives", testRpcLeaseSingleNumInstances), false)
   263  
   264  	testRpcLeaseClient[0].sendLeaseRequest(LeaseRequestTypeExclusive)
   265  	testRpcLeaseClient[0].validateChOutValueIsLeaseReplyType(LeaseReplyTypeExclusive)
   266  	for instance = 1; instance < testRpcLeaseSingleNumInstances; instance++ {
   267  		testRpcLeaseClient[instance].sendLeaseRequest(LeaseRequestTypeExclusive)
   268  		testRpcLeaseClient[(instance - 1)].validateChOutValueIsRPCInterruptType(RPCInterruptTypeRelease)
   269  		testRpcLeaseClient[(instance - 1)].sendLeaseRequest(LeaseRequestTypeRelease)
   270  		testRpcLeaseClient[(instance-1)].validateChOutValueIsLeaseReplyTypeIgnoringRPCInterruptType(LeaseReplyTypeReleased, RPCInterruptTypeRelease)
   271  		testRpcLeaseClient[instance].validateChOutValueIsLeaseReplyType(LeaseReplyTypeExclusive)
   272  	}
   273  	testRpcLeaseClient[(testRpcLeaseSingleNumInstances - 1)].sendLeaseRequest(LeaseRequestTypeRelease)
   274  	testRpcLeaseClient[(testRpcLeaseSingleNumInstances - 1)].validateChOutValueIsLeaseReplyType(LeaseReplyTypeReleased)
   275  
   276  	// Shutdown Single Lease instances
   277  
   278  	for instance = 0; instance < testRpcLeaseSingleNumInstances; instance++ {
   279  		close(testRpcLeaseClient[instance].chIn)
   280  	}
   281  
   282  	wg.Wait()
   283  
   284  	// Setup Multi Lease instances
   285  
   286  	wg.Add(testRpcLeaseMultiNumInstances)
   287  
   288  	testRpcLeaseClient = make([]*testRpcLeaseClientStruct, testRpcLeaseMultiNumInstances)
   289  
   290  	for instance = 0; instance < testRpcLeaseMultiNumInstances; instance++ {
   291  		testRpcLeaseClient[instance] = &testRpcLeaseClientStruct{
   292  			instance:    instance,
   293  			inodeNumber: (testRpcLeaseMultiFirstInodeNumber + int64(instance)),
   294  			chIn:        make(chan LeaseRequestType),
   295  			chOut:       make(chan interface{}),
   296  			wg:          &wg,
   297  			t:           t,
   298  		}
   299  
   300  		go testRpcLeaseClient[instance].instanceGoroutine()
   301  	}
   302  
   303  	// Perform Multi Lease test case
   304  
   305  	testRpcLeaseLogTestCase(fmt.Sprintf("%v Unique InodeNumber Exclusives", testRpcLeaseMultiNumInstances), true)
   306  
   307  	testRpcLeaseClient[0].sendLeaseRequest(LeaseRequestTypeExclusive)
   308  	testRpcLeaseClient[1].sendLeaseRequest(LeaseRequestTypeExclusive)
   309  	testRpcLeaseClient[2].sendLeaseRequest(LeaseRequestTypeExclusive)
   310  	testRpcLeaseClient[3].sendLeaseRequest(LeaseRequestTypeExclusive)
   311  	testRpcLeaseClient[4].sendLeaseRequest(LeaseRequestTypeExclusive)
   312  
   313  	testRpcLeaseClient[0].validateChOutValueIsLeaseReplyType(LeaseReplyTypeExclusive)
   314  	testRpcLeaseClient[1].validateChOutValueIsLeaseReplyType(LeaseReplyTypeExclusive)
   315  	testRpcLeaseClient[2].validateChOutValueIsLeaseReplyType(LeaseReplyTypeExclusive)
   316  	testRpcLeaseClient[3].validateChOutValueIsLeaseReplyType(LeaseReplyTypeExclusive)
   317  	testRpcLeaseClient[4].validateChOutValueIsLeaseReplyType(LeaseReplyTypeExclusive)
   318  
   319  	testRpcLeaseClient[0].validateChOutValueIsRPCInterruptType(RPCInterruptTypeRelease)
   320  	testRpcLeaseClient[1].validateChOutValueIsRPCInterruptType(RPCInterruptTypeRelease)
   321  
   322  	testRpcLeaseClient[0].sendLeaseRequest(LeaseRequestTypeRelease)
   323  	testRpcLeaseClient[1].sendLeaseRequest(LeaseRequestTypeRelease)
   324  	testRpcLeaseClient[2].sendLeaseRequest(LeaseRequestTypeRelease)
   325  	testRpcLeaseClient[3].sendLeaseRequest(LeaseRequestTypeRelease)
   326  	testRpcLeaseClient[4].sendLeaseRequest(LeaseRequestTypeRelease)
   327  
   328  	testRpcLeaseClient[0].validateChOutValueIsLeaseReplyTypeIgnoringRPCInterruptType(LeaseReplyTypeReleased, RPCInterruptTypeRelease)
   329  	testRpcLeaseClient[1].validateChOutValueIsLeaseReplyTypeIgnoringRPCInterruptType(LeaseReplyTypeReleased, RPCInterruptTypeRelease)
   330  	testRpcLeaseClient[2].validateChOutValueIsLeaseReplyType(LeaseReplyTypeReleased)
   331  	testRpcLeaseClient[3].validateChOutValueIsLeaseReplyType(LeaseReplyTypeReleased)
   332  	testRpcLeaseClient[4].validateChOutValueIsLeaseReplyType(LeaseReplyTypeReleased)
   333  
   334  	// Shutdown Multi Lease instances
   335  
   336  	for instance = 0; instance < testRpcLeaseMultiNumInstances; instance++ {
   337  		close(testRpcLeaseClient[instance].chIn)
   338  	}
   339  
   340  	wg.Wait()
   341  }
   342  
   343  func (testRpcLeaseClient *testRpcLeaseClientStruct) instanceGoroutine() {
   344  	var (
   345  		deadlineIO                time.Duration
   346  		err                       error
   347  		keepAlivePeriod           time.Duration
   348  		leaseReply                *LeaseReply
   349  		leaseRequest              *LeaseRequest
   350  		leaseRequestType          LeaseRequestType
   351  		mountByAccountNameRequest *MountByAccountNameRequest
   352  		mountByAccountNameReply   *MountByAccountNameReply
   353  		ok                        bool
   354  		retryRPCClient            *retryrpc.Client
   355  		retryrpcClientConfig      *retryrpc.ClientConfig
   356  		server                    *Server
   357  		unmountReply              *Reply
   358  		unmountRequest            *UnmountRequest
   359  	)
   360  
   361  	server = &Server{}
   362  
   363  	mountByAccountNameRequest = &MountByAccountNameRequest{
   364  		AccountName:  testAccountName,
   365  		MountOptions: 0,
   366  		AuthUserID:   0,
   367  		AuthGroupID:  0,
   368  	}
   369  	mountByAccountNameReply = &MountByAccountNameReply{}
   370  
   371  	err = server.RpcMountByAccountName(mountByAccountNameRequest, mountByAccountNameReply)
   372  	if nil != err {
   373  		testRpcLeaseClient.Fatalf("server.RpcMountByAccountName(AccountName=\"%s\",) failed: %v", mountByAccountNameRequest.AccountName, err)
   374  	}
   375  
   376  	deadlineIO, err = time.ParseDuration(testRpcLeaseRetryRPCDeadlineIO)
   377  	if nil != err {
   378  		testRpcLeaseClient.Fatalf("time.ParseDuration(\"%s\") failed: %v", testRpcLeaseRetryRPCDeadlineIO, err)
   379  	}
   380  	keepAlivePeriod, err = time.ParseDuration(testRpcLeaseRetryRPCKeepAlivePeriod)
   381  	if nil != err {
   382  		testRpcLeaseClient.Fatalf("time.ParseDuration(\"%s\") failed: %v", testRpcLeaseRetryRPCKeepAlivePeriod, err)
   383  	}
   384  
   385  	retryrpcClientConfig = &retryrpc.ClientConfig{
   386  		MyUniqueID:               string(mountByAccountNameReply.MountID),
   387  		IPAddr:                   mountByAccountNameReply.RetryRPCPublicIPAddr,
   388  		Port:                     int(mountByAccountNameReply.RetryRPCPort),
   389  		RootCAx509CertificatePEM: mountByAccountNameReply.RootCAx509CertificatePEM,
   390  		Callbacks:                testRpcLeaseClient,
   391  		DeadlineIO:               deadlineIO,
   392  		KeepAlivePeriod:          keepAlivePeriod,
   393  	}
   394  
   395  	retryRPCClient, err = retryrpc.NewClient(retryrpcClientConfig)
   396  	if nil != err {
   397  		testRpcLeaseClient.Fatalf("retryrpc.NewClient() failed: %v", err)
   398  	}
   399  
   400  	for {
   401  		leaseRequestType, ok = <-testRpcLeaseClient.chIn
   402  
   403  		if ok {
   404  			time.Sleep(testRpcLeaseDelayBeforeSendingRequest)
   405  
   406  			leaseRequest = &LeaseRequest{
   407  				InodeHandle: InodeHandle{
   408  					MountID:     mountByAccountNameReply.MountID,
   409  					InodeNumber: testRpcLeaseClient.inodeNumber,
   410  				},
   411  				LeaseRequestType: leaseRequestType,
   412  			}
   413  			leaseReply = &LeaseReply{}
   414  
   415  			testRpcLeaseClient.logEvent(leaseRequest.LeaseRequestType)
   416  
   417  			err = retryRPCClient.Send("RpcLease", leaseRequest, leaseReply)
   418  			if nil != err {
   419  				testRpcLeaseClient.Fatalf("retryRPCClient.Send(\"RpcLease\",LeaseRequestType=%d) failed: %v", leaseRequestType, err)
   420  			}
   421  
   422  			testRpcLeaseClient.logEvent(leaseReply.LeaseReplyType)
   423  
   424  			testRpcLeaseClient.chOut <- leaseReply.LeaseReplyType
   425  		} else {
   426  			retryRPCClient.Close()
   427  
   428  			unmountRequest = &UnmountRequest{
   429  				MountID: mountByAccountNameReply.MountID,
   430  			}
   431  			unmountReply = &Reply{}
   432  
   433  			err = server.RpcUnmount(unmountRequest, unmountReply)
   434  			if nil != err {
   435  				testRpcLeaseClient.Fatalf("server.RpcUnmount(MountID=\"%s\",) failed: %v", unmountRequest.MountID, err)
   436  			}
   437  
   438  			testRpcLeaseClient.wg.Done()
   439  
   440  			runtime.Goexit()
   441  		}
   442  	}
   443  }
   444  
   445  func (testRpcLeaseClient *testRpcLeaseClientStruct) Interrupt(rpcInterruptBuf []byte) {
   446  	var (
   447  		err          error
   448  		rpcInterrupt *RPCInterrupt
   449  	)
   450  
   451  	rpcInterrupt = &RPCInterrupt{}
   452  
   453  	err = json.Unmarshal(rpcInterruptBuf, rpcInterrupt)
   454  	if nil != err {
   455  		testRpcLeaseClient.Fatalf("json.Unmarshal() failed: %v", err)
   456  	}
   457  	if rpcInterrupt.InodeNumber != testRpcLeaseClient.inodeNumber {
   458  		testRpcLeaseClient.Fatalf("Interrupt() called for InodeNumber %v... expected to be for %v", rpcInterrupt.InodeNumber, testRpcLeaseClient.inodeNumber)
   459  	}
   460  
   461  	testRpcLeaseClient.logEvent(rpcInterrupt.RPCInterruptType)
   462  
   463  	testRpcLeaseClient.chOut <- rpcInterrupt.RPCInterruptType
   464  }
   465  
   466  func (testRpcLeaseClient *testRpcLeaseClientStruct) Fatalf(format string, args ...interface{}) {
   467  	var (
   468  		argsForPrintf   []interface{}
   469  		argsIndex       int
   470  		argsValue       interface{}
   471  		formatForPrintf string
   472  	)
   473  
   474  	formatForPrintf = "Failing testRpcLeaseClient %v: " + format + "\n"
   475  
   476  	argsForPrintf = make([]interface{}, len(args)+1)
   477  	argsForPrintf[0] = testRpcLeaseClient.instance
   478  	for argsIndex, argsValue = range args {
   479  		argsForPrintf[argsIndex+1] = argsValue
   480  	}
   481  
   482  	fmt.Printf(formatForPrintf, argsForPrintf...)
   483  
   484  	os.Exit(-1)
   485  }
   486  
   487  func (testRpcLeaseClient *testRpcLeaseClientStruct) sendLeaseRequest(leaseRequestType LeaseRequestType) {
   488  	time.Sleep(testRpcLeaseDelayBeforeSendingRequest)
   489  	testRpcLeaseClient.chIn <- leaseRequestType
   490  	time.Sleep(testRpcLeaseDelayAfterSendingRequest)
   491  }
   492  
   493  func (testRpcLeaseClient *testRpcLeaseClientStruct) validateChOutValueIsLeaseReplyType(expectedLeaseReplyType LeaseReplyType) {
   494  	var (
   495  		chOutValueAsInterface      interface{}
   496  		chOutValueAsLeaseReplyType LeaseReplyType
   497  		ok                         bool
   498  	)
   499  
   500  	chOutValueAsInterface = <-testRpcLeaseClient.chOut
   501  
   502  	chOutValueAsLeaseReplyType, ok = chOutValueAsInterface.(LeaseReplyType)
   503  	if !ok {
   504  		testRpcLeaseClient.t.Fatalf("<-testRpcLeaseClient.chOut did not return a LeaseReplyType")
   505  	}
   506  	if chOutValueAsLeaseReplyType != expectedLeaseReplyType {
   507  		testRpcLeaseClient.t.Fatalf("<-testRpcLeaseClient.chOut returned LeaseReplyType %v... expected %v", chOutValueAsLeaseReplyType, expectedLeaseReplyType)
   508  	}
   509  }
   510  
   511  func (testRpcLeaseClient *testRpcLeaseClientStruct) validateChOutValueIsLeaseReplyTypeIgnoringRPCInterruptType(expectedLeaseReplyType LeaseReplyType, ignoredRPCInterruptType RPCInterruptType) {
   512  	var (
   513  		chOutValueAsInterface        interface{}
   514  		chOutValueAsRPCInterruptType RPCInterruptType
   515  		chOutValueAsLeaseReplyType   LeaseReplyType
   516  		ok                           bool
   517  	)
   518  
   519  	for {
   520  		chOutValueAsInterface = <-testRpcLeaseClient.chOut
   521  
   522  		chOutValueAsRPCInterruptType, ok = chOutValueAsInterface.(RPCInterruptType)
   523  		if ok {
   524  			if chOutValueAsRPCInterruptType != ignoredRPCInterruptType {
   525  				testRpcLeaseClient.t.Fatalf("<-testRpcLeaseClient.chOut did not return an ignored RPCInterruptType")
   526  			}
   527  		} else {
   528  			break
   529  		}
   530  	}
   531  
   532  	chOutValueAsLeaseReplyType, ok = chOutValueAsInterface.(LeaseReplyType)
   533  	if !ok {
   534  		testRpcLeaseClient.t.Fatalf("<-testRpcLeaseClient.chOut did not return a LeaseReplyType or ignored RPCInterruptType")
   535  	}
   536  	if chOutValueAsLeaseReplyType != expectedLeaseReplyType {
   537  		testRpcLeaseClient.t.Fatalf("<-testRpcLeaseClient.chOut returned LeaseReplyType %v... expected %v", chOutValueAsLeaseReplyType, expectedLeaseReplyType)
   538  	}
   539  }
   540  
   541  func (testRpcLeaseClient *testRpcLeaseClientStruct) validateChOutValueIsRPCInterruptType(expectedRPCInterruptType RPCInterruptType) {
   542  	var (
   543  		chOutValueAsInterface        interface{}
   544  		chOutValueAsRPCInterruptType RPCInterruptType
   545  		ok                           bool
   546  	)
   547  
   548  	chOutValueAsInterface = <-testRpcLeaseClient.chOut
   549  
   550  	chOutValueAsRPCInterruptType, ok = chOutValueAsInterface.(RPCInterruptType)
   551  	if !ok {
   552  		testRpcLeaseClient.t.Fatalf("<-testRpcLeaseClient.chOut did not return a RPCInterruptType")
   553  	}
   554  	if chOutValueAsRPCInterruptType != expectedRPCInterruptType {
   555  		testRpcLeaseClient.t.Fatalf("<-testRpcLeaseClient.chOut returned RPCInterruptType %v... expected %v", chOutValueAsRPCInterruptType, expectedRPCInterruptType)
   556  	}
   557  }
   558  
   559  func testRpcLeaseLogTestCase(testCase string, verbose bool) {
   560  	fmt.Printf("%v %s\n", time.Now().Format(testRpcLeaseTimeFormat), testCase)
   561  	testRpcLeaseLogVerbosely = verbose
   562  }
   563  
   564  func (testRpcLeaseClient *testRpcLeaseClientStruct) logEvent(ev interface{}) {
   565  	if testRpcLeaseLogVerbosely {
   566  		switch ev.(type) {
   567  		case LeaseRequestType:
   568  			fmt.Printf("%v      %s%s-> \n", time.Now().Format(testRpcLeaseTimeFormat), strings.Repeat("           ", testRpcLeaseClient.instance), testRpcLeaseRequestLetters[ev.(LeaseRequestType)])
   569  		case LeaseReplyType:
   570  			fmt.Printf("%v      %s <-%s\n", time.Now().Format(testRpcLeaseTimeFormat), strings.Repeat("           ", testRpcLeaseClient.instance), testRpcLeaseReplyLetters[ev.(LeaseReplyType)])
   571  		case RPCInterruptType:
   572  			fmt.Printf("%v      %s ^^%s\n", time.Now().Format(testRpcLeaseTimeFormat), strings.Repeat("           ", testRpcLeaseClient.instance), testRpcLeaseInterruptLetters[ev.(RPCInterruptType)])
   573  		}
   574  	}
   575  }