title: How to test concurrency and locking in golang?
body: <p>We are trying to test locks. Basically, there are multiple clients trying to obtain a lock on a particular key. In the example below, we used the key "x". </p>
  
  <p>I don't know how to test whether the locking is working. I can only read the logs to determine whether it is working.</p>
  
  <p>The correct sequence of events should be:</p>
  
  <ol>
  <li>client1 obtains lock on key "x"</li>
  <li>client2 tries to obtain lock on key "x" (fmt.Println("2 getting lock")) - but is blocked and waits</li>
  <li>client1 releases lock on key "x"</li>
  <li>client2 obtains lock on key "x"</li>
  </ol>
  
  <p>Q1: How could I automate the process and turn this into a test? </p>
  
  <p>Q2: What are some of the tips to testing concurrency / mutex locking in general?</p>
  
  <pre><code>func TestLockUnlock(t *testing.T) {
      client1, err := NewClient()
      if err != nil {
          t.Error("Unexpected new client error: ", err)
      }
  
      fmt.Println("1 getting lock")
      id1, err := client1.Lock("x", 10*time.Second)
      if err != nil {
          t.Error("Unexpected lock error: ", err)
      }
      fmt.Println("1 got lock")
  
      go func() {
          client2, err := NewClient()
          if err != nil {
              t.Error("Unexpected new client error: ", err)
          }
          fmt.Println("2 getting lock")
          id2, err := client2.Lock("x", 10*time.Second)
          if err != nil {
              t.Error("Unexpected lock error: ", err)
          }
          fmt.Println("2 got lock")
  
          fmt.Println("2 releasing lock")
          err = client2.Unlock("x", id2)
          if err != nil {
              t.Error("Unexpected Unlock error: ", err)
          }
          fmt.Println("2 released lock")
          err = client2.Close()
          if err != nil {
              t.Error("Unexpected connection close error: ", err)
          }
      }()
  
      fmt.Println("sleeping")
      time.Sleep(2 * time.Second)
      fmt.Println("finished sleeping")
  
      fmt.Println("1 releasing lock")
      err = client1.Unlock("x", id1)
      if err != nil {
          t.Error("Unexpected Unlock error: ", err)
      }
  
      fmt.Println("1 released lock")
  
      err = client1.Close()
      if err != nil {
          t.Error("Unexpected connection close error: ", err)
      }
  
      time.Sleep(5 * time.Second)
  }
  
  func NewClient() *Client {
     ....
  }
  
  func (c *Client) Lock(lockKey string, timeout time.Duration) (lockId int64, err error){
     ....
  }
  
  func (c *Client) Unlock(lockKey string) err error {
     ....
  }
  </code></pre>