Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Improve resilience of api pkg tests #4676

Merged
merged 5 commits into from
Sep 18, 2018
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion GNUmakefile
Original file line number Diff line number Diff line change
Expand Up @@ -162,7 +162,7 @@ test-internal:
@# hide it from travis as it exceeds their log limits and causes job to be
@# terminated (over 4MB and over 10k lines in the UI). We need to output
@# _something_ to stop them terminating us due to inactivity...
{ go test $(GOTEST_FLAGS) -tags '$(GOTAGS)' $(GOTEST_PKGS) 2>&1 ; echo $$? > exit-code ; } | tee test.log | egrep '^(ok|FAIL|panic:|--- FAIL)'
{ go test -v $(GOTEST_FLAGS) -tags '$(GOTAGS)' $(GOTEST_PKGS) 2>&1 ; echo $$? > exit-code ; } | tee test.log | egrep '^(ok|FAIL|panic:|--- FAIL|--- PASS)'
@echo "Exit code: $$(cat exit-code)"
@# This prints all the race report between ====== lines
@awk '/^WARNING: DATA RACE/ {do_print=1; print "=================="} do_print==1 {print} /^={10,}/ {do_print=0}' test.log || true
Expand Down
84 changes: 51 additions & 33 deletions api/lock_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -13,18 +13,44 @@ import (
"github.com/hashicorp/consul/testutil/retry"
)

func createTestLock(t *testing.T, c *Client, key string) (*Lock, *Session) {
t.Helper()
session := c.Session()

se := &SessionEntry{
Name: DefaultLockSessionName,
TTL: DefaultLockSessionTTL,
Behavior: SessionBehaviorDelete,
}
id, _, err := session.CreateNoChecks(se, nil)
if err != nil {
t.Fatalf("err: %v", err)
}

opts := &LockOptions{
Key: key,
Session: id,
SessionName: se.Name,
SessionTTL: se.TTL,
}
lock, err := c.LockOpts(opts)
if err != nil {
t.Fatalf("err: %v", err)
}

return lock, session
}

func TestAPI_LockLockUnlock(t *testing.T) {
t.Parallel()
c, s := makeClientWithoutConnect(t)
defer s.Stop()

lock, err := c.LockKey("test/lock")
if err != nil {
t.Fatalf("err: %v", err)
}
lock, session := createTestLock(t, c, "test/lock")
defer session.Destroy(lock.opts.Session, nil)

// Initial unlock should fail
err = lock.Unlock()
err := lock.Unlock()
if err != ErrLockNotHeld {
t.Fatalf("err: %v", err)
}
Expand Down Expand Up @@ -77,10 +103,8 @@ func TestAPI_LockForceInvalidate(t *testing.T) {
defer s.Stop()

retry.Run(t, func(r *retry.R) {
lock, err := c.LockKey("test/lock")
if err != nil {
t.Fatalf("err: %v", err)
}
lock, session := createTestLock(t, c, "test/lock")
defer session.Destroy(lock.opts.Session, nil)

// Should work
leaderCh, err := lock.Lock(nil)
Expand Down Expand Up @@ -119,10 +143,8 @@ func TestAPI_LockDeleteKey(t *testing.T) {
// territory.
for i := 0; i < 10; i++ {
func() {
lock, err := c.LockKey("test/lock")
if err != nil {
t.Fatalf("err: %v", err)
}
lock, session := createTestLock(t, c, "test/lock")
defer session.Destroy(lock.opts.Session, nil)

// Should work
leaderCh, err := lock.Lock(nil)
Expand Down Expand Up @@ -161,10 +183,8 @@ func TestAPI_LockContend(t *testing.T) {
wg.Add(1)
go func(idx int) {
defer wg.Done()
lock, err := c.LockKey("test/lock")
if err != nil {
t.Fatalf("err: %v", err)
}
lock, session := createTestLock(t, c, "test/lock")
defer session.Destroy(lock.opts.Session, nil)

// Should work eventually, will contend
leaderCh, err := lock.Lock(nil)
Expand Down Expand Up @@ -208,10 +228,8 @@ func TestAPI_LockDestroy(t *testing.T) {
c, s := makeClientWithoutConnect(t)
defer s.Stop()

lock, err := c.LockKey("test/lock")
if err != nil {
t.Fatalf("err: %v", err)
}
lock, session := createTestLock(t, c, "test/lock")
defer session.Destroy(lock.opts.Session, nil)

// Should work
leaderCh, err := lock.Lock(nil)
Expand All @@ -234,10 +252,8 @@ func TestAPI_LockDestroy(t *testing.T) {
}

// Acquire with a different lock
l2, err := c.LockKey("test/lock")
if err != nil {
t.Fatalf("err: %v", err)
}
l2, session := createTestLock(t, c, "test/lock")
defer session.Destroy(lock.opts.Session, nil)

// Should work
leaderCh, err = l2.Lock(nil)
Expand Down Expand Up @@ -277,10 +293,8 @@ func TestAPI_LockConflict(t *testing.T) {
c, s := makeClientWithoutConnect(t)
defer s.Stop()

sema, err := c.SemaphorePrefix("test/lock/", 2)
if err != nil {
t.Fatalf("err: %v", err)
}
sema, session := createTestSemaphore(t, c, "test/lock/", 2)
defer session.Destroy(sema.opts.Session, nil)

// Should work
lockCh, err := sema.Acquire(nil)
Expand All @@ -292,10 +306,8 @@ func TestAPI_LockConflict(t *testing.T) {
}
defer sema.Release()

lock, err := c.LockKey("test/lock/.lock")
if err != nil {
t.Fatalf("err: %v", err)
}
lock, session := createTestLock(t, c, "test/lock/.lock")
defer session.Destroy(lock.opts.Session, nil)

// Should conflict with semaphore
_, err = lock.Lock(nil)
Expand All @@ -315,6 +327,8 @@ func TestAPI_LockReclaimLock(t *testing.T) {
c, s := makeClientWithoutConnect(t)
defer s.Stop()

s.WaitForSerfCheck(t)

session, _, err := c.Session().Create(&SessionEntry{}, nil)
if err != nil {
t.Fatalf("err: %v", err)
Expand Down Expand Up @@ -383,6 +397,8 @@ func TestAPI_LockMonitorRetry(t *testing.T) {
raw, s := makeClientWithoutConnect(t)
defer s.Stop()

s.WaitForSerfCheck(t)

// Set up a server that always responds with 500 errors.
failer := func(w http.ResponseWriter, req *http.Request) {
w.WriteHeader(500)
Expand Down Expand Up @@ -498,6 +514,8 @@ func TestAPI_LockOneShot(t *testing.T) {
c, s := makeClientWithoutConnect(t)
defer s.Stop()

s.WaitForSerfCheck(t)

// Set up a lock as a one-shot.
opts := &LockOptions{
Key: "test/lock",
Expand Down
99 changes: 56 additions & 43 deletions api/semaphore_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -11,18 +11,45 @@ import (
"time"
)

func createTestSemaphore(t *testing.T, c *Client, prefix string, limit int) (*Semaphore, *Session) {
t.Helper()
session := c.Session()

se := &SessionEntry{
Name: DefaultSemaphoreSessionName,
TTL: DefaultSemaphoreSessionTTL,
Behavior: SessionBehaviorDelete,
}
id, _, err := session.CreateNoChecks(se, nil)
if err != nil {
t.Fatalf("err: %v", err)
}

opts := &SemaphoreOptions{
Prefix: prefix,
Limit: limit,
Session: id,
SessionName: se.Name,
SessionTTL: se.TTL,
}
sema, err := c.SemaphoreOpts(opts)
if err != nil {
t.Fatalf("err: %v", err)
}

return sema, session
}

func TestAPI_SemaphoreAcquireRelease(t *testing.T) {
t.Parallel()
c, s := makeClient(t)
defer s.Stop()

sema, err := c.SemaphorePrefix("test/semaphore", 2)
if err != nil {
t.Fatalf("err: %v", err)
}
sema, session := createTestSemaphore(t, c, "test/semaphore", 2)
defer session.Destroy(sema.opts.Session, nil)

// Initial release should fail
err = sema.Release()
err := sema.Release()
if err != ErrSemaphoreNotHeld {
t.Fatalf("err: %v", err)
}
Expand Down Expand Up @@ -74,10 +101,8 @@ func TestAPI_SemaphoreForceInvalidate(t *testing.T) {
c, s := makeClient(t)
defer s.Stop()

sema, err := c.SemaphorePrefix("test/semaphore", 2)
if err != nil {
t.Fatalf("err: %v", err)
}
sema, session := createTestSemaphore(t, c, "test/semaphore", 2)
defer session.Destroy(sema.opts.Session, nil)

// Should work
lockCh, err := sema.Acquire(nil)
Expand Down Expand Up @@ -109,10 +134,8 @@ func TestAPI_SemaphoreDeleteKey(t *testing.T) {
c, s := makeClient(t)
defer s.Stop()

sema, err := c.SemaphorePrefix("test/semaphore", 2)
if err != nil {
t.Fatalf("err: %v", err)
}
sema, session := createTestSemaphore(t, c, "test/semaphore", 2)
defer session.Destroy(sema.opts.Session, nil)

// Should work
lockCh, err := sema.Acquire(nil)
Expand Down Expand Up @@ -149,10 +172,8 @@ func TestAPI_SemaphoreContend(t *testing.T) {
wg.Add(1)
go func(idx int) {
defer wg.Done()
sema, err := c.SemaphorePrefix("test/semaphore", 2)
if err != nil {
t.Fatalf("err: %v", err)
}
sema, session := createTestSemaphore(t, c, "test/semaphore", 2)
defer session.Destroy(sema.opts.Session, nil)

// Should work eventually, will contend
lockCh, err := sema.Acquire(nil)
Expand Down Expand Up @@ -198,23 +219,19 @@ func TestAPI_SemaphoreBadLimit(t *testing.T) {

sema, err := c.SemaphorePrefix("test/semaphore", 0)
if err == nil {
t.Fatalf("should error")
t.Fatalf("should error, limit must be positive")
}

sema, err = c.SemaphorePrefix("test/semaphore", 1)
if err != nil {
t.Fatalf("err: %v", err)
}
sema, session := createTestSemaphore(t, c, "test/semaphore", 1)
defer session.Destroy(sema.opts.Session, nil)

_, err = sema.Acquire(nil)
if err != nil {
t.Fatalf("err: %v", err)
}

sema2, err := c.SemaphorePrefix("test/semaphore", 2)
if err != nil {
t.Fatalf("err: %v", err)
}
sema2, session := createTestSemaphore(t, c, "test/semaphore", 2)
defer session.Destroy(sema.opts.Session, nil)

_, err = sema2.Acquire(nil)
if err.Error() != "semaphore limit conflict (lock: 1, local: 2)" {
Expand All @@ -227,17 +244,13 @@ func TestAPI_SemaphoreDestroy(t *testing.T) {
c, s := makeClient(t)
defer s.Stop()

sema, err := c.SemaphorePrefix("test/semaphore", 2)
if err != nil {
t.Fatalf("err: %v", err)
}
sema, session := createTestSemaphore(t, c, "test/semaphore", 2)
defer session.Destroy(sema.opts.Session, nil)

sema2, err := c.SemaphorePrefix("test/semaphore", 2)
if err != nil {
t.Fatalf("err: %v", err)
}
sema2, session := createTestSemaphore(t, c, "test/semaphore", 2)
defer session.Destroy(sema.opts.Session, nil)

_, err = sema.Acquire(nil)
_, err := sema.Acquire(nil)
if err != nil {
t.Fatalf("err: %v", err)
}
Expand Down Expand Up @@ -283,10 +296,8 @@ func TestAPI_SemaphoreConflict(t *testing.T) {
c, s := makeClient(t)
defer s.Stop()

lock, err := c.LockKey("test/sema/.lock")
if err != nil {
t.Fatalf("err: %v", err)
}
lock, session := createTestLock(t, c, "test/sema/.lock")
defer session.Destroy(lock.opts.Session, nil)

// Should work
leaderCh, err := lock.Lock(nil)
Expand All @@ -298,10 +309,8 @@ func TestAPI_SemaphoreConflict(t *testing.T) {
}
defer lock.Unlock()

sema, err := c.SemaphorePrefix("test/sema/", 2)
if err != nil {
t.Fatalf("err: %v", err)
}
sema, session := createTestSemaphore(t, c, "test/sema/", 2)
defer session.Destroy(sema.opts.Session, nil)

// Should conflict with lock
_, err = sema.Acquire(nil)
Expand All @@ -321,6 +330,8 @@ func TestAPI_SemaphoreMonitorRetry(t *testing.T) {
raw, s := makeClient(t)
defer s.Stop()

s.WaitForSerfCheck(t)

// Set up a server that always responds with 500 errors.
failer := func(w http.ResponseWriter, req *http.Request) {
w.WriteHeader(500)
Expand Down Expand Up @@ -438,6 +449,8 @@ func TestAPI_SemaphoreOneShot(t *testing.T) {
c, s := makeClient(t)
defer s.Stop()

s.WaitForSerfCheck(t)

// Set up a semaphore as a one-shot.
opts := &SemaphoreOptions{
Prefix: "test/sema/.lock",
Expand Down
Loading