Skip to content
New issue

Have a question about this project? # for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “#”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? # to your account

finagle-redis tests need refactoring to from specs2 to scalatest #283

Closed
wants to merge 12 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -64,6 +64,11 @@ class BaseClient(service: Service[Command, Reply]) {
case EmptyBulkReply() => Future.value(None)
}

/**
* Deletes all keys in all databases
*/
def flushAll(): Future[Unit] = doRequest(FlushAll) {case StatusReply(_) => Future.Unit}

/**
* Deletes all keys in current DB
*/
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -82,6 +82,7 @@ object Commands {
val BRANGE = "BRANGE"

// Miscellaneous
val FLUSHALL = "FLUSHALL"
val FLUSHDB = "FLUSHDB"
val SELECT = "SELECT"
val AUTH = "AUTH"
Expand Down Expand Up @@ -203,6 +204,7 @@ object Commands {
BGET -> {BGet(_)},

// miscellaneous
FLUSHALL -> {_ => FlushAll},
FLUSHDB -> {_ => FlushDB},
SELECT -> {Select(_)},
AUTH -> {Auth(_)},
Expand Down Expand Up @@ -341,6 +343,7 @@ object CommandBytes {
val BRANGE = StringToChannelBuffer("BRANGE")

// Miscellaneous
val FLUSHALL = StringToChannelBuffer("FLUSHALL")
val FLUSHDB = StringToChannelBuffer("FLUSHDB")
val SELECT = StringToChannelBuffer("SELECT")
val AUTH = StringToChannelBuffer("AUTH")
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,11 @@ import com.twitter.finagle.redis.protocol.Commands.trimList
import com.twitter.finagle.redis.util._
import org.jboss.netty.buffer.{ChannelBuffer, ChannelBuffers}

case object FlushAll extends Command {
def command = Commands.FLUSHALL
val toChannelBuffer = RedisCodec.toUnifiedFormat(Seq(CommandBytes.FLUSHALL))
}

case object FlushDB extends Command {
def command = Commands.FLUSHDB
val toChannelBuffer = RedisCodec.toUnifiedFormat(Seq(CommandBytes.FLUSHDB))
Expand Down Expand Up @@ -52,7 +57,7 @@ case object Quit extends Command {
val toChannelBuffer = RedisCodec.toUnifiedFormat(Seq(CommandBytes.QUIT))
}

case class ConfigSet(param: ChannelBuffer, value: ChannelBuffer) extends Config(ConfigSet.channelBuffer, Seq(param, value))
case class ConfigSet(param: ChannelBuffer, value: ChannelBuffer) extends Config(ConfigSet.channelBuffer, Seq(param, value))
object ConfigSet extends ConfigHelper {
val command = "SET"
def apply(args: Seq[Array[Byte]]): ConfigSet = {
Expand All @@ -61,7 +66,7 @@ object ConfigSet extends ConfigHelper {
}
}

case class ConfigGet(param: ChannelBuffer) extends Config(ConfigGet.channelBuffer, Seq(param))
case class ConfigGet(param: ChannelBuffer) extends Config(ConfigGet.channelBuffer, Seq(param))
object ConfigGet extends ConfigHelper {
val command = "GET"
def apply(args: Seq[Array[Byte]]): ConfigGet = {
Expand All @@ -70,7 +75,7 @@ object ConfigGet extends ConfigHelper {
}
}

case class ConfigResetStat() extends Config(sub = ConfigResetStat.channelBuffer, args = Seq())
case class ConfigResetStat() extends Config(sub = ConfigResetStat.channelBuffer, args = Seq())
object ConfigResetStat extends ConfigHelper {
val command = "RESETSTAT"
def apply(args: Seq[Array[Byte]]): ConfigResetStat = new ConfigResetStat()
Expand All @@ -85,7 +90,7 @@ abstract class Config(sub: ChannelBuffer, args: Seq[ChannelBuffer]) extends Comm
trait ConfigHelper {
def command: String
def apply(args: Seq[Array[Byte]]): Config

def channelBuffer: ChannelBuffer = StringToChannelBuffer(command)
def bytes: Array[Byte] = StringToBytes(command)

Expand All @@ -100,7 +105,7 @@ object Config {
subCommand(args.tail)
}
}


case class SlaveOf(host: ChannelBuffer, port: ChannelBuffer) extends Command {
def command = Commands.SLAVEOF
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,145 @@
package com.twitter.finagle.redis.naggati

import com.twitter.finagle.builder.{ClientBuilder, ServerBuilder}
import com.twitter.finagle.redis.naggati.test.TestCodec
import com.twitter.finagle.redis.protocol._
import com.twitter.finagle.redis.util.{BytesToString, CBToString, RedisCluster, ReplyFormat, StringToChannelBuffer}
import com.twitter.finagle.redis.{Redis, TransactionalClient}
import com.twitter.util.{Await, Future, Time}
import org.jboss.netty.buffer.ChannelBuffer
import org.scalatest.{BeforeAndAfterAll, FunSuite}
import java.net.InetSocketAddress
import com.twitter.finagle.Service
import com.twitter.finagle.redis.Client

trait RedisTest extends FunSuite {
protected def wrap(s: String): ChannelBuffer = StringToChannelBuffer(s)
protected def string2ChanBuf(s: String): ChannelBuffer = wrap(s)
protected def chanBuf2String(cb: ChannelBuffer): String = CBToString(cb)

protected val foo = StringToChannelBuffer("foo")
protected val bar = StringToChannelBuffer("bar")
protected val baz = StringToChannelBuffer("baz")
protected val boo = StringToChannelBuffer("boo")
protected val moo = StringToChannelBuffer("moo")

}

trait RedisResponseTest extends RedisTest {
protected val replyCodec = new ReplyCodec
protected val (codec, counter) = TestCodec(replyCodec.decode, replyCodec.encode)
}

trait RedisRequestTest extends RedisTest {
protected val commandCodec = new CommandCodec
protected val (codec, counter) = TestCodec(commandCodec.decode, commandCodec.encode)


def unwrap(list: Seq[AnyRef])(fn: PartialFunction[Command,Unit]) = list.toList match {
case head :: Nil => head match {
case c: Command => fn.isDefinedAt(c) match {
case true => fn(c)
case false => fail("Didn't find expected type in list: %s".format(c.getClass))
}
case _ => fail("Expected to find a command in the list")
}
case _ => fail("Expected single element list")
}
}

trait RedisClientTest extends RedisTest with BeforeAndAfterAll {

override def beforeAll(configMap: Map[String, Any]): Unit = RedisCluster.start()
override def afterAll(configMap: Map[String, Any]): Unit = RedisCluster.stop()

protected def withRedisClient(testCode: TransactionalClient => Any) {
val client = TransactionalClient(
ClientBuilder()
.codec(new Redis())
.hosts(RedisCluster.hostAddresses())
.hostConnectionLimit(1)
.buildFactory())
Await.result(client.flushAll)
try {
testCode(client)
}
finally {
client.release
}
}
}

trait RedisClientServerIntegrationTest extends RedisTest with BeforeAndAfterAll {

private[this] lazy val svcClient = ClientBuilder()
.name("redis-client")
.codec(Redis())
.hosts(RedisCluster.hostAddresses())
.hostConnectionLimit(2)
.retries(2)
.build()

private[this] val service = new Service[Command, Reply] {
def apply(cmd: Command): Future[Reply] = {
svcClient(cmd)
}
}

private[this] val server = ServerBuilder()
.name("redis-server")
.codec(Redis())
.bindTo(new InetSocketAddress(0))
.build(service)

override def beforeAll(configMap: Map[String, Any]): Unit = RedisCluster.start()
override def afterAll(configMap: Map[String, Any]): Unit = RedisCluster.stop()

protected val OKStatusReply = StatusReply("OK")

protected def withRedisClient(testCode: Service[Command, Reply] => Any) {
val client = ClientBuilder()
.name("redis-client")
.codec(Redis())
.hosts(server.localAddress)
.hostConnectionLimit(1)
.retries(2)
.build()
Await.result(client(FlushAll))
try {
testCode(client)
}
finally {
client.close()
}
}

protected def assertMBulkReply(reply: Future[Reply], expects: List[String],
contains: Boolean = false) = Await.result(reply) match {
case MBulkReply(msgs) => contains match {
case true =>
assert(expects.isEmpty === false, "Test did no supply a list of expected replies.")
val newMsgs = ReplyFormat.toString(msgs)
expects.foreach({ msg =>
val doesMBulkReplyContainMessage = newMsgs.contains(msg)
assert(doesMBulkReplyContainMessage === true)
})
case false =>
val actualMessages = ReplyFormat.toChannelBuffers(msgs).map({ msg =>
chanBuf2String(msg)
})
assert(actualMessages == expects)
}
case EmptyMBulkReply() => {
val isEmpty = true
val actualReply = expects.isEmpty
assert(actualReply === isEmpty)
}
case r: Reply => fail("Expected MBulkReply, got %s".format(r))
case _ => fail("Expected MBulkReply")
}

def assertBulkReply(reply: Future[Reply], expects: String) = Await.result(reply) match {
case BulkReply(msg) => assert(BytesToString(msg.array) === expects)
case _ => fail("Expected BulkReply")
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
package com.twitter.finagle.redis.tags

import org.scalatest.Tag

object RedisTest extends Tag("com.twitter.finagle.redis.tags.RedisTest")
object CodecTest extends Tag("com.twitter.finagle.redis.tags.CodecTest")
object ClientTest extends Tag("com.twitter.finagle.redis.tags.ClientTest")
object ClientServerTest extends Tag("com.twitter.finagle.redis.tags.ClientServerTest")
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
package com.twitter.finagle.redis.protocol

import com.twitter.finagle.redis.naggati.RedisRequestTest
import com.twitter.finagle.redis.tags.CodecTest
import org.junit.runner.RunWith
import org.scalatest.junit.JUnitRunner

@RunWith(classOf[JUnitRunner])
final class RequestEncodingSuite extends RedisRequestTest {

test("Correctly encode inline requests", CodecTest) {
val actualEncoding = codec.send(Get(foo))
val expectedEncoding = List("*2\r\n$3\r\nGET\r\n$3\r\nfoo\r\n")
assert(actualEncoding === expectedEncoding)
}

test("Correctly encode unified requests", CodecTest) {
val value = "bar\r\nbaz"
val actualEncoding = codec.send(Set(foo, string2ChanBuf(value)))
val expectedEncoding = List("*3\r\n$3\r\nSET\r\n$3\r\nfoo\r\n$%d\r\n%s\r\n".format(8, value))
assert(actualEncoding === expectedEncoding)
}

test("Correctly encode a HSet request with an empty string as value", CodecTest) {
val actualEncoding = codec.send(HSet(foo, bar, string2ChanBuf("")))
val expectedEncoding = List("*4\r\n$4\r\nHSET\r\n$3\r\nfoo\r\n$3\r\nbar\r\n$0\r\n\r\n")
assert(actualEncoding === expectedEncoding)
}
}
Loading