func MemcachedServerProcessSpecs(c gospec.Context) {
	logger := log4go.NewDefaultLogger(log4go.CRITICAL)

	c.Specify("[MemcachedServerProcess] Starts a new Memcached-Server", func() {
		server, err := StartMemcachedServer(&logger)
		defer server.Close()

		c.Expect(err, gospec.Equals, nil)
		c.Expect(server, gospec.Satisfies, server != nil)
		c.Expect(server.logger, gospec.Equals, &logger)
		c.Expect(server.port, gospec.Satisfies, server.port >= 1024)
		c.Expect(server.cmd, gospec.Satisfies, nil != server.cmd)
		c.Expect(server.connection, gospec.Satisfies, nil == server.connection)
	})

	c.Specify("[MemcachedServerProcess] Creates a connection to a Memcached-Server", func() {
		server, err := StartMemcachedServer(&logger)
		defer server.Close()

		c.Expect(err, gospec.Equals, nil)
		c.Expect(server, gospec.Satisfies, server != nil)

		connection := server.Connection()
		c.Expect(connection, gospec.Satisfies, nil != connection)
		c.Expect(server.connection, gospec.Equals, connection)

		err = connection.Open()
		c.Expect(err, gospec.Equals, nil)
		c.Expect(connection.IsOpen(), gospec.Equals, true)
	})
}
Exemplo n.º 2
0
//
// Benchmark Bit Operation A & !B on 10x keys
//
func Benchmark_BitOp_ComplementSet_BatchCommands(b *testing.B) {
	logger := log4go.NewDefaultLogger(log4go.CRITICAL)
	server, err := StartRedisServer(&logger)
	if nil != err {
		panic(err)
	}
	defer server.Close()

	keys_all := [][]string{make([]string, 10), make([]string, 10)}
	keys_bob := [][]string{make([]string, 10), make([]string, 10)}
	keys_not_bob := [][]string{make([]string, 10), make([]string, 10)}
	keys_gary := [][]string{make([]string, 10), make([]string, 10)}
	keys_not_gary := [][]string{make([]string, 10), make([]string, 10)}
	for i := 0; i < 10; i++ {
		for j := 0; j <= 1; j++ {
			keys_all[j][i] = fmt.Sprintf("ALL:%d:%d", j, i)
			keys_bob[j][i] = fmt.Sprintf("BOB:%d:%d", j, i)
			keys_not_bob[j][i] = fmt.Sprintf("Not-BOB:%d:%d", j, i)
			keys_gary[j][i] = fmt.Sprintf("GARY:%d:%d", j, i)
			keys_not_gary[j][i] = fmt.Sprintf("Not-GARY:%d:%d", j, i)
		}
	}

	for i := 0; i < 1024; i++ {
		for j := 0; j < 10; j++ {
			for k := 0; k <= 1; k++ {
				server.Connection().Cmd("SETBIT", keys_all[k][j], i, true)
				server.Connection().Cmd("SETBIT", keys_bob[k][j], i, i%2 == 0)
				server.Connection().Cmd("SETBIT", keys_not_bob[k][j], i, i%2 == 1)
				server.Connection().Cmd("SETBIT", keys_gary[k][j], i, i%4 == 0)
				server.Connection().Cmd("SETBIT", keys_not_gary[k][j], i, i%4 == 0)
			}
		}
	}

	cmds := RedisBatchCommands{
		MakeRedisBatchCommandBitopAnd("ALL:0", keys_all[0]...),
		MakeRedisBatchCommandBitopAnd("ALL:1", keys_all[1]...),
		MakeRedisBatchCommandBitopAnd("BOB:0", keys_bob[0]...),
		MakeRedisBatchCommandBitopAnd("BOB:1", keys_bob[1]...),
		MakeRedisBatchCommandBitopAnd("Not-BOB:0", keys_not_bob[0]...),
		MakeRedisBatchCommandBitopAnd("Not-BOB:1", keys_not_bob[1]...),
		MakeRedisBatchCommandBitopAnd("GARY:0", keys_gary[0]...),
		MakeRedisBatchCommandBitopAnd("GARY:1", keys_gary[1]...),
		MakeRedisBatchCommandBitopAnd("Not-GARY:0", keys_not_gary[0]...),
		MakeRedisBatchCommandBitopOr("Not-GARY:1", keys_not_gary[1]...),
		MakeRedisBatchCommandBitopNot("Not-GARY:1", "Not-GARY:1"),
		MakeRedisBatchCommandBitopAnd("Complement", "Not-GARY:1", "ALL:0", "ALL:1", "BOB:0", "BOB:1", "Not-BOB:0", "Not-BOB:1", "GARY:0", "GARY:1", "Not-GARY:0"),
	}
	for _, key := range []string{"Complement", "Not-GARY:1", "ALL:0", "ALL:1", "BOB:0", "BOB:1", "Not-BOB:0", "Not-BOB:1", "GARY:0", "GARY:1", "Not-GARY:0"} {
		cmds = append(cmds, MakeRedisBatchCommandBitCount(key))
	}
	cmds = append(cmds, MakeRedisBatchCommandGet("Complement"))

	b.ResetTimer()
	for i := 0; i < b.N; i++ {
		cmds.ExecuteBatch(server.Connection())
	}
}
Exemplo n.º 3
0
func Benchmark_Del_CacheMiss_RedisConnection(b *testing.B) {
	logger := log4go.NewDefaultLogger(log4go.CRITICAL)
	server, err := StartRedisServer(&logger)
	if nil != err {
		panic(err)
	}
	defer server.Close()

	b.ResetTimer()
	for i := 0; i < b.N; i++ {
		server.Connection().Cmd("DEL", "BOB", "Hello", "World", "GARY", "THE", "SNAIL")
	}
}
Exemplo n.º 4
0
func Benchmark_Set_RedisConnection(b *testing.B) {
	logger := log4go.NewDefaultLogger(log4go.CRITICAL)
	server, err := StartRedisServer(&logger)
	if nil != err {
		panic(err)
	}
	defer server.Close()

	b.ResetTimer()
	for i := 0; i < b.N; i++ {
		server.Connection().Cmd("SET", "BOB", "Hello")
	}
}
Exemplo n.º 5
0
func Benchmark_MemcachedConnection_Set(b *testing.B) {
	logger := log4go.NewDefaultLogger(log4go.CRITICAL)
	server, err := StartMemcachedServer(&logger)
	if nil != err {
		panic(err)
	}
	defer server.Close()

	b.ResetTimer()
	for i := 0; i < b.N; i++ {
		server.Connection().Set(&memcached.Item{Key: "BOB", Value: []byte("Hello")})
	}
}
Exemplo n.º 6
0
func Benchmark_Bit_Get_RedisConnection(b *testing.B) {
	logger := log4go.NewDefaultLogger(log4go.CRITICAL)
	server, err := StartRedisServer(&logger)
	if nil != err {
		panic(err)
	}
	defer server.Close()

	for i := 0; i < 1024; i++ {
		server.Connection().Cmd("SETBIT", "ALL", i, true)
	}

	b.ResetTimer()
	for i := 0; i < b.N; i++ {
		server.Connection().Cmd("GET", "ALL")
	}
}
Exemplo n.º 7
0
func Benchmark_BitOp_Not_RedisConnection(b *testing.B) {
	logger := log4go.NewDefaultLogger(log4go.CRITICAL)
	server, err := StartRedisServer(&logger)
	if nil != err {
		panic(err)
	}
	defer server.Close()

	for i := 0; i < 1024; i++ {
		server.Connection().Cmd("SETBIT", "ALL", i, true)
		server.Connection().Cmd("SETBIT", "BOB", i, i%2 == 0)
		server.Connection().Cmd("SETBIT", "Not-BOB", i, i%2 == 1)
		server.Connection().Cmd("SETBIT", "GARY", i, i%4 == 0)
	}

	b.ResetTimer()
	for i := 0; i < b.N; i++ {
		server.Connection().Cmd("BITOP", "NOT", "ALL", "BOB", "Not-BOB", "GARY", "Cache-Miss")
	}
}
Exemplo n.º 8
0
// Pre-format the commands as a single string, and compare the results to above
func Benchmark_BitOp_ComplementSet_RedisConnection(b *testing.B) {
	logger := log4go.NewDefaultLogger(log4go.CRITICAL)
	server, err := StartRedisServer(&logger)
	if nil != err {
		panic(err)
	}
	defer server.Close()

	keys_all := [][]string{make([]string, 10), make([]string, 10)}
	keys_bob := [][]string{make([]string, 10), make([]string, 10)}
	keys_not_bob := [][]string{make([]string, 10), make([]string, 10)}
	keys_gary := [][]string{make([]string, 10), make([]string, 10)}
	keys_not_gary := [][]string{make([]string, 10), make([]string, 10)}
	for i := 0; i < 10; i++ {
		for j := 0; j <= 1; j++ {
			keys_all[j][i] = fmt.Sprintf("ALL:%d:%d", j, i)
			keys_bob[j][i] = fmt.Sprintf("BOB:%d:%d", j, i)
			keys_not_bob[j][i] = fmt.Sprintf("Not-BOB:%d:%d", j, i)
			keys_gary[j][i] = fmt.Sprintf("GARY:%d:%d", j, i)
			keys_not_gary[j][i] = fmt.Sprintf("Not-GARY:%d:%d", j, i)
		}
	}

	for i := 0; i < 1024; i++ {
		for j := 0; j < 10; j++ {
			for k := 0; k <= 1; k++ {
				server.Connection().Cmd("SETBIT", keys_all[k][j], i, true)
				server.Connection().Cmd("SETBIT", keys_bob[k][j], i, i%2 == 0)
				server.Connection().Cmd("SETBIT", keys_not_bob[k][j], i, i%2 == 1)
				server.Connection().Cmd("SETBIT", keys_gary[k][j], i, i%4 == 0)
				server.Connection().Cmd("SETBIT", keys_not_gary[k][j], i, i%4 == 0)
			}
		}
	}

	b.ResetTimer()
	for i := 0; i < b.N; i++ {
		server.Connection().Cmd("BITOP AND ALL:0 %s", keys_all[0])
		server.Connection().Cmd("BITOP AND ALL:1 %s", keys_all[1])
		server.Connection().Cmd("BITOP AND BOB:0 %s", keys_bob[0])
		server.Connection().Cmd("BITOP AND BOB:1 %s", keys_bob[1])
		server.Connection().Cmd("BITOP AND Not-BOB:0 %s", keys_not_bob[0])
		server.Connection().Cmd("BITOP AND Not-BOB:1 %s", keys_not_bob[1])
		server.Connection().Cmd("BITOP AND GARY:0 %s", keys_gary[0])
		server.Connection().Cmd("BITOP AND GARY:1 %s", keys_gary[1])
		server.Connection().Cmd("BITOP AND Not-GARY:0 %s", keys_not_gary[0])
		server.Connection().Cmd("BITOP AND Not-GARY:0 %s", keys_not_gary[0])
		server.Connection().Cmd("BITOP OR Not-GARY:1 %s", keys_not_gary[1])

		server.Connection().Cmd("BITOP", "NOT", "Not-GARY:1", "Not-GARY:1")
		server.Connection().Cmd("BITOP", "AND", "Complement", "Not-GARY:1", "ALL:0", "ALL:1", "BOB:0", "BOB:1", "Not-BOB:0", "Not-BOB:1", "GARY:0", "GARY:1", "Not-GARY:0")
		server.Connection().Cmd("BITCOUNT", "Complement")
		server.Connection().Cmd("BITCOUNT", "Not-GARY:1")
		server.Connection().Cmd("BITCOUNT", "ALL:0")
		server.Connection().Cmd("BITCOUNT", "ALL:1")
		server.Connection().Cmd("BITCOUNT", "BOB:0")
		server.Connection().Cmd("BITCOUNT", "BOB:1")
		server.Connection().Cmd("BITCOUNT", "Not-BOB:0")
		server.Connection().Cmd("BITCOUNT", "Not-BOB:1")
		server.Connection().Cmd("BITCOUNT", "GARY:0")
		server.Connection().Cmd("BITCOUNT", "GARY:1")
		server.Connection().Cmd("BITCOUNT", "Not-GARY:0")
		server.Connection().Cmd("GET", "Complement")
	}
}
Exemplo n.º 9
0
// Helpers
func ReplyToSpecs(c gospec.Context) {

	c.Specify("[ReplyToBool] returns boolean or error", func() {
		logger := log4go.NewDefaultLogger(log4go.CRITICAL)
		server, err := StartRedisServer(&logger)
		if nil != err {
			panic(err)
		}
		defer server.Close()

		// Cache Miss
		reply := server.Connection().Cmd("EXISTS", "Bob")
		c.Expect(reply.Err, gospec.Equals, nil)
		c.Expect(reply, gospec.Satisfies, nil != reply)
		c.Expect(reply.Type, gospec.Equals, redis.IntegerReply)

		value, value_err := ReplyToBool(reply)
		c.Expect(value_err, gospec.Equals, nil)
		c.Expect(value, gospec.Equals, false)

		// Cache Hit
		server.Connection().Cmd("SET", "Bob", "George")
		reply = server.Connection().Cmd("EXISTS", "Bob")
		c.Expect(reply.Err, gospec.Equals, nil)
		c.Expect(reply, gospec.Satisfies, nil != reply)
		c.Expect(reply.Type, gospec.Equals, redis.IntegerReply)

		value, value_err = ReplyToBool(reply)
		c.Expect(value_err, gospec.Equals, nil)
		c.Expect(value, gospec.Equals, true)

		// Parsing Error
		reply = server.Connection().Cmd("MGET", "Bob")
		c.Expect(reply.Err, gospec.Equals, nil)
		c.Expect(reply, gospec.Satisfies, nil != reply)
		c.Expect(reply.Type, gospec.Equals, redis.MultiReply)

		value, value_err = ReplyToBool(reply)
		c.Expect(value_err, gospec.Satisfies, nil != value_err)
		c.Expect(value, gospec.Equals, false)
	})

	c.Specify("[ReplyToInt64Ptr] returns *int64 or error", func() {
		logger := log4go.NewDefaultLogger(log4go.CRITICAL)
		server, err := StartRedisServer(&logger)
		if nil != err {
			panic(err)
		}
		defer server.Close()

		// Cache Miss
		reply := server.Connection().Cmd("GET", "Bob")
		c.Expect(reply.Err, gospec.Equals, nil)
		c.Expect(reply, gospec.Satisfies, nil != reply)
		c.Expect(reply.Type, gospec.Equals, redis.NilReply)

		value, value_err := ReplyToInt64Ptr(reply)
		c.Expect(value_err, gospec.Equals, nil)
		c.Expect(value, gospec.Satisfies, nil == value)

		// Cache Hit --> String
		server.Connection().Cmd("SET", "Bob", "123")
		reply = server.Connection().Cmd("GET", "Bob")
		c.Expect(reply.Err, gospec.Equals, nil)
		c.Expect(reply, gospec.Satisfies, nil != reply)
		c.Expect(reply.Type, gospec.Equals, redis.BulkReply)

		value, value_err = ReplyToInt64Ptr(reply)
		c.Expect(value_err, gospec.Equals, nil)
		c.Expect(value, gospec.Satisfies, nil != value)
		c.Expect(value, gospec.Satisfies, int64(123) == *value)

		// Cache Hit --> Integer
		reply = server.Connection().Cmd("INCRBY", "Bob", 1000)
		c.Expect(reply.Err, gospec.Equals, nil)
		c.Expect(reply, gospec.Satisfies, nil != reply)
		c.Expect(reply.Type, gospec.Equals, redis.IntegerReply)

		value, value_err = ReplyToInt64Ptr(reply)
		c.Expect(value_err, gospec.Equals, nil)
		c.Expect(value, gospec.Satisfies, nil != value)
		c.Expect(*value, gospec.Equals, int64(1123))

		// Cache Hit --> Integer
		reply = server.Connection().Cmd("DECRBY", "Bob", 1000)
		c.Expect(reply.Err, gospec.Equals, nil)
		c.Expect(reply, gospec.Satisfies, nil != reply)
		c.Expect(reply.Type, gospec.Equals, redis.IntegerReply)

		value, value_err = ReplyToInt64Ptr(reply)
		c.Expect(value_err, gospec.Equals, nil)
		c.Expect(value, gospec.Satisfies, nil != value)
		c.Expect(*value, gospec.Equals, int64(123))

		// Cache Hit --> Integer
		reply = server.Connection().Cmd("INCR", "Bob")
		c.Expect(reply.Err, gospec.Equals, nil)
		c.Expect(reply, gospec.Satisfies, nil != reply)
		c.Expect(reply.Type, gospec.Equals, redis.IntegerReply)

		value, value_err = ReplyToInt64Ptr(reply)
		c.Expect(value_err, gospec.Equals, nil)
		c.Expect(value, gospec.Satisfies, nil != value)
		c.Expect(*value, gospec.Equals, int64(124))

		// Cache Hit --> Integer
		reply = server.Connection().Cmd("DECR", "Bob")
		c.Expect(reply.Err, gospec.Equals, nil)
		c.Expect(reply, gospec.Satisfies, nil != reply)
		c.Expect(reply.Type, gospec.Equals, redis.IntegerReply)

		value, value_err = ReplyToInt64Ptr(reply)
		c.Expect(value_err, gospec.Equals, nil)
		c.Expect(value, gospec.Satisfies, nil != value)
		c.Expect(*value, gospec.Equals, int64(123))

		// Parsing Error
		reply = server.Connection().Cmd("MGET", "Bob")
		c.Expect(reply.Err, gospec.Equals, nil)
		c.Expect(reply, gospec.Satisfies, nil != reply)
		c.Expect(reply.Type, gospec.Equals, redis.MultiReply)

		value, value_err = ReplyToInt64Ptr(reply)
		c.Expect(value_err, gospec.Satisfies, nil != value_err)
		c.Expect(value, gospec.Satisfies, nil == value)
	})

	c.Specify("[ReplyToInt64Ptrs] returns []*int64 or error", func() {
		logger := log4go.NewDefaultLogger(log4go.CRITICAL)
		server, err := StartRedisServer(&logger)
		if nil != err {
			panic(err)
		}
		defer server.Close()

		// Invalid Reply Type

		// Cache Miss
		reply := server.Connection().Cmd("MGET", "Bob")
		c.Expect(reply.Err, gospec.Equals, nil)
		c.Expect(reply, gospec.Satisfies, nil != reply)
		c.Expect(reply.Type, gospec.Equals, redis.MultiReply)

		value, value_err := ReplyToInt64Ptrs(reply)
		c.Expect(value_err, gospec.Equals, nil)
		c.Expect(value, gospec.Satisfies, 1 == len(value))
		c.Expect(value[0], gospec.Satisfies, nil == value[0])

		// Cache Hit --> String
		server.Connection().Cmd("SET", "Bob", "123")
		reply = server.Connection().Cmd("MGET", "Bob")
		c.Expect(reply.Err, gospec.Equals, nil)
		c.Expect(reply, gospec.Satisfies, nil != reply)
		c.Expect(reply.Type, gospec.Equals, redis.MultiReply)
		c.Expect(len(reply.Elems), gospec.Equals, 1)
		c.Expect(reply.Elems[0].Type, gospec.Equals, redis.BulkReply)

		value, value_err = ReplyToInt64Ptrs(reply)
		c.Expect(value_err, gospec.Equals, nil)
		c.Expect(value, gospec.Satisfies, 1 == len(value))
		c.Expect(value[0], gospec.Satisfies, nil != value[0])
		c.Expect(value[0], gospec.Satisfies, int64(123) == *value[0])

		// Parsing Error
		reply = server.Connection().Cmd("GET", "Missing")
		c.Expect(reply.Err, gospec.Equals, nil)
		c.Expect(reply, gospec.Satisfies, nil != reply)
		c.Expect(reply.Type, gospec.Equals, redis.NilReply)

		value, value_err = ReplyToInt64Ptrs(reply)
		c.Expect(value_err, gospec.Satisfies, strings.HasPrefix(value_err.Error(), "Reply type is not MultiReply, "))
		c.Expect(value, gospec.Satisfies, 0 == len(value))

		// Parsing Error
		reply = server.Connection().Cmd("GET", "Bob")
		c.Expect(reply.Err, gospec.Equals, nil)
		c.Expect(reply, gospec.Satisfies, nil != reply)
		c.Expect(reply.Type, gospec.Equals, redis.BulkReply)

		value, value_err = ReplyToInt64Ptrs(reply)
		c.Expect(value_err, gospec.Satisfies, strings.HasPrefix(value_err.Error(), "Reply type is not MultiReply, "))
		c.Expect(value, gospec.Satisfies, 0 == len(value))
	})

	c.Specify("[ReplyToFloat64Ptr] returns *float64 or error", func() {
		logger := log4go.NewDefaultLogger(log4go.CRITICAL)
		server, err := StartRedisServer(&logger)
		if nil != err {
			panic(err)
		}
		defer server.Close()

		// Cache Miss
		reply := server.Connection().Cmd("GET", "Bob")
		c.Expect(reply.Err, gospec.Equals, nil)
		c.Expect(reply, gospec.Satisfies, nil != reply)
		c.Expect(reply.Type, gospec.Equals, redis.NilReply)

		value, value_err := ReplyToFloat64Ptr(reply)
		c.Expect(value_err, gospec.Equals, nil)
		c.Expect(value, gospec.Satisfies, nil == value)

		// Cache Hit --> String
		server.Connection().Cmd("SET", "Bob", "123.456")
		reply = server.Connection().Cmd("GET", "Bob")
		c.Expect(reply.Err, gospec.Equals, nil)
		c.Expect(reply, gospec.Satisfies, nil != reply)
		c.Expect(reply.Type, gospec.Equals, redis.BulkReply)

		value, value_err = ReplyToFloat64Ptr(reply)
		c.Expect(value_err, gospec.Equals, nil)
		c.Expect(value, gospec.Satisfies, nil != value)
		c.Expect(value, gospec.Satisfies, float64(123.456) == *value)

		// Cache Hit --> Float
		reply = server.Connection().Cmd("INCRBYFLOAT", "Bob", 1000.0)
		c.Expect(reply.Err, gospec.Equals, nil)
		c.Expect(reply, gospec.Satisfies, nil != reply)
		c.Expect(reply.Type, gospec.Equals, redis.BulkReply)

		value, value_err = ReplyToFloat64Ptr(reply)
		c.Expect(value_err, gospec.Equals, nil)
		c.Expect(value, gospec.Satisfies, nil != value)
		c.Expect(*value, gospec.Equals, float64(1123.456))

		// Cache Hit --> Integer
		server.Connection().Cmd("SET", "Bob", 123)
		reply = server.Connection().Cmd("INCR", "Bob")
		c.Expect(reply.Err, gospec.Equals, nil)
		c.Expect(reply, gospec.Satisfies, nil != reply)
		c.Expect(reply.Type, gospec.Equals, redis.IntegerReply)

		value, value_err = ReplyToFloat64Ptr(reply)
		c.Expect(value_err, gospec.Equals, nil)
		c.Expect(value, gospec.Satisfies, nil != value)
		c.Expect(*value, gospec.Equals, float64(123+1))

		// Parsing Error
		reply = server.Connection().Cmd("MGET", "Bob")
		c.Expect(reply.Err, gospec.Equals, nil)
		c.Expect(reply, gospec.Satisfies, nil != reply)
		c.Expect(reply.Type, gospec.Equals, redis.MultiReply)

		value, value_err = ReplyToFloat64Ptr(reply)
		c.Expect(value_err, gospec.Satisfies, nil != value_err)
		c.Expect(value, gospec.Satisfies, nil == value)
	})

	c.Specify("[ReplyToFloat64Ptrs] returns []*float64 or error", func() {
		logger := log4go.NewDefaultLogger(log4go.CRITICAL)
		server, err := StartRedisServer(&logger)
		if nil != err {
			panic(err)
		}
		defer server.Close()

		// Invalid Reply Type

		// Cache Miss
		reply := server.Connection().Cmd("MGET", "Bob")
		c.Expect(reply.Err, gospec.Equals, nil)
		c.Expect(reply, gospec.Satisfies, nil != reply)
		c.Expect(reply.Type, gospec.Equals, redis.MultiReply)

		value, value_err := ReplyToFloat64Ptrs(reply)
		c.Expect(value_err, gospec.Equals, nil)
		c.Expect(value, gospec.Satisfies, 1 == len(value))
		c.Expect(value[0], gospec.Satisfies, nil == value[0])

		// Cache Hit --> String
		server.Connection().Cmd("SET", "Bob", "123.456")
		reply = server.Connection().Cmd("MGET", "Bob")
		c.Expect(reply.Err, gospec.Equals, nil)
		c.Expect(reply, gospec.Satisfies, nil != reply)
		c.Expect(reply.Type, gospec.Equals, redis.MultiReply)
		c.Expect(len(reply.Elems), gospec.Equals, 1)
		c.Expect(reply.Elems[0].Type, gospec.Equals, redis.BulkReply)

		value, value_err = ReplyToFloat64Ptrs(reply)
		c.Expect(value_err, gospec.Equals, nil)
		c.Expect(value, gospec.Satisfies, 1 == len(value))
		c.Expect(value[0], gospec.Satisfies, nil != value[0])
		c.Expect(value[0], gospec.Satisfies, float64(123.456) == *value[0])

		// Parsing Error
		reply = server.Connection().Cmd("GET", "Missing")
		c.Expect(reply.Err, gospec.Equals, nil)
		c.Expect(reply, gospec.Satisfies, nil != reply)
		c.Expect(reply.Type, gospec.Equals, redis.NilReply)

		value, value_err = ReplyToFloat64Ptrs(reply)
		c.Expect(value_err, gospec.Satisfies, strings.HasPrefix(value_err.Error(), "Reply type is not MultiReply, "))
		c.Expect(value, gospec.Satisfies, 0 == len(value))

		// Parsing Error
		reply = server.Connection().Cmd("GET", "Bob")
		c.Expect(reply.Err, gospec.Equals, nil)
		c.Expect(reply, gospec.Satisfies, nil != reply)
		c.Expect(reply.Type, gospec.Equals, redis.BulkReply)

		value, value_err = ReplyToFloat64Ptrs(reply)
		c.Expect(value_err, gospec.Satisfies, strings.HasPrefix(value_err.Error(), "Reply type is not MultiReply, "))
		c.Expect(value, gospec.Satisfies, 0 == len(value))
	})

	c.Specify("[ReplyToStringPtr] returns *string or error", func() {
		logger := log4go.NewDefaultLogger(log4go.CRITICAL)
		server, err := StartRedisServer(&logger)
		if nil != err {
			panic(err)
		}
		defer server.Close()

		// Cache Miss
		reply := server.Connection().Cmd("GET", "Bob")
		c.Expect(reply.Err, gospec.Equals, nil)
		c.Expect(reply, gospec.Satisfies, nil != reply)
		c.Expect(reply.Type, gospec.Equals, redis.NilReply)

		value, value_err := ReplyToStringPtr(reply)
		c.Expect(value_err, gospec.Equals, nil)
		c.Expect(value, gospec.Satisfies, nil == value)

		// Cache Hit --> String
		server.Connection().Cmd("SET", "Bob", "123.456")
		reply = server.Connection().Cmd("GET", "Bob")
		c.Expect(reply.Err, gospec.Equals, nil)
		c.Expect(reply, gospec.Satisfies, nil != reply)
		c.Expect(reply.Type, gospec.Equals, redis.BulkReply)

		value, value_err = ReplyToStringPtr(reply)
		c.Expect(value_err, gospec.Equals, nil)
		c.Expect(value, gospec.Satisfies, nil != value)
		c.Expect(value, gospec.Satisfies, string("123.456") == *value)

		// Cache Hit --> Float
		reply = server.Connection().Cmd("INCRBYFLOAT", "Bob", 1000.0)
		c.Expect(reply.Err, gospec.Equals, nil)
		c.Expect(reply, gospec.Satisfies, nil != reply)
		c.Expect(reply.Type, gospec.Equals, redis.BulkReply)

		value, value_err = ReplyToStringPtr(reply)
		c.Expect(value_err, gospec.Equals, nil)
		c.Expect(value, gospec.Satisfies, nil != value)
		c.Expect(*value, gospec.Equals, string("1123.45599999999999996"))

		// Cache Hit --> Integer
		server.Connection().Cmd("SET", "Bob", 123)
		reply = server.Connection().Cmd("INCR", "Bob")
		c.Expect(reply.Err, gospec.Equals, nil)
		c.Expect(reply, gospec.Satisfies, nil != reply)
		c.Expect(reply.Type, gospec.Equals, redis.IntegerReply)

		value, value_err = ReplyToStringPtr(reply)
		c.Expect(value_err, gospec.Equals, nil)
		c.Expect(value, gospec.Satisfies, nil != value)
		c.Expect(*value, gospec.Equals, string("124"))

		// Parsing Error
		reply = server.Connection().Cmd("MGET", "Bob")
		c.Expect(reply.Err, gospec.Equals, nil)
		c.Expect(reply, gospec.Satisfies, nil != reply)
		c.Expect(reply.Type, gospec.Equals, redis.MultiReply)

		value, value_err = ReplyToStringPtr(reply)
		c.Expect(value_err, gospec.Satisfies, nil != value_err)
		c.Expect(value, gospec.Satisfies, nil == value)
	})

	c.Specify("[ReplyToStringPtrs] returns []*string or error", func() {
		logger := log4go.NewDefaultLogger(log4go.CRITICAL)
		server, err := StartRedisServer(&logger)
		if nil != err {
			panic(err)
		}
		defer server.Close()

		// Invalid Reply Type

		// Cache Miss
		reply := server.Connection().Cmd("MGET", "Bob")
		c.Expect(reply.Err, gospec.Equals, nil)
		c.Expect(reply, gospec.Satisfies, nil != reply)
		c.Expect(reply.Type, gospec.Equals, redis.MultiReply)

		value, value_err := ReplyToStringPtrs(reply)
		c.Expect(value_err, gospec.Equals, nil)
		c.Expect(value, gospec.Satisfies, 1 == len(value))
		c.Expect(value[0], gospec.Satisfies, nil == value[0])

		// Cache Hit --> String
		server.Connection().Cmd("SET", "Bob", "123.456")
		reply = server.Connection().Cmd("MGET", "Bob")
		c.Expect(reply.Err, gospec.Equals, nil)
		c.Expect(reply, gospec.Satisfies, nil != reply)
		c.Expect(reply.Type, gospec.Equals, redis.MultiReply)
		c.Expect(len(reply.Elems), gospec.Equals, 1)
		c.Expect(reply.Elems[0].Type, gospec.Equals, redis.BulkReply)

		value, value_err = ReplyToStringPtrs(reply)
		c.Expect(value_err, gospec.Equals, nil)
		c.Expect(value, gospec.Satisfies, 1 == len(value))
		c.Expect(value[0], gospec.Satisfies, nil != value[0])
		c.Expect(value[0], gospec.Satisfies, string("123.456") == *value[0])

		// Parsing Error
		reply = server.Connection().Cmd("GET", "Missing")
		c.Expect(reply.Err, gospec.Equals, nil)
		c.Expect(reply, gospec.Satisfies, nil != reply)
		c.Expect(reply.Type, gospec.Equals, redis.NilReply)

		value, value_err = ReplyToStringPtrs(reply)
		c.Expect(value_err, gospec.Satisfies, strings.HasPrefix(value_err.Error(), "Reply type is not MultiReply, "))
		c.Expect(value, gospec.Satisfies, 0 == len(value))

		// Parsing Error
		reply = server.Connection().Cmd("GET", "Bob")
		c.Expect(reply.Err, gospec.Equals, nil)
		c.Expect(reply, gospec.Satisfies, nil != reply)
		c.Expect(reply.Type, gospec.Equals, redis.BulkReply)

		value, value_err = ReplyToStringPtrs(reply)
		c.Expect(value_err, gospec.Satisfies, strings.HasPrefix(value_err.Error(), "Reply type is not MultiReply, "))
		c.Expect(value, gospec.Satisfies, 0 == len(value))
	})

}
Exemplo n.º 10
0
// Helpers
func MemcachedConnectionSpecs(c gospec.Context) {
	var memcached_connection_logger = log4go.NewDefaultLogger(log4go.CRITICAL)

	c.Specify("[MemcachedConnection] New connection is not open", func() {
		connection := MemcachedConnection{Url: "127.0.0.1:11290", Logger: &memcached_connection_logger}
		defer connection.Close()

		// Should be opposite of each other:
		c.Expect(connection.IsOpen(), gospec.Equals, false)
		c.Expect(connection.IsClosed(), gospec.Equals, true)
	})

	c.Specify("[MemcachedConnection] Opening connection to Invalid Host/Port has errors", func() {
		connection := MemcachedConnection{Url: "127.0.0.1:11291", Logger: &memcached_connection_logger}
		defer connection.Close()

		c.Expect(nil != connection.Open(), gospec.Equals, true)
		c.Expect(connection.IsClosed(), gospec.Equals, true)
	})

	c.Specify("[MemcachedConnection] Opening connection to Valid Host/Port has no errors", func() {
		logger := log4go.NewDefaultLogger(log4go.CRITICAL)
		server, err := StartMemcachedServer(&logger)
		if nil != err {
			panic(err)
		}
		defer server.Close()

		c.Expect(server.Connection().Open(), gospec.Equals, nil)
		c.Expect(server.Connection().IsOpen(), gospec.Equals, true)
		c.Expect(server.Connection().IsClosed(), gospec.Equals, false)
	})

	c.Specify("[MemcachedConnection] Ping (-->Set-->Delete) (re-)opens the connection automatically", func() {
		logger := log4go.NewDefaultLogger(log4go.CRITICAL)
		server, err := StartMemcachedServer(&logger)
		if nil != err {
			panic(err)
		}
		defer server.Close()

		// Starts off closed ...
		c.Expect(server.Connection().IsClosed(), gospec.Equals, true)

		// Ping the server
		// Should now be open
		c.Expect(server.Connection().Ping(), gospec.Equals, nil)
		c.Expect(server.Connection().IsOpen(), gospec.Equals, true)

		// Close the connection
		err = server.Connection().Close()
		c.Expect(err, gospec.Equals, nil)
		c.Expect(server.Connection().IsClosed(), gospec.Equals, true)

		// Ping the server again
		// Should now be open again
		c.Expect(server.Connection().Ping(), gospec.Equals, nil)
		c.Expect(server.Connection().IsOpen(), gospec.Equals, true)
	})

	c.Specify("[MemcachedConnection] Clone+Ping (-->Set-->Delete) (re-)opens the connection automatically", func() {
		logger := log4go.NewDefaultLogger(log4go.CRITICAL)
		server, err := StartMemcachedServer(&logger)
		if nil != err {
			panic(err)
		}
		defer server.Close()

		// Starts off closed ...
		c.Expect(server.Connection().IsClosed(), gospec.Equals, true)

		// Ping the server
		// Should now be open
		c.Expect(server.Connection().Ping(), gospec.Equals, nil)
		c.Expect(server.Connection().IsOpen(), gospec.Equals, true)

		// Clone the connection
		clone := server.Connection().Clone()
		defer clone.Close()

		// Close the connection
		c.Expect(err, gospec.Equals, nil)
		c.Expect(clone.IsClosed(), gospec.Equals, true)

		// Ping the server again
		// Should now be open again
		c.Expect(clone.Ping(), gospec.Equals, nil)
		c.Expect(clone.IsOpen(), gospec.Equals, true)
	})

	c.Specify("[MemcachedConnection][Get] Returns Cache Miss", func() {
		logger := log4go.NewDefaultLogger(log4go.CRITICAL)
		server, err := StartMemcachedServer(&logger)
		if nil != err {
			panic(err)
		}
		defer server.Close()

		item, err := server.Connection().Get("BOB")
		c.Expect(err, gospec.Equals, memcached.ErrCacheMiss)
		c.Expect(item, gospec.Satisfies, nil == item)
	})

	c.Specify("[MemcachedConnection][Set+Get] Returns Value", func() {
		logger := log4go.NewDefaultLogger(log4go.CRITICAL)
		server, err := StartMemcachedServer(&logger)
		if nil != err {
			panic(err)
		}
		defer server.Close()

		item_input := &memcached.Item{Key: "BOB", Value: []byte("Hello")}
		c.Expect(server.Connection().Set(item_input), gospec.Equals, nil)

		item_output, err := server.Connection().Get("BOB")
		c.Expect(err, gospec.Equals, nil)
		c.Expect(item_output.Key, gospec.Equals, item_input.Key)
		c.Expect(string(item_output.Value), gospec.Equals, string(item_input.Value))
	})

	c.Specify("[MemcachedConnection][SetStr+GetStr] Returns Value", func() {
		logger := log4go.NewDefaultLogger(log4go.CRITICAL)
		server, err := StartMemcachedServer(&logger)
		if nil != err {
			panic(err)
		}
		defer server.Close()

		c.Expect(server.Connection().SetStr("BOB", "Hello", 0), gospec.Equals, nil)

		ptr, err := server.Connection().GetStr("BOB")
		c.Expect(err, gospec.Equals, nil)
		c.Expect(ptr, gospec.Satisfies, nil != ptr)
		c.Expect(*ptr, gospec.Equals, "Hello")
	})

}
Exemplo n.º 11
0
// Helpers
func StopWatchSpecs(c gospec.Context) {

	c.Specify("[StopWatch] Makes StopWatch", func() {
		logger := log4go.NewDefaultLogger(log4go.CRITICAL)
		value := MakeStopWatch(c, &logger, "Make")
		c.Expect(value, gospec.Satisfies, nil != value)
		c.Expect(value.Logger, gospec.Equals, &logger)
		c.Expect(value.Connection, gospec.Equals, c)
		c.Expect(value.Tags[0], gospec.Equals, "Make")
		c.Expect(value.Time, gospec.Satisfies, value.Time.IsZero())
		c.Expect(value.Duration, gospec.Equals, time.Duration(0))
	})

	c.Specify("[StopWatch] Starts StopWatch", func() {
		logger := log4go.NewDefaultLogger(log4go.CRITICAL)
		value := MakeStopWatch(c, &logger, "Make")
		c.Expect(value, gospec.Satisfies, nil != value)
		c.Expect(value.Logger, gospec.Equals, &logger)
		c.Expect(value.Connection, gospec.Equals, c)
		c.Expect(value.Tags[0], gospec.Equals, "Make")
		c.Expect(value.Time, gospec.Satisfies, value.Time.IsZero())
		c.Expect(value.Duration, gospec.Equals, time.Duration(0))

		value.Start()
		c.Expect(value.Time, gospec.Satisfies, !value.Time.IsZero())
		c.Expect(value.Duration, gospec.Equals, time.Duration(0))

		time.Sleep(time.Duration(1) * time.Microsecond)
	})

	c.Specify("[StopWatch] Stops StopWatch", func() {
		logger := log4go.NewDefaultLogger(log4go.CRITICAL)
		value := MakeStopWatch(c, &logger, "Make")
		c.Expect(value, gospec.Satisfies, nil != value)
		c.Expect(value.Logger, gospec.Equals, &logger)
		c.Expect(value.Connection, gospec.Equals, c)
		c.Expect(value.Tags[0], gospec.Equals, "Make")
		c.Expect(value.Time, gospec.Satisfies, value.Time.IsZero())
		c.Expect(value.Duration, gospec.Equals, time.Duration(0))

		// Don't error out or panic if the stop watch was not started!
		value.Stop()
		c.Expect(value.Time, gospec.Satisfies, value.Time.IsZero())
		c.Expect(value.Duration, gospec.Equals, time.Duration(0))

		// Start the stop watch
		value.Start()
		c.Expect(value.Time, gospec.Satisfies, !value.Time.IsZero())
		c.Expect(value.Duration, gospec.Equals, time.Duration(0))

		// Sleep, then stop the stop watch
		time.Sleep(time.Duration(2) * time.Microsecond)
		value.Stop()
		c.Expect(value.Time, gospec.Satisfies, !value.Time.IsZero())
		c.Expect(value.Duration, gospec.Satisfies, value.Duration > 0)
		c.Expect(value.Duration.Nanoseconds(), gospec.Satisfies, value.Duration.Nanoseconds() >= 2*1000)
	})

	c.Specify("[StopWatch] Logs StopWatch", func() {
		logger := log4go.NewDefaultLogger(log4go.CRITICAL)
		value := MakeStopWatch(c, &logger, "Make")
		c.Expect(value, gospec.Satisfies, nil != value)
		c.Expect(value.Logger, gospec.Equals, &logger)
		c.Expect(value.Connection, gospec.Equals, c)
		c.Expect(value.Tags[0], gospec.Equals, "Make")
		c.Expect(value.Time, gospec.Satisfies, value.Time.IsZero())
		c.Expect(value.Duration, gospec.Equals, time.Duration(0))

		// Start the stop watch
		value.Start()
		c.Expect(value.Time, gospec.Satisfies, !value.Time.IsZero())

		// Sleep, then stop the stop watch
		time.Sleep(time.Duration(2) * time.Microsecond)
		value.Stop()

		// Execute the logger
		value.LogDuration()
	})

}
Exemplo n.º 12
0
// Helpers
func MemcachedPoolSpecs(c gospec.Context) {
	var memcached_pool_logger = log4go.NewDefaultLogger(log4go.CRITICAL)

	c.Specify("[MemcachedConnectionPool] New Pool is not open", func() {
		pool := MemcachedConnectionPool{Mode: AGRESSIVE, Size: 0, Urls: []string{}, Logger: memcached_pool_logger}
		defer pool.Close()

		c.Expect(pool.IsOpen(), gospec.Equals, false)
		c.Expect(pool.IsClosed(), gospec.Equals, true)
		c.Expect(pool.IsOpen(), gospec.Satisfies, pool.IsOpen() != pool.IsClosed())
		c.Expect(pool.Len(), gospec.Equals, -1)
	})

	c.Specify("[MemcachedConnectionPool] Opening a Pool with Undefined Mode has errors", func() {
		pool := MemcachedConnectionPool{Mode: 0, Size: 0, Urls: []string{}, Logger: memcached_pool_logger}
		defer pool.Close()

		// Should have an error
		err := pool.Open()
		c.Expect(err, gospec.Satisfies, err != nil)

		// Should be closed
		c.Expect(pool.IsClosed(), gospec.Equals, true)
		c.Expect(pool.Len(), gospec.Equals, -1)
	})

	c.Specify("[MemcachedConnectionPool] Size=0 pool is Empty", func() {
		pool := MemcachedConnectionPool{Mode: AGRESSIVE, Size: 0, Urls: []string{}, Logger: memcached_pool_logger}
		defer pool.Close()

		// Shouldn't have any errors
		err := pool.Open()
		c.Expect(err, gospec.Equals, nil)

		// Should be open
		c.Expect(pool.IsOpen(), gospec.Equals, true)
		c.Expect(pool.IsClosed(), gospec.Equals, false)

		// Should be empty
		c.Expect(pool.Len(), gospec.Equals, 0)
	})

	c.Specify("[MemcachedConnectionPool] Pop from empty pool returns error", func() {
		pool := MemcachedConnectionPool{Mode: AGRESSIVE, Size: 0, Urls: []string{}, Logger: memcached_pool_logger}
		defer pool.Close()

		// Shouldn't have any errors
		err := pool.Open()
		c.Expect(err, gospec.Equals, nil)

		// Should be open
		c.Expect(pool.IsOpen(), gospec.Equals, true)
		c.Expect(pool.IsClosed(), gospec.Equals, false)

		// Should be empty
		c.Expect(pool.Len(), gospec.Equals, 0)

		var connection *MemcachedConnection
		connection, err = pool.Pop()
		c.Expect(err, gospec.Equals, ErrNoConnectionsAvailable)
		c.Expect(connection, gospec.Satisfies, nil == connection)
	})

	c.Specify("[MemcachedConnectionPool] Opening connection to Invalid Host/Port has errors", func() {
		pool := MemcachedConnectionPool{Mode: AGRESSIVE, Size: 1, Urls: []string{"127.0.0.1:11391"}, Logger: memcached_pool_logger}
		defer pool.Close()

		// Should have an error
		err := pool.Open()
		c.Expect(err, gospec.Satisfies, err != nil)

		// Should be closed
		c.Expect(pool.IsClosed(), gospec.Equals, true)
		c.Expect(pool.Len(), gospec.Equals, -1)
	})

	c.Specify("[MemcachedConnectionPool] Opening connection to Valid Host/Port has no errors", func() {
		server, err := StartMemcachedServer(&memcached_pool_logger)
		if nil != err {
			panic(err)
		}
		defer server.Close()

		pool := MemcachedConnectionPool{Mode: AGRESSIVE, Size: 1, Urls: []string{server.Url()}, Logger: memcached_pool_logger}
		defer pool.Close()

		c.Expect(pool.Open(), gospec.Equals, nil)
		c.Expect(pool.IsOpen(), gospec.Equals, true)
		c.Expect(pool.IsClosed(), gospec.Equals, false)
		c.Expect(pool.IsClosed(), gospec.Satisfies, pool.IsOpen() != pool.IsClosed())
	})

	c.Specify("[MemcachedConnectionPool] 10x AGRESSIVE Pool Pops 10x open connections", func() {
		server, err := StartMemcachedServer(&memcached_pool_logger)
		if nil != err {
			panic(err)
		}
		defer server.Close()

		pool := MemcachedConnectionPool{Mode: AGRESSIVE, Size: 10, Urls: []string{server.Url()}, Logger: memcached_pool_logger}
		defer pool.Close()

		c.Expect(pool.Open(), gospec.Equals, nil)
		c.Expect(pool.IsOpen(), gospec.Equals, true)

		// Has 10x connections
		for count := 10; count > 0; count-- {
			// Count decrements when the connection is pop'd
			c.Expect(pool.Len(), gospec.Equals, count)
			connection, err := pool.Pop()
			c.Expect(pool.Len(), gospec.Equals, count-1)

			// Expecting an open connection
			c.Expect(err, gospec.Equals, nil)
			c.Expect(connection, gospec.Satisfies, connection != nil)
			c.Expect(connection.IsOpen(), gospec.Equals, true)
		}
	})

	c.Specify("[MemcachedConnectionPool] 10x LAZY Pool Pops 10x closed connections", func() {
		server, err := StartMemcachedServer(&memcached_pool_logger)
		if nil != err {
			panic(err)
		}
		defer server.Close()

		pool := MemcachedConnectionPool{Mode: LAZY, Size: 10, Urls: []string{server.Url()}, Logger: memcached_pool_logger}
		defer pool.Close()

		c.Expect(pool.Open(), gospec.Equals, nil)
		c.Expect(pool.IsOpen(), gospec.Equals, true)

		// Has 10x connections
		for count := 10; count > 0; count-- {
			// Count decrements when the connection is pop'd
			c.Expect(pool.Len(), gospec.Equals, count)
			connection, err := pool.Pop()
			c.Expect(pool.Len(), gospec.Equals, count-1)

			// Expecting an open connection
			c.Expect(err, gospec.Equals, nil)
			c.Expect(connection, gospec.Satisfies, connection != nil)
			c.Expect(connection.IsClosed(), gospec.Equals, true)
		}
	})
}
func RedisBatchQueueWorkerSpecs(c gospec.Context) {

	c.Specify("[RedisBatchQueueWorker][Make]", func() {
		ptr, err := makeRedisBatchQueueWorker(nil, nil, 0, nil)
		c.Expect(err, gospec.Satisfies, nil != err)
		c.Expect(err.Error(), gospec.Equals, "[redisBatchQueueWorker][Make] Nil logger!")
		c.Expect(ptr, gospec.Satisfies, nil == ptr)

		logger := &log4go.Logger{}
		ptr, err = makeRedisBatchQueueWorker(logger, nil, 0, nil)
		c.Expect(err, gospec.Satisfies, nil != err)
		c.Expect(err.Error(), gospec.Equals, "[redisBatchQueueWorker][Make] Nil redis connection!")
		c.Expect(ptr, gospec.Satisfies, nil == ptr)

		connection := &RedisConnection{}
		ptr, err = makeRedisBatchQueueWorker(logger, connection, 0, nil)
		c.Expect(err, gospec.Satisfies, nil != err)
		c.Expect(err.Error(), gospec.Equals, "[redisBatchQueueWorker][Make] Nil queue!")
		c.Expect(ptr, gospec.Satisfies, nil == ptr)

		queue := make(chan *RedisBatchCommand)
		defer close(queue)

		ptr, err = makeRedisBatchQueueWorker(logger, connection, 0, queue)
		c.Expect(err, gospec.Satisfies, nil != err)
		c.Expect(err.Error(), gospec.Equals, "[redisBatchQueueWorker][Make] BatchSize must be greater than 0!")
		c.Expect(ptr, gospec.Satisfies, nil == ptr)

		batch_size := uint(1)
		ptr, err = makeRedisBatchQueueWorker(logger, connection, batch_size, queue)
		c.Expect(err, gospec.Satisfies, nil == err)
		c.Expect(ptr, gospec.Satisfies, nil != ptr)
	})

	c.Specify("[RedisBatchQueueWorker][runCommands]", func() {
		logger := log4go.NewDefaultLogger(log4go.CRITICAL)
		server, err := StartRedisServer(&logger)
		if nil != err {
			panic(err)
		}
		defer server.Close()

		queue := make(chan *RedisBatchCommand)
		defer close(queue)

		worker, worker_err := makeRedisBatchQueueWorker(&logger, server.Connection(), 1, queue)
		c.Expect(worker_err, gospec.Equals, nil)
		c.Expect(worker, gospec.Satisfies, nil != worker)

		cmds := []*RedisBatchCommand{
			MakeRedisBatchCommandSet("A", []byte("Bob")),
			MakeRedisBatchCommandSet("B", []byte("Gary")),
		}
		worker.runCommands(cmds)

		strs, strs_err := RedisDsl{server.Connection()}.MGET_STRINGS("A", "B")
		c.Expect(strs_err, gospec.Equals, nil)
		c.Expect(strs, gospec.Satisfies, 2 == len(strs))
		c.Expect(*strs[0], gospec.Equals, "Bob")
		c.Expect(*strs[1], gospec.Equals, "Gary")
	})

	c.Specify("[RedisBatchQueueWorker][mustPopCommand]", func() {
		prev := runtime.GOMAXPROCS(2)
		defer runtime.GOMAXPROCS(prev)

		logger := &log4go.Logger{}
		connection := &RedisConnection{}
		batch_size := uint(1)
		queue := make(chan *RedisBatchCommand, 2)
		defer close(queue)

		ptr, err := makeRedisBatchQueueWorker(logger, connection, batch_size, queue)
		c.Expect(err, gospec.Satisfies, nil == err)
		c.Expect(ptr, gospec.Satisfies, nil != ptr)

		counter := make(chan int, 2)
		defer close(counter)

		// Pop the command
		go func() {
			fmt.Println("Waiting for command ...")
			cmd, ok := ptr.mustPopCommand()

			fmt.Println("Got command:", cmd, ok)
			counter <- 1

			fmt.Println("Forwarded command:", cmd, ok)
		}()

		time.Sleep(time.Millisecond)

		fmt.Println("Queue sizes:", len(queue), len(counter))
		c.Expect(len(counter), gospec.Equals, 0)

		queue <- &RedisBatchCommand{}
		fmt.Println("Queue sizes:", len(queue), len(counter))

		time.Sleep(10 * time.Millisecond)

		fmt.Println("Queue sizes:", len(queue), len(counter))
		c.Expect(len(counter), gospec.Equals, 1)

		<-counter

		fmt.Println("Queue sizes:", len(queue), len(counter))
	})

	c.Specify("[RedisBatchQueueWorker][mayPopCommand]", func() {
		prev := runtime.GOMAXPROCS(2)
		defer runtime.GOMAXPROCS(prev)

		logger := &log4go.Logger{}
		connection := &RedisConnection{}
		batch_size := uint(1)
		queue := make(chan *RedisBatchCommand, 2)
		defer close(queue)

		ptr, err := makeRedisBatchQueueWorker(logger, connection, batch_size, queue)
		c.Expect(err, gospec.Satisfies, nil == err)
		c.Expect(ptr, gospec.Satisfies, nil != ptr)

		cmd, ok := ptr.mayPopCommand()
		c.Expect(cmd, gospec.Satisfies, nil == cmd)
		c.Expect(ok, gospec.Equals, true)
		c.Expect(len(queue), gospec.Equals, 0)

		queue <- &RedisBatchCommand{}
		c.Expect(len(queue), gospec.Equals, 1)

		cmd, ok = ptr.mayPopCommand()
		c.Expect(cmd, gospec.Satisfies, nil != cmd)
		c.Expect(ok, gospec.Equals, true)
		c.Expect(len(queue), gospec.Equals, 0)
	})

	c.Specify("[RedisBatchQueueWorker][popCommands]", func() {
		prev := runtime.GOMAXPROCS(2)
		defer runtime.GOMAXPROCS(prev)

		logger := &log4go.Logger{}
		connection := &RedisConnection{}
		batch_size := uint(10)
		queue := make(chan *RedisBatchCommand, int(batch_size*3))
		defer close(queue)

		ptr, err := makeRedisBatchQueueWorker(logger, connection, batch_size, queue)
		c.Expect(err, gospec.Satisfies, nil == err)
		c.Expect(ptr, gospec.Satisfies, nil != ptr)

		counter := make(chan int, 2)
		defer close(counter)

		// Pop the commands
		pop := func() {
			cmds, _ := ptr.popCommands()
			counter <- len(cmds)
		}

		c.Expect(len(queue), gospec.Equals, 0)
		c.Expect(len(counter), gospec.Equals, 0)

		queue <- &RedisBatchCommand{}
		c.Expect(len(queue), gospec.Equals, 1)
		c.Expect(len(counter), gospec.Equals, 0)

		go pop()
		time.Sleep(time.Millisecond)
		c.Expect(len(queue), gospec.Equals, 0)
		c.Expect(len(counter), gospec.Equals, 1)

		count, ok := <-counter
		c.Expect(count, gospec.Equals, 1)
		c.Expect(ok, gospec.Equals, true)

		for i := 0; i < 15; i++ {
			queue <- &RedisBatchCommand{}
		}
		c.Expect(len(queue), gospec.Equals, 15)
		c.Expect(len(counter), gospec.Equals, 0)

		// Pops 1x batch_size commands
		go pop()
		time.Sleep(time.Millisecond)
		c.Expect(len(queue), gospec.Equals, 5)
		c.Expect(len(counter), gospec.Equals, 1)

		// Counts the correct number of commands
		count, ok = <-counter
		c.Expect(count, gospec.Equals, 10)
		c.Expect(ok, gospec.Equals, true)

		// Pops 1/2x batch_size commands
		go pop()
		time.Sleep(time.Millisecond)
		c.Expect(len(queue), gospec.Equals, 0)
		c.Expect(len(counter), gospec.Equals, 1)

		// Pop a partial batch:
		count, ok = <-counter
		c.Expect(count, gospec.Equals, 5)
		c.Expect(ok, gospec.Equals, true)
	})

	c.Specify("[RedisBatchQueueWorker][Run]", func() {
		prev := runtime.GOMAXPROCS(2)
		defer runtime.GOMAXPROCS(prev)

		logger := log4go.NewDefaultLogger(log4go.CRITICAL)
		server, err := StartRedisServer(&logger)
		if nil != err {
			panic(err)
		}
		defer server.Close()

		batch_size := uint(10)
		queue := make(chan *RedisBatchCommand, int(batch_size*3))
		// defer close(queue)

		ptr, err := makeRedisBatchQueueWorker(&logger, server.Connection(), batch_size, queue)
		c.Expect(err, gospec.Satisfies, nil == err)
		c.Expect(ptr, gospec.Satisfies, nil != ptr)

		// Runs the task until the queue is closed
		go ptr.Run()

		queue <- MakeRedisBatchCommandHashIncrementBy("Hash", "Field A", 1)
		queue <- MakeRedisBatchCommandHashIncrementBy("Hash", "Field B", 10)
		queue <- MakeRedisBatchCommandHashIncrementBy("Hash", "Field C", 100)

		time.Sleep(50 * time.Millisecond)

		ints, ints_err := RedisDsl{server.Connection()}.HASH_MGET_INT64S("Hash", "Field A", "Field B", "Field C")
		c.Expect(ints_err, gospec.Equals, nil)
		c.Expect(len(ints), gospec.Equals, 3)
		c.Expect(*ints[0], gospec.Equals, int64(1))
		c.Expect(*ints[1], gospec.Equals, int64(10))
		c.Expect(*ints[2], gospec.Equals, int64(100))

		queue <- MakeRedisBatchCommandHashDelete("Hash", "Field A", "Field B", "Field C")
		time.Sleep(time.Millisecond)
		close(queue)

		time.Sleep(50 * time.Millisecond)

		ints, ints_err = RedisDsl{server.Connection()}.HASH_MGET_INT64S("Hash", "Field A", "Field B", "Field C")
		c.Expect(ints_err, gospec.Equals, nil)
		c.Expect(len(ints), gospec.Equals, 3)
		c.Expect(ints[0], gospec.Satisfies, nil == ints[0])
		c.Expect(ints[1], gospec.Satisfies, nil == ints[1])
		c.Expect(ints[2], gospec.Satisfies, nil == ints[2])
	})

}
Exemplo n.º 14
0
// Helpers
func RedisPoolSpecs(c gospec.Context) {
	var redis_pool_logger = log4go.NewDefaultLogger(log4go.CRITICAL)

	c.Specify("[RedisConnectionPool] New Pool is not open", func() {
		pool := RedisConnectionPool{Mode: AGRESSIVE, Size: 0, Urls: []string{}, Logger: redis_pool_logger}
		defer pool.Close()

		c.Expect(pool.IsOpen(), gospec.Equals, false)
		c.Expect(pool.IsClosed(), gospec.Equals, true)
		c.Expect(pool.IsOpen(), gospec.Satisfies, pool.IsOpen() != pool.IsClosed())
		c.Expect(pool.Len(), gospec.Equals, -1)
	})

	c.Specify("[RedisConnectionPool] Opening a Pool with Undefined Mode has errors", func() {
		pool := RedisConnectionPool{Mode: 0, Size: 0, Urls: []string{}, Logger: redis_pool_logger}
		defer pool.Close()

		// Should have an error
		err := pool.Open()
		c.Expect(err, gospec.Satisfies, err != nil)

		// Should be closed
		c.Expect(pool.IsClosed(), gospec.Equals, true)
		c.Expect(pool.Len(), gospec.Equals, -1)
	})

	c.Specify("[RedisConnectionPool] Size=0 pool is Empty", func() {
		pool := RedisConnectionPool{Mode: AGRESSIVE, Size: 0, Urls: []string{}, Logger: redis_pool_logger}
		defer pool.Close()

		// Shouldn't have any errors
		err := pool.Open()
		c.Expect(err, gospec.Equals, nil)

		// Should be open
		c.Expect(pool.IsOpen(), gospec.Equals, true)
		c.Expect(pool.IsClosed(), gospec.Equals, false)

		// Should be empty
		c.Expect(pool.Len(), gospec.Equals, 0)
	})

	c.Specify("[RedisConnectionPool] Pop from empty pool returns error", func() {
		pool := RedisConnectionPool{Mode: AGRESSIVE, Size: 0, Urls: []string{}, Logger: redis_pool_logger}
		defer pool.Close()

		// Shouldn't have any errors
		err := pool.Open()
		c.Expect(err, gospec.Equals, nil)

		// Should be open
		c.Expect(pool.IsOpen(), gospec.Equals, true)
		c.Expect(pool.IsClosed(), gospec.Equals, false)

		// Should be empty
		c.Expect(pool.Len(), gospec.Equals, 0)

		var connection *RedisConnection
		connection, err = pool.Pop()
		c.Expect(err, gospec.Equals, ErrNoConnectionsAvailable)
		c.Expect(connection, gospec.Satisfies, nil == connection)
	})

	c.Specify("[RedisConnectionPool] Opening connection to Invalid Host/Port has errors", func() {
		pool := RedisConnectionPool{Mode: AGRESSIVE, Size: 1, Urls: []string{"127.0.0.1:6991"}, Logger: redis_pool_logger}
		defer pool.Close()

		// Should have an error
		err := pool.Open()
		c.Expect(err, gospec.Satisfies, err != nil)

		// Should be closed
		c.Expect(pool.IsClosed(), gospec.Equals, true)
		c.Expect(pool.Len(), gospec.Equals, -1)
	})

	c.Specify("[RedisConnectionPool] Opening connection to Valid Host/Port has no errors", func() {
		pool := RedisConnectionPool{Mode: AGRESSIVE, Size: 1, Urls: []string{"127.0.0.1:6992"}, Logger: redis_pool_logger}
		defer pool.Close()

		// Start the server ...
		cmd := exec.Command("redis-server", "--port", "6992")
		err := cmd.Start()
		c.Expect(err, gospec.Equals, nil)
		if err != nil {
			// Abort on errors
			return
		}
		time.Sleep(time.Duration(1) * time.Second)
		defer cmd.Wait()
		defer cmd.Process.Kill()

		err = pool.Open()
		c.Expect(err, gospec.Equals, nil)

		c.Expect(pool.IsOpen(), gospec.Equals, true)
		c.Expect(pool.IsClosed(), gospec.Equals, false)
		c.Expect(pool.IsClosed(), gospec.Satisfies, pool.IsOpen() != pool.IsClosed())
	})

	c.Specify("[RedisConnectionPool] 10x AGRESSIVE Pool Pops 10x open connections", func() {
		pool := RedisConnectionPool{Mode: AGRESSIVE, Size: 10, Urls: []string{"127.0.0.1:6993"}, Logger: redis_pool_logger}
		defer pool.Close()

		// Start the server ...
		cmd := exec.Command("redis-server", "--port", "6993")
		err := cmd.Start()
		c.Expect(err, gospec.Equals, nil)
		if err != nil {
			// Abort on errors
			return
		}
		time.Sleep(time.Duration(1) * time.Second)
		defer cmd.Wait()
		defer cmd.Process.Kill()

		err = pool.Open()
		c.Expect(err, gospec.Equals, nil)
		c.Expect(pool.IsOpen(), gospec.Equals, true)

		// Has 10x connections
		var connection *RedisConnection

		for count := 10; count > 0; count-- {
			// Count decrements when the connection is pop'd
			c.Expect(pool.Len(), gospec.Equals, count)
			connection, err = pool.Pop()
			c.Expect(pool.Len(), gospec.Equals, count-1)

			// Expecting an open connection
			c.Expect(err, gospec.Equals, nil)
			c.Expect(connection, gospec.Satisfies, connection != nil)
			c.Expect(connection.IsOpen(), gospec.Equals, true)
		}
	})

	c.Specify("[RedisConnectionPool] 10x LAZY Pool Pops 10x closed connections", func() {
		pool := RedisConnectionPool{Mode: LAZY, Size: 10, Urls: []string{"127.0.0.1:6994"}, Logger: redis_pool_logger}
		defer pool.Close()

		// Start the server ...
		cmd := exec.Command("redis-server", "--port", "6994")
		err := cmd.Start()
		c.Expect(err, gospec.Equals, nil)
		if err != nil {
			// Abort on errors
			return
		}
		time.Sleep(time.Duration(1) * time.Second)
		defer cmd.Wait()
		defer cmd.Process.Kill()

		err = pool.Open()
		c.Expect(err, gospec.Equals, nil)
		c.Expect(pool.IsOpen(), gospec.Equals, true)

		// Has 10x connections
		var connection *RedisConnection

		for count := 10; count > 0; count-- {
			// Count decrements when the connection is pop'd
			c.Expect(pool.Len(), gospec.Equals, count)
			connection, err = pool.Pop()
			c.Expect(pool.Len(), gospec.Equals, count-1)

			// Expecting an open connection
			c.Expect(err, gospec.Equals, nil)
			c.Expect(connection, gospec.Satisfies, connection != nil)
			c.Expect(connection.IsClosed(), gospec.Equals, true)
		}
	})
}
Exemplo n.º 15
0
// Helpers
func RedisBatchCommandsSpecs(c gospec.Context) {

	c.Specify("[RedisBatchCommands] PING Test", func() {
		logger := log4go.NewDefaultLogger(log4go.CRITICAL)
		server, err := StartRedisServer(&logger)
		if nil != err {
			panic(err)
		}
		defer server.Close()
		c.Expect(server.Connection().IsClosed(), gospec.Equals, true)

		var commands RedisBatchCommands
		commands = make([]*RedisBatchCommand, 1)
		commands[0] = MakeRedisBatchCommand("PING")

		err = commands.ExecuteBatch(server.Connection())
		c.Expect(err, gospec.Equals, nil)

		str, _ := commands[0].Reply().Str()
		c.Expect(commands[0].Reply(), gospec.Satisfies, str == "PONG")
	})

	c.Specify("[RedisBatchCommands] Value Exists", func() {
		logger := log4go.NewDefaultLogger(log4go.CRITICAL)
		server, err := StartRedisServer(&logger)
		if nil != err {
			panic(err)
		}
		defer server.Close()
		c.Expect(server.Connection().IsClosed(), gospec.Equals, true)

		server.Connection().Cmd("SET", "Bob", "123")

		var commands RedisBatchCommands
		commands = make([]*RedisBatchCommand, 2)
		commands[0] = MakeRedisBatchCommandExists("Bob")
		commands[1] = MakeRedisBatchCommandExists("George")

		err = commands.ExecuteBatch(server.Connection())
		c.Expect(err, gospec.Equals, nil)

		ok, _ := commands[0].Reply().Int()
		c.Expect(commands[0].Reply(), gospec.Satisfies, ok == 1)

		ok, _ = commands[1].Reply().Int()
		c.Expect(commands[1].Reply(), gospec.Satisfies, ok == 0)
	})

	c.Specify("[RedisBatchCommands] Expire value", func() {
		logger := log4go.NewDefaultLogger(log4go.CRITICAL)
		server, err := StartRedisServer(&logger)
		if nil != err {
			panic(err)
		}
		defer server.Close()
		c.Expect(server.Connection().IsClosed(), gospec.Equals, true)

		commands := RedisBatchCommands{
			// Expects -2
			MakeRedisBatchCommandGetExpiresIn("Bob"),
			// Expects OK
			MakeRedisBatchCommandSet("Bob", []byte("123")),
			// Expects -1
			MakeRedisBatchCommandGetExpiresIn("Bob"),
			// Expects OK
			MakeRedisBatchCommandExpireIn("Bob", time.Duration(1)*time.Second),
			// Expects ~1s
			MakeRedisBatchCommandGetExpiresIn("Bob"),
			// Clear the TTL
			MakeRedisBatchCommandPersist("Bob"),
			// Expects -1
			MakeRedisBatchCommandGetExpiresIn("Bob"),
			// Set the TTL again, and use a Sleep below to test the expiration
			MakeRedisBatchCommandExpireIn("Bob", time.Duration(1)*time.Second),
		}

		err = commands.ExecuteBatch(server.Connection())
		c.Expect(err, gospec.Equals, nil)

		// Expects -2, or -1 for older redis's
		ttl, _ := commands[0].Reply().Int()
		c.Expect(commands[0].Reply(), gospec.Satisfies, ttl == -2 || ttl == -1)

		// Expects OK
		ok, _ := commands[1].Reply().Bool()
		c.Expect(commands[1].Reply(), gospec.Satisfies, ok)

		// Expects -1
		ttl, _ = commands[2].Reply().Int()
		c.Expect(commands[2].Reply(), gospec.Satisfies, ttl == -1)

		// Expects OK
		ok, _ = commands[3].Reply().Bool()
		c.Expect(commands[3].Reply(), gospec.Satisfies, ok)

		// Expects ~1s
		ttl, _ = commands[4].Reply().Int()
		c.Expect(commands[4].Reply(), gospec.Satisfies, ttl == 1)

		// Expects 1, for TTL removed
		ttl, _ = commands[5].Reply().Int()
		c.Expect(commands[5].Reply(), gospec.Satisfies, ttl == 1)
		ttl, _ = commands[6].Reply().Int()
		c.Expect(commands[6].Reply(), gospec.Satisfies, ttl == -1)

		// Sleep for 1.5 seconds
		time.Sleep(time.Duration(1500) * time.Millisecond)

		// Value has expired!
		reply := server.Connection().Cmd("GET", "Bob")
		c.Expect(reply, gospec.Satisfies, reply.Type == redis.NilReply)
	})

	c.Specify("[RedisBatchCommands] Delete values", func() {
		logger := log4go.NewDefaultLogger(log4go.CRITICAL)
		server, err := StartRedisServer(&logger)
		if nil != err {
			panic(err)
		}
		defer server.Close()
		c.Expect(server.Connection().IsClosed(), gospec.Equals, true)

		server.Connection().Cmd("SET", "Bob", "123")
		server.Connection().Cmd("SET", "Gary", "456")

		var commands RedisBatchCommands
		commands = make([]*RedisBatchCommand, 1)
		commands[0] = MakeRedisBatchCommandDelete("Bob", "Gary", "George")

		err = commands.ExecuteBatch(server.Connection())
		c.Expect(err, gospec.Equals, nil)

		// Deleted 2 keys:
		count, _ := commands[0].Reply().Int()
		c.Expect(commands[0].Reply(), gospec.Satisfies, count == 2)
	})

	c.Specify("[RedisBatchCommands] Mget values", func() {
		logger := log4go.NewDefaultLogger(log4go.CRITICAL)
		server, err := StartRedisServer(&logger)
		if nil != err {
			panic(err)
		}
		defer server.Close()
		c.Expect(server.Connection().IsClosed(), gospec.Equals, true)

		server.Connection().Cmd("SET", "Bob", "123")
		server.Connection().Cmd("SET", "Gary", "456")

		var commands RedisBatchCommands
		commands = make([]*RedisBatchCommand, 1)
		commands[0] = MakeRedisBatchCommandMget("Bob", "Gary", "George")

		err = commands.ExecuteBatch(server.Connection())
		c.Expect(err, gospec.Equals, nil)

		// Cache Hit on 2x; Cache Miss on 1x
		bytes_array, _ := commands[0].Reply().ListBytes()
		c.Expect(commands[0].Reply(), gospec.Satisfies, len(bytes_array) == 3)
		c.Expect(commands[0].Reply(), gospec.Satisfies, string(bytes_array[0]) == "123")
		c.Expect(commands[0].Reply(), gospec.Satisfies, string(bytes_array[1]) == "456")
		c.Expect(commands[0].Reply(), gospec.Satisfies, len(bytes_array[2]) == 0)
	})

	c.Specify("[RedisBatchCommands] Get values", func() {
		logger := log4go.NewDefaultLogger(log4go.CRITICAL)
		server, err := StartRedisServer(&logger)
		if nil != err {
			panic(err)
		}
		defer server.Close()
		c.Expect(server.Connection().IsClosed(), gospec.Equals, true)

		server.Connection().Cmd("SET", "Bob", "123")
		server.Connection().Cmd("SET", "Gary", "456")

		var commands RedisBatchCommands
		commands = make([]*RedisBatchCommand, 3)
		commands[0] = MakeRedisBatchCommandGet("Bob")
		commands[1] = MakeRedisBatchCommandGet("Gary")
		commands[2] = MakeRedisBatchCommandGet("George")

		err = commands.ExecuteBatch(server.Connection())
		c.Expect(err, gospec.Equals, nil)

		// Cache Hit on 2x; Cache Miss on 1x
		str, _ := commands[0].Reply().Str()
		c.Expect(commands[0].Reply(), gospec.Satisfies, str == "123")

		str, _ = commands[1].Reply().Str()
		c.Expect(commands[1].Reply(), gospec.Satisfies, str == "456")

		str, _ = commands[2].Reply().Str()
		c.Expect(commands[2].Reply(), gospec.Satisfies, str == "")
	})

	c.Specify("[RedisBatchCommands] Set value", func() {
		logger := log4go.NewDefaultLogger(log4go.CRITICAL)
		server, err := StartRedisServer(&logger)
		if nil != err {
			panic(err)
		}
		defer server.Close()
		c.Expect(server.Connection().IsClosed(), gospec.Equals, true)

		var commands RedisBatchCommands
		commands = make([]*RedisBatchCommand, 1)
		commands[0] = MakeRedisBatchCommandSet("Bob", []byte("123"))

		err = commands.ExecuteBatch(server.Connection())
		c.Expect(err, gospec.Equals, nil)

		ok, _ := commands[0].Reply().Str()
		c.Expect(commands[0].Reply(), gospec.Satisfies, ok == "OK")
	})

	c.Specify("[RedisBatchCommands] IncrementBy value", func() {
		logger := log4go.NewDefaultLogger(log4go.CRITICAL)
		server, err := StartRedisServer(&logger)
		if nil != err {
			panic(err)
		}
		defer server.Close()
		c.Expect(server.Connection().IsClosed(), gospec.Equals, true)

		var commands RedisBatchCommands
		commands = make([]*RedisBatchCommand, 1)
		commands[0] = MakeRedisBatchCommandIncrementBy("Bob", 123)

		err = commands.ExecuteBatch(server.Connection())
		c.Expect(err, gospec.Equals, nil)

		// Returns the new value
		ok, _ := commands[0].Reply().Int()
		c.Expect(commands[0].Reply(), gospec.Satisfies, ok == 123)
	})

	c.Specify("[RedisBatchCommands] IncrementByFloat value", func() {
		logger := log4go.NewDefaultLogger(log4go.CRITICAL)
		server, err := StartRedisServer(&logger)
		if nil != err {
			panic(err)
		}
		defer server.Close()
		c.Expect(server.Connection().IsClosed(), gospec.Equals, true)

		var commands RedisBatchCommands
		commands = make([]*RedisBatchCommand, 1)
		commands[0] = MakeRedisBatchCommandIncrementByFloat("Bob", 123.456)

		err = commands.ExecuteBatch(server.Connection())
		c.Expect(err, gospec.Equals, nil)

		// Returns the new value
		ok, _ := commands[0].Reply().Float64()
		c.Expect(commands[0].Reply(), gospec.Satisfies, ok == 123.456)
	})

	c.Specify("[RedisBatchCommands] Hash Value Exists", func() {
		logger := log4go.NewDefaultLogger(log4go.CRITICAL)
		server, err := StartRedisServer(&logger)
		if nil != err {
			panic(err)
		}
		defer server.Close()
		c.Expect(server.Connection().IsClosed(), gospec.Equals, true)

		server.Connection().Cmd("HSET", "Bob", "123", "")

		var commands RedisBatchCommands
		commands = make([]*RedisBatchCommand, 2)
		commands[0] = MakeRedisBatchCommandHashExists("Bob", "123")
		commands[1] = MakeRedisBatchCommandHashExists("Bob", "George")

		err = commands.ExecuteBatch(server.Connection())
		c.Expect(err, gospec.Equals, nil)

		ok, _ := commands[0].Reply().Int()
		c.Expect(commands[0].Reply(), gospec.Satisfies, ok == 1)

		ok, _ = commands[1].Reply().Int()
		c.Expect(commands[1].Reply(), gospec.Satisfies, ok == 0)
	})

	c.Specify("[RedisBatchCommands] Hash Delete values", func() {
		logger := log4go.NewDefaultLogger(log4go.CRITICAL)
		server, err := StartRedisServer(&logger)
		if nil != err {
			panic(err)
		}
		defer server.Close()
		c.Expect(server.Connection().IsClosed(), gospec.Equals, true)

		server.Connection().Cmd("HSET", "Bob", "A", "123")

		str, _ := server.Connection().Cmd("HGET", "Bob", "A").Str()
		c.Expect(str, gospec.Equals, "123")

		var commands RedisBatchCommands
		commands = make([]*RedisBatchCommand, 1)
		commands[0] = MakeRedisBatchCommandHashDelete("Bob", "A")

		err = commands.ExecuteBatch(server.Connection())
		c.Expect(err, gospec.Equals, nil)

		// Deleted 1 keys:
		count, _ := commands[0].Reply().Int()
		c.Expect(commands[0].Reply(), gospec.Satisfies, count == 1)
	})

	c.Specify("[RedisBatchCommands] Hash Mget values", func() {
		logger := log4go.NewDefaultLogger(log4go.CRITICAL)
		server, err := StartRedisServer(&logger)
		if nil != err {
			panic(err)
		}
		defer server.Close()
		c.Expect(server.Connection().IsClosed(), gospec.Equals, true)

		server.Connection().Cmd("HSET", "A", "Bob", "123")
		server.Connection().Cmd("HSET", "A", "Gary", "456")

		var commands RedisBatchCommands
		commands = make([]*RedisBatchCommand, 1)
		commands[0] = MakeRedisBatchCommandHashMget("A", "Bob", "Gary", "George")

		err = commands.ExecuteBatch(server.Connection())
		c.Expect(err, gospec.Equals, nil)

		// Cache Hit on 2x; Cache Miss on 1x
		bytes_array, _ := commands[0].Reply().ListBytes()
		c.Expect(commands[0].Reply(), gospec.Satisfies, len(bytes_array) == 3)
		c.Expect(commands[0].Reply(), gospec.Satisfies, string(bytes_array[0]) == "123")
		c.Expect(commands[0].Reply(), gospec.Satisfies, string(bytes_array[1]) == "456")
		c.Expect(commands[0].Reply(), gospec.Satisfies, len(bytes_array[2]) == 0)
	})

	c.Specify("[RedisBatchCommands] Hash Get values", func() {
		logger := log4go.NewDefaultLogger(log4go.CRITICAL)
		server, err := StartRedisServer(&logger)
		if nil != err {
			panic(err)
		}
		defer server.Close()
		c.Expect(server.Connection().IsClosed(), gospec.Equals, true)

		server.Connection().Cmd("HSET", "Bob", "A", "123")
		server.Connection().Cmd("HSET", "Gary", "A", "456")

		var commands RedisBatchCommands
		commands = make([]*RedisBatchCommand, 3)
		commands[0] = MakeRedisBatchCommandHashGet("Bob", "A")
		commands[1] = MakeRedisBatchCommandHashGet("Gary", "A")
		commands[2] = MakeRedisBatchCommandHashGet("George", "A")

		err = commands.ExecuteBatch(server.Connection())
		c.Expect(err, gospec.Equals, nil)

		// Cache Hit on 2x; Cache Miss on 1x
		str, _ := commands[0].Reply().Str()
		c.Expect(commands[0].Reply(), gospec.Satisfies, str == "123")

		str, _ = commands[1].Reply().Str()
		c.Expect(commands[1].Reply(), gospec.Satisfies, str == "456")

		str, _ = commands[2].Reply().Str()
		c.Expect(commands[2].Reply(), gospec.Satisfies, str == "")
	})

	c.Specify("[RedisBatchCommands] Hash Set value", func() {
		logger := log4go.NewDefaultLogger(log4go.CRITICAL)
		server, err := StartRedisServer(&logger)
		if nil != err {
			panic(err)
		}
		defer server.Close()
		c.Expect(server.Connection().IsClosed(), gospec.Equals, true)

		var commands RedisBatchCommands
		commands = make([]*RedisBatchCommand, 1)
		commands[0] = MakeRedisBatchCommandHashSet("Bob", "A", []byte("123"))

		err = commands.ExecuteBatch(server.Connection())
		c.Expect(err, gospec.Equals, nil)

		ok, _ := commands[0].Reply().Int()
		c.Expect(commands[0].Reply(), gospec.Satisfies, ok == 1)
	})

	c.Specify("[RedisBatchCommands] Hash IncrementBy value", func() {
		logger := log4go.NewDefaultLogger(log4go.CRITICAL)
		server, err := StartRedisServer(&logger)
		if nil != err {
			panic(err)
		}
		defer server.Close()
		c.Expect(server.Connection().IsClosed(), gospec.Equals, true)

		var commands RedisBatchCommands
		commands = make([]*RedisBatchCommand, 1)
		commands[0] = MakeRedisBatchCommandHashIncrementBy("Bob", "A", 123)

		err = commands.ExecuteBatch(server.Connection())
		c.Expect(err, gospec.Equals, nil)

		// Returns the new hash value
		ok, _ := commands[0].Reply().Int()
		c.Expect(commands[0].Reply(), gospec.Satisfies, ok == 123)
	})

	c.Specify("[MakeRedisBatchCommand][Bitop][And] Makes command", func() {
		logger := log4go.NewDefaultLogger(log4go.CRITICAL)
		server, err := StartRedisServer(&logger)
		if nil != err {
			panic(err)
		}
		defer server.Close()
		c.Expect(server.Connection().IsClosed(), gospec.Equals, true)

		server.Connection().Cmd("SETBIT", "Bob", "123", "1")
		server.Connection().Cmd("SETBIT", "Gary", "456", "1")

		var commands RedisBatchCommands
		commands = make([]*RedisBatchCommand, 1)
		commands[0] = MakeRedisBatchCommandBitopAnd("DEST", "Bob", "Gary")

		err = commands.ExecuteBatch(server.Connection())
		c.Expect(err, gospec.Equals, nil)

		ok, _ := commands[0].Reply().Int()
		c.Expect(commands[0].Reply(), gospec.Satisfies, ok == 58)
	})

	c.Specify("[MakeRedisBatchCommand][Bitop][Or] Makes command", func() {
		logger := log4go.NewDefaultLogger(log4go.CRITICAL)
		server, err := StartRedisServer(&logger)
		if nil != err {
			panic(err)
		}
		defer server.Close()
		c.Expect(server.Connection().IsClosed(), gospec.Equals, true)

		server.Connection().Cmd("SETBIT", "Bob", "123", "1")
		server.Connection().Cmd("SETBIT", "Gary", "456", "1")

		var commands RedisBatchCommands
		commands = make([]*RedisBatchCommand, 1)
		commands[0] = MakeRedisBatchCommandBitopOr("DEST", "Bob", "Gary")

		err = commands.ExecuteBatch(server.Connection())
		c.Expect(err, gospec.Equals, nil)

		ok, _ := commands[0].Reply().Int()
		c.Expect(commands[0].Reply(), gospec.Satisfies, ok == 58)
	})

	c.Specify("[MakeRedisBatchCommand][Bitop][Not] Makes command", func() {
		logger := log4go.NewDefaultLogger(log4go.CRITICAL)
		server, err := StartRedisServer(&logger)
		if nil != err {
			panic(err)
		}
		defer server.Close()
		c.Expect(server.Connection().IsClosed(), gospec.Equals, true)

		server.Connection().Cmd("SETBIT", "Bob", "123", "1")

		var commands RedisBatchCommands
		commands = make([]*RedisBatchCommand, 1)
		commands[0] = MakeRedisBatchCommandBitopNot("DEST", "Bob")

		err = commands.ExecuteBatch(server.Connection())
		c.Expect(err, gospec.Equals, nil)

		ok, _ := commands[0].Reply().Int()
		c.Expect(commands[0].Reply(), gospec.Satisfies, ok == 16)
	})

	c.Specify("[MakeRedisBatchCommand][BitCount] Makes command", func() {
		logger := log4go.NewDefaultLogger(log4go.CRITICAL)
		server, err := StartRedisServer(&logger)
		if nil != err {
			panic(err)
		}
		defer server.Close()
		c.Expect(server.Connection().IsClosed(), gospec.Equals, true)

		server.Connection().Cmd("SETBIT", "Bob", "123", "1")
		server.Connection().Cmd("SETBIT", "Bob", "456", "1")

		var commands RedisBatchCommands
		commands = make([]*RedisBatchCommand, 1)
		commands[0] = MakeRedisBatchCommandBitCount("Bob")

		err = commands.ExecuteBatch(server.Connection())
		c.Expect(err, gospec.Equals, nil)

		ok, _ := commands[0].Reply().Int()
		c.Expect(commands[0].Reply(), gospec.Satisfies, ok == 2)
	})

	c.Specify("[MakeRedisBatchCommand][BitCount] Makes command", func() {
		logger := log4go.NewDefaultLogger(log4go.CRITICAL)
		server, err := StartRedisServer(&logger)
		if nil != err {
			panic(err)
		}
		defer server.Close()
		c.Expect(server.Connection().IsClosed(), gospec.Equals, true)

		server.Connection().Cmd("SETBIT", "Bob", "123", "1")

		var commands RedisBatchCommands
		commands = make([]*RedisBatchCommand, 2)
		commands[0] = MakeRedisBatchCommandGetBit("Bob", 123)
		commands[1] = MakeRedisBatchCommandGetBit("Bob", 456)

		err = commands.ExecuteBatch(server.Connection())
		c.Expect(err, gospec.Equals, nil)

		ok, _ := commands[0].Reply().Int()
		c.Expect(commands[0].Reply(), gospec.Satisfies, ok == 1)

		ok, _ = commands[1].Reply().Int()
		c.Expect(commands[1].Reply(), gospec.Satisfies, ok == 0)
	})

	c.Specify("[MakeRedisBatchCommand][SetBit] Makes command", func() {
		logger := log4go.NewDefaultLogger(log4go.CRITICAL)
		server, err := StartRedisServer(&logger)
		if nil != err {
			panic(err)
		}
		defer server.Close()
		c.Expect(server.Connection().IsClosed(), gospec.Equals, true)

		var commands RedisBatchCommands
		commands = make([]*RedisBatchCommand, 1)
		commands[0] = MakeRedisBatchCommandSetBit("Bob", 123, true)

		err = commands.ExecuteBatch(server.Connection())
		c.Expect(err, gospec.Equals, nil)

		ok, _ := commands[0].Reply().Int()
		c.Expect(commands[0].Reply(), gospec.Satisfies, ok == 0)
	})

}
Exemplo n.º 16
0
// Helpers
func RedisConnectionSpecs(c gospec.Context) {
	var redis_connection_logger = log4go.NewDefaultLogger(log4go.CRITICAL)

	c.Specify("[RedisConnection] Clone a connection", func() {
		connection := &RedisConnection{Url: "127.0.0.1:6990", Id: "Bob", Logger: &redis_connection_logger}
		defer connection.Close()
		c.Expect(connection.IsOpen(), gospec.Equals, false)

		connection2 := connection.Clone()
		defer connection2.Close()
		c.Expect(connection2.IsOpen(), gospec.Equals, false)

		// Should be differient pointers
		c.Expect(connection2, gospec.Satisfies, connection != connection2)
	})

	c.Specify("[RedisConnection] New connection is not open", func() {
		connection := RedisConnection{Url: "127.0.0.1:6990", Logger: &redis_connection_logger}
		defer connection.Close()

		open := connection.IsOpen()
		closed := connection.IsClosed()

		// Should be opposite of each other:
		c.Expect(open, gospec.Equals, false)
		c.Expect(closed, gospec.Equals, true)
		c.Expect(closed, gospec.Satisfies, open != closed)
	})

	c.Specify("[RedisConnection] Opening connection to Invalid Host/Port has errors", func() {
		connection := RedisConnection{Url: "127.0.0.1:6991", Logger: &redis_connection_logger}
		defer connection.Close()

		// The server is not running ...
		// This should return an error
		err := connection.Open()
		c.Expect(err, gospec.Satisfies, err != nil)

		closed := connection.IsClosed()
		c.Expect(closed, gospec.Equals, true)
	})

	c.Specify("[RedisConnection] Opening connection to Valid Host/Port has no errors", func() {
		logger := log4go.NewDefaultLogger(log4go.CRITICAL)
		server, err := StartRedisServer(&logger)
		if nil != err {
			panic(err)
		}
		defer server.Close()

		c.Expect(server.Connection().Open(), gospec.Equals, nil)
		c.Expect(server.Connection().IsOpen(), gospec.Equals, true)
		c.Expect(server.Connection().IsClosed(), gospec.Equals, false)
	})

	c.Specify("[RedisConnection][KeysExist] Checks if keys exists", func() {
		logger := log4go.NewDefaultLogger(log4go.CRITICAL)
		server, server_err := StartRedisServer(&logger)
		if nil != server_err {
			panic(server_err)
		}
		defer server.Close()

		keys := []string{"Key", "Bob", "George", "Alex", "Applause"}
		for _, key := range keys {
			server.Connection().Cmd("SET", key, "123")
		}

		oks, err := server.Connection().KeysExist(keys...)
		c.Expect(err, gospec.Equals, nil)
		c.Expect(len(oks), gospec.Equals, len(keys))
		for _, ok := range oks {
			c.Expect(ok, gospec.Equals, true)
		}

		// Cache Miss
		server.Connection().Cmd("DEL", keys)
		oks, err = server.Connection().KeysExist(keys...)
		c.Expect(err, gospec.Equals, nil)
		c.Expect(len(oks), gospec.Equals, len(keys))
		for _, ok := range oks {
			c.Expect(ok, gospec.Equals, false)
		}
	})

	c.Specify("[RedisConnection][HashFieldsExist] Checks if keys exists", func() {
		logger := log4go.NewDefaultLogger(log4go.CRITICAL)
		server, server_err := StartRedisServer(&logger)
		if nil != server_err {
			panic(server_err)
		}
		defer server.Close()

		fields := []string{"Key", "Bob", "George", "Alex", "Applause"}
		for _, field := range fields {
			server.Connection().Cmd("HSET", "Hash Name", field, "123")
		}

		oks, err := server.Connection().HashFieldsExist("Hash Name", fields...)
		c.Expect(err, gospec.Equals, nil)
		c.Expect(len(oks), gospec.Equals, len(fields))
		for _, ok := range oks {
			c.Expect(ok, gospec.Equals, true)
		}

		// Cache Miss
		server.Connection().Cmd("HDEL", "Hash Name", fields)
		oks, err = server.Connection().HashFieldsExist("Hash Name", fields...)
		c.Expect(err, gospec.Equals, nil)
		c.Expect(len(oks), gospec.Equals, len(fields))
		for _, ok := range oks {
			c.Expect(ok, gospec.Equals, false)
		}

		// Cache Miss
		oks, err = server.Connection().HashFieldsExist("Hash Missing", fields...)
		c.Expect(err, gospec.Equals, nil)
		c.Expect(len(oks), gospec.Equals, len(fields))
		for _, ok := range oks {
			c.Expect(ok, gospec.Equals, false)
		}
	})

	c.Specify("[RedisConnection] Ping (-->Cmd-->Append+GetReply) (re-)opens the connection automatically", func() {
		logger := log4go.NewDefaultLogger(log4go.INFO)
		server, err := StartRedisServer(&logger)
		if nil != err {
			panic(err)
		}
		defer server.Close()

		// Starts off closed ...
		c.Expect(server.Connection().IsClosed(), gospec.Equals, true)

		// Ping the server
		// Should now be open
		c.Expect(server.Connection().Ping(), gospec.Equals, nil)
		c.Expect(server.Connection().IsOpen(), gospec.Equals, true)
		c.Expect(server.Connection().IsClosed(), gospec.Equals, false)

		// Close the connection
		c.Expect(server.Connection().Close(), gospec.Equals, nil)
		c.Expect(server.Connection().IsClosed(), gospec.Equals, true)

		// Ping the server again
		// Should now be open again
		c.Expect(server.Connection().Ping(), gospec.Equals, nil)
		c.Expect(server.Connection().IsOpen(), gospec.Equals, true)
		c.Expect(server.Connection().IsClosed(), gospec.Equals, false)
	})

}
Exemplo n.º 17
0
func RedisBatchQueueSpecs(c gospec.Context) {

	c.Specify("[RedisBatchQueue][Cap]", func() {
		ptr := &RedisBatchQueue{
			queue: nil,
		}
		c.Expect(ptr.Cap(), gospec.Equals, -1)

		ptr.queue = make(chan *RedisBatchCommand, 10)
		defer close(ptr.queue)
		c.Expect(ptr.Cap(), gospec.Equals, 10)
	})

	c.Specify("[RedisBatchQueue][Len]", func() {
		ptr := &RedisBatchQueue{
			queue: nil,
		}
		c.Expect(ptr.Len(), gospec.Equals, -1)

		ptr.queue = make(chan *RedisBatchCommand, 10)
		defer close(ptr.queue)
		c.Expect(ptr.Len(), gospec.Equals, 0)

		ptr.queue <- &RedisBatchCommand{}
		c.Expect(ptr.Len(), gospec.Equals, 1)
	})

	c.Specify("[RedisBatchQueue][String]", func() {
		ptr := &RedisBatchQueue{
			QueueSize:        10,
			WorkersSize:      1,
			WorkersBatchSize: 5,
			queue:            make(chan *RedisBatchCommand, 10),
		}
		defer close(ptr.queue)
		c.Expect(ptr.String(), gospec.Equals, "RedisBatchQueue { Connection=<nil>, QueueSize=10, WorkersSize=1, WorkersBatchSize=5, Queue.Cap=10, Queue.Len=0 }")
	})

	c.Specify("[RedisBatchQueue][Open]", func() {
		ptr := &RedisBatchQueue{}
		defer ptr.Close()

		err := ptr.Open()
		c.Expect(err, gospec.Satisfies, nil != err)
		c.Expect(ptr.queue, gospec.Satisfies, nil == ptr.queue)
		c.Expect(ptr.workers, gospec.Satisfies, 0 == len(ptr.workers))
		c.Expect(err.Error(), gospec.Equals, "[RedisBatchQueue][Open] Nil Logger!")

		ptr.Logger = &log4go.Logger{}
		ptr.queue = make(chan *RedisBatchCommand, 10)

		err = ptr.Open()
		c.Expect(err, gospec.Satisfies, nil != err)
		c.Expect(ptr.queue, gospec.Satisfies, nil != ptr.queue)
		c.Expect(ptr.workers, gospec.Satisfies, 0 == len(ptr.workers))
		c.Expect(err.Error(), gospec.Equals, "[RedisBatchQueue][Open] Queue is already open!")

		close(ptr.queue)
		ptr.queue = nil
		err = ptr.Open()
		c.Expect(err, gospec.Satisfies, nil != err)
		c.Expect(ptr.queue, gospec.Satisfies, nil == ptr.queue)
		c.Expect(ptr.workers, gospec.Satisfies, 0 == len(ptr.workers))
		c.Expect(err.Error(), gospec.Equals, "[RedisBatchQueue][Open] Nil redis connection!")

		ptr.Connection = &RedisConnection{}
		err = ptr.Open()
		c.Expect(err, gospec.Satisfies, nil != err)
		c.Expect(ptr.queue, gospec.Satisfies, nil == ptr.queue)
		c.Expect(ptr.workers, gospec.Satisfies, 0 == len(ptr.workers))
		c.Expect(err.Error(), gospec.Equals, "[RedisBatchQueue][Open] QueueSize[0] must be > 0!")

		ptr.QueueSize = 10
		err = ptr.Open()
		c.Expect(err, gospec.Satisfies, nil != err)
		c.Expect(ptr.queue, gospec.Satisfies, nil == ptr.queue)
		c.Expect(ptr.workers, gospec.Satisfies, 0 == len(ptr.workers))
		c.Expect(err.Error(), gospec.Equals, "[RedisBatchQueue][Open] WorkersSize[0] must be > 0!")

		ptr.WorkersSize = 20
		err = ptr.Open()
		c.Expect(err, gospec.Satisfies, nil != err)
		c.Expect(ptr.queue, gospec.Satisfies, nil == ptr.queue)
		c.Expect(ptr.workers, gospec.Satisfies, 0 == len(ptr.workers))
		c.Expect(err.Error(), gospec.Equals, "[RedisBatchQueue][Open] WorkersBatchSize[0] must be > 0!")

		ptr.WorkersBatchSize = 5
		err = ptr.Open()
		c.Expect(err, gospec.Satisfies, nil != err)
		c.Expect(ptr.queue, gospec.Satisfies, nil == ptr.queue)
		c.Expect(ptr.workers, gospec.Satisfies, 0 == len(ptr.workers))
		c.Expect(err.Error(), gospec.Equals, "[RedisBatchQueue][Open] QueueSize[10] must be > WorkersSize[20]!")

		ptr.WorkersSize = 10
		err = ptr.Open()
		c.Expect(err, gospec.Equals, nil)
		c.Expect(ptr.queue, gospec.Satisfies, nil != ptr.queue)
		c.Expect(ptr.workers, gospec.Satisfies, 0 < len(ptr.workers))
	})

	c.Specify("[RedisBatchQueue][Close]", func() {
		ptr := &RedisBatchQueue{}

		err := ptr.Close()
		c.Expect(err, gospec.Satisfies, nil == err)
		c.Expect(ptr.queue, gospec.Satisfies, nil == ptr.queue)
		c.Expect(ptr.workers, gospec.Satisfies, 0 == len(ptr.workers))

		ptr.queue = make(chan *RedisBatchCommand, 10)
		ptr.workers = []*redisBatchQueueWorker{nil, nil, nil, nil, nil}
		err = ptr.Close()
		c.Expect(err, gospec.Satisfies, nil == err)
		c.Expect(ptr.queue, gospec.Satisfies, nil == ptr.queue)
		c.Expect(ptr.workers, gospec.Satisfies, 0 == len(ptr.workers))
	})

	c.Specify("[RedisBatchQueue][RunAsync]", func() {
		prev := runtime.GOMAXPROCS(2)
		defer runtime.GOMAXPROCS(prev)

		logger := log4go.NewDefaultLogger(log4go.CRITICAL)
		server, err := StartRedisServer(&logger)
		if nil != err {
			panic(err)
		}
		defer server.Close()

		ptr := &RedisBatchQueue{
			Logger:           &logger,
			Connection:       server.Connection(),
			QueueSize:        10,
			WorkersSize:      5,
			WorkersBatchSize: 2,
		}

		err = ptr.RunAsync(nil)
		c.Expect(err, gospec.Satisfies, nil != err)
		c.Expect(err.Error(), gospec.Equals, "[RedisBatchQueue][RunAsync] Queue is closed!")

		err = ptr.Open()
		c.Expect(err, gospec.Satisfies, nil == err)

		err = ptr.RunAsync(nil)
		c.Expect(err, gospec.Satisfies, nil != err)
		c.Expect(err.Error(), gospec.Equals, "[RedisBatchQueue][RunAsync][0] Nil RedisBatchCommand!")

		err = ptr.RunAsync(
			MakeRedisBatchCommandHashIncrementBy("Hash", "Field A", 1),
			MakeRedisBatchCommandHashIncrementBy("Hash", "Field B", 10),
			MakeRedisBatchCommandHashIncrementBy("Hash", "Field C", 100),
		)
		c.Expect(err, gospec.Satisfies, nil == err)

		time.Sleep(50 * time.Millisecond)

		ints, ints_err := RedisDsl{server.Connection()}.HASH_MGET_INT64S("Hash", "Field A", "Field B", "Field C")
		c.Expect(ints_err, gospec.Equals, nil)
		c.Expect(len(ints), gospec.Equals, 3)
		c.Expect(*ints[0], gospec.Equals, int64(1))
		c.Expect(*ints[1], gospec.Equals, int64(10))
		c.Expect(*ints[2], gospec.Equals, int64(100))

		err = ptr.RunAsync(
			MakeRedisBatchCommandHashDelete("Hash", "Field A", "Field B", "Field C"),
		)
		c.Expect(err, gospec.Satisfies, nil == err)

		time.Sleep(time.Millisecond)
		ptr.Close()

		time.Sleep(50 * time.Millisecond)

		ints, ints_err = RedisDsl{server.Connection()}.HASH_MGET_INT64S("Hash", "Field A", "Field B", "Field C")
		c.Expect(ints_err, gospec.Equals, nil)
		c.Expect(len(ints), gospec.Equals, 3)
		c.Expect(ints[0], gospec.Satisfies, nil == ints[0])
		c.Expect(ints[1], gospec.Satisfies, nil == ints[1])
		c.Expect(ints[2], gospec.Satisfies, nil == ints[2])
	})

}