Просмотр исходного кода

Use internal package.

Move function lookupCommadInfo in redis package to LookupCommandInfo in
new internal package.

Move test only function DialTestDB function in redis package to Dial in
new internal/redistest package.

Bonus edit: add package import comments.
Gary Burd 11 лет назад
Родитель
Сommit
3bd67d4044
11 измененных файлов с 147 добавлено и 186 удалено
  1. 17 17
      internal/commandinfo.go
  2. 65 0
      internal/redistest/testdb.go
  3. 9 8
      redis/conn_test.go
  4. 1 1
      redis/doc.go
  5. 12 10
      redis/pool.go
  6. 27 100
      redis/pool_test.go
  7. 4 2
      redis/pubsub_test.go
  8. 2 1
      redis/reply_test.go
  9. 4 2
      redis/script_test.go
  10. 5 44
      redis/test_test.go
  11. 1 1
      redisx/doc.go

+ 17 - 17
redis/commandinfo.go → internal/commandinfo.go

@@ -12,34 +12,34 @@
 // License for the specific language governing permissions and limitations
 // License for the specific language governing permissions and limitations
 // under the License.
 // under the License.
 
 
-package redis
+package internal // import "github.com/garyburd/redigo/internal"
 
 
 import (
 import (
 	"strings"
 	"strings"
 )
 )
 
 
 const (
 const (
-	watchState = 1 << iota
-	multiState
-	subscribeState
-	monitorState
+	WatchState = 1 << iota
+	MultiState
+	SubscribeState
+	MonitorState
 )
 )
 
 
-type commandInfo struct {
-	set, clear int
+type CommandInfo struct {
+	Set, Clear int
 }
 }
 
 
-var commandInfos = map[string]commandInfo{
-	"WATCH":      {set: watchState},
-	"UNWATCH":    {clear: watchState},
-	"MULTI":      {set: multiState},
-	"EXEC":       {clear: watchState | multiState},
-	"DISCARD":    {clear: watchState | multiState},
-	"PSUBSCRIBE": {set: subscribeState},
-	"SUBSCRIBE":  {set: subscribeState},
-	"MONITOR":    {set: monitorState},
+var commandInfos = map[string]CommandInfo{
+	"WATCH":      {Set: WatchState},
+	"UNWATCH":    {Clear: WatchState},
+	"MULTI":      {Set: MultiState},
+	"EXEC":       {Clear: WatchState | MultiState},
+	"DISCARD":    {Clear: WatchState | MultiState},
+	"PSUBSCRIBE": {Set: SubscribeState},
+	"SUBSCRIBE":  {Set: SubscribeState},
+	"MONITOR":    {Set: MonitorState},
 }
 }
 
 
-func lookupCommandInfo(commandName string) commandInfo {
+func LookupCommandInfo(commandName string) CommandInfo {
 	return commandInfos[strings.ToUpper(commandName)]
 	return commandInfos[strings.ToUpper(commandName)]
 }
 }

+ 65 - 0
internal/redistest/testdb.go

@@ -0,0 +1,65 @@
+// Copyright 2014 Gary Burd
+//
+// Licensed under the Apache License, Version 2.0 (the "License"): you may
+// not use this file except in compliance with the License. You may obtain
+// a copy of the License at
+//
+//     http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+// WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+// License for the specific language governing permissions and limitations
+// under the License.
+
+// Package redistest contains utilities for writing Redigo tests.
+package redistest
+
+import (
+	"errors"
+	"time"
+
+	"github.com/garyburd/redigo/redis"
+)
+
+type testConn struct {
+	redis.Conn
+}
+
+func (t testConn) Close() error {
+	_, err := t.Conn.Do("SELECT", "9")
+	if err != nil {
+		return nil
+	}
+	_, err = t.Conn.Do("FLUSHDB")
+	if err != nil {
+		return err
+	}
+	return t.Conn.Close()
+}
+
+// Dial dials the local Redis server and selects database 9. To prevent
+// stomping on real data, DialTestDB fails if database 9 contains data. The
+// returned connection flushes database 9 on close.
+func Dial() (redis.Conn, error) {
+	c, err := redis.DialTimeout("tcp", ":6379", 0, 1*time.Second, 1*time.Second)
+	if err != nil {
+		return nil, err
+	}
+
+	_, err = c.Do("SELECT", "9")
+	if err != nil {
+		return nil, err
+	}
+
+	n, err := redis.Int(c.Do("DBSIZE"))
+	if err != nil {
+		return nil, err
+	}
+
+	if n != 0 {
+		return nil, errors.New("database #9 is not empty, test can not continue")
+	}
+
+	return testConn{c}, nil
+}

+ 9 - 8
redis/conn_test.go

@@ -24,6 +24,7 @@ import (
 	"testing"
 	"testing"
 	"time"
 	"time"
 
 
+	"github.com/garyburd/redigo/internal/redistest"
 	"github.com/garyburd/redigo/redis"
 	"github.com/garyburd/redigo/redis"
 )
 )
 
 
@@ -221,7 +222,7 @@ var testCommands = []struct {
 }
 }
 
 
 func TestDoCommands(t *testing.T) {
 func TestDoCommands(t *testing.T) {
-	c, err := redis.DialTestDB()
+	c, err := redistest.Dial()
 	if err != nil {
 	if err != nil {
 		t.Fatalf("error connection to database, %v", err)
 		t.Fatalf("error connection to database, %v", err)
 	}
 	}
@@ -240,7 +241,7 @@ func TestDoCommands(t *testing.T) {
 }
 }
 
 
 func TestPipelineCommands(t *testing.T) {
 func TestPipelineCommands(t *testing.T) {
-	c, err := redis.DialTestDB()
+	c, err := redistest.Dial()
 	if err != nil {
 	if err != nil {
 		t.Fatalf("error connection to database, %v", err)
 		t.Fatalf("error connection to database, %v", err)
 	}
 	}
@@ -266,7 +267,7 @@ func TestPipelineCommands(t *testing.T) {
 }
 }
 
 
 func TestBlankCommmand(t *testing.T) {
 func TestBlankCommmand(t *testing.T) {
-	c, err := redis.DialTestDB()
+	c, err := redistest.Dial()
 	if err != nil {
 	if err != nil {
 		t.Fatalf("error connection to database, %v", err)
 		t.Fatalf("error connection to database, %v", err)
 	}
 	}
@@ -293,7 +294,7 @@ func TestBlankCommmand(t *testing.T) {
 }
 }
 
 
 func TestRecvBeforeSend(t *testing.T) {
 func TestRecvBeforeSend(t *testing.T) {
-	c, err := redis.DialTestDB()
+	c, err := redistest.Dial()
 	if err != nil {
 	if err != nil {
 		t.Fatalf("error connection to database, %v", err)
 		t.Fatalf("error connection to database, %v", err)
 	}
 	}
@@ -314,7 +315,7 @@ func TestRecvBeforeSend(t *testing.T) {
 }
 }
 
 
 func TestError(t *testing.T) {
 func TestError(t *testing.T) {
-	c, err := redis.DialTestDB()
+	c, err := redistest.Dial()
 	if err != nil {
 	if err != nil {
 		t.Fatalf("error connection to database, %v", err)
 		t.Fatalf("error connection to database, %v", err)
 	}
 	}
@@ -399,7 +400,7 @@ func ExampleDial(x int) {
 // http://redis.io/topics/transactions for information on how Redis handles
 // http://redis.io/topics/transactions for information on how Redis handles
 // errors in a transaction.
 // errors in a transaction.
 func TestExecError(t *testing.T) {
 func TestExecError(t *testing.T) {
-	c, err := redis.DialTestDB()
+	c, err := redistest.Dial()
 	if err != nil {
 	if err != nil {
 		t.Fatalf("error connection to database, %v", err)
 		t.Fatalf("error connection to database, %v", err)
 	}
 	}
@@ -477,7 +478,7 @@ func TestExecError(t *testing.T) {
 
 
 func BenchmarkDoEmpty(b *testing.B) {
 func BenchmarkDoEmpty(b *testing.B) {
 	b.StopTimer()
 	b.StopTimer()
-	c, err := redis.DialTestDB()
+	c, err := redistest.Dial()
 	if err != nil {
 	if err != nil {
 		b.Fatal(err)
 		b.Fatal(err)
 	}
 	}
@@ -492,7 +493,7 @@ func BenchmarkDoEmpty(b *testing.B) {
 
 
 func BenchmarkDoPing(b *testing.B) {
 func BenchmarkDoPing(b *testing.B) {
 	b.StopTimer()
 	b.StopTimer()
-	c, err := redis.DialTestDB()
+	c, err := redistest.Dial()
 	if err != nil {
 	if err != nil {
 		b.Fatal(err)
 		b.Fatal(err)
 	}
 	}

+ 1 - 1
redis/doc.go

@@ -166,4 +166,4 @@
 //   if _, err := redis.Scan(reply, &value1, &value2); err != nil {
 //   if _, err := redis.Scan(reply, &value1, &value2); err != nil {
 //      // handle error
 //      // handle error
 //  }
 //  }
-package redis
+package redis // import "github.com/garyburd/redigo/redis"

+ 12 - 10
redis/pool.go

@@ -24,6 +24,8 @@ import (
 	"strconv"
 	"strconv"
 	"sync"
 	"sync"
 	"time"
 	"time"
+
+	"github.com/garyburd/redigo/internal"
 )
 )
 
 
 var nowFunc = time.Now // for testing
 var nowFunc = time.Now // for testing
@@ -290,14 +292,14 @@ func (pc *pooledConnection) Close() error {
 	}
 	}
 	pc.c = errorConnection{errConnClosed}
 	pc.c = errorConnection{errConnClosed}
 
 
-	if pc.state&multiState != 0 {
+	if pc.state&internal.MultiState != 0 {
 		c.Send("DISCARD")
 		c.Send("DISCARD")
-		pc.state &^= (multiState | watchState)
-	} else if pc.state&watchState != 0 {
+		pc.state &^= (internal.MultiState | internal.WatchState)
+	} else if pc.state&internal.WatchState != 0 {
 		c.Send("UNWATCH")
 		c.Send("UNWATCH")
-		pc.state &^= watchState
+		pc.state &^= internal.WatchState
 	}
 	}
-	if pc.state&subscribeState != 0 {
+	if pc.state&internal.SubscribeState != 0 {
 		c.Send("UNSUBSCRIBE")
 		c.Send("UNSUBSCRIBE")
 		c.Send("PUNSUBSCRIBE")
 		c.Send("PUNSUBSCRIBE")
 		// To detect the end of the message stream, ask the server to echo
 		// To detect the end of the message stream, ask the server to echo
@@ -311,7 +313,7 @@ func (pc *pooledConnection) Close() error {
 				break
 				break
 			}
 			}
 			if p, ok := p.([]byte); ok && bytes.Equal(p, sentinel) {
 			if p, ok := p.([]byte); ok && bytes.Equal(p, sentinel) {
-				pc.state &^= subscribeState
+				pc.state &^= internal.SubscribeState
 				break
 				break
 			}
 			}
 		}
 		}
@@ -326,14 +328,14 @@ func (pc *pooledConnection) Err() error {
 }
 }
 
 
 func (pc *pooledConnection) Do(commandName string, args ...interface{}) (reply interface{}, err error) {
 func (pc *pooledConnection) Do(commandName string, args ...interface{}) (reply interface{}, err error) {
-	ci := lookupCommandInfo(commandName)
-	pc.state = (pc.state | ci.set) &^ ci.clear
+	ci := internal.LookupCommandInfo(commandName)
+	pc.state = (pc.state | ci.Set) &^ ci.Clear
 	return pc.c.Do(commandName, args...)
 	return pc.c.Do(commandName, args...)
 }
 }
 
 
 func (pc *pooledConnection) Send(commandName string, args ...interface{}) error {
 func (pc *pooledConnection) Send(commandName string, args ...interface{}) error {
-	ci := lookupCommandInfo(commandName)
-	pc.state = (pc.state | ci.set) &^ ci.clear
+	ci := internal.LookupCommandInfo(commandName)
+	pc.state = (pc.state | ci.Set) &^ ci.Clear
 	return pc.c.Send(commandName, args...)
 	return pc.c.Send(commandName, args...)
 }
 }
 
 

+ 27 - 100
redis/pool_test.go

@@ -12,7 +12,7 @@
 // License for the specific language governing permissions and limitations
 // License for the specific language governing permissions and limitations
 // under the License.
 // under the License.
 
 
-package redis
+package redis_test
 
 
 import (
 import (
 	"io"
 	"io"
@@ -21,12 +21,15 @@ import (
 	"sync"
 	"sync"
 	"testing"
 	"testing"
 	"time"
 	"time"
+
+	"github.com/garyburd/redigo/internal/redistest"
+	"github.com/garyburd/redigo/redis"
 )
 )
 
 
 type poolTestConn struct {
 type poolTestConn struct {
 	d   *poolDialer
 	d   *poolDialer
 	err error
 	err error
-	Conn
+	redis.Conn
 }
 }
 
 
 func (c *poolTestConn) Close() error { c.d.open -= 1; return nil }
 func (c *poolTestConn) Close() error { c.d.open -= 1; return nil }
@@ -53,17 +56,17 @@ type poolDialer struct {
 	commands     []string
 	commands     []string
 }
 }
 
 
-func (d *poolDialer) dial() (Conn, error) {
+func (d *poolDialer) dial() (redis.Conn, error) {
 	d.open += 1
 	d.open += 1
 	d.dialed += 1
 	d.dialed += 1
-	c, err := DialTestDB()
+	c, err := redistest.Dial()
 	if err != nil {
 	if err != nil {
 		return nil, err
 		return nil, err
 	}
 	}
 	return &poolTestConn{d: d, Conn: c}, nil
 	return &poolTestConn{d: d, Conn: c}, nil
 }
 }
 
 
-func (d *poolDialer) check(message string, p *Pool, dialed, open int) {
+func (d *poolDialer) check(message string, p *redis.Pool, dialed, open int) {
 	if d.dialed != dialed {
 	if d.dialed != dialed {
 		d.t.Errorf("%s: dialed=%d, want %d", message, d.dialed, dialed)
 		d.t.Errorf("%s: dialed=%d, want %d", message, d.dialed, dialed)
 	}
 	}
@@ -77,7 +80,7 @@ func (d *poolDialer) check(message string, p *Pool, dialed, open int) {
 
 
 func TestPoolReuse(t *testing.T) {
 func TestPoolReuse(t *testing.T) {
 	d := poolDialer{t: t}
 	d := poolDialer{t: t}
-	p := &Pool{
+	p := &redis.Pool{
 		MaxIdle: 2,
 		MaxIdle: 2,
 		Dial:    d.dial,
 		Dial:    d.dial,
 	}
 	}
@@ -98,7 +101,7 @@ func TestPoolReuse(t *testing.T) {
 
 
 func TestPoolMaxIdle(t *testing.T) {
 func TestPoolMaxIdle(t *testing.T) {
 	d := poolDialer{t: t}
 	d := poolDialer{t: t}
-	p := &Pool{
+	p := &redis.Pool{
 		MaxIdle: 2,
 		MaxIdle: 2,
 		Dial:    d.dial,
 		Dial:    d.dial,
 	}
 	}
@@ -120,7 +123,7 @@ func TestPoolMaxIdle(t *testing.T) {
 
 
 func TestPoolError(t *testing.T) {
 func TestPoolError(t *testing.T) {
 	d := poolDialer{t: t}
 	d := poolDialer{t: t}
-	p := &Pool{
+	p := &redis.Pool{
 		MaxIdle: 2,
 		MaxIdle: 2,
 		Dial:    d.dial,
 		Dial:    d.dial,
 	}
 	}
@@ -141,7 +144,7 @@ func TestPoolError(t *testing.T) {
 
 
 func TestPoolClose(t *testing.T) {
 func TestPoolClose(t *testing.T) {
 	d := poolDialer{t: t}
 	d := poolDialer{t: t}
-	p := &Pool{
+	p := &redis.Pool{
 		MaxIdle: 2,
 		MaxIdle: 2,
 		Dial:    d.dial,
 		Dial:    d.dial,
 	}
 	}
@@ -181,15 +184,15 @@ func TestPoolClose(t *testing.T) {
 
 
 func TestPoolTimeout(t *testing.T) {
 func TestPoolTimeout(t *testing.T) {
 	d := poolDialer{t: t}
 	d := poolDialer{t: t}
-	p := &Pool{
+	p := &redis.Pool{
 		MaxIdle:     2,
 		MaxIdle:     2,
 		IdleTimeout: 300 * time.Second,
 		IdleTimeout: 300 * time.Second,
 		Dial:        d.dial,
 		Dial:        d.dial,
 	}
 	}
 
 
 	now := time.Now()
 	now := time.Now()
-	nowFunc = func() time.Time { return now }
-	defer func() { nowFunc = time.Now }()
+	redis.SetNowFunc(func() time.Time { return now })
+	defer redis.SetNowFunc(time.Now)
 
 
 	c := p.Get()
 	c := p.Get()
 	c.Do("PING")
 	c.Do("PING")
@@ -209,8 +212,8 @@ func TestPoolTimeout(t *testing.T) {
 }
 }
 
 
 func TestPoolConcurrenSendReceive(t *testing.T) {
 func TestPoolConcurrenSendReceive(t *testing.T) {
-	p := &Pool{
-		Dial: DialTestDB,
+	p := &redis.Pool{
+		Dial: redistest.Dial,
 	}
 	}
 	c := p.Get()
 	c := p.Get()
 	done := make(chan error, 1)
 	done := make(chan error, 1)
@@ -234,10 +237,10 @@ func TestPoolConcurrenSendReceive(t *testing.T) {
 
 
 func TestPoolBorrowCheck(t *testing.T) {
 func TestPoolBorrowCheck(t *testing.T) {
 	d := poolDialer{t: t}
 	d := poolDialer{t: t}
-	p := &Pool{
+	p := &redis.Pool{
 		MaxIdle:      2,
 		MaxIdle:      2,
 		Dial:         d.dial,
 		Dial:         d.dial,
-		TestOnBorrow: func(Conn, time.Time) error { return Error("BLAH") },
+		TestOnBorrow: func(redis.Conn, time.Time) error { return redis.Error("BLAH") },
 	}
 	}
 
 
 	for i := 0; i < 10; i++ {
 	for i := 0; i < 10; i++ {
@@ -251,7 +254,7 @@ func TestPoolBorrowCheck(t *testing.T) {
 
 
 func TestPoolMaxActive(t *testing.T) {
 func TestPoolMaxActive(t *testing.T) {
 	d := poolDialer{t: t}
 	d := poolDialer{t: t}
-	p := &Pool{
+	p := &redis.Pool{
 		MaxIdle:   2,
 		MaxIdle:   2,
 		MaxActive: 2,
 		MaxActive: 2,
 		Dial:      d.dial,
 		Dial:      d.dial,
@@ -264,7 +267,7 @@ func TestPoolMaxActive(t *testing.T) {
 	d.check("1", p, 2, 2)
 	d.check("1", p, 2, 2)
 
 
 	c3 := p.Get()
 	c3 := p.Get()
-	if _, err := c3.Do("PING"); err != ErrPoolExhausted {
+	if _, err := c3.Do("PING"); err != redis.ErrPoolExhausted {
 		t.Errorf("expected pool exhausted")
 		t.Errorf("expected pool exhausted")
 	}
 	}
 
 
@@ -285,7 +288,7 @@ func TestPoolMaxActive(t *testing.T) {
 
 
 func TestPoolMonitorCleanup(t *testing.T) {
 func TestPoolMonitorCleanup(t *testing.T) {
 	d := poolDialer{t: t}
 	d := poolDialer{t: t}
-	p := &Pool{
+	p := &redis.Pool{
 		MaxIdle:   2,
 		MaxIdle:   2,
 		MaxActive: 2,
 		MaxActive: 2,
 		Dial:      d.dial,
 		Dial:      d.dial,
@@ -300,7 +303,7 @@ func TestPoolMonitorCleanup(t *testing.T) {
 
 
 func TestPoolPubSubCleanup(t *testing.T) {
 func TestPoolPubSubCleanup(t *testing.T) {
 	d := poolDialer{t: t}
 	d := poolDialer{t: t}
-	p := &Pool{
+	p := &redis.Pool{
 		MaxIdle:   2,
 		MaxIdle:   2,
 		MaxActive: 2,
 		MaxActive: 2,
 		Dial:      d.dial,
 		Dial:      d.dial,
@@ -331,7 +334,7 @@ func TestPoolPubSubCleanup(t *testing.T) {
 
 
 func TestPoolTransactionCleanup(t *testing.T) {
 func TestPoolTransactionCleanup(t *testing.T) {
 	d := poolDialer{t: t}
 	d := poolDialer{t: t}
-	p := &Pool{
+	p := &redis.Pool{
 		MaxIdle:   2,
 		MaxIdle:   2,
 		MaxActive: 2,
 		MaxActive: 2,
 		Dial:      d.dial,
 		Dial:      d.dial,
@@ -403,7 +406,7 @@ func TestPoolTransactionCleanup(t *testing.T) {
 
 
 func BenchmarkPoolGet(b *testing.B) {
 func BenchmarkPoolGet(b *testing.B) {
 	b.StopTimer()
 	b.StopTimer()
-	p := Pool{Dial: DialTestDB, MaxIdle: 2}
+	p := redis.Pool{Dial: redistest.Dial, MaxIdle: 2}
 	c := p.Get()
 	c := p.Get()
 	if err := c.Err(); err != nil {
 	if err := c.Err(); err != nil {
 		b.Fatal(err)
 		b.Fatal(err)
@@ -419,7 +422,7 @@ func BenchmarkPoolGet(b *testing.B) {
 
 
 func BenchmarkPoolGetErr(b *testing.B) {
 func BenchmarkPoolGetErr(b *testing.B) {
 	b.StopTimer()
 	b.StopTimer()
-	p := Pool{Dial: DialTestDB, MaxIdle: 2}
+	p := redis.Pool{Dial: redistest.Dial, MaxIdle: 2}
 	c := p.Get()
 	c := p.Get()
 	if err := c.Err(); err != nil {
 	if err := c.Err(); err != nil {
 		b.Fatal(err)
 		b.Fatal(err)
@@ -438,7 +441,7 @@ func BenchmarkPoolGetErr(b *testing.B) {
 
 
 func BenchmarkPoolGetPing(b *testing.B) {
 func BenchmarkPoolGetPing(b *testing.B) {
 	b.StopTimer()
 	b.StopTimer()
-	p := Pool{Dial: DialTestDB, MaxIdle: 2}
+	p := redis.Pool{Dial: redistest.Dial, MaxIdle: 2}
 	c := p.Get()
 	c := p.Get()
 	if err := c.Err(); err != nil {
 	if err := c.Err(); err != nil {
 		b.Fatal(err)
 		b.Fatal(err)
@@ -454,79 +457,3 @@ func BenchmarkPoolGetPing(b *testing.B) {
 		c.Close()
 		c.Close()
 	}
 	}
 }
 }
-
-const numConcurrent = 10
-
-func BenchmarkPipelineConcurrency(b *testing.B) {
-	b.StopTimer()
-	c, err := DialTestDB()
-	if err != nil {
-		b.Fatalf("error connection to database, %v", err)
-	}
-	defer c.Close()
-
-	var wg sync.WaitGroup
-	wg.Add(numConcurrent)
-
-	var pipeline textproto.Pipeline
-
-	b.StartTimer()
-
-	for i := 0; i < numConcurrent; i++ {
-		go func() {
-			defer wg.Done()
-			for i := 0; i < b.N; i++ {
-				id := pipeline.Next()
-				pipeline.StartRequest(id)
-				c.Send("PING")
-				c.Flush()
-				pipeline.EndRequest(id)
-				pipeline.StartResponse(id)
-				_, err := c.Receive()
-				if err != nil {
-					b.Fatal(err)
-				}
-				c.Flush()
-				pipeline.EndResponse(id)
-			}
-		}()
-	}
-	wg.Wait()
-}
-
-func BenchmarkPoolConcurrency(b *testing.B) {
-	b.StopTimer()
-
-	p := Pool{Dial: DialTestDB, MaxIdle: numConcurrent}
-	defer p.Close()
-
-	// fill the pool
-	conns := make([]Conn, numConcurrent)
-	for i := range conns {
-		c := p.Get()
-		if err := c.Err(); err != nil {
-			b.Fatal(err)
-		}
-		conns[i] = c
-	}
-	for _, c := range conns {
-		c.Close()
-	}
-
-	var wg sync.WaitGroup
-	wg.Add(numConcurrent)
-
-	b.StartTimer()
-
-	for i := 0; i < numConcurrent; i++ {
-		go func() {
-			defer wg.Done()
-			for i := 0; i < b.N; i++ {
-				c := p.Get()
-				c.Do("PING")
-				c.Close()
-			}
-		}()
-	}
-	wg.Wait()
-}

+ 4 - 2
redis/pubsub_test.go

@@ -16,12 +16,14 @@ package redis_test
 
 
 import (
 import (
 	"fmt"
 	"fmt"
-	"github.com/garyburd/redigo/redis"
 	"net"
 	"net"
 	"reflect"
 	"reflect"
 	"sync"
 	"sync"
 	"testing"
 	"testing"
 	"time"
 	"time"
+
+	"github.com/garyburd/redigo/internal/redistest"
+	"github.com/garyburd/redigo/redis"
 )
 )
 
 
 func publish(channel, value interface{}) {
 func publish(channel, value interface{}) {
@@ -109,7 +111,7 @@ func expectPushed(t *testing.T, c redis.PubSubConn, message string, expected int
 }
 }
 
 
 func TestPushed(t *testing.T) {
 func TestPushed(t *testing.T) {
-	pc, err := redis.DialTestDB()
+	pc, err := redistest.Dial()
 	if err != nil {
 	if err != nil {
 		t.Fatalf("error connection to database, %v", err)
 		t.Fatalf("error connection to database, %v", err)
 	}
 	}

+ 2 - 1
redis/reply_test.go

@@ -19,6 +19,7 @@ import (
 	"reflect"
 	"reflect"
 	"testing"
 	"testing"
 
 
+	"github.com/garyburd/redigo/internal/redistest"
 	"github.com/garyburd/redigo/redis"
 	"github.com/garyburd/redigo/redis"
 )
 )
 
 
@@ -92,7 +93,7 @@ func TestReply(t *testing.T) {
 
 
 // dial wraps DialTestDB() with a more suitable function name for examples.
 // dial wraps DialTestDB() with a more suitable function name for examples.
 func dial() (redis.Conn, error) {
 func dial() (redis.Conn, error) {
-	return redis.DialTestDB()
+	return redistest.Dial()
 }
 }
 
 
 func ExampleBool() {
 func ExampleBool() {

+ 4 - 2
redis/script_test.go

@@ -16,10 +16,12 @@ package redis_test
 
 
 import (
 import (
 	"fmt"
 	"fmt"
-	"github.com/garyburd/redigo/redis"
 	"reflect"
 	"reflect"
 	"testing"
 	"testing"
 	"time"
 	"time"
+
+	"github.com/garyburd/redigo/internal/redistest"
+	"github.com/garyburd/redigo/redis"
 )
 )
 
 
 func ExampleScript(c redis.Conn, reply interface{}, err error) {
 func ExampleScript(c redis.Conn, reply interface{}, err error) {
@@ -33,7 +35,7 @@ func ExampleScript(c redis.Conn, reply interface{}, err error) {
 }
 }
 
 
 func TestScript(t *testing.T) {
 func TestScript(t *testing.T) {
-	c, err := redis.DialTestDB()
+	c, err := redistest.Dial()
 	if err != nil {
 	if err != nil {
 		t.Fatalf("error connection to database, %v", err)
 		t.Fatalf("error connection to database, %v", err)
 	}
 	}

+ 5 - 44
redis/test_test.go

@@ -16,60 +16,21 @@ package redis
 
 
 import (
 import (
 	"bufio"
 	"bufio"
-	"errors"
 	"net"
 	"net"
 	"time"
 	"time"
 )
 )
 
 
-type testConn struct {
-	Conn
+func SetNowFunc(f func() time.Time) {
+	nowFunc = f
 }
 }
 
 
-func (t testConn) Close() error {
-	_, err := t.Conn.Do("SELECT", "9")
-	if err != nil {
-		return nil
-	}
-	_, err = t.Conn.Do("FLUSHDB")
-	if err != nil {
-		return err
-	}
-	return t.Conn.Close()
-}
-
-// DialTestDB dials the local Redis server and selects database 9. To prevent
-// stomping on real data, DialTestDB fails if database 9 contains data. The
-// returned connection flushes database 9 on close.
-func DialTestDB() (Conn, error) {
-	c, err := DialTimeout("tcp", ":6379", 0, 1*time.Second, 1*time.Second)
-	if err != nil {
-		return nil, err
-	}
-
-	_, err = c.Do("SELECT", "9")
-	if err != nil {
-		return nil, err
-	}
-
-	n, err := Int(c.Do("DBSIZE"))
-	if err != nil {
-		return nil, err
-	}
-
-	if n != 0 {
-		return nil, errors.New("database #9 is not empty, test can not continue")
-	}
-
-	return testConn{c}, nil
-}
-
-type dummyClose struct{ net.Conn }
+type nopCloser struct{ net.Conn }
 
 
-func (dummyClose) Close() error { return nil }
+func (nopCloser) Close() error { return nil }
 
 
 // NewConnBufio is a hook for tests.
 // NewConnBufio is a hook for tests.
 func NewConnBufio(rw bufio.ReadWriter) Conn {
 func NewConnBufio(rw bufio.ReadWriter) Conn {
-	return &conn{br: rw.Reader, bw: rw.Writer, conn: dummyClose{}}
+	return &conn{br: rw.Reader, bw: rw.Writer, conn: nopCloser{}}
 }
 }
 
 
 var (
 var (

+ 1 - 1
redisx/doc.go

@@ -14,4 +14,4 @@
 
 
 // Package redisx contains experimental features for Redigo. Features in this
 // Package redisx contains experimental features for Redigo. Features in this
 // package may be modified or deleted at any time.
 // package may be modified or deleted at any time.
-package redisx
+package redisx // import "github.com/garyburd/redigo/redisx"