miniredis

package module
v2.5.0+incompatible Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Feb 20, 2019 License: MIT Imports: 23 Imported by: 60

README

Miniredis

Pure Go Redis test server, used in Go unittests.

Sometimes you want to test code which uses Redis, without making it a full-blown integration test. Miniredis implements (parts of) the Redis server, to be used in unittests. It enables a simple, cheap, in-memory, Redis replacement, with a real TCP interface. Think of it as the Redis version of net/http/httptest.

It saves you from using mock code, and since the redis server lives in the test process you can query for values directly, without going through the server stack.

There are no dependencies on external binaries, so you can easily integrate it in automated build processes.

Changelog

2.5.0

Added ZPopMin and ZPopMax

v2.4.6

support for TIME (thanks @leon-barrett and @lirao) support for ZREVRANGEBYLEX fix for SINTER (thanks @robstein) updates for latest redis

2.4.4

Fixed nil Lua return value (#43)

2.4.3

Fixed using Lua with authenticated redis.

2.4.2

Changed redigo import path.

2.4

Minor cleanups. Miniredis now requires Go >= 1.9 (only for the tests. If you don't run the tests you can use an older Go version).

2.3.1

Lua changes: added cjson library, and redis.sha1hex().

2.3

Added the EVAL, EVALSHA, and SCRIPT commands. Uses a pure Go Lua interpreter. Please open an issue if there are problems with any Lua code.

2.2

Introduced StartAddr().

2.1

Internal cleanups. No changes in functionality.

2.0

2.0.0 improves TTLs to be time.Duration values. .Expire() is removed and replaced by .TTL(), which returns the TTL as a time.Duration. This should be the change needed to upgrade:

1.0:

m.Expire() == 4

2.0:

m.TTL() == 4 * time.Second

Furthermore, .SetTime() is added to help with EXPIREAT commands, and .FastForward() is introduced to test keys expiration.

Commands

Implemented commands:

  • Connection (complete)
    • AUTH -- see RequireAuth()
    • ECHO
    • PING
    • SELECT
    • QUIT
  • Key
    • DEL
    • EXISTS
    • EXPIRE
    • EXPIREAT
    • KEYS
    • MOVE
    • PERSIST
    • PEXPIRE
    • PEXPIREAT
    • PTTL
    • RENAME
    • RENAMENX
    • RANDOMKEY -- call math.rand.Seed(...) once before using.
    • TTL
    • TYPE
    • SCAN
  • Transactions (complete)
    • DISCARD
    • EXEC
    • MULTI
    • UNWATCH
    • WATCH
  • Server
    • DBSIZE
    • FLUSHALL
    • FLUSHDB
    • TIME -- returns time.Now() or value set by SetTime()
  • String keys (complete)
    • APPEND
    • BITCOUNT
    • BITOP
    • BITPOS
    • DECR
    • DECRBY
    • GET
    • GETBIT
    • GETRANGE
    • GETSET
    • INCR
    • INCRBY
    • INCRBYFLOAT
    • MGET
    • MSET
    • MSETNX
    • PSETEX
    • SET
    • SETBIT
    • SETEX
    • SETNX
    • SETRANGE
    • STRLEN
  • Hash keys (complete)
    • HDEL
    • HEXISTS
    • HGET
    • HGETALL
    • HINCRBY
    • HINCRBYFLOAT
    • HKEYS
    • HLEN
    • HMGET
    • HMSET
    • HSET
    • HSETNX
    • HVALS
    • HSCAN
  • List keys (complete)
    • BLPOP
    • BRPOP
    • BRPOPLPUSH
    • LINDEX
    • LINSERT
    • LLEN
    • LPOP
    • LPUSH
    • LPUSHX
    • LRANGE
    • LREM
    • LSET
    • LTRIM
    • RPOP
    • RPOPLPUSH
    • RPUSH
    • RPUSHX
  • Set keys (complete)
    • SADD
    • SCARD
    • SDIFF
    • SDIFFSTORE
    • SINTER
    • SINTERSTORE
    • SISMEMBER
    • SMEMBERS
    • SMOVE
    • SPOP -- call math.rand.Seed(...) once before using.
    • SRANDMEMBER -- call math.rand.Seed(...) once before using.
    • SREM
    • SUNION
    • SUNIONSTORE
    • SSCAN
  • Sorted Set keys (complete)
    • ZADD
    • ZCARD
    • ZCOUNT
    • ZINCRBY
    • ZINTERSTORE
    • ZLEXCOUNT
    • ZPOPMIN
    • ZPOPMAX
    • ZRANGE
    • ZRANGEBYLEX
    • ZRANGEBYSCORE
    • ZRANK
    • ZREM
    • ZREMRANGEBYLEX
    • ZREMRANGEBYRANK
    • ZREMRANGEBYSCORE
    • ZREVRANGE
    • ZREVRANGEBYLEX
    • ZREVRANGEBYSCORE
    • ZREVRANK
    • ZSCORE
    • ZUNIONSTORE
    • ZSCAN
  • Scripting
    • EVAL
    • EVALSHA
    • SCRIPT LOAD
    • SCRIPT EXISTS
    • SCRIPT FLUSH

TTLs, key expiration, and time

Since miniredis is intended to be used in unittests TTLs don't decrease automatically. You can use TTL() to get the TTL (as a time.Duration) of a key. It will return 0 when no TTL is set.

m.FastForward(d) can be used to decrement all TTLs. All TTLs which become <= 0 will be removed.

EXPIREAT and PEXPIREAT values will be converted to a duration. For that you can either set m.SetTime(t) to use that time as the base for the (P)EXPIREAT conversion, or don't call SetTime(), in which case time.Now() will be used.

SetTime() also sets the value returned by TIME, which defaults to time.Now(). It is not updated by FastForward, only by SetTime.

Example

func TestSomething(t *testing.T) {
	s, err := miniredis.Run()
	if err != nil {
		panic(err)
	}
	defer s.Close()

	// Optionally set some keys your code expects:
	s.Set("foo", "bar")
	s.HSet("some", "other", "key")

	// Run your code and see if it behaves.
	// An example using the redigo library from "github.com/gomodule/redigo/redis":
	c, err := redis.Dial("tcp", s.Addr())
	_, err = c.Do("SET", "foo", "bar")

	// Optionally check values in redis...
	if got, err := s.Get("foo"); err != nil || got != "bar" {
		t.Error("'foo' has the wrong value")
	}
	// ... or use a helper for that:
	s.CheckGet(t, "foo", "bar")

	// TTL and expiration:
	s.Set("foo", "bar")
	s.SetTTL("foo", 10*time.Second)
	s.FastForward(11 * time.Second)
	if s.Exists("foo") {
		t.Fatal("'foo' should not have existed anymore")
	}
}

Not supported

Commands which will probably not be implemented:

  • CLUSTER (all)
    • CLUSTER *
    • READONLY
    • READWRITE
  • GEO (all) -- unless someone needs these
    • GEOADD
    • GEODIST
    • GEOHASH
    • GEOPOS
    • GEORADIUS
    • GEORADIUSBYMEMBER
  • HyperLogLog (all) -- unless someone needs these
    • PFADD
    • PFCOUNT
    • PFMERGE
  • Key
    • DUMP
    • MIGRATE
    • OBJECT
    • RESTORE
    • WAIT
  • Pub/Sub (all)
    • PSUBSCRIBE
    • PUBLISH
    • PUBSUB
    • PUNSUBSCRIBE
    • SUBSCRIBE
    • UNSUBSCRIBE
  • Scripting
    • SCRIPT DEBUG
    • SCRIPT KILL
  • Server
    • BGSAVE
    • BGWRITEAOF
    • CLIENT *
    • COMMAND *
    • CONFIG *
    • DEBUG *
    • INFO
    • LASTSAVE
    • MONITOR
    • ROLE
    • SAVE
    • SHUTDOWN
    • SLAVEOF
    • SLOWLOG
    • SYNC

&c.

Tests are run against Redis 5.0.3. The ./integration subdir compares miniredis against a real redis instance.

Build Status GoDoc

Documentation

Overview

Package miniredis is a pure Go Redis test server, for use in Go unittests. There are no dependencies on system binaries, and every server you start will be empty.

Start a server with `s, err := miniredis.Run()`. Stop it with `defer s.Close()`.

Point your Redis client to `s.Addr()` or `s.Host(), s.Port()`.

Set keys directly via s.Set(...) and similar commands, or use a Redis client.

For direct use you can select a Redis database with either `s.Select(12); s.Get("foo")` or `s.DB(12).Get("foo")`.

Example
package main

import (
	"time"

	"github.com/alicebob/miniredis"
	"github.com/gomodule/redigo/redis"
)

func main() {
	s, err := miniredis.Run()
	if err != nil {
		panic(err)
	}
	defer s.Close()

	// Configure you application to connect to redis at s.Addr()
	// Any redis client should work, as long as you use redis commands which
	// miniredis implements.
	c, err := redis.Dial("tcp", s.Addr())
	if err != nil {
		panic(err)
	}
	if _, err = c.Do("SET", "foo", "bar"); err != nil {
		panic(err)
	}

	// You can ask miniredis about keys directly, without going over the network.
	if got, err := s.Get("foo"); err != nil || got != "bar" {
		panic("Didn't get 'bar' back")
	}
	// Or with a DB id
	if _, err := s.DB(42).Get("foo"); err != miniredis.ErrKeyNotFound {
		panic("didn't use a different database")
	}

	// Test key with expiration
	s.SetTTL("foo", 60*time.Second)
	s.FastForward(60 * time.Second)
	if s.Exists("foo") {
		panic("expect key to be expired")
	}

	// Or use a Check* function which Fail()s if the key is not what we expect
	// (checks for existence, key type and the value)
	// s.CheckGet(t, "foo", "bar")

	// Check if there really was only one connection.
	if s.TotalConnectionCount() != 1 {
		panic("too many connections made")
	}

}
Output:

Index

Examples

Constants

This section is empty.

Variables

View Source
var (
	// ErrKeyNotFound is returned when a key doesn't exist.
	ErrKeyNotFound = errors.New(msgKeyNotFound)
	// ErrWrongType when a key is not the right type.
	ErrWrongType = errors.New(msgWrongType)
	// ErrIntValueError can returned by INCRBY
	ErrIntValueError = errors.New(msgInvalidInt)
	// ErrFloatValueError can returned by INCRBYFLOAT
	ErrFloatValueError = errors.New(msgInvalidFloat)
)

Functions

This section is empty.

Types

type Miniredis

type Miniredis struct {
	sync.Mutex
	// contains filtered or unexported fields
}

Miniredis is a Redis server implementation.

func NewMiniRedis

func NewMiniRedis() *Miniredis

NewMiniRedis makes a new, non-started, Miniredis object.

func Run

func Run() (*Miniredis, error)

Run creates and Start()s a Miniredis.

func (*Miniredis) Addr

func (m *Miniredis) Addr() string

Addr returns '127.0.0.1:12345'. Can be given to a Dial(). See also Host() and Port(), which return the same things.

func (*Miniredis) CheckGet

func (m *Miniredis) CheckGet(t T, key, expected string)

CheckGet does not call Errorf() iff there is a string key with the expected value. Normal use case is `m.CheckGet(t, "username", "theking")`.

func (*Miniredis) CheckList

func (m *Miniredis) CheckList(t T, key string, expected ...string)

CheckList does not call Errorf() iff there is a list key with the expected values. Normal use case is `m.CheckGet(t, "favorite_colors", "red", "green", "infrared")`.

func (*Miniredis) CheckSet

func (m *Miniredis) CheckSet(t T, key string, expected ...string)

CheckSet does not call Errorf() iff there is a set key with the expected values. Normal use case is `m.CheckSet(t, "visited", "Rome", "Stockholm", "Dublin")`.

func (*Miniredis) Close

func (m *Miniredis) Close()

Close shuts down a Miniredis.

func (*Miniredis) CommandCount

func (m *Miniredis) CommandCount() int

CommandCount returns the number of processed commands.

func (*Miniredis) CurrentConnectionCount

func (m *Miniredis) CurrentConnectionCount() int

CurrentConnectionCount returns the number of currently connected clients.

func (*Miniredis) DB

func (m *Miniredis) DB(i int) *RedisDB

DB returns a DB by ID.

func (*Miniredis) Del

func (m *Miniredis) Del(k string) bool

Del deletes a key and any expiration value. Returns whether there was a key.

func (*Miniredis) Dump

func (m *Miniredis) Dump() string

Dump returns a text version of the selected DB, usable for debugging.

func (*Miniredis) Exists

func (m *Miniredis) Exists(k string) bool

Exists tells whether a key exists.

func (*Miniredis) FastForward

func (m *Miniredis) FastForward(duration time.Duration)

FastForward decreases all TTLs by the given duration. All TTLs <= 0 will be expired.

func (*Miniredis) FlushAll

func (m *Miniredis) FlushAll()

FlushAll removes all keys from all databases.

func (*Miniredis) FlushDB

func (m *Miniredis) FlushDB()

FlushDB removes all keys from the selected database.

func (*Miniredis) Get

func (m *Miniredis) Get(k string) (string, error)

Get returns string keys added with SET.

func (*Miniredis) HDel

func (m *Miniredis) HDel(k, f string)

HDel deletes a hash key.

func (*Miniredis) HGet

func (m *Miniredis) HGet(k, f string) string

HGet returns hash keys added with HSET. This will return an empty string if the key is not set. Redis would return a nil. Returns empty string when the key is of a different type.

func (*Miniredis) HIncr

func (m *Miniredis) HIncr(k, f string, delta int) (int, error)

HIncr increases a key/field by delta (int).

func (*Miniredis) HIncrfloat

func (m *Miniredis) HIncrfloat(k, f string, delta float64) (float64, error)

HIncrfloat increases a key/field by delta (float).

func (*Miniredis) HKeys

func (m *Miniredis) HKeys(k string) ([]string, error)

HKeys returns all (sorted) keys ('fields') for a hash key.

func (*Miniredis) HSet

func (m *Miniredis) HSet(k, f, v string)

HSet sets a hash key. If there is another key by the same name it will be gone.

func (*Miniredis) Host

func (m *Miniredis) Host() string

Host returns the host part of Addr().

func (*Miniredis) Incr

func (m *Miniredis) Incr(k string, delta int) (int, error)

Incr changes a int string value by delta.

func (*Miniredis) Incrfloat

func (m *Miniredis) Incrfloat(k string, delta float64) (float64, error)

Incrfloat changes a float string value by delta.

func (*Miniredis) IsMember

func (m *Miniredis) IsMember(k, v string) (bool, error)

IsMember tells if value is in the set.

func (*Miniredis) Keys

func (m *Miniredis) Keys() []string

Keys returns all keys from the selected database, sorted.

func (*Miniredis) List

func (m *Miniredis) List(k string) ([]string, error)

List returns the list k, or an error if it's not there or something else. This is the same as the Redis command `LRANGE 0 -1`, but you can do your own range-ing.

func (*Miniredis) Lpop

func (m *Miniredis) Lpop(k string) (string, error)

Lpop is a shift. Returns the popped element.

func (*Miniredis) Lpush

func (m *Miniredis) Lpush(k, v string) (int, error)

Lpush is an unshift. Returns the new length.

func (*Miniredis) Members

func (m *Miniredis) Members(k string) ([]string, error)

Members gives all set keys. Sorted.

func (*Miniredis) Pop

func (m *Miniredis) Pop(k string) (string, error)

Pop removes and returns the last element. Is called RPOP in Redis.

func (*Miniredis) Port

func (m *Miniredis) Port() string

Port returns the (random) port part of Addr().

func (*Miniredis) Push

func (m *Miniredis) Push(k string, v ...string) (int, error)

Push add element at the end. Is called RPUSH in redis. Returns the new length.

func (*Miniredis) RequireAuth

func (m *Miniredis) RequireAuth(pw string)

RequireAuth makes every connection need to AUTH first. Disable again by setting an empty string.

func (*Miniredis) Restart

func (m *Miniredis) Restart() error

Restart restarts a Close()d server on the same port. Values will be preserved.

func (*Miniredis) SRem

func (m *Miniredis) SRem(k string, fields ...string) (int, error)

SRem removes fields from a set. Returns number of deleted fields.

func (*Miniredis) Select

func (m *Miniredis) Select(i int)

Select sets the DB id for all direct commands.

func (*Miniredis) Set

func (m *Miniredis) Set(k, v string) error

Set sets a string key. Removes expire.

func (*Miniredis) SetAdd

func (m *Miniredis) SetAdd(k string, elems ...string) (int, error)

SetAdd adds keys to a set. Returns the number of new keys.

func (*Miniredis) SetTTL

func (m *Miniredis) SetTTL(k string, ttl time.Duration)

SetTTL sets the TTL of a key.

func (*Miniredis) SetTime

func (m *Miniredis) SetTime(t time.Time)

SetTime sets the time against which EXPIREAT values are compared. EXPIREAT will use time.Now() if this is not set.

func (*Miniredis) SortedSet

func (m *Miniredis) SortedSet(k string) (map[string]float64, error)

SortedSet returns a raw string->float64 map.

func (*Miniredis) Start

func (m *Miniredis) Start() error

Start starts a server. It listens on a random port on localhost. See also Addr().

func (*Miniredis) StartAddr

func (m *Miniredis) StartAddr(addr string) error

StartAddr runs miniredis with a given addr. Examples: "127.0.0.1:6379", ":6379", or "127.0.0.1:0"

func (*Miniredis) TTL

func (m *Miniredis) TTL(k string) time.Duration

TTL is the left over time to live. As set via EXPIRE, PEXPIRE, EXPIREAT, PEXPIREAT. 0 if not set.

func (*Miniredis) TotalConnectionCount

func (m *Miniredis) TotalConnectionCount() int

TotalConnectionCount returns the number of client connections since server start.

func (*Miniredis) Type

func (m *Miniredis) Type(k string) string

Type gives the type of a key, or ""

func (*Miniredis) ZAdd

func (m *Miniredis) ZAdd(k string, score float64, member string) (bool, error)

ZAdd adds a score,member to a sorted set.

func (*Miniredis) ZMembers

func (m *Miniredis) ZMembers(k string) ([]string, error)

ZMembers returns all members by score

func (*Miniredis) ZRem

func (m *Miniredis) ZRem(k, member string) (bool, error)

ZRem deletes a member. Returns whether the was a key.

func (*Miniredis) ZScore

func (m *Miniredis) ZScore(k, member string) (float64, error)

ZScore gives the score of a sorted set member.

type RedisDB

type RedisDB struct {
	// contains filtered or unexported fields
}

RedisDB holds a single (numbered) Redis database.

func (*RedisDB) Del

func (db *RedisDB) Del(k string) bool

Del deletes a key and any expiration value. Returns whether there was a key.

func (*RedisDB) Exists

func (db *RedisDB) Exists(k string) bool

Exists tells whether a key exists.

func (*RedisDB) FlushDB

func (db *RedisDB) FlushDB()

FlushDB removes all keys.

func (*RedisDB) Get

func (db *RedisDB) Get(k string) (string, error)

Get returns a string key.

func (*RedisDB) HDel

func (db *RedisDB) HDel(k, f string)

HDel deletes a hash key.

func (*RedisDB) HGet

func (db *RedisDB) HGet(k, f string) string

HGet returns hash keys added with HSET. Returns empty string when the key is of a different type.

func (*RedisDB) HIncr

func (db *RedisDB) HIncr(k, f string, delta int) (int, error)

HIncr increases a key/field by delta (int).

func (*RedisDB) HIncrfloat

func (db *RedisDB) HIncrfloat(k, f string, delta float64) (float64, error)

HIncrfloat increases a key/field by delta (float).

func (*RedisDB) HKeys

func (db *RedisDB) HKeys(key string) ([]string, error)

HKeys returns all (sorted) keys ('fields') for a hash key.

func (*RedisDB) HSet

func (db *RedisDB) HSet(k, f, v string)

HSet sets a hash key. If there is another key by the same name it will be gone.

func (*RedisDB) Incr

func (db *RedisDB) Incr(k string, delta int) (int, error)

Incr changes a int string value by delta.

func (*RedisDB) Incrfloat

func (db *RedisDB) Incrfloat(k string, delta float64) (float64, error)

Incrfloat changes a float string value by delta.

func (*RedisDB) IsMember

func (db *RedisDB) IsMember(k, v string) (bool, error)

IsMember tells if value is in the set.

func (*RedisDB) Keys

func (db *RedisDB) Keys() []string

Keys returns all keys, sorted.

func (*RedisDB) List

func (db *RedisDB) List(k string) ([]string, error)

List returns the list k, or an error if it's not there or something else. This is the same as the Redis command `LRANGE 0 -1`, but you can do your own range-ing.

func (*RedisDB) Lpop

func (db *RedisDB) Lpop(k string) (string, error)

Lpop is a shift. Returns the popped element.

func (*RedisDB) Lpush

func (db *RedisDB) Lpush(k, v string) (int, error)

Lpush is an unshift. Returns the new length.

func (*RedisDB) Members

func (db *RedisDB) Members(k string) ([]string, error)

Members gives all set keys. Sorted.

func (*RedisDB) Pop

func (db *RedisDB) Pop(k string) (string, error)

Pop removes and returns the last element. Is called RPOP in Redis.

func (*RedisDB) Push

func (db *RedisDB) Push(k string, v ...string) (int, error)

Push add element at the end. Is called RPUSH in redis. Returns the new length.

func (*RedisDB) SRem

func (db *RedisDB) SRem(k string, fields ...string) (int, error)

SRem removes fields from a set. Returns number of deleted fields.

func (*RedisDB) Set

func (db *RedisDB) Set(k, v string) error

Set sets a string key. Removes expire. Unlike redis the key can't be an existing non-string key.

func (*RedisDB) SetAdd

func (db *RedisDB) SetAdd(k string, elems ...string) (int, error)

SetAdd adds keys to a set. Returns the number of new keys.

func (*RedisDB) SetTTL

func (db *RedisDB) SetTTL(k string, ttl time.Duration)

SetTTL sets the time to live of a key.

func (*RedisDB) SortedSet

func (db *RedisDB) SortedSet(k string) (map[string]float64, error)

SortedSet returns a raw string->float64 map.

func (*RedisDB) TTL

func (db *RedisDB) TTL(k string) time.Duration

TTL is the left over time to live. As set via EXPIRE, PEXPIRE, EXPIREAT, PEXPIREAT. 0 if not set.

func (*RedisDB) Type

func (db *RedisDB) Type(k string) string

Type gives the type of a key, or ""

func (*RedisDB) ZAdd

func (db *RedisDB) ZAdd(k string, score float64, member string) (bool, error)

ZAdd adds a score,member to a sorted set.

func (*RedisDB) ZMembers

func (db *RedisDB) ZMembers(k string) ([]string, error)

ZMembers returns all members by score

func (*RedisDB) ZRem

func (db *RedisDB) ZRem(k, member string) (bool, error)

ZRem deletes a member. Returns whether the was a key.

func (*RedisDB) ZScore

func (db *RedisDB) ZScore(k, member string) (float64, error)

ZScore gives the score of a sorted set member.

type T

type T interface {
	Fail()
}

T is implemented by Testing.T

Directories

Path Synopsis

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL