瀏覽代碼

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 年之前
父節點
當前提交
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
 // under the License.
 
-package redis
+package internal // import "github.com/garyburd/redigo/internal"
 
 import (
 	"strings"
 )
 
 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)]
 }

+ 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"
 	"time"
 
+	"github.com/garyburd/redigo/internal/redistest"
 	"github.com/garyburd/redigo/redis"
 )
 
@@ -221,7 +222,7 @@ var testCommands = []struct {
 }
 
 func TestDoCommands(t *testing.T) {
-	c, err := redis.DialTestDB()
+	c, err := redistest.Dial()
 	if err != nil {
 		t.Fatalf("error connection to database, %v", err)
 	}
@@ -240,7 +241,7 @@ func TestDoCommands(t *testing.T) {
 }
 
 func TestPipelineCommands(t *testing.T) {
-	c, err := redis.DialTestDB()
+	c, err := redistest.Dial()
 	if err != nil {
 		t.Fatalf("error connection to database, %v", err)
 	}
@@ -266,7 +267,7 @@ func TestPipelineCommands(t *testing.T) {
 }
 
 func TestBlankCommmand(t *testing.T) {
-	c, err := redis.DialTestDB()
+	c, err := redistest.Dial()
 	if err != nil {
 		t.Fatalf("error connection to database, %v", err)
 	}
@@ -293,7 +294,7 @@ func TestBlankCommmand(t *testing.T) {
 }
 
 func TestRecvBeforeSend(t *testing.T) {
-	c, err := redis.DialTestDB()
+	c, err := redistest.Dial()
 	if err != nil {
 		t.Fatalf("error connection to database, %v", err)
 	}
@@ -314,7 +315,7 @@ func TestRecvBeforeSend(t *testing.T) {
 }
 
 func TestError(t *testing.T) {
-	c, err := redis.DialTestDB()
+	c, err := redistest.Dial()
 	if err != nil {
 		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
 // errors in a transaction.
 func TestExecError(t *testing.T) {
-	c, err := redis.DialTestDB()
+	c, err := redistest.Dial()
 	if err != nil {
 		t.Fatalf("error connection to database, %v", err)
 	}
@@ -477,7 +478,7 @@ func TestExecError(t *testing.T) {
 
 func BenchmarkDoEmpty(b *testing.B) {
 	b.StopTimer()
-	c, err := redis.DialTestDB()
+	c, err := redistest.Dial()
 	if err != nil {
 		b.Fatal(err)
 	}
@@ -492,7 +493,7 @@ func BenchmarkDoEmpty(b *testing.B) {
 
 func BenchmarkDoPing(b *testing.B) {
 	b.StopTimer()
-	c, err := redis.DialTestDB()
+	c, err := redistest.Dial()
 	if err != nil {
 		b.Fatal(err)
 	}

+ 1 - 1
redis/doc.go

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

+ 12 - 10
redis/pool.go

@@ -24,6 +24,8 @@ import (
 	"strconv"
 	"sync"
 	"time"
+
+	"github.com/garyburd/redigo/internal"
 )
 
 var nowFunc = time.Now // for testing
@@ -290,14 +292,14 @@ func (pc *pooledConnection) Close() error {
 	}
 	pc.c = errorConnection{errConnClosed}
 
-	if pc.state&multiState != 0 {
+	if pc.state&internal.MultiState != 0 {
 		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")
-		pc.state &^= watchState
+		pc.state &^= internal.WatchState
 	}
-	if pc.state&subscribeState != 0 {
+	if pc.state&internal.SubscribeState != 0 {
 		c.Send("UNSUBSCRIBE")
 		c.Send("PUNSUBSCRIBE")
 		// To detect the end of the message stream, ask the server to echo
@@ -311,7 +313,7 @@ func (pc *pooledConnection) Close() error {
 				break
 			}
 			if p, ok := p.([]byte); ok && bytes.Equal(p, sentinel) {
-				pc.state &^= subscribeState
+				pc.state &^= internal.SubscribeState
 				break
 			}
 		}
@@ -326,14 +328,14 @@ func (pc *pooledConnection) 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...)
 }
 
 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...)
 }
 

+ 27 - 100
redis/pool_test.go

@@ -12,7 +12,7 @@
 // License for the specific language governing permissions and limitations
 // under the License.
 
-package redis
+package redis_test
 
 import (
 	"io"
@@ -21,12 +21,15 @@ import (
 	"sync"
 	"testing"
 	"time"
+
+	"github.com/garyburd/redigo/internal/redistest"
+	"github.com/garyburd/redigo/redis"
 )
 
 type poolTestConn struct {
 	d   *poolDialer
 	err error
-	Conn
+	redis.Conn
 }
 
 func (c *poolTestConn) Close() error { c.d.open -= 1; return nil }
@@ -53,17 +56,17 @@ type poolDialer struct {
 	commands     []string
 }
 
-func (d *poolDialer) dial() (Conn, error) {
+func (d *poolDialer) dial() (redis.Conn, error) {
 	d.open += 1
 	d.dialed += 1
-	c, err := DialTestDB()
+	c, err := redistest.Dial()
 	if err != nil {
 		return nil, err
 	}
 	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 {
 		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) {
 	d := poolDialer{t: t}
-	p := &Pool{
+	p := &redis.Pool{
 		MaxIdle: 2,
 		Dial:    d.dial,
 	}
@@ -98,7 +101,7 @@ func TestPoolReuse(t *testing.T) {
 
 func TestPoolMaxIdle(t *testing.T) {
 	d := poolDialer{t: t}
-	p := &Pool{
+	p := &redis.Pool{
 		MaxIdle: 2,
 		Dial:    d.dial,
 	}
@@ -120,7 +123,7 @@ func TestPoolMaxIdle(t *testing.T) {
 
 func TestPoolError(t *testing.T) {
 	d := poolDialer{t: t}
-	p := &Pool{
+	p := &redis.Pool{
 		MaxIdle: 2,
 		Dial:    d.dial,
 	}
@@ -141,7 +144,7 @@ func TestPoolError(t *testing.T) {
 
 func TestPoolClose(t *testing.T) {
 	d := poolDialer{t: t}
-	p := &Pool{
+	p := &redis.Pool{
 		MaxIdle: 2,
 		Dial:    d.dial,
 	}
@@ -181,15 +184,15 @@ func TestPoolClose(t *testing.T) {
 
 func TestPoolTimeout(t *testing.T) {
 	d := poolDialer{t: t}
-	p := &Pool{
+	p := &redis.Pool{
 		MaxIdle:     2,
 		IdleTimeout: 300 * time.Second,
 		Dial:        d.dial,
 	}
 
 	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.Do("PING")
@@ -209,8 +212,8 @@ func TestPoolTimeout(t *testing.T) {
 }
 
 func TestPoolConcurrenSendReceive(t *testing.T) {
-	p := &Pool{
-		Dial: DialTestDB,
+	p := &redis.Pool{
+		Dial: redistest.Dial,
 	}
 	c := p.Get()
 	done := make(chan error, 1)
@@ -234,10 +237,10 @@ func TestPoolConcurrenSendReceive(t *testing.T) {
 
 func TestPoolBorrowCheck(t *testing.T) {
 	d := poolDialer{t: t}
-	p := &Pool{
+	p := &redis.Pool{
 		MaxIdle:      2,
 		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++ {
@@ -251,7 +254,7 @@ func TestPoolBorrowCheck(t *testing.T) {
 
 func TestPoolMaxActive(t *testing.T) {
 	d := poolDialer{t: t}
-	p := &Pool{
+	p := &redis.Pool{
 		MaxIdle:   2,
 		MaxActive: 2,
 		Dial:      d.dial,
@@ -264,7 +267,7 @@ func TestPoolMaxActive(t *testing.T) {
 	d.check("1", p, 2, 2)
 
 	c3 := p.Get()
-	if _, err := c3.Do("PING"); err != ErrPoolExhausted {
+	if _, err := c3.Do("PING"); err != redis.ErrPoolExhausted {
 		t.Errorf("expected pool exhausted")
 	}
 
@@ -285,7 +288,7 @@ func TestPoolMaxActive(t *testing.T) {
 
 func TestPoolMonitorCleanup(t *testing.T) {
 	d := poolDialer{t: t}
-	p := &Pool{
+	p := &redis.Pool{
 		MaxIdle:   2,
 		MaxActive: 2,
 		Dial:      d.dial,
@@ -300,7 +303,7 @@ func TestPoolMonitorCleanup(t *testing.T) {
 
 func TestPoolPubSubCleanup(t *testing.T) {
 	d := poolDialer{t: t}
-	p := &Pool{
+	p := &redis.Pool{
 		MaxIdle:   2,
 		MaxActive: 2,
 		Dial:      d.dial,
@@ -331,7 +334,7 @@ func TestPoolPubSubCleanup(t *testing.T) {
 
 func TestPoolTransactionCleanup(t *testing.T) {
 	d := poolDialer{t: t}
-	p := &Pool{
+	p := &redis.Pool{
 		MaxIdle:   2,
 		MaxActive: 2,
 		Dial:      d.dial,
@@ -403,7 +406,7 @@ func TestPoolTransactionCleanup(t *testing.T) {
 
 func BenchmarkPoolGet(b *testing.B) {
 	b.StopTimer()
-	p := Pool{Dial: DialTestDB, MaxIdle: 2}
+	p := redis.Pool{Dial: redistest.Dial, MaxIdle: 2}
 	c := p.Get()
 	if err := c.Err(); err != nil {
 		b.Fatal(err)
@@ -419,7 +422,7 @@ func BenchmarkPoolGet(b *testing.B) {
 
 func BenchmarkPoolGetErr(b *testing.B) {
 	b.StopTimer()
-	p := Pool{Dial: DialTestDB, MaxIdle: 2}
+	p := redis.Pool{Dial: redistest.Dial, MaxIdle: 2}
 	c := p.Get()
 	if err := c.Err(); err != nil {
 		b.Fatal(err)
@@ -438,7 +441,7 @@ func BenchmarkPoolGetErr(b *testing.B) {
 
 func BenchmarkPoolGetPing(b *testing.B) {
 	b.StopTimer()
-	p := Pool{Dial: DialTestDB, MaxIdle: 2}
+	p := redis.Pool{Dial: redistest.Dial, MaxIdle: 2}
 	c := p.Get()
 	if err := c.Err(); err != nil {
 		b.Fatal(err)
@@ -454,79 +457,3 @@ func BenchmarkPoolGetPing(b *testing.B) {
 		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 (
 	"fmt"
-	"github.com/garyburd/redigo/redis"
 	"net"
 	"reflect"
 	"sync"
 	"testing"
 	"time"
+
+	"github.com/garyburd/redigo/internal/redistest"
+	"github.com/garyburd/redigo/redis"
 )
 
 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) {
-	pc, err := redis.DialTestDB()
+	pc, err := redistest.Dial()
 	if err != nil {
 		t.Fatalf("error connection to database, %v", err)
 	}

+ 2 - 1
redis/reply_test.go

@@ -19,6 +19,7 @@ import (
 	"reflect"
 	"testing"
 
+	"github.com/garyburd/redigo/internal/redistest"
 	"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.
 func dial() (redis.Conn, error) {
-	return redis.DialTestDB()
+	return redistest.Dial()
 }
 
 func ExampleBool() {

+ 4 - 2
redis/script_test.go

@@ -16,10 +16,12 @@ package redis_test
 
 import (
 	"fmt"
-	"github.com/garyburd/redigo/redis"
 	"reflect"
 	"testing"
 	"time"
+
+	"github.com/garyburd/redigo/internal/redistest"
+	"github.com/garyburd/redigo/redis"
 )
 
 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) {
-	c, err := redis.DialTestDB()
+	c, err := redistest.Dial()
 	if err != nil {
 		t.Fatalf("error connection to database, %v", err)
 	}

+ 5 - 44
redis/test_test.go

@@ -16,60 +16,21 @@ package redis
 
 import (
 	"bufio"
-	"errors"
 	"net"
 	"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.
 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 (

+ 1 - 1
redisx/doc.go

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