From 3077979a3bc756d3493f89aeb3e47901f58d9572 Mon Sep 17 00:00:00 2001 From: Frode Nordahl Date: Fri, 27 May 2016 13:25:31 +0200 Subject: [PATCH] Functional tests for LDAP Connection Pool --- functional/ldap_test.go | 57 +++++++++++++++++++++++++++++++++++++++++ 1 file changed, 57 insertions(+) diff --git a/functional/ldap_test.go b/functional/ldap_test.go index 701cd060..d7d6a6d5 100644 --- a/functional/ldap_test.go +++ b/functional/ldap_test.go @@ -7,9 +7,12 @@ import ( "net/url" "os" "strconv" + "sync" "testing" + "time" "github.com/coreos/dex/connector" + "golang.org/x/net/context" "gopkg.in/ldap.v2" ) @@ -123,3 +126,57 @@ func TestConnectorLDAPHealthy(t *testing.T) { } } } + +func TestLDAPPoolHighWatermarkAndLockContention(t *testing.T) { + server := ldapServer(t) + ldapPool := &connector.LDAPPool{ + MaxIdleConn: 30, + ServerHost: server.Host, + ServerPort: server.Port, + UseTLS: false, + UseSSL: false, + } + + // Excercise pool operations with MaxIdleConn + 10 concurrent goroutines. + // We are testing both pool high watermark code and lock contention + numRoutines := ldapPool.MaxIdleConn + 10 + var wg sync.WaitGroup + wg.Add(numRoutines) + ctx, _ := context.WithTimeout(context.Background(), 5*time.Second) + for i := 0; i < numRoutines; i++ { + go func() { + defer wg.Done() + for { + select { + case <-ctx.Done(): + return + default: + ldapConn, err := ldapPool.Acquire() + if err != nil { + t.Errorf("Unable to acquire LDAP Connection: %v", err) + } + s := ldap.NewSearchRequest("", ldap.ScopeBaseObject, ldap.NeverDerefAliases, 0, 0, false, "(objectClass=*)", []string{}, nil) + _, err = ldapConn.Search(s) + if err != nil { + t.Errorf("Search request failed. Dead/invalid LDAP connection from pool?: %v", err) + ldapConn.Close() + } else { + ldapPool.Put(ldapConn) + } + _, _ = ldapPool.CheckConnections() + } + } + }() + } + + // Wait for all operations to complete and check status. + // There should be MaxIdleConn connections in the pool. This confirms: + // 1. The tests was indeed executed concurrently + // 2. Even though we ran more routines than the configured MaxIdleConn the high + // watermark code did its job and closed surplus connections + wg.Wait() + alive, killed := ldapPool.CheckConnections() + if alive < ldapPool.MaxIdleConn { + t.Errorf("expected %v connections, got alive=%v killed=%v", ldapPool.MaxIdleConn, alive, killed) + } +}